/* Generated by .build/assemble.py: .build/sections/*.css in page order (homepage only; loaded after site.css).
   Edit the sources and re-run it; edits here are overwritten. */

/* --------------------------------------------------------------------------
   Section 01 "top" (#top)  source: .build/sections/01-top.css
   -------------------------------------------------------------------------- */
/* ---------- 01 Hero #top ----------
   One grid holds the stage frame and the copy. Desktop (>= 900px): the stage spans the whole grid and
   the copy sits over it (voice pill and H1 bottom-left, side column bottom-right). Mobile: the stage is
   ~78svh with the H1 over its bottom; the voice pill and the side copy follow on the dark ground.
   DOM order is H1, voice, side: on desktop the pill sits above the H1 in the left column and the side
   column is read after it; on mobile the pill comes first under the frame. Tab order follows the
   visual order at every size (A11Y-09).
   Columns: the copy lines up with the 1320px container at wide screens (DV-08) and never enters the
   landscape safe areas (M5). */
.s-top {
  /* 100% resolves against the grid container in grid-template-columns: the H1 and the side column
     share the nav's and the sections' container edges once the viewport is wider than the container. */
  --px: max(clamp(24px, 3.4vw, 48px), calc((100% - var(--container)) / 2 - var(--frame-inset)));
  --col-l: max(calc(var(--frame-inset) + var(--px)), calc(var(--safe-left) + 8px));
  --col-r: max(calc(var(--frame-inset) + var(--px)), calc(var(--safe-right) + 8px));
  --pb: clamp(28px, 3.4vw, 48px);
  --side: 360px;
  --gap: clamp(32px, 4vw, 72px);
  --top-space: calc(var(--nav-space) + 24px);
  position: relative;
  display: grid;
  grid-template-columns:
    var(--col-l)
    minmax(0, 1fr)
    var(--gap)
    minmax(0, var(--side))
    var(--col-r);
  grid-template-rows: minmax(var(--top-space), 1fr) auto auto var(--pb);
  /* The first screen is the hero at every height (D6: the old 1000px cap left an empty band under it on
     tall monitors). border-box, so the 10px frame padding is inside: the stage ends 10px above the fold. */
  min-height: 100svh;
  padding-block: var(--frame-inset);
}

/* Stage frame: spans the grid, so it grows with the copy and never crops the H1. */
.s-top__stage {
  grid-column: 1 / -1;
  grid-row: 1 / -1;
}
.s-top__media {
  /* her face in the desktop files (x 42%, y 42%); the push-in grows from it */
  transform-origin: 42% 42%;
  will-change: transform;
}
.s-top__poster {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.s-top__video {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur-7) var(--ease-out);
}
.s-top__video[data-media-state="live"] {
  opacity: 1;
}
/* Scroll dim (inline opacity from JS) and the listening hush share the plain ink ground. */
.s-top__dim,
.s-top__hush {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-color: var(--ink-0);
  opacity: 0;
  pointer-events: none;
}
.s-top__hush {
  transition: opacity var(--dur-4) var(--ease-out);
}
.s-top.is-speaking .s-top__hush {
  opacity: 0.32;
  transition-duration: var(--dur-6);
}
.s-top__scrim {
  height: 58%;
  background: linear-gradient(to top, rgba(10, 9, 8, 0.74), rgba(10, 9, 8, 0.4) 42%, rgba(10, 9, 8, 0));
}
/* Desktop safety net under the side column (DV-03): the media keeps the speaker at ~42% of the frame,
   so the column already sits over dark stage; this soft pool keeps the lede calm if a gesture reaches
   toward it on narrower laptops. Under the grain, so it cannot band. */
@media (min-width: 900px) {
  /* Narrower laptops crop more of the 16:9 files: take the extra crop from the left, so the speaker
     moves toward the H1 and her gestures stay clear of the side column (about 33px at 1024, 0 at 16:9). */
  .s-top__poster,
  .s-top__video {
    object-position: 60% 50%;
  }
  .s-top__stage::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: radial-gradient(calc(var(--side) * 1.25) 72% at calc(100% - var(--px) - var(--side) / 2) 94%,
      rgba(10, 9, 8, 0.52), rgba(10, 9, 8, 0.3) 52%, rgba(10, 9, 8, 0) 100%);
    pointer-events: none;
  }
}

/* Copy layer */
.s-top__title,
.s-top__side,
.s-top__voice,
.s-top__pause {
  position: relative;
  z-index: 3;
}
.s-top__title {
  grid-column: 2;
  grid-row: 3;
  align-self: end;
  max-width: 6.4em;
  font-size: min(var(--display-xl), 13.2svh);
  color: var(--fg-dark);
  text-shadow: 0 2px 40px rgba(10, 9, 8, 0.35);
  /* Optical: the display face's side bearing, so the stem of "T" sits on the pill's edge. */
  margin-left: -0.035em;
}
.s-top__side {
  grid-column: 4;
  grid-row: 2 / 4;
  align-self: end;
  display: grid;
  justify-items: start;
  gap: 0;
}
.s-top__lede {
  max-width: 34ch;
  font-size: var(--text-body);
  line-height: 1.55;
  color: rgba(243, 239, 233, 0.86);
  text-wrap: pretty;
}
.s-top__cta {
  margin-top: 24px;
}
.s-top__micro {
  margin-top: 16px;
  color: rgba(243, 239, 233, 0.62);
}

/* Voice: the "Hear your AI coach" pill with the coach's words under it */
.s-top__voice {
  grid-column: 2;
  grid-row: 2;
  align-self: end;
  display: grid;
  justify-items: start;
  margin-bottom: clamp(10px, 1.6vh, 18px);
}
.s-top__pill .sound-pill__meta {
  color: rgba(243, 239, 233, 0.62);
}
/* Adam's portrait in place of the white play disc (2026-10-09, lights up): 36px, the app's round crop with
   a soft shadow only (the app's rule: never a ring or hairline around a coach). The play/stop glyph
   rides on a small badge at its lower right, so the pill still reads as play, then stop. */
.s-top__pill {
  padding-left: 4px;
}
.s-top__pill .sound-pill__bar {
  left: 50px;
}
.s-top__pill .s-top__icon {
  position: relative;
  width: 36px;
  height: 36px;
  background-color: transparent;
  overflow: visible;
}
.s-top__face {
  display: block;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 1px 2px rgba(10, 9, 8, 0.45), 0 3px 10px rgba(10, 9, 8, 0.35);
}
.s-top__badge {
  position: absolute;
  right: -3px;
  bottom: -2px;
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background-color: var(--fg-dark);
  color: var(--ink-0);
  box-shadow: 0 1px 3px rgba(10, 9, 8, 0.5);
}
.s-top__pill .s-top__badge svg {
  width: 9px;
  height: 9px;
}
/* The coach's words in the brand serif, the voice the verdict speaks in further down.
   The wrapper is an accordion on phones (closed until the first play); always open on desktop. */
.s-top__subs-wrap {
  display: grid;
  grid-template-rows: 1fr;
}
.s-top__subs {
  min-height: 0;
  display: grid;
  margin-top: 14px;
  font-family: var(--font-display);
  font-size: clamp(20px, 1.75vw, 26px);
  line-height: 1.25;
  font-weight: 500;
  color: var(--fg-dark);
  text-shadow: 0 1px 16px rgba(10, 9, 8, 0.6);
}
.s-top__chunk {
  grid-area: 1 / 1;
  white-space: nowrap;
  min-height: 1.25em;
}
html:not(.js) .s-top__voice,
html:not(.js) .s-top__pause {
  display: none;
}
/* Streaming text: words resolve through a soft 1px blur; spoken lines lift away as the next begins. */
html.js .s-top__w {
  opacity: 0;
  filter: blur(1px);
  transition:
    opacity var(--dur-3) var(--ease-out),
    filter var(--dur-3) var(--ease-out);
}
html.js .s-top__w.is-in {
  opacity: 1;
  filter: blur(0);
  /* Lets the previous line clear first; the script leads each word by the same amount. */
  transition-delay: 120ms;
}
html.js .s-top__chunk {
  transition:
    opacity 180ms var(--ease-out),
    transform 180ms var(--ease-out),
    filter 180ms var(--ease-out);
}
html.js .s-top__chunk.is-past {
  opacity: 0;
  transform: translateY(-0.4em);
  filter: blur(2px);
}
html.js .s-top__subs.is-clearing .s-top__chunk {
  opacity: 0;
  transition-duration: var(--dur-2);
}
html.js .s-top__subs.is-reset .s-top__w,
html.js .s-top__subs.is-reset .s-top__chunk {
  transition: none;
}
html.still .s-top__w,
html.still .s-top__chunk {
  transition: none;
  filter: none;
}
html.still .s-top__chunk.is-past {
  transform: none;
}

/* Pause control for the background loop: a small glass disc in the stage's bottom-right corner. */
.s-top__pause {
  grid-column: 1 / -1;
  grid-row: 1 / -1;
  align-self: end;
  justify-self: end;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0 max(calc(var(--frame-inset) + 12px), var(--safe-right)) 12px 0;
  border-radius: 50%;
  color: var(--fg-dark);
}
.s-top__pause-disc {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: rgba(20, 18, 16, 0.5);
  box-shadow: inset 0 0 0 1px rgba(245, 238, 228, 0.14);
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
  backdrop-filter: blur(12px) saturate(1.3);
  transition:
    background-color var(--dur-2) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
.s-top__pause svg {
  grid-area: 1 / 1;
  width: 12px;
  height: 12px;
  fill: currentColor;
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-out);
}
.s-top__pause .i-play {
  opacity: 0;
  transform: translateX(1px) scale(0.6);
}
.s-top__pause[aria-pressed="true"] .i-pause {
  opacity: 0;
  transform: scale(0.6);
}
.s-top__pause[aria-pressed="true"] .i-play {
  opacity: 1;
  transform: translateX(1px);
}
@media (hover: hover) {
  .s-top__pause:hover .s-top__pause-disc {
    background-color: rgba(34, 31, 28, 0.66);
  }
}
.s-top__pause:active .s-top__pause-disc {
  transform: scale(0.94);
}
.s-top__pause:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

/* Entrance (Texts reveal, 500ms): side copy and the voice pill rise in after first paint.
   The H1 and the poster are never hidden. Pure CSS, so nothing stays hidden if a script fails. */
@keyframes s-top-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
    filter: blur(3px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}
@keyframes s-top-rise-plain {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes s-top-fade {
  from {
    opacity: 0;
  }
}
/* .is-intro-done (top.js, after the entrance) retires these, so turning Pause motion off later
   does not replay the entrance. */
@media (prefers-reduced-motion: no-preference) {
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__lede,
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__micro {
    animation: s-top-rise var(--dur-4) var(--ease-out) both;
  }
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__cta,
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__voice {
    animation: s-top-rise-plain var(--dur-4) var(--ease-out) both;
  }
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__voice {
    animation-delay: 140ms;
  }
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__lede {
    animation-delay: 200ms;
  }
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__cta {
    animation-delay: 260ms;
  }
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__micro {
    animation-delay: 320ms;
  }
  html.js:not(.still) .s-top:not(.is-intro-done) .s-top__pause {
    animation: s-top-fade var(--dur-4) var(--ease-out) 700ms both;
  }
}

/* Mobile and portrait tablets: stage ~78svh with the H1 over its bottom; the rest on the dark ground. */
@media (max-width: 899px) {
  .s-top {
    --px: 16px;
    --pb: 22px;
    grid-template-columns: var(--col-l) minmax(0, 1fr) var(--col-r);
    grid-template-rows: auto auto auto;
    min-height: 0;
    /* keeps the orange CTA and the orange card below apart, so one of them leads the view */
    padding-bottom: clamp(40px, 8svh, 72px);
  }
  .s-top__stage {
    grid-column: 1 / -1;
    grid-row: 1;
    min-height: max(78svh, 320px);
  }
  .s-top__scrim {
    height: 64%;
    background: linear-gradient(to top, rgba(10, 9, 8, 0.86), rgba(10, 9, 8, 0.5) 40%, rgba(10, 9, 8, 0));
  }
  .s-top__title {
    grid-column: 2;
    grid-row: 1;
    align-self: end;
    padding: var(--top-space) 0 var(--pb);
    font-size: var(--display-xl);
  }
  /* The portrait files keep their two spotlight lamps at the very top: the media box reaches 7% above
     the frame (clipped by it), so no bright dot sits in the nav line next to the brand (DV-11). */
  .s-top__media {
    top: -7%;
    transform-origin: 40% 46%;
  }
  /* The pill comes first under the frame (the DOM order), then the side copy. */
  .s-top__voice {
    grid-column: 2;
    grid-row: 2;
    margin-bottom: 0;
    padding-top: 20px;
  }
  .s-top__side {
    grid-column: 2;
    grid-row: 3;
    padding-top: 22px;
  }
  .s-top__lede {
    max-width: 40ch;
  }
  /* The words open a two-line space under the pill on the first tap (an accordion the visitor asks
     for, so nothing moves by itself) and keep it, so the copy below never jumps back. */
  html.js .s-top__subs-wrap {
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--dur-3) var(--ease-out);
  }
  html.js .s-top__voice.is-open .s-top__subs-wrap {
    grid-template-rows: 1fr;
  }
  /* No margin or padding on the clipped item itself, so the closed track is truly 0 high. */
  .s-top__subs {
    margin-top: 0;
    overflow: hidden;
    font-size: 22px;
  }
  .s-top__chunk {
    min-height: calc(2.5em + 12px);
    padding-top: 12px;
    white-space: normal;
    align-self: start;
  }
  .s-top__pause {
    grid-column: 1 / -1;
    grid-row: 1;
    margin: 0 max(calc(var(--frame-inset) + 8px), var(--safe-right)) 10px 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .s-top__media {
    transform: none !important;
    will-change: auto;
  }
  .s-top__video,
  .s-top__hush,
  .s-top__subs-wrap,
  .s-top__w,
  .s-top__chunk,
  .s-top__pause svg {
    transition: none;
  }
}
html.reduced .s-top__media {
  transform: none !important;
}
html.still .s-top__subs-wrap {
  transition: none;
}

/* --------------------------------------------------------------------------
   Section 02 "hears" (#hears)  source: .build/sections/02-hears.css
   -------------------------------------------------------------------------- */
/* ==========================================================================
   02 How it works (.s-hears): The Take's look with The Transcript's mechanics
   (2026-10-08 rework; lab: .build/hiw-lab/combined/)
   02a: the orange statement card with the six-column wipe (shortened).
   02b: one warm room (#1D1A17, baked vignette, grain, the frame inset and
        radius), id="verdict" on the verdict:
        - Adam's Coach Medallion, big, standing on the pool plate as a floor
          light (no card, ring or halo). Wide screens: the disc in the left
          column, sticky beside the lines. Phones: a medium disc in a band
          under the nav, sticky above the lines (the band carries an exact copy
          of the house lights, so lines pass under it without a seam).
        - the lines on the right: the "How it works" eyebrow over the
          headline, Adam's question, your answer with its two strikes and
          the "2 softeners" count, his status line, his verdict, then your
          second take ("You, again"): the softeners struck, cut out of the
          line, and the sentence said firm.
        - the proof: the app's verdict screen on the phone (under Adam's
          column) beside its title and one lead paragraph, cropped by the
          room's bottom edge below the screen's buttons.
   Lights up (2026-10-09): the sprint-data story of the App Store set.
   Native scroll. Each line plays once on its own short timer when it reaches
   the screen (hears.js); scroll never scrubs or pins anything.
   The markup is the composed still (no JS, reduced motion, Pause motion,
   short screens). .is-motion (set by hears.js only when motion runs) holds
   the start states; the beats add .is-on / .is-struck / data-st as they play.
   ========================================================================== */

.s-hears {
  /* the quieter half of the two-tone statement: the card's ink at reduced strength (3.4:1 on #FF5C00) */
  --hears-on-orange-quiet: #6D2C07;
  --hr-room: #1D1A17;                              /* the lit room */
  --hr-soft: cubic-bezier(0.16, 0.84, 0.24, 1);    /* the app's verdict settle curve */
  --hr-max: 1240px;                                /* the room's content width */
  --med: clamp(160px, 21svh, 210px);               /* Medallion canvas (the disc is 0.7 of it) */
  --hr-colgap: clamp(28px, 5vw, 88px);
  --hr-q: 22px;                                    /* Adam's question */
  --hr-a: 19px;                                    /* your answer (one short sentence) */
  --hr-a2: var(--hr-a);                            /* your second take (larger from 600px up: the payoff) */
  /* Your answer's kept words once Adam has listened back (the marks stay at full strength). 0.7, not
     less: scrolled back up, the answer reads over the floor light at 4.5:1 without the shade. */
  --hr-dim: 0.7;
  /* The small lines that pass through the floor light (the listen-back status): --fg-dark-2 lifted 40% toward --fg-dark, so they keep 4.5:1 over the light without the
     shade (--fg-2 falls to about 3.5:1 where the composed still's pool lifts the ground). */
  --hr-small: #C8C2BA;
  --hr-v: 30px;                                    /* Adam's verdict */
  --hr-pt: 22px;                                   /* the proof title: the question's size on phones, so the verdict stays the one focal block */
  /* Small text in the room keeps a soft shade of the room's colour around its glyphs. It cannot be
     seen on the dark ground; where a line passes over the floor light it keeps the ground right
     behind the letters dark enough to read. */
  --hr-shade: 0 0 2px #1D1A17, 0 0 6px rgba(29, 26, 23, 0.85), 0 0 12px rgba(29, 26, 23, 0.5);
  --hr-pw: min(220px, calc(100vw - 150px));        /* the proof phone */
  /* The proof phone fades into the room's floor over its last stretch, so the room's bottom edge
     stays one dark line against the paper. 0.17 of the device width: with the 0.95 cut the fade
     starts right under the screen's "Work on it with Adam" pill (y 1087 of the 1238px screen, 1.717
     device widths from the top; the cut is at 1.888) and "Next question" goes soft. */
  --hr-fade: calc(var(--hr-pw) * 0.17);
  /* Share of the device above the room's bottom edge: the cut lands in the white between "Next
     question" and the home indicator (screen 0.929 to 0.985 of a 600 x 1238 screen in a 3.6% bezel:
     device height 1.987 x width; 0.95 of the device is 0.967 of the screen) */
  --hr-cut: 0.95;
  /* Composed still (default): tight gaps so the end frame reads as one picture */
  --g-head: 24px;
  --g-qa: 26px;
  --g-at: 0px;
  --g-tv: 30px;
  --g-again: 26px;
  --g-proof: clamp(64px, 14svh, 160px);
  position: relative;
  padding-top: var(--frame-inset);
  padding-bottom: clamp(24px, 4vh, 48px);
  /* "How it works" lands with the orange card 40px from the top (D4). */
  scroll-margin-top: -52px;
}
/* The nav's bottom edge for hears.js (it reads this probe's height instead of querying the nav) */
.s-hears__navprobe {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: var(--nav-space);
  visibility: hidden;
  pointer-events: none;
}


/* ---------- 02a: the orange statement card ---------- */
.s-hears__card {
  position: relative;
  isolation: isolate;
  display: flex;
  min-height: 46svh;
  margin-inline: var(--frame-inset);
  border-radius: var(--frame-radius);
  overflow: hidden;
  background-color: var(--orange);
  color: var(--on-orange);
}
.s-hears__cols {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  pointer-events: none;
}
.s-hears__cols > span {
  --c: 0;
  display: block;
  margin-right: -1px;
  background-color: var(--orange);
  /* the column guides (Performance Lab) stay after the wipe */
  box-shadow: inset -1px 0 0 rgba(20, 15, 11, 0.075);
  transform-origin: 50% 0;
}
.s-hears__cols > span:nth-child(2) { --c: 1; }
.s-hears__cols > span:nth-child(3) { --c: 2; }
.s-hears__cols > span:nth-child(4) { --c: 3; }
.s-hears__cols > span:nth-child(5) { --c: 4; }
.s-hears__cols > span:nth-child(6) {
  --c: 5;
  margin-right: 0;
  box-shadow: none;
}
.s-hears__card-in {
  --card-pad: clamp(22px, 3.6vw, 52px);
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: var(--card-pad);
  /* Landscape phones: the copy stays 16px inside the safe area */
  padding-left: max(var(--card-pad), calc(var(--safe-left) - var(--frame-inset) + 16px));
  padding-right: max(var(--card-pad), calc(var(--safe-right) - var(--frame-inset) + 16px));
}
.s-hears__statement {
  margin-top: auto;
  margin-bottom: clamp(0px, 5svh, 72px);
  padding-top: 32px;
  color: var(--on-orange);
}
.s-hears__sl {
  display: block;
}
.s-hears__sl--quiet {
  color: var(--hears-on-orange-quiet);
}
@media (max-width: 899px) {
  .s-hears__card {
    min-height: 38svh;
  }
  .s-hears__card-in {
    justify-content: center;
  }
  .s-hears__statement {
    margin-top: 0;
    margin-bottom: 0;
    padding-top: 0;
  }
}

/* Wipe: six columns drop in 50ms apart, then the line resolves. The start states apply only once
   hears.js runs (.is-live), so the card shows its final state if the script fails. */
html.js:not(.reduced) .s-hears.is-live .s-hears__card:not(.is-filled) {
  background-color: var(--ink-1);
}
html.js:not(.reduced) .s-hears.is-live .s-hears__cols > span {
  transform: scaleY(0);
  transition: transform 800ms var(--ease-in-out) calc(var(--c) * 50ms);
}
html.js:not(.reduced) .s-hears.is-live .s-hears__card.is-wiped .s-hears__cols > span {
  transform: scaleY(1);
}
html.js:not(.reduced) .s-hears.is-live .s-hears__sl {
  --d: 520ms;
  opacity: 0;
  transform: translateY(0.12em);
  filter: blur(8px);
  transition:
    opacity 900ms var(--ease-out) var(--d),
    transform 900ms var(--ease-out) var(--d),
    filter 900ms var(--ease-out) var(--d);
}
html.js:not(.reduced) .s-hears.is-live .s-hears__sl + .s-hears__sl {
  --d: 600ms;
}
html.js:not(.reduced) .s-hears.is-live .s-hears__card.is-wiped .s-hears__sl {
  opacity: 1;
  transform: none;
  filter: none;
}

/* ==========================================================================
   02b: the room
   ========================================================================== */
.s-hears__room {
  position: relative;
  isolation: isolate;
  margin: var(--frame-inset) var(--frame-inset) 0;
  border-radius: var(--frame-radius);
  background-color: var(--hr-room);
  color: var(--fg);
  overflow: hidden;
  overflow: clip;   /* clip, so the lights and the disc can stay sticky inside; also crops the phone */
}
.s-hears__room::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 6;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(245, 238, 228, 0.06);
  pointer-events: none;
}

/* House lights: an absolute layer the height of the room, with a sticky viewport-sized child.
   up = the room arrives lit; half = the conversation and the proof; down = the verdict. */
.s-hears__lights {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.s-hears__lights-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
}
.s-hears__ambient,
.s-hears__vignette {
  position: absolute;
  max-width: none;
  transition-property: opacity;
  transition-duration: 900ms;
  transition-timing-function: var(--ease-in-out);
}
/* Ambient: the house lights while they are up (the pool plate stretched wide over the room) */
.s-hears__ambient {
  left: 50%;
  top: 46%;
  width: 180%;
  height: 120%;
  transform: translate(-50%, -50%);
  opacity: 0.2;
}
/* Vignette: the room dimming toward its edges, stretched so the sides darken at any aspect */
.s-hears__vignette {
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  opacity: 0.6;
}
.s-hears__room[data-lights="up"] .s-hears__ambient {
  opacity: 0.6;
  transition-duration: 700ms;
}
.s-hears__room[data-lights="up"] .s-hears__vignette {
  opacity: 0;
  transition-duration: 700ms;
}
.s-hears__room[data-lights="half"] :is(.s-hears__ambient, .s-hears__vignette) {
  transition-duration: 1200ms;   /* the app's "lights back" */
}
.s-hears__room[data-lights="down"] .s-hears__ambient {
  opacity: 0;
  transition-duration: 600ms;
}
.s-hears__room[data-lights="down"] .s-hears__vignette {
  opacity: 1;
  transition-duration: 600ms;
}

.s-hears__in {
  position: relative;
  z-index: 1;
  max-width: calc(var(--hr-max) + var(--gutter) * 2);
  margin-inline: auto;
  padding-top: calc(var(--nav-space) + clamp(24px, 4.5svh, 56px));
  padding-left: max(var(--gutter), calc(var(--safe-left) - var(--frame-inset) + 16px));
  padding-right: max(var(--gutter), calc(var(--safe-right) - var(--frame-inset) + 16px));
}

/* ---------- The flow: headline, the coach, the lines ---------- */
.s-hears__flow {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "head"
    "coach"
    "lines";
}
.s-hears__head {
  grid-area: head;
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: var(--g-head);
}
/* "How it works" over the headline, spaced as on the app tour's head */
.s-hears__head .eyebrow {
  margin-bottom: 14px;
}
.s-hears__title {
  max-width: 12em;
}
.s-hears__tl {
  display: inline-block;
}
/* Level with the eyebrow's line (a 24px tag on its 18px line) */
.s-hears__tag {
  flex: none;
  margin-top: -3px;
}

/* The coach: the Medallion standing on a pool of floor light */
.s-hears__coach {
  grid-area: coach;
  position: relative;
  z-index: 0;
  pointer-events: none;
}
.s-hears__band {
  display: none;
}
.s-hears__pin {
  position: relative;
  display: grid;
  place-items: center;
  height: calc(var(--med) * 0.9);
}
.s-hears__med {
  position: relative;
  width: var(--med);
  aspect-ratio: 1;
}
.s-hears__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.s-hears__still {
  position: absolute;
  inset: 0;
  width: 91%;   /* the SVG's disc is 77% of its box: 0.91 x 0.77 = the canvas disc (fit 0.7) */
  height: auto;
  margin: auto;
}
/* The SVG disc until hears.js has mounted the Medallion (.has-med): no JS, a failed script or a
   failed mount keep it. */
.s-hears.has-med .s-hears__still {
  display: none;
}
.s-hears:not(.has-med) .s-hears__canvas {
  display: none;
}
/* A wide floor light whose bright core sits just under the disc: the charcoal disc is the darkest
   thing in a lit room. It opens fully for the verdict. */
.s-hears__pool {
  position: absolute;
  z-index: -1;
  left: 50%;
  top: calc(50% + var(--med) * 0.3);
  width: calc(var(--med) * 2.8);
  max-width: none;
  height: auto;
  aspect-ratio: 1600 / 600;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* ---------- The lines ---------- */
.s-hears__lines {
  grid-area: lines;
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.s-hears__turn {
  position: relative;
  margin: 0;
}
.s-hears__turn--you {
  margin-top: var(--g-qa);
}
/* The speaker labels ("Adam, AI coach", "You", "You, again"). 13px, so a lighter tone than --fg-2:
   where a label crosses the opened pool's core just under the disc (about #785D49 on wide screens)
   --fg-2 falls to about 2.5:1; this tone keeps 4.5:1 there without counting the shade. */
.s-hears__who {
  margin-bottom: 10px;
  text-shadow: var(--hr-shade);
  font-size: var(--text-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: rgba(243, 239, 233, 0.9);
}
/* Adam's question, in the display serif (it steps back to fg-2 once you answer) */
.s-hears__q {
  max-width: 24em;
  font-family: var(--font-display);
  font-size: var(--hr-q);
  line-height: 1.18;
  font-weight: 500;
  color: var(--fg-2);
  text-wrap: balance;
}
/* Your answer, in the text sans */
.s-hears__a {
  max-width: 38em;
  font-size: var(--hr-a);
  line-height: 1.5;
  color: var(--fg);
  text-wrap: pretty;
}
.s-hears__w,
.s-hears__q .word,
.s-hears__vt .word {
  display: inline-block;
}
/* After Adam has listened back, the answer steps back and only the two marks stay lit */
.s-hears__w:not(.is-mark) {
  opacity: var(--hr-dim);
}
.s-hears__t {
  position: relative;
  display: inline-block;
  line-height: 1.25;
}
/* Marked words (the softeners): an orange strike (Wispr), the word still legible in --fg-2. No label
   under each word: the "2 softeners" count names them (App Store frame 1); the sr-only
   "(softener)" carries it for screen readers. */
.s-hears__w.is-mark .s-hears__t {
  color: var(--fg-2);
}
.s-hears__t::after {
  content: "";
  position: absolute;
  top: 54%;
  left: -0.08em;
  right: -0.08em;
  height: 2px;
  border-radius: 1px;
  background-color: var(--orange);
  transform-origin: 0 50%;
}
/* The count (App Store frame 1's "2 softeners"): a small chip under your answer, no hairline,
   so it reads as part of the take rather than another Example tag */
.s-hears__count {
  margin-top: 12px;
}
/* Inline boxes only (no flex or block children), so the text reads "2 softeners" as one line.
   The fill is a dark base under the light tint: on the dark room it looks as before (a soft light
   pill), and where the floor light lifts the ground the base keeps the chip dark enough to read
   (it never brightens what is under it). */
.s-hears__chip {
  display: inline-block;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  background-color: rgba(23, 20, 17, 0.6);
  background-image: linear-gradient(rgba(245, 238, 228, 0.12), rgba(245, 238, 228, 0.12));
  font-size: var(--text-small);
  font-weight: 500;
  line-height: 28px;
  color: var(--fg);
  white-space: nowrap;
}
/* The digit is a one-line window; the "1" it rolls up from sits above it (CSS text) */
.s-hears__num {
  display: inline-block;
  height: 28px;
  vertical-align: top;
  overflow: hidden;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.s-hears__d {
  position: relative;
  display: inline-block;
}
.s-hears__d::before {
  content: attr(data-from);
  content: attr(data-from) / "";
  position: absolute;
  left: 0;
  bottom: 100%;
}

/* Your second take: "You, again", then the sentence you meant, said firm (full strength, a step
   heavier than the first take). The struck words it comes back with are CSS (only while the take
   plays); the composed still is the sentence alone. */
.s-hears__turn--again {
  margin-top: var(--g-again);
}
.s-hears__a2 {
  max-width: 38em;
  font-size: var(--hr-a2);
  line-height: 1.5;
  font-weight: 500;
  color: var(--fg);
  text-wrap: pretty;
}
.s-hears__w2 {
  display: inline-block;
}
/* The first take drawn over the line (hears.js builds it, aria-hidden, CSS text) */
.s-hears__ghost {
  display: none;
}

/* Adam's working status: one small line in its own slot (only while the take plays) */
.s-hears__status {
  display: none;
  margin: var(--g-at) 0 0;
}
.s-hears__st {
  position: relative;
  grid-area: 1 / 1;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--hr-small);
  white-space: nowrap;
}

/* Adam's verdict: the biggest line in the room, standing in the light. #verdict lands with it
   in the middle of the screen, beside the disc. */
.s-hears__verdict {
  margin: var(--g-tv) 0 0;
  scroll-margin-top: 36svh;
}
.s-hears__vq {
  margin: 0;
}
.s-hears__v {
  max-width: 15em;
  font-family: var(--font-display);
  font-size: var(--hr-v);
  line-height: 1.1;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--fg);
  text-wrap: balance;
}
.s-hears__vs {
  display: block;
}
.s-hears__keep {
  white-space: nowrap;
}

/* ---------- The proof: the title, the six-categories line, the Sample microline and the app's verdict screen on the phone ---------- */
.s-hears__proof {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: clamp(28px, 5svh, 48px);
  margin-top: var(--g-proof);
}
.s-hears__ptitle {
  max-width: 12em;
  font-family: var(--font-display);
  font-size: var(--hr-pt);
  line-height: 1.08;
  font-weight: 500;
  letter-spacing: -0.005em;
}
.s-hears__pline {
  max-width: 34ch;
  margin-top: 14px;
}
.s-hears__phone {
  --pad: 96px;   /* the mask's box reaches past the device, so its shadow is kept */
  position: relative;
  justify-self: center;
  height: calc(var(--hr-pw) * 1.987 * var(--hr-cut) + var(--pad));
  margin: calc(-1 * var(--pad)) calc(-1 * var(--pad)) 0;
  padding: var(--pad) var(--pad) 0;
  /* The device sinks into the room's floor: an eased fade over its last stretch, gone 6px above the
     room's edge, so the edge stays one dark line against the paper (the screen's white never meets
     the page) */
  -webkit-mask-image: linear-gradient(to bottom,
    #000 calc(100% - var(--hr-fade)),
    rgba(0, 0, 0, 0.62) calc(100% - var(--hr-fade) * 0.62),
    rgba(0, 0, 0, 0.24) calc(100% - var(--hr-fade) * 0.34),
    transparent calc(100% - 6px));
  mask-image: linear-gradient(to bottom,
    #000 calc(100% - var(--hr-fade)),
    rgba(0, 0, 0, 0.62) calc(100% - var(--hr-fade) * 0.62),
    rgba(0, 0, 0, 0.24) calc(100% - var(--hr-fade) * 0.34),
    transparent calc(100% - 6px));
  pointer-events: none;
}
.s-hears__device {
  --device-w: var(--hr-pw);
}
/* The verdict screen is 600 x 1238 with the status bar and the island baked in (the app section's
   frame), shown uncropped; the device draws no island of its own */
.s-hears__screen {
  aspect-ratio: 600 / 1238;
  background-color: #FDFDFC;   /* the app's sheet ground */
}

/* ---------- Sizes ---------- */
@media (min-width: 600px) {
  .s-hears {
    --hr-q: clamp(22px, 2.1vw, 32px);
    --hr-a: clamp(19px, 1.5vw, 23px);
    --hr-a2: clamp(22px, 1.9vw, 28px);   /* the sentence you meant: a clear step up from the first take */
    --hr-v: clamp(30px, 3.1vw, 48px);
    --hr-pt: clamp(28px, 2.6vw, 40px);
    --hr-pw: clamp(236px, 19vw, 290px);
  }
}
/* Big screens (1920x1080): the room's content grows with the screen instead of floating in it */
@media (min-width: 1600px) and (min-height: 960px) {
  .s-hears {
    --hr-max: 1440px;
    --hr-a: 24px;
  }
}
/* Portrait tablets: a larger disc */
@media (min-width: 600px) and (orientation: portrait) {
  .s-hears {
    --med: clamp(190px, 21svh, 250px);
    --hr-q: clamp(24px, 3.4vw, 30px);
    --hr-v: clamp(32px, 5vw, 44px);
  }
}

/* ==========================================================================
   Wide screens (landscape, 640px and up): Adam's column on the left, the lines on the right.
   The composed still: the disc centred against the lines, all in one screen.
   ========================================================================== */
@media (min-width: 640px) and (orientation: landscape) {
  .s-hears {
    --med: clamp(150px, min(28vw, 40svh), 460px);
    --g-head: clamp(20px, 4svh, 44px);
    --g-qa: clamp(22px, 3.4svh, 36px);
    --g-tv: clamp(24px, 4svh, 40px);
  }
  .s-hears__flow {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    grid-template-rows: auto 1fr;
    grid-template-areas:
      ".     head"
      "coach lines";
    column-gap: var(--hr-colgap);
  }
  .s-hears__title {
    max-width: none;
  }
  .s-hears__coach {
    align-self: center;
  }
  .s-hears__pin {
    height: var(--med);
  }
  /* #verdict lands with the verdict level with the disc (its centre 60% down the screen under
     the nav; the verdict is about three lines of 1.1). The root's scroll-padding-top (nav-space
     + 12px) is added to this margin, so it is taken off here. */
  .s-hears__verdict {
    scroll-margin-top: calc((100svh - var(--nav-space)) * 0.6 - var(--hr-v) * 1.65 - 12px);
  }
  /* The floor light reaches to the right, so the lines (and the verdict) stand in it too */
  .s-hears__pool {
    left: calc(50% + var(--med) * 0.7);
    top: calc(var(--med) * 0.8);
    width: calc(var(--med) * 4.4);
  }
  .s-hears__proof {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    grid-template-areas: "phone text";
    column-gap: var(--hr-colgap);
    align-items: start;
  }
  .s-hears__ptext {
    grid-area: text;
    padding-top: clamp(8px, 4svh, 48px);
  }
  .s-hears__phone {
    grid-area: phone;
  }
}
/* Landscape phones and short laptops: tighter type so the composed still fits */
@media (orientation: landscape) and (max-height: 559px) {
  .s-hears {
    --hr-q: 18px;
    --hr-a: 17px;
    --hr-v: 24px;
    --hr-pt: 24px;
    --hr-pw: 200px;
    --hr-cut: 0.58;   /* the mark and the verdict; the cut falls in the screen's empty band */
  }
  .s-hears__in {
    padding-top: calc(var(--nav-space) + 16px);
  }
  .s-hears__title {
    font-size: 28px;
  }
  /* Always the composed still here (no sticky disc): #verdict lands with the verdict 16px above
     the bottom of the screen (about three lines of 1.1, the root's scroll-padding-top taken off),
     so the disc centred against the lines stays clear of the nav. */
  .s-hears__verdict {
    scroll-margin-top: calc(100svh - var(--nav-space) - 12px - var(--hr-v) * 3.3 - 16px);
  }
}

/* ==========================================================================
   Motion layout (hears.js adds .is-motion when motion runs and the screen is
   at least 560px tall). The beats get their own scroll room; the disc stays
   in view beside (wide) or above (phones) the lines while they play.
   ========================================================================== */
.s-hears.is-motion {
  --g-head: 24px;
  --g-qa: clamp(30px, 4.5svh, 48px);
  --g-at: 14px;
  --g-tv: clamp(72px, 11svh, 120px);
  --g-again: clamp(30px, 4.5svh, 48px);
  --g-proof: clamp(80px, 13svh, 140px);
}
/* The status line takes no room of its own: it sits in the gap between your answer and the
   verdict (--g-tv is the whole gap), so the end frame stays one tight picture. */
.s-hears.is-motion .s-hears__status {
  display: grid;
  height: 0;
}
.s-hears.is-motion .s-hears__verdict {
  margin-top: calc(var(--g-tv) - var(--g-at));
}
/* Phones: the coach is a band under the nav. While it is stuck (.is-stuck) its copy of the house
   lights covers what scrolls under it, with a soft fade at its lower edge. */
.s-hears.is-motion .s-hears__coach {
  position: sticky;
  top: var(--nav-space);
  z-index: 3;
  --fade: 16px;
}
/* The band hugs the disc (the canvas's empty margin overhangs into the fade) */
.s-hears.is-motion .s-hears__pin {
  height: calc(var(--med) * 0.76);
}
.s-hears.is-motion .s-hears__band {
  display: block;
  position: absolute;
  left: calc(-1 * var(--gutter));
  right: calc(-1 * var(--gutter));
  top: calc(-1 * var(--nav-space));
  bottom: calc(-1 * var(--fade));
  overflow: hidden;
  opacity: 0;
  transition: opacity 200ms var(--ease-out);
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - var(--fade)), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - var(--fade)), transparent 100%);
}
.s-hears.is-motion.is-stuck .s-hears__band {
  opacity: 1;
}
.s-hears__band-lights {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 100vh;
  height: 100lvh;
  background-color: var(--hr-room);
}
@media (min-width: 640px) and (orientation: landscape) {
  .s-hears.is-motion {
    --g-head: clamp(24px, 5svh, 56px);
    --g-qa: clamp(32px, 6svh, 64px);
    --g-at: clamp(16px, 2.6svh, 28px);
    --g-tv: clamp(96px, 16svh, 180px);
    --g-again: clamp(30px, 5svh, 52px);
  }
  .s-hears.is-motion .s-hears__flow {
    grid-template-areas:
      "coach head"
      "coach lines";
  }
  /* The disc rides beside the lines: sticky in its column, its centre 60% down the screen under
     the nav (level with the line that is playing, and with the verdict while the question is still
     in view). The column reaches a little past the verdict, so the disc leaves level with it. */
  .s-hears.is-motion .s-hears__coach {
    position: relative;
    top: auto;
    z-index: 0;
    align-self: stretch;
    margin-bottom: calc(var(--med) * -0.3);
  }
  .s-hears.is-motion .s-hears__band {
    display: none;
  }
  .s-hears.is-motion .s-hears__pin {
    position: sticky;
    top: calc(var(--nav-space) + (100svh - var(--nav-space)) * 0.6 - var(--med) * 0.5);
    height: var(--med);
  }
}

/* ---------- Beat start states (only while motion runs) ---------- */
/* Lines not yet played are simply not there yet; their space is kept, so nothing shifts. */
.s-hears.is-motion .s-hears__who {
  opacity: 0;
  transition: opacity 300ms var(--ease-out);
}
.s-hears.is-motion .s-hears__turn.is-on .s-hears__who {
  opacity: 1;
}
/* The question streams in at speech pace (Streaming text: a fade with a 1px blur) */
.s-hears.is-motion .s-hears__q .word {
  opacity: 0;
  filter: blur(1px);
  transition:
    opacity 340ms var(--ease-out),
    filter 340ms var(--ease-out);
}
.s-hears.is-motion .s-hears__q .word.is-on {
  opacity: 1;
  filter: blur(0);
}
.s-hears.is-motion .s-hears__q {
  transition: color 400ms var(--ease-out);
}
.s-hears.is-motion .s-hears__turn--ask:not(.is-past) .s-hears__q {
  color: var(--fg);
}
/* Your answer streams in word by word, in place (opacity only: 39 words, so no per-word blur; a
   short fade, so only a few words fade at once) */
.s-hears.is-motion .s-hears__w {
  opacity: 0;
  transition: opacity 160ms var(--ease-out);
}
.s-hears.is-motion .s-hears__w.is-on {
  opacity: 1;
}
/* Adam listens back: the answer steps back; the two marks stay at full strength */
.s-hears.is-motion.is-reviewed .s-hears__w.is-on:not(.is-mark) {
  opacity: var(--hr-dim);
  transition-duration: 600ms;
}
/* The strikes land as their words are said */
.s-hears.is-motion .s-hears__w.is-mark .s-hears__t {
  color: inherit;
  transition: color 500ms var(--ease-out) 200ms;
}
.s-hears.is-motion .s-hears__w.is-mark.is-struck .s-hears__t {
  color: var(--fg-2);
}
.s-hears.is-motion .s-hears__t::after {
  transform: scaleX(0);
  transition: transform 160ms var(--ease-out);
}
.s-hears.is-motion .s-hears__w.is-struck .s-hears__t::after {
  transform: scaleX(1);
  transition-duration: 300ms;
}
/* The count rises in after the second strike, its digit rolling up from 1 to 2 */
.s-hears.is-motion .s-hears__chip {
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 300ms var(--ease-out),
    transform 300ms var(--ease-out);
}
.s-hears.is-motion .s-hears__chip.is-on {
  opacity: 1;
  transform: none;
}
.s-hears.is-motion .s-hears__d {
  transform: translateY(100%);
  transition: transform 420ms var(--hr-soft) 160ms;
}
.s-hears.is-motion .s-hears__chip.is-on .s-hears__d {
  transform: none;
}
/* Thinking states (transitions.dev): one line at a time, the old one exits up, a shimmer while
   it holds. Nothing shows once the verdict takes the room (data-st="off"). */
.s-hears.is-motion .s-hears__st {
  opacity: 0;
  transform: translateY(8px);
  filter: blur(2px);
  transition:
    opacity 150ms ease-in-out,
    transform 150ms ease-in-out,
    filter 150ms ease-in-out;
}
.s-hears.is-motion .s-hears__status[data-st="b"] .s-hears__st[data-st="a"],
.s-hears.is-motion .s-hears__status[data-st="off"] .s-hears__st {
  transform: translateY(-8px);
}
.s-hears.is-motion .s-hears__status[data-st="a"] .s-hears__st[data-st="a"],
.s-hears.is-motion .s-hears__status[data-st="b"] .s-hears__st[data-st="b"] {
  opacity: 1;
  transform: none;
  filter: blur(0);
  transition-delay: 50ms;
}
.s-hears.is-motion .s-hears__st::before {
  content: attr(data-text);
  content: attr(data-text) / "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(90deg,
    transparent 0%, transparent 40%,
    #FFF8EE 50%,
    transparent 60%, transparent 100%);
  background-size: 400% 100%;
  background-repeat: no-repeat;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.s-hears.is-motion .s-hears__status[data-st="a"] .s-hears__st[data-st="a"]::before,
.s-hears.is-motion .s-hears__status[data-st="b"] .s-hears__st[data-st="b"]::before {
  animation: s-hears-shimmer 1000ms linear 80ms 1;
}
@keyframes s-hears-shimmer {
  0% { background-position: 100% 0; }
  100% { background-position: 0% 0; }
}
/* The verdict focuses in word by word (the app's daily tempo: a 500ms soft settle from an 8px
   blur and a small rise) */
.s-hears.is-motion .s-hears__vt .word {
  opacity: 0;
  filter: blur(8px);
  transform: translateY(0.12em);
  transition:
    opacity 500ms var(--hr-soft),
    filter 500ms var(--hr-soft),
    transform 500ms var(--hr-soft);
}
.s-hears.is-motion .s-hears__vt .word.is-on {
  opacity: 1;
  filter: blur(0);
  transform: none;
}
/* The pool: a floor light during the conversation, opened for the verdict while the lights are
   down (hears.js closes it again when they come back up to half) */
.s-hears.is-motion .s-hears__pool {
  opacity: 0.45;
  transform: translate(-50%, -50%) scale(0.86);
  /* closing: on the house lights' own "lights back" (1200ms), eased in and out, so it settles under
     your second take instead of dipping as it starts */
  transition:
    opacity 1200ms var(--ease-in-out),
    transform 1200ms var(--ease-in-out);
}
.s-hears.is-motion .s-hears__coach.is-open .s-hears__pool {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  transition:
    opacity 950ms var(--hr-soft),
    transform 950ms var(--hr-soft);
}
/* Phones (the band layout): the pool rides in the sticky band and its glow reaches below the
   band's edge, where the lines come out from under it, so the opened pool stays dimmer there
   (the question, your answer and the small labels keep 4.5:1). Wide screens: the verdict stands
   in the full light while the lights are down. */
@media (max-width: 639px), (orientation: portrait) {
  .s-hears.is-motion .s-hears__coach.is-open .s-hears__pool {
    opacity: 0.6;
  }
}
/* The proof: one feathered mask sweep down the block (Monogram), then the mask is dropped */
.s-hears.is-motion .s-hears__proof:not(.is-done) {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 33.3%, transparent 44%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 33.3%, transparent 44%, transparent 100%);
  -webkit-mask-size: 100% 300%;
  mask-size: 100% 300%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: 0 100%;
  mask-position: 0 100%;
}
.s-hears.is-motion .s-hears__proof.is-in:not(.is-done) {
  -webkit-mask-position: 0 0;
  mask-position: 0 0;
  transition:
    -webkit-mask-position 900ms var(--ease-out),
    mask-position 900ms var(--ease-out);
}

/* Go again. The line in the markup is the sentence you meant (the layout never changes); over it
   hears.js lays the first take, "I think the sprint data maybe tells a different story.", in the
   same type. It comes back at the reviewed strength with both softeners struck; they fade where
   they stand while the kept words glide along their line onto the sentence's own words (a word
   that changes line fades and comes back in its new place; transforms and opacity only, so
   nothing reflows), then the sentence takes over and is said firm, word by word. */
.s-hears.is-motion .s-hears__a2 {
  position: relative;
}
.s-hears.is-motion .s-hears__ghost {
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  opacity: 0;
  pointer-events: none;
  transition: opacity 240ms var(--ease-out);
}
.s-hears.is-motion .s-hears__turn--again.is-on .s-hears__ghost {
  opacity: 1;
}
.s-hears.is-motion .s-hears__turn--again.is-merged .s-hears__ghost {
  opacity: 0;
  transition-duration: 160ms;
}
.s-hears__gw {
  display: inline-block;
  white-space: nowrap;
  opacity: var(--hr-dim);
  transition:
    transform 300ms var(--ease-in-out),
    opacity 260ms var(--ease-out),
    filter 260ms var(--ease-out);
}
.s-hears__gw::before {
  content: attr(data-t);
  content: attr(data-t) / "";
}
/* the struck words, as in your first take: --fg-2 at full strength with the orange strike */
.s-hears__gw.is-cutw {
  opacity: 1;
  color: var(--fg-2);
}
.s-hears__gw.is-cutw::before {
  background-image: linear-gradient(var(--orange), var(--orange));
  background-repeat: no-repeat;
  background-size: 100% 2px;
  background-position: 0 58%;
}
.s-hears.is-motion .s-hears__turn--again.is-cut .s-hears__gw.is-cutw {
  opacity: 0;
  filter: blur(2px);
}
/* a word that changes line fades where it is; the sentence brings it in at its new place */
.s-hears.is-motion .s-hears__turn--again.is-cut .s-hears__gw.is-hop {
  opacity: 0;
}
/* The sentence: hidden under the first take, then at the reviewed strength, then said firm */
.s-hears.is-motion .s-hears__w2 {
  opacity: 0;
  transition: opacity 160ms var(--ease-out);
}
.s-hears.is-motion .s-hears__turn--again.is-merged .s-hears__w2 {
  opacity: var(--hr-dim);
}
.s-hears.is-motion .s-hears__turn--again.is-merged .s-hears__w2.is-on {
  opacity: 1;
  transition-duration: 200ms;
}

/* Finish on skip. Soft (a beat cut short while on screen): what is left lands in 220ms.
   Instant (a beat scrolled past, Pause motion): no transitions for that one frame. */
.s-hears .is-catchup,
.s-hears .is-catchup *,
.s-hears .is-catchup *::before,
.s-hears .is-catchup *::after {
  transition-duration: 220ms !important;
  transition-delay: 0ms !important;
  animation: none !important;
}
.s-hears .is-instant,
.s-hears .is-instant *,
.s-hears .is-instant *::before,
.s-hears .is-instant *::after {
  transition: none !important;
  animation: none !important;
}

/* ---------- Reduced motion and Pause motion: the composed still ---------- */
/* Pause motion: every state still changes, instantly (the orange card's wipe and line too; the
   Medallion holds its still pose itself). */
html.still .s-hears *,
html.still .s-hears *::before,
html.still .s-hears *::after {
  transition-duration: 0ms !important;
  transition-delay: 0ms !important;
  animation: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .s-hears__cols > span,
  .s-hears__sl,
  .s-hears__ambient,
  .s-hears__vignette,
  .s-hears__st,
  .s-hears__st::before {
    transition: none !important;
    animation: none !important;
  }
}

/* --------------------------------------------------------------------------
   Section 04 "app" (#app)  source: .build/sections/04-app.css
   -------------------------------------------------------------------------- */
/* ==========================================================================
   04 The app (#app)
   Lights up (2026-10-09): the house lights are up. The first section of
   the light page (.theme-paper; .lights-up draws the seam from the How it works
   room, see site.base.css 10b). The App Store way (round 7, frames 1 and 4):
   a two-tone charcoal title on the warm white page, the pill list on the page
   (light surfaces with the app's card edge, the selected pill charcoal with
   light text like the app's selected chips), and the phone standing on a
   charcoal plinth (--plinth, the set's panel). Five real app loops in a CSS
   iPhone; only the active loop loads and plays. Callouts are the app's own
   stickers: white capsules that pop at the loop's marker times, hang over the
   phone's right edge onto the plinth, stand still and leave on their marker.
   No orange of its own: the app's screens carry their one orange.
   ========================================================================== */

.s-app {
  /* The phone is sized from the view under the floating nav, within sane bounds
     (phone height = 1.987 x width for a 600 x 1238 screen and a 3.6% bezel). */
  --app-frame-h: clamp(620px, calc(100svh - 2 * var(--frame-inset)), 920px);
  /* The plinth's padding above the "Example" tag and below the phone. */
  --app-pad-top: 24px;
  --app-pad-bot: 48px;
  --app-tag-room: 40px;
  --app-dw: clamp(240px, calc((var(--app-frame-h) - var(--nav-space) - 16px - var(--app-pad-bot) - var(--app-tag-room)) / 1.987), 380px);
  /* Short landscape windows (under about 645px tall): the phone follows the view
     height, so the pills and the phone fit under the nav. Taller views keep the
     size above. */
  --app-dw: min(clamp(240px, calc((var(--app-frame-h) - var(--nav-space) - 16px - var(--app-pad-bot) - var(--app-tag-room)) / 1.987), 380px), max(180px, calc((100svh - var(--nav-space) - 96px) / 1.987)));
  /* Narrow desktop windows (900 to about 1100px, iPad portrait): the pill column (340px), the
     plinth's sides and an --app-gap of paper on each side of the centred plinth come first,
     so the phone gives way instead of the row overflowing. 16px allows for a classic
     scrollbar inside 100vw. */
  --app-gap: clamp(40px, 4.4vw, 72px);
  --app-plinth-x: clamp(64px, 6vw, 88px);
  --app-dw: min(clamp(240px, calc((var(--app-frame-h) - var(--nav-space) - 16px - var(--app-pad-bot) - var(--app-tag-room)) / 1.987), 380px), max(180px, calc((100svh - var(--nav-space) - 96px) / 1.987)), calc(100vw - 16px - 2 * var(--gutter) - 340px - 2 * var(--app-gap) - 2 * var(--app-plinth-x)));
  --app-bezel: calc(var(--app-dw) * 0.036);
  /* How far a callout reaches past the screen's right edge. */
  --app-overhang: clamp(14px, calc(var(--app-dw) * 0.15), 56px);
  /* --app-plinth-x (above): the plinth's sides hold the callouts' overhang (56px at most)
     and the play control (18 + 44px). */
  --app-plinth-r: clamp(22px, calc(var(--app-dw) * 0.11), 40px);
  --app-swap: 400ms;
  --app-tab-r: 26px;
  /* The nav's "The app" jump lands the head 40px under the nav instead of one
     section padding lower, so the five pills and the top of the phone show
     under it (html adds nav-space + 12px of scroll padding). */
  scroll-margin-top: calc(28px - var(--section-y));
}

/* ---------- Head ---------- */
.s-app__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin-bottom: clamp(32px, 5vh, 56px);
}
.s-app__title {
  max-width: 15ch;
  margin-top: 14px;
}
.s-app__lead {
  max-width: 30ch;
  margin-top: 18px;
}
/* Heads share one right column across the page: the intro starts on the 7/12 line
   (7fr / 5fr, no gap), as in coaches. */
@media (min-width: 900px) {
  .s-app__head {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: 0;
    align-items: end;
  }
  .s-app__head .eyebrow {
    grid-column: 1 / -1;
  }
  .s-app__title {
    padding-right: 32px;
  }
  .s-app__lead {
    margin-top: 0;
    padding-bottom: 0.4em;
  }
}

/* ---------- Stage: the light page itself (no frame), with the plinth in the middle ---------- */
/* The stage keeps the frame's side inset, so the layout lines up as before. */
.s-app__stage {
  position: relative;
  margin-inline: var(--frame-inset);
}
/* One instrument: the pill list on the container's left edge (one 340px track, so every
   pill has one width at every desktop size), and the plinth centred in the rest of the
   row, so the paper is shared evenly on both sides of it. (Round 1: the plinth used to
   stand in the middle of the page, which left the right third of a wide screen as empty
   paper once the dark stage was gone; at 1440 its centre moves from x 727 to 890.) The
   plinth holds the callouts' overhang and the play control, so nothing needs the track
   beside it. The side padding lines the pills up with the section head above.
   The pill list starts level with the top of the phone, so a longer pill grows
   the list downward and nothing above it moves. */
.s-app__layout {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  /* No gap: the plinth sits midway between the pills and the content edge, and the
     --app-dw cap keeps at least about one --app-gap of paper on each side of it. */
  column-gap: 0;
  align-items: start;
  padding-inline: max(calc(var(--gutter) - var(--frame-inset)), calc((100% - var(--container)) / 2), var(--safe-left)) max(calc(var(--gutter) - var(--frame-inset)), calc((100% - var(--container)) / 2), var(--safe-right));
}

/* ---------- Tabs (vertical pill list, Tabs sliding indicator) ---------- */
.s-app__side {
  min-width: 0;
  max-width: 400px;
  margin-top: calc(var(--app-pad-top) + var(--app-tag-room));
}
/* Every pill has one width (the column) and, when open, one height (app.js
   measures the tallest open pill), so picking a pill only moves the fill. */
.s-app__tabs {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}
.s-app__indicator {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: var(--ind-w, 0px);
  height: var(--ind-h, 0px);
  border-radius: var(--app-tab-r);
  /* The app's selected chip: charcoal with light text (Tier 1, navigation). */
  background-color: var(--charcoal);
  box-shadow: 0 1px 2px rgba(38, 30, 20, 0.16), 0 14px 32px -14px rgba(38, 30, 20, 0.42);
  opacity: 0;
  transform: translate(var(--ind-x, 0px), var(--ind-y, 0px));
  pointer-events: none;
  transition:
    transform var(--dur-3) var(--ease-out),
    width var(--dur-3) var(--ease-out),
    height var(--dur-3) var(--ease-out),
    opacity var(--dur-2) var(--ease-out);
}
.s-app__indicator.is-on {
  opacity: 1;
}
.s-app__indicator.is-snap {
  transition: none;
}

.s-app__tab {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  max-width: 100%;
  min-height: 52px;
  padding: 10px 22px 10px 10px;
  border-radius: var(--app-tab-r);
  /* The app's card: the #F5F5F3 surface with its thin #EBEBEA edge. */
  background-color: var(--paper-2);
  box-shadow: inset 0 0 0 1px var(--paper-line);
  color: var(--charcoal);
  text-align: left;
  transition:
    background-color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out),
    min-height var(--dur-3) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .s-app__tab:hover {
    background-color: var(--surface-2);
  }
}
.s-app__tab-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background-color: rgba(38, 38, 38, 0.07);
  transition:
    background-color var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out);
}
.s-app__tab-icon svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
}
.s-app__tab-v {
  transform-origin: 8px 8px;
  transition: transform var(--dur-3) var(--ease-out);
}
.s-app__tab-body {
  display: grid;
  min-width: 0;
  padding-top: 5px;
}
.s-app__tab-title {
  font-size: 16px;
  font-weight: 500;
  line-height: 22px;
}
/* The line under the title. Without JS every line shows (content-first). */
.s-app__tab-line {
  display: grid;
  grid-template-rows: 1fr;
  color: var(--fg-2);
}
.s-app__tab-line-in {
  min-height: 0;
  overflow: hidden;
  padding-top: 3px;
  font-size: 15px;
  line-height: 1.45;
  text-wrap: pretty;
}

/* "Included with Gravitas Pro." under the line: smaller, quieter, own line. */
.s-app__tab-note {
  display: block;
  padding-top: 2px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--fg-2);
}

/* Selected (JS only: the indicator is the fill). */
html.js .s-app__tab[aria-selected="true"] {
  background-color: transparent;
  box-shadow: inset 0 0 0 1px transparent;
  color: var(--paper);
}
html.js .s-app__tab[aria-selected="true"] .s-app__tab-icon {
  background-color: var(--paper);
  color: var(--charcoal);
}
html.js .s-app__tab[aria-selected="true"] .s-app__tab-v {
  transform: rotate(90deg) scaleX(0);
}
html.js .s-app__tab-line {
  grid-template-rows: 0fr;
  opacity: 0;
  transition:
    grid-template-rows var(--dur-3) var(--ease-out),
    opacity var(--dur-2) var(--ease-out);
}
/* On the charcoal pill: the line 9.0:1, the Pro note (the app's #A3A3A2) 6.0:1. */
html.js .s-app__tab[aria-selected="true"] .s-app__tab-note {
  color: #A3A3A2;
}
html.js .s-app__tab[aria-selected="true"] .s-app__tab-line {
  grid-template-rows: 1fr;
  opacity: 1;
  color: #C8C8C6;
  transition:
    grid-template-rows var(--dur-3) var(--ease-out),
    opacity var(--dur-3) var(--ease-out) 60ms;
}
/* The open pill takes the shared open height (set on the list by app.js). The
   probe class opens a pill's line while app.js measures it. */
@media (min-width: 900px) {
  html.js .s-app__tab[aria-selected="true"] {
    min-height: var(--app-tab-open, 52px);
  }
}
html.js .s-app__tab.is-probe .s-app__tab-line {
  grid-template-rows: 1fr;
}
/* JS measures the target layout with transitions off, then animates to it. */
.s-app.is-measure .s-app__tab,
.s-app.is-measure .s-app__tab-icon,
.s-app.is-measure .s-app__tab-v,
.s-app.is-measure .s-app__tab-line {
  transition: none !important;
}

/* ---------- Viewer: the plinth, phone, callouts, tag, play control ---------- */
.s-app__viewer {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* desktop: as wide as the plinth, centred in its track (the tilt reads the viewer's box) */
  justify-self: center;
  min-width: 0;
}
/* The charcoal plinth the phone stands on: flat, no glow, no edge (the App Store set's panel).
   It holds the "Example" tag above the phone, the callouts' overhang and the play control. */
.s-app__plinth {
  position: relative;
  padding: var(--app-pad-top) var(--app-plinth-x) var(--app-pad-bot);
  border-radius: var(--app-plinth-r);
  background-color: var(--plinth);
  color: var(--fg-dark);
}
.s-app__anchor {
  position: relative;
  z-index: 0;
  width: var(--app-dw);
  margin-top: var(--app-tag-room);
}
.s-app__rig {
  transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 1000ms var(--ease-out);
}
.s-app__rig.is-tilting {
  transition: transform 400ms var(--ease-out);
}
.s-app__turn {
  position: relative;
}

.s-app .s-app__phone {
  --device-w: var(--app-dw);
}
/* On the plinth the phone keeps its rims and its tight contact shadow only. The foundation's
   deep drop (0 40px 90px) reached about 60px under the phone, past the plinth's 32 to 48px
   bottom padding, and left a grey smudge (and banding on phones) on the paper below. */
.s-app__plinth .device {
  box-shadow:
    inset 0 0 0 calc(var(--device-w) * 0.009) var(--metal),
    inset 0 1px 1px calc(var(--device-w) * 0.009) rgba(255, 246, 235, 0.16),
    0 1px 1px rgba(0, 0, 0, 0.5),
    0 10px 24px -8px rgba(0, 0, 0, 0.55);
}
/* The loops are 600 x 1238 with the status bar baked in: show them uncropped. */
.s-app .s-app__phone .device__screen {
  aspect-ratio: 600 / 1238;
  background-color: #F6F6F4;
}

/* Screens: the incoming loop fades in over the outgoing one (no dip to black),
   both through a 3px blur, then the outgoing one is hidden. */
.s-app__screen {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 0;
  opacity: 0;
  visibility: hidden;
  filter: blur(3px);
}
.s-app__screen.is-active {
  z-index: 2;
  opacity: 1;
  visibility: visible;
  filter: blur(0);
  transition:
    opacity var(--app-swap) var(--ease-out),
    filter var(--app-swap) var(--ease-out);
}
.s-app__screen.is-leaving {
  z-index: 1;
  opacity: 1;
  visibility: visible;
  filter: blur(3px);
  transition: filter var(--app-swap) var(--ease-out);
}
.s-app__screen > video,
.s-app__screen > .s-app__still,
.s-app__nojs {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The designed still (the loop's last frame) for reduced motion and a paused
   start; it only gets its src when it is needed. */
.s-app__still {
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease-out);
}
.s-app__screen.is-static .s-app__still {
  opacity: 1;
}
/* Glass glare that follows a mouse pointer. */
.s-app__glare {
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  opacity: 0;
  mix-blend-mode: screen;
  pointer-events: none;
  background:
    radial-gradient(circle calc(var(--app-dw) * 0.3) at var(--gx, 50%) var(--gy, 30%), rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.05) 55%, rgba(255, 255, 255, 0) 85%),
    radial-gradient(circle calc(var(--app-dw) * 0.8) at var(--gx, 50%) var(--gy, 30%), rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 80%);
  transition: opacity var(--dur-3) var(--ease-out);
}
.s-app.is-hover .s-app__glare {
  opacity: 0.34;
}

/* Callouts: the app's demo stickers (white capsule, hairline, raised shadow,
   icon tile). Anchored to the screen's right edge at the subject's height. */
.s-app__callouts {
  position: absolute;
  inset: var(--app-bezel);
  z-index: 4;
  pointer-events: none;
  /* the screen's width, for the small-screen height below */
  container-type: inline-size;
}
.s-app__callout {
  position: absolute;
  top: calc(var(--y) * 100%);
  right: calc(var(--app-overhang) * -1);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 30px;
  padding: 0 12px 0 4px;
  border-radius: var(--r-pill);
  background-color: #FDFDFC;
  box-shadow:
    inset 0 0 0 1px #EBEBEA,
    0 1px 2px rgba(10, 9, 8, 0.2),
    0 10px 24px -10px rgba(10, 9, 8, 0.55);
  color: var(--charcoal);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  transform-origin: 100% 50%;
  opacity: 0;
  transform: translateY(-50%) translateY(6px) scale(0.92);
  /* Leave: the app's 0.22 s ease-in, no spring. */
  transition:
    opacity 220ms cubic-bezier(0.42, 0, 1, 1),
    transform 220ms cubic-bezier(0.42, 0, 1, 1);
}
.s-app__callout.is-on {
  opacity: 1;
  transform: translateY(-50%);
  /* Pop: the app's spring (response 0.45, damping 0.72). Fallback first. */
  transition:
    opacity 180ms var(--ease-out),
    transform 560ms var(--ease-pop);
  transition:
    opacity 180ms var(--ease-out),
    transform 560ms linear(0, 0.034, 0.118, 0.231, 0.356, 0.48, 0.596, 0.7, 0.788, 0.861, 0.918, 0.962, 0.994, 1.015, 1.029, 1.036, 1.038, 1.038, 1.035, 1.031, 1.026, 1.021, 1.016, 1.012, 1.009, 1.006, 1.004, 1.002, 1);
}
/* On a screen about 300px wide or less (every phone layout, and short desktops) a sticker reaches
   past the middle of the screen, so a callout can carry a second height (--y-m) clear of what it
   labels. liveCoaching: above the Coach Medallion (over the transcript button), which "One clear
   cue" and "Hear what changed" would otherwise cover, and clear of the "Your line" card. */
@container (max-width: 300px) {
  .s-app__callout {
    top: calc(var(--y-m, var(--y)) * 100%);
  }
}
.s-app__ctile {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background-color: #F0F0EE;
}
.s-app__ctile svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* "Example" sits on the phone frame: above its top-left corner, edge aligned. */
.s-app__example {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 0;
  z-index: 5;
}

/* Play / pause for the loop (a visible control for motion longer than 5 s). */
.s-app__play {
  position: absolute;
  bottom: 2px;
  left: calc(100% + 18px);
  z-index: 6;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background-color: rgba(245, 238, 228, 0.08);
  box-shadow: inset 0 0 0 1px rgba(245, 238, 228, 0.16);
  color: var(--fg-dark);
  transition:
    background-color var(--dur-2) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .s-app__play:hover {
    background-color: rgba(245, 238, 228, 0.15);
  }
}
.s-app__play:active {
  transform: scale(0.94);
}
.s-app__play svg {
  grid-area: 1 / 1;
  width: 14px;
  height: 14px;
  fill: currentColor;
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-out);
}
.s-app__i-play {
  transform: translateX(1px);
}
.s-app__play[aria-pressed="false"] .s-app__i-play,
.s-app__play[aria-pressed="true"] .s-app__i-pause {
  opacity: 0;
  transform: scale(0.6);
}

/* Mobile caption under the phone (desktop shows the line inside the pill). */
.s-app__caption {
  display: none;
}

/* ---------- Under 900px: pills become a scroll-snap row above the phone ---------- */
@media (max-width: 899px) {
  .s-app {
    --app-dw: clamp(208px, 60vw, 300px);
    /* Short screens: cap the phone by the view height so the pill row, the phone
       and the caption under it fit under the nav together. The stack around the
       phone takes about 185px (pill row 56, Example tag and gaps 58, caption
       22 + 49), so 200px leaves a little air. Tall phones (390 x 844) keep the width
       above; short portrait screens (375 x 548 or 375 x 667 with the browser bars)
       get a smaller phone. Phones held sideways stop at 140px and use the
       side-by-side caption below. */
    --app-dw: min(clamp(208px, 60vw, 300px), max(140px, calc((100svh - var(--nav-space) - 226px) / 1.987)));
    --app-tab-r: 22px;
    --app-tag-room: 40px;
    --app-pad-top: 20px;
    --app-pad-bot: 32px;
  }
  .s-app__layout {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding: 12px 0 0;
  }
  .s-app__side {
    max-width: none;
    margin-top: 0;
  }
  /* The row clips (it scrolls sideways), so its 6px of room above and below
     holds the 2px focus ring at its 3px offset and the selected pill's short
     shadow. The layout's top padding and the viewer's gap give the 4px back,
     so nothing below moves. */
  .s-app__tabs {
    flex-direction: row;
    align-items: center;
    gap: 6px;
    padding: 6px max(16px, var(--safe-right)) 6px max(16px, var(--safe-left));
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-inline: max(16px, var(--safe-left)) max(16px, var(--safe-right));
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 14px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 14px), transparent);
  }
  .s-app__tabs::-webkit-scrollbar {
    display: none;
  }
  .s-app__indicator {
    box-shadow: 0 1px 2px rgba(38, 30, 20, 0.16), 0 4px 8px -6px rgba(38, 30, 20, 0.42);
  }
  .s-app__tab {
    flex: none;
    align-items: center;
    justify-content: center;
    min-width: var(--app-tab-w, 0px);
    min-height: 44px;
    padding: 0 16px;
    scroll-snap-align: center;
  }
  .s-app__tab-icon,
  html.js .s-app__tab-line {
    display: none;
  }
  .s-app__tab-body {
    padding-top: 0;
  }
  .s-app__tab-title {
    font-size: 15px;
    white-space: nowrap;
  }
  .s-app__viewer {
    height: auto;
    padding-top: 20px;
  }
  /* The plinth spans the frame (the stage's inset), the phone in its middle. */
  .s-app__plinth {
    align-self: stretch;
    padding: var(--app-pad-top) 0 var(--app-pad-bot);
    border-radius: var(--frame-radius);
  }
  .s-app__anchor {
    margin-inline: auto;
  }
  .s-app__play {
    left: calc(100% + 12px);
  }
  .s-app__caption {
    display: block;
    width: min(100%, 34ch);
    min-height: calc(2 * 1.45em);
    margin: 22px auto 0;
    padding-inline: 16px;
    font-size: 17px;
    line-height: 1.45;
    text-align: center;
    text-wrap: balance;
    color: var(--fg);
    transition: opacity var(--dur-2) var(--ease-out);
  }
  .s-app__caption.is-out {
    opacity: 0;
    transition-duration: var(--dur-1);
  }
  .s-app__caption-note {
    display: block;
    margin-top: 4px;
    font-size: 14px;
    color: var(--fg-2);
  }
}
/* A phone held sideways (short and wide): the stack cannot fit under the nav at
   any phone size, so the caption moves beside the phone, level with its top.
   The pill row, the caption and the top of the screen then show together, and
   a tap changes the caption in view. */
@media (max-width: 899px) and (max-height: 500px) and (orientation: landscape) {
  .s-app__viewer {
    flex-direction: row;
    justify-content: center;
    align-items: flex-start;
  }
  /* Sideways the plinth hugs the phone again (its sides hold the play control). */
  .s-app__plinth {
    align-self: flex-start;
    padding-inline: 64px;
    border-radius: var(--app-plinth-r);
  }
  .s-app__caption {
    flex: none;
    width: min(34ch, calc(100% - var(--app-dw) - 128px - 40px));
    margin: calc(var(--app-pad-top) + var(--app-tag-room)) 0 0 40px;
    padding-inline: 0;
    text-align: left;
  }
}
@media (max-width: 599px) {
  .s-app__head {
    margin-bottom: 28px;
  }
}

/* ---------- Forced colors: the selected pill keeps a visible edge ---------- */
@media (forced-colors: active) {
  .s-app__tab[aria-selected="true"] {
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }
  .s-app__callout {
    border: 1px solid CanvasText;
  }
}

/* ---------- Reduced motion: instant swaps, static stills, no pop ---------- */
@media (prefers-reduced-motion: reduce) {
  .s-app__indicator,
  .s-app__tab,
  .s-app__tab-icon,
  .s-app__tab-v,
  html.js .s-app__tab-line,
  html.js .s-app__tab[aria-selected="true"] .s-app__tab-line,
  .s-app__screen,
  .s-app__screen.is-active,
  .s-app__screen.is-leaving,
  .s-app__still,
  .s-app__callout,
  .s-app__callout.is-on,
  .s-app__rig,
  .s-app__caption {
    transition: none !important;
  }
  .s-app__screen,
  .s-app__screen.is-leaving {
    filter: none;
  }
}
html.reduced .s-app__indicator,
html.reduced .s-app__tab,
html.reduced .s-app__tab-icon,
html.reduced .s-app__tab-v,
html.reduced .s-app__tab-line,
html.reduced .s-app__tab[aria-selected="true"] .s-app__tab-line,
html.reduced .s-app__screen,
html.reduced .s-app__screen.is-active,
html.reduced .s-app__screen.is-leaving,
html.reduced .s-app__still,
html.reduced .s-app__callout,
html.reduced .s-app__callout.is-on,
html.reduced .s-app__rig,
html.reduced .s-app__caption {
  transition: none !important;
}
html.reduced .s-app__screen,
html.reduced .s-app__screen.is-leaving {
  filter: none;
}

/* --------------------------------------------------------------------------
   Section 03b "coaches" (#coaches)  source: .build/sections/03b-coaches.css
   -------------------------------------------------------------------------- */
/* ---------- 03b Coaches (#coaches) ----------
   Lights up (2026-10-09): on the light page (.theme-paper). The prints are
   the app's cards: the #F5F5F3 surface on the #FDFDFC page, warm soft shadows
   only (no outline, ring, hairline or glow); the dark-room pool of light is
   gone. Heading in charcoal two-tone (the quiet half in --paper-quiet).
   Three AI coach portrait prints, soft shadow
   only (no outline, ring or glow). Dealt in from below at -7 / 3 / 8 degrees,
   straightening 95ms apart. Each print is a toggle button that plays its
   coach's voice sample. At rest a print shows only the portrait, name, lane
   and the play disc; the words appear only when the voice speaks them (they
   land under the print in step with the audio and stay after), and a small
   orange level bar follows the voice. Mobile: a horizontal scroll-snap row. */

.s-coaches {
  --print-pad: clamp(8px, 0.85vw, 12px);
  --cap-inset: clamp(4px, 0.5vw, 8px);
  --photo-r: 6px;
  --print-r: calc(var(--photo-r) + var(--print-pad));
  /* Width-led (24vw, 320px max), and on short laptop screens height-led too, so the heading and all
     three prints fit under the nav (D5: 1366x768 and 1280x720 overflowed by 65 to 81px). The 458px is the
     head, its margin, the middle print's 44px drop, the caption and the scroll padding; 0.8 = 1 / 1.25,
     the photo's 4:5. No effect at 900px tall and up, so 1440x900 and 1920x1080 keep 320px prints. */
  --print-w: min(320px, 24vw, max(200px, calc((100svh - 458px) * 0.8)));
  --disc: clamp(38px, 3vw, 44px);
  --disc-in: clamp(10px, 1vw, 14px);
  --deal-ease: cubic-bezier(0.28, 0.96, 0.36, 1.05);
  overflow-x: clip;
  /* No bottom padding (lights up, round 2). The space kept under each print for its words
     (.s-coaches__say, reserved so playing a coach shifts nothing) is the section's bottom air; the
     next section's top padding follows it. On the dark page the section padding came on top of that
     space and left about 410px of blank paper between the prints and the situation photo (46 to 49%
     of a laptop or phone screen) for words most visitors never call up. Now about 270 to 290px,
     near the app tour to coaches step, and a played coach's words still end a full section padding
     above the photo. */
  padding-bottom: 0;
}

/* Header: the two-tone headline left, the intro on the right from the page's shared
   head column (7/12 of the container), bottoms aligned */
.s-coaches__head {
  display: grid;
  gap: 18px;
  margin-bottom: clamp(40px, 5vw, 72px);
}
.s-coaches__title {
  max-width: 12em;
}
.s-coaches__intro {
  display: grid;
  gap: 10px;
  align-content: end;
}
.s-coaches__intro .lead {
  max-width: 40ch;
}
@media (min-width: 900px) {
  .s-coaches__head {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: 0;
    align-items: end;
  }
  .s-coaches__title {
    padding-right: 32px;
  }
  .s-coaches__intro {
    padding-bottom: 0.3em;
  }
}

/* Stage: the row on the plain page (the dark room's pool of light is not used on paper) */
.s-coaches__stage {
  position: relative;
}

/* The row: three prints, centred, small enough that the heading and all
   three fit one laptop viewport */
.s-coaches__row {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 48px);
  align-items: start;
  margin: 0;
  padding: 0;
  list-style: none;
}
.s-coaches__coach {
  position: relative;
  min-width: 0;
}
.s-coaches__coach:nth-child(1) { --deal-y: 120px; --deal-r: -7deg; }
.s-coaches__coach:nth-child(2) { --deal-y: 150px; --deal-r: 3deg; }
.s-coaches__coach:nth-child(3) { --deal-y: 125px; --deal-r: 8deg; }

@media (min-width: 900px) {
  .s-coaches__row {
    grid-template-columns: repeat(3, var(--print-w));
    justify-content: center;
  }
  .s-coaches__coach:nth-child(2) { margin-top: 44px; }
  .s-coaches__coach:nth-child(3) { margin-top: 16px; }
}

/* Deal wrapper: carries only the entrance, so the print's own lift stays separate.
   The transitions exist only once dealt, so arming (hiding) is instant. */
.s-coaches.is-dealt .s-coaches__deal {
  transition:
    transform var(--dur-7) var(--deal-ease),
    opacity var(--dur-4) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 95ms);
}
html.js .s-coaches.is-armed:not(.is-dealt) .s-coaches__deal {
  opacity: 0;
  transform: translateY(var(--deal-y)) rotate(var(--deal-r)) scale(0.9);
}

/* The print: the app's card surface on the page, warm soft shadows only */
.s-coaches__print {
  position: relative;
  display: block;
  width: 100%;
  padding: var(--print-pad);
  border-radius: var(--print-r);
  background-color: var(--paper-2);
  color: var(--charcoal);
  text-align: left;
  box-shadow:
    0 1px 2px rgba(38, 30, 20, 0.08),
    0 10px 22px -12px rgba(38, 30, 20, 0.2),
    0 32px 64px -32px rgba(38, 30, 20, 0.24);
  transform: none;
  filter: brightness(1);
  transition:
    transform var(--dur-3) var(--ease-out),
    filter var(--dur-4) var(--ease-out);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
/* A deeper shadow for the lifted print, faded in rather than repainted. Kept tight on paper:
   the dark page's long 56px / 100px lift fell on the caption under the print and pulled its
   "Sample" label below AA while a coach played. */
.s-coaches__print::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow:
    0 14px 26px -16px rgba(38, 30, 20, 0.26),
    0 30px 56px -34px rgba(38, 30, 20, 0.22);
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease-out);
  pointer-events: none;
}

.s-coaches__photo {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  border-radius: var(--photo-r);
  overflow: hidden;
  background-color: #D9D1C6;
}
.s-coaches__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(1);
  transition: filter var(--dur-4) var(--ease-out);
}

/* Play / stop disc on the photo's bottom-right corner (the whole print is the button) */
.s-coaches__disc {
  position: absolute;
  z-index: 1;
  right: var(--disc-in);
  bottom: var(--disc-in);
  display: grid;
  place-items: center;
  width: var(--disc);
  height: var(--disc);
  border-radius: 50%;
  background-color: var(--paper);
  color: var(--charcoal);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.16),
    0 8px 18px -8px rgba(0, 0, 0, 0.4);
  transition:
    transform var(--dur-3) var(--ease-out),
    background-color var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out);
}
/* The cue: the disc grows into a charcoal pill that names the action ("Play sample",
   "Stop") on keyboard focus and mouse hover. It is the print's focus indicator, drawn
   on the play control inside the photo corner, never as a ring around the portrait. */
.s-coaches__cue {
  position: absolute;
  z-index: 1;
  right: var(--disc-in);
  bottom: var(--disc-in);
  display: grid;
  align-items: center;
  height: var(--disc);
  padding: 0 calc(var(--disc) + 10px) 0 16px;
  border-radius: var(--r-pill);
  background-color: var(--charcoal);
  color: var(--paper);
  font-size: var(--text-small);
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 8px 18px -8px rgba(0, 0, 0, 0.5);
  opacity: 0;
  clip-path: inset(0 0 0 calc(100% - var(--disc)) round var(--r-pill));
  transition:
    opacity var(--dur-2) var(--ease-out),
    clip-path var(--dur-3) var(--ease-out);
  pointer-events: none;
}
.s-coaches__cue-stop,
.s-coaches__print[aria-pressed="true"] .s-coaches__cue-play {
  display: none;
}
.s-coaches__print[aria-pressed="true"] .s-coaches__cue-stop {
  display: inline;
}
.s-coaches__disc svg {
  grid-area: 1 / 1;
  width: 38%;
  height: 38%;
  fill: currentColor;
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-out);
}
.s-coaches__i-play {
  transform: translateX(6%);
}
.s-coaches__i-stop {
  opacity: 0;
  transform: scale(0.6);
}
.s-coaches__print[aria-pressed="true"] .s-coaches__i-play {
  opacity: 0;
  transform: scale(0.6);
}
.s-coaches__print[aria-pressed="true"] .s-coaches__i-stop {
  opacity: 1;
  transform: none;
}

/* Caption on the paper: name and "AI coach" on one baseline, the lane under it */
.s-coaches__cap {
  display: block;
  padding: clamp(12px, 1.2vw, 18px) var(--cap-inset) var(--cap-inset);
}
.s-coaches__nameline {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.s-coaches__name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(24px, 2.1vw, 32px);
  line-height: 1.05;
  letter-spacing: 0;
  color: var(--charcoal);
}
.s-coaches__ai {
  flex: none;
  font-size: var(--text-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: var(--charcoal-2);
  white-space: nowrap;
}
.s-coaches__lane {
  display: block;
  margin-top: 6px;
  font-size: 15px;
  line-height: 1.4;
  color: var(--charcoal-2);
}

/* The small orange level bar under the caption: space always reserved, shown while playing */
.s-coaches__level {
  display: block;
  width: 72px;
  height: 3px;
  margin-top: 14px;
  border-radius: 2px;
  background-color: var(--paper-line);
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out);
}
.s-coaches__level-fill {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background-color: var(--orange);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
.s-coaches__coach.is-playing .s-coaches__level {
  opacity: 1;
}

/* What the coach says, under the print. The space is reserved (no layout shift); the
   words are in the DOM for screen readers and no-JS visitors, and under html.js they
   show only once the voice has spoken them: streamed while playing, kept after. */
.s-coaches__say {
  /* the words hang from the same left edge as the name on the print */
  padding: clamp(20px, 2vw, 28px) var(--cap-inset) 0 calc(var(--print-pad) + var(--cap-inset));
  transition: opacity var(--dur-3) var(--ease-out);
}
html.js .s-coaches__coach:not(.is-playing):not(.is-heard) .s-coaches__say {
  opacity: 0;
}
/* After the deal, state changes are immediate */
.s-coaches.is-settled .s-coaches__deal {
  transition-delay: 0ms;
}
.s-coaches__say-label {
  margin-bottom: 8px;
  font-size: var(--text-small);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.01em;
  /* --fg-2 on paper (#62625F): 6.0:1 on the page and still 5.2:1 where the playing print's
     shadow falls (--fg-3 dropped to 4.4:1 there on phones). */
  color: var(--fg-2);
}
.s-coaches__line {
  max-width: 34ch;
  font-size: var(--text-body);
  line-height: 1.55;
  color: var(--fg-2);
  transition: color var(--dur-5) var(--ease-out);
}

/* Streaming text: words resolve through a soft blur as they are spoken */
.s-coaches__line .word {
  transition:
    opacity var(--dur-3) var(--ease-out),
    filter var(--dur-3) var(--ease-out);
}
.s-coaches__coach.is-streaming .s-coaches__line .word:not(.is-in) {
  opacity: 0;
  filter: blur(4px);
}
.s-coaches__coach.is-wipe .s-coaches__line .word {
  transition: none;
}

/* Playback state */
.s-coaches__coach.is-playing .s-coaches__line {
  color: var(--fg);
  transition-duration: var(--dur-2);
}
.s-coaches__coach.is-playing .s-coaches__print {
  transform: translateY(-8px) scale(1.03);
  transition-timing-function: var(--ease-pop);
}
.s-coaches__coach.is-playing .s-coaches__print::before {
  opacity: 1;
}
.s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print {
  transform: scale(0.97);
  /* on paper a resting print steps back gently (0.8 read as a grey smudge on the light page) */
  filter: brightness(0.95);
}
.s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__photo img {
  filter: saturate(0.55);
}
/* A heard caption stays legible while another coach plays: its line already steps back from
   --fg to --fg-2 (6.0:1). The dark page dimmed it to 0.4, which on paper is 1.8:1. */
.s-coaches.has-playing .s-coaches__coach.is-heard:not(.is-playing) .s-coaches__say {
  opacity: 1;
}

/* Keyboard focus, drawn on the print's own controls (no ring or outline around the
   portrait): the play disc turns charcoal and grows into the "Play sample" cue, the
   name is underlined and, with motion allowed, the print lifts. */
.s-coaches__print:focus-visible {
  outline: none;
}
.s-coaches__print:focus-visible .s-coaches__name {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.16em;
}
.s-coaches__print:focus-visible .s-coaches__disc {
  background-color: var(--charcoal);
  color: var(--paper);
  box-shadow: none;
}
.s-coaches__print:focus-visible .s-coaches__cue {
  opacity: 1;
  clip-path: inset(0 round var(--r-pill));
}
.s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print:focus-visible {
  filter: none;
}
@media (prefers-reduced-motion: no-preference) {
  .s-coaches__coach:not(.is-playing) .s-coaches__print:focus-visible {
    transform: translateY(-4px);
  }
  .s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print:focus-visible {
    transform: translateY(-4px) scale(0.97);
  }
}
.s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print:focus-visible .s-coaches__photo img {
  filter: saturate(0.9);
}
/* Windows High Contrast and other forced colors drop the cue's fills: use the system ring */
@media (forced-colors: active) {
  .s-coaches__print:focus-visible {
    outline: 2px solid Highlight;
    outline-offset: 4px;
  }
}

/* Mouse: a small lift; a resting print gets its color back under the pointer */
@media (hover: hover) and (pointer: fine) {
  .s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print:hover .s-coaches__photo img {
    filter: saturate(0.9);
  }
  .s-coaches__print:hover .s-coaches__disc {
    background-color: var(--charcoal);
    color: var(--paper);
    box-shadow: none;
  }
  .s-coaches__print:hover .s-coaches__cue {
    opacity: 1;
    clip-path: inset(0 round var(--r-pill));
  }
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .s-coaches__print:hover {
    transform: translateY(-4px);
  }
  .s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print:hover {
    transform: translateY(-4px) scale(0.97);
  }
}

/* Phones: a horizontal scroll-snap row, one print and a bit of the next */
@media (max-width: 719px) {
  .s-coaches .s-coaches__row {
    display: flex;
    gap: 14px;
    margin-inline: calc(-1 * var(--gutter));
    /* 8px under the words (was 28px): the print's lift and shadow fall inside the words' space,
       so the bottom padding only had to clear the last line (round 2) */
    padding: 18px var(--gutter) 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .s-coaches__row::-webkit-scrollbar {
    display: none;
  }
  .s-coaches__coach {
    flex: 0 0 min(76vw, 320px);
    scroll-snap-align: start;
  }
  .s-coaches__line {
    font-size: 16px;
  }
  .s-coaches__say {
    padding-top: 20px;
  }
}

/* Short landscape screens (phones held sideways): a whole print stays in the view under the nav.
   The photo keeps its width and gives up height (cover, cropped from the bottom so the face stays);
   about 132px is left for the print padding, the caption and a little air (m8). The explicit width
   keeps the 4:5 ratio from shrinking the width along with the capped height. */
@media (max-height: 500px) {
  .s-coaches__photo {
    width: 100%;
    max-height: max(140px, calc(100svh - var(--nav-space) - 132px));
  }
  .s-coaches__photo img {
    object-position: 50% 24%;
  }
}

/* Reduced motion: prints straight and still, no deal, no lift; the words show whole */
@media (prefers-reduced-motion: reduce) {
  .s-coaches.is-dealt .s-coaches__deal,
  .s-coaches__say,
  .s-coaches__print,
  .s-coaches__print::before,
  .s-coaches__disc,
  .s-coaches__disc svg,
  .s-coaches__cue,
  .s-coaches__photo img,
  .s-coaches__line,
  .s-coaches__line .word {
    transition: none;
  }
  .s-coaches .s-coaches__print,
  .s-coaches .s-coaches__coach.is-playing .s-coaches__print,
  .s-coaches.has-playing .s-coaches__coach:not(.is-playing) .s-coaches__print {
    transform: none;
  }
  .s-coaches .s-coaches__coach.is-streaming .s-coaches__line .word {
    opacity: 1;
    filter: none;
  }
}
html.reduced .s-coaches .s-coaches__deal {
  opacity: 1;
  transform: none;
  transition: none;
}
/* Pause motion: the deal happens at once */
html.motion-paused .s-coaches.is-dealt .s-coaches__deal {
  transition: none;
}

/* --------------------------------------------------------------------------
   Section 05 "situation" (#situation)  source: .build/sections/05-situation.css
   -------------------------------------------------------------------------- */
/* ==========================================================================
   05 Your situation (#situation)
   Lights up (2026-10-09): the section is light page (.theme-paper); the
   photo stage stays a dark rounded panel on it (the list and "Gravitas asks"
   need the dark photo ground), and foundation 2 hands the stage the ink tokens
   back (.theme-paper .stage), so its focus rings stay light.
   Stage frame, situation stills that crossfade (opacity only) with a slow
   drift on the active still; the stacked list of situations is the only
   big text; one orange square marker; the app's question bottom-right.
   ========================================================================== */

.s-situation {
  --sit-pad: clamp(20px, 3.4vw, 48px);
  --sit-size: var(--display-m);
  --sit-gut: 30px;
  --sit-mk: 10px;
  --sit-mk-nudge: 0.04em;
  --sit-fade: 600ms;
  /* The nav's "Practice" jump lands the stage on the frame inset, like a normal
     scroll does, instead of one section padding lower (html adds nav-space + 12px
     of scroll padding; the stage pads its own content clear of the nav). */
  scroll-margin-top: calc(var(--frame-inset) - var(--section-y) - var(--nav-space) - 12px);
}

/* ---------- Stage ---------- */
.s-situation__stage {
  display: flex;
  flex-direction: column;
  min-height: clamp(600px, calc(100svh - var(--frame-inset) * 2), 980px);
}

.s-situation__still {
  position: absolute;
  inset: 0;
  opacity: 0;
}
.s-situation__still img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--sit-pos, 50% 50%);
  transform-origin: var(--sit-origin, 50% 60%);
}
.s-situation__still[data-slug="interviews"] { --sit-pos: 58% 35%; --sit-origin: 58% 42%; }
.s-situation__still[data-slug="meetings"] { --sit-pos: 62% 40%; --sit-origin: 70% 35%; }
.s-situation__still[data-slug="presentations"] { --sit-pos: 38% 35%; --sit-origin: 28% 30%; }
.s-situation__still[data-slug="difficult-conversations"] { --sit-pos: 44% 50%; --sit-origin: 45% 50%; }
.s-situation__still[data-slug="everyday-conversations"] { --sit-pos: 52% 55%; --sit-origin: 55% 60%; }
.s-situation__still[data-slug="your-own-question"] { --sit-pos: 70% 50%; --sit-origin: 80% 70%; }
/* Phone (9:16) crops: position and drift origin per still. The two-person scenes
   (interviews, difficult and everyday conversations) keep both people in the upper
   part of the frame, above the list, so their drift grows from there. */
.s-situation__still[data-slug="interviews"] { --sit-pos-m: 50% 50%; --sit-origin-m: 50% 22%; }
.s-situation__still[data-slug="presentations"] { --sit-pos-m: 50% 50%; --sit-origin-m: 47% 20%; }
.s-situation__still[data-slug="difficult-conversations"] { --sit-pos-m: 50% 50%; --sit-origin-m: 50% 24%; }
.s-situation__still[data-slug="everyday-conversations"] { --sit-pos-m: 50% 50%; --sit-origin-m: 50% 22%; }

/* Crossfade: the incoming still fades in on top; the outgoing one stays lit under it. */
.s-situation__still.is-active,
.s-situation__still.is-prev {
  opacity: 1;
  transition: opacity var(--sit-fade) var(--ease-in-out);
}

/* Slow drift on the active still, 1 to 1.035 in 5 s, then it rests. It holds while
   the frame is out of view (.is-away) and freezes under Pause motion. */
@keyframes s-situation-drift {
  from { transform: scale(1); }
  to { transform: scale(1.035); }
}
.s-situation__still.is-drift img {
  animation: s-situation-drift 5s cubic-bezier(0.3, 0.1, 0.3, 1) both;
}
.s-situation__stage.is-away .s-situation__still.is-drift img,
html.still .s-situation__still.is-drift img {
  animation-play-state: paused;
}

.s-situation__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(95% 80% at 0% 100%, rgba(10, 9, 8, 0.64) 0%, rgba(10, 9, 8, 0.5) 40%, rgba(10, 9, 8, 0.2) 64%, rgba(10, 9, 8, 0) 82%),
    linear-gradient(to top, rgba(10, 9, 8, 0.8) 0%, rgba(10, 9, 8, 0.56) 24%, rgba(10, 9, 8, 0.2) 48%, rgba(10, 9, 8, 0) 66%),
    linear-gradient(to right, rgba(10, 9, 8, 0.36) 0%, rgba(10, 9, 8, 0) 46%);
}

.s-situation__content {
  flex: 1;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px clamp(32px, 4vw, 64px);
  padding: calc(var(--nav-space) + 24px) max(var(--sit-pad), var(--safe-right)) var(--sit-pad) max(var(--sit-pad), var(--safe-left));
  color: var(--fg-dark);
}

.s-situation__title {
  max-width: 34ch;
  margin-bottom: 14px;
  padding-left: var(--sit-gut);
  font-family: var(--font-text);
  font-size: var(--text-body);
  font-weight: 500;
  line-height: 1.35;
  color: var(--fg-dark);
  /* A tight dark halo keeps the line readable where it crosses hair or a bright window. */
  text-shadow:
    0 0 3px rgba(10, 9, 8, 0.75),
    0 1px 8px rgba(10, 9, 8, 0.6),
    0 1px 20px rgba(10, 9, 8, 0.5);
}

.s-situation__listwrap {
  position: relative;
}
.s-situation__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.s-situation__list > li {
  display: flex;
}
.s-situation__opt {
  display: inline-flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 44px;
  padding: 0 4px 0 var(--sit-gut);
  border-radius: 6px;
  color: var(--fg-dark);
  font-family: var(--font-display);
  font-size: var(--sit-size);
  font-weight: 500;
  line-height: 1.07;
  letter-spacing: -0.005em;
  text-align: left;
  white-space: nowrap;
  text-shadow: 0 1px 24px rgba(10, 9, 8, 0.35);
  -webkit-tap-highlight-color: transparent;
}
.s-situation__opt:focus-visible {
  outline-offset: 2px;
}
.s-situation__name {
  transition: opacity var(--dur-3) var(--ease-out);
}
html.js .s-situation__opt:not(.is-active) .s-situation__name {
  opacity: 0.42;
}
/* The notebook still ("Your own question") is the brightest: at 0.42 the unselected names fall under
   3:1 over it, so they go lighter while it shows (the same 0.62 as on short landscape screens). */
html.js .s-situation:has(.s-situation__still[data-slug="your-own-question"].is-active) .s-situation__opt:not(.is-active) .s-situation__name {
  opacity: 0.62;
}
@media (hover: hover) and (pointer: fine) {
  html.js .s-situation__opt:not(.is-active):hover .s-situation__name {
    opacity: 0.72;
  }
}
/* The one orange moment in the frame: a small square that slides between lines. */
.s-situation__marker {
  --y: calc((max(44px, var(--sit-size) * 1.07) - var(--sit-mk)) / 2 + var(--sit-mk-nudge));
  position: absolute;
  top: 0;
  left: 2px;
  width: var(--sit-mk);
  height: var(--sit-mk);
  border-radius: 1px;
  background-color: var(--orange);
  transform: translate3d(0, var(--y), 0);
  transition:
    transform var(--dur-4) var(--ease-out),
    opacity var(--dur-4) var(--ease-out) 320ms;
  pointer-events: none;
}
.s-situation__marker.is-snap {
  transition: none;
}
html.js .s-situation__content:not(.is-in) .s-situation__marker {
  opacity: 0;
}

/* The question the app asks, bottom-right. Stacked so the box never changes size. */
.s-situation__ask {
  display: grid;
  flex: none;
  width: min(360px, 34%);
  padding-bottom: 4px;
}
.s-situation__q {
  grid-area: 1 / 1;
  align-self: end;
}
.s-situation__q-label {
  margin-bottom: 10px;
  font-size: var(--text-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: rgba(243, 239, 233, 0.9);
  text-shadow:
    0 0 2px rgba(10, 9, 8, 0.5),
    0 1px 12px rgba(10, 9, 8, 0.55);
}
.s-situation__q-text {
  font-family: var(--font-display);
  font-size: clamp(22px, 1.9vw, 30px);
  font-weight: 500;
  line-height: 1.18;
  color: var(--fg-dark);
  text-wrap: balance;
  text-shadow: 0 1px 20px rgba(10, 9, 8, 0.4);
}
html.js .s-situation__q {
  transition:
    opacity var(--dur-4) var(--ease-out) 140ms,
    transform var(--dur-5) var(--ease-out) 140ms,
    filter var(--dur-4) var(--ease-out) 140ms,
    visibility 0s linear 0s;
}
html.js .s-situation__q:not(.is-active) {
  visibility: hidden;
  opacity: 0;
  transform: translateY(0.35em);
  filter: blur(6px);
  transition:
    opacity 200ms ease,
    transform 0s linear 260ms,
    filter 200ms ease,
    visibility 0s linear 260ms;
}
html.js .s-situation__q.is-out {
  transform: translateY(-0.25em);
  transition:
    opacity 200ms ease,
    transform 260ms var(--ease-out),
    filter 200ms ease,
    visibility 0s linear 260ms;
}

/* Tablet and phone: the list over the lower frame, the question under it. A phone
   held sideways (520 to 899px wide, 500px or less tall) keeps the desktop row,
   list left and question bottom-right, so the question changes in view next to
   the option tapped. */
@media (max-width: 899px) and (min-height: 501px), (max-width: 519px) {
  .s-situation__content {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-end;
    gap: 26px;
  }
  .s-situation__ask {
    width: auto;
    max-width: 30ch;
    padding-left: var(--sit-gut);
  }
}
/* The sideways row: the six 44px lines take 264px, so the title drops to a 15px
   line with a tighter gap. */
@media (min-width: 520px) and (max-width: 899px) and (max-height: 500px) {
  .s-situation {
    --sit-pad: 18px;
  }
  .s-situation__title {
    font-size: 15px;
    margin-bottom: 8px;
  }
  /* The six lines climb most of this short frame, above the scrim's dark
     lower part, so the unselected names go lighter to keep 3:1 over the
     brighter stills (the notebook shot measured 2.3:1 at 0.42). */
  html.js .s-situation__opt:not(.is-active) .s-situation__name {
    opacity: 0.62;
  }
}
@media (max-width: 599px) {
  .s-situation {
    --sit-pad: 18px;
    --sit-size: clamp(26px, 7.4vw, 34px);
    --sit-gut: 22px;
    --sit-mk: 8px;
  }
  .s-situation__stage {
    min-height: clamp(600px, calc(100svh - var(--frame-inset) * 2), 820px);
  }
  .s-situation__scrim {
    background:
      linear-gradient(to top, rgba(10, 9, 8, 0.88) 0%, rgba(10, 9, 8, 0.78) 30%, rgba(10, 9, 8, 0.6) 50%, rgba(10, 9, 8, 0.22) 62%, rgba(10, 9, 8, 0) 72%);
  }
  /* Two short lines on the calm left side, clear of faces on the right. */
  .s-situation__title {
    max-width: 21ch;
    font-size: 15px;
    margin-bottom: 8px;
  }
  .s-situation__opt {
    align-items: center;
  }
  .s-situation__q-text {
    font-size: 22px;
  }
}
/* The narrowest sideways row (520 to 599px wide): smaller lines leave the
   question a readable column. */
@media (min-width: 520px) and (max-width: 599px) and (max-height: 500px) {
  .s-situation {
    --sit-size: 26px;
  }
  .s-situation__ask {
    width: min(360px, 40%);
  }
}
/* At 340px tall or less the nav and the six lines need more than the screen, so
   the question sits a little higher and stays whole while the first line is in view. */
@media (min-width: 520px) and (max-width: 599px) and (max-height: 340px) {
  .s-situation__ask {
    margin-bottom: 16px;
  }
}
/* Sideways phones too short for the title and the whole list under the nav
   (the title needs about 386px of height on one line, 400px on two): the list
   and the question carry the frame, and the heading stays for screen readers. */
@media (min-width: 600px) and (max-width: 899px) and (max-height: 385px),
  (min-width: 520px) and (max-width: 599px) and (max-height: 400px) {
  .s-situation__title {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
/* Portrait frames use the 9:16 crops (art direction in the <picture>). */
@media (max-aspect-ratio: 3/4) {
  .s-situation__still img {
    object-position: var(--sit-pos-m, 50% 50%);
    transform-origin: var(--sit-origin-m, 50% 45%);
  }
}

/* ---------- Forced colors: the selected line stays visible without fills ---------- */
@media (forced-colors: active) {
  .s-situation__opt[aria-pressed="true"] .s-situation__name {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.12em;
  }
  .s-situation__marker {
    forced-color-adjust: none;
    background-color: Highlight;
  }
}

/* ---------- Reduced motion: instant swaps, no drift ---------- */
@media (prefers-reduced-motion: reduce) {
  .s-situation__still,
  .s-situation__still.is-active,
  .s-situation__still.is-prev,
  .s-situation__marker,
  .s-situation__name,
  html.js .s-situation__q,
  html.js .s-situation__q:not(.is-active) {
    transition: none !important;
  }
  .s-situation__still img {
    animation: none !important;
  }
  html.js .s-situation__q:not(.is-active),
  html.js .s-situation__q.is-out {
    transform: none;
    filter: none;
  }
}
html.reduced .s-situation__still,
html.reduced .s-situation__marker,
html.reduced .s-situation__q {
  transition: none !important;
}
html.reduced .s-situation__still img {
  animation: none !important;
}

/* --------------------------------------------------------------------------
   Section 08 "faq" (#faq)  source: .build/sections/08-faq.css
   -------------------------------------------------------------------------- */
/* ---------- 08 FAQ #faq ----------
   Lights up (2026-10-09): no longer a band. The page around it is paper
   now, so the inset and the rounded corners are gone (they would show the ink
   body in 10px strips beside it) and the FAQ is simply more of the light page.
   Was: the one paper band on the homepage, inset like the stage frames.
   Heading left (sticky on wide screens), questions right on hairlines
   (Cohere). An accordion (grid rows 0fr to 1fr, 250 ms both ways) with one
   item open at a time; a thin orange rule draws across the top of the open
   item. faq.js toggles [data-open] and aria-expanded; the hidden states apply
   only under html.js, so without JS every answer is visible. */

.s-faq__grid {
  display: grid;
  gap: clamp(36px, 6vw, 56px);
}
.s-faq__head {
  display: grid;
  align-content: start;
  gap: 20px;
}
.s-faq__title {
  color: var(--fg);
}
.s-faq__aside {
  max-width: 32ch;
  font-size: var(--text-small);
  line-height: 1.5;
  color: var(--fg-2);
}
.s-faq__link {
  color: var(--fg);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: rgba(38, 38, 38, 0.32);
  transition: text-decoration-color var(--dur-2) var(--ease-out);
  overflow-wrap: anywhere;
}
@media (hover: hover) {
  .s-faq__link:hover {
    text-decoration-color: currentColor;
  }
}
/* The contact address is the FAQ's only way out: a 44px+ tap target (m4). The padding grows the hit
   area and the equal negative margin keeps the line box, so the text does not move. */
.s-faq__aside .s-faq__link {
  display: inline-block;
  padding-block: 13px;
  margin-block: -13px;
}

@media (min-width: 1024px) {
  .s-faq__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
    column-gap: clamp(48px, 5vw, 96px);
  }
  .s-faq__head {
    position: sticky;
    top: calc(var(--nav-space) + 40px);
  }
}

/* List and hairlines. Each item draws its own top hairline; the list draws the last one. */
.s-faq__list {
  position: relative;
}
.s-faq__list::after,
.s-faq__item::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background-color: var(--line-2);
  transform-origin: 0 50%;
}
.s-faq__list::after {
  bottom: 0;
}
.s-faq__item {
  position: relative;
}
.s-faq__item::before {
  top: 0;
}

/* The orange rule: draws in from the left on open, sweeps out to the right on close. */
.s-faq__rule {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: -0.5px;
  height: 2px;
  background-color: var(--orange);
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform var(--dur-2) var(--ease-out);
  pointer-events: none;
}
.s-faq__item[data-open] .s-faq__rule {
  transform: scaleX(1);
  transform-origin: 0 50%;
  transition: transform var(--dur-5) var(--ease-out) var(--s-faq-rule-delay, 40ms);
}

/* Question row */
.s-faq__q {
  margin: 0;
}
.s-faq__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  min-height: 80px;
  padding: 22px 0;
  border-radius: var(--r-1);
  color: var(--fg);
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.s-faq__qtext {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(21px, 1.75vw, 27px);
  line-height: 1.2;
  letter-spacing: 0;
  text-wrap: balance;
}
.s-faq__chev {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--r-pill);
  color: var(--fg);
  transition:
    transform var(--dur-2) var(--ease-out),
    background-color var(--dur-2) var(--ease-out);
}
.s-faq__chev svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.s-faq__chev path {
  vector-effect: non-scaling-stroke;
}
.s-faq__item[data-open] .s-faq__chev {
  transform: scaleY(-1);
}
@media (hover: hover) {
  .s-faq__btn:hover .s-faq__chev {
    background-color: var(--surface-1);
  }
}
.s-faq__btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
}

/* Answer */
.s-faq__panel {
  display: grid;
  grid-template-rows: 1fr;
}
.s-faq__inner {
  min-height: 0;
  overflow: hidden;
}
.s-faq__inner p {
  max-width: 60ch;
  padding: 0 clamp(0px, 5vw, 60px) 30px 0;
  font-size: var(--text-body);
  line-height: 1.6;
  color: var(--fg-2);
}
html.js .s-faq__panel {
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-2) var(--ease-out);
}
html.js .s-faq__item[data-open] .s-faq__panel {
  grid-template-rows: 1fr;
}
html.js .s-faq__inner {
  opacity: 0;
  filter: blur(2px);
  visibility: hidden;
  transition:
    opacity var(--dur-2) var(--ease-out),
    filter var(--dur-2) var(--ease-out),
    visibility 0s linear var(--dur-2);
}
html.js .s-faq__item[data-open] .s-faq__inner {
  opacity: 1;
  filter: none;
  visibility: visible;
  transition:
    opacity var(--dur-2) var(--ease-out),
    filter var(--dur-2) var(--ease-out),
    visibility 0s linear 0s;
}

/* Entrance (the list is a foundation reveal group, core.js adds .is-in):
   hairlines draw left to right 60 ms apart, questions rise in behind them,
   and the open item's orange rule follows. */
.s-faq__item::before {
  transition: transform var(--dur-6) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.s-faq__list::after {
  transition: transform var(--dur-6) var(--ease-out) 420ms;
}
.s-faq__q {
  transition:
    opacity var(--dur-5) var(--ease-out),
    transform var(--dur-5) var(--ease-out);
  transition-delay: calc(80ms + var(--i, 0) * 60ms);
}
html.js .s-faq__list:not(.is-in)::after,
html.js .s-faq__list:not(.is-in) .s-faq__item::before,
html.js .s-faq__list:not(.is-in) .s-faq__rule {
  transform: scaleX(0);
}
html.js .s-faq__list:not(.is-in) .s-faq__q {
  opacity: 0;
  transform: translateY(12px);
}
html.js .s-faq__list:not(.is-in) .s-faq__item[data-open] .s-faq__inner {
  opacity: 0;
}
.s-faq__list:not(.is-settled) {
  --s-faq-rule-delay: 520ms;
}
.s-faq__list:not(.is-settled) .s-faq__item[data-open] .s-faq__inner {
  transition:
    opacity var(--dur-5) var(--ease-out) 360ms,
    filter var(--dur-5) var(--ease-out) 360ms,
    visibility 0s linear 0s;
}

@media (max-width: 599px) {
  .s-faq__btn {
    min-height: 72px;
    padding: 18px 0;
    gap: 16px;
  }
  .s-faq__qtext {
    font-size: 21px;
  }
  .s-faq__chev {
    width: 32px;
    height: 32px;
  }
  .s-faq__inner p {
    padding-right: 0;
    padding-bottom: 26px;
  }
}

/* Pause motion: the entrance happens at once; the accordion stays a UI transition. */
html.motion-paused .s-faq__item::before,
html.motion-paused .s-faq__list::after,
html.motion-paused .s-faq__q {
  transition: none;
}

/* Reduced motion: no transitions anywhere, everything in its final place. */
@media (prefers-reduced-motion: reduce) {
  .s-faq__rule,
  .s-faq__item[data-open] .s-faq__rule,
  .s-faq__chev,
  .s-faq__item::before,
  .s-faq__list::after,
  .s-faq__q,
  html.js .s-faq__panel,
  html.js .s-faq__inner,
  html.js .s-faq__item[data-open] .s-faq__inner,
  .s-faq__list:not(.is-settled) .s-faq__item[data-open] .s-faq__inner {
    transition: none;
  }
  html.js .s-faq__list:not(.is-in)::after,
  html.js .s-faq__list:not(.is-in) .s-faq__item::before,
  html.js .s-faq__list:not(.is-in) .s-faq__q {
    opacity: 1;
    transform: none;
  }
  html.js .s-faq__list:not(.is-in) .s-faq__item[data-open] .s-faq__rule {
    transform: scaleX(1);
  }
  html.js .s-faq__list:not(.is-in) .s-faq__item[data-open] .s-faq__inner {
    opacity: 1;
  }
}
html.reduced .s-faq__rule,
html.reduced .s-faq__item[data-open] .s-faq__rule,
html.reduced .s-faq__chev,
html.reduced .s-faq__item::before,
html.reduced .s-faq__list::after,
html.reduced .s-faq__q,
html.reduced .s-faq__panel,
html.reduced .s-faq__inner,
html.reduced .s-faq__item[data-open] .s-faq__inner {
  transition: none;
}

/* --------------------------------------------------------------------------
   Section 09 "get" (#get)  source: .build/sections/09-get.css
   -------------------------------------------------------------------------- */
/* ---------- 09 Closer #get ----------
   Lights up (2026-10-09): the section is light page (.theme-paper), so the
   sky stage is a framed panel on paper and the footer's gutters sit on paper
   while it covers the stage (site.base.css 16 carries the paper itself where
   the stage does not pin). The sky, the copy and the choreography are unchanged.
   A cloud-sky stage (the app's blue and coral atmosphere) that pins while the
   footer sheet scrolls up over it. Two photographic layers drift on their own
   cycles (54 s far, 38 s near, from the app's CloudAtmosphere tokens).
   get.js measures the footer and writes --get-under; without it (no JS or
   reduced motion) the stage simply scrolls and the footer follows. */

.s-get {
  --get-under: 0px;
  --s-get-sine: cubic-bezier(0.37, 0, 0.63, 1);
  --s-get-white: #FFFFFF;
  position: relative;
  z-index: 1;
  padding-top: var(--frame-inset);
  margin-bottom: calc(var(--get-under) * -1);
}
.s-get__pin {
  position: sticky;
  top: var(--frame-inset);
}
.s-get__under {
  height: var(--get-under);
}
.s-get__stage {
  height: calc(100svh - var(--frame-inset) * 2);
  min-height: 540px;
  background-color: #22252D;
}

/* Sky: two drifting layers, a legibility veil, then the foundation grain. */
.s-get__sky {
  overflow: hidden;
  border-radius: inherit;
  transform-origin: 50% 40%;
}
.s-get__layer {
  position: absolute;
  inset: 0;
  will-change: transform;
}
.s-get__layer picture,
.s-get__layer img {
  display: block;
  width: 100%;
  height: 100%;
}
.s-get__layer img {
  max-width: none;
  object-fit: cover;
  /* Desktop plate: x keeps the one coral crest in frame on narrow screens,
     y leaves open sky above it for the headline. */
  object-position: 60% 16%;
}
@media (max-aspect-ratio: 3/5) {
  .s-get__layer img {
    object-position: 50% 50%;
  }
}

/* Drift. Each layer follows the app's path: x = sin, y = cos - 1, as two
   sine-eased half cycles. `translate` carries x, `transform` carries y, and
   `scale` keeps the layer larger than the frame so no edge ever shows. */
.s-get__far {
  scale: 1.12;
  /* Scaled from the top edge, so the crest settles a little lower and the
     headline keeps open sky on every screen shape. */
  transform-origin: 50% 0%;
  animation:
    s-get-far-x 27s var(--s-get-sine) -13.5s infinite alternate both,
    s-get-far-y 27s var(--s-get-sine) 0s infinite alternate both;
  animation-play-state: paused;
}
.s-get__near {
  scale: 1.18;
  /* Scaled about a point near the foot, so the layer reaches about 2.5%
     below the frame and its lower edge never shows at the top of the drift. */
  transform-origin: 50% 86%;
  animation:
    s-get-near-x 19s var(--s-get-sine) -9.5s infinite alternate both,
    s-get-near-y 19s var(--s-get-sine) 0s infinite alternate both;
  animation-play-state: paused;
}
.s-get.is-drifting .s-get__far,
.s-get.is-drifting .s-get__near {
  animation-play-state: running;
}
@keyframes s-get-far-x {
  from { translate: -2.5% 0; }
  to { translate: 2.5% 0; }
}
@keyframes s-get-far-y {
  from { transform: translateY(0); }
  to { transform: translateY(-1.6%); }
}
@keyframes s-get-near-x {
  from { translate: 4.5% 0; }
  to { translate: -4.5% 0; }
}
@keyframes s-get-near-y {
  from { transform: translateY(0); }
  to { transform: translateY(-1.6%); }
}

/* Veil: the app's invitation veil (a flat 14% plus a darker foot), a touch
   heavier at the top so the nav and headline sit on calm sky. The grain
   element above it breaks up any banding. */
.s-get__veil {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom,
      rgba(10, 12, 18, 0.30) 0%,
      rgba(10, 12, 18, 0.10) 26%,
      rgba(10, 12, 18, 0) 44%,
      rgba(10, 12, 18, 0.06) 62%,
      rgba(10, 12, 18, 0.46) 100%),
    rgba(10, 12, 18, 0.12);
  pointer-events: none;
}

/* Content: centered column. The stage__content class sets z 3. */
.s-get__content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding:
    calc(var(--nav-space) + 8px)
    max(var(--gutter), var(--safe-right))
    clamp(56px, 9vh, 104px)
    max(var(--gutter), var(--safe-left));
  text-align: center;
  color: var(--s-get-white);
}
.s-get__title {
  max-width: 14ch;
  color: var(--s-get-white);
  text-shadow: 0 2px 32px rgba(12, 18, 30, 0.22);
}
.s-get__act {
  margin-top: clamp(32px, 6.4vh, 72px);
  display: grid;
  justify-items: center;
  gap: 16px;
}
.s-get__cta {
  justify-content: center;
}
.s-get__micro {
  position: relative;
  color: var(--s-get-white);
  text-shadow: 0 1px 12px rgba(12, 18, 30, 0.45);
}
/* The trial terms sit on the lit cloud bank on wide screens: a soft,
   blurred shade keeps them at 4.5:1 or better. */
.s-get__micro::before {
  content: "";
  position: absolute;
  inset: -6px -20px;
  z-index: -1;
  border-radius: 999px;
  background-color: rgba(10, 12, 18, 0.34);
  filter: blur(14px);
  pointer-events: none;
}
.s-get__content :focus-visible {
  outline-color: var(--s-get-white);
}

/* Local pause for the drift, anchored to the frame's bottom-right corner. */
.s-get__pause {
  position: absolute;
  z-index: 5;
  right: max(14px, var(--safe-right));
  bottom: 14px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  color: var(--s-get-white);
  /* A solid tint, no backdrop blur: the clouds drift under it. */
  background-color: rgba(10, 12, 18, 0.46);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2);
  transition:
    background-color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
.s-get__pause svg {
  grid-area: 1 / 1;
  width: 14px;
  height: 14px;
  fill: currentColor;
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.s-get__i-play {
  opacity: 0;
  transform: scale(0.6);
}
.s-get__pause[aria-pressed="true"] .s-get__i-pause {
  opacity: 0;
  transform: scale(0.6);
}
.s-get__pause[aria-pressed="true"] .s-get__i-play {
  opacity: 1;
  transform: none;
}
@media (hover: hover) {
  .s-get__pause:hover {
    background-color: rgba(10, 12, 18, 0.62);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);
  }
}
.s-get__pause:active {
  transform: scale(0.94);
}
.s-get__pause:focus-visible {
  outline: 2px solid var(--s-get-white);
  outline-offset: 3px;
}
/* Nothing to pause before JS arms the drift. */
html:not(.js) .s-get__pause {
  display: none;
}

/* Phones: headline high, actions on the dark bank (the app's invitation
   layout). */
@media (max-width: 599px) {
  .s-get__stage {
    min-height: 600px;
  }
  .s-get__content {
    justify-content: flex-start;
    padding-top: calc(var(--nav-space) + 28px);
    padding-bottom: calc(28px + var(--safe-bottom));
  }
  .s-get__title {
    max-width: 12ch;
  }
  .s-get__act {
    margin-top: auto;
    padding-top: 40px;
    gap: 14px;
  }
  .s-get__cta {
    flex-direction: column;
    gap: 12px;
  }
  .s-get__micro {
    max-width: 27ch;
    font-size: 13px;
  }
  .s-get__pause {
    right: 10px;
    bottom: 10px;
  }
}

/* Short viewports (landscape phones, small laptop windows): a pinned stage
   taller than the viewport would hide its own foot, so the stage unpins, grows
   to its content and the footer simply follows (as under reduced motion).
   get.js reads the pin's position and skips the cover choreography. */
@media (max-height: 620px) {
  .s-get {
    margin-bottom: 0;
  }
  .s-get__pin {
    position: relative;
    top: auto;
  }
  .s-get__under {
    display: none;
  }
  .s-get__stage {
    height: auto;
    min-height: calc(100svh - var(--frame-inset) * 2);
  }
  .s-get__content {
    position: relative;
    inset: auto;
    min-height: inherit;
  }
  .s-get__title {
    font-size: min(var(--display-xl), 13vh);
  }
}

/* Reduced motion: still sky, no pin (the footer simply follows). */
@media (prefers-reduced-motion: reduce) {
  .s-get__far,
  .s-get__near {
    animation: none;
  }
  .s-get__pause {
    display: none;
  }
  .s-get {
    margin-bottom: 0;
  }
  .s-get__pin {
    position: relative;
    top: auto;
  }
  .s-get__under {
    display: none;
  }
}
html.reduced .s-get__far,
html.reduced .s-get__near {
  animation: none;
}
html.reduced .s-get__pause {
  display: none;
}
html.reduced .s-get {
  margin-bottom: 0;
}
html.reduced .s-get__pin {
  position: relative;
  top: auto;
}
html.reduced .s-get__under {
  display: none;
}
