/* ============================================================================
   milo.live: the page's own styles.
   The engine (scrollcraft.css) is themed through its tokens and never edited.

   Two layouts share one markup:
     static   the baseline: no sticky Milo column, every result listed in order
              with its "You:" caption, every wake line violet. Reduced motion
              gets this. (With no script at all the engine never mounts; a
              <noscript> rule in index.html opens its cues and entrances.)
     motion   html.milo-motion, set by milo.js only when motion is allowed:
              the split stage, Milo's column header, the trigger, the result log.
   Violet means "Milo heard you": at rest the only violet is the glasses mark
   (and the LIVE dot); woken lines, the lifted mark, the wake accent and the
   Listening pill light up together.
   ========================================================================== */

@font-face {
  font-family: "Inter";
  src: url("fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------- tokens -- */
:root {
  --sc-canvas: #FFF9EF;
  --sc-surface: #FFFFFF;
  --sc-ink: #29262E;
  --sc-ink-soft: #6A6571;
  --sc-accent: #6D2CFF;
  --sc-accent-ink: #FFFFFF;
  --sc-font-display: "Inter", system-ui, sans-serif;
  --sc-font-text: "Inter", system-ui, sans-serif;
  --sc-shadow-color: 262 18% 12%;

  --milo-ink: #29262E;          /* Milo's column, always */
  --milo-cream: #FFF9EF;
  --milo-mist: #B9B2C2;         /* muted text on ink */
  --milo-border: #DDD8E4;
  --milo-violet: #6D2CFF;
  --milo-violet-light: #B9A0FF; /* the same hue, light stop, for violet on ink */
  --milo-lavender: #F2EBFF;
  --milo-wake: var(--milo-violet);  /* woken lines on the host column */
  --milo-scrim: 0.72;           /* hero scrim density at the copy */

  --gut: clamp(16px, 4vw, 56px);
  --playhead: 58svh;
  --r-card: 12px;
  --r-pill: 999px;
}

/* Dark: the host column goes deep warm ink; Milo's column, the trigger and
   the cards are unchanged; the hero scrim gets denser. */
:root[data-theme="dark"] {
  --sc-canvas: #1B1920;
  --sc-ink: #FFF9EF;
  --sc-ink-soft: #B9B2C2;
  --milo-wake: var(--milo-violet-light);
  --milo-scrim: 0.84;
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --sc-canvas: #1B1920;
    --sc-ink: #FFF9EF;
    --sc-ink-soft: #B9B2C2;
    --milo-wake: var(--milo-violet-light);
    --milo-scrim: 0.84;
  }
}
:root[data-theme="light"] { color-scheme: light; }

/* ------------------------------------------------------------------ base -- */
html { scroll-behavior: auto; }
body { background: var(--sc-canvas); color: var(--sc-ink); font-feature-settings: "cv11", "ss01"; }
p, ol, ul, figure { margin: 0; }
ol, ul { padding: 0; list-style: none; }
.sc-display { font-weight: 650; }
.sc-display--md { font-size: clamp(1.9rem, 1.4rem + 1.6vw, 2.75rem); }

/* ------------------------------------------------------------ the stage -- */
.stage { position: relative; display: grid; grid-template-columns: 1fr 1fr; }
.you { grid-column: 1; grid-row: 1; min-width: 0; }

/* Milo's column. Ink ground, cream text: the token AND colour are restated,
   because a redefined token does not re-ink inherited text (taste.md). */
.milo {
  grid-column: 2; grid-row: 1; align-self: start; min-width: 0;
  --sc-ink: var(--milo-cream);
  --sc-ink-soft: var(--milo-mist);
  background: var(--milo-ink);
  color: var(--sc-ink);
  padding: var(--sc-8) var(--gut);
}

/* ---------------------------------------------------------------- hero -- */
.hero { background: #1B1920; }
.hero .sc-stage__poster { object-position: 50% 40%; }
.hero video[data-sc-scrub] { object-position: 50% 40%; }
/* A corner of density where the copy sits (top-left), a sibling of the copy.
   Ink-coloured, not canvas-coloured: the type over the photo is cream. */
.hero__scrim {
  inset: 0 auto auto 0; width: 85%; height: 50%;
  background: rgb(27 25 32 / var(--milo-scrim));
  -webkit-mask-image: linear-gradient(to right, #000 62%, transparent 100%), linear-gradient(to bottom, #000 62%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to right, #000 62%, transparent 100%), linear-gradient(to bottom, #000 62%, transparent 100%);
  mask-composite: intersect;
}
.hero__copy {
  position: absolute; z-index: var(--sc-z-copy);
  top: clamp(1.5rem, 4vh, 2.5rem); left: var(--gut); right: var(--gut);
  color: var(--milo-cream);
}
.hero__lockup { width: 166px; height: auto; }
.tagline {
  margin-top: var(--sc-3);
  font-size: var(--sc-t-sm); font-weight: 500; letter-spacing: 0.01em;
  color: var(--milo-cream);
}
.hero__h1 {
  margin-top: clamp(2rem, 9vh, 5.5rem);
  font-size: var(--sc-t-3xl);
  line-height: 1.02;
  color: var(--milo-cream);
}
.h1-you, .h1-milo { display: block; width: fit-content; }
.tagline, .hero__brand { width: fit-content; }

/* ------------------------------------------------------------ the acts -- */
/* One text system for the host column (decision 5). Headings, body, the P.S.
   and the notes sit on one left axis in every act. The transcript is its own
   lane: a 30ch block against the column's inner gutter, facing Milo, ending at
   the trigger mark. ?tx=right right-aligns the text inside the lane. */
:root {
  --t-body: 1.1875rem;   /* 19px */
  --t-line: 1.3125rem;   /* 21px */
  --t-note: 0.9375rem;   /* 15px */
  --lane-end: 0px;       /* extra room between the lane and the column edge */
}
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.act:not(.act--hero) {
  position: relative;
  padding: var(--sc-10) var(--gut) var(--sc-9);
}
.act__copy > * + * { margin-top: var(--sc-4); }
.act__copy .sc-body { font-size: var(--t-body); line-height: 1.55; max-width: 46ch; color: var(--sc-ink); }
.act__copy .ps { font-size: var(--t-note); line-height: 1.5; color: var(--sc-ink-soft); }

.transcript {
  display: flex; flex-direction: column;
  gap: var(--line-gap, var(--sc-6));
  width: min(30ch, 100% - var(--lane-end));
  margin: var(--sc-9) var(--lane-end) 0 auto;
  font-size: var(--t-line);
  line-height: 1.4;
  letter-spacing: var(--sc-track-snug);
}
.line {
  display: grid; grid-template-columns: 12px minmax(0, 1fr); column-gap: 10px; align-items: start;
  color: var(--sc-ink-soft); font-weight: 400; text-wrap: pretty;
}
.mic { width: 12px; height: 12px; margin-top: calc((1.4em - 12px) / 2); color: var(--milo-mist); }
.line--wake, .line--answer, .line--action { color: var(--sc-ink); font-weight: 600; }
/* End live is an action, not speech: it never turns violet. */
.line--woken { color: var(--milo-wake); }
.line--woken .mic { color: var(--milo-wake); }
/* The host's answer to Milo's question: no wake phrase, set in as a reply. */
.line--answer { margin-left: 1.5em; }
.end-live {
  display: inline-block; justify-self: start;
  padding: 0.3em 0.9em;
  border: 1px solid currentColor; border-radius: var(--r-pill);
  font-size: var(--sc-t-base); font-weight: 600; letter-spacing: 0; line-height: 1.3;
}
.notes { margin-top: var(--sc-9); }
.notes > * + * { margin-top: var(--sc-4); }
.act--wake .note { margin-top: var(--sc-9); }
.note {
  max-width: 40ch; padding-left: 12px; border-left: 1px solid var(--milo-border);
  font-size: var(--t-note); line-height: 1.5; color: var(--sc-ink-soft); text-wrap: pretty;
}

/* Grounds (the owner's pick, round 2): cream and lavender alternate per act
   behind the host column, changing at act boundaries only, never in dark
   mode: lavender for acts 2, 4 and 6 (right after the photo, the peak, the
   end), cream for 3 and 5. */
.act--wake, .act--claims, .act--end { background: var(--milo-lavender); }
:root[data-theme="dark"] .act--wake,
:root[data-theme="dark"] .act--claims,
:root[data-theme="dark"] .act--end { background: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .act--wake,
  :root:not([data-theme="light"]) .act--claims,
  :root:not([data-theme="light"]) .act--end { background: none; }
}

/* Scroll pacing (motion only): the transcript is the timeline, and the peak
   gets the most scroll room. Capped at 10svh (decision 11); the claims act
   keeps 12svh. The static layout keeps the default compact gap. */
.milo-motion .act--wake   { --line-gap: 10svh; }
.milo-motion .act--product{ --line-gap: 10svh; }
.milo-motion .act--claims { --line-gap: 12svh; }
.milo-motion .act--send   { --line-gap: 10svh; }
.milo-motion .act--end    { --line-gap: 10svh; padding-bottom: var(--end-pad); }

/* ------------------------------------------------------------ Milo side -- */
.mascot-tile {
  display: inline-grid; place-items: center;
  width: 96px; height: 96px; border-radius: 50%;
  background: var(--milo-cream);
}
.mascot-tile .mascot { width: 84px; height: 84px; }
.mascot-tile--lg { width: 120px; height: 120px; }
.mascot-tile--lg .mascot { width: 104px; height: 104px; }
.promise { margin-top: var(--sc-5); max-width: 34ch; font-size: var(--sc-t-lg); line-height: 1.45; color: var(--sc-ink); text-wrap: pretty; }
.cta { margin-top: var(--sc-4); font-weight: 600; color: var(--milo-cream); letter-spacing: 0; }
.milo__slot { display: none; }
/* The pane's own visual copy of "Milo works." (phones only; aria-hidden). */
.slot__text { display: none; }

/* "Coming soon" (round 3): styled as a pill button, but a plain <p>: it does
   nothing yet, so it is not a focusable control (it becomes the listing link
   after approval). Cream, never violet. By default it sits top right inside
   the hero plate and scrolls away with it (phones, reduced motion); on a
   desktop with motion it is fixed at the top right of the viewport. */
:root { --cta-w: 8.75rem; }
.cta-btn {
  position: absolute; z-index: var(--sc-z-copy); top: var(--sc-6); right: var(--gut);
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--cta-w); height: 44px; border-radius: var(--r-pill);
  background: var(--milo-cream); color: var(--milo-ink);
  font-size: var(--sc-t-sm); font-weight: 600; letter-spacing: 0; white-space: nowrap;
  box-shadow: var(--sc-e1);
}

.log { margin-top: var(--sc-8); }
.result { margin-top: var(--sc-6); }
.result--card {
  background: var(--sc-surface);
  border: 1px solid var(--milo-border);
  border-radius: var(--r-card);
  overflow: hidden;
  box-shadow: var(--sc-e2);
  color: var(--milo-ink);
}
.result--card img { width: 100%; height: auto; }
.result__said {
  padding: var(--sc-3) var(--sc-4);
  border-top: 1px solid var(--milo-border);
  font-size: var(--sc-t-sm); color: #6A6571;
}
/* Milo's replies: compact chat rows (decision 7). */
.result--reply {
  display: flex; gap: var(--sc-3); align-items: flex-start;
  padding: var(--sc-3) var(--sc-4);
  background: var(--sc-surface);
  border: 1px solid var(--milo-border);
  border-radius: var(--r-card);
  box-shadow: var(--sc-e1);
  color: var(--milo-ink);
  font-size: var(--t-note); line-height: 1.45; text-wrap: pretty;
}
.reply__t { min-width: 0; }
.glasses {
  flex: none; width: 1.45em; height: 1.45em; margin-top: 0;
  border-radius: 7px;
  background: url("brand/milo-compact-icon-32.svg") center / contain no-repeat;
}
.chips { display: flex; flex-wrap: wrap; gap: var(--sc-2); padding: var(--sc-3) var(--sc-4); border-top: 1px solid var(--milo-border); }
.chips li {
  padding: 0.2em 0.75em; border-radius: var(--r-pill);
  font-size: var(--sc-t-sm); font-weight: 550;
}
/* Status colour, not accent: the app's own badge fills and inks, sampled from
   the screenshots (payments.webp). Open 6.7:1, Invoice Sent 11.9:1, Paid 9.9:1. */
.chip--open { background: #8AE0F7; color: #00485E; }
.chip--sent { background: #E2E0FE; color: #22007E; }
.chip--paid { background: #B0F581; color: #133A00; }

/* ------------------------------------------------- Milo's column header -- */
/* Static: a plain header at the top of Milo's list. In motion it is the
   compact header the hero state condenses into at the first wake. */
.milo__head { display: grid; gap: var(--sc-3); }
.head__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sc-3); }
.mascot-tile--sm { width: 56px; height: 56px; }
.mascot-tile--sm .mascot { width: 48px; height: 48px; }
.timer {
  display: inline-flex; gap: 0.5em; align-items: center;
  padding: 0.3em 0.75em; border-radius: var(--r-pill);
  background: rgb(255 249 239 / 0.10); color: var(--milo-cream);
  font-size: var(--sc-t-xs); font-weight: 650; font-variant-numeric: tabular-nums; line-height: 1.3;
}
.timer__live::before {
  content: ""; display: inline-block; width: 0.5em; height: 0.5em; margin-right: 0.45em;
  border-radius: 50%; background: var(--milo-violet-light); vertical-align: 0.05em;
}
.steps { display: flex; flex-wrap: wrap; gap: var(--sc-2) var(--sc-5); font-size: var(--sc-t-xs); line-height: 1.3; }
.step { display: flex; align-items: center; gap: 0.5em; color: var(--milo-mist); }
.step::before {
  content: ""; width: 0.5em; height: 0.5em; border-radius: 50%;
  border: 1px solid currentColor;
}
.step.is-lit { color: var(--milo-cream); }
.step.is-lit::before { background: var(--milo-cream); }

.pill {
  display: inline-flex; align-items: center;
  padding: 0.3em 0.8em; border-radius: var(--r-pill);
  border: 1px solid rgb(255 249 239 / 0.22); color: var(--milo-cream);
  font-size: var(--sc-t-xs); font-weight: 650; line-height: 1.3; white-space: nowrap;
}
.pill__dots { letter-spacing: 0.08em; margin-left: 0.2em; }
.pill__live { display: none; }
.is-listening .pill { background: var(--milo-violet); border-color: var(--milo-violet); color: #FFFFFF; }
.is-listening .pill__idle { display: none; }
.is-listening .pill__live { display: inline; }
.milo__pillslot { display: none; }

/* ------------------------------------------------------------ the trigger -- */
/* The wake trigger at the listening height (decision 4, the mark): it spans
   the transcript lane only (milo.js sets left/width from the lane), never
   crosses the hero photo or page copy, appears with act 2 and leaves when the
   close starts. */
.trigger { display: none; }
.glasses-mark {
  display: block; width: 30px; height: 13px;
  background: url("brand/milo-glasses-violet.svg") center / contain no-repeat;
}

/* --------------------------------------------------------------- close -- */
.close { --sc-ink: var(--milo-cream); --sc-ink-soft: var(--milo-mist); color: var(--sc-ink); }
.close__stage { display: grid; }
.close__panel { position: absolute; inset: 0; background: var(--milo-ink); }
.close__inner {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  min-height: 100%;
  padding: var(--sc-9) var(--gut) var(--sc-6);
  text-align: center;
}
.close__copy { display: grid; justify-items: center; gap: var(--sc-5); margin-block: auto; }
.close__copy h2 { color: var(--milo-cream); }
.close__body { max-width: 52ch; color: var(--milo-mist); font-size: var(--sc-t-lg); line-height: 1.5; text-wrap: pretty; }
.cta--close { margin-top: var(--sc-2); font-size: var(--sc-t-lg); }
.foot {
  width: 100%; max-width: var(--sc-maxw);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sc-5);
  margin-top: var(--sc-8); padding-top: var(--sc-5);
  border-top: 1px solid rgb(255 249 239 / 0.14);
  font-size: var(--sc-t-sm); color: var(--milo-mist);
}
.foot__lockup { width: 140px; height: auto; margin: 10px 0; }
.foot__links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sc-2) var(--sc-6); }
.foot a {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--milo-cream); text-decoration: underline; text-decoration-color: rgb(255 249 239 / 0.4);
}
@media (hover: hover) and (pointer: fine) {
  .foot a:hover { text-decoration-color: var(--milo-violet-light); }
}
.foot a:focus-visible { outline: 2px solid var(--milo-violet-light); outline-offset: 2px; border-radius: 4px; }
.foot a:active { transform: translateY(1px); }

/* ================================================================ MOTION ==
   Only when milo.js has confirmed motion is allowed.                      */
.milo-motion .milo {
  position: sticky; top: 0; height: 100vh; height: 100svh;
  padding: 0; overflow: clip;
  /* Above the close's stage (z 1), so the column holds over the close's first
     stretch while the ink wipes the host column; under the hero stage (raised
     to 3 below), so the second half of the h1 paints over it. */
  z-index: 2;
}
.milo-motion .act--hero [data-sc-stage] { z-index: 3; }

/* The header: at the top of the column. Before the first wake only the pill
   shows, moved (transform) to the waiting slot under the hero's CTA line; at
   the first wake the hero condenses into it (360 ms). */
.milo-motion .milo__head {
  position: absolute; z-index: 4; top: var(--sc-6); left: var(--gut); right: var(--gut);
}
.milo-motion .milo__head .mascot-tile,
.milo-motion .milo__head .timer,
.milo-motion .milo__head .steps {
  transition: opacity 360ms var(--sc-ease-out), transform 360ms var(--sc-ease-out);
}
.milo-motion .milo:not(.has-results) .milo__head .mascot-tile,
.milo-motion .milo:not(.has-results) .milo__head .timer,
.milo-motion .milo:not(.has-results) .milo__head .steps { opacity: 0; transform: translateY(8px); }
.milo-motion .milo__head .pill { transform-origin: 0 0; transition: transform 360ms var(--sc-ease-out); }
.milo-motion .milo:not(.has-results) .milo__head .pill {
  transform: translate(var(--pill-dx, 0px), var(--pill-dy, 0px)) scale(1.18);
}
.milo-motion .milo:not(.has-results) .pill__dots { animation: milo-wait 1.6s ease-in-out infinite; }
@keyframes milo-wait { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
.milo-motion .milo__pillslot { display: block; height: 34px; margin-top: var(--sc-5); }

.milo-motion .milo__hero {
  position: absolute; left: var(--gut); right: var(--gut);
  top: var(--h1-top, 30svh);
  transition: opacity 360ms var(--sc-ease-out), transform 360ms var(--sc-ease-out);
}
.milo-motion .milo__slot { display: block; height: calc(var(--sc-t-3xl) * 1.02); margin-top: var(--sc-4); }
.milo-motion .milo.has-results .milo__hero { opacity: 0; transform: translateY(-24px) scale(0.98); pointer-events: none; }
/* The second half of the one <h1>, placed into Milo's column on the same line as
   the first half. Fixed, so it sits in the aside's hero slot; milo.js fades it
   with the end of the hero act (decision 9). */
.milo-motion .h1-milo {
  position: fixed; z-index: 3;
  left: calc(50% + var(--gut));
  top: var(--h1-top, 40svh);
  color: var(--milo-cream);
}

/* The session log (decision 7). The newest result enters at the top, under
   the header; older ones slide down by their measured height (milo.js sets
   --y). The newest two show in full; older ones collapse to a one-line
   receipt (a card's own "You:" caption, a reply's own text). The column's
   foot fades into the ink. Results not yet woken are clipped away, not
   hidden, so every alt and caption stays in the accessibility tree. */
.milo-motion .log {
  position: absolute; left: var(--gut); right: var(--gut); bottom: 0; top: var(--log-top, 132px);
  max-width: min(100% - 2 * var(--gut), (100svh - 220px) * 0.8);
  margin: 0; overflow: clip;
  -webkit-mask-image: linear-gradient(to bottom, #000 78%, transparent 98%);
  mask-image: linear-gradient(to bottom, #000 78%, transparent 98%);
}
.milo-motion .result {
  position: absolute; left: 0; right: 0; top: 0; margin: 0;
  transform: translateY(var(--y, -16px));
  transition: transform 360ms var(--sc-ease-out), opacity 300ms var(--sc-ease-out);
}
.milo-motion .result:not(.is-on) { opacity: 0; clip-path: inset(50%); }
/* A full card shows its picture; its caption stays for assistive tech only. */
.milo-motion .result:not(.is-receipt) .result__said {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; padding: 0; border: 0;
}
.milo-motion .result.is-receipt {
  height: 40px; display: flex; align-items: center; gap: var(--sc-3);
  padding: 0 var(--sc-4);
  background: rgb(255 249 239 / 0.06); border: 1px solid rgb(255 249 239 / 0.12); box-shadow: none;
  color: var(--milo-mist); font-size: var(--sc-t-sm); line-height: 1.3;
}
/* The receipt's picture stays in the accessibility tree (its alt), clipped. */
.milo-motion .result.is-receipt img {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
}
.milo-motion .result.is-receipt .chips { display: none; }
.milo-motion .result.is-receipt .result__said { padding: 0; border: 0; color: inherit; }
.milo-motion .result.is-receipt .result__said,
.milo-motion .result.is-receipt .reply__t { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.milo-motion .result.is-receipt .glasses { width: 18px; height: 18px; border-radius: 5px; }
/* First frame after load (e.g. a reload restored mid-page): no entrances. */
.milo-instant .result, .milo-instant .milo__hero, .milo-instant .milo__head *, .milo-instant .h1-milo { transition: none !important; }

/* The close (decision 8). #close is pulled up under the end of the split so
   Milo's column (z 2, above the close's stage at z 1) holds through the first
   0.3 of the pin while the ink wipes the host column (0.15 to 0.65). The
   numbers: End live crosses at about p 0.10; the column stays sticky until the
   stage's bottom reaches the viewport's, which the act 6 padding below sets
   to about p 0.3; it then fades (0.30 to 0.42) as the close copy opens from
   0.42. The close's stage passes pointer events through until a cue opens
   (the engine sets pointer-events: auto on an open cue). */
/* svh, like the listening height and the pane, so the crossing timing holds
   where vh is the large viewport (iOS Safari). */
.milo-motion { --end-pad: 62svh; --close-pull: 130svh; }
.milo-motion #close { margin-top: calc(-1 * var(--close-pull)); }
.milo-motion #close .close__stage { pointer-events: none; }

/* The lane ends where the trigger mark (glasses + tick, 54px) begins. */
.milo-motion { --lane-end: max(0px, calc(58px - var(--gut))); }
/* The trigger mark sits at the seam (desktop) or the right gutter (phone).
   Page copy ends where the lane ends (--lane-end), so the mark never sits on a
   heading, body line or note, and it never has to step aside. */
.milo-motion .act__copy,
.milo-motion .act > .note,
.milo-motion .notes { margin-right: var(--lane-end); }
.milo-motion .trigger {
  display: block; position: fixed; z-index: var(--sc-z-chrome);
  top: var(--playhead); left: 0; width: 0; height: 0;
  pointer-events: none;
  transition: opacity 240ms var(--sc-ease-out);
}
.trigger__mark {
  position: absolute; right: 0; top: 0; transform: translateY(-50%);
  display: flex; align-items: center; gap: 4px;
}
.trigger__tick { display: block; width: 20px; height: 2px; border-radius: 1px; background: var(--trig, var(--milo-violet)); }
/* The mark is the brand glasses used as a mask, so dark mode can draw it in
   the light stop. */
.trigger .glasses-mark {
  background: var(--trig, var(--milo-violet));
  -webkit-mask: url("brand/milo-glasses-violet.svg") center / contain no-repeat;
  mask: url("brand/milo-glasses-violet.svg") center / contain no-repeat;
  transition: transform 200ms var(--sc-ease-out);
}
.trigger.is-listening .glasses-mark { transform: scale(1.25); }
/* The wake accent (mark): a 3px violet rule drawn from the seam across the
   lane (400 ms), held, then retracted. */
.trigger__accent {
  position: absolute; left: 0; right: 54px; top: -1.5px; height: 3px; border-radius: 2px;
  background: var(--trig, var(--milo-violet));
  transform: scaleX(0); transform-origin: 100% 50%;
  transition: transform 300ms var(--sc-ease-out);
}
.trigger.is-accent .trigger__accent { transform: scaleX(1); transition-duration: 400ms; }
/* ...and it cuts out at once when a line or page copy reaches it. */
.trigger.is-cut .trigger__accent { opacity: 0; transition: none; }
.milo-motion .trigger:not(.is-on) { opacity: 0; }

.milo-motion .close__panel { clip-path: inset(0 0 0 50%); }

/* Dark: the two inks are 1.17:1 apart, so Milo's column gets a hairline on its
   left edge (the only place the seam is drawn). */
:root[data-theme="dark"] .milo { box-shadow: inset 1px 0 0 rgb(255 249 239 / 0.10); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .milo { box-shadow: inset 1px 0 0 rgb(255 249 239 / 0.10); }
}
/* Dark: the trigger draws in the light violet stop (#6D2CFF is 2.86:1 on
   #1B1920). */
:root[data-theme="dark"] { --trig: var(--milo-violet-light); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --trig: var(--milo-violet-light); }
}

/* ============================================================== DESKTOP == */
@media (min-width: 860.02px) {
  /* "Milo works." sits on the same line as "You host."; the mascot closes that line. */
  .milo-motion .milo__hero .mascot-tile { position: absolute; right: 0; top: 0; }
  .milo-motion .milo__slot { margin-top: 0; }
  /* The button is fixed over Milo's column at the top right; the header
     reserves its width so the two never meet (its rows wrap on narrow
     desktops instead). */
  .milo-motion .cta-btn { position: fixed; z-index: 5; }
  .milo-motion .milo__head { padding-right: calc(var(--cta-w) + var(--sc-4)); }
}

/* Narrow desktops (860 to 1199 px): the h1 steps down one rung so the hero
   mascot keeps closing the "Milo works." line without touching it. */
@media (min-width: 860.02px) and (max-width: 1199.98px) {
  .hero__h1, .milo-motion .h1-milo { font-size: var(--sc-t-2xl); }
  .milo-motion .milo__slot { height: calc(var(--sc-t-2xl) * 1.02); }
  /* ...and the mascot (56px face, above the 48px floor) is centred on that
     shorter line, so it doesn't reach down into the promise. */
  .milo-motion .milo__hero .mascot-tile { width: 64px; height: 64px; top: calc((var(--sc-t-2xl) * 1.02 - 64px) / 2); }
  .milo-motion .milo__hero .mascot-tile .mascot { width: 56px; height: 56px; }
}

/* =============================================================== PHONE == */
@media (max-width: 860px) {
  :root { --gut: 16px; }
  .stage { display: block; }
  .hero__h1, .milo-motion .h1-milo, .milo-motion .slot__text { font-size: var(--sc-t-3xl); }
  .cta-btn { top: clamp(1.5rem, 4vh, 2.5rem); }
  .hero video[data-sc-scrub] { display: none; }
  .act:not(.act--hero) { padding: var(--sc-9) var(--gut) var(--sc-8); }
  :root { --t-body: 1.0625rem; --t-line: 1.125rem; --t-note: 0.875rem; }
  .transcript { margin-top: var(--sc-7); }
  .notes, .act--wake .note { margin-top: var(--sc-7); }
  /* Phone: the pane (44svh) follows the transcript in the flow, so it adds to
     the column's sticky run; act 6 needs less padding for the same hold. */
  .milo-motion { --end-pad: 26svh; }
  .milo-motion .act--end { padding-bottom: var(--end-pad); }   /* after the phone .act rule, which would win */

  /* Phone hero: the photo is a plate at the top (no clip, no pin travel), the
     headline stays put and scrolls away with it. */
  .act--hero, .hero { height: 78svh !important; }
  .hero__lockup { width: 136px; }
  .hero__h1 { margin-top: var(--sc-4); }
  /* Taller since round 3: "You host." is a rung bigger on phones now. */
  .hero__scrim {
    width: 100%; height: 72%;
    -webkit-mask-image: linear-gradient(to bottom, #000 65%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 65%, transparent 100%);
  }
  .hero__brand > *, .h1-you, .h1-you .sc-split__i { opacity: 1 !important; transform: none !important; }

  /* static phone: one column, Milo's header above Milo's list */
  .steps { gap: var(--sc-2) var(--sc-4); }
  .milo { padding: var(--sc-6) var(--gut) var(--sc-8); }
  .promise { font-size: var(--sc-t-base); }
  .foot { justify-content: center; text-align: center; }
  .foot__links { justify-content: center; }

  /* motion phone: Milo is a pane pinned to the bottom 44svh */
  .milo-motion { --playhead: 50svh; }
  .milo-motion .act--hero, .milo-motion .hero { height: 56svh !important; }
  .milo-motion .milo { position: sticky; top: auto; bottom: 0; height: 44svh; }
  .milo-motion .milo__head { top: var(--sc-3); gap: var(--sc-2); }
  .milo-motion .milo__head .steps { gap: var(--sc-2); }
  .milo-motion .step:not(.is-current) .step__label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  /* Round 4: "Milo works." is drawn inside the pane (the slot's own
     aria-hidden copy, on the pane's ink at its left gutter); the h1's second
     half stays in the document for assistive tech but is visually hidden. The
     pane's hero reads top to bottom: headline, promise, CTA line, pill, and
     the mascot last, left-aligned (dropped by milo.js on short phones if the
     stack would overflow the pane). */
  .milo-motion .h1-milo {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .milo-motion .slot__text {
    display: block; font-weight: 650; line-height: 1.02; color: var(--milo-cream); white-space: nowrap;
  }
  .milo-motion .milo__hero {
    top: var(--sc-4); left: var(--gut); right: var(--gut);
    display: flex; flex-direction: column; align-items: flex-start;
  }
  .milo-motion .milo__hero > * { align-self: stretch; }
  .milo-motion .milo__hero .mascot-tile {
    order: 5; align-self: flex-start; margin-top: var(--sc-4);
    width: 56px; height: 56px;
  }
  .milo-motion .milo__hero .mascot-tile .mascot { width: 48px; height: 48px; }
  .milo-motion .milo.hero-tight .milo__hero .mascot-tile { display: none; }
  .milo-motion .milo__slot { margin: 0; height: auto; }
  .milo-motion .milo__pillslot { margin-top: var(--sc-3); height: 28px; }
  .milo-motion .promise { margin-top: var(--sc-3); font-size: var(--sc-t-sm); line-height: 1.45; }
  .milo-motion .milo__hero .cta { margin-top: var(--sc-2); font-size: var(--sc-t-sm); }

  .milo-motion .log { max-width: none; }

  /* The lane and page copy end where the trigger mark begins. On a phone the
     mark is compact (glasses 24px + 4px + tick 12px = 40px, 4px clear). */
  .milo-motion { --lane-end: 44px; }
  .milo-motion .trigger .glasses-mark { width: 24px; height: 10.4px; }
  .milo-motion .trigger__tick { width: 12px; }
  .milo-motion .trigger__accent { right: 40px; }

  .milo-motion .close__panel { clip-path: inset(56% 0 0 0); }
}

/* Short viewports: the close must still hold the CTA and the whole footer on
   its last screen (360×640 overflowed by 108px). */
@media (max-height: 760px) {
  .close__inner { padding-top: var(--sc-6); padding-bottom: var(--sc-3); }
  .close__copy { gap: var(--sc-3); }
  .mascot-tile--lg { width: 72px; height: 72px; }
  .mascot-tile--lg .mascot { width: 62px; height: 62px; }
  .close__copy .sc-display--lg { font-size: var(--sc-t-2xl); }
  .close__body, .cta--close { font-size: var(--sc-t-base); }
  .foot { margin-top: var(--sc-5); padding-top: var(--sc-3); gap: var(--sc-2); }
  .foot__lockup { width: 120px; margin: 4px 0; }
}

/* ======================================================== REDUCED MOTION ==
   Fewer and gentler, not zero. The static layout above is the readable
   version of every act (milo.js never adds .milo-motion here); this block
   settles what the engine still drives. */
@media (prefers-reduced-motion: reduce) {
  .result, .h1-milo, .milo__hero, .milo__head *, .trigger, .trigger *, .glasses-mark { transition: none !important; }
  /* The close is a normal full-width section: everything already shown. */
  .close [data-sc-cue] { opacity: 1 !important; transform: none !important; pointer-events: auto !important; }
  .close__panel { clip-path: none !important; }
  /* ...and not pinned: no viewport of unchanging scroll at the end. */
  #close { height: auto !important; }
}

/* Static (no .milo-motion): every wake line is already woken. */
html:not(.milo-motion) .line--wake,
html:not(.milo-motion) .line--answer { color: var(--milo-wake); }
html:not(.milo-motion) .line--wake .mic,
html:not(.milo-motion) .line--answer .mic { color: var(--milo-wake); }
html:not(.milo-motion) .h1-milo { display: block; }
/* The trigger's static form (reduced motion): the glasses mark at the lane's
   end of each wake line. Nothing is fixed or moving. */
html:not(.milo-motion) { --lane-end: 40px; }
html:not(.milo-motion) .line--wake { position: relative; }
html:not(.milo-motion) .line--wake::after {
  content: ""; position: absolute; right: -38px; top: calc((1.4em - 13px) / 2);
  width: 30px; height: 13px;
  background: var(--trig, var(--milo-violet));
  -webkit-mask: url("brand/milo-glasses-violet.svg") center / contain no-repeat;
  mask: url("brand/milo-glasses-violet.svg") center / contain no-repeat;
}
/* Static acts read as compact columns: no scroll-pacing air. */
html:not(.milo-motion) .act:not(.act--hero) { padding-block: var(--sc-8) var(--sc-7); }
html:not(.milo-motion) .transcript,
html:not(.milo-motion) .notes,
html:not(.milo-motion) .act--wake .note { margin-top: var(--sc-6); }
/* Static hero: a plate, not a pinned act. The whole <h1> stays readable and
   there is no pinned travel with nothing to show. */
html:not(.milo-motion) .act--hero, html:not(.milo-motion) .hero { height: 100svh !important; }
html:not(.milo-motion) .hero__brand > *,
html:not(.milo-motion) .h1-you,
html:not(.milo-motion) .h1-you .sc-split__i { opacity: 1 !important; transform: none !important; }
html:not(.milo-motion) .milo__head { margin-bottom: var(--sc-7); }
@media (max-width: 860px) {
  html:not(.milo-motion) .act--hero, html:not(.milo-motion) .hero { height: 78svh !important; }
}

/* ==================================================== STATIC, PER-ACT ROWS ==
   Reduced motion with script (html.milo-static, set by milo.js): every act is
   its own two-column row, the host's copy on cream at the left and Milo's
   results for that act on ink at the right (milo.js moves them into
   .act__milo right after the act's transcript). Phones stack the ink block
   under the transcript. With no script at all the aside keeps the list. */
.act__milo {
  --sc-ink: var(--milo-cream); --sc-ink-soft: var(--milo-mist);
  color: var(--sc-ink);
}
html.milo-static .act__milo .result:first-child { margin-top: 0; }
html.milo-static .milo__head .mascot-tile,
html.milo-static .milo__head .pill { display: none; }
html.milo-static .act--hero .milo__head { margin: var(--sc-7) 0 0; }
@media (min-width: 860.02px) {
  html.milo-static .stage { display: block; }
  html.milo-static .act {
    display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto auto 1fr;
    column-gap: calc(2 * var(--gut)); align-items: start;
    background: linear-gradient(to right, transparent 50%, var(--milo-ink) 50%);
  }
  html.milo-static .act > * { grid-column: 1; }
  html.milo-static .act > .act__milo { grid-column: 2; grid-row: 1 / 5; }
  html.milo-static .act--hero { column-gap: 0; grid-template-rows: auto; }
  html.milo-static .act--hero > .act__milo { grid-row: 1; align-self: center; padding: var(--sc-8) var(--gut); }
  html.milo-static:not([data-theme="dark"]) .act--wake,
  html.milo-static:not([data-theme="dark"]) .act--claims,
  html.milo-static:not([data-theme="dark"]) .act--end {
    background: linear-gradient(to right, var(--milo-lavender) 50%, var(--milo-ink) 50%);
  }
  /* Dark: the 10% cream hairline on Milo's side of each row. */
  html.milo-static[data-theme="dark"] .act {
    background: linear-gradient(to right, transparent 50%, rgb(255 249 239 / 0.10) 50%, rgb(255 249 239 / 0.10) calc(50% + 1px), var(--milo-ink) calc(50% + 1px));
  }
}
@media (min-width: 860.02px) and (prefers-color-scheme: dark) {
  html.milo-static:not([data-theme="light"]) .act,
  html.milo-static:not([data-theme="light"]) .act--wake,
  html.milo-static:not([data-theme="light"]) .act--claims,
  html.milo-static:not([data-theme="light"]) .act--end {
    background: linear-gradient(to right, transparent 50%, rgb(255 249 239 / 0.10) 50%, rgb(255 249 239 / 0.10) calc(50% + 1px), var(--milo-ink) calc(50% + 1px));
  }
}
@media (max-width: 860px) {
  html.milo-static .act__milo {
    margin: var(--sc-6) calc(-1 * var(--gut)) 0; padding: var(--sc-6) var(--gut);
    background: var(--milo-ink);
  }
  html.milo-static .act--hero > .act__milo { margin: 0; }
  html.milo-static .act--hero { height: auto !important; }
}
