/* ==========================================================================
   Components — their architecture, levelled up.

   The shapes that already work on the live site are kept: the chevron marquee,
   the serif section headings, the mint Unboxed block, the tan insights band,
   the tilted ribbon, the googly eyes, the ghosted footer wordmark.
   What changes is the execution, and the three places where a three-card grid
   was standing in for a shape that actually suited the content.
   ========================================================================== */

/* --- Shared -------------------------------------------------------------- */
.eyebrow {
  display: inline-block;
  padding: 0.45em 0.9em;
  background: var(--tan);
  color: var(--on-tan);
  font-size: var(--micro-size);
  font-weight: 700;
  letter-spacing: var(--micro-track);
  text-transform: uppercase;
}
.eyebrow--mint { background: var(--mint); color: var(--on-mint); }

.tm { font-size: 0.42em; vertical-align: super; font-weight: 400; }

.section-head { max-width: 46rem; margin-bottom: var(--s-5); }
.section-head--centre { margin-inline: auto; text-align: center; }

.section-head__title {
  font-family: var(--font-display);
  font-size: var(--step-5);
  text-wrap: balance;
  line-height: 0.95;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  margin-block: var(--s-2) var(--s-3);
}
/* Their serif headings are the warmth in the whole thing. Kept, at the wide
   tracking they set them in. */
.section-head__title--serif {
  font-family: var(--font-serif);
  font-weight: 900;
  letter-spacing: 0.01em;
  text-transform: none;
  line-height: 1.05;
}

.section-head__sub { font-size: var(--step-1); line-height: 1.45; max-width: 44ch; }

.link {
  display: inline-flex;
  gap: 0.4em;
  font-weight: 600;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  padding: 0.9em 1.5em;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: transform var(--t-fast) var(--ease-out),
              background-color var(--t-fast) linear,
              color var(--t-fast) linear;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn--sm { padding: 0.65em 1.1em; }
.btn--lg { padding: 1.05em 1.9em; font-size: var(--step-0); }

/* Their magenta CTA sets a cream label, which measures 4.29:1 and misses AA
   body by 0.21. White is 4.89:1 — the same button, compliant. */
.btn--magenta   { background: var(--magenta);   color: var(--on-magenta); }
.btn--mint      { background: var(--mint);      color: var(--on-mint); }
.btn--bubblegum { background: var(--bubblegum); color: var(--on-bubblegum); }
.btn--dark      { background: var(--charcoal);  color: var(--cream); }
.btn--outline   { border-color: currentColor; }

.btn--magenta:hover   { background: var(--white);    color: var(--magenta); }
.btn--mint:hover      { background: var(--charcoal); color: var(--mint); }
.btn--bubblegum:hover { background: var(--charcoal); color: var(--bubblegum); }
.btn--dark:hover      { background: var(--mint);     color: var(--on-mint); }
.btn--outline:hover   { background: var(--cream);    color: var(--charcoal); }

/* --- Masthead ------------------------------------------------------------ */
/* ==========================================================================
   THE MASTHEAD — it takes the colour of the band underneath it
   --------------------------------------------------------------------------
   A translucent, blurred bar lets the page ghost through it: you read half a
   headline sliding under the logo. So the header is OPAQUE, and it wears the
   ground colour of whatever section is currently beneath it — which means on
   the pink band it IS the pink band, on the mint it is the mint, and nothing
   ever scrolls through it.

   Each section declares three things and the header reads them off the section
   under it (see `chrome()` in app.js). Anything that declares nothing inherits
   the charcoal default from :root, so a new section needs no wiring at all.

     --chrome       the band colour
     --chrome-ink   what is legible on it
     --chrome-mark  which lockup colourway to paint

   Photo sections declare a colour sampled from the top of their own image, not
   a guess: the hero's top third measures (46,46,59) and holds that within two
   points for the whole time it is under the header.
   ========================================================================== */
.masthead {
  position: fixed;
  inset: 0 0 auto;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--hdr-h);
  padding-inline: var(--gutter);
  /* The fill lives in .masthead__bg, not here — see below. */
  background: none;
  color: var(--chrome-fg, var(--cream));
  transition: color 260ms linear;
}
/* The background is two slices rather than one fill, so a section boundary
   travelling up through the header is painted at its exact pixel instead of
   the whole band flipping colour at some threshold. Each slice carries its
   own scrim and, where a band declares one, its own picture. */
.masthead__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.masthead__film {
  position: absolute;
  left: 0;
  width: 100%;
  display: none;          /* only while a film band is under the header */
  pointer-events: none;
}
.masthead__bg i {
  position: absolute;
  left: 0; right: 0;
  display: block;
  background-repeat: no-repeat;
  /* No transition on the fill: the hero band is re-sampled every other frame
     while the film plays, and a 260ms colour transition would chase it and
     smear. Flat bands change once, where a jump is imperceptible anyway. */
}
/* Rich sets the lockup at 18.26% of the page width with its top edge at 1.27%,
   which needs a taller band than the 68px one we had. */
@media (min-width: 62rem) {
  .masthead { padding-inline: min(3.98vw, 68px); }
}

.masthead__logo { display: flex; margin-right: auto; }
.masthead__mark {
  display: block;
  width: clamp(150px, 18.26vw, 292px);
  aspect-ratio: 3992 / 944;      /* the lockup's own viewBox */
  background-image: var(--chrome-mark, url('/assets/brand/fractionals-lockup-cream.svg'));
  background-size: contain;
  background-repeat: no-repeat;
  background-position: left center;
}

.masthead__nav { display: flex; gap: var(--s-3); font-size: var(--step--1); font-weight: 500; }
.masthead__nav a { color: var(--cream-muted); transition: color var(--t-fast) linear; }
.masthead__nav a:hover { color: var(--cream); }

/* Left to right: the two routes, then the sign-in icon, then the menu — each
   separated so the icon does not read as part of either neighbour. */
.masthead__actions { display: flex; align-items: center; gap: var(--s-3); }
.masthead__login { font-size: var(--step--1); font-weight: 600; color: var(--cream-muted); }
.masthead__login:hover { color: var(--cream); }

@media (max-width: 68rem) { .masthead__nav { display: none; } }
@media (max-width: 46rem) {
  .masthead__login,
  .masthead__actions .btn[data-role="candidate"] { display: none; }
}

/* --- Hero ---------------------------------------------------------------- */
.hero {
  position: relative;
  display: grid;
  align-content: end;
  min-height: min(100svh, 56rem);
  padding-top: var(--chrome-h);
  background: var(--charcoal);
  color: var(--cream);
  overflow: clip;
}

.hero__media { position: absolute; inset: 0; }
.hero__poster,
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
}
.hero__video { opacity: 0; transition: opacity 900ms linear; }
.hero.is-live .hero__video { opacity: 1; }

/* Theirs darkens the whole photograph evenly, which on a phone flattens the
   subject into black. This keeps the middle of the frame readable and puts the
   weight where the type actually sits. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, var(--charcoal) 2%, rgb(26 27 30 / 0.82) 26%,
                    rgb(26 27 30 / 0.28) 58%, rgb(26 27 30 / 0.45) 100%);
}

.hero__inner {
  position: relative;
  z-index: 2;
  padding-top: var(--s-6);
  padding-bottom: clamp(var(--s-4), 6vh, var(--s-6));
}

/* Their H1 is 57.6px inside a 900px hero, while the biggest type on the site
   (144px) is four sections further down. The budget is spent here instead. */
.hero__title {
  font-family: var(--font-display);
  font-size: var(--hero);
  line-height: 0.86;
  letter-spacing: 0.002em;
  text-transform: uppercase;
  margin: var(--s-3) 0;
  text-wrap: balance;
}

.hero__lede {
  max-width: 42ch;
  font-size: var(--step-1);
  line-height: 1.45;
  margin-bottom: var(--s-4);
}

.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s-2); }

.hero__play {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  margin-top: var(--s-4);
  padding: 0.6em 1.2em 0.6em 0.6em;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--cream);
  text-align: left;
  transition: background-color var(--t-fast) linear, border-color var(--t-fast) linear;
}
.hero__play:hover {
  background: color-mix(in srgb, var(--cream) 12%, transparent);
  border-color: var(--cream);
}
.hero__play-glyph {
  flex: none;
  position: relative;
  width: 2.2rem; height: 2.2rem;
  border-radius: 50%;
  background: var(--bubblegum);
}
.hero__play-glyph::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 0; height: 0;
  border-left: 9px solid var(--charcoal);
  border-block: 6px solid transparent;
  transform: translateX(2px);
}
.hero__play-label { display: grid; gap: 0.15em; }
.hero__play-label b { font-size: var(--step--1); letter-spacing: 0.02em; }
.hero__play-label .micro { color: var(--cream-muted); }

/* --- Marquee -------------------------------------------------------------
   Theirs clips mid-glyph at 390px because it is a fixed string. This one is
   filled to the measured viewport and scrolls as two identical runs. */
.marquee {
  position: relative;
  z-index: 2;
  overflow: hidden;
  border-top: 1px solid var(--rule);
  padding-block: var(--s-2);
  background: var(--charcoal);
}
.marquee__track { display: flex; width: max-content; }
.marquee__run {
  display: flex;
  gap: 0.45rem;
  padding-right: 0.45rem;
  animation: marquee 44s linear infinite;
}
/* Theirs are chunky solid arrowheads, not a typed ">" — a glyph renders thin
   and varies by platform, so these are drawn. */
.marquee__chev {
  flex: none;
  width: 1.45rem;
  height: 2.1rem;
  background: var(--cream);
  opacity: 0.95;
  clip-path: polygon(0 0, 44% 0, 100% 50%, 44% 100%, 0 100%, 56% 50%);
}

/* The rotated wordmark badge that terminates their marquee. */
.marquee__badge {
  position: absolute;
  right: var(--gutter);
  top: 50%;
  z-index: 2;
  height: 3.4rem;
  transform: translateY(-50%);
  padding-left: var(--s-5);
  background: linear-gradient(to right, transparent, var(--charcoal) 40%);
}
.marquee__badge img { height: 100%; width: auto; }
@media (max-width: 40rem) { .marquee__badge { display: none; } }
@keyframes marquee { to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) { .marquee__run { animation: none; } }

/* --- The difference ------------------------------------------------------ */
.difference { background: var(--charcoal); color: var(--cream); padding-block: var(--s-6); }

.versus { display: grid; gap: var(--s-3); align-items: start; }
@media (min-width: 62rem) {
  .versus { grid-template-columns: 1fr 1.15fr 1fr; gap: var(--s-4); align-items: stretch; }
}

.card-v {
  display: grid;
  gap: var(--s-1);
  align-content: start;
  padding: var(--s-3);
  background: color-mix(in srgb, var(--cream) 5%, transparent);
  border: 1px solid var(--rule);
}
.card-v--fred { border-color: color-mix(in srgb, var(--bubblegum) 55%, transparent); }

/* Both figures stand on one baseline at a common height. The two cutouts have
   very different aspect ratios — NED is 939x2812, FrED 2673x2967 because the
   flame runs out to the right — so sizing by width would render them at wildly
   different scales and lose the comparison the section exists to make. */
.card-v__figure {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  height: clamp(13rem, 30vh, 20rem);
  margin-bottom: var(--s-2);
  border-bottom: 1px solid var(--rule);
}
.card-v__figure img { height: 100%; width: auto; max-width: 100%; object-fit: contain; object-position: bottom center; }

.card-v__name {
  font-family: var(--font-display);
  font-size: var(--step-4);
  line-height: 1;
  text-transform: uppercase;
}
.card-v--fred .card-v__name { color: var(--bubblegum); }
.card-v__expand { color: var(--cream-muted); }
.card-v__blurb { font-size: var(--step--1); line-height: 1.55; color: var(--cream-muted); }

/* The stat ladder, from the client's own Top Thumps cards. */
.ladder { display: grid; align-content: center; }
.ladder__table { width: 100%; border-collapse: collapse; }
.ladder__table thead th {
  font-size: var(--micro-size);
  font-weight: 700;
  letter-spacing: var(--micro-track);
  text-transform: uppercase;
  color: var(--cream-muted);
  padding-bottom: var(--s-1);
  border-bottom: 1px solid var(--rule);
}
.ladder__table thead th:nth-child(2) { text-align: center; }
.ladder__table tbody tr { border-bottom: 1px solid var(--rule); }
.ladder__table tbody th {
  font-size: var(--step--1);
  font-weight: 500;
  text-align: center;
  padding: 0.9em 0.5em;
}
.ladder__n { position: relative; width: 26%; padding: 0.9em 0.6em; }
.ladder__n b { font-family: var(--font-display); font-size: var(--step-2); }
.ladder__n:first-child { text-align: left; }
.ladder__n:last-child { text-align: right; }

/* Bars inset to their own cell and scale. An em-based width reaches 145px at
   10/10, which is wider than the cell on a phone and escapes the table. */
.ladder__bar {
  position: absolute;
  left: 0.6em; right: 0.6em; bottom: 0.55em;
  height: 3px;
  background: currentColor;
  opacity: 0.3;
  transform: scaleX(0);
  transition: transform var(--t-slow) var(--ease-out);
}
.ladder__bar--a { transform-origin: left center; }
.ladder__bar--b { transform-origin: right center; }
.ladder__table.is-in .ladder__bar--a { transform: scaleX(calc(var(--a) / 10)); }
.ladder__table.is-in .ladder__bar--b { transform: scaleX(calc(var(--b) / 10)); }

tr[data-win="ned"]  .ladder__n:first-child b,
tr[data-win="fred"] .ladder__n:last-child b { color: var(--mint); }
tr[data-win="ned"]  .ladder__n:first-child .ladder__bar,
tr[data-win="fred"] .ladder__n:last-child .ladder__bar { opacity: 1; height: 5px; }

.difference__foot {
  margin-top: var(--s-4);
  max-width: 54ch;
  color: var(--cream-muted);
}
.difference__foot .link { color: var(--cream); margin-left: 0.4em; }

/* --- Let it burn --------------------------------------------------------- */
.burn__media img { width: 100%; aspect-ratio: 16/6; object-fit: cover; object-position: 50% 40%; }
.burn__band { background: var(--bubblegum); color: var(--on-bubblegum); padding-block: var(--s-5); }
.burn__grid { display: grid; gap: var(--s-3); }
@media (min-width: 62rem) {
  .burn__grid { grid-template-columns: 1.1fr 1fr; gap: var(--s-5); align-items: end; }
}
.burn__title {
  font-family: var(--font-display);
  font-size: var(--step-5);
  line-height: 0.95;
  text-transform: uppercase;
}
/* Upright, not italic: this instance of Fraunces has no italic, and a
   synthesised oblique on a soft serif shears the ball terminals into a mess.
   The face change against the Anton line above is contrast enough. */
.burn__title em {
  font-family: var(--font-serif);
  font-style: normal;
  font-weight: 900;
  text-transform: none;
}
.burn__copy { display: grid; gap: var(--s-3); justify-items: start; }
.burn__copy p { max-width: 38ch; }

/* --- How it works — a sequence, not three peers --------------------------- */
.how { background: var(--oat); color: var(--charcoal); padding-block: var(--s-6); }

.toggle {
  display: inline-flex;
  padding: 4px;
  border: 1px solid var(--rule-dark);
  border-radius: 999px;
}
.toggle__btn {
  padding: 0.55em 1.2em;
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--charcoal-muted);
}
.toggle__btn.is-on { background: var(--magenta); color: var(--on-magenta); }

.steps { display: grid; gap: var(--s-4); margin-top: var(--s-5); }

@media (min-width: 56rem) {
  .steps { position: relative; grid-template-columns: repeat(3, 1fr); }
  /* The line is what makes it a sequence rather than three boxes with numbers
     printed on them. */
  .steps::before {
    content: '';
    position: absolute;
    z-index: 0;
    top: calc(var(--s-3) + 1.15rem);
    left: 12%;
    right: 12%;
    height: 2px;
    background: repeating-linear-gradient(to right,
      var(--charcoal) 0 9px, transparent 9px 17px);
    opacity: 0.4;
  }
}

.step {
  position: relative;
  display: grid;
  gap: var(--s-1);
  align-content: start;
  padding: var(--s-3);
  background: var(--magenta);
  color: var(--on-magenta);
}
/* The slabs tilt, the way their I'M HIRING button does. The individual rotate
   and translate properties rather than transform, which reveals() is using. */
.step { rotate: var(--tilt); }
.step:nth-child(1) { --tilt: -1.4deg; --dx: 10px; --dy: -13px; --float: 7.5s; --at: -1s; }
.step:nth-child(2) { --tilt: 1deg; --dx: -9px; --dy: 12px; --float: 9s; --at: -4s; }
.step:nth-child(3) { --tilt: -1.2deg; --dx: 8px; --dy: 14px; --float: 8s; --at: -6s; }
@media (max-width: 55.99rem) {
  /* One column, so the scatter is sideways and the drift stays small. */
  .step:nth-child(odd) { margin-right: 1.25rem; }
  .step:nth-child(even) { margin-left: 1.25rem; }
  .step { --dx: 3px; --dy: 6px; }
}
/* Slow and small, because there is text on it, and it stops under the pointer
   so nobody has to chase a sentence. */
@media (prefers-reduced-motion: no-preference) {
  .step { animation: step-float var(--float) ease-in-out var(--at) infinite; }
  .step:hover { animation-play-state: paused; }
  @keyframes step-float {
    0%, 100% { translate: 0 0; rotate: var(--tilt); }
    33% { translate: var(--dx) var(--dy); rotate: calc(var(--tilt) * 0.2); }
    66% { translate: calc(var(--dx) * -0.7) calc(var(--dy) * 0.5); rotate: calc(var(--tilt) * 1.5); }
  }
}

.step__n {
  display: grid;
  place-items: center;
  position: relative;
  z-index: 1;
  width: 2.3rem; height: 2.3rem;
  background: var(--white);
  color: var(--magenta);
  font-family: var(--font-display);
  font-size: var(--step--1);
}
.step__h { font-size: var(--step-2); font-weight: 700; line-height: 1.15; }
/* No opacity. White on --magenta is 4.89:1 with almost no headroom; at 0.92
   it blends to #FCEBF4 and lands on 4.26. Full strength or nothing. */
.step__b { color: var(--white); max-width: 34ch; }

.how__cta { margin-top: var(--s-5); display: flex; justify-content: center; }

/* The Unboxed eyes in miniature, popping up on the corner of the button. Hidden
   until hover or keyboard focus, so a touch screen never shows them. */
.how__cta .btn { position: relative; }
.btn-eyes {
  --eye: 1.6rem;
  position: absolute;
  left: 0.7rem;
  bottom: calc(100% - 0.45rem);
  display: flex;
  gap: 1px;
  pointer-events: none;
  opacity: 0;
  transform: translateY(35%) scale(0.3);
  transform-origin: 50% 100%;
  transition: transform var(--t-base) cubic-bezier(0.34, 1.56, 0.64, 1), opacity var(--t-fast) linear;
}
.btn-eyes .eye { border-width: 2px; box-shadow: none; }
.btn:hover .btn-eyes, .btn:focus-visible .btn-eyes { opacity: 1; transform: none; }
@media (prefers-reduced-motion: no-preference) {
  .btn:hover .btn-eyes .eye i { animation: eye-glance 2.4s ease-in-out infinite; }
  @keyframes eye-glance {
    0%, 30%, 100% { translate: 0 0; }
    45%, 60% { translate: -3px -1px; }
    75%, 90% { translate: 3px 1px; }
  }
}

/* The fractional route is green, as it is everywhere else. --mint-deep and not
   --mint so the white type stays: 5.03:1, against 1.58:1 on mint. */
.how[data-path="candidate"] .toggle__btn.is-on,
.how[data-path="candidate"] .step,
.how[data-path="candidate"] .how__cta .btn { background: var(--mint-deep); }
.how[data-path="candidate"] .step__n { color: var(--mint-deep); }
.how[data-path="candidate"] .how__cta .btn:hover { background: var(--white); color: var(--mint-deep); }

/* On desktop this is a screen of its own: it holds while the next section comes
   over it, so it clears the header and fills what is left. */
@media (min-width: 62rem) {
  .how {
    display: grid;
    align-content: center;
    min-height: 100svh;
    padding-block: calc(var(--chrome-h) + var(--s-2)) var(--s-4);
  }
  .how .section-head { margin-bottom: 0; }
  .steps { margin-top: var(--s-4); gap: var(--s-5); align-items: start; }
  .steps::before { top: 50%; }
  .step { gap: var(--s-2); padding: var(--s-4); }
  .step:nth-child(2) { margin-top: var(--s-4); }
  .step:nth-child(3) { margin-top: var(--s-2); }
  .step__n { width: 3rem; height: 3rem; font-size: var(--step-0); }
  .step__h { font-size: var(--step-3); }
  .step__b { font-size: var(--step-1); line-height: 1.4; }
  .how__cta { margin-top: var(--s-4); }
}

/* --- Pricing ------------------------------------------------------------- */
.pricing { background: var(--charcoal); color: var(--cream); padding-block: var(--s-6); }
.plans { display: grid; gap: var(--s-3); }
@media (min-width: 52rem) { .plans { grid-template-columns: repeat(2, 1fr); gap: var(--s-4); } }

.plan {
  display: grid;
  gap: var(--s-1);
  align-content: start;
  padding: var(--s-4);
  border: 1px solid var(--rule);
}
.plan--feature {
  background: color-mix(in srgb, var(--bubblegum) 12%, transparent);
  border-color: var(--bubblegum);
}
.plan__name { font-size: var(--step-1); font-weight: 700; }
.plan__price {
  font-family: var(--font-display);
  font-size: var(--step-4);
  line-height: 1;
  text-transform: uppercase;
}
.plan--feature .plan__price { color: var(--bubblegum); }
.plan__note { color: var(--cream-muted); }
.plan__lines { display: grid; gap: 0.4em; margin-block: var(--s-2); }
.plan__lines li {
  position: relative;
  padding-left: 1.3em;
  font-size: var(--step--1);
  color: var(--cream-muted);
}
.plan__lines li::before { content: '›'; position: absolute; left: 0; color: var(--mint); font-weight: 700; }
.plan .btn { justify-self: start; margin-top: var(--s-1); }
.pricing__note { margin-top: var(--s-3); color: var(--cream-muted); }

/* --- Fractional Unboxed --------------------------------------------------
   Theirs, turned up. The eyes move BEHIND the headline rather than perching
   on the section edge, and they follow the cursor. */
.unboxed {
  position: relative;
  background: var(--mint);
  color: var(--on-mint);
  padding-block: var(--s-5) var(--s-4);
  text-align: center;
  overflow: clip;
}
.unboxed__inner { position: relative; z-index: 2; display: grid; justify-items: center; gap: var(--s-1); }

.unboxed__title {
  font-family: var(--font-body);
  font-weight: 900;
  font-size: var(--mega);
  line-height: 0.86;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}
/* The deck is dealt up behind this line, and some of what ends up behind it is
   photograph — a trouser leg in a card window measured 1.00:1 against the ink.
   So the line carries its own mint ground (10.93:1) and reads as a label laid
   over the pack rather than text floating on top of a picture. */
.unboxed__sub {
  position: relative;
  z-index: 1;
  background: var(--mint);
  padding: 0.18em 0.75em 0.26em;
  border-radius: 999px;
  font-family: var(--font-serif);
  font-weight: 900;
  font-size: var(--step-2);
}

/* The box is DEALT UP INTO the type rather than parked under it: its top edge
   tucks behind the headline and the toolkit line, which is both the nicer
   composition and about 9rem shorter a section.

   The tuck is 13% of the BOX's height, derived rather than guessed: the file
   is trimmed to its own ink (tools/unboxed-box.py) at 1163x857, so the height
   is the width over 1.357. Any more than 13% and the lift starts eating the
   CLICK TO UNLOCK stamp, which sits 31% down the box face. Deriving it from
   --box-w means the tuck stays proportional when the width clamps at 94vw on
   a phone instead of 62rem. */
.unboxed__box {
  --box-w: min(62rem, 94vw);
  position: relative;
  z-index: 0;
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  width: var(--box-w);
  margin: calc(var(--box-w) / 1.357 * -0.13) 0 var(--s-2);
  color: inherit;
  text-decoration: none;
}
.unboxed__box img {
  width: 100%;
  height: auto;
  /* The box is a cutout on transparency; a soft drop shadow stops it floating
     flat on the mint. */
  filter: drop-shadow(0 26px 34px rgb(26 27 30 / 0.28));
  transform: rotate(-1.2deg);
  transition: transform var(--t-slow) var(--ease-out);
}
/* The whole box is the target, so the hover has to be on the LINK, not on the
   section — a section-wide hover tells you the wrong thing about what is
   clickable. */
.unboxed__box:hover img,
.unboxed__box:focus-visible img { transform: rotate(0deg) scale(1.012); }

/* The caption is the link's words. It keeps the button's shape so it still
   reads as the call to action, but it is not a second target. */
.unboxed__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.7em 1.4em;
  border-radius: 999px;
  background: var(--charcoal);
  color: var(--cream);
  font-weight: 800;
  font-size: var(--step-0);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  transition: transform var(--t) var(--ease-out);
}
.unboxed__box:hover .unboxed__cta { transform: translateY(-2px); }
.unboxed__box:focus-visible { outline: 3px solid var(--charcoal); outline-offset: 6px; border-radius: 1rem; }

@media (prefers-reduced-motion: reduce) {
  .unboxed__box img, .unboxed__cta { transition: none; }
}

/* --- The eyes ------------------------------------------------------------
   They sit just ABOVE the headline with only their bottom edge tucked behind
   it, and they follow the pointer.

   They are in the flow, not absolutely positioned, and the overlap is a
   fraction of --eye. The first version set the eye SIZE from viewport width
   and the offset from viewport HEIGHT, so the two scaled independently and
   the relationship was accidental: measured at 73% of the eye buried behind
   the type on desktop and 29% on mobile. Tying both to one variable makes the
   overlap identical at every size. */
:root { --eye: clamp(4.25rem, 9.5vw, 9rem); }

.eyes {
  position: relative;
  z-index: 0;
  display: flex;
  justify-content: center;
  gap: calc(var(--eye) * 0.18);
  height: var(--eye);
  /* Pull the headline up over the bottom quarter of the eyes. */
  margin-bottom: calc(var(--eye) * -0.24);
  pointer-events: none;
}
.eye {
  position: relative;
  width: var(--eye);
  height: var(--eye);
  border-radius: 50%;
  background: var(--cream);
  border: clamp(3px, 0.45vw, 6px) solid var(--charcoal);
  box-shadow: inset 0 -8px 20px rgb(26 27 30 / 0.12);
}
.eye i {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--charcoal);
  /* --px/--py are set by JS in the range -1..1; 26% is how far the pupil may
     travel before it would clip the sclera. */
  transform: translate(-50%, -50%)
             translate(calc(var(--px, 0) * 26%), calc(var(--py, 0.25) * 26%));
  transition: transform 120ms var(--ease-out);
}
.eye i::after {
  content: '';
  position: absolute;
  top: 16%; left: 20%;
  width: 26%; aspect-ratio: 1;
  border-radius: 50%;
  background: var(--cream);
  opacity: 0.85;
}

/* The title must sit over them. */
.unboxed__title { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .eye i { transition: none; }
}

/* A concept has no booking system, so the "Book a meeting" plan button is
   honestly not a link. It keeps the button's shape so the two plans still read
   as a pair, but it takes no pointer and no tab stop — better than an <a> that
   goes to "#" and silently scrolls you to the top of the page. */
.btn.is-inert {
  cursor: default;
  opacity: 0.82;
}

/* --- Insights ------------------------------------------------------------ */
.insights { background: var(--tan); color: var(--on-tan); padding-block: var(--s-6); }

.ribbon {
  display: inline-block;
  padding: 0.4em 1em;
  background: var(--magenta);
  color: var(--on-magenta);
  font-size: var(--micro-size);
  font-weight: 700;
  letter-spacing: var(--micro-track);
  text-transform: uppercase;
  transform: rotate(-3deg);
}

.insights__head { display: grid; gap: var(--s-3); margin-block: var(--s-3) var(--s-5); align-items: end; }
@media (min-width: 58rem) { .insights__head { grid-template-columns: 1fr auto; } }

.signup { display: flex; flex-wrap: wrap; gap: var(--s-1); align-items: center; }
.signup input {
  flex: 1 1 16rem;
  /* 16px minimum, or iOS Safari zooms the page on focus. */
  font-size: max(16px, var(--step-0));
  font-family: inherit;
  padding: 0.85em 1em;
  background: var(--cream);
  color: var(--charcoal);
  border: 1px solid var(--charcoal);
}
.signup__msg { flex: 1 0 100%; font-size: var(--step--1); min-height: 1.3em; }

.cards { display: grid; gap: var(--s-3); }
@media (min-width: 52rem) { .cards { grid-template-columns: repeat(3, 1fr); } }

.card { background: var(--cream); border: 1px solid var(--charcoal); }
.card__link { display: grid; gap: var(--s-1); height: 100%; padding-bottom: var(--s-3); align-content: start; }
.card__img { width: 100%; aspect-ratio: 16/10; object-fit: cover; margin-bottom: var(--s-2); }
.card__meta { padding-inline: var(--s-3); color: var(--charcoal-muted); }
.card__tag { color: var(--magenta-ink); font-weight: 700; }
.card__title { padding-inline: var(--s-3); font-size: var(--step-2); font-weight: 700; line-height: 1.15; }
.card__teaser { padding-inline: var(--s-3); font-size: var(--step--1); color: var(--charcoal-muted); }
.card:hover .card__title { text-decoration: underline; }

.insights__more { margin-top: var(--s-4); }

/* --- Close --------------------------------------------------------------- */
.close { background: var(--charcoal); color: var(--cream); padding-block: var(--s-6); }
.close__inner { display: grid; gap: var(--s-4); justify-items: center; text-align: center; }
.close__strap {
  font-family: var(--font-display);
  font-size: var(--step-5);
  line-height: 0.95;
  text-transform: uppercase;
}
.close__cta { display: flex; flex-wrap: wrap; gap: var(--s-2); justify-content: center; }

/* --- Footer -------------------------------------------------------------- */
.foot {
  position: relative;
  background: var(--charcoal);
  color: var(--cream);
  padding-block: var(--s-5);
  overflow: clip;
}

.foot__ghost {
  position: absolute;
  left: -0.04em;
  bottom: -0.12em;
  font-family: var(--font-display);
  font-size: clamp(5rem, 18vw, 16rem);
  line-height: 0.82;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--cream) 5%, transparent);
  white-space: pre-line;
  pointer-events: none;
}

.foot__grid { position: relative; z-index: 1; display: grid; gap: var(--s-4); }
@media (min-width: 56rem) {
  .foot__grid { grid-template-columns: repeat(3, auto) 1fr; gap: var(--s-5); }
}

.foot__col { display: grid; gap: 0.5em; align-content: start; }
.foot__h {
  margin-bottom: 0.3em;
  font-size: var(--micro-size);
  font-weight: 700;
  letter-spacing: var(--micro-track);
  text-transform: uppercase;
  color: var(--magenta-lift);
}
.foot__col a { font-size: var(--step--1); color: var(--cream-muted); }
.foot__col a:hover { color: var(--cream); }

.foot__sign { display: grid; gap: var(--s-2); align-content: start; }
.foot__firepower {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 0.95;
  text-transform: uppercase;
  text-shadow: 0 0 18px color-mix(in srgb, var(--bubblegum) 60%, transparent);
}
.foot__legal { color: var(--cream-muted); line-height: 1.7; }

/* --- Theatre ------------------------------------------------------------- */

/* --- Before you start ----------------------------------------------------
   The app opens on a password wall with five complexity rules and nothing
   behind it visible. This section is the only place a visitor can find out
   what they are committing to before they commit. */
.start { position: relative; background: var(--cream); color: var(--charcoal); padding-block: var(--s-6); }
.start > .wrap { position: relative; }
/* Pink is hiring and green is fractional, as everywhere else. No viewBox, so
   the drips stay round at every width. app.js keeps them off the text. */
.start__paint { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.start__paint [data-c="company"] { fill: var(--magenta); }
.start__paint [data-c="candidate"] { fill: var(--mint); }
.start .eyebrow--mint { margin-bottom: var(--s-1); }

.toggle--start { margin-bottom: var(--s-4); }

.start__panel { display: grid; gap: var(--s-4); }
@media (min-width: 62rem) {
  .start__panel { grid-template-columns: 1.4fr 1fr; gap: var(--s-5); align-items: start; }
}

.start__steps { display: grid; gap: var(--s-3); }
.start__step {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2);
  align-items: start;
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--rule-dark);
}
.start__step:last-child { border-bottom: 0; padding-bottom: 0; }

.start__n {
  display: grid;
  place-items: center;
  width: 2.2rem; height: 2.2rem;
  border-radius: 50%;
  background: var(--charcoal);
  color: var(--cream);
  font-family: var(--font-display);
  font-size: var(--step--1);
}
.start__h { font-size: var(--step-1); font-weight: 700; line-height: 1.2; }
.start__b { color: var(--charcoal-muted); max-width: 46ch; }

.start__aside {
  display: grid;
  gap: var(--s-2);
  justify-items: start;
  padding: var(--s-3);
  background: var(--charcoal);
  color: var(--cream);
}
/* One wavy shape, not a box with a line round it. A border-image with `fill`, so
   the wave is the edge of the colour itself and `round` fits a whole number of
   waves to any size. It has its own colours because an image cannot read a
   token: --magenta for hiring, --mint-deep for fractional. Everything inside is
   white, which is 4.89:1 and 5.03:1 on those, and mint would not be. */
.start__aside {
  border: 24px solid transparent;
  border-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='72'%3E%3Cpath d='M24 12c4-5 8-5 12 0s8 5 12 0Q60 12 60 24c5 4 5 8 0 12s-5 8 0 12Q60 60 48 60c-4 5-8 5-12 0s-8-5-12 0Q12 60 12 48c-5-4-5-8 0-12s5-8 0-12Q12 12 24 12Z' fill='%23FF87FF'/%3E%3C/svg%3E") 24 fill round;
  background: none;
  color: var(--white);
  padding: var(--s-2);
  --route: var(--magenta);
  /* rotate, not transform, which reveals() is using. drop-shadow, not box-shadow,
     so the shadow follows the wave instead of a rectangle. */
  rotate: 2deg;
  filter: drop-shadow(0 1.1rem 1.4rem rgb(0 0 0 / 0.3));
}
/* One bounce per hover, in translate because rotate and transform are taken. The
   ::before holds the hover while it jumps: without it the box leaves a pointer
   resting on its bottom edge, drops back, and bounces for ever. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .start__aside:hover { animation: aside-bounce 800ms ease-out; }
  .start__aside:hover::before { content: ''; position: absolute; inset: -1.5rem -1.5rem -3rem; z-index: -1; }
  @keyframes aside-bounce {
    0%, 100% { translate: 0 0; }
    22% { translate: 0 -18px; }
    45% { translate: 0 0; }
    62% { translate: 0 -8px; }
    78% { translate: 0 0; }
    89% { translate: 0 -3px; }
  }
}
/* Up into the empty space beside the toggle. On one column there is nothing
   beside it, only the step above. */
@media (min-width: 62rem) { .start__aside { margin-top: -6rem; } }
.start__aside--candidate {
  border-image-source: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='72'%3E%3Cpath d='M24 12c4-5 8-5 12 0s8 5 12 0Q60 12 60 24c5 4 5 8 0 12s-5 8 0 12Q60 60 48 60c-4 5-8 5-12 0s-8-5-12 0Q12 60 12 48c-5-4-5-8 0-12s5-8 0-12Q12 12 24 12Z' fill='%231A7F49'/%3E%3C/svg%3E");
  --route: var(--mint-deep);
}
.start__aside .btn { background: var(--white); color: var(--route); }
.start__aside .btn:hover { background: var(--charcoal); color: var(--white); }
.start__kicker { color: var(--white); }
.start__ready { display: grid; gap: 0.45em; width: 100%; }
.start__ready li {
  position: relative;
  padding-left: 1.4em;
  font-size: var(--step-0);
}
.start__ready li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.55em;
  width: 0.7em; height: 0.35em;
  border-left: 2px solid var(--white);
  border-bottom: 2px solid var(--white);
  transform: rotate(-45deg);
}
.start__meta { color: var(--white); padding-top: var(--s-1); border-top: 1px solid rgb(255 255 255 / 0.4); width: 100%; }
/* Sentence case, not the tracked micro style — this is a sentence a human
   reads, not a stamp, and uppercase+0.15em tracking broke it over three
   ragged lines. */
.start__sso {
  color: var(--white);
  max-width: 34ch;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  line-height: 1.5;
}

/* ==========================================================================
   Inner pages
   ========================================================================== */
.page-hero {
  position: relative;
  display: grid;
  align-content: end;
  min-height: min(72svh, 40rem);
  padding-top: var(--chrome-h);
  background: var(--charcoal);
  color: var(--cream);
  overflow: clip;
}
/* The masthead grows to 118px at the canvas breakpoint (Rich draws the lockup
   at 18.26% of the page width), so everything that clears it has to grow too. */
@media (min-width: 62rem) { .page-hero { padding-top: var(--chrome-h); } }
.page-hero--flat { min-height: min(52svh, 28rem); }

.page-hero__media { position: absolute; inset: 0; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; }
.page-hero__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top, var(--charcoal) 4%, rgb(26 27 30 / 0.8) 30%,
                              rgb(26 27 30 / 0.3) 70%, rgb(26 27 30 / 0.5) 100%);
}
.page-hero__inner { position: relative; z-index: 2; padding-block: var(--s-6) var(--s-5); }
.page-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 1.4rem + 5vw, 5.5rem);
  line-height: 0.88;
  text-transform: uppercase;
  margin: var(--s-3) 0;
}
.page-hero__lede { max-width: 46ch; font-size: var(--step-1); line-height: 1.45; margin-bottom: var(--s-4); }

/* --- Situations ---------------------------------------------------------- */
.situations { background: var(--cream); color: var(--charcoal); padding-block: var(--s-6); }
.sit-list { display: grid; gap: 0; border-top: 1px solid var(--rule-dark); }
.sit {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2) var(--s-3);
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--rule-dark);
  transition: background-color var(--t-fast) linear;
}
.sit:hover { background: color-mix(in srgb, var(--magenta) 6%, transparent); }
.sit__n { grid-row: span 2; color: var(--magenta-ink); padding-top: 0.35em; }
.sit__q { font-family: var(--font-serif); font-weight: 900; font-size: var(--step-2); line-height: 1.15; }
.sit__a { grid-column: 2; color: var(--charcoal-muted); max-width: 62ch; }

/* --- Claims: the assertion, then the mechanism ---------------------------- */
.claims { background: var(--charcoal); color: var(--cream); padding-block: var(--s-6); }
.claims--mint { background: var(--mint); color: var(--on-mint); }

.claim-grid { display: grid; gap: var(--s-3); }
@media (min-width: 56rem) { .claim-grid { grid-template-columns: repeat(3, 1fr); gap: var(--s-4); } }

.claim {
  display: grid;
  gap: var(--s-2);
  align-content: start;
  padding-top: var(--s-2);
  border-top: 3px solid currentColor;
}
.claim__h { font-size: var(--step-2); font-weight: 700; line-height: 1.15; }
.claim__b { font-size: var(--step-0); }
.claim__how {
  font-size: var(--step--1);
  padding-top: var(--s-2);
  border-top: 1px solid currentColor;
  opacity: 1;
}
.claims .claim__how { color: var(--cream-muted); border-top-color: var(--rule); }
.claims--mint .claim__how { color: var(--charcoal); border-top-color: var(--rule-dark); }
.claim__kicker { color: var(--mint); margin-right: 0.4em; }
.claims--mint .claim__kicker { color: var(--charcoal); }   /* 10.93:1 — --magenta-ink is 3.73 on mint */

/* --- FAQ ----------------------------------------------------------------- */
.faq { background: var(--cream); color: var(--charcoal); padding-block: var(--s-6); }
.faq__list { border-top: 1px solid var(--rule-dark); }
.faq__item { border-bottom: 1px solid var(--rule-dark); }
.faq__q {
  display: flex;
  justify-content: space-between;
  gap: var(--s-2);
  padding-block: var(--s-3);
  font-size: var(--step-1);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after { content: '+'; font-family: var(--font-display); font-size: var(--step-2); line-height: 1; }
.faq__item[open] .faq__q::after { content: '–'; }
.faq__a { padding-bottom: var(--s-3); max-width: 62ch; color: var(--charcoal-muted); }
.faq__flag {
  margin-top: var(--s-2);
  padding: var(--s-2);
  background: color-mix(in srgb, var(--magenta) 10%, transparent);
  border-left: 3px solid var(--magenta-ink);
  color: var(--charcoal);
  text-transform: none;
  letter-spacing: normal;
  line-height: 1.5;
}

.pricing--page { padding-top: var(--s-5); }

/* --- Ghost button on dark ------------------------------------------------ */
.btn--ghost { border-color: currentColor; color: inherit; }
.btn--ghost:hover { background: var(--cream); color: var(--charcoal); border-color: var(--cream); }

/* ==========================================================================
   Craft layer — the things that make it feel made rather than assembled
   ========================================================================== */

/* Film grain over the charcoal grounds. The campaign is shot on 70s stock and
   flat digital black next to it looks synthetic. Very low opacity, and it is a
   single inline SVG so it costs no request. */
.hero::after,
.page-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0.16;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* Sections rise as they enter. Staggered by child so a row of cards deals in
   rather than appearing all at once. */
@media (prefers-reduced-motion: no-preference) {
  .reveal > * {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-out);
    transition-delay: calc(var(--i, 0) * 70ms);
  }
  .reveal.is-in > * { opacity: 1; transform: none; }
}

/* Every interactive surface answers. */
.btn, .card, .claim, .plan, .sit, .step { will-change: transform; }
.card { transition: transform var(--t-base) var(--ease-out), box-shadow var(--t-base) var(--ease-out); }
.card:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -20px rgb(0 0 0 / 0.55); }
.plan { transition: transform var(--t-base) var(--ease-out), border-color var(--t-fast) linear; }
.plan:hover { transform: translateY(-3px); border-color: var(--mint); }

/* ==========================================================================
   CV drop
   ========================================================================== */
.cv { display: grid; gap: var(--s-2); }

.cv__zone {
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  padding: var(--s-5) var(--s-3);
  text-align: center;
  cursor: pointer;
  border: 2px dashed color-mix(in srgb, var(--cream) 30%, transparent);
  background: color-mix(in srgb, var(--cream) 4%, transparent);
  transition: border-color var(--t-fast) linear, background-color var(--t-fast) linear,
              transform var(--t-fast) var(--ease-out);
}
.cv__zone:hover { border-color: var(--mint); background: color-mix(in srgb, var(--mint) 8%, transparent); }
.cv[data-drag="on"] .cv__zone { border-color: var(--mint); background: color-mix(in srgb, var(--mint) 14%, transparent); transform: scale(1.01); }
.cv[data-state="working"] .cv__zone,
.cv[data-state="done"] .cv__zone,
.cv[data-state="accepted"] .cv__zone { display: none; }

.cv__icon {
  width: 2.6rem; height: 2.6rem;
  border: 2px solid currentColor;
  border-radius: 50%;
  position: relative;
  margin-bottom: 0.3rem;
}
.cv__icon::before,
.cv__icon::after { content: ''; position: absolute; background: currentColor; }
.cv__icon::before { width: 2px; height: 1.1rem; left: calc(50% - 1px); top: 0.55rem; }
.cv__icon::after { width: 0.7rem; height: 0.7rem; border-left: 2px solid currentColor; border-top: 2px solid currentColor; background: none; left: calc(50% - 0.35rem); top: 0.62rem; transform: rotate(45deg); }

.cv__lead { font-size: var(--step-1); font-weight: 700; }
.cv__sub { color: var(--cream-muted); }
.cv__privacy { color: var(--mint); }

.cv__working { display: grid; gap: 0.5rem; }
.cv__filename { font-weight: 600; }
.cv__bar { height: 4px; background: color-mix(in srgb, var(--cream) 16%, transparent); overflow: hidden; }
.cv__fill { display: block; height: 100%; width: 0; background: var(--mint); transition: width 260ms var(--ease-out); }
.cv__status { color: var(--cream-muted); }

.cv__result { display: grid; gap: var(--s-2); }
.cv__ok { color: var(--mint); }
.cv__found { display: grid; gap: var(--s-2); }

.cv__row { display: grid; gap: 0.4rem; }
@media (min-width: 40rem) { .cv__row { grid-template-columns: 9rem 1fr; align-items: baseline; } }
.cv__label { color: var(--cream-muted); }

/* The chips had no gap and ran together as one unreadable string. */
.cv__chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.chip {
  display: inline-block;
  padding: 0.3em 0.7em;
  font-size: var(--step--1);
  background: color-mix(in srgb, var(--cream) 10%, transparent);
  border: 1px solid var(--rule);
}
.chip--quiet { color: var(--cream-muted); }
.chip--yes { border-color: var(--mint); color: var(--mint); }
.chip--no  { color: var(--cream-muted); border-style: dashed; }

.cv__note { font-size: var(--step--1); color: var(--cream-muted); max-width: 56ch; }
.cv__error {
  padding: var(--s-2);
  border-left: 3px solid var(--magenta-lift);
  background: color-mix(in srgb, var(--magenta) 14%, transparent);
  font-size: var(--step--1);
}

/* ==========================================================================
   The sign-up flow
   ========================================================================== */
.joinpage { background: var(--charcoal); color: var(--cream); padding-block: calc(var(--chrome-h) + var(--s-5)) var(--s-5); }

.join { display: grid; gap: var(--s-5); align-items: start; }
@media (min-width: 64rem) { .join { grid-template-columns: 1fr 22rem; gap: var(--s-6); } }

.join__main { max-width: 42rem; }
@media (prefers-reduced-motion: no-preference) {
  .join__main { opacity: 0; transform: translateY(12px); transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out); }
  .join__main.is-in { opacity: 1; transform: none; }
}

.join__progress { display: flex; gap: 4px; margin-bottom: var(--s-3); }
.join__tick { flex: 1; height: 3px; background: color-mix(in srgb, var(--cream) 16%, transparent); }
.join__tick.is-done { background: var(--mint); }

.join__kicker { color: var(--mint); }
.join__q {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.2rem + 3.4vw, 4rem);
  line-height: 0.96;
  text-transform: uppercase;
  margin: var(--s-2) 0 var(--s-2);
}
.join__sub { color: var(--cream-muted); max-width: 52ch; margin-bottom: var(--s-4); }
.join__body { display: grid; gap: var(--s-3); }
.join__nav { display: flex; gap: var(--s-2); margin-top: var(--s-5); }
.join__nav .btn[disabled] { opacity: 0.4; pointer-events: none; }

/* --- Tiles --------------------------------------------------------------- */
.tiles { display: grid; gap: var(--s-2); }
.tiles[data-cols="1"] { grid-template-columns: 1fr; }
@media (min-width: 34rem) {
  .tiles[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
  .tiles[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
  .tiles[data-cols="4"] { grid-template-columns: repeat(4, 1fr); }
}
.tile {
  display: grid; gap: 0.25rem; align-content: start;
  min-height: 6.5rem;
  padding: var(--s-3);
  text-align: left;
  border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--cream) 4%, transparent);
  transition: border-color var(--t-fast) linear, background-color var(--t-fast) linear, transform var(--t-fast) var(--ease-out);
}
.tile:hover { border-color: var(--cream); transform: translateY(-2px); }
.tile.is-on { border-color: var(--mint); background: color-mix(in srgb, var(--mint) 14%, transparent); }
.tile__label { font-weight: 700; font-size: var(--step-1); text-wrap: balance; }
.tile__sub { color: var(--cream-muted); text-wrap: pretty; }

/* --- Segmented ----------------------------------------------------------- */
.seg { display: flex; flex-wrap: wrap; gap: 4px; }
.seg__btn {
  padding: 0.6em 1em;
  font-size: var(--step--1);
  font-weight: 600;
  border: 1px solid var(--rule);
  transition: border-color var(--t-fast) linear, background-color var(--t-fast) linear;
}
.seg__btn:hover { border-color: var(--cream); }
.seg__btn.is-on { background: var(--mint); color: var(--on-mint); border-color: var(--mint); }

/* --- Fields -------------------------------------------------------------- */
.field { display: grid; gap: 0.5rem; }
.field__label { font-size: var(--step--1); font-weight: 600; color: var(--cream); }
.field__hint { color: var(--cream-muted); text-transform: none; letter-spacing: normal; line-height: 1.5; max-width: 52ch; }

.input {
  font: inherit;
  /* 16px floor or iOS Safari zooms the page on focus. */
  font-size: max(16px, var(--step-0));
  padding: 0.75em 0.9em;
  color: var(--cream);
  background: color-mix(in srgb, var(--cream) 6%, transparent);
  border: 1px solid var(--rule);
  width: 100%;
}
.input:focus { border-color: var(--mint); outline: none; }
.input-money { display: flex; align-items: center; gap: 0.5rem; }
.input-money > span { font-size: var(--step-2); color: var(--cream-muted); }

.checks { display: flex; flex-wrap: wrap; gap: var(--s-1); }
.check {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.55em 0.9em;
  border: 1px solid var(--rule);
  font-size: var(--step--1);
  cursor: pointer;
}
.check.is-on { border-color: var(--mint); background: color-mix(in srgb, var(--mint) 12%, transparent); }
.check input { accent-color: var(--mint); }

/* --- Days dots ------------------------------------------------------------ */
.dots { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.dot {
  width: 1.15rem; height: 1.15rem;
  border-radius: 50%;
  border: 1px solid var(--rule);
  transition: background-color 120ms linear, border-color 120ms linear, transform 120ms var(--ease-out);
}
.dot:hover { transform: scale(1.18); border-color: var(--cream); }
.dot.is-on { background: var(--mint); border-color: var(--mint); }
.dots__read { flex: 1 0 100%; font-size: var(--step--1); color: var(--cream-muted); }

.aside {
  padding: var(--s-2) var(--s-3);
  border-left: 3px solid var(--mint);
  background: color-mix(in srgb, var(--mint) 8%, transparent);
  font-size: var(--step--1);
  line-height: 1.6;
  max-width: 56ch;
}
.vat-hint { color: var(--cream-muted); }
.vat-hint b { color: var(--mint); }

.linkish {
  justify-self: start;
  font-size: var(--step--1);
  color: var(--cream-muted);
  border-bottom: 1px solid currentColor;
}
.linkish:hover { color: var(--cream); }

.done { display: grid; gap: var(--s-3); }
.done__note {
  padding: var(--s-3);
  border: 1px dashed var(--rule);
  color: var(--cream-muted);
  font-size: var(--step--1);
  line-height: 1.6;
}
.done__cta { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* --- The card that builds as you go ---------------------------------------
   Built like something printed, not like a div: a keyline inset from the
   trim, a foil spine, registration crop marks, and paper grain over the face.
   That construction is why it reads as an object rather than a panel. */
.join__card { position: sticky; top: calc(var(--chrome-h) + var(--s-3)); }

.tcard {
  position: relative;
  /* The real card is 1276 x 1809 — 0.706. But `aspect-ratio` FIXES the
     height from the width, so once every stat carries an evidence line the
     content spills out of the box instead of growing it, and on this dark
     ground charcoal text outside the pink is simply invisible. `overflow`
     does not help either way: hidden clips it, visible loses it.
     A min-height gives the same proportion at the column's 22rem width and
     still lets the card grow. (`min-height: calc(100cqw / .706)` does NOT
     work — an element cannot be its own container-query container, so cqw
     resolves against the viewport and produces a 2000px card.) */
  min-height: 31rem;
  background: var(--bubblegum);
  color: var(--charcoal);
  border-radius: 14px;
  padding: var(--s-3) var(--s-3) var(--s-3) 2rem;
  box-shadow: 0 24px 40px -18px rgb(0 0 0 / 0.55);
  transform: rotate(-1.5deg);
  transition: transform var(--t-slow) var(--ease-out), filter var(--t-slow) linear;
  filter: saturate(0.3);
  overflow: visible;
  isolation: isolate;
}
.tcard--role { background: var(--mint); }
.tcard.is-live { filter: none; transform: rotate(0deg); }

/* Keyline, inset from the trim the way a printed card is. */
.tcard::before {
  content: '';
  position: absolute;
  inset: 6px;
  border: 3px solid color-mix(in srgb, var(--cream) 70%, transparent);
  border-radius: 9px;
  pointer-events: none;
  z-index: 2;
}
/* Paper grain over the face. */
.tcard::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0.09;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* Registration crop marks. */
.tcard__crop {
  position: absolute;
  width: 10px; height: 10px;
  z-index: 2;
  border-color: color-mix(in srgb, var(--charcoal) 40%, transparent);
  border-style: solid;
  border-width: 0;
}
.tcard__crop--tl { top: 10px; left: 10px; border-top-width: 1px; border-left-width: 1px; }
.tcard__crop--tr { top: 10px; right: 10px; border-top-width: 1px; border-right-width: 1px; }
.tcard__crop--bl { bottom: 10px; left: 10px; border-bottom-width: 1px; border-left-width: 1px; }
.tcard__crop--br { bottom: 10px; right: 10px; border-bottom-width: 1px; border-right-width: 1px; }

.tcard__spine {
  position: absolute;
  left: 0.55rem; bottom: var(--s-3);
  z-index: 2;
  transform-origin: left bottom;
  transform: rotate(-90deg);
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.7;
}

.tcard__inner { position: relative; z-index: 1; display: grid; gap: 0.35rem; align-content: start; height: 100%; }

/* Anton carries numbers and the name. It never sets a sentence. */
.tcard__name { font-family: var(--font-display); font-size: var(--step-3); line-height: 1; text-transform: uppercase; }
.tcard__sub { opacity: 0.8; }

.tcard__window {
  display: grid; place-items: center;
  border: 2px solid var(--charcoal);
  border-radius: 8px;
  min-height: 4.6rem;
  margin-block: 0.3rem;
  background: color-mix(in srgb, var(--charcoal) 12%, transparent);
  text-align: center;
  padding: var(--s-1);
}
.tcard__initials { font-family: var(--font-display); font-size: var(--step-4); line-height: 1; }
.tcard__empty { opacity: 0.65; }

.tcard__stats { display: grid; gap: 0.3rem; }
.tcard__stats li {
  display: grid;
  grid-template-columns: 1fr 3.2rem auto;
  grid-template-areas: 'axis bar val' 'because because because';
  gap: 0.1rem 0.4rem;
  align-items: center;
}
.tcard__axis { grid-area: axis; font-size: var(--step--1); }
.tcard__bar {
  grid-area: bar;
  height: 4px;
  background: color-mix(in srgb, var(--charcoal) 22%, transparent);
}
.tcard__bar i {
  display: block;
  height: 100%;
  width: calc(var(--v) * 10%);
  background: var(--charcoal);
  transition: width var(--t-slow) var(--ease-out);
}
.tcard__stats b { grid-area: val; font-family: var(--font-display); font-size: var(--step-0); }
.tcard__because {
  grid-area: because;
  font-size: 0.56rem;
  letter-spacing: 0.06em;
  opacity: 0.68;
  text-transform: none;
  line-height: 1.35;
}

.tcard__positional {
  margin-top: 0.4rem;
  padding-top: 0.4rem;
  border-top: 1px solid color-mix(in srgb, var(--charcoal) 28%, transparent);
  font-size: 0.58rem;
  letter-spacing: 0.04em;
  text-transform: none;
  line-height: 1.4;
  opacity: 0.8;
}

@media (max-width: 64rem) {
  .join__card { position: static; max-width: 22rem; }
}

/* --- The dealt shortlist -------------------------------------------------- */
.deal { display: grid; gap: var(--s-2); }
@media (min-width: 46rem) { .deal { grid-template-columns: repeat(3, 1fr); } }

.mini {
  display: grid;
  gap: 0.4rem;
  align-content: start;
  padding: var(--s-2);
  background: var(--bubblegum);
  color: var(--charcoal);
  border-radius: 10px;
  box-shadow: 0 14px 26px -14px rgb(0 0 0 / 0.55);
}
@media (prefers-reduced-motion: no-preference) {
  .mini { animation: deal 520ms var(--ease-out) backwards; animation-delay: calc(var(--d) * 110ms); }
  @keyframes deal {
    from { opacity: 0; transform: translateY(26px) rotate(-3deg) scale(0.97); }
    to   { opacity: 1; transform: none; }
  }
}
.mini:nth-child(2) { background: var(--mint); }

.mini__ref { opacity: 0.7; }
.mini__name { font-family: var(--font-display); font-size: var(--step-2); line-height: 1; text-transform: uppercase; }
.mini__stats { display: grid; gap: 0.2rem; margin-top: 0.2rem; }
.mini__stats li { display: grid; grid-template-columns: 1fr 2.4rem auto; gap: 0.4rem; align-items: center; font-size: 0.68rem; }
.mini__bar { height: 3px; background: color-mix(in srgb, var(--charcoal) 22%, transparent); }
.mini__bar i { display: block; height: 100%; width: calc(var(--v) * 10%); background: var(--charcoal); }
.mini__stats b { font-family: var(--font-display); font-size: 0.85rem; }
.mini__ev { display: grid; gap: 0.1rem; margin-top: 0.3rem; padding-top: 0.35rem; border-top: 1px solid color-mix(in srgb, var(--charcoal) 26%, transparent); }
.mini__ev li { font-size: 0.62rem; opacity: 0.85; }
.mini__terms { margin-top: 0.3rem; font-weight: 700; }
.deal__note { color: var(--cream-muted); text-transform: none; letter-spacing: normal; margin-top: var(--s-2); }

/* ==========================================================================
   Rich's design — the top of the site
   ========================================================================== */

/* --- Masthead: logo, two links, hamburger -------------------------------- */
.masthead__link {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--chrome-accent-live, var(--bubblegum));
  transition: color 260ms linear;
}
.masthead__link:hover { color: var(--chrome-fg, var(--cream)); }
.masthead__pair { display: flex; align-items: center; gap: 0.5rem; margin-right: var(--s-2); }

/* The two routes are boxes, not links, so they carry their own ground and stay
   legible on every band the header wears — including the film, where nothing
   else in the masthead can be taken for granted.
   White on --mint-deep is 5.03:1 and on --magenta 4.89:1; mint itself is
   1.58:1 with white and could never have been used flat. */
.masthead__tag {
  display: inline-flex;
  align-items: center;
  padding: 0.52em 0.95em;
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.06em;
  /* Tracking opens the gaps BETWEEN letters but leaves the word space alone,
     so "I'M A FRACTIONAL" closed up into "I'M AFRACTIONAL". Give the space
     back twice what each letter took. */
  word-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
  transition: filter var(--t-fast) linear;
}
/* Pink is hiring and green is fractional — that is the client's convention on
   thefractionals.ai, sampled off their live header: I'm Hiring rgb(255,64,180),
   I'm Fractional rgb(118,227,169). Ours had them the other way round, which
   also put the masthead at odds with the body buttons on our own pages.
   White on --magenta is 4.89:1 and on --mint-deep 5.03:1, so the swap costs
   nothing. */
.masthead__tag--hiring { background: var(--magenta); }
.masthead__tag--fractional { background: var(--mint-deep); }
.masthead__tag:hover { filter: brightness(1.14); }
/* One burst per hover, not a loop: a button that keeps moving is hard to click
   and starts to look like an error. hover: hover keeps it off touch screens,
   where a tap would leave it stuck in :hover. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .masthead__tag:hover { animation: tag-shake 450ms ease-in-out; }
  @keyframes tag-shake {
    20% { transform: translateX(-2px) rotate(-3deg); }
    40% { transform: translateX(2px) rotate(3deg); }
    60% { transform: translateX(-2px) rotate(-2deg); }
    80% { transform: translateX(1px) rotate(1deg); }
  }
}

/* Icon-only sign in. 2.75rem keeps the tap target at 44px even though the
   glyph is 22px, and it follows the band colour like everything else up here. */
.masthead__signin {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  color: var(--chrome-accent-live, var(--bubblegum));
  transition: color 260ms linear, background-color var(--t-fast) linear;
}
.masthead__signin svg { display: block; }
.masthead__signin:hover {
  color: var(--chrome-fg, var(--cream));
  background: color-mix(in srgb, currentColor 14%, transparent);
}
/* Below this the pills cannot fit beside the lockup — measured, 94px of free
   space at 390 and 27px at 320 against ~300px of pills — so they used to be
   hidden outright. That left the unlabelled sign-in icon as the ONLY visible
   header control on a phone, which is why both routes felt like they led to a
   sign-in page: on mobile the only obvious thing to press WAS sign in.

   They get their own strip under the header instead: full width, split in two,
   each half carrying its own opaque ground. Opaque by construction means the
   header's colour-blending never has to account for a second band, and nothing
   can scroll through it. z-index sits BELOW .menu (55) so opening the burger
   covers it, and below .masthead (60) so the burger stays reachable. */
@media (max-width: 44rem) {
  .masthead__pair {
    position: fixed;
    top: var(--hdr-h);
    left: 0;
    right: 0;
    z-index: 54;
    display: flex;
    gap: 0;
    margin-right: 0;
    height: var(--rolebar-h);
  }
  .masthead__tag {
    flex: 1 1 50%;
    display: grid;
    place-items: center;
    height: 100%;
    padding: 0;
    border-radius: 0;
  }
}

.burger {
  display: grid;
  gap: 5px;
  width: 2.4rem;
  padding: 0.4rem 0;
}
.burger span {
  display: block;
  height: 2px;
  background: var(--chrome-accent-live, var(--bubblegum));
  transition: background-color 260ms linear,
              transform var(--t-base) var(--ease-out),
              opacity var(--t-fast) linear;
}
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: 0;
  z-index: 55;
  display: grid;
  justify-items: center;
  /* Clear of the header, which stays on top. Auto margins rather than
     align-items: center, which puts the top of an overflowing list out of
     reach of the scroll. */
  padding-top: var(--chrome-h);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: color-mix(in srgb, var(--charcoal) 97%, transparent);
  backdrop-filter: blur(6px);
}
.menu__inner { display: grid; gap: var(--s-2); text-align: center; padding: var(--s-2) var(--s-4); margin-block: auto; }
.menu__inner a {
  font-family: var(--font-display);
  /* Capped by height as well: a laptop is wide and short, so on width alone the
     list ran off both ends of the screen. */
  font-size: clamp(1.6rem, min(1rem + 2.6vw, 5.2svh), 3rem);
  line-height: 1;
  text-transform: uppercase;
  color: var(--cream);
  transition: color var(--t-fast) linear;
}
.menu__inner a:hover { color: var(--bubblegum); }
.menu__rule { height: 1px; background: var(--rule); margin-block: var(--s-2); }
.menu__cta { color: var(--bubblegum) !important; }
.menu__cta:hover { color: var(--cream) !important; }
:root.is-menu-open { overflow: hidden; }

/* ==========================================================================
   RICH'S PAGE, TO THE MILLIMETRE
   --------------------------------------------------------------------------
   TheFractionals-web-s3.pdf is one InDesign page, 958.16 x 2620 pt. Every
   number below was measured off a 100dpi render of it — ink bounding boxes of
   the actual letterforms, not eyeballed — and expressed as a percentage of
   that same canvas width. So `10.62cqw` is not a guess that looked right: it
   is the cap height Rich drew, divided by his page width.

   HOW IT WORKS
     .rcanvas is a container (container-type: inline-size), so 1cqw == 1% of
     Rich's page width. Vertical positions are ALSO in cqw, because his page is
     one fixed proportion — using cqh or vh would let the composition drift the
     moment the window changes shape.

   THE FACE
     His display face is unknown (still on the ask-Rich list). Archivo's width
     axis was fitted to his letterforms by least squares over nine measured
     words — FIREPOWER, /ON, DEMAND, KNOW, DIFFERENCE, SEARCH FOR, YOUR, NOW,
     FRACTIONAL — comparing ink-width / cap-height. Best fit: wdth 90, tracking
     +0.02em, RMS error 4.5%. FIREPOWER lands within 0.2%.
     Note the tracking is POSITIVE: the earlier -0.035em was set by eye and was
     wrong, which is why every long line came out short.

   Below 62rem none of this applies — a fixed canvas cannot survive a phone —
   and each section falls back to a plain stacked layout further down.
   ========================================================================== */
.rcanvas {
  position: relative;
  width: min(100%, var(--canvas));
  margin-inline: auto;
  container-type: inline-size;
}
/* Below the canvas breakpoint the sections are ordinary stacked blocks, so
   they need the page gutter back or the display type runs off the edge. */
@media (max-width: 61.99rem) {
  .rcanvas { padding-inline: var(--gutter); }
  .rdiff__canvas { padding-inline: 0; }
  .rdiff__title { padding-inline: var(--gutter); }
}

/* --- Hero ---------------------------------------------------------------- */
.rhero {
  position: relative;
  display: grid;
  align-content: center;
  min-height: min(100svh, 58rem);
  background: var(--charcoal);
  overflow: clip;
}
.rhero__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 58%; }
/* The film sits over the still and fades in only once it is genuinely playing
   — not on a timer — so a refused autoplay leaves Rich's frame in place
   rather than a black rectangle. */
.rhero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 50%;
  opacity: 0;
  transition: opacity 700ms linear;
  pointer-events: none;
}
.rhero.is-playing .rhero__video { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .rhero__video { display: none; } }

.rhero__title {
  margin: 0;
  font-family: var(--font-poster);
  font-weight: 900;
  font-stretch: 90%;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  /* Rich's page has this in bubblegum #FF87FF, sampled off the render. Hot pink
     is a deliberate change from that, made so it stands out on the moving film,
     where his still-photo colour lost to the bright shots. */
  color: var(--hot-pink);
  text-align: right;
}
.rhero__l { display: block; }

/* THE SLASH IS A DRAWN SHAPE, NOT THE FONT'S GLYPH.
   Measured off Rich's page as a connected component: box 4.884% x 7.363% of
   the page width, 21.9 degrees from vertical, 1.878% horizontal stroke, its
   bottom sitting 1.2pt above the baseline and its top 1% proud of the cap
   height. Archivo's own "/" is thinner and shallower, which is exactly why it
   disappeared into the letterforms next to it — it reads as punctuation where
   his reads as a device.

   Everything is in em so the one rule serves the hero, the mobile hero and
   KNOW /THE DIFFERENCE at whatever size each is set. Archivo's cap is 0.686em,
   so: height 70.55/101.75 em, width 46.79/101.75 em, and the top edge starts
   60.5% across the box. */
.slash {
  display: inline-block;
  width: 0.460em;
  height: 0.693em;
  margin-right: 0.042em;
  position: relative;
  bottom: 0.012em;
  background: currentColor;
  clip-path: polygon(60.5% 0, 100% 0, 39.5% 100%, 0 100%);
}

@media (min-width: 62rem) {
  /* 555pt of 958.16 = 57.93% — the frame is a fixed proportion, as drawn —
     but the SECTION fills the viewport so the film is seen full screen with
     no pink band peeking under the fold. The canvas is top-aligned, so the
     headline keeps the exact distance from the top of the frame that Rich
     drew; any extra height goes to the floor of the photograph. */
  /* Bottom-aligned, not top. Rich's frame is 1.727:1 and the section fills the
     viewport, so on any screen taller than that there is slack to place. Top-
     aligning put all of it UNDER the headline — 161px of empty floor at
     1440x900 — which read as the type floating high. Aligning the canvas to
     the bottom keeps the headline exactly 7.03cqw off the foot of the screen,
     which is the 67.4pt Rich drew below DEMAND, and gives the extra height to
     the film above it instead. It also fails better on a short viewport: the
     overflow now clips the top of the frame rather than the headline. Pinning
     max-height as well as min-height makes that symmetrical — taller than the
     frame gives the slack to the film above, shorter clips the film above —
     so the headline keeps the same 94px off the foot of the screen at every
     height. Do NOT express this as a max-height on the CANVAS: aspect-ratio
     resolves in both directions, so constraining its block size shrinks its
     inline size and every cqw offset in it with it. */
  .rhero { min-height: 100svh; max-height: 100svh; align-content: end; }
  /* The canvas keeps Rich's frame EXACTLY — 1.727:1, nothing else — because
     every type offset in it is a percentage of that frame's width.
     Do not put a min-height on this. `aspect-ratio` resolves in both
     directions, so forcing the block size inflates the INLINE size to match:
     min-height:100svh on a 900px viewport made the canvas 1554px wide inside
     a 1440px window and pushed the headline 114px off the right edge.
     The section is what fills the screen instead — the film and the still are
     both absolutely positioned against the SECTION, not the canvas, so they
     already cover whatever height it takes. */
  .rhero__canvas { aspect-ratio: 958.16 / 555; }
  .rhero__title {
    position: absolute;
    /* cap top 199.7pt = 20.84cqw, less the 0.17cqw from line box to cap. */
    top: 20.82cqw;
    right: 3.43cqw;
    /* cap height 69.8pt = 7.285cqw; Archivo's cap is 0.686em. */
    font-size: 10.62cqw;
    /* 74.9pt between the cap tops of /ON and DEMAND. */
    line-height: 0.7355;
  }
  /* FIREPOWER sits a full extra line above /ON — 143.2pt rather than 74.9 —
     so the shoes read between the two halves of the line. That gap is the
     composition; closing it up is what made ours look wrong. */
  .rhero__l--1 { margin-bottom: 7.14cqw; }
}

/* --- Search -------------------------------------------------------------- */
.rsearch { background: var(--bubblegum); color: var(--on-bubblegum); padding-block: var(--s-5) var(--s-6); }

/* The design sets this small in cream on pink, which measures 1.81:1. At body
   size that is unreadable, so the paragraph takes the ink and keeps the
   uppercase, tracking and size the design specifies. The giant display type
   stays cream, where it is a brand statement rather than something you read. */
.rsearch__strap {
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--on-bubblegum);
  font-size: var(--step--1);
  line-height: 1.55;
  max-width: 46ch;
}
.rsearch__label {
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--on-bubblegum);
  font-size: var(--step--1);
  margin-top: var(--s-2);
}
.rsearch__title {
  font-family: var(--font-poster);
  font-weight: 900;
  font-stretch: 90%;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--cream);
  font-size: clamp(2.4rem, 1rem + 6vw, 6rem);
  line-height: 0.88;
  margin-top: var(--s-5);
}
.seek { display: flex; align-items: center; gap: 0.5rem; background: var(--cream); border-radius: 999px; padding: 0.4rem 0.4rem 0.4rem 1.6rem; margin-top: var(--s-4); cursor: text; }
.seek__input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  font-family: inherit;
  /* 16px floor or iOS zooms the page on focus. */
  font-size: max(16px, var(--step-0));
  color: var(--charcoal);
  caret-color: var(--magenta);
  padding-block: 1.05rem;
}
.seek__input::placeholder { color: color-mix(in srgb, var(--charcoal) 62%, transparent); }
/* The pill is the field, so the pill carries the focus. The shadow has to go as
   well as the outline: base :focus-visible sets a charcoal one, and a text input
   always matches it, so clearing only the outline left a black box on click.
   The ring is inset because magenta reads on the cream (4.29:1), not on the
   bubblegum ground outside it (2.37:1). */
.seek__input:focus { outline: none; box-shadow: none; }
.seek:focus-within { outline: 3px solid var(--magenta); outline-offset: -3px; }
.seek__go {
  flex: none;
  width: 3rem; height: 3rem;
  border-radius: 50%;
  background: var(--charcoal);
  color: var(--cream);
  font-size: var(--step-1);
  cursor: pointer;
  transition: background-color var(--t-fast) linear;
}
.seek__go:hover { background: var(--magenta); }
.seek__out { margin-top: var(--s-2); }
.seek__hit { font-size: var(--step-0); color: var(--on-bubblegum); }
.seek__hit .link { margin-left: 0.4em; }
.seek__note { color: color-mix(in srgb, var(--charcoal) 70%, transparent); text-transform: none; letter-spacing: normal; margin-top: 0.3rem; }

@media (min-width: 62rem) {
  .rsearch { padding: 0; }
  /* 444.2pt of 958.16 */
  .rsearch__canvas { aspect-ratio: 958.16 / 444.2; }
  .rsearch__canvas > * { position: absolute; margin: 0; }

  .rsearch__strap {
    top: 5.87cqw; left: 3.90cqw;
    font-size: 1.37cqw;       /* cap 10.1pt */
    line-height: 1.207;       /* 15.85pt between baselines */
    font-weight: 500;
    max-width: none;
  }
  .rsearch__label { top: 5.87cqw; right: 6.91cqw; font-size: 1.37cqw; line-height: 1.207; font-weight: 700; }

  .rsearch__title {
    top: 19.58cqw; left: 3.71cqw;
    font-size: 6.025cqw;      /* cap 39.6pt */
    line-height: 0.7330;      /* 41.72pt between cap tops, measured back */
  }
  /* Four lines in the design, not two. */
  .rsearch__title br { display: block; }

  .seek {
    /* Centred on the headline beside it, which is above where Rich's page has it. */
    top: 24.92cqw; left: 47.71cqw;
    width: 47.18cqw; height: 6.909cqw;
    padding-inline: 2.6cqw 0.55cqw;
    gap: 0.8cqw;
  }
  /* Set as the design has it: uppercase, tracked, inside the pill. */
  .seek__input { font-size: max(16px, 1.35cqw); padding-block: 0; }
  .seek__input::placeholder { text-transform: uppercase; letter-spacing: 0.02em; }
  .seek__go { width: 5.2cqw; height: 5.2cqw; font-size: 2cqw; }
  .seek__out { top: 33cqw; left: 47.71cqw; width: 47.18cqw; }
}
@media (max-width: 74.99rem) {
  /* The strap's three hand-set breaks are Rich's, and they only hold while the
     canvas is wide enough to fit those exact lines. Narrower, they break the
     paragraph in the wrong places, so they are switched off. */
  .rsearch__strap br { display: none; }
}

/* --- Know the difference, on the desk ------------------------------------ */
.rdiff { background: var(--charcoal); }
.rdiff__stage {
  position: relative;
  display: grid;
  place-items: center;
  padding-block: clamp(var(--s-4), 6vw, var(--s-6));
  background-image: url('/assets/img/wood-1920.webp');
  background-size: cover;
  background-position: center;
  overflow: clip;
}
.rdiff__title {
  margin: 0;
  font-family: var(--font-poster);
  font-weight: 900;
  font-stretch: 90%;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--cream);
  font-size: clamp(2.6rem, 0.5rem + 10vw, 10rem);
  line-height: 0.86;
  pointer-events: none;
}
.rdiff__w { display: block; }
.rdiff__w--the, .rdiff__w--diff { text-align: right; }
.rdiff__fan { position: relative; z-index: 1; width: 106%; max-width: none; height: auto; display: block; }
/* The fan is one cut-out, so drop-shadow runs round the outline of every card at
   once. Same three shadows at rest and on hover, or the fade cannot interpolate.
   The neon is its own colour: the cards are pink too, and only something this
   saturated still reads as light against them and the wood. */
@media (hover: hover) {
  .rdiff__fan {
    --neon: rgb(255 31 209 / 0);
    filter: drop-shadow(0 0.25rem 0.4rem var(--neon)) drop-shadow(0 0.5rem 1.1rem var(--neon)) drop-shadow(0 0.75rem 2.4rem var(--neon));
    transition: filter var(--t-base) linear;
  }
  /* is-lit, not :hover: most of the image's box is bare wood. See fan() in app.js. */
  .rdiff__fan.is-lit { --neon: rgb(255 31 209 / 0.95); }
}

@media (min-width: 62rem) {
  .rdiff__stage { padding: 0; display: block; }
  /* 535.6pt of 958.16 */
  .rdiff__canvas { aspect-ratio: 958.16 / 535.6; }
  .rdiff__title {
    position: absolute;
    inset: 3.42cqw 3.30cqw auto 2.80cqw;
    font-size: 12.917cqw;   /* cap 84.9pt */
    line-height: 0.7208;    /* 89.2pt between cap tops */
  }
  /* KNOW is set left, /THE and DIFFERENCE right — they are not one
     right-aligned block, which is what ours used to draw. */
  .rdiff__w--know { text-align: left; }

  /* The pack is dealt OVER the headline; DIFFERENCE reads through the gaps.
     Placed from the fan's own alpha bounding box, not its frame: the PNG
     carries transparent margin, so `width: 77.75cqw` lands its INK at
     12.62% -> 86.48% of the page, which is where Rich deals it. */
  .rdiff__fan { position: absolute; z-index: 1; top: 3.80cqw; left: 9.85cqw; width: 78.30cqw; }
}


/* --- Three-way ladder ----------------------------------------------------- */
.l3 { width: 100%; border-collapse: collapse; }
.l3 thead th {
  font-size: var(--micro-size);
  font-weight: 700;
  letter-spacing: var(--micro-track);
  text-transform: uppercase;
  color: var(--cream-muted);
  padding-bottom: var(--s-1);
  border-bottom: 1px solid var(--rule);
  text-align: left;
}
.l3 thead th:first-child { width: 28%; }
.l3 tbody tr { border-bottom: 1px solid var(--rule); }
.l3 tbody th { text-align: left; font-weight: 500; font-size: var(--step--1); padding: 0.85em 0.5em 0.85em 0; color: var(--cream); }
.l3__cell { position: relative; padding: 0.85em 0.6em; width: 24%; }
.l3__bar { position: absolute; left: 0.6em; right: 0.6em; bottom: 0.55em; height: 4px; background: color-mix(in srgb, var(--cream) 14%, transparent); }
/* The bar mechanic, the per-character inks and the whole entrance now live
   in the block after this section's mobile rules. */

.l3__legend { display: grid; gap: var(--s-3); margin-top: var(--s-4); }
@media (min-width: 58rem) { .l3__legend { grid-template-columns: repeat(3, 1fr); gap: var(--s-4); } }
/* The legend is the three printed cards, not three abstract dots: the pack IS
   the argument, and the Fractional CXO card only arrived on 18 Sep so this is
   the first place all three can be seen at a readable size. */
.l3__key { display: grid; gap: 0.9rem; align-items: start; }
@media (min-width: 34rem) and (max-width: 57.99rem) { .l3__key { grid-template-columns: 11rem 1fr; gap: 1.25rem; } }
/* Sized by HEIGHT, not width: the three source crops have different aspects
   (0.65 / 0.71 / 0.71), so matching widths deals a hand of three different
   sizes. Matching heights is how a pack actually looks. */
.l3__card { height: clamp(11rem, 17vw, 16rem); width: auto; max-width: 100%; display: block; }
.l3__swatch { display: inline-block; width: 0.7em; height: 0.7em; border-radius: 50%; margin-right: 0.5em; }
.l3__name { font-family: var(--font-display); font-size: var(--step-1); text-transform: uppercase; color: var(--cream); }
.l3__blurb { font-size: var(--step--1); color: var(--cream-muted); line-height: 1.55; }

@media (max-width: 40rem) {
  .l3 thead th:first-child { width: 34%; }
  .l3__cell { padding-inline: 0.3em; }
}

/* ==========================================================================
   KNOW / THE DIFFERENCE — the three-way ladder, animated.

   WHERE THIS GOES (site/assets/css/components.css):
     - REPLACES lines 1778-1788 (the `.l3__cell b` rule, the bar mechanic,
       and the three per-who colour rules).
     - Everything from "--- 1. Geometry" down is APPENDED after the existing
       `@media (max-width: 40rem)` block at ~line 1808.

   THE UNIT OF MOTION IS THE COLUMN, NEVER THE ROW.
   The six measures are a POSITION, not a score — "a 10 in everything isn't
   a card, it's a claim". Three bars growing side by side in one row is a
   100m dash, so a row is never animated as a group. Each character's six
   marks travel top-to-bottom as one gesture, and --l3-colgap (400ms) is
   deliberately LONGER than --l3-dur (380ms). That single inequality is what
   makes this not a race: there is a 20ms clearance between any two cells in
   the SAME measure row, so no two people's marks in one row are ever in
   motion at the same instant. Adjacent columns do overlap by ~205ms, but
   only a column's bottom rows against the next column's top row — different
   measures, opposite ends of the table, nothing to read a speed against.
   If you retune these, keep colgap > dur or the guarantee is gone.

   NOTHING COUNTS UP. The numbers fade and settle; they never tally from 0.
   A count-up is the single micro-interaction that still reads as a
   scoreboard after every other competitive cue has been removed. This is a
   rule, not an omission — do not "improve" it later.

   FAIL-OPEN BY CONSTRUCTION — read this before editing anything below.
   Every hidden "before" state lives in a @keyframes `from` block applied
   only under `.l3-scope.is-in`, with animation-fill-mode: backwards. NO
   element anywhere declares opacity:0 as its own resting style. So if the
   module fails to load, the observer never fires, or the visitor lands with
   the page already scrolled past this section, everything paints correctly
   and statically: an untriggered section is a CORRECT section, not an
   invisible one. That is also why there is deliberately NO setTimeout
   backstop — a timer started at page load either beats the reader to the
   section (killing the reveal for everyone who scrolls slowly) or arrives
   far too late to rescue anything. Fixing the failure mode in the cascade
   beats papering over it with a timer.
   (memory/feedback/feedback_visibility_gate_needs_failure_state.md)

   The same rule repairs an inherited bug. The old pair —
     .l3__bar i              { width: 0 }
     .l3.is-in … .l3__bar i  { width: calc(var(--v) * 10%) }
   — failed CLOSED: if `.is-in` never landed, every score on the page read
   as ZERO. A confidently wrong page is worse than a plain one. The resting
   width is now the true value and the animation travels FROM zero.

   `backwards`, never `both`: a `both` fill leaves the final keyframe in the
   animation origin of the cascade, which outranks every normal author
   declaration and would permanently dead-lock the card's hover transform.

   CLS: only opacity, transform, and the bar's own width ever change. The
   bar sits inside `.l3__bar`, which is position:absolute, so its width
   cannot move anything on the page.
   ========================================================================== */


/* --- 0. Per-character identity ---------------------------------------------
   One declaration block per character, carrying BOTH the ink colour and the
   column index. Replaces the three colour rules that were here: the ink is
   now a named token instead of being restated at every use site, which is
   what lets the marker dot take the bar's colour without a `background:
   inherit` coupling that would silently go transparent if the bar ever
   became a gradient. --l3-col is read by the entrance delays; it comes off
   the data-who the template already renders, so no index has to be counted
   in JS.

   NOTE the custom properties are named --l3-*, never --i. `reveals()`
   (app.js:310) stamps an inline `--i` on the children of every element in
   its target list, and on /fractional those children are this very table
   and legend. A bare `--i` here would be a live collision. */
.l3__cell[data-who="ned"],  .l3 thead th[data-who="ned"],  .l3__key[data-who="ned"]  { --l3-ink: var(--cream);     --l3-col: 0; }
.l3__cell[data-who="cxo"],  .l3 thead th[data-who="cxo"],  .l3__key[data-who="cxo"]  { --l3-ink: var(--mint);      --l3-col: 1; }
.l3__cell[data-who="fred"], .l3 thead th[data-who="fred"], .l3__key[data-who="fred"] { --l3-ink: var(--bubblegum); --l3-col: 2; }

/* Identical output to the three rules this replaces: NED's number resolved
   to var(--cream) by inheritance from body anyway. */
.l3__bar i,
.l3__swatch    { background: var(--l3-ink); }
.l3__cell b    { color: var(--l3-ink); }


/* --- 1. Geometry: the mark, not the fill -----------------------------------
   THE most important two rules in this file, and they contain no motion.

   A bar growing from zero reads as a quantity filling toward "full". A dot
   sitting at a point on a fixed grey track reads as a POSITION on a shared
   line — which is exactly what this section claims the six measures are.
   The dot is permanent geometry, not an extra animated beat: it is anchored
   to the right edge of the growing `i`, so it rides the tip as the bar
   travels and needs no delay, no transition and no hover pulse of its own.
   It therefore costs zero moving objects, and it makes the argument for
   reduced-motion visitors and forever after the entrance is spent —
   the same reasoning as the permanent card tilt below.

   `position: relative` on the fill is only an anchor for the dot; it
   changes no layout. */
.l3__bar i {
  display: block;
  height: 100%;
  position: relative;
  /* Resting state is the TRUE value — see the fail-open note in the header.
     The entrance animates FROM zero rather than TO this. */
  width: calc(var(--v) * 10%);
}
.l3__bar i::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--l3-ink);
  /* Centres the dot ON the tip whatever its own size, so it reads as a mark
     placed at a point rather than a cap stuck on the end of a bar. */
  transform: translate(50%, -50%);
}

/* `<b>` is a non-replaced INLINE element — components.css set only
   font-family and font-size on it — so `transform` silently does not apply
   and the number would only ever fade. This is the one-line fix; without it
   half the per-cell motion specified below does not exist. CLS-safe: the
   number is single-line content whose inline-block margin box is exactly
   the 1.55 line-height box it already occupied, and the row's height is set
   by the taller cell padding either way. */
.l3__cell b {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--step-1);
}

/* Each card keeps a small PERMANENT resting angle. Three cards at three
   slightly different angles read as three physical objects on a desk;
   three cards squared up in a tidy 3-up grid is how ranked items sit. This
   is static, unconditional CSS — it is not motion, nothing travels to reach
   it, so it survives prefers-reduced-motion untouched and carries the "not
   interchangeable" argument on the static page. It is also the single
   source of truth for how a card sits, animated or not: the deal animation
   runs on the PARENT .l3__key and never touches this transform. */
.l3__key[data-who="ned"]  .l3__card { --l3-tilt: -1.4deg; }
.l3__key[data-who="cxo"]  .l3__card { --l3-tilt:  1deg; }
.l3__key[data-who="fred"] .l3__card { --l3-tilt: -0.8deg; }
.l3__card {
  transform: rotate(var(--l3-tilt, 0deg));
  /* Declared on the BASE selector, never inside the interaction state.
     A transition that lives in the `[data-active]` rule disappears the
     moment that rule stops matching, so the element snaps back with no
     animation on every pointer-out — smooth in, hard cut out. */
  transition: transform var(--t-base) var(--ease-out),
              opacity   var(--t-base) linear;
}


/* --- 2. Timing ------------------------------------------------------------
   Every beat is one calc() off these five numbers. Scoped to .l3-scope so
   the whole choreography can be retuned in one place.
   Totals: last mark lands 1785ms, last card settles ~2080ms. */
.l3-scope {
  --l3-t0:      380ms;  /* when column 0 starts, after the frame beat       */
  --l3-colgap:  400ms;  /* MUST stay > --l3-dur — see the header note       */
  --l3-rowstep:  45ms;  /* top-to-bottom within one column                  */
  --l3-dur:     380ms;  /* one mark's travel                                */
  --l3-tint: color-mix(in srgb, var(--cream) 6%, transparent);
}

/* The entrance delay for any cell: its column's turn, then its row's place
   within that column. Both indices are inherited (--l3-col from the cell's
   data-who rule, --l3-row from the inline style on its <tr>), so a seventh
   measure or a fourth character needs no new CSS — unlike an :nth-child
   ladder, which silently stops staggering the moment STATS grows. */
@media (prefers-reduced-motion: no-preference) {

  /* Hidden "before" states exist ONLY as keyframe `from` blocks. */
  @keyframes l3-rise { from { opacity: 0; transform: translateY(10px); } }
  @keyframes l3-mark { from { opacity: 0; transform: translateY(5px); } }
  @keyframes l3-draw { from { width: 0; } }
  @keyframes l3-fade { from { opacity: 0; } }

  /* Beat 1 — the section's own sentence leads. */
  .l3-scope.is-in .rdiff__lede {
    animation: l3-rise 380ms var(--ease-out) backwards;
  }

  /* Beat 2 — the ruled axis appears ONCE, as one neutral frame. Deliberately
     unstaggered by column or by row: the frame belongs to the measure, not
     to whichever character happens to lead a row. A left-to-right header
     stamp would be decoration on a data table and would cost half a second
     before the first mark moves. <th> is display:table-cell, which IS
     transformable — unlike the `<b>` above. */
  .l3-scope.is-in .l3 thead th,
  .l3-scope.is-in .l3 tbody th {
    animation: l3-rise 320ms var(--ease-out) backwards;
    animation-delay: 140ms;
  }

  /* Beats 3-5 — one character's whole column, top to bottom, as one gesture.
     The mark travels; the number settles just before it arrives. */
  .l3-scope.is-in .l3__bar i {
    animation: l3-draw var(--l3-dur) var(--ease-out) backwards;
    animation-delay: calc(var(--l3-t0)
                        + var(--l3-col, 0) * var(--l3-colgap)
                        + var(--l3-row, 0) * var(--l3-rowstep));
  }
  .l3-scope.is-in .l3__cell b {
    animation: l3-mark var(--t-base) var(--ease-out) backwards;
    animation-delay: calc(var(--l3-t0)
                        + var(--l3-col, 0) * var(--l3-colgap)
                        + var(--l3-row, 0) * var(--l3-rowstep));
  }

  /* The card lands as its own column becomes legible, so the card reads as
     that shape rather than as a caption. Reuses the site's existing `deal`
     keyframe (components.css:1383, used by .mini) so a Top Thumps card
     looks like the same kind of object landing wherever it appears, instead
     of a bespoke entrance invented once here.
     The animation is on .l3__key (the parent). The tilt and the lift both
     live on .l3__card (the child), so the two can never collide and the
     hover lift is never outranked by an animation origin. */
  .l3-scope.is-in .l3__key {
    animation: deal 520ms var(--ease-out) backwards;
    animation-delay: calc(var(--l3-t0)
                        + var(--l3-col, 0) * var(--l3-colgap)
                        + var(--l3-dur));
  }

  /* The artwork develops into its already-dealt frame on its OWN clock.
     .l3-scope is added by JS synchronously, so this hidden state can only
     ever apply when a script is definitely running to remove it; .is-ready
     has three independent exits (load / error / timeout) in app.js. */
  .l3-scope .l3__card:not(.is-ready) { opacity: 0; }
  .l3-scope .l3__card.is-ready       { animation: l3-fade var(--t-base) linear; }
}


/* --- 3. After the entrance: the card and its column are one thing ----------
   The only ongoing interaction, and the only part of this file that keeps
   working long after the one-shot reveal is spent: point at any cell, any
   column header, or a printed card, and that whole column is tinted and its
   card lifts. It is what lets a reader isolate one silhouette on demand,
   which is the argument itself.

   NOTHING IS DIMMED. The obvious version of this — recede the other two —
   is one design step from "winner lit, losers greyed", and it is a measured
   contrast failure here: the three columns' inks at 0.4 opacity on charcoal
   land at 3.48 / 2.83 / 2.39:1, all below 1.4.3, for as long as a pointer
   sits anywhere in the table.
   (memory/feedback/feedback_opacity_is_not_de_emphasis_on_brand_colour.md —
   the lesson is about the resulting RATIO, not the direction of the blend.)
   Tinting the active column instead RAISES the ground very slightly and
   leaves everything legible: measured on this section's own tokens, cream
   goes 15.10 -> 12.93:1, mint 10.93 -> 9.36:1, bubblegum 8.33 -> 7.13:1,
   and --cream-muted 8.68 -> 7.43:1. All far above AA.

   No tabindex, no role, no cursor:pointer. A read-only data table has no
   native tab stops and must not gain fake ones: three focusable <div>s that
   do nothing on activation would be a real keyboard regression traded for a
   decorative highlight. Do not "fix" this by adding tabindex. (If a card
   ever becomes a real link, add :focus-within here and a focusin handler in
   app.js at the same time.)

   Pointer-gated so it cannot stick after a tap on touch, where :hover has
   no way to clear. */
.l3__cell,
.l3 thead th[data-who] {
  transition: background-color var(--t-base) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .l3-scope[data-active="ned"]  .l3 [data-who="ned"],
  .l3-scope[data-active="cxo"]  .l3 [data-who="cxo"],
  .l3-scope[data-active="fred"] .l3 [data-who="fred"] {
    background-color: var(--l3-tint);
  }

  /* Pointing at the table lifts the card the column belongs to, and
     pointing at the card does the same thing through the same rule — one
     mechanism, not two. The lift partially straightens the card rather than
     snapping it flat, which reads as picking it up off the table. */
  .l3-scope[data-active="ned"]  .l3__key[data-who="ned"]  .l3__card,
  .l3-scope[data-active="cxo"]  .l3__key[data-who="cxo"]  .l3__card,
  .l3-scope[data-active="fred"] .l3__key[data-who="fred"] .l3__card {
    transform: translateY(-4px) rotate(calc(var(--l3-tilt, 0deg) * 0.35));
  }
}

/* --- FrED, the manifesto -------------------------------------------------- */
/* Measured off Rich's page: the section runs 1534.8 -> 2069.7pt, so 55.80% of
   his page width tall. Everything inside is a percentage of that same width. */
.rfred {
  position: relative;
  background: var(--bubblegum);
  color: var(--on-bubblegum);
  padding-block: var(--s-4) var(--s-6);
  overflow: clip;
}
/* On a phone the figure is a band in the flow between the lockup and the copy
   — floating it behind the text at half opacity put a flamethrower through
   three paragraphs. */
.rfred__figure {
  display: block;
  width: 112%;
  margin: var(--s-3) -6% var(--s-2);
  height: auto;
  pointer-events: none;
}
.rfred__kicker, .rfred__mark, .rfred__expand, .rfred__cols { position: relative; z-index: 1; }

/* Small text, so it takes the ink. Cream here measures 1.81:1 — fine as a
   statement at poster scale, not for a line someone has to read. */
.rfred__kicker {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--on-bubblegum);
}
.rfred__mark { display: block; width: min(82vw, 36rem); height: auto; margin-top: var(--s-2); }
.rfred__expand {
  font-family: var(--font-poster);
  font-weight: 900;
  font-stretch: 90%;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-size: clamp(1.1rem, 0.6rem + 1.8vw, 2.2rem);
  line-height: 0.98;
  color: var(--cream);
  margin-top: var(--s-2);
}
.rfred__cols { display: grid; gap: var(--s-3); margin-top: var(--s-5); }
.rfred__cols p { font-size: var(--step--1); line-height: 1.6; }

@media (min-width: 62rem) {
  /* The copy runs to the very foot of the canvas, so it needs this to clear the
     blend below. */
  .rfred { padding: 0 0 var(--s-3); }
  /* 534.6pt of 958.16 */
  .rfred__canvas { aspect-ratio: 958.16 / 534.6; }
  .rfred__canvas > * { margin: 0; }
  .rfred__figure,
  .rfred__kicker, .rfred__mark, .rfred__expand, .rfred__cols { position: absolute; }

  /* The figure's own aspect is 1.785 and the section's is 1.796 — within half
     a percent — so it is placed edge to edge at full width rather than floated
     and masked. That is how it is drawn: his head is cropped by the left edge
     of the page and the flame crosses the whole width behind the copy. */
  .rfred__figure {
    inset: 0 auto auto 0;
    width: 100%; height: auto;
    opacity: 1;
    z-index: 0;
    /* The body copy starts at 73.5% of the section height and Rich runs it
       straight over the flamethrower. He can: his copy is cream, which is 14:1
       on the gun. Ours takes the ink so it is readable on the pink — and ink on
       the gun barrel measured 1.00:1, i.e. literally invisible.
       So the figure is faded from just above the copy down. The flame sits at
       21-59% and is untouched; only the gun and gloves dissolve. Verified by
       sampling the rendered background behind every line. */
    -webkit-mask-image: linear-gradient(to bottom, #000 0 62%, rgba(0,0,0,0.24) 72%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 0 62%, rgba(0,0,0,0.24) 72%, transparent 100%);
  }

  /* kicker: cap top 1553.5pt, left 24.94% */
  .rfred__kicker {
    top: 1.63cqw; left: 24.94cqw;
    font-size: 1.32cqw; line-height: 1.2; letter-spacing: 0.01em;
  }
  /* The mark is Rich's own lockup placed whole, not type: the three column
     runs of FRED-2.png (0 -> .437, .443 -> .705, .716 -> 1) land on the PDF's
     runs (24.64 -> 55.37, 55.90 -> 74.31, 75.21 -> ...) for one consistent
     width of 70.5% and a left edge of 24.64%. Typed Archivo came out 16% wide,
     because this is lettering, not a typeface. The ™ rides along with it and
     lands at 90.0 -> 95.1%, which is where the design has it. */
  .rfred__mark { top: 4.12cqw; left: 24.62cqw; width: 70.5cqw; }
  /* FRACTIONAL / EXECUTIVE / DIRECTOR: cap tops 1780.3 / 1804.0 / 1827.8,
     left 42.67% — indented well past the FrED mark, not aligned with it. */
  .rfred__expand {
    top: 25.58cqw; left: 42.67cqw;
    font-size: 3.396cqw;   /* cap 22.3pt */
    line-height: 0.7297;   /* 23.75pt between cap tops */
  }
  /* Two columns of body copy starting at 51.84% and 75.51%, each ~21% wide. */
  .rfred__cols {
    top: 41.04cqw; left: 51.84cqw;
    display: grid; grid-template-columns: 21.2cqw 21.2cqw; gap: 2.5cqw;
  }
  /* His body copy is 0.859% of the page width — 13.7px on a 1600px canvas,
     which is smaller than we would set it. The proportion is kept and a 14px
     floor stops it going below the readable range on a narrower canvas. */
  .rfred__cols p { font-size: max(14px, 0.859cqw); line-height: 1.446; }
  .rfred__cols p + p { margin-top: 1.242cqw; }
}

/* --- Sign in -------------------------------------------------------------- */
/* The concept's own sign-in. The live masthead link leaves for
   app.thefractionals.ai; this keeps the whole thing on one origin so it can be
   walked end to end. It does not pretend to authenticate — see signin.js. */
.signin {
  display: grid;
  min-height: calc(100svh - var(--chrome-h));
  background: var(--charcoal);
}
@media (min-width: 62rem) {
  .signin { grid-template-columns: 46fr 54fr; min-height: calc(100svh - var(--chrome-h)); }
}
/* Grid items default to min-width:auto, i.e. their min-content width, and a
   1684px-wide <img> and a row of buttons both push that past a phone. */
.signin > * { min-width: 0; }
/* The pack is a cut-out object now, not a photograph filling the panel, so it
   is CONTAINED and centred with room around it — the whole box visible rather
   than a crop of it — and lit by a soft wash so it does not float on flat
   charcoal. */
.signin__art {
  position: relative;
  overflow: clip;
  background: var(--charcoal);
  min-width: 0;
  display: grid;
  /* An explicit track, not the implicit auto row. With an auto row the row
     height depends on the item, so the item's percentage max-height is
     cyclic and resolves to none — the pack rendered 288px tall inside a
     270px panel and lost its hang tab off the top. minmax(0, 1fr) makes the
     row definite, so max-height actually binds. */
  grid-template-rows: minmax(0, 1fr);
  place-items: center;
  padding: clamp(1.5rem, 5vw, 4rem);
}
.signin__art::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(52% 46% at 62% 48%,
              color-mix(in srgb, var(--bubblegum) 22%, transparent), transparent 70%);
  /* MUST stay here. On desktop this wash is deliberately allowed to spill 70%
     of its column to the RIGHT so the glow follows the pack instead of ending
     at an invisible panel edge — which puts an absolutely positioned,
     invisible box over the first 190px of the form. Without this it swallowed
     clicks on the Create account tab and the left half of both inputs: the
     page looked perfect and could not be used. */
  pointer-events: none;
}
.signin__art img {
  position: relative;
  z-index: 2;
  width: auto;
  height: auto;
  max-width: min(74%, 22rem);
  max-height: 66%;
  object-fit: contain;
  display: block;
  transform: rotate(-2.5deg);
  filter: drop-shadow(0 1.8rem 2.4rem rgb(0 0 0 / 0.55));
}
@media (max-width: 61.99rem) {
  /* Top padding clears the fixed masthead: the art is the first thing on the
     page here, so without it the pack's hang tab sits behind the header. */
  .signin__art { height: 40svh; min-height: 15rem; padding: calc(var(--chrome-h) + var(--s-2)) var(--s-2) var(--s-2); }
  .signin__art img { max-height: 100%; max-width: 62%; }
}

/* No chrome clearance here. Below the breakpoint the art panel is STACKED
   ABOVE this one and already carries it, so adding it again cost 157px of
   dead black between the pack and the heading. On desktop the two sit side by
   side and the panel needs its own — which the rules below give it. */
.signin__panel { display: grid; align-items: center; padding: var(--s-4) var(--gutter) var(--s-6); }
@media (min-width: 62rem) { .signin__panel { padding-top: calc(var(--chrome-h) + var(--s-4)); } }
.signin__inner { width: 100%; max-width: 30rem; margin-inline: auto; }
.signin__title {
  font-family: var(--font-poster);
  font-weight: 900;
  font-stretch: 90%;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-size: var(--step-5);
  line-height: 0.9;
  color: var(--cream);
  margin: 0.2em 0 var(--s-4);
}
.signin__form { display: grid; gap: var(--s-3); }
.signin__form .field__input {
  width: 100%;
  /* 16px floor or iOS zooms the page on focus. */
  font-size: max(16px, var(--step-0));
  font-family: inherit;
  color: var(--cream);
  background: color-mix(in srgb, var(--cream) 7%, transparent);
  border: 1px solid var(--rule);
  border-radius: 0.6rem;
  padding: 0.85rem 1rem;
}
.signin__form .field__input::placeholder { color: color-mix(in srgb, var(--cream) 42%, transparent); }
.signin__form .field__input:focus-visible { outline: 2px solid var(--bubblegum); outline-offset: 2px; }
.signin__go { justify-self: start; margin-top: var(--s-2); }

/* The status line is a colour, not an opacity: dimming toward the ground is
   what cost 33 contrast failures last time. */
.signin__msg:empty { display: none; }
.signin__msg {
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--cream);
  border-left: 3px solid var(--mint);
  padding-left: 0.85rem;
}
.signin__msg[data-state="err"] { border-left-color: var(--magenta-lift); }

.signin__note {
  margin-top: var(--s-4);
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--cream-muted);
}
.signin__alt { margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--rule); }
.signin__altq { font-size: var(--step--1); color: var(--cream-muted); margin-bottom: var(--s-2); }

/* --- The one door: sign in / create account ------------------------------
   Both panes ship visible. Only once JS sets data-on does the second one
   collapse, so a no-JS visitor gets a long page rather than half a screen
   behind a button that does nothing. */
.authtabs {
  display: inline-flex;
  gap: 0.25rem;
  margin: var(--s-2) 0 var(--s-3);
  padding: 0.25rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--cream) 8%, transparent);
}
.authtabs__t {
  appearance: none;
  border: 0;
  cursor: pointer;
  padding: 0.55em 1.1em;
  border-radius: 999px;
  background: none;
  color: var(--cream-muted);
  font: inherit;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.02em;
  transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}
.authtabs__t.is-on { background: var(--cream); color: var(--charcoal); }
.authtabs__t:focus-visible { outline: 2px solid var(--bubblegum); outline-offset: 2px; }

/* Until JS arrives neither pane is hidden, so the tablist would be lying. */
.authtabs:not([data-on]) { display: none; }
.authpane + .authpane { margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--rule); }
.authtabs[data-on] ~ .authpane + .authpane { margin-top: 0; padding-top: 0; border-top: 0; }
/* The same, from the first frame: data-auth is set inline before anything
   paints (see signin.html), where data-on waits for signin.js. */
[data-auth] .authtabs { display: inline-flex; }
[data-auth] .authpane + .authpane { margin-top: 0; padding-top: 0; border-top: 0; }
[data-auth="in"] #paneUp, [data-auth="up"] #paneIn { display: none; }
[data-auth="in"] #tabIn, [data-auth="up"] #tabUp { background: var(--cream); color: var(--charcoal); }

.authhint {
  margin-bottom: var(--s-3);
  padding-left: 0.85rem;
  border-left: 3px solid var(--bubblegum);
  font-size: var(--step--1);
  color: var(--cream-muted);
  line-height: 1.5;
}

.authpane__q {
  font-size: var(--step--1);
  color: var(--cream-muted);
  margin-bottom: var(--s-2);
}

/* The fork. Each side says what happens next rather than repeating its own
   label, because this is the one moment the two routes genuinely diverge. */
.rolepick { display: grid; gap: var(--s-2); }
.rolecard {
  display: grid;
  gap: 0.25rem;
  /* Tighter than --s-3: the create pane has a vertical budget (it has to fit
     an 800px-tall laptop under a 118px header without the panel scrolling)
     and this is where the room is, not in the display title. */
  padding: 1rem 1.15rem;
  border-radius: 1rem;
  border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--cream) 5%, transparent);
  color: var(--cream);
  text-decoration: none;
  transition: border-color var(--t-fast) linear, background-color var(--t-fast) linear,
              transform var(--t-fast) var(--ease-out);
}
.rolecard:hover { transform: translateY(-2px); background: color-mix(in srgb, var(--cream) 9%, transparent); }
.rolecard:focus-visible { outline: 3px solid var(--bubblegum); outline-offset: 3px; }
/* The arrow rides the heading row rather than taking a line of its own. The
   whole card is the link, so a separate "Continue" line was 26px of repeating
   what the card already is. */
.rolecard__h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  font-weight: 800;
  font-size: var(--step-1);
  line-height: 1.15;
}
.rolecard__b { font-size: var(--step--1); color: var(--cream-muted); line-height: 1.45; }
.rolecard__go { font-weight: 700; transition: transform var(--t-fast) var(--ease-out); }
.rolecard:hover .rolecard__go { transform: translateX(3px); }

/* Pink is hiring, green is fractional — the client's convention. The accent is
   carried on the left edge and the small type, never as a flat fill behind the
   body copy: --magenta under --cream-muted is 1.67:1 and could not be read. */
.rolecard--hiring { border-left: 4px solid var(--magenta); }
.rolecard--hiring .rolecard__go { color: var(--magenta-lift); }
.rolecard--fractional { border-left: 4px solid var(--mint); }
.rolecard--fractional .rolecard__go { color: var(--mint); }

/* Arrived via "I'm hiring" or "I'm a fractional": that side is already lit,
   but the other stays fully usable — a pre-selection, not a lock. */
.rolecard.is-picked { border-color: currentColor; background: color-mix(in srgb, var(--cream) 11%, transparent); }
.rolecard--hiring.is-picked { border-color: var(--magenta-lift); }
.rolecard--fractional.is-picked { border-color: var(--mint); }

@media (prefers-reduced-motion: reduce) {
  .rolecard, .authtabs__t { transition: none; }
}

/* ==========================================================================
   APP SCREENS — /signin and /join
   --------------------------------------------------------------------------
   These two are not documents, they are screens: you arrive to do one thing.
   So on desktop the whole thing fits the viewport on load — no scrolling to
   find the button you came for — and there is no sitemap footer under them.
   Below the breakpoint they behave like normal pages and scroll, which is what
   a phone wants.

   Where a screen's own content is genuinely taller than the viewport (the CV
   step, the shortlist), the CONTENT scrolls inside its panel and the controls
   stay put. A page that scrolls hides the Continue button; a panel that
   scrolls never does.
   ========================================================================== */
.page-app .foot { display: none; }

@media (min-width: 62rem) {
  .page-app main { min-height: 0; }

  /* --- Sign in ---
     Both panels paint the page's own charcoal — measured, they are the same
     rgb(26,27,30) — so the join between them is invisible and a 46fr/54fr
     split of the window is not a composition, it is just where the fr units
     landed. It stranded 356px of dead black to the LEFT of the pack at 1440
     while the form had 101px of air to its right; at 1700 the slab was 475px.
     So both columns are sized to their content and the PAIR is centred: the
     group sits in the middle of the screen at every width and the slack falls
     evenly either side instead of all on one. */
  .signin {
    height: 100svh;
    min-height: 0;
    grid-template-columns: minmax(0, 23.5rem) minmax(0, 30rem);
    justify-content: center;
    column-gap: clamp(2rem, 5vw, 4.5rem);
    padding-inline: var(--gutter);
    /* The wash below reaches well outside its column; this stops that ever
       becoming a horizontal scrollbar. */
    overflow: clip;
  }

  .signin__art { overflow: visible; padding: 0; place-items: center; }
  /* The glow stays anchored to the PACK's column rather than to the section,
     so it tracks the pack at every width instead of drifting as the centred
     group moves. It is allowed to spill because .signin clips. */
  .signin__art::before { inset: -25% -70%; }
  /* 22rem, not 100% of the column: that is the size already signed off, and
     the column carries 1.5rem of extra so the rotated box has room to bulge
     (it needs 11px a side at -2.5deg) without clipping. */
  .signin__art img { transform: rotate(-2.5deg); max-width: 22rem; max-height: 72%; }

  /* The form column IS the form, so it needs no inner centring or nudge. */
  .signin__inner { margin-inline: 0; max-width: none; }

  .signin__panel {
    padding-top: var(--chrome-h);
    padding-bottom: var(--s-3);
    /* overflow-y: auto clips sideways too, at this padding edge, and the
       controls are full width: with no padding here every focus ring lost both
       its sides. 0.5rem clears the widest ring (the 6px on .rolecard and the
       base :focus-visible), and the margin cancels it so the form does not
       move. */
    padding-inline: 0.5rem;
    margin-inline: -0.5rem;
    overflow-y: auto;
    align-content: center;
  }
  .signin__title { margin: 0.15em 0 var(--s-3); }
  .signin__form { gap: var(--s-2); }
  .signin__note { margin-top: var(--s-3); }
  .signin__alt { margin-top: var(--s-3); padding-top: var(--s-3); }

  /* --- The sign-up flow --- */
  .joinpage {
    height: 100svh;
    padding-block: calc(var(--chrome-h) + var(--s-3)) var(--s-3);
    display: grid;
    align-content: stretch;
  }
  .joinpage > .wrap { min-height: 0; display: grid; }
  .join { height: 100%; min-height: 0; align-items: stretch; gap: var(--s-5); }

  /* The question column keeps its furniture fixed and scrolls only the answer. */
  .join__main { display: flex; flex-direction: column; min-height: 0; }
  .join__body {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 0.6rem;
    /* A panel that scrolls with no cue is a trap, so the bar is made visible
       rather than hidden. */
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--mint) 70%, transparent) transparent;
  }
  .join__nav { flex: none; margin-top: var(--s-3); }

  /* The card is already the right height for the column; it no longer needs to
     stick to anything because nothing behind it moves. */
  .join__card { position: static; min-height: 0; overflow-y: auto; }
}

/* ==========================================================================
   WHAT EACH BAND TELLS THE HEADER TO WEAR
   --------------------------------------------------------------------------
   Sections not listed here inherit the charcoal default from :root.
   Photo bands carry a colour sampled from the top of their own image — the
   part that is actually behind the header — not a guess.
   ========================================================================== */
.rsearch, .rfred {
  --chrome: var(--bubblegum);
  --chrome-ink: var(--on-bubblegum);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
}
.unboxed {
  --chrome: var(--mint);
  --chrome-ink: var(--on-mint);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
}
.insights {
  --chrome: var(--tan);
  --chrome-ink: var(--on-tan);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
}
.how {
  --chrome: var(--oat);
  --chrome-ink: var(--charcoal);
  --chrome-accent: var(--magenta-ink);
  --chrome-mark: url('/assets/brand/fractionals-lockup-magenta.svg');
}
.start, .situations {
  --chrome: var(--cream);
  --chrome-ink: var(--charcoal);
  --chrome-accent: var(--magenta-ink);
  --chrome-mark: url('/assets/brand/fractionals-lockup-magenta.svg');
}
/* THE HERO: THE FILM PLAYS IN THE HEADER.
   Transparent was the wrong answer here. The film runs 25.7s from a near-black
   lift shaft to a blown white highlight, so holding the type over it needs a
   58% scrim — and a 58% scrim IS a dark bar, which is the thing it was meant
   to avoid. And the page scrolls through a transparent header, which is what
   the whole two-slice mechanism exists to stop.

   So the header is opaque here like everywhere else, and app.js DRAWS the
   strip of video that is actually behind it into a canvas, every other frame.
   The header is not a colour taken from the film, it is the film — and unlike
   a transparent header, nothing else can scroll through it.

   Legibility is handled per frame rather than with a fixed scrim: the same
   32x4 readback that used to pick the fill colour now says how much this
   particular frame needs darkening for the type to clear 4.5:1, and that much
   is painted over the canvas and no more. On the film's dark shots that is
   zero and you get the picture untouched; only the blown-out reveal pays.

   --chrome below is the fallback for when no video is playing at all —
   reduced motion, Save-Data or a refused autoplay — and is the measured mean
   of the hero still. */
.rhero {
  --chrome: #2e2e3b;
  --chrome-sample: video;
}
@media (max-width: 61.99rem) { .rhero { --chrome: #2d222f; } }
/* THE DESK: the header shows the actual wood, not a flat sample of it.
   app.js paints wood-1920.webp into the header and offsets it by the stage's
   own cover-crop, so the grain runs continuously from under the header into
   the section — at the bottom edge of the band there is no seam at all,
   which is the whole point.

   It needs lifting for the ink, and a flat wash would make the band read as
   a paler strip. So the wash is a top-down gradient: strongest at the page
   edge, nothing at all by the foot of the band, where it has to match. Over
   the wood's mean (179,153,124) charcoal is 6.37:1; the darkest grain knot
   in the crop is (118,73,40) where it is 2.26:1 raw and about 3.4:1 through
   the middle of this wash. That residual — a dark knot passing behind a
   letter — is the price of showing the real thing, and it is named here
   rather than hidden. */
.rdiff__stage {
  --chrome: #b3997c;
  --chrome-ink: var(--charcoal);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
  --chrome-img: url('/assets/img/wood-1920.webp');
  --chrome-scrim: linear-gradient(to bottom, rgb(255 255 255 / 0.36), rgb(255 255 255 / 0.16) 62%, rgb(255 255 255 / 0));
}
/* The inner-page heroes are photographs too, each sampled at the top of its
   own plate with the masthead taken out of the shot:
     /hiring     (85,63,46)   /fractional (80,72,51)   /pricing already charcoal
   Bubblegum on either of those browns is 4.2:1, under the small-text floor, so
   the links take the cream instead. */
.page-hiring .page-hero     { --chrome: #553f2e; --chrome-accent: var(--cream); }
.page-fractional .page-hero { --chrome: #504833; --chrome-accent: var(--cream); }

/* ==========================================================================
   KNOW / THE DIFFERENCE — the scroll-told version
   --------------------------------------------------------------------------
   Replaces the lede-plus-table block on the home page with five scenes on a
   sticky stage, scrubbed by scroll position (site/assets/js/scrolly.js).
   /fractional keeps the compact animated ladder — a reader that deep wants
   the table, not a five-scene narrative.

   The whole thing is built on this site's own tokens, not the reference's:
   charcoal ground, the three character inks, Anton for display and Inter for
   everything else, all self-hosted. No Google Fonts request, no CDN, nothing
   that the CSP would have to be opened up for.

   FAIL-OPEN: no rule here sets opacity:0 as a resting style. The hidden
   states are written by scrolly.js's render(0), so if the module never runs,
   the scenes stack down the page as readable blocks instead of an empty hole.
   The `.is-static` class (reduced motion) makes that the intended layout.
   ========================================================================== */
.scrolly { position: relative; background: var(--charcoal); color: var(--cream); }
.rs-stage { position: sticky; top: 0; height: 100svh; overflow: clip; }

/* The masthead is fixed and opaque, so every scene clears its height rather
   than sliding under it. */
.rs-scene {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--chrome-h) + var(--s-3)) var(--gutter) clamp(5rem, 11vh, 7rem);
}
@media (min-width: 62rem) { .rs-scene { padding-top: calc(var(--chrome-h) + var(--s-3)); } }

/* One ink per character file, exactly as the compact ladder assigns them.
   Scoped to .scrolly: a bare [data-who] would also match the cells of the
   compact table on /fractional, which is harmless today but is the kind of
   global attribute selector that goes wrong later. */
.scrolly [data-who="ned"]  { --rs-c: var(--cream); }
.scrolly [data-who="cxo"]  { --rs-c: var(--mint); }
.scrolly [data-who="fred"] { --rs-c: var(--bubblegum); }
.scrolly [data-who="all"]  { --rs-c: var(--tan); }

.rs-wash {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(58% 68% at 26% 50%,
              color-mix(in srgb, var(--rs-c) 20%, transparent), transparent 70%);
}
/* The outlined wordmark behind the scene — the same device as the footer's
   ghost, at scene scale. */
.rs-ghost {
  position: absolute; right: -3vw; bottom: -5vh;
  font-family: var(--font-poster); font-weight: 900; font-stretch: 90%;
  font-size: min(32vw, 58svh); line-height: 0.8;
  color: transparent;
  -webkit-text-stroke: 1.5px color-mix(in srgb, var(--rs-c) 28%, transparent);
  white-space: nowrap; pointer-events: none; user-select: none;
}

/* --- the opening line ----------------------------------------------------- */
.rs-intro { flex-direction: column; text-align: center; }
.rs-intro__copy {
  margin: 0; max-width: 20em;
  font-family: var(--font-poster); font-weight: 900; font-stretch: 90%;
  letter-spacing: 0.02em; text-transform: uppercase;
  font-size: clamp(2rem, min(5vw, 8svh), 4.6rem); line-height: 1.02;
}
.rs-intro__line { display: block; overflow: hidden; }
.rs-intro__line i { display: block; font-style: normal; }
.rs-intro__line + .rs-intro__line i { color: var(--bubblegum); }
.rs-hint {
  margin-top: var(--s-4);
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  color: var(--cream-muted);
}
.rs-hint::after {
  content: ''; width: 2px; height: 2.25rem;
  background: linear-gradient(var(--bubblegum), transparent);
  animation: rs-drip 1.6s ease-in-out infinite;
}
@keyframes rs-drip {
  0%   { transform: scaleY(0); transform-origin: top; }
  50%  { transform: scaleY(1); transform-origin: top; }
  51%  { transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
@media (prefers-reduced-motion: reduce) { .rs-hint::after { animation: none; } }

/* --- a single character file ---------------------------------------------- */
.rs-solo__inner {
  position: relative; width: 100%; max-width: 68rem;
  display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(1.5rem, 5vw, 4.5rem); align-items: center;
}
.rs-card-wrap { justify-self: center; perspective: 1400px; }
.rs-card {
  width: min(26vw, 34svh); height: auto;
  filter: drop-shadow(0 1.6rem 2.6rem rgb(0 0 0 / 0.55));
}
.rs-float { animation: rs-float 4.8s ease-in-out infinite; }
@keyframes rs-float { 50% { transform: translateY(-12px); } }
@media (prefers-reduced-motion: reduce) { .rs-float { animation: none; } }
.rs-tilt { transition: transform var(--t-base) var(--ease-out); }

.rs-info { max-width: 38rem; }
.rs-kicker { color: var(--cream-muted); margin-bottom: 0.5rem; }
.rs-name {
  margin: 0;
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.6rem, min(7.4vw, 12svh), 7rem); line-height: 0.92;
  text-transform: uppercase; color: var(--rs-c);
}
.rs-name sup { font-size: 0.26em; vertical-align: super; }
/* overflow:hidden is what lets each letter rise out of its own box. */
.rs-w { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: 0.04em; }
.rs-ch { display: inline-block; }
.rs-tag {
  margin-top: 0.5rem;
  font-family: var(--font-serif); font-weight: 900;
  font-size: clamp(1.05rem, min(1.7vw, 2.6svh), 1.4rem);
}
.rs-desc {
  margin-top: 0.6rem; max-width: 34em;
  font-size: clamp(0.9rem, min(1.15vw, 2svh), 1.05rem);
  line-height: 1.58; color: var(--cream-muted);
}
.rs-dw { display: inline-block; }

.rs-stats { list-style: none; margin: clamp(1rem, 2.6vh, 1.5rem) 0 0; padding: 0; }
.rs-st {
  display: grid; grid-template-columns: minmax(9rem, 13rem) 1fr 2.6rem;
  gap: 1rem; align-items: center;
  padding: min(0.5rem, 0.9vh) 0; border-bottom: 1px solid var(--rule);
}
.rs-lab { font-size: var(--step--1); display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
/* "Leads here", never "best" or "top": this section's whole argument is that
   the six measures are a position, not a score, and each of the three leads
   exactly two of them. Do not reword this into a ranking. */
.rs-leads {
  font-size: var(--micro-size); font-weight: 700; letter-spacing: var(--micro-track);
  text-transform: uppercase;
  color: var(--charcoal); background: var(--rs-c);
  border-radius: 999px; padding: 0.15em 0.6em; display: inline-block;
}
/* display:block matters: in the solo scene the track is a grid item and gets
   its width from the column, but in the all-three cell it is a bare <span> in
   a block — inline, and therefore zero wide, which collapses every bar to a
   stub sitting against the number. */
.rs-track { display: block; width: 100%; position: relative; height: 4px; background: color-mix(in srgb, var(--cream) 14%, transparent); }
.rs-fill { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--rs-c); }
/* The marker that rides the tip, same device as the compact ladder: a dot at
   a point on a fixed track reads as a POSITION, where a bar filling to the
   end reads as a quantity reaching "full". */
.rs-fill::after {
  content: ''; position: absolute; top: 50%; right: 0;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--rs-c); transform: translate(50%, -50%);
}
.rs-num {
  font-family: var(--font-display); font-size: clamp(1.3rem, min(2vw, 3.4svh), 1.75rem);
  line-height: 1; text-align: right; color: var(--rs-c); font-variant-numeric: tabular-nums;
}

/* --- all three on one set of axes ----------------------------------------- */
.rs-all__inner { width: 100%; max-width: 62rem; }
.rs-all__title {
  margin: 0 0 clamp(0.9rem, 2.4vh, 1.25rem);
  font-family: var(--font-poster); font-weight: 900; font-stretch: 90%;
  letter-spacing: 0.02em; text-transform: uppercase;
  font-size: clamp(1.7rem, min(4vw, 6.4svh), 3.4rem); line-height: 1;
}
.rs-ln { display: block; overflow: hidden; }
.rs-li { display: block; }
.rs-ln + .rs-ln .rs-li { color: var(--bubblegum); }

.rs-row {
  display: grid; grid-template-columns: 1.1fr repeat(3, 1fr);
  align-items: end; border-bottom: 1px solid var(--rule);
}
.rs-row > * { padding: min(0.6rem, 1.2vh) 0.65rem; }
.rs-row--head { border-bottom-color: color-mix(in srgb, var(--cream) 28%, transparent); }
.rs-hcell { display: flex; align-items: flex-end; gap: 0.75rem; }
.rs-mini { width: 3.4rem; height: auto; }
.rs-hname {
  font-family: var(--font-display); text-transform: uppercase;
  font-size: clamp(0.95rem, min(1.6vw, 3svh), 1.4rem); line-height: 1; color: var(--rs-c);
}
.rs-tlab { font-size: var(--step--1); align-self: center; }
.rs-tc .rs-n {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, min(1.8vw, 3.2svh), 1.5rem); line-height: 1;
  display: inline-block; margin-bottom: min(0.45rem, 1vh);
  color: var(--rs-c); transform-origin: left bottom; font-variant-numeric: tabular-nums;
}
.rs-tc .rs-track { height: 3px; }
.rs-closer {
  margin-top: clamp(0.9rem, 2.4vh, 1.25rem); max-width: 46em;
  font-size: clamp(0.9rem, min(1.3vw, 2.2svh), 1.1rem); color: var(--cream-muted);
}

/* --- wipes and chapter nav ------------------------------------------------ */
.rs-wipe {
  position: absolute; inset: 0; z-index: 5;
  transform: translateX(-101%); pointer-events: none;
  background: var(--rs-c);
}
.rs-nav {
  position: absolute; z-index: 6; left: 50%; bottom: clamp(0.75rem, 2.4vh, 1.4rem);
  transform: translateX(-50%);
  display: flex; gap: 4px;
  background: color-mix(in srgb, var(--charcoal) 85%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--rule); border-radius: 999px; padding: 5px;
  max-width: calc(100% - 1.25rem);
}
.rs-chap {
  position: relative; padding: 0.55rem 0.9rem 0.8rem;
  border-radius: 999px; font-size: var(--step--1); font-weight: 600;
  color: var(--cream-muted); white-space: nowrap;
  transition: color var(--t-fast) linear, background-color var(--t-fast) linear;
}
.rs-chap:hover { background: color-mix(in srgb, var(--cream) 6%, transparent); }
.rs-chap.is-on { color: var(--cream); }
.rs-chap__bar {
  position: absolute; left: 0.9rem; right: 0.9rem; bottom: 0.35rem;
  height: 2px; background: var(--rule); border-radius: 2px; overflow: hidden;
}
.rs-chap__bar i { position: absolute; inset: 0; background: var(--rs-c); transform: scaleX(0); transform-origin: left; }

/* --- reduced motion: no scroll-jack at all -------------------------------- */
/* Playing the same sequence faster is not the fix. The complaint behind the
   preference is a 3,000px hijacked scroll, so under `reduce` the stage stops
   being sticky and the five scenes become ordinary stacked blocks. */
.scrolly.is-static { height: auto !important; }
.scrolly.is-static .rs-stage { position: static; height: auto; overflow: visible; }
.scrolly.is-static .rs-scene {
  position: static; display: block;
  padding: var(--s-5) var(--gutter);
  border-bottom: 1px solid var(--rule);
}
.scrolly.is-static .rs-ghost,
.scrolly.is-static .rs-wash,
.scrolly.is-static .rs-wipe { display: none; }
.scrolly.is-static .rs-solo__inner,
.scrolly.is-static .rs-all__inner { margin-inline: auto; }

/* --- narrow screens ------------------------------------------------------- */
@media (max-width: 52rem) {
  .rs-scene { align-items: flex-start; }
  .rs-solo__inner {
    grid-template-columns: auto 1fr;
    grid-template-areas: "card head" "desc desc" "stats stats";
    column-gap: 1rem; row-gap: 0; align-items: end;
  }
  .rs-info { display: contents; }
  .rs-card-wrap { grid-area: card; justify-self: start; }
  .rs-card { width: min(34vw, 22svh); }
  .rs-head { grid-area: head; padding-bottom: 0.25rem; }
  .rs-desc { grid-area: desc; margin-top: 0.9rem; }
  .rs-stats { grid-area: stats; margin-top: 0.6rem; }
  .rs-name { font-size: clamp(2.2rem, 11vw, 3.4rem); }
  .rs-st { grid-template-columns: minmax(6.5rem, 1.1fr) 1fr 1.9rem; gap: 0.6rem; }
  /* On a phone the copy runs the full width, so the ghost can only ever sit
     behind it. Dropped to texture rather than moved — there is nowhere on a
     390px screen for a 62vw word to go. */
  .rs-ghost { font-size: 62vw; bottom: auto; top: 26%;
              -webkit-text-stroke-width: 1px;
              -webkit-text-stroke-color: color-mix(in srgb, var(--rs-c) 15%, transparent); }
  .rs-row { grid-template-columns: 0.95fr repeat(3, 1fr); }
  .rs-row > * { padding: 0.5rem 0.3rem; }
  .rs-hcell { flex-direction: column; align-items: flex-start; gap: 0.4rem; }
  .rs-mini { width: 2.2rem; }
  .rs-chap { padding: 0.55rem 0.55rem 0.8rem; }
  .rs-chap__bar { left: 0.55rem; right: 0.55rem; }
  .rs-chap__full { display: none; }
}

/* --- Page to page --------------------------------------------------------
   Every route is a full document, so each change used to be a hard cut. This
   needs nothing but CSS: a browser without cross-document view transitions
   ignores it and simply loads the page. The masthead is its own layer so the
   one thing on every page holds still while the content under it changes. The
   hidden state lives in keyframes only, so a failed transition leaves the page
   visible. Opt-in rather than opt-out: reduced motion gets the plain cut. The
   @view-transition rule that turns this on is inline in shell.html, because it
   does nothing from here — see the note there. */
@media (prefers-reduced-motion: no-preference) {
  .masthead { view-transition-name: masthead; }
  ::view-transition-old(root) { animation: page-out var(--t-fast) linear both; }
  ::view-transition-new(root) { animation: page-in var(--t-base) var(--ease-out) both; }
  @keyframes page-out { to { opacity: 0; } }
  @keyframes page-in { from { opacity: 0; transform: translateY(12px); } }
}

/* --- The hold ------------------------------------------------------------
   A section stays put while the next slides up over it. .hold is the end of
   the hold: sticky only lasts as long as its parent, and without that the hero
   would sit under the whole page with the film still running. So .hold has to
   contain enough to cover the first child completely. is-on comes from
   holds() in app.js, which also sets `top` so a section taller than the screen
   holds at its bottom edge rather than losing it; no JS or reduced motion means
   a plain scroll. Jump links must not target a held section: a browser measures
   it where it is stuck, not where it belongs. */
.hold.is-on > :first-child { position: sticky; top: 0; z-index: 0; }
.hold.is-on > * + * { position: relative; z-index: 1; }

/* --- Pink into cream -----------------------------------------------------
   FrED's pink breaks up into circles that shrink to nothing on the cream. It is
   a picture because that is what the header can line up: it paints --chrome-img
   offset to the section, so the dots stay in register as the band passes behind
   it. 4000px wide and shown at its own size, so both are the same centred crop.
   Colours are --bubblegum and --oat. */
.fade {
  --chrome: var(--oat);
  --chrome-ink: var(--charcoal);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
  --chrome-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4000' height='160'%3E%3Cpattern id='d' width='32' height='160' patternUnits='userSpaceOnUse'%3E%3Cg fill='%23FF87FF'%3E%3Crect width='32' height='12'/%3E%3Ccircle cx='0' cy='4' r='12.0'/%3E%3Ccircle cx='32' cy='4' r='12.0'/%3E%3Ccircle cx='16' cy='20' r='10.8'/%3E%3Ccircle cx='0' cy='36' r='9.7'/%3E%3Ccircle cx='32' cy='36' r='9.7'/%3E%3Ccircle cx='16' cy='52' r='8.5'/%3E%3Ccircle cx='0' cy='68' r='7.3'/%3E%3Ccircle cx='32' cy='68' r='7.3'/%3E%3Ccircle cx='16' cy='84' r='6.2'/%3E%3Ccircle cx='0' cy='100' r='5.0'/%3E%3Ccircle cx='32' cy='100' r='5.0'/%3E%3Ccircle cx='16' cy='116' r='3.8'/%3E%3Ccircle cx='0' cy='132' r='2.7'/%3E%3Ccircle cx='32' cy='132' r='2.7'/%3E%3Ccircle cx='16' cy='148' r='1.5'/%3E%3C/g%3E%3C/pattern%3E%3Crect width='4000' height='160' fill='%231A1B1E'/%3E%3Crect width='4000' height='160' fill='url(%23d)'/%3E%3C/svg%3E");
  height: 10rem;
  background: var(--oat) var(--chrome-img) center / 4000px 100% no-repeat;
}

/* --- Sign-up section on Off-Black ---------------------------------------
   The section was Off-White; it is now the dark ground. The dotted band
   above it fades FrED's pink into Off-Black to match. */
.fade {
  --chrome: var(--charcoal);
  --chrome-ink: var(--cream);
  --chrome-accent: var(--bubblegum);
  --chrome-mark: url('/assets/brand/fractionals-lockup-cream.svg');
  background-color: var(--charcoal);
}
.start {
  background: var(--charcoal);
  color: var(--cream);
  --chrome: var(--charcoal);
  --chrome-ink: var(--cream);
  --chrome-accent: var(--bubblegum);
  --chrome-mark: url('/assets/brand/fractionals-lockup-cream.svg');
}
.start .toggle { border-color: var(--rule); }
.start .toggle__btn { color: var(--cream-muted); }
.start .toggle__btn.is-on { color: var(--on-magenta); }
.start__step { border-bottom-color: var(--rule); }
.start__n { background: var(--cream); color: var(--charcoal); }
.start__b { color: var(--cream-muted); }
.start__aside .btn:hover { background: var(--cream); color: var(--charcoal); }

/* --- Closing call to action ---------------------------------------------
   Two boxes of the same size, in the palette's 50% tints: 50% Magenta for
   hiring, 50% Bright Mint for fractional. Off-Black text on both (6.3:1 and
   13:1). */
.close__cta .btn {
  width: 17rem;
  max-width: 100%;
  justify-content: center;
  color: var(--charcoal);
}
.close__cta .btn--magenta { background: var(--bubblegum); }
.close__cta .btn--mint    { background: var(--teal-50); }
.close__cta .btn:hover    { background: var(--cream); color: var(--charcoal); }

/* --- Header route buttons -----------------------------------------------
   Same size, same colours as the closing call to action: 50% Magenta for
   hiring, 50% Bright Mint for fractional, Off-Black text. Sized in em so the
   two stay equal as the type scales. The mobile strip already splits 50/50. */
.masthead__tag {
  width: 13em;
  justify-content: center;
  color: var(--charcoal);
}
.masthead__tag--hiring     { background: var(--hot-pink); }   /* Bright Pink, as the hero headline */
.masthead__tag--fractional { background: var(--teal-50); }
@media (max-width: 44rem) {
  .masthead__tag { width: auto; }
}

/* --- Know the difference: Tan, with the cards dropped in -----------------
   Replaces the wood desk and the single fanned image. Each card has its own
   resting place (--x, --y as % of the deck, --r its tilt) and falls into it
   from above the section when .is-dealt is added (deck() in app.js). The
   cards land OVER the headline, as the fan did, so the words read through
   the gaps. */
.rdiff__stage {
  background: var(--tan);
  --chrome: var(--tan);
  --chrome-ink: var(--charcoal);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
  --chrome-img: none;
  --chrome-scrim: none;
}
.rdiff__title { color: var(--charcoal); }

.rdiff__deck {
  position: relative;
  z-index: 1;
  width: 100%;
  aspect-ratio: 1 / 0.9;
  pointer-events: none;
}
.rdiff__card {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 38%;
  height: auto;
  pointer-events: auto;
  filter: drop-shadow(0 0.6rem 1.2rem rgb(26 27 30 / 0.35));
  transform: rotate(var(--r));
}
/* Five cards, dealt in document order: the back first (underneath), then
   NED, CXO and FrED, then the Top Thumps card last, on top of the three. */
.rdiff__card--back { --x: 20%; --y: 3%;  --r: 14deg;  --start: 40deg;  --d: 0ms;   }
.rdiff__card--ned  { --x: 4%;  --y: 12%; --r: -12deg; --start: -32deg; --d: 220ms; }
.rdiff__card--cxo  { --x: 31%; --y: 2%;  --r: 5deg;   --start: 24deg;  --d: 440ms; }
.rdiff__card--fred { --x: 60%; --y: 18%; --r: -6deg;  --start: -20deg; --d: 660ms; }
.rdiff__card--top  { --x: 32%; --y: 22%; --r: -3deg;  --start: 18deg;  --d: 940ms; }

@media (min-width: 62rem) {
  /* Over the fixed canvas, as the fan was. */
  .rdiff__deck { position: absolute; inset: 0; aspect-ratio: auto; }
  .rdiff__card { width: 22%; }
  .rdiff__card--ned  { --x: 9%;  --y: 16%; }
  .rdiff__card--cxo  { --x: 39%; --y: 5%;  }
  .rdiff__card--fred { --x: 67%; --y: 22%; }
  .rdiff__card--back { --x: 24%; --y: 6%;  }
  .rdiff__card--top  { --x: 40%; --y: 24%; }
}

@media (prefers-reduced-motion: no-preference) {
  /* Waiting above the section, turned, until the deck is dealt. */
  .rdiff__deck:not(.is-dealt) .rdiff__card {
    transform: translateY(-160%) rotate(var(--start));
    opacity: 0;
  }
  .rdiff__deck.is-dealt .rdiff__card {
    transition: transform 900ms cubic-bezier(0.2, 1.25, 0.4, 1) var(--d),
                opacity 200ms linear var(--d);
  }
  @media (hover: hover) {
    .rdiff__deck.is-dealt .rdiff__card:hover {
      transform: rotate(var(--r)) translateY(-4%) scale(1.04);
      transition: transform var(--t-base) var(--ease-out);
      z-index: 2;
    }
  }
}

/* The header wears the colour of the band beneath it, and two bands (search
   and FrED) are the same 50% Magenta as the hiring button. A thin Off-Black
   edge keeps both route buttons visible on every band. */
.masthead__tag { box-shadow: inset 0 0 0 1.5px var(--charcoal); }

/* --- Character files: the opening screen on Tan --------------------------
   Only the intro ("Three ways to get senior experience…") is Tan; the
   character scenes after it stay on Off-Black. No pink in the brand palette
   reaches 3:1 on Tan, so both lines are Off-Black here. While the intro is on
   screen the scroll section reports a Tan chrome, so the header matches
   (introChrome() in app.js). */
.rs-intro { background: var(--tan); color: var(--charcoal); }
.rs-intro__line + .rs-intro__line i { color: var(--charcoal); }
.rs-intro .rs-hint { color: var(--charcoal-muted); }
.rs-intro .rs-hint::after { background: linear-gradient(var(--charcoal), transparent); }
.scrolly.is-intro {
  --chrome: var(--tan);
  --chrome-ink: var(--charcoal);
  --chrome-accent: var(--charcoal);
  --chrome-mark: url('/assets/brand/fractionals-lockup-ink.svg');
}

/* Intro paragraph in the live site's font: Neue Haas Grotesk Bold, about
   22px, sentence case. The live site sets this paragraph in Light. */
.rsearch__strap {
  font-family: 'Neue Haas Grotesk', var(--font-body);
  font-weight: 700;
  font-size: 1.4rem;
  line-height: 1.5;
  letter-spacing: normal;
  text-transform: none;
  color: var(--charcoal);
  max-width: 40rem;
}
/* "Firepower on Demand" set as the brand line: Anton capitals, as the hero. */
.rsearch__fod {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;      /* Anton is very tight; a little air keeps it sharp */
  font-size: 1.15em;
  font-synthesis: none;        /* never fake a bold from the bold paragraph */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: geometricPrecision;
}
.rsearch__fod sup {
  font-size: 0.5em;
  vertical-align: super;
  line-height: 0;
  margin-left: 0.08em;
}
/* Brand names that must keep their own casing inside capitalised lines. */
.keep-case { text-transform: none; }

/* "Meet FrED™": larger than the small kicker it replaced. On the wide canvas
   it still has to finish above the FrED lockup, which starts at 4.12cqw. */
.rfred__kicker { font-size: var(--step-2); line-height: 1.1; }
.rfred__kicker sup { font-size: 0.5em; vertical-align: super; line-height: 0; margin-left: 0.04em; }
@media (min-width: 62rem) {
  .rfred__kicker { top: 1.2cqw; font-size: 2.3cqw; line-height: 1; }
}

/* --- FrED's flame, moving --------------------------------------------------
   The flame is part of a still photograph, so a copy of the photo is laid
   exactly over it (fredFlame() in app.js), clipped to the flame, and that copy
   ripples with heat (#fred-heat), flickers and surges from the nozzle. The
   nozzle is at 72% / 62% of the photo; the flame runs up to the top right.
   Nothing is drawn under reduced motion. */
.rfred__canvas { position: relative; }
.rfred__flame {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  clip-path: polygon(66% 76%, 67% 52%, 74% 38%, 84% 24%, 93% 8%, 100% 2%,
                     100% 70%, 92% 70%, 82% 74%, 74% 80%);
  animation: flame-flicker 1.9s steps(1, end) infinite;
  animation-play-state: paused;
}
.rfred__flame img {
  display: block;
  width: 100%;
  height: 100%;
  filter: url(#fred-heat);
  transform-origin: 72% 62%;           /* the nozzle */
  animation: flame-surge 2.6s ease-in-out infinite;
  animation-play-state: paused;
}
/* A warm bloom over the flame that breathes with it. */
.rfred__flame::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 22% 26% at 86% 40%, rgb(255 214 140 / 0.55), transparent 70%);
  mix-blend-mode: screen;
  animation: flame-bloom 1.3s ease-in-out infinite alternate;
  animation-play-state: paused;
}
.rfred__flame.is-burning,
.rfred__flame.is-burning img,
.rfred__flame.is-burning::after { animation-play-state: running; }

@keyframes flame-flicker {
  0%   { filter: brightness(1)    saturate(1); }
  13%  { filter: brightness(1.12) saturate(1.08); }
  21%  { filter: brightness(0.96) saturate(1); }
  38%  { filter: brightness(1.08) saturate(1.05); }
  52%  { filter: brightness(1.18) saturate(1.1); }
  61%  { filter: brightness(0.98) saturate(1); }
  79%  { filter: brightness(1.1)  saturate(1.06); }
  90%  { filter: brightness(1.02) saturate(1); }
}
@keyframes flame-surge {
  0%, 100% { transform: scale(1); }
  30%      { transform: scale(1.035) rotate(-0.4deg); }
  55%      { transform: scale(0.99)  rotate(0.2deg); }
  75%      { transform: scale(1.025) rotate(-0.2deg); }
}
@keyframes flame-bloom {
  from { opacity: 0.35; }
  to   { opacity: 0.85; }
}
@media (min-width: 62rem) {
  /* Fade the copy the same way the photo is faded behind the body copy. */
  .rfred__flame img {
    -webkit-mask-image: linear-gradient(to bottom, #000 0 62%, rgba(0,0,0,0.24) 72%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 0 62%, rgba(0,0,0,0.24) 72%, transparent 100%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .rfred__flame { display: none; }
}

/* --- "See the full deck" ----------------------------------------------------
   A Top Thumps card tucked into an Off-Black button. On a phone it follows
   the copy; on the wide canvas it sits in the gap under FRACTIONAL EXECUTIVE
   DIRECTOR, above the two columns. */
.rfred__deck {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  margin-top: var(--s-3);
  padding: 0.55em 1.3em 0.55em 0.6em;
  background: var(--charcoal);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: transform var(--t-fast) var(--ease-out), background-color var(--t-fast) linear;
}
.rfred__deck img {
  width: 1.9em;
  height: auto;
  margin-block: -0.9em;          /* lets the card poke out of the button */
  transform: rotate(-8deg);
  filter: drop-shadow(0 0.2em 0.35em rgb(0 0 0 / 0.35));
  transition: transform var(--t-base) var(--ease-out);
}
.rfred__deck:hover { transform: translateY(-2px); background: var(--ink); }
.rfred__deck:hover img { transform: rotate(4deg) scale(1.12); }
.rfred__deck:focus-visible { outline: 2px solid var(--charcoal); outline-offset: 3px; }
@media (min-width: 62rem) {
  .rfred__deck { position: absolute; top: 35.4cqw; left: 42.67cqw; margin: 0; font-size: max(13px, 0.92cqw); }
}

/* No paint spill on the sign-up section. */
.start__paint { display: none; }
/* "Before you start" label in Tan, Off-Black text (7.8:1). */
.start .eyebrow--mint { background: var(--tan); color: var(--on-tan); }

/* --- The account checklist as a clipboard ---------------------------------
   Replaces the wavy pink/green stamp: a Tan sheet with an Off-Black clip at
   the top and tick boxes down the list. Off-Black on Tan is 7.8:1. The ::after
   is the clip (::before is taken by the hover bounce). */
.start__aside,
.start__aside--candidate {
  position: relative;
  border: 0;
  border-image: none;
  background: var(--tan);
  color: var(--charcoal);
  border-radius: 6px;
  padding: calc(var(--s-3) + 1.2rem) var(--s-3) var(--s-3);
  rotate: -1.5deg;
  box-shadow: 0 0 0 1px rgb(26 27 30 / 0.15);
  filter: drop-shadow(0 1.1rem 1.4rem rgb(0 0 0 / 0.4));
}
.start__aside::after {
  content: '';
  position: absolute;
  top: -1.1rem;
  left: 50%;
  translate: -50% 0;
  width: 7.5rem;
  height: 2.3rem;
  border-radius: 0.6rem 0.6rem 0.35rem 0.35rem;
  background:
    radial-gradient(circle at 50% 32%, var(--tan) 0 0.32rem, transparent 0.34rem),
    linear-gradient(var(--charcoal), var(--ink));
  box-shadow: inset 0 1px 0 rgb(240 240 239 / 0.25), 0 0.2rem 0.4rem rgb(0 0 0 / 0.35);
}
.start__kicker,
.start__meta,
.start__sso { color: var(--charcoal); }
.start__meta { border-top-color: rgb(26 27 30 / 0.3); }

/* Tick boxes: an empty square with a tick in it. */
.start__ready li { padding-left: 1.8em; }
.start__ready li::before {
  left: 0; top: 0.2em;
  width: 1.05em; height: 1.05em;
  border: 2px solid var(--charcoal);
  border-radius: 3px;
  transform: none;
  background: rgb(240 240 239 / 0.35);
}
.start__ready li::after {
  content: '';
  position: absolute;
  left: 0.3em; top: 0.38em;
  width: 0.55em; height: 0.3em;
  border-left: 2.5px solid var(--charcoal);
  border-bottom: 2.5px solid var(--charcoal);
  transform: rotate(-45deg);
}

.start__aside .btn { background: var(--charcoal); color: var(--cream); }
/* Hover: 50% Magenta for hiring; 50% Teal for fractional, matching the
   header's "I'm a fractional" button. */
.start__aside .btn:hover { background: var(--bubblegum); color: var(--charcoal); }
.start__aside--candidate .btn:hover { background: var(--teal-50); color: var(--charcoal); }
@media (min-width: 62rem) { .start__aside { margin-top: -4rem; } }

/* Contrast: Off-White on 50% Magenta is 2.4:1, under the 3:1 large-text
   minimum. Both big headings on the pink sections take Off-Black (6.3:1). */
.rfred__expand { color: var(--charcoal); }
/* "Find your firepower today": white, in the concept's original poster face,
   by choice. Off-White on 50% Magenta is 2.4:1, under the 3:1 large-text
   guideline. */
.rsearch__title { color: var(--cream); }
/* The intro's one break ("…we're a community. / We connect…") is meant at
   every width. */
.rsearch__strap br { display: inline; }

/* --- One pink (#FF87FF) everywhere: keep the text readable ---------------
   Pale pink cannot carry white text (about 2:1) or be read as small text on
   cream (1.8:1). So pink is always the ground, and the text on it Off-Black. */
.card__tag {
  color: var(--charcoal);
  background: var(--bubblegum);
  padding: 0.15em 0.45em;
  border-radius: 2px;
}
.btn--magenta:hover { background: var(--white); color: var(--charcoal); }
/* A gap after FIREPOWER before /READY TO, as the hero sets FIREPOWER above /ON. */
.rsearch__l1 { display: block; margin-bottom: 0.22em; }
/* Right-aligned like the hero: the lines sit flush right under FIREPOWER.
   fit-content keeps the block only as wide as its longest line, so it never
   reaches under the search box. */
.rsearch__title { width: fit-content; text-align: right; }
/* Nudged down a little. translate, so it moves the same at every width
   whether the heading is in the flow (phone) or placed (desktop). */
.rsearch__title { translate: 0 1.25rem; }

/* --- Know the difference: cards land BELOW the heading -------------------
   On the wide canvas the heading was placed absolutely and the cards dealt
   over it. Now the heading sits in the flow at its designed size and the
   deck is its own band underneath, sized to the cards, so there is no empty
   canvas left below them. */
@media (min-width: 62rem) {
  .rdiff__canvas { aspect-ratio: auto; }
  .rdiff__title {
    position: static;
    padding: 3.42cqw 3.30cqw 0 2.80cqw;
  }
  .rdiff__deck {
    position: relative;
    inset: auto;
    aspect-ratio: 100 / 44;
    margin-top: 1.5cqw;
  }
  .rdiff__stage { padding-bottom: 2cqw; }
  .rdiff__card--back { --x: 22%; --y: 4%;  }
  .rdiff__card--ned  { --x: 8%;  --y: 14%; }
  .rdiff__card--cxo  { --x: 38%; --y: 2%;  }
  .rdiff__card--fred { --x: 68%; --y: 16%; }
  .rdiff__card--top  { --x: 40%; --y: 20%; }
}
/* The intro screen set its lines in the middle of a full-height screen, which
   left a tall empty Tan band after the cards. Set them near the top instead,
   so they follow the cards closely. */
.rs-intro {
  justify-content: flex-start;
  padding-top: calc(var(--chrome-h) + clamp(1.5rem, 4vh, 3rem));
}
/* No seam between the cards and the intro screen. The two Tan bands met on a
   fractional pixel, and the Off-Black grounds behind them showed through as a
   hairline that read as a page break. Both grounds are Tan where they meet. */
.rdiff { background: var(--tan); }
.scrolly.is-intro { background: var(--tan); }
/* NED, CXO and FrED cards open their character file. */
.rdiff__card[data-go] { cursor: pointer; }
.rdiff__card[data-go]:focus-visible { outline: 3px solid var(--charcoal); outline-offset: 4px; }
/* The brand slash closing the intro's first line, with a little air before it. */
.rs-intro__slash { margin-left: 0.18em; margin-right: 0; }
.nowrap { white-space: nowrap; }
/* Intro set like the hero: right-aligned in the hero's poster face, with
   tighter lines. The block sits on the right of the screen. */
.rs-intro {
  align-items: flex-end;
  text-align: right;
  padding-right: var(--gutter);
}
.rs-intro__copy { line-height: 0.92; }
.rs-intro .rs-hint { align-items: flex-end; }
/* A line's space before /MEET THE HEAVY HITTERS. */
.rs-intro__line + .rs-intro__line { margin-top: 0.9em; }

/* Off-Black down arrow after MEET THE HEAVY HITTERS, bobbing to say "scroll". */
.rs-intro__arrow {
  display: inline-block;
  width: 0.55em;
  height: 0.75em;
  margin-left: 0.3em;
  vertical-align: -0.02em;
  color: var(--charcoal);
}
@media (prefers-reduced-motion: no-preference) {
  .rs-intro__arrow { animation: arrow-bob 1.4s ease-in-out infinite; }
  @keyframes arrow-bob {
    0%, 100% { transform: translateY(-0.08em); }
    50%      { transform: translateY(0.14em); }
  }
}
/* The intro, bigger. Off-Black on Tan (7.8:1). */
.rs-intro__copy { font-size: clamp(2.6rem, min(6.4vw, 10svh), 6rem); }

/* "Before you start" toggle: two equal boxes, and each route in its header
   colour when chosen (I'm hiring pink, I'm fractional 50% Teal). */
.toggle--start { display: inline-grid; grid-template-columns: 1fr 1fr; }
.toggle--start .toggle__btn { text-align: center; }
.toggle--start .toggle__btn[data-start="company"].is-on { background: var(--hot-pink); color: var(--charcoal); }
.toggle--start .toggle__btn[data-start="candidate"].is-on { background: var(--teal-50); color: var(--charcoal); }

/* Over the hero the header is see-through: the film plays behind it at full
   quality. It used to repaint a copy of the film into a canvas in the header,
   which came out soft (and was darkened), so the top of the video looked
   blurred. */
.rhero,
.rhero.is-playing { --chrome: transparent; --chrome-sample: none; --chrome-scrim: none; }
@media (max-width: 61.99rem) { .rhero { --chrome: transparent; } }

/* Phones, tablets and narrow windows: pin FIREPOWER ON DEMAND near the foot of
   the film, as the wide layout already does, instead of centring it (which
   left it floating mid-screen with the lower half of the film empty). */
@media (max-width: 61.99rem) {
  .rhero {
    align-content: end;
    min-height: 100svh;
    padding-bottom: max(clamp(2.5rem, 7vw, 4.5rem), env(safe-area-inset-bottom, 0px));
  }
}

/* FrED: the section grows to fit its copy. The canvas had a fixed shape
   (534.6 / 958.16) with the two columns placed absolutely inside it, so on
   windows narrower than about 1300px the longer copy ran past the bottom and
   was clipped. Now the columns sit in the flow at the same position, and a
   float keeps the canvas at least its designed proportion, so it is never
   shorter than the artwork and never shorter than the text. */
@media (min-width: 62rem) {
  .rfred__canvas { aspect-ratio: auto; display: flow-root; }
  .rfred__canvas::before {
    content: '';
    float: left;
    width: 1px;
    margin-left: -1px;
    padding-bottom: 55.794%;   /* 534.6 / 958.16 */
  }
  .rfred__cols {
    position: relative;
    top: auto; left: auto;
    margin: 41.04cqw 0 2.5cqw 51.84cqw;
  }
}

/* --- The film under "Who do you need in the room?" ------------------------ */
.close__film {
  position: relative;
  width: min(100%, 64rem);
  aspect-ratio: 16 / 9;
  max-width: 100%;
  background: var(--ink) center / cover no-repeat;
  overflow: hidden;
}
.close__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; }
.close__play {
  position: absolute;
  top: 50%; left: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: clamp(4.5rem, 9vw, 7rem);
  aspect-ratio: 1;
  border-radius: 50%;
  background: rgb(240 240 239 / 0.2);
  border: 2px solid rgb(240 240 239 / 0.7);
  color: var(--cream);
  backdrop-filter: blur(4px);
  transition: background-color var(--t-fast) linear, scale var(--t-fast) var(--ease-out), color var(--t-fast) linear;
}
.close__play svg { width: 45%; margin-left: 8%; }
.close__play:hover { background: var(--bubblegum); border-color: var(--bubblegum); color: var(--charcoal); scale: 1.08; }
.close__play:focus-visible { outline: 3px solid var(--cream); outline-offset: 4px; }
.close__film.is-playing .close__play { display: none; }

/* NED in Tan (CXO teal, FrED pink). "All three" takes Off-White, the colour
   NED used to have, so the four still read apart. Tan on Off-Black is 7.8:1. */
.scrolly [data-who="ned"] { --rs-c: var(--tan); }
.scrolly [data-who="all"] { --rs-c: var(--cream); }

/* "Leads here" always sits under the measure's name, never beside it, so every
   row reads the same whatever the screen width. */
.rs-lab { flex-direction: column; align-items: flex-start; gap: 0.3rem; }
/* FRactional EXecutive Director: the letters that spell FrED in white. */
.rfred__ini { color: var(--cream); }

/* "Before you start" and "News & insights" labels, a size up. */
.start .eyebrow { font-size: calc(var(--micro-size) * 1.35); padding: 0.5em 1em; }
.insights .ribbon { font-size: calc(var(--micro-size) * 1.35); padding: 0.5em 1em; }

/* Googly eyes perched on the top edge of News & insights: half over the black
   section above, half over the Tan. */
.insights { position: relative; overflow: visible; }
.insights__eyes {
  --eye: clamp(3.5rem, 7vw, 6.5rem);
  position: absolute;
  z-index: 2;
  top: 0;
  left: 50%;
  translate: -50% -55%;
  margin: 0;
  pointer-events: none;
}

/* Bigger pupil travel: up to 55% of the pupil's own width, which keeps it just
   inside the white of the eye (the original 26% barely moved). */
.eye i { transform: translate(-50%, -50%) translate(calc(var(--px, 0) * 55%), calc(var(--py, 0.25) * 55%)); }

/* News & insights: the email sign-up sits bottom right, under the cards, with
   "More news and insights" on the left of the same row. */
.insights__head { margin-bottom: var(--s-4); }
.insights__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-4);
}
.insights__foot .insights__more { margin-top: 0; }
.insights__foot .signup { margin-left: auto; width: min(100%, 34rem); }
/* A wider gap before the slash in "advisors   /we call it". */
.rsearch__slash { margin-left: 0.45em; }

/* The search example ("Search/ I'm looking for a CFO…") is sized by
   fitSearch() in app.js so it always fits the box. Only the placeholder
   shrinks; typed text stays at 16px+ so iOS does not zoom on focus. */
.seek__input::placeholder { font-size: var(--ph-size, inherit); }

/* FrED copy: was 14px regular over the faded photo, which read soft. A size
   up and a touch heavier, with normal (not thinned) smoothing. */
.rfred__cols p {
  font-size: max(16px, 1.02cqw);
  font-weight: 500;
  line-height: 1.5;
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
}

/* Short phones (about 360 x 740): with the larger minimum text size the
   character files ran up to 68px past the screen. A smaller card and a
   tighter foot give that room back. */
@media (max-width: 44rem) and (max-height: 780px) {
  .rs-card { width: min(26vw, 15svh); }
  .rs-solo { padding-bottom: 3.25rem; }
  .rs-st { padding-block: 0.25rem; }
  .rs-desc { margin-top: 0.6rem; }
  .rs-stats { margin-top: 0.4rem; }
}

/* FrED™ in the character file: the ™ sits at the top of the D, level with the
   cap height, instead of floating at mid-height. */
.rs-name sup {
  vertical-align: top;
  position: relative;
  top: 0.08em;
  line-height: 1;
  margin-left: 0.04em;
}

/* Footer FIREPOWER ON DEMAND™: a small ™ at the top of the D. */
.foot__tm {
  font-size: 0.4em;
  vertical-align: top;
  position: relative;
  top: 0.12em;
  line-height: 1;
  margin-left: 0.05em;
}

/* Footer bottom strip: LinkedIn, copyright, Privacy & Terms (as the live site). */
.foot__bar {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
}
.foot__in { display: inline-flex; color: var(--cream-muted); transition: color var(--t-fast) linear; }
.foot__in:hover { color: var(--teal-50); }
.foot__copy { margin: 0; font-size: var(--step--1); color: var(--cream-muted); }
.foot__copy a { color: var(--cream); text-decoration: underline; text-underline-offset: 0.2em; }
.foot__copy a:hover { color: var(--teal-50); }
.foot__in:focus-visible, .foot__copy a:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }

/* Menu route buttons: the same pair as everywhere else. Two equal boxes,
   pink for hiring and 50% Teal for fractional, Off-Black text. */
.menu__cta {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  width: min(100%, 16rem);
  padding: 0.75em 1.2em;
  font-size: var(--step-0) !important;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--charcoal) !important;
  box-shadow: inset 0 0 0 1.5px var(--charcoal);
}
.menu__cta--hiring     { background: var(--hot-pink); }
.menu__cta--fractional { background: var(--teal-50); }
.menu__cta:hover { color: var(--charcoal) !important; filter: brightness(1.08); }

/* ==========================================================================
   Port into apps/www
   ========================================================================== */

/* The root layout puts Tailwind's `font-sans` on <body>; as a class it outranks
   base.css's `body { font-family }`. Restore the design's face inside its own
   scope rather than touching globals.css. */
.home-root { font-family: var(--font-body); }

/* Anonymous match preview under the search box (seek() in app.js). */
.seek__carousel { margin-bottom: var(--s-2); }
.seek__results { display: grid; }
/* Every card in the same cell: the list is as tall as the tallest card. */
.seek__results > .seek__card { grid-area: 1 / 1; }
.seek__carousel .seek__card:not(.is-active) { visibility: hidden; }
.seek__carousel .seek__results > .seek__card:only-child { visibility: visible; }
.seek__nav {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  margin-top: var(--s-1);
}
.seek__step {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 0;
  background: var(--charcoal);
  color: var(--cream);
  font-size: 1.1rem;
  cursor: pointer;
}
.seek__step:hover { background: var(--magenta); }
.seek__step:focus-visible, .seek__dot:focus-visible { outline: 2px solid var(--charcoal); outline-offset: 2px; }
.seek__dots { display: flex; gap: 0.4rem; }
.seek__dot {
  width: 0.65rem;
  height: 0.65rem;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--charcoal);
  background: transparent;
  cursor: pointer;
}
.seek__dot[aria-current="true"] { background: var(--charcoal); }
.seek__count { color: var(--on-bubblegum, var(--charcoal)); text-transform: none; letter-spacing: normal; margin-right: auto; }
.seek__card {
  display: grid;
  gap: 0.35rem;
  align-content: start;
  padding: var(--s-2) var(--s-3);
  background: var(--cream);
  color: var(--charcoal);
  border-radius: 1.1rem;
}
.seek__card { position: relative; cursor: pointer; }
.seek__card:focus-visible { outline: 2px solid var(--charcoal); outline-offset: 3px; }
.seek__reveal {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--s-2);
  border-radius: inherit;
  background: color-mix(in srgb, var(--cream) 82%, transparent);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms ease, visibility 0s linear 160ms;
}
.seek__card.is-revealed .seek__reveal { opacity: 1; visibility: visible; transition: opacity 160ms ease; }
@media (prefers-reduced-motion: reduce) { .seek__reveal { transition: none; } }
.seek__role { font-size: var(--step-1); font-weight: 700; line-height: 1.15; }
.seek__meta { color: var(--charcoal-muted); text-transform: none; letter-spacing: normal; }
.seek__hero {
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--charcoal);
  /* The API sends up to 600 characters; show what the card has room for. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 6;
  line-clamp: 6;
  overflow: hidden;
}
@media (min-width: 62rem) {
  .seek__hero { -webkit-line-clamp: 5; line-clamp: 5; }
}
.seek__label { color: var(--charcoal-muted); text-transform: uppercase; letter-spacing: 0.04em; margin-top: 0.35rem; }
.seek__tags { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.25rem; }
.seek__tag {
  font-size: var(--step--1);
  line-height: 1;
  padding: 0.35em 0.7em;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--charcoal) 35%, transparent);
}
.seek__hit.seek__loading { opacity: 0.7; }
.seek__cta { margin-top: var(--s-1); }

/* Menu: the rest of the site, below the primary links. Body type, not display,
   so eleven destinations still fit a laptop screen. Overrides .menu__inner a. */
.menu__more {
  list-style: none;
  margin: var(--s-2) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, auto));
  justify-content: center;
  gap: var(--s-1) var(--s-3);
}
.menu__more a {
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.3;
  text-transform: none;
  color: var(--cream-muted);
}
.menu__more a:hover { color: var(--bubblegum); }

/* Search results, desktop. The canvas is a fixed aspect ratio with every child
   absolutely placed, so three result cards pinned at top: 33cqw ran ~200px
   into the next section. The pill moves up to 18cqw (clear of the strap, which
   reaches 16.8cqw at 1280px wide), and the results go back into normal flow,
   held in place by padding rather than offsets, so the canvas grows to fit
   them. Static, not relative: positioned siblings (the pill) then paint above
   the padding, so it never swallows a click. */
@media (min-width: 62rem) {
  .rsearch__canvas > .seek { top: 18cqw; }
  .rsearch__canvas > .seek__out {
    position: static;
    top: auto;
    left: auto;
    width: 47.18cqw;
    margin: 0 0 0 47.71cqw;
    padding: 26.2cqw 0 4cqw;
  }
}

/* The www site's global styles reach into the homepage. Undo the four places
   where they changed the signed-off design.
   - Tailwind's reset sizes every heading at body size and normal weight. The
     design relied on the browser defaults: 2em for the phone hero (desktop
     sets its own size in cqw) and bold for the closing line.
   - globals.css sets h1, h2 in Grouch BT, which caught the footer headings.
   - Tailwind Typography owns the `.prose` class, so the FrED copy turned grey
     and picked up its paragraph margins. */
@media (max-width: 61.99rem) {
  .home-root .rhero__title { font-size: 2em; }
}
.home-root .close__strap { font-weight: 700; }
.home-root .foot__h { font-family: var(--font-body); }
.home-root .prose { color: inherit; max-width: var(--measure); }
.home-root .prose p { margin: 0; }
.home-root .prose p + p { margin-top: 1em; }
