/* ─────────────────────────────────────────────────────────────
   hero.css — the fold
   ───────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  display: flex;

  /* stretch, not center: the measure block has to fill the fold so the scroll
     cue can sit against the bottom of the SCREEN. The copy is centred inside
     it instead — an absolutely positioned child of a centred block measures
     against the copy's height, not the fold's. */
  align-items: stretch;

  /* Exactly the viewport, less the masthead above it. --nav-h is computed in
     base.css from the masthead's own tokens, which is the right answer
     without JS; main.js then overwrites it with the measured height, because
     the demo pill is taller than the logo the token is derived from. The
     floor keeps the copy from being crushed on a short landscape phone. */
  /* Not a full viewport. At 100svh the fold had more empty height than its
     content needed, and the copy position, the scroll cue and the band's ramp
     all competed for the surplus. The fold is now sized to its content, and
     the slice of ramp showing below it does the same job the cue does.

     74svh, and this is a ceiling rather than a preference. The fold and the
     scroll cue compete for the same pixels: the ramp starts where the fold
     ends, and the cue can only go as deep as what is left below it, so every
     pixel given to the hero is a pixel of gradient the flat white cue cannot
     reach. Swept at three viewports, the cue holds 3.12:1 at 62, 66, 70 and 74
     and falls to 2.96 at 78 — under the 3:1 bar. Note that below 74 this value
     is inert at common sizes: at 1440x900 the copy already makes the fold
     549px, taller than 74svh less the masthead, so the min-height only bites
     on tall viewports. The floor keeps the copy from being crushed on a short
     landscape phone. */
  min-height: max(460px, calc(74svh - var(--nav-h)));
  padding: clamp(24px, 3vh, 48px) 0;
}

/* The fold's own box: full height, cue pinned to the bottom edge.
   The copy sits in the upper third rather than dead centre — centred, it left
   ~180px of empty ivory between the masthead and the headline at 1440x900 and
   243px at 1920, which read as the page not having started yet. Weighted up,
   the space collects at the bottom instead, where the field and the scroll cue
   are doing something with it. */
.hero > .wrap {
  position: relative;
  z-index: 1;                 /* above the fixed signal field */
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.hero__copy {
  /* 11.5vh, up from 8.5. Worth knowing this is not free: the fold's height is
     content-driven at common sizes, so every pixel added here pushes the join
     down and takes a pixel of gradient the scroll cue needs to stay legible.
     The ramp was shortened to pay for it. */
  margin-top: clamp(36px, 14.5vh, 174px);

  /* The shader veils roughly the left third of the viewport for copy — this
     column is sized to stay inside that cleared area. Widened from 560 to 640
     for the category headline: "The decision layer" sets 703px at the old
     92.16px display size, so at 560 it could not hold on one line at any size
     worth setting it at. The halo is not a fixed region — main.js reports the
     measured copy box to the field every frame — so the cleared area follows
     this, and 640 at 1440 still lands inside the default box the shader boots
     with (0.03-0.44 of the viewport). */
  width: min(100%, 640px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* ── Headline ─────────────────────────────────────────────── */
.hero__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  /* 80px at the top, down from 104. The headline is 52 characters now rather
     than 34, and the longest line has to hold in the copy column: measured,
     "The decision layer" needs 7.63px of width for every px of font-size, so
     640px of column buys 83px of type and 80 leaves the margin. A category
     line earns its size by being read, not by being the largest thing on the
     page — and at 80px it is still the largest thing on the page.

     ONE curve, not two. A separate mobile clamp under a 900px breakpoint put
     a cliff at the breakpoint itself: 72px at 900 and 58px at 901, the
     headline shrinking as the viewport grew. And a fixed 46px floor wrapped
     "The decision layer" onto two rows at 375px — an iPhone SE — because the
     column there is 335px and the line needs 341.

     So the size is solved from the column instead of guessed per breakpoint:
     the line needs 7.41px of width per px of font-size, the column is the
     viewport less two gutters, and this is 88% of what that allows. It
     reaches its 80px ceiling at 713px, which is where the column stops
     growing.

     ONE curve, not two. A separate mobile clamp under a 900px breakpoint put
     a cliff at the breakpoint itself: 72px at 900 and 58px at 901, the
     headline shrinking as the viewport grew. This is continuous from 320 to
     2560 and solved so the widest line ("at the moment", italic at 0.86em,
     5.05px of width per px of font-size) always holds in the copy column. */
  /* Bounded on BOTH axes. The clamp scales with viewport WIDTH, but the space
     the fold has to fit into is bounded by viewport HEIGHT — so a 1920x900
     laptop got 104px of headline in 900px of page, the fold ran long, and the
     scroll cue below it could not reach the green part of the ramp. The vh
     term only bites on short viewports: at 1440x900 the width term already
     asks for 95 and this caps it at 90; at 1440x1080 it asks for 95 and the
     cap is 108, so nothing changes. */
  font-size: min(clamp(46px, 27.7px + 4.696vw, 104px), 10vh);
  line-height: 0.98;
  color: var(--ink);
  font-optical-sizing: auto;

  /* Tracking is size-specific, never one value for all sizes: letters read
     too far apart as display type grows, so it tightens as the headline
     scales. An em value would be proportionally constant — the exact thing
     that is wrong. This tracks the font-size clamp above, -0.012em at the
     small end to -0.025em at the large one. */
     Re-solved for the 46-104px range the single clamp above now spans. Same
     intent and the same em endpoints throughout: -0.012em where the type is
     smallest, -0.025em where it is largest. */
  letter-spacing: clamp(-2.6px, 0.097px - 0.166vw, -0.55px);
}

.hero__line { display: block; }

/* The roman line carries more counter space than the italics at the same
   size, so it takes a touch more tightening. */
.hero__line--display {
  letter-spacing: clamp(-3.1px, 0.097px - 0.1968vw, -0.67px);
}

/* The italic lines run marginally smaller than the roman first line, the
   way the reference sets them — the drop keeps the three lines optically
   equal in weight even though the italic carries more visual texture. */
.hero__line--italic {
  font-style: italic;
  font-size: 0.86em;
  letter-spacing: -0.005em;
}

/* The emphasised word takes the primary logo green, tying the headline to
   the mark in the masthead. It clears AA on the ivory at this size; the
   accent sage does not, which is why that one stays in the field. */
.hero__title em {
  font-style: italic;
  color: var(--signal);
}

/* ── Category ─────────────────────────────────────────────────
   The sentence that names what this is, sitting between the brand
   line and the mechanism. Inter, not Newsreader: two display faces
   stacked compete, and this one's job is to be read flatly rather
   than to perform. It is the second-largest type in the fold, which
   is the position it has to hold — the visitor who does not read
   past it should still leave knowing the category.               */
.hero__category {
  max-width: 26em;
  margin: clamp(20px, 2.6vh, 30px) 0 0;
  font-size: clamp(18.5px, 1.5vw, 23px);
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.008em;
  color: var(--ink);
  text-wrap: balance;
}

/* ── Lede ─────────────────────────────────────────────────── */
.hero__lede {
  /* Wide enough for the longer of the two lines below to hold on one row.
     Re-measured for the new lede: "It says what changed, what it is worth,
     and who needs to decide." is the longer clause. The em unit keeps the
     ratio across the whole font-size clamp. */
  max-width: 33em;
  margin: clamp(16px, 2vh, 24px) 0 0;
  /* Back to --t-body. With the category line above it at 23px, a lede at
     --t-lede put two near-equal sizes next to each other and flattened the
     step between "what this is" and "what it does". */
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink-soft);
}

/* The lede breaks by clause rather than wherever the measure runs out —
   two rows, one thought each. Only where there is room for it: below that,
   forcing the break would just move the ragged edge into the middle of a
   sentence, so the lines go back to being inline and wrap normally. The
   newline between them in the markup is the space that rejoins them. */
@media (min-width: 660px) {
  .hero__lede-line { display: block; }
}

/* ── Actions ──────────────────────────────────────────────── */
.hero__actions {
  display: flex;
  align-items: center;
  gap: clamp(24px, 3vw, 46px);
  margin-top: clamp(30px, 4.4vh, 56px);
}

/* Hidden outside the mobile block below — see .hero__cta-pill there. */
.hero__cta-pill { display: none; }

/* ── Responsive ───────────────────────────────────────────────
   No size override here. The headline's clamp is continuous from
   320px to 2560px, which is what removed the cliff at this
   breakpoint; the copy column is min(100%, 640px) at every width
   and needs no restatement.                                     */

@media (max-width: 560px) {
  /* Centered rather than left-edge-aligned: at this width the copy column
     runs the full viewport (less the gutters), so a left-aligned block has
     no visible column to align against — it just reads as text sitting at
     the screen's edge. Centering gives it a deliberate axis instead. */
  .hero__copy {
    align-items: center;
    text-align: center;
  }

  .hero__actions {
    flex-direction: column;
    align-items: center;
    gap: 22px;
  }

  /* The disc CTA and the quiet "See the signal" link both did a job a
     single pill now does on its own — see the markup note by
     .hero__cta-pill in index.html. */
  .cta,
  .hero__actions > .link-quiet {
    display: none;
  }

  .hero__cta-pill { display: inline-flex; }
}

/* ── Scroll cue ───────────────────────────────────────────────
   Centred on the page and sized to be found. An outlined disc,
   not a filled one, so it reads below the primary CTA in the
   hierarchy while still being unmissable.
   ───────────────────────────────────────────────────────────── */
.hero__scroll {
  position: absolute;
  left: 50%;

  /* Positioned against --ramp, not against the fold's edge. The cue has to
     land deep enough into the gradient that the ground behind it is green
     rather than ivory — a white chevron on paper is not a cue, it is nothing —
     and the only value that knows where the green is is the ramp's own length.
     That is why --ramp lives on :root now instead of on .band--noise: the two
     sides of this must not be able to drift apart. */
  /* --cue-drop is written by main.js: the deepest the cue can sit and still be
     fully on screen, capped at the depth where the ramp has gone dark. It has
     to be measured rather than expressed in vh, because where the fold ends
     depends on how tall the copy renders, not on the viewport alone — a 20vh
     guess put the cue back up on the ivory at 1440x900 and 5px off the bottom
     edge at 1280x800. The fallback only matters before JS runs. */
  bottom: calc(-1 * var(--cue-drop, 24vh));
  transform: translateX(-50%);
  display: grid;
  place-items: center;

  /* No disc. On ivory the chevron needed a container to hold its own against
     the paper; sitting on the green it does not, and that ring was the only
     hard edge in a part of the page whose whole job is having none. The box
     stays large for the touch target — 2.5.8 asks for 24x24 and this is well
     past it — but nothing about it paints. */
  width: clamp(64px, 5.5vw, 84px);
  height: clamp(64px, 5.5vw, 84px);
  border: 0;
  background: none;

  /* White, flat, no disc, sitting in the green. Worth recording that this is
     a deliberate call and not an oversight: measured, the mark lands at
     2.9:1 at 1440x900 and lower on shorter folds, under the 3:1 that 1.4.11
     asks of a control whose only visual it is. The alternatives were a dark
     chevron (9.1:1, but it reads as a different object) or a shadow (which is
     the disc again in all but name). The motion below is doing the
     discoverability work instead. */
  color: #FFFFFF;
  transition: color var(--dur-fast) var(--ease),
              opacity 420ms var(--ease);
}

.hero__scroll svg {
  width: clamp(32px, 2.8vw, 40px);
  height: auto;
}

.hero__scroll:hover { color: var(--sage-pale); }

.hero__scroll:active { transform: translate(-50%, 2px); transition-duration: 90ms; }

/* Once the reader is moving, the prompt has done its job. */
.hero__scroll[data-spent] {
  opacity: 0;
  pointer-events: none;
}

/* And its loop stops with it — a nonessential animation must not keep running
   on an element nobody can see. */
.hero__scroll[data-spent] svg { animation: none; }

/* A slow, shallow drift — an affordance hint, not a performance. It is the
   only looping motion on the page and it stops the moment it is not needed. */
@media (prefers-reduced-motion: no-preference) {
  .hero__scroll svg { animation: hero-cue 3s var(--ease) infinite; }

  /* A fall and a settle, then a long rest — not a continuous drift.
     The old curve moved 5px on a soft sine, which at this size on this ground
     was close to invisible; the reason to notice a scroll cue is that it
     MOVED, and 5px of ease-in-out barely registers as movement.

     This travels 11px, drops fast (18% of the cycle) and returns slower, then
     repeats the gesture at roughly half the amplitude before stopping. Two
     dips read as deliberate where one reads as a twitch. The rest is the
     other half of the design: 40% of every cycle is completely still, which
     is what keeps a louder motion from becoming a metronome in the corner of
     the eye. Opacity swings with it so the mark gains presence on the way
     down rather than only shifting position. */
  @keyframes hero-cue {
    0%          { transform: translateY(0);    opacity: 0.72; }
    18%         { transform: translateY(11px); opacity: 1; }
    34%         { transform: translateY(0);    opacity: 0.84; }
    46%         { transform: translateY(6px);  opacity: 0.96; }
    60%, 100%   { transform: translateY(0);    opacity: 0.72; }
  }
}

/* Too short to spare the room, and the affordance matters least where the
   whole page is already one gesture away. 720 rather than 660: shortening the
   fold to 88svh moved the cue up with it, and at 700 its box began overlapping
   the copy's. Nothing visibly collides — the copy's children shrink-wrap — but
   a longer headline would land on it. */
@media (max-height: 720px) {
  .hero__scroll { display: none; }
}

/* The same rule, measured rather than guessed. main.js sets this when the
   cue's centre lands shallower than a quarter of --ramp below the join —
   where the gradient is still near-ivory and a white chevron reads at 1.1:1.
   The 720px media query above was standing in for this condition and was set
   too low: at 768 the cue was still on paper.

   Hidden, not recoloured. A dark chevron reads as a different object — it was
   considered and rejected when the cue was designed — and it is better for
   the affordance to be absent than to be invisible while still sitting in the
   tab order. */
.hero__scroll[data-no-ground] { display: none; }

