/* ============================================================
   HERO — "THE REVISION"
   Today's startup ecosystem, at full volume. It does not shatter.
   It is set down, and what is left is the quiet behind it.
   ============================================================ */

.hero{
  position:relative;
  height:250vh;                 /* the scroll track */
  background:var(--stage);
}
@media (max-width:47.99rem){ .hero{height:200vh} }

.hero__stage{
  position:sticky; top:var(--masthead-h);
  height:calc(100dvh - var(--masthead-h));
  overflow:clip;
  contain:layout paint style;
  display:grid;
  place-items:center;
  isolation:isolate;
  --p:0;
  /* four multipliers. reduced motion sets all of them to 0. */
  --parallax:1; --disperse:1; --drift:1; --xfade:1;

}

/* Every consumer derives the named phases from ITS OWN --p. They are all
   0..1 ramps scrubbed off the scrollbar, so the sequence runs backwards
   identically. Nothing here fires on a beat change. */
.hero [data-p]{
  --swell:   clamp(0, (var(--p) - .015) * 9, 1);
  --peak:    clamp(0, (var(--p) - .10) * 4.4, 1);
  --letgo:   clamp(0, (var(--p) - .545) * 7, 1);
  --file:    clamp(0, (var(--p) - .685) * 20, 1);
  --quiet:   clamp(0, (var(--p) - .865) * 11, 1);
}

/* the warm paper that was behind the screen the whole time */
.hero__paper{
  position:absolute; inset:0; z-index:0;
  background:var(--paper);
  opacity:1;
  transform:translate3d(0, calc((1 - var(--file)) * 101%), 0);
  will-change:transform;
}
@media (prefers-reduced-motion:reduce){
  .hero__paper{ will-change:auto }
}

/* a soft well behind the announcement. it fades as the ecosystem fills,
   so the original post is genuinely hard to find at peak volume. */
.plate__scrim{
  content:""; position:absolute; z-index:-1;
  inset:-16% -12%;
  background:radial-gradient(62% 56% at 34% 50%, rgba(13,12,11,.97) 34%, rgba(13,12,11,.86) 58%, transparent 80%);
  opacity:calc((1 - var(--peak) * .5) * (1 - var(--letgo)));
  pointer-events:none;
}

/* ---------------- the announcement plate ---------------- */
.plate{
  position:relative; z-index:3;
  width:min(100% - 2 * var(--gutter), 62rem);
  transform:translate3d(0, calc(var(--drift) * (var(--p) * -3vh - var(--letgo) * 9vh)), 0);
  opacity:calc(1 - var(--letgo));
}
/* promoted only while the sequence is on screen, so the fade composites
   instead of repainting the headline every frame */
.is-live .plate{ will-change:transform, opacity }

/* ---------------- the statement at the centre of the storm ---------------- */
.anno{
  font-family:var(--sans); font-weight:800; font-stretch:104%;
  -webkit-user-select:none; user-select:none;
  font-size:clamp(2.2rem, 1rem + 5.9vw, 6.25rem);
  line-height:1.0; letter-spacing:-.038em;
  color:#FFFDF8;
  text-wrap:balance;
  max-width:15ch;
}

.plate__byline{
  -webkit-user-select:none; user-select:none;
  font-family:var(--mono); font-size:clamp(.625rem,.55rem + .2vw,.75rem);
  letter-spacing:.2em; text-transform:uppercase; color:var(--on-stage-dim);
  margin-top:clamp(1rem,3vh,2rem);
}

/* ---------------- reactions — genuinely warm, zero irony -------------- */
.reactions{
  -webkit-user-select:none; user-select:none;
  display:flex; flex-wrap:wrap; align-items:center; gap:.35rem 1.15rem;
  margin-top:clamp(1.25rem,3.5vh,2.25rem);
}

.react{
  display:inline-flex; align-items:center; gap:.4rem;
  font-family:var(--serif); font-size:.9375rem; letter-spacing:0;
  color:var(--on-stage-dim);
  /* each congratulation arrives on its own stretch of scroll, then leaves together */
  --on:clamp(0, (var(--p) - .022 - var(--i) * .013) * 42, 1);
  opacity:calc(var(--on) * (1 - var(--letgo)));
  transform:translate3d(0, calc(6px * (1 - var(--on))), 0);
}
.react b{ color:var(--on-stage); font-weight:500; font-variant-numeric:tabular-nums }
/* only the counter keeps a shape — it is the thing that will stop */
.react--tally{
  font-family:var(--mono); font-size:.75rem; letter-spacing:.06em;
  padding:.3rem .6rem; border-radius:999px;
  background:var(--stage-3); box-shadow:inset 0 0 0 1px var(--stage-line);
}

/* the counter that stops. it climbs with the scroll and freezes the moment
   someone starts editing — after that, nothing new arrives. */
@property --tick{ syntax:"<integer>"; inherits:true; initial-value:0 }
.tally{
  color:color-mix(in srgb, var(--on-stage-dim) calc(var(--letgo) * 100%), var(--accent-lift));
  --tick:calc(64 + 1220 * clamp(0, (var(--p) - .012) * 4.4, 1));
  counter-reset:tick var(--tick);
}
.tally::after{ content:counter(tick) }
.tally-fallback{ display:none }
@supports not (counter-reset: tick 1){
  .tally::after{ content:none }
  .tally-fallback{ display:inline }
}

/* ---------------- syndication wall — 3 depth layers ---------------- */
.wall{
  -webkit-user-select:none; user-select:none;
  position:absolute; inset:0; z-index:1;
  pointer-events:none;
  /* swells in with the scroll, and is set down at the turn */
  opacity:calc(var(--swell) * (1 - var(--letgo)));
}

/* parallax lives on the layer, not on the 60 chips */
.wall__layer{
  position:absolute; inset:-14% -4%;
  display:flex; flex-wrap:wrap;
  align-content:space-evenly; justify-content:space-evenly;
  gap:clamp(.35rem,1vw,.9rem) clamp(.6rem,2vw,1.8rem);
  will-change:transform;
  /* parallax lives here, and so does the un-setting — one transform, one layer */
  transform:translate3d(0, calc(
      var(--parallax) * var(--speed) * (var(--p) - .30) * -58vh
      + var(--disperse) * var(--letgo) * 46vh
  ), 0);
}
.wall__layer{ opacity:calc(var(--depth-op) * (.42 + var(--peak) * .58)) }
.wall__layer[data-depth="1"]{ --speed:.34; --depth-op:.42; filter:blur(2.2px) }
.wall__layer[data-depth="2"]{ --speed:.66; --depth-op:.74 }
.wall__layer[data-depth="3"]{ --speed:1;   --depth-op:1 }

/* THE FOREGROUND. These pass in front of the announcement, which is what makes
   the visitor feel inside the ecosystem instead of looking at a backdrop.
   Kept blurred and faint so the sentence still wins. */
.wall--front{
  z-index:4;
  opacity:calc(var(--swell) * .5 * (1 - var(--letgo)));
}
.wall__layer--front{
  --speed:1.5;
  filter:blur(3.5px);
  display:block; inset:0;
}
.wall__layer--front .chip{
  position:absolute; left:var(--fx); top:var(--fy);
  translate:-50% -50%;
  color:var(--on-stage);
  opacity:.5;
}
.wall__layer--front .chip--solid{ opacity:.42 }

/* the signals are mostly bare type — headline fragments, not a tag cloud */
.chip{
  font-family:var(--sans); font-weight:800; font-stretch:98%;
  letter-spacing:-.022em; white-space:nowrap; line-height:1;
  color:var(--on-stage-dim);
  font-size:calc(var(--sz,1) * clamp(.8rem, .45rem + 1.5vw, 2rem));
  transform:translate3d(var(--dx,0), var(--dy,0), 0);
}
/* ticker / metadata voice */
.chip--mono{
  font-family:var(--mono); font-weight:500; letter-spacing:.14em;
  font-size:calc(var(--sz,1) * clamp(.6rem,.45rem + .45vw,.9rem));
  color:var(--on-stage-dim);
}
/* press clipping — a rule above, like a cut column */
.chip--clip{
  font-weight:600; font-stretch:88%; letter-spacing:0;
  font-size:calc(var(--sz,1) * clamp(.72rem,.5rem + .8vw,1.15rem));
  border-top:1px solid var(--stage-line); padding-top:.3em;
}
/* notification — the only boxed form, and it is rare */
.chip--box{
  font-weight:600; font-size:calc(var(--sz,1) * clamp(.7rem,.5rem + .7vw,1.05rem));
  padding:.42em .7em; border-radius:3px;
  background:var(--stage-2); box-shadow:inset 0 0 0 1px var(--stage-line);
  color:var(--on-stage);
}
.chip--hot{ color:var(--accent-lift) }
.chip--solid{
  background:var(--accent); color:#fff; padding:.28em .6em; border-radius:2px;
  font-size:calc(var(--sz,1) * clamp(.75rem,.5rem + 1vw,1.4rem));
}

/* The wall UN-SETS: type falls to a baseline and sweeps off — printing,
   run backwards. Nothing explodes and nothing is destroyed. It is scrubbed,
   so scrolling back up sets the type again. */

/* ---------------- margin notes — every one of them reasonable ------- */




@media (max-width:47.99rem){
  .chip[data-m="0"]{ display:none }
  .wall__layer--front{ filter:blur(3px) }
  .wall--front{ opacity:calc(var(--swell) * .34 * (1 - var(--letgo))) }
  .wall__layer{ inset:-14% -4%; gap:.35rem .6rem }
  /* the plate has to win on a small screen — the storm reads around it */
  .plate__scrim{
    inset:-10% -22% -22%;
    background:radial-gradient(76% 46% at 42% 50%, var(--stage) 46%, rgba(13,12,11,.9) 66%, transparent 86%);
  }
  
  
  
}

/* One artefact is left on the empty page, so the silence reads as aftermath
   rather than as a page that failed to load. It is the counter that stopped. */
.hero__residue{
  -webkit-user-select:none; user-select:none;
  position:absolute; z-index:5;
  left:var(--gutter); top:50%;
  transform:translateY(-50%);
  display:flex; align-items:center; gap:.9rem;
  font-family:var(--mono); font-size:.6875rem; font-weight:500;
  letter-spacing:.24em; text-transform:uppercase; color:var(--muted);
  opacity:calc(clamp(0, (var(--p) - .735) * 16, 1) * (1 - var(--quiet)));
}
.hero__residue::before{
  content:""; width:clamp(1.5rem,4vw,3rem); height:1px; background:var(--accent);
}

/* ---------------- the bridge into the room ---------------- */
.hero__bridge{
  position:absolute; z-index:5;
  left:var(--gutter); right:var(--gutter);
  top:50%; transform:translateY(-50%);
  margin-inline:auto; max-width:26ch;
  font-family:var(--serif); font-weight:400;
  font-size:clamp(1.35rem, .95rem + 2.1vw, 2.75rem);
  line-height:1.24; letter-spacing:-.018em;
  color:var(--ink); text-align:center; text-wrap:balance;
  opacity:var(--quiet);
}

/* ---------------- scroll hint — the only instruction, and it is one word */
.hero__hint{
  position:absolute; z-index:6; left:50%; bottom:1.75rem;
  transform:translateX(-50%);
  display:flex; align-items:center; gap:.6rem;
  font-family:var(--mono); font-size:.625rem; letter-spacing:.24em;
  text-transform:uppercase; color:var(--on-stage-dim);
  opacity:calc(1 - clamp(0, (var(--p) - .04) * 14, 1));
}
.hero__hint::after{
  content:""; width:1px; height:1.6rem; background:currentColor;
  transform-origin:top; animation:drop 2.2s var(--ease-io) infinite;
}
@keyframes drop{ 0%,100%{transform:scaleY(.3);opacity:.35} 50%{transform:scaleY(1);opacity:1} }


/* ============================================================
   Reduced motion: four multipliers to zero, pins become panels.
   Every beat is still received — as a finished editorial plate.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  .hero__stage{ --parallax:0; --disperse:0; --drift:0; --xfade:0 }
  .wall__layer{ will-change:auto; transform:none!important; filter:none }
  .hero__hint::after{ animation:none; transform:scaleY(1) }
  
  
}

/* No JS: the hero must still say something true and complete.
   The kinetic layers are absent rather than merely transparent, and the
   statement plus the bridge line carry the argument on their own. */
html:not(.seq-ready) .hero{ height:auto }
html:not(.seq-ready) .hero__stage{
  position:static; height:auto; padding-block:18vh; place-items:start center;
}
html:not(.seq-ready) .wall,
html:not(.seq-ready) .hero__hint,
html:not(.seq-ready) .hero__residue,
html:not(.seq-ready) .hero__paper{ display:none }
html:not(.seq-ready) .plate{ opacity:1; transform:none }
html:not(.seq-ready) .plate__scrim{ display:none }
html:not(.seq-ready) .hero__bridge{
  position:static; transform:none; opacity:1;
  margin-top:3rem; color:var(--on-stage);
}
