/* ---------------------------------------------------------------------------
   Hero stage — three concepts, one slot
   ---------------------------------------------------------------------------
   A "gap"     the headline, drawn. A finished application, solid ground, and a
               measured void between them that fills member by member until the
               measurement is no longer a cost but a name.
   B "ground"  the calm one. The building is drawn once and never moves again;
               only the site under it changes.
C "blocked"  the loud one. Finished code reaches the production line, a named wall
               assembles in front of it, and Groundfloor takes the wall over rather
               than opening it. Ends on the same drawing as A.
   All three use the same coordinate system, the same ground, the same controls and
   the same role tokens: SIGNAL is what the customer owns, STEEL is what
   Groundfloor runs, GAP is the cost of the distance between them.
--------------------------------------------------------------------------- */

.hero-split{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
  gap:clamp(24px,4vw,64px);align-items:center}
.hero-split .hero-copy{min-width:0}
.hero-split h1{line-height:1.06}
.hero-split .lede{max-width:46ch}
/* The full-width hero puts the lede and the buttons on one line. Inside the split
   layout that column is half as wide, which crushed the lede to ~28ch. Stack them. */
.hero-split .hero-bottom{margin-top:28px;display:block}
.hero-split .hero-bottom .actions{margin-top:26px;max-width:none}

/* Only the selected concept is in the document flow. */
.hero-stages{min-width:0}
.hero-stages>.hero-stage{display:none}
.hero-stages[data-hero="gap"]>[data-variant="gap"],
.hero-stages[data-hero="ground"]>[data-variant="ground"],
.hero-stages[data-hero="blocked"]>[data-variant="blocked"]{display:flex}

.hero-stage{min-width:0;position:relative;flex-direction:column;gap:14px;
  --ease:cubic-bezier(.2,.8,.2,1);
  /* Weight: fast out, a hair of overshoot, then it settles and stays settled. */
  --land:cubic-bezier(.16,1.02,.3,1)}
.hero-stage .stage-svg{width:100%;height:auto;display:block;overflow:visible}

/* --- shared parts -------------------------------------------------------- */
.hero-stage .plate{fill:none;stroke:color-mix(in srgb,var(--signal) 44%,transparent);stroke-width:1.5}
.hero-stage .plate-fill{fill:color-mix(in srgb,var(--signal) 9%,transparent)}
.hero-stage text{fill:currentColor;font-family:var(--font-mono);font-size:13px;letter-spacing:.04em}
.hero-stage .t-label{font-size:10.5px;letter-spacing:.17em;text-transform:uppercase;
  fill:color-mix(in srgb,currentColor 50%,transparent)}
.hero-stage .t-chip{font-size:12px;letter-spacing:.1em;fill:var(--signal)}
.hero-stage .t-env{font-family:var(--font-sans,inherit);font-size:21px;letter-spacing:-.01em}

/* the ground is the same object in both concepts */
.hero-stage .s-ground{opacity:0;transform:translateY(12px);
  transition:opacity .5s ease,transform .5s var(--ease)}
.is-base .s-ground{opacity:1;transform:none}
.hero-stage .ground-plate{fill:color-mix(in srgb,var(--steel) 10%,transparent);
  stroke:color-mix(in srgb,var(--steel) 30%,transparent);stroke-width:1.5}
.hero-stage .ground-hatch{stroke:color-mix(in srgb,var(--steel) 24%,transparent);stroke-width:1}
.hero-stage .env{opacity:0;transform:translateY(10px);
  transition:opacity .4s ease,transform .46s var(--ease)}
.hero-stage[data-env="private"]  .env[data-env="private"],
.hero-stage[data-env="hyper"]    .env[data-env="hyper"],
.hero-stage[data-env="regional"] .env[data-env="regional"]{opacity:1;transform:none}

/* ===========================================================================
   A — the gap
   ======================================================================== */

/* The application is finished before the sequence starts. It is the one thing
   on the page that never had to wait, so it arrives first and arrives whole. */
.hero-gap .s-app{opacity:0;transform:translateY(-44px);
  transition:opacity .5s ease,transform .62s var(--ease)}
.hero-gap.is-base .s-app{opacity:1;transform:translateY(-30px)}
.hero-gap .t-ready{fill:color-mix(in srgb,var(--signal) 74%,transparent)}
/* It lands on the finished structure, with weight. */
.hero-gap.is-closed .s-app{transform:none;transition:transform .5s var(--land)}
/* Landed: plain ink, neither SIGNAL (reads as a problem) nor STEEL (Groundfloor's). See C. */
.hero-gap .s-app .plate,.hero-gap .s-app .plate-fill,.hero-gap .s-app .t-chip,
.hero-gap .s-app .t-ready{transition:stroke .6s ease .3s,fill .6s ease .3s}
.hero-gap.is-closed .s-app .plate{stroke:color-mix(in srgb,var(--ink-landed,currentColor) 80%,transparent)}
.hero-gap.is-closed .s-app .plate-fill{fill:color-mix(in srgb,var(--ink-landed,currentColor) 8%,transparent)}
.hero-gap.is-closed .s-app .t-chip,
.hero-gap.is-closed .s-app .t-ready{fill:var(--ink-landed,currentColor)}

/* The measurement. One rule: first it measures what the gap costs,
   then the same rule measures what filled it. */
.hero-gap .s-dim{opacity:0;transition:opacity .45s ease}
.hero-gap.is-base .s-dim{opacity:1}
.hero-gap .dim-rule,.hero-gap .dim-cap{fill:var(--gap);
  transition:transform .54s var(--ease),fill .5s ease}
.hero-gap .dim-rule{transform-origin:56px 104px;
  transform:translateY(calc(var(--dimtop,0) * 1px)) scaleY(calc(var(--dimlen,226) / 226))}
.hero-gap .dim-cap-top{transform:translateY(calc(var(--dimtop,0) * 1px))}
.hero-gap .dim-cap-end{transform:translateY(calc((var(--dimend,330) - 330) * 1px))}
.hero-gap{--dimtop:0;--dimlen:226;--dimend:330;--wordy:0;--wordsize:36}
.hero-gap.is-m1{--dimlen:190;--dimend:294;--wordy:-18;--wordsize:32}
.hero-gap.is-m2{--dimlen:158;--dimend:262;--wordy:-34;--wordsize:28}
.hero-gap.is-m3{--dimlen:126;--dimend:230;--wordy:-50;--wordsize:24}
.hero-gap.is-m4{--dimlen:94; --dimend:198;--wordy:-66;--wordsize:20}
.hero-gap.is-m5{--dimlen:62; --dimend:166;--wordy:-82;--wordsize:17}
.hero-gap.is-m6{--dimlen:30; --dimend:134;--wordy:-98;--wordsize:14}
/* Closed: the rule now spans the structure, and it is Groundfloor's, not a cost. */
.hero-gap.is-closed{--dimtop:30;--dimlen:196;--dimend:330}
.hero-gap.is-closed .dim-rule,.hero-gap.is-closed .dim-cap{fill:color-mix(in srgb,var(--steel) 72%,transparent)}
.hero-gap .dim-final{font-size:10.5px;letter-spacing:.17em;text-transform:uppercase;
  fill:color-mix(in srgb,var(--steel) 86%,transparent);opacity:0;transition:opacity .5s ease .18s}
.hero-gap.is-closed .dim-final{opacity:1}

/* What the distance costs, sitting in the space it describes. */
.hero-gap .s-word{opacity:0;transform:translateY(calc(var(--wordy,0) * 1px));
  transition:opacity .45s ease,transform .54s var(--ease)}
.hero-gap.is-base .s-word{opacity:1}
.hero-gap.is-closed .s-word{opacity:0;transition:opacity .3s ease}
.hero-gap .dim-word{fill:var(--gap);font-size:calc(var(--wordsize,36) * 1px);
  letter-spacing:-.01em;transition:font-size .54s var(--ease)}
.hero-gap .dim-sub{transition:opacity .4s ease}
.hero-gap.is-m2 .dim-sub{opacity:0}

/* The members arrive from alternating sides, land, and stop. */
.hero-gap .s-mem{opacity:0;
  transform:translateX(-64px);
  transition:opacity .34s ease,transform .5s var(--land)}
.hero-gap .s-mem:nth-child(even){transform:translateX(64px)}
.hero-gap .t-mem{font-size:12.5px;letter-spacing:.06em;
  fill:color-mix(in srgb,var(--steel) 92%,transparent)}
.hero-gap .t-idx{font-size:10px;letter-spacing:.14em;
  fill:color-mix(in srgb,var(--steel) 46%,transparent)}
.hero-gap .s-mem .plate{stroke:color-mix(in srgb,var(--steel) 40%,transparent)}
.hero-gap .s-mem .plate-fill{fill:color-mix(in srgb,var(--steel) 10%,transparent)}
.hero-gap.is-m1 .s-mem:nth-child(1),.hero-gap.is-m2 .s-mem:nth-child(2),
.hero-gap.is-m3 .s-mem:nth-child(3),.hero-gap.is-m4 .s-mem:nth-child(4),
.hero-gap.is-m5 .s-mem:nth-child(5),.hero-gap.is-m6 .s-mem:nth-child(6){opacity:1;transform:none}

/* ===========================================================================
   B — the ground
   ======================================================================== */

/* One object, drawn once. The outline is drawn, not faded: it is being built. */
.hero-ground .block-plate{fill:color-mix(in srgb,var(--signal) 7%,transparent);
  stroke:color-mix(in srgb,var(--signal) 52%,transparent);stroke-width:1.5;
  stroke-dasharray:1308;stroke-dashoffset:1308;
  transition:stroke-dashoffset 1.15s cubic-bezier(.5,0,.2,1)}
.hero-ground.is-block .block-plate{stroke-dashoffset:0}
.hero-ground .s-block>*:not(.block-plate){opacity:0;transition:opacity .5s ease}
.hero-ground.is-labels .s-block>*{opacity:1}
.hero-ground .block-seam{fill:color-mix(in srgb,var(--signal) 34%,transparent)}
.hero-ground .stratum-rule{fill:color-mix(in srgb,var(--steel) 20%,transparent)}
.hero-ground .t-stratum{font-size:12.5px;letter-spacing:.06em;
  fill:color-mix(in srgb,var(--steel) 92%,transparent)}
.hero-ground .t-managed{fill:color-mix(in srgb,var(--steel) 62%,transparent)}

/* It bears on the ground. It is not fused to it, and that is the point. */
.hero-ground .bearing{fill:color-mix(in srgb,var(--steel) 54%,transparent);
  opacity:0;transform:scaleY(0);transform-origin:50% 100%;
  transition:opacity .3s ease,transform .4s var(--land)}
.hero-ground.is-labels .bearing{opacity:1;transform:none}

/* One word, bracketed against the block, after the ground has changed once. */
.hero-ground .s-mark{opacity:0;transition:opacity .5s ease}
.hero-ground.is-mark .s-mark{opacity:1}
.hero-ground .mark-rule,.hero-ground .mark-cap{fill:color-mix(in srgb,var(--signal) 54%,transparent)}
.hero-ground .mark-word{font-size:10.5px;letter-spacing:.17em;text-transform:uppercase;
  fill:var(--signal)}

/* --- the interactive end state ------------------------------------------ */
.stage-controls{display:flex;flex-wrap:wrap;gap:8px;opacity:0;pointer-events:none;
  visibility:hidden;transition:opacity .45s ease,visibility 0s linear .45s}
/* Hidden buttons are out of the tab order until they can be seen (audit V2). */
.is-live .stage-controls{opacity:1;pointer-events:auto;visibility:visible;transition:opacity .45s ease}
.stage-controls button{font:500 13px/1 var(--font-sans,inherit);padding:9px 14px;cursor:pointer;
  color:inherit;background:transparent;border-radius:2px;
  border:1px solid color-mix(in srgb,currentColor 24%,transparent);
  transition:border-color .18s ease,background-color .18s ease}
.stage-controls button:hover{border-color:color-mix(in srgb,var(--signal) 70%,transparent)}
.stage-controls button[aria-pressed="true"]{border-color:var(--signal);
  background:color-mix(in srgb,var(--signal) 16%,transparent)}
.stage-note{font-size:12.5px;line-height:1.5;margin:0;
  color:color-mix(in srgb,currentColor 58%,transparent);max-width:46ch}
/* Buttons and note sit on the stack's own column: the plates run x 88 to 552 of the 640 viewBox
   (13.75% in from each side), so the button row spans exactly that width in three equal cells. */
.hero-stage .stage-controls{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));margin-inline:13.75%}
.hero-stage .stage-controls button{padding-inline:4px;text-align:center;line-height:1.2}
.hero-stage .stage-note{margin-inline:13.75%;max-width:none}

/* --- narrow ------------------------------------------------------------- */
@media(max-width:1020px){
  .hero-split{grid-template-columns:1fr;gap:34px}
  .hero-stages{max-width:620px}
}
@media(max-width:620px){
  .hero-stage .t-chip,.hero-stage .t-label,.hero-gap .t-mem,.hero-ground .t-stratum,
  .hero-blocked .t-row{font-size:12px}
  .hero-stage .t-env{font-size:18px}
  .hero-stage .stage-controls button{font-size:12px}
}

/* --- no motion ---------------------------------------------------------- */
/* The end state is the honest one: the gap closed, the structure named. */
@media(prefers-reduced-motion:reduce){
  .hero-stage *{transition:none!important;animation:none!important}
}

/* ===========================================================================
   C — the wall
   ---------------------------------------------------------------------------
   Four acts, about thirteen seconds, once. The code is the character; there is
   no person in it. Nothing turns red and nothing turns green: the obstruction
   is drawn in GAP, which already carries "production still takes months", and
   what replaces it is drawn in STEEL, which is everything Groundfloor runs.
   The blockers are not ticked off, they are taken over — the rows stay exactly
   where they are and change hands, which is the larger claim.
   ======================================================================== */

/* --- act 1 · working code ----------------------------------------------- */
.hero-blocked .s-prod{opacity:0;transition:opacity .5s ease}
.hero-blocked.is-code .s-prod{opacity:1}
.hero-blocked .prod-line{fill:none;stroke:color-mix(in srgb,var(--steel) 44%,transparent);
  stroke-width:1.5;stroke-dasharray:7 8}

/* The outer group does the one journey in act 3; the inner one does the typing
   and the two failed pushes, so the two transforms never fight. */
.hero-blocked .s-code{transition:transform .9s var(--land)}
.hero-blocked .code-body{opacity:0;transform:translateY(20px);
  transition:opacity .45s ease,transform .55s var(--ease)}
.hero-blocked.is-code .code-body{opacity:1;transform:none}
.hero-blocked .code-line{fill:color-mix(in srgb,var(--signal) 48%,transparent);
  opacity:0;transition:opacity .16s ease calc(var(--i) * .15s + .22s)}
.hero-blocked.is-code .code-line{opacity:1}
.hero-blocked .t-ready{fill:color-mix(in srgb,var(--signal) 74%,transparent)}
/* The caret keeps blinking all through the stall. It is the only thing alive
   on the stage while nothing is happening, which is the point of that second. */
.hero-blocked .code-caret{fill:var(--signal);opacity:0}
.hero-blocked.is-code .code-caret{animation:blk-caret 1.05s steps(1) .85s infinite}
@keyframes blk-caret{0%,50%{opacity:1}50.01%,100%{opacity:0}}

/* --- act 2 · the wall ---------------------------------------------------- */
/* It assembles downward, so the last row lands directly in front of the code. */
.hero-blocked .s-row{opacity:0;transform:scaleX(.8);
  transform-box:fill-box;transform-origin:50% 50%;
  transition:opacity .26s ease calc(var(--i) * .17s),
    transform .42s var(--land) calc(var(--i) * .17s)}
.hero-blocked.is-wall .s-row{opacity:1;transform:none}
.hero-blocked .s-row .plate{stroke:color-mix(in srgb,var(--gap) 62%,transparent);
  transition:stroke .5s ease calc(var(--j) * .13s)}
.hero-blocked .s-row .plate-fill{fill:color-mix(in srgb,var(--gap) 11%,transparent);
  transition:fill .5s ease calc(var(--j) * .13s)}
.hero-blocked .t-row{font-size:12.5px;letter-spacing:.06em;fill:var(--gap);
  transition:fill .5s ease calc(var(--j) * .13s)}
/* A thickened left edge on every row: the bar that holds it shut. */
.hero-blocked .row-latch{fill:var(--gap);
  transition:opacity .3s ease calc(var(--j) * .13s),
    transform .42s var(--ease) calc(var(--j) * .13s)}

/* The bracket. One rule marks the obstruction, then names what took it over. */
.hero-blocked{--blkend:319}
.hero-blocked .s-brace{opacity:0;transition:opacity .45s ease .62s}
.hero-blocked.is-wall .s-brace{opacity:1}
.hero-blocked .blk-rule{fill:var(--gap);transform-box:fill-box;transform-origin:50% 0;
  transform:scaleY(calc((var(--blkend) - 134) / 185));
  transition:transform .54s var(--ease),fill .5s ease}
.hero-blocked .blk-cap{fill:var(--gap);transition:fill .5s ease,transform .54s var(--ease)}
.hero-blocked .blk-cap-end{transform:translateY(calc((var(--blkend) - 319) * 1px))}
.hero-blocked .blk-word,.hero-blocked .blk-final{font-size:10.5px;letter-spacing:.17em;
  text-transform:uppercase}
.hero-blocked .blk-word{fill:var(--gap);transition:opacity .32s ease}
.hero-blocked .blk-final{fill:color-mix(in srgb,var(--steel) 86%,transparent);
  opacity:0;transition:opacity .5s ease .34s}

/* Two pushes, two failures. Differently named so the second one re-triggers. */
.hero-blocked.is-push .code-body{animation:blk-nudge .66s var(--ease)}
.hero-blocked.is-push2 .code-body{animation:blk-nudge2 .52s var(--ease)}
@keyframes blk-nudge{0%{transform:none}44%{transform:translateY(-26px)}100%{transform:none}}
@keyframes blk-nudge2{0%{transform:none}30%{transform:translateY(-13px)}
  64%{transform:translateY(3px)}100%{transform:none}}

/* --- act 3 · Groundfloor ------------------------------------------------- */
/* The wall is not opened. It changes hands, from the bottom up. */
.hero-blocked.is-absorb{--blkend:330}
.hero-blocked.is-absorb .s-row .plate{stroke:color-mix(in srgb,var(--steel) 56%,transparent)}
.hero-blocked.is-absorb .s-row .plate-fill{fill:color-mix(in srgb,var(--steel) 11%,transparent)}
.hero-blocked.is-absorb .t-row{fill:color-mix(in srgb,var(--steel) 92%,transparent)}
.hero-blocked.is-absorb .row-latch{opacity:0;transform:translateX(-12px)}
.hero-blocked.is-absorb .blk-rule,
.hero-blocked.is-absorb .blk-cap{fill:color-mix(in srgb,var(--steel) 72%,transparent)}
.hero-blocked.is-absorb .blk-word{opacity:0}
.hero-blocked.is-absorb .blk-final{opacity:1}

/* The one journey: through the layer, into production. */
.hero-blocked.is-through .s-code{transform:translateY(-302px)}
.hero-blocked .t-code-2{opacity:0}
.hero-blocked.is-through .t-code-1{opacity:0;transition:opacity .3s ease .45s}
.hero-blocked.is-through .t-code-2{opacity:1;transition:opacity .4s ease .6s}
.hero-blocked.is-through .code-caret{animation:none;opacity:0;transition:opacity .3s ease}

/* Landed: once the code is in production it is drawn in plain ink. Not SIGNAL, which reads as
   a problem once GAP has carried "months", and not STEEL, which is Groundfloor's and would say
   the application changed hands (decided 2026-10-17). Orange stays only while it is blocked. */
.hero-blocked .s-code .plate,.hero-blocked .s-code .plate-fill,
.hero-blocked .code-line,.hero-blocked .t-ready{transition:stroke .6s ease .55s,fill .6s ease .55s}
.hero-blocked .code-line{transition:opacity .16s ease calc(var(--i) * .15s + .22s),fill .6s ease .55s}
.hero-blocked.is-through .s-code .plate{stroke:color-mix(in srgb,var(--ink-landed,currentColor) 80%,transparent)}
.hero-blocked.is-through .s-code .plate-fill{fill:color-mix(in srgb,var(--ink-landed,currentColor) 8%,transparent)}
.hero-blocked.is-through .code-line{fill:color-mix(in srgb,var(--ink-landed,currentColor) 55%,transparent)}
.hero-blocked.is-through .t-ready{fill:var(--ink-landed,currentColor)}

/* --- act 4 · portable --------------------------------------------------- */
/* The ground arrives after the code has vacated the bottom of the frame. */
.hero-blocked.is-ground .s-ground{opacity:1;transform:none}
