/* =========================================================================
   Chan site v2 — "Bright manager" design system (P0.9)
   Palette: Gleam (joingleam.com), sampled live — sky wash #C1D8FC into
   cream #F8F8F5, pure marigold #FFB500, warm ink. Chunky ink-bordered
   components with hard offset shadows.
   Structure: extra.email's vision-confirmed section order. P0.9 copies
   their two flagship mechanics surgically:
   - mega-room = FULL-BLEED product stage that transforms per rail scene
     (raw feed → scroll wipe stamps chips → rows fly out → digest sheet
     slides up). Their stage bleeds past the viewport (measured 1735px
     right edge on a 1470px viewport).
   - carousel = real device + ghost neighbor panels + emoji dock.
   Device frame is Fae-grade: metallic rim, side buttons, status bar.
   Self-contained: does NOT import or extend colors_and_type.css.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Unbounded:wght@500;600;700&family=Instrument+Sans:wght@400;500;600&display=swap');

:root {
  /* canvas + ink (Gleam-sampled) */
  --v2-cream:      #F8F8F5;
  --v2-cream-deep: #EFEEE7;
  --v2-ink:        #222019;
  --v2-ink-soft:   #554C3D;   /* warm body text */
  --v2-ink-dim:    rgba(34,32,25,.55);

  /* brand pair: marigold + sky (Gleam's "light blue and yellow") */
  --v2-yellow:      #FFB500;
  --v2-yellow-deep: #E2A000;
  --v2-brown:       #4A2D00;  /* type tint on yellow rooms */
  --v2-amber-deep:  #B26A00;  /* tinted second paragraph in the compose body */
  --v2-butter:      #FBF1D7;
  --v2-sky:         #C1D8FC;  /* powder wash + blue rooms */
  --v2-sky-soft:    #DDEAFB;
  --v2-navy:        #1B3960;  /* type tint on sky rooms */
  --v2-night:       #1D1812;  /* warm ink room for the close */

  /* product blue (iMessage-true): bubbles + every send affordance */
  --v2-blue:      #0A84FF;
  --v2-blue-deep: #0668CC;

  /* type */
  --v2-display: 'Unbounded', sans-serif;
  --v2-body:    'Instrument Sans', sans-serif;
  --fs-h1: clamp(32px, 4.6vw, 60px);
  --fs-h2: clamp(26px, 3.4vw, 46px);
  --fs-body: 17px;
  --fs-micro: 13px;

  /* shape */
  --r-room: 40px;
  --r-card: 20px;
  --r-btn: 14px;
  --r-pill: 9999px;
  --bd: 2px solid var(--v2-ink);
  --shadow-hard: 0 3px 0 0 var(--v2-ink);
  --shadow-hard-sm: 0 2px 0 0 var(--v2-ink);

  /* iMessage thread (product-true) */
  --th-screen: #000000;
  --th-chan:   #2C2C2E;
  --th-me:     #0A84FF;

  --v2-max: 1180px;
  --room-x: clamp(10px, 1.6vw, 22px);

  /* spring overshoot, the Extra appear feel (their springs settle ~.7s) */
  --ease-spring: cubic-bezier(.32, 1.4, .45, 1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--v2-cream);
  color: var(--v2-ink);
  font-family: var(--v2-body);
  font-size: var(--fs-body);
  font-weight: 500;            /* Extra runs body at 500, it reads premium */
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 {
  font-family: var(--v2-display);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 0.98;           /* sub-1 leading, per Extra's display craft */
  margin: 0;
}
img { display: block; }
a { color: inherit; }

/* ---- scroll-reveal primitives ------------------------------------------ */
[data-reveal] { opacity: 0; transform: translateY(22px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.2,1); }
[data-reveal="l"] { transform: translateX(-30px); }
[data-reveal="r"] { transform: translateX(30px); }
[data-reveal].seen { opacity: 1; transform: none; }
/* bare reveal: an IntersectionObserver hook only; the CHILDREN choreograph
   (Extra never fades whole sections, it assembles their members) */
[data-reveal="bare"] { opacity: 1; transform: none; transition: none; }
/* masked headline rise: overflow-clip wrapper, the line climbs out
   (Extra's TextMask: measured overflow:clip + inner translate) */
.rise { display: block; overflow: clip; }
.rise .rise-in {
  display: inline-block; translate: 0 115%;
  transition: translate .9s cubic-bezier(.19, 1, .22, 1);
}
.rise-d1 .rise-in { transition-delay: .12s; }
.seen .rise-in, .seen.rise .rise-in, .rise .rise-in.up { translate: 0 0; }

/* =========================================================================
   Nav — ink over the sky wash; chunky CTA right (Gleam's move)
   ========================================================================= */
.v2-nav {
  position: absolute; top: 0; left: 0; right: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px clamp(20px, 4vw, 44px);
  color: var(--v2-ink);
}
.v2-wordmark { font-family: var(--v2-display); font-weight: 700; font-size: 19px; text-decoration: none; letter-spacing: -0.01em; }
.v2-nav-right { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; }
.v2-nav-right a { text-decoration: none; padding: 9px 16px; border-radius: var(--r-pill); transition: background .15s ease; }
.v2-nav-right a:hover { background: rgba(34,32,25,.07); }
.v2-nav-login { background: #FFFDF7; border: var(--bd); box-shadow: var(--shadow-hard-sm); }
.v2-nav-login:hover { background: #FFFDF7; transform: translateY(1px); box-shadow: 0 1px 0 0 var(--v2-ink); }
.v2-nav-hire { background: var(--v2-yellow); border: var(--bd); box-shadow: var(--shadow-hard-sm); }
.v2-nav-hire:hover { background: var(--v2-yellow); transform: translateY(1px); box-shadow: 0 1px 0 0 var(--v2-ink); }

/* =========================================================================
   S1 · Hero — bright sky-washed room, device thread as the cinematic
   object, headline low (Extra's film-still slot)
   ========================================================================= */
.sc-hero {
  position: relative; min-height: 100svh; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  background: linear-gradient(to bottom, var(--v2-sky) 0%, rgba(193,216,252,.4) 26%, var(--v2-cream) 58%);
  padding-bottom: clamp(40px, 7vh, 80px);
}
/* the sun halo — Gleam's soft radial wash behind the device */
.hero-halo {
  position: absolute; inset: -10%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(640px 480px at 50% 30%, rgba(255,181,0,.26), transparent 64%),
    radial-gradient(820px 560px at 80% 24%, rgba(244,182,166,.2), transparent 62%);
}
.hero-dev-wrap {
  position: absolute; top: clamp(44px, 8vh, 88px); left: 50%; transform: translateX(-50%);
  z-index: 1;
  filter: drop-shadow(0 26px 48px rgba(34,32,25,.28));
}
/* hero thread anchors TOP (the screen bottom hides behind the fog) */
.hero-dev-wrap .th-msgs { justify-content: flex-start; }
/* cream fog so the headline reads over the device */
.sc-hero::after {
  content: ''; position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(to bottom, transparent 36%, rgba(248,248,245,.86) 60%, rgba(248,248,245,.99) 84%);
  pointer-events: none;
}
.hero-copy { position: relative; z-index: 4; text-align: center; padding: 0 20px; max-width: 880px; }
.hero-copy h1 { font-size: var(--fs-h1); }
.hero-sub { margin: 20px auto 28px; font-size: clamp(15px, 1.6vw, 18px); color: var(--v2-ink-soft); max-width: 440px; line-height: 1.5; }
.hero-ctas { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.hero-hint { position: relative; z-index: 4; margin-top: 22px; font-size: var(--fs-micro); color: var(--v2-ink-dim); }

/* ---- buttons: Gleam-chunky — fill, ink border, hard offset shadow ------ */
.cta {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 13px 26px; border-radius: var(--r-btn);
  font-family: var(--v2-body); font-weight: 600; font-size: 15.5px;
  text-decoration: none; cursor: pointer;
  border: var(--bd); box-shadow: var(--shadow-hard);
  transition: transform .12s ease, box-shadow .12s ease;
}
.cta:hover { transform: translateY(2px); box-shadow: 0 1px 0 0 var(--v2-ink); }
.cta-primary { background: var(--v2-yellow); color: var(--v2-ink); }
.cta-frosted { background: #FFFDF7; color: var(--v2-ink); }

/* =========================================================================
   S1b · The LOUD scene — wafer-grade noise collage (window cards, DM
   panels, app badges, a cascading unread pile), scroll-claimed by Chan.
   Stage A: items spring in one by one. Stage B: each greys + shrinks as
   the calm thread and the answered call land at center. Stage C: quiet.
   ========================================================================= */
.sc-loud { position: relative; height: 320vh; }
.loud-pin {
  position: sticky; top: 0; height: 100svh; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(18px, 4vh, 36px);
  background: var(--v2-cream);
}
.loud-field { position: absolute; inset: 0; pointer-events: none; z-index: 1; transition: opacity .8s ease; }
.loud-pin.calm .loud-field { opacity: .7; }

/* every noise artifact: pops in with a spring, then gets claimed */
.nz {
  position: absolute;
  rotate: var(--nr, 0deg);
  /* --sy runs 0 → negative through the scrub, so this drifts items UP,
     away from the headline (the noise lifts off as Chan claims it) */
  transform: translateY(calc(var(--sy, 0) * var(--sp, .4) * 1px));
  opacity: 0; translate: 0 30px; scale: .82;
  transition:
    opacity .55s ease,
    translate .6s var(--ease-spring),
    scale .6s var(--ease-spring),
    filter .6s ease;
  will-change: transform;
}
.nz.on { opacity: 1; translate: 0 0; scale: 1; }
/* first wave pops on section enter (:where keeps specificity at .nz.on
   level so the claim rule below still wins once the sweep reaches it) */
:where(.sc-loud.seen) .nz.n0 { opacity: 1; translate: 0 0; scale: 1; }
.nz.on.off { opacity: .13; scale: .76; filter: grayscale(1) blur(1.6px); }

/* mail window (traffic lights, like the real thing) */
.nz-mail {
  width: 240px; background: #FFFFFF;
  border: 1px solid rgba(34,32,25,.14); border-radius: 12px;
  box-shadow: 0 14px 34px rgba(34,32,25,.14);
  padding: 11px 14px 12px; font-size: 12px; color: var(--v2-ink);
}
.nz .tl { display: flex; gap: 4px; margin-bottom: 7px; }
.nz .tl i { width: 8px; height: 8px; border-radius: 50%; background: #FF5F57; }
.nz .tl i:nth-child(2) { background: #FEBC2E; }
.nz .tl i:nth-child(3) { background: #28C840; }
.nz-mail b { display: block; font-size: 12.5px; }
.nz-mail em { display: block; font-style: normal; font-weight: 600; color: rgba(34,32,25,.8); margin: 2px 0; }
.nz-mail p, .nz-dm p, .nz-miss p { margin: 2px 0 0; color: rgba(34,32,25,.55); line-height: 1.35; }

/* dark DM panel (the Slack-shaped ping) */
.nz-dm {
  width: 215px; background: #26252B; color: #FFF; border-radius: 13px;
  box-shadow: 0 14px 34px rgba(0,0,0,.25);
  padding: 11px 14px; font-size: 12px;
}
.nz-dm b { font-size: 12.5px; }
.nz-dm p { color: rgba(255,255,255,.6); }

/* missed call (red-tinted alert card) */
.nz-miss {
  width: 232px; background: #FFF5F4;
  border: 1px solid rgba(255,59,48,.25); border-radius: 12px;
  box-shadow: 0 14px 30px rgba(255,59,48,.12);
  padding: 11px 14px; font-size: 12px; color: var(--v2-ink);
}
.nz-miss b { display: block; color: #D70015; font-size: 12.5px; }
.nz-miss em { display: block; font-style: normal; font-weight: 600; margin: 2px 0; }

/* a client ask, grey iMessage bubble */
.nz-bub {
  display: inline-block; max-width: 250px;
  background: #E9E9EB; color: var(--v2-ink);
  padding: 11px 16px; border-radius: 20px; border-bottom-left-radius: 6px;
  font-size: 15px; white-space: nowrap;
  box-shadow: 0 10px 24px rgba(34,32,25,.12);
}

/* invoice / calendar mini-cards */
.nz-inv, .nz-cal {
  width: 195px; background: #FFFFFF;
  border: 1px solid rgba(34,32,25,.14); border-radius: 12px;
  box-shadow: 0 12px 28px rgba(34,32,25,.12);
  padding: 12px 14px; font-size: 12px; color: var(--v2-ink);
}
.nz-inv b, .nz-cal b { display: block; font-size: 13.5px; }
.nz-inv p, .nz-cal p { margin: 2px 0 0; color: rgba(34,32,25,.55); }
.nz-due {
  position: absolute; top: -9px; right: -12px; rotate: 6deg;
  background: #D70015; color: #FFF;
  font-size: 9.5px; font-weight: 800; letter-spacing: .08em;
  padding: 4px 9px; border-radius: 6px;
}

/* sticky note + lead ping */
.nz-note {
  display: inline-block; background: var(--v2-butter); color: var(--v2-brown);
  border-radius: 4px; padding: 14px 16px 18px;
  font-size: 14px; font-weight: 600;
  box-shadow: 0 12px 26px rgba(34,32,25,.16);
}
.nz-ping {
  display: inline-block; background: #FFFDF7;
  border: 1.5px solid var(--v2-ink); border-radius: var(--r-pill);
  padding: 8px 14px; font-size: 13px; font-weight: 600;
  box-shadow: var(--shadow-hard-sm);
}

/* app badge with unread count */
.nz-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 58px; height: 58px; border-radius: 14px;
  background: #FFFFFF; border: 1px solid rgba(34,32,25,.12);
  box-shadow: 0 12px 26px rgba(34,32,25,.14);
}
.nz-badge img { width: 30px; height: 30px; }
.nzb-e { font-size: 30px; line-height: 1; }
.nz-badge i {
  position: absolute; top: -8px; right: -8px;
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: var(--r-pill);
  background: #FF3B30; color: #FFF;
  font-style: normal; font-size: 12px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 10px rgba(255,59,48,.4);
}

/* the cascading unread pile (wafer's duplicated-dialog gag) */
.nz-stack { width: 212px; height: 110px; }
.nz-stack > span, .nzs-top {
  position: absolute; left: 0; top: 0; width: 176px; height: 62px;
  background: #FFFFFF; border: 1px solid rgba(34,32,25,.16); border-radius: 10px;
  box-shadow: 0 10px 22px rgba(34,32,25,.1);
}
.nz-stack > span:nth-child(1) { translate: 36px 40px; opacity: .5; }
.nz-stack > span:nth-child(2) { translate: 27px 30px; opacity: .65; }
.nz-stack > span:nth-child(3) { translate: 18px 20px; opacity: .8; }
.nz-stack > span:nth-child(4) { translate: 9px 10px; opacity: .92; }
.nzs-top { display: flex; align-items: center; gap: 6px; padding: 0 14px; font-size: 13px; }
.nzs-top b { font-weight: 700; }
.nzs-top em { font-style: normal; color: #D70015; font-weight: 700; }

/* the headline floats OVER the noise (wafer's move), then the answer line */
.loud-copy { position: relative; z-index: 4; text-align: center; max-width: 900px; padding: 0 24px; }
.loud-copy h2 { font-size: clamp(28px, 3.8vw, 52px); }
.loud-l2 { margin-top: 8px; }
/* line 1 rises on section enter (via .seen); line 2 is the ANSWER and
   stays scroll-gated, so re-pin it below the mask until its .up fires */
.loud-l2 .rise-in { color: var(--v2-amber-deep); translate: 0 115%; }
.loud-l2 .rise-in.up { translate: 0 0; }

/* the calm cluster: a ROTATING run of resolutions (one per noise artifact
   the visitor just watched), scrubbed by scroll. Sets stack absolutely in
   a fixed-height stage so the swap never shifts the layout: the active
   set springs up from below, the spent one slips upward. */
.loud-thread {
  position: relative; z-index: 4;
  width: min(440px, 88vw); min-height: 150px;
}
.lt-set {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: center; gap: 9px;
  opacity: 0; translate: 0 28px;
  transition: opacity .45s ease, translate .55s var(--ease-spring);
  pointer-events: none;
}
.loud-thread.in .lt-set.on { opacity: 1; translate: 0 0; }
.lt-set.past { translate: 0 -24px; }
/* each resolution's rows POP in like fresh texts when its set takes
   the stage (artifact first, bubble right after) */
.loud-thread.in .lt-set.on .lt-call,
.loud-thread.in .lt-set.on .lt-att { animation: sbPop .38s cubic-bezier(.2,.8,.25,1) both; }
.loud-thread.in .lt-set.on .lt-b { animation: sbPop .38s cubic-bezier(.2,.8,.25,1) .13s both; }
/* progress dots only (no label: the headline already says what this is) */
.lt-dots {
  position: absolute; bottom: -32px; left: 50%; translate: -50% 0;
  display: flex; gap: 7px;
  opacity: 0; transition: opacity .5s ease .15s;
}
.loud-thread.in .lt-dots { opacity: 1; }
.lt-dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(34,32,25,.22);
  transition: background .3s ease, scale .3s ease;
}
.lt-dots i.on { background: var(--v2-yellow); scale: 1.3; box-shadow: 0 0 0 1.5px rgba(34,32,25,.4); }

/* the attachment artifacts: real iMessage send-kinds, one per resolution
   (paid receipt, location pin, rich tracking link, triage summary) */
.lt-att {
  align-self: flex-start;
  display: flex; align-items: center; gap: 12px;
  background: #FFFFFF; border-radius: 16px;
  padding: 10px 14px;
  box-shadow: 0 12px 28px rgba(34,32,25,.14);
  font-size: 13px; color: var(--v2-ink);
}
.lt-att b { display: block; font-size: 13.5px; line-height: 1.25; }
.lt-att em { display: block; font-style: normal; color: rgba(34,32,25,.55); font-size: 12px; line-height: 1.3; }
.ltr-ic { font-size: 22px; }
.ltr-paid {
  margin-left: 4px;
  background: #CFEFAF; color: #2E5E0E;
  font-size: 10.5px; font-weight: 800; letter-spacing: .06em;
  padding: 4px 9px; border-radius: var(--r-pill);
}
/* location pin: a tiny stylized map tile (mint blocks + white roads) */
.lt-map { padding: 8px 14px 8px 8px; }
.ltm-tile {
  position: relative; width: 56px; height: 56px; border-radius: 12px;
  overflow: hidden; flex-shrink: 0;
  background: linear-gradient(135deg, #DCEFDD 0%, #CDE8EF 55%, #DCEFDD 100%);
}
.ltm-tile i { position: absolute; background: #FFFFFF; opacity: .85; }
.ltm-tile .r1 { width: 130%; height: 7px; top: 32%; left: -15%; rotate: -18deg; }
.ltm-tile .r2 { width: 7px; height: 130%; left: 60%; top: -15%; rotate: 14deg; }
.ltm-pin {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 22px; filter: drop-shadow(0 3px 4px rgba(0,0,0,.25));
}
/* rich link preview: thumb strip + meta (the tracking card) */
.lt-link { padding: 8px 14px 8px 8px; }
.ltl-thumb {
  width: 56px; height: 44px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 22px;
  background: linear-gradient(135deg, var(--v2-sky-soft), var(--v2-sky));
}
/* triage summary: the chip vocabulary, mathematically honest (2 + 45 = 47) */
.lt-sweep { gap: 10px; }
.ltw-line { color: rgba(34,32,25,.6); font-size: 12.5px; font-weight: 600; }
.lt-call {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: #FFFFFF; border: 1.5px solid rgba(34,32,25,.18);
  border-radius: 17px; padding: 13px 18px; font-size: 15px; color: var(--v2-ink);
  box-shadow: 0 14px 32px rgba(34,32,25,.16);
}
.lt-call .call-dur { color: rgba(34,32,25,.5); }
.lt-b {
  position: relative; max-width: 88%;
  padding: 12px 17px; border-radius: 20px;
  font-size: 16.5px; line-height: 1.42;
}
.lt-b.chan { align-self: flex-start; background: #E9E9EB; color: var(--v2-ink); border-bottom-left-radius: 7px; box-shadow: 0 10px 24px rgba(34,32,25,.12); }
.lt-b.me   { align-self: flex-end; background: var(--v2-blue); color: #FFF; border-bottom-right-radius: 7px; box-shadow: 0 10px 24px rgba(10,132,255,.28); }
.lt-b .tap {
  position: absolute; top: -14px; right: -8px;
  background: #FFFDF7; border: 1.5px solid rgba(34,32,25,.25); border-radius: var(--r-pill);
  padding: 3px 6px; font-size: 12px; box-shadow: 0 2px 8px rgba(0,0,0,.12);
  transform: scale(0);
  transition: transform .4s cubic-bezier(.3,1.6,.4,1) .4s;
}
.loud-thread.in .lt-set.on .tap { transform: scale(1); }

/* =========================================================================
   S2+S3 · Compose bridge → blue mega-room, ONE pinned sequence. The chrome
   assembles, the body types itself by scroll, the giant Send arms, and the
   pill's fill opens into an already-furnished room (Extra's construction,
   verified live: their clip window expands over a room whose headline +
   list sit at final positions UNDERNEATH; content never waits for the
   morph). The room then plays the three rail scenes and hands its digest
   phone off to the carousel device below.
   ========================================================================= */
/* z-index 2: during the unpin the room's tail (the 56px below the viewport
   that carries the rounded exit corners) glides OVER the next section */
.sc-compose { position: relative; height: 640vh; z-index: 2; }
.compose-pin {
  position: sticky; top: 0; height: 100svh;
  /* NO overflow:hidden here: the room hangs 56px past the pin's bottom on
     purpose (rounded corners hide off-screen while pinned, then ride into
     view at the exit, Extra's construction) */
  display: flex; align-items: flex-start;
}
/* the opening window: a viewport-sized starfield ROOM clipped down to the
   pill's exact rect, scrubbed open to full bleed. It CONTAINS the room
   content (left column + stage), laid out at final positions, so the
   expanding window reveals a furnished room, never an empty wall. */
.send-room {
  position: absolute; top: 0; left: 0; right: 0;
  /* 56px taller than the pin: the rounded exit corners live BELOW the
     viewport while pinned (no cream notches mid-scene), then ride up over
     the next section as the pin releases. Keep in sync with the +56 in
     the clip-path bottom inset (v2-scenes.jsx). */
  height: calc(100svh + 56px);
  border-radius: 0 0 var(--r-room) var(--r-room);
  z-index: 6; pointer-events: none;
  overflow: hidden;
  display: flex; align-items: center;
  gap: clamp(28px, 4vw, 64px);
  padding: 0 0 0 clamp(26px, 5vw, 76px);
  color: #FFF;
  /* HORIZONTAL gradient on purpose (one-material law): every horizontal
     cut samples identically, so the unpin seam is invisible. */
  background-image:
    radial-gradient(2px 2px at 22px 34px, rgba(255,255,255,.95), transparent 55%),
    radial-gradient(1.2px 1.2px at 120px 138px, rgba(255,255,255,.7), transparent 55%),
    radial-gradient(1.5px 1.5px at 185px 64px, rgba(255,255,255,.55), transparent 55%),
    linear-gradient(90deg, #3D9BFF 0%, #0A84FF 52%, #0668CC 100%);
  background-size: 230px 190px, 274px 242px, 322px 286px, auto;
  will-change: clip-path;
}
/* before the morph the room hides UNDER the identical-material pill, so
   the swap is invisible */
.send-room.shut { opacity: 0; }
/* focus vignette for the hand-off beat: the room dims around the phone
   (spotlight pattern), positioned children paint above it */
.send-room::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 60% 55% at 50% 46%, transparent 32%, rgba(2,30,70,.42) 100%);
  opacity: 0; transition: opacity .6s ease;
}
.send-room.hand::after { opacity: 1; }
/* the room furnishes itself IN VIEW (never preloaded): the left column
   rises from the BOTTOM as the window opens (.lit), then the rows drop
   in from the TOP right after (.lit2), cascading quick like a sort pass
   (Extra's enter order, founder-confirmed) */
.send-room .reel-left {
  transition: opacity .5s ease, translate .6s var(--ease-spring);
}
.send-room:not(.lit) .reel-left { opacity: 0; translate: 0 52px; }
.send-room:not(.lit2) .feed-row { opacity: 0; translate: 0 -18px; }
.send-room.lit2 .feed-row { transition-delay: calc(var(--ri) * 38ms); }
.compose-in { width: 100%; max-width: 1020px; margin: 0 auto; padding: clamp(64px, 10vh, 110px) clamp(22px, 5vw, 64px) 0; }
/* chrome assembles on section ENTER (IO hook), not on pin catch */
.sc-compose.seen .compose-row { opacity: 1; transform: none; }
.sc-compose.seen .compose-row:nth-child(2) { transition-delay: .12s; }
.sc-compose.seen .compose-row:nth-child(3) { transition-delay: .24s; }

/* compose chrome rows (FROM / TO / ATTACHED), staggered in via .on */
.compose-rows { display: flex; flex-direction: column; gap: 14px; margin-bottom: clamp(28px, 4.5vh, 46px); }
.compose-row {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  opacity: 0; transform: translateY(14px);
  transition: opacity .55s ease, transform .55s cubic-bezier(.2,.7,.2,1);
}
.compose-rows.on .compose-row { opacity: 1; transform: none; }
.compose-rows.on .compose-row:nth-child(2) { transition-delay: .12s; }
.compose-rows.on .compose-row:nth-child(3) { transition-delay: .24s; }
.cr-label {
  width: 86px; flex-shrink: 0;
  font-size: 12px; font-weight: 600; letter-spacing: .1em;
  color: var(--v2-ink-dim);
}
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 16px; border-radius: var(--r-pill);
  font-size: 15px; font-weight: 600;
  border: 1.5px solid var(--v2-ink); box-shadow: var(--shadow-hard-sm);
}
.chip-blue   { background: var(--v2-sky-soft); color: var(--v2-navy); }
.chip-yellow { background: var(--v2-yellow); color: var(--v2-ink); }
.chip-ghost  {
  border: 1.5px dashed rgba(34,32,25,.35); box-shadow: none;
  background: transparent; color: var(--v2-ink-dim); font-weight: 500;
}
/* attached: the loud scene's resolution cluster, scaled to a tilted chip.
   The inner clone is laid out at the cluster's REAL width (440) and
   scaled, so the seam flyer's end state and this landed state are
   pixel-identical: one object, carried across the sections. */
.mini-attach {
  position: relative; width: 176px; height: 54px;
  transform: rotate(-2deg); flex-shrink: 0;
}
.ma-inner {
  position: absolute; top: 0; left: 0;
  width: 440px; height: 135px;
  transform: scale(.4); transform-origin: 0 0;
  display: flex; flex-direction: column; justify-content: center; gap: 9px;
}
.mb.chan { background: #E9E7E0; color: var(--v2-ink); align-self: flex-start; }
.mb.me   { background: var(--v2-blue); color: #FFF; align-self: flex-end; }
.mb { font-size: 11px; line-height: 1.3; padding: 4px 9px; border-radius: 9px; max-width: 150px; }

/* the body types itself — display type, like Extra's email body.
   A hidden sizer holds the FULL height of both paragraphs so the layout
   below (the Send pill) is ANCHORED: nothing shifts while the text types */
.compose-body { position: relative; }
.cb-sizer { visibility: hidden; }
.cb-live { position: absolute; inset: 0; }
.compose-body p {
  font-family: var(--v2-display); font-weight: 600; letter-spacing: -0.015em;
  font-size: clamp(26px, 3.6vw, 50px); line-height: 1.08; margin: 0 0 20px;
}
.cb-p2 { color: var(--v2-amber-deep); }
.caret {
  display: inline-block; width: 3px; height: .92em; margin-left: 6px;
  background: var(--v2-ink); vertical-align: -0.12em; border-radius: 2px;
  animation: caretBlink 1s steps(1) infinite;
}
.cb-p2 .caret { background: var(--v2-amber-deep); }
@keyframes caretBlink { 50% { opacity: 0; } }

/* the giant Send — iMessage-blue stadium pill, arms when the body is done.
   Circle-arrow LEFT of the word (iMessage composition); the arrow LAUNCHES
   off the pill when the morph starts (.fired): a tiny anticipation dip,
   then up and away with a tilt, like the message leaving */
.send-mega {
  display: flex; align-items: center; justify-content: center; gap: clamp(16px, 2.4vw, 30px);
  width: min(860px, 100%);
  margin: clamp(24px, 4vh, 44px) auto 0;
  padding: clamp(20px, 3.2vw, 40px) clamp(40px, 6vw, 88px);
  transform-origin: 50% 100%;
  border-radius: var(--r-pill); text-decoration: none;
  font-family: var(--v2-display); font-weight: 600;
  font-size: clamp(32px, 5.4vw, 72px); letter-spacing: -0.015em; color: #FFF;
  /* same starfield material as .send-room + the blue mega-room: the pill's
     fill IS the next section's background (Extra's continuity trick) */
  background-image:
    radial-gradient(2px 2px at 22px 34px, rgba(255,255,255,.95), transparent 55%),
    radial-gradient(1.2px 1.2px at 120px 138px, rgba(255,255,255,.7), transparent 55%),
    radial-gradient(1.5px 1.5px at 185px 64px, rgba(255,255,255,.55), transparent 55%),
    linear-gradient(90deg, #3D9BFF 0%, var(--v2-blue) 52%, var(--v2-blue-deep) 100%);
  background-size: 230px 190px, 274px 242px, 322px 286px, auto;
  border: var(--bd); box-shadow: 0 6px 0 0 var(--v2-ink);
  position: relative; z-index: 7;
  opacity: .25; transform: scale(.95); filter: saturate(.4);
  transition:
    opacity .6s ease, transform .6s cubic-bezier(.2,.7,.2,1), filter .6s ease,
    box-shadow .35s ease, border-color .35s ease, color .3s ease;
}
.send-mega.armed { opacity: 1; transform: none; filter: none; }
.send-mega.armed:hover { transform: none; box-shadow: 0 4px 0 0 var(--v2-ink); }
/* PORTAL state: once armed, the pill's own paint drops away and the room
   surface (clipped to this exact rect, z-indexed beneath) becomes the
   fill. No swap at the morph: the same surface expands. */
.send-mega.portal { background-image: none; background: transparent; }
/* fired: the button stops being a button (border + shadow + word shed)
   while the arrow launches and the window opens */
.send-mega.fired { border-color: transparent; box-shadow: none; color: transparent; }
.send-mega .sm-circle {
  display: inline-flex; align-items: center; justify-content: center;
  width: clamp(44px, 6vw, 78px); height: clamp(44px, 6vw, 78px);
  border-radius: 50%; background: #FFF; flex-shrink: 0;
  /* anticipation curve: dips a touch, then launches */
  transition:
    translate .8s cubic-bezier(.5, -0.35, .75, .5),
    rotate .8s cubic-bezier(.5, -0.35, .75, .5),
    scale .8s ease,
    opacity .5s ease .28s;
}
/* the send gesture: the arrow takes off, up and slightly away with a tilt */
.send-mega.fired .sm-circle { translate: 48px -190px; rotate: 16deg; scale: .9; opacity: 0; }
.send-mega .sm-circle svg { width: 52%; height: 52%; }
.send-mega .sm-circle svg path { stroke: var(--v2-blue); stroke-width: 3; fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* soft pulse ring, only once armed */
.send-mega.armed::after {
  content: ''; position: absolute; inset: -3px; border-radius: inherit; pointer-events: none;
  border: 2px solid rgba(10,132,255,.45);
  animation: sendRing 2.8s ease-out infinite;
}
@keyframes sendRing {
  0% { opacity: .8; transform: scale(1); }
  70%, 100% { opacity: 0; transform: scale(1.08); }
}

/* =========================================================================
   Device + iMessage thread — Fae-grade frame: metallic rim, side buttons,
   status bar + island; typing dots; tapback pop
   ========================================================================= */
.dev {
  position: relative;
  width: 320px; border-radius: 46px; padding: 7px;
  background: linear-gradient(150deg, #3E3D43 0%, #18171B 38%, #232227 70%, #322F36 100%);
  box-shadow:
    inset 0 0 0 1.5px rgba(255,255,255,.16),
    0 0 0 1px rgba(0,0,0,.35),
    0 18px 44px rgba(34,32,25,.30);
}
.dev-btn { position: absolute; background: #2B2A30; border-radius: 2px; box-shadow: inset 0 0 0 .5px rgba(255,255,255,.18); }
.db-l { left: -2.5px; top: 132px; width: 3px; height: 56px; }
.db-r { right: -2.5px; top: 116px; width: 3px; height: 84px; }
.dev-screen { position: relative; border-radius: 39px; background: var(--th-screen); overflow: hidden; height: 580px; }
.dev-status {
  position: absolute; top: 13px; left: 26px; right: 22px; z-index: 3;
  display: flex; justify-content: space-between; align-items: center;
  color: #FFF; pointer-events: none;
}
.ds-time { font-size: 13px; font-weight: 600; letter-spacing: .02em; }
.ds-icons { width: 52px; height: 12px; display: block; }
.ds-icons rect, .ds-icons circle { fill: rgba(255,255,255,.92); }
.ds-icons .wifi { fill: none; stroke: rgba(255,255,255,.92); stroke-width: 1.7; stroke-linecap: round; }
.ds-icons .batt { fill: none; stroke: rgba(255,255,255,.45); stroke-width: 1.1; }
.dev-island { position: absolute; top: 11px; left: 50%; transform: translateX(-50%); width: 104px; height: 28px; border-radius: var(--r-pill); background: #000; z-index: 4; box-shadow: inset 0 0 0 1px #161616; }
.th { display: flex; flex-direction: column; height: 100%; color: #FFF; }
.th-head { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 56px 0 12px; border-bottom: 1px solid rgba(255,255,255,.08); }
.th-head img { width: 42px; height: 42px; border-radius: 50%; object-fit: cover; }
.th-head span { font-size: 11.5px; color: rgba(255,255,255,.75); font-weight: 400; }
.th-msgs { flex: 1; padding: 16px 14px 78px; display: flex; flex-direction: column; justify-content: flex-end; gap: 8px; overflow: hidden; }
.tb {
  max-width: 80%; padding: 9px 13px; border-radius: 18px;
  font-size: 14.5px; line-height: 1.35; position: relative; font-weight: 400;
  opacity: 0; transform: translateY(10px) scale(.97);
  animation: tbIn .42s cubic-bezier(.2,.8,.25,1) forwards;
}
@keyframes tbIn { to { opacity: 1; transform: none; } }
.tb.chan { align-self: flex-start; background: var(--th-chan); border-bottom-left-radius: 6px; }
.tb.me   { align-self: flex-end;   background: var(--th-me);   border-bottom-right-radius: 6px; }
/* tapback lands with its own spring, after the bubble */
.tb .tap {
  position: absolute; top: -14px; right: -8px;
  background: #3A3A3C; border-radius: var(--r-pill); padding: 3px 6px; font-size: 12px;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
  transform: scale(0); animation: tapIn .4s cubic-bezier(.3,1.6,.4,1) .55s forwards;
}
.tb.me .tap { right: auto; left: -8px; }
@keyframes tapIn { to { transform: scale(1); } }
/* typing indicator (three pulsing dots) */
.tb-typing { display: inline-flex; gap: 4px; align-items: center; padding: 12px 14px; }
.tb-typing span { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,.55); animation: typingDot 1.1s ease-in-out infinite; }
.tb-typing span:nth-child(2) { animation-delay: .15s; }
.tb-typing span:nth-child(3) { animation-delay: .3s; }
@keyframes typingDot { 0%, 60%, 100% { opacity: .35; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }
/* call-answered card (voice concierge vignette) */
.tb-call {
  display: flex; align-items: center; gap: 10px; max-width: 88%;
  background: #1C1C1E; border: 1px solid rgba(255,255,255,.14);
  border-radius: 14px; padding: 11px 13px;
}
.call-ic { font-size: 16px; }
.call-lbl { font-size: 13.5px; font-weight: 500; }
.call-dur { margin-left: auto; font-size: 12px; color: rgba(255,255,255,.5); }
/* =========================================================================
   iMessage composer + home indicator: the bottom anatomy a real iPhone
   never goes without (founder note: a screen must not end at floating
   bubbles). One block, dark by default, .mb-light for white screens.
   ========================================================================= */
.dev-foot {
  position: absolute; bottom: 0; left: 0; right: 0; z-index: 4;
  display: flex; flex-direction: column; gap: 9px; padding: 6px 12px 8px;
}
.msgbar { display: flex; align-items: center; gap: 9px; }
.mb-plus {
  flex-shrink: 0; width: 31px; height: 31px; border-radius: 50%;
  background: rgba(255,255,255,.10); display: grid; place-items: center;
}
.mb-plus svg { width: 13px; height: 13px; fill: none; stroke: rgba(255,255,255,.62); stroke-width: 1.6; stroke-linecap: round; }
.mb-field {
  flex: 1; display: flex; align-items: center; justify-content: space-between;
  border: 1px solid rgba(255,255,255,.22); border-radius: var(--r-pill);
  padding: 6px 8px 6px 13px; font-size: 14px; color: rgba(255,255,255,.38);
}
.mb-mic { width: 15px; height: 15px; flex-shrink: 0; }
.mb-mic rect { fill: rgba(255,255,255,.45); }
.mb-mic .mm-arc { fill: none; stroke: rgba(255,255,255,.45); stroke-width: 1.7; stroke-linecap: round; }
.dev-home { width: 116px; height: 5px; border-radius: 3px; background: rgba(255,255,255,.36); margin: 0 auto; }
/* light variant (white digest screen) */
.mb-light .mb-plus { background: rgba(34,32,25,.07); }
.mb-light .mb-plus svg { stroke: rgba(34,32,25,.55); }
.mb-light .mb-field { border-color: rgba(34,32,25,.22); color: rgba(34,32,25,.4); }
.mb-light .mb-mic rect { fill: rgba(34,32,25,.42); }
.mb-light .mb-mic .mm-arc { stroke: rgba(34,32,25,.42); }
/* live composer state: typed text + caret + the blue send button */
.mb-live .mb-field { border-color: rgba(255,255,255,.3); }
.mb-typed { color: #FFF; display: inline-flex; align-items: center; white-space: nowrap; overflow: hidden; }
.mb-caret { width: 2px; height: 15px; margin-left: 1px; background: #4C8DFF; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
.mb-send {
  flex-shrink: 0; width: 23px; height: 23px; border-radius: 50%;
  background: var(--th-me, #0A84FF); display: grid; place-items: center;
  animation: tapIn .3s cubic-bezier(.3,1.6,.4,1);
}
.mb-send svg { width: 12px; height: 12px; fill: none; stroke: #FFF; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }

/* simplified iOS dark keyboard (fills the lower screen like a real
   mid-conversation phone; Folk's composition) */
.kb { background: rgba(255,255,255,.045); border-radius: 10px 10px 0 0; padding: 7px 3px 6px; margin: 0 -4px; }
.kb-r { display: flex; justify-content: center; }
.kb-r2 { padding: 0 14px; }
.kk {
  flex: 1; height: 31px; margin: 2.5px; border-radius: 5px;
  background: #565658; color: rgba(255,255,255,.92);
  display: grid; place-items: center;
  font-size: 13.5px; font-weight: 400; font-family: var(--v2-body);
  box-shadow: 0 1px 0 rgba(0,0,0,.45);
}
.kk-sp { background: #3A3A3C; flex: 1.4; font-size: 12px; }
.kk-123 { flex: 1.6; font-size: 11px; }
.kk-space { flex: 5.2; }
.kk-ret { flex: 2.2; font-size: 11px; }

/* contact-head chrome: back chevron + unread count, video call button
   (the parts a real Messages thread always shows) */
.th-head { position: relative; }
.th-back {
  position: absolute; left: 13px; top: 64px;
  display: flex; align-items: center; gap: 5px;
}
.th-back svg { width: 9px; height: 15px; fill: none; stroke: #0A84FF; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.th-back i {
  font-style: normal; min-width: 21px; height: 18px; padding: 0 6px;
  border-radius: var(--r-pill); background: #3A3A3C; color: rgba(255,255,255,.85);
  font-size: 11px; font-weight: 600; display: grid; place-items: center;
}
.th-vid { position: absolute; right: 15px; top: 66px; }
.th-vid svg { width: 24px; height: 16px; fill: rgba(255,255,255,.7); }

/* glare sweep across the screen when a scene lands */
.dev-screen::after {
  content: ''; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: linear-gradient(115deg, transparent 38%, rgba(255,255,255,.12) 49%, transparent 60%);
  transform: translateX(-130%);
}
.dev.glint .dev-screen::after { animation: glint 1s ease .2s forwards; }
@keyframes glint { to { transform: translateX(130%); } }

/* =========================================================================
   The mega-room interior (lives INSIDE .send-room) — rail left, full-bleed
   transforming stage right.
   Scene 0: raw feed fills the full height, wipe stamps chips row by row.
   Scene 1: rows fly off, the four chips float.
   Scene 2: the digest PHONE rises (outline frame, bleeds past the bottom)
   and drifts centerward to hand off to the carousel device below.
   ========================================================================= */
.reel-left { position: relative; z-index: 2; flex-shrink: 0; width: min(430px, 34%); }
.reel-left h2 { font-size: clamp(30px, 3.6vw, 54px); margin-bottom: 36px; color: #FFF; }
.reel-rail { position: relative; display: flex; flex-direction: column; gap: 4px; }
.reel-rail::before {
  content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; width: 2.5px;
  border-radius: 2px; background: rgba(255,255,255,.3);
}
.rail-dot {
  position: absolute; left: -3.5px; top: var(--dot-y, 18px); width: 10px; height: 10px;
  border-radius: 50%; background: var(--v2-yellow);
  box-shadow: 0 0 0 3px rgba(255,255,255,.22);
  transition: top .5s cubic-bezier(.2,.7,.2,1);
}
.reel-item { padding: 10px 0 10px 22px; cursor: default; }
.reel-item .ri-label { font-family: var(--v2-display); font-weight: 600; font-size: 18px; color: rgba(255,255,255,.5); transition: color .3s ease; }
.reel-item .ri-cap { max-height: 0; overflow: hidden; opacity: 0; transition: max-height .45s ease, opacity .45s ease .1s; font-size: 14.5px; color: rgba(255,255,255,.88); line-height: 1.5; max-width: 340px; }
.reel-item.on .ri-label { color: #FFF; }
.reel-item.on .ri-cap { max-height: 96px; opacity: 1; margin-top: 6px; }

/* the stage: fills the right side FULL HEIGHT (Extra's list bleeds past
   both edges; the rows run to the right edge of the viewport) */
.reel-stage { position: relative; z-index: 1; flex: 1; align-self: stretch; min-width: 0; }

/* scene 0/1 · the raw feed — rows distribute across the full height */
.feed { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-evenly; }
.feed-row {
  display: flex; align-items: center; gap: 13px;
  padding: 13px 10px; min-width: 0; white-space: nowrap;
  border-bottom: 1px solid rgba(255,255,255,.18);
  color: #FFF; font-size: 15px;
  transition:
    opacity .5s ease,
    translate .55s cubic-bezier(.2,.8,.25,1),
    transform .55s cubic-bezier(.4,0,.6,1);
}
.feed-e { width: 24px; flex-shrink: 0; font-size: 16px; opacity: 0; transform: scale(.4); transition: opacity .35s ease, transform .35s cubic-bezier(.3,1.4,.4,1); }
.feed-row .fchip { opacity: 0; transform: scale(.6); transition: opacity .35s ease, transform .35s cubic-bezier(.3,1.4,.4,1); }
.feed-row.sorted .feed-e, .feed-row.sorted .fchip { opacity: 1; transform: none; }
.feed-from { font-weight: 700; width: 162px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; }
.feed-txt { opacity: .85; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.feed-txt b { font-weight: 700; }
/* scene 1+: rows fly off to the right (stagger comes from the .lit rule) */
.st-1 .feed-row, .st-2 .feed-row { opacity: 0; transform: translateX(80px); border-bottom-color: transparent; }

/* the category chips (Extra's colored pills, Chan vocabulary) */
.fchip {
  display: inline-flex; align-items: center; flex-shrink: 0;
  padding: 5px 13px; border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 700; letter-spacing: .01em;
}
.fc-need  { background: #E9D9FF; color: #5B2D91; }
.fc-done  { background: #CFEFAF; color: #2E5E0E; }
.fc-wait  { background: #FFE9A8; color: #7A4A00; box-shadow: inset 0 0 0 1px rgba(122,74,0,.25); }
.fc-noise { background: rgba(255,255,255,.3); color: rgba(74,45,0,.75); box-shadow: inset 0 0 0 1.5px rgba(74,45,0,.35); }
/* noise chip on the blue room reads white-on-glass */
.reel-stage .fc-noise { background: rgba(255,255,255,.16); color: rgba(255,255,255,.85); box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.4); }

/* scene 1 · the sorted tally: each chip DETACHES from its category's first
   row (base state = that row's chip position, with the rows at 13-way
   space-evenly) and floats out to its big spot as the rows fly off, so the
   tally visibly comes FROM the list (Extra's shared-element move). Counts
   are computed from FEED, so they can never drift from the rows. */
.chips-float { position: absolute; inset: 0; pointer-events: none; }
.chips-float .fchip {
  position: absolute; font-size: clamp(16px, 1.5vw, 21px); padding: 13px 26px;
  box-shadow: 0 16px 38px rgba(2,38,88,.3);
  left: 3%;
  opacity: 0; transform: scale(.5); transform-origin: 0 50%;
  transition:
    left .8s var(--ease-spring), top .8s var(--ease-spring),
    transform .6s cubic-bezier(.2,.8,.25,1), opacity .35s ease;
  transition-delay: calc(var(--ci) * 90ms);
}
.chips-float .fchip i { font-style: normal; margin-left: 12px; opacity: .62; font-weight: 800; }
/* FROM: the first row of each category (rows 1, 3, 4, 11 of 13) */
.chips-float .fchip:nth-child(1) { top: 2.5%; }
.chips-float .fchip:nth-child(2) { top: 18%; }
.chips-float .fchip:nth-child(3) { top: 25.5%; }
.chips-float .fchip:nth-child(4) { top: 79.5%; }
/* TO: the floating constellation */
.st-1 .chips-float .fchip { opacity: 1; transform: none; }
.st-1 .chips-float .fchip:nth-child(1) { left: 14%; top: 24%; rotate: -3deg; }
.st-1 .chips-float .fchip:nth-child(2) { left: 47%; top: 36%; rotate: 2deg; }
.st-1 .chips-float .fchip:nth-child(3) { left: 22%; top: 54%; rotate: 2deg; }
.st-1 .chips-float .fchip:nth-child(4) { left: 52%; top: 68%; rotate: -2deg; }
/* scene 2: the chips CONVERGE INTO THE PHONE and become the texts (the
   sorted categories get texted to you): all four stream to the phone's
   upper screen, shrinking out, staggered by their existing delays */
.st-2 .chips-float .fchip { left: 60%; top: 30%; opacity: 0; transform: scale(.22); }

/* scene 2 · the brief arrives AS A PHONE: an outline device frame on the
   right (Extra's Today-Tab move: their last rail scene renders inside a
   phone outline that hands off to the next section's real device). It
   BLEEDS past the bottom edge, so there is no empty floor under the
   thread, and drifts centerward during the hand-off beat. */
.dg-phone {
  /* right offset mirrors the JS hand-off math (60px..18vw..270px): the
     phone parks just right of center, then travels to TRUE center.
     SIZED TO ITS CONTENT, not to the viewport: a ~2.05 aspect device
     small enough that the brief + composer FILL the screen (founder
     note: the tall version read as an endless white slab). Fits whole
     above the fold from ~900px viewports up. */
  position: absolute; right: clamp(60px, 18vw, 270px); top: 8vh;
  width: min(384px, 42%);
  height: min(88vh, calc(min(384px, 42vw) * 2.05));
  z-index: 3;
  border: 2px solid rgba(255,255,255,.55);
  border-radius: 54px;
  padding: 10px;
  opacity: 0; transform: translateY(12%);
  transition: opacity .6s ease, transform .65s cubic-bezier(.2,.7,.2,1);
  will-change: transform;
}
.st-2 .dg-phone { opacity: 1; transform: none; }
/* dynamic island over the light screen */
.dg-phone::before {
  content: ''; position: absolute; top: 22px; left: 50%; transform: translateX(-50%);
  width: 96px; height: 26px; border-radius: var(--r-pill);
  background: #0B1726; z-index: 2;
}
/* hardware language: power button right, volume pair left */
.dg-phone::after {
  content: ''; position: absolute; right: -5px; top: 124px;
  width: 3px; height: 64px; border-radius: 2px;
  background: rgba(255,255,255,.55);
}
.dgp-btn {
  position: absolute; left: -5px; width: 3px; border-radius: 2px;
  background: rgba(255,255,255,.55);
}
.dgp-vol1 { top: 108px; height: 38px; }
.dgp-vol2 { top: 156px; height: 38px; }
.digest {
  position: absolute; inset: 10px;
  background: #FFFFFF; color: var(--v2-ink);
  border-radius: 45px;
  box-shadow: 0 28px 64px rgba(2,38,88,.55);
  padding: 62px 22px 26px;
  display: flex; flex-direction: column; gap: 9px;
  overflow: hidden;
}
/* the composer parks at the screen's bottom edge, above the home bar */
.digest .msgbar { margin-top: auto; }
/* home indicator (visible when the full device fits on screen) */
.digest::after {
  content: ''; position: absolute; bottom: 9px; left: 50%; transform: translateX(-50%);
  width: 110px; height: 5px; border-radius: 3px; background: rgba(34,32,25,.28);
}
.dg-head { display: flex; flex-direction: column; align-items: center; gap: 5px; padding-bottom: 4px; }
.dg-head img { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; }
.dg-name { font-size: 12px; color: rgba(34,32,25,.65); }
.dg-stamp { text-align: center; font-size: 11px; color: rgba(34,32,25,.45); margin-bottom: 6px; }
/* light-mode bubbles: they POP in staggered like arriving texts (an
   overshoot bezier on the transition keeps it scrub-reversible) */
.dgb {
  position: relative; max-width: 84%;
  align-self: flex-start; background: #E9E9EB; color: var(--v2-ink);
  padding: 9px 13px; border-radius: 18px; border-bottom-left-radius: 6px;
  font-size: 14.5px; line-height: 1.4;
  opacity: 0; transform: translateY(12px) scale(.6);
  transition: opacity .22s ease, transform .38s cubic-bezier(.34,1.56,.5,1);
  transition-delay: calc(var(--bi, 0) * 95ms + .2s);
}
.dgb.me { align-self: flex-end; background: var(--v2-blue); color: #FFF; border-radius: 18px; border-bottom-right-radius: 6px; }
.st-2 .dgb { opacity: 1; transform: none; }
.dgb .tap {
  position: absolute; top: -14px; right: -8px;
  background: #FFFDF7; border: 1.5px solid rgba(34,32,25,.25); border-radius: var(--r-pill);
  padding: 3px 6px; font-size: 12px; box-shadow: 0 2px 8px rgba(0,0,0,.12);
  transform: scale(0); transition: transform .4s cubic-bezier(.3,1.6,.4,1);
  transition-delay: calc(var(--bi, 0) * 110ms + .65s);
}
.dgb.me .tap { right: auto; left: -8px; }
.st-2 .dgb .tap { transform: scale(1); }

/* =========================================================================
   The attach flyer — the resolution cluster shrinks, tilts, and lands in
   the compose letter's ATTACHED slot across the loud->compose seam. Faces
   are laid out at their REAL widths and transform-scaled, so text wrap
   matches both takeovers exactly.
   ========================================================================= */
.lh-fly { position: fixed; z-index: 55; pointer-events: none; }
.lhf-a {
  position: absolute; top: 0; left: 0; transform-origin: 0 0;
  display: flex; flex-direction: column; justify-content: center; gap: 9px;
}
.lh-morph .loud-thread, .lh-morph .compose-rows .mini-attach { visibility: hidden; }

/* =========================================================================
   The phone flyer — ONE object across the room->carousel seam. While the
   pin releases, both real phones hide (body.ph-morph) and this fixed
   element interpolates rect + radius from the digest phone's live position
   to the device's caught position, crossfading white -> dark hardware.
   ========================================================================= */
.ph-fly {
  position: fixed; z-index: 60; pointer-events: none;
  filter: drop-shadow(0 30px 60px rgba(2,38,88,.35));
}
.phf-l, .phf-d { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; }
/* light face: the digest phone's language (outline + white screen + island) */
.phf-l { border: 2px solid rgba(255,255,255,.55); }
.phf-lscr {
  position: absolute; inset: 10px;
  background: #FFF; border-radius: 45px;
  overflow: hidden; color: var(--v2-ink);
}
.phf-cl {
  position: absolute; inset: 0; padding: 62px 22px 0;
  display: flex; flex-direction: column; gap: 9px;
}
/* the clone carries the digest's composer so the flyer overlays the real
   phone EXACTLY at hand-off start (a missing bar would pop on unhide) */
.phf-bar { position: absolute; bottom: 22px; left: 22px; right: 22px; transition: opacity .2s ease, transform .22s ease; }
.phf-lscr::after {
  content: ''; position: absolute; bottom: 9px; left: 50%; transform: translateX(-50%);
  width: 110px; height: 5px; border-radius: 3px; background: rgba(34,32,25,.28);
}
/* UNSEND choreography: the digest leaves one bubble at a time (newest
   first), each shrinking into itself the way a recalled message does.
   Rows are visible by default (the flyer has no .st-2 ancestor). */
.phf-cl .dgb {
  opacity: 1; transform: none; transition: opacity .17s ease, transform .2s cubic-bezier(.55,-0.3,.8,.6);
}
.phf-cl .dgb .tap { transform: scale(1); transition: none; }
.phf-cl .dgb.out { opacity: 0; transform: scale(.25) translateY(-4px); }
.phf-cl .dg-head, .phf-cl .dg-stamp { transition: opacity .2s ease, transform .22s ease; }
.phf-cl .dg-head.out, .phf-cl .dg-stamp.out, .phf-bar.out { opacity: 0; transform: scale(.92); }
/* then the next thread POPS in oldest-first, like being texted */
.phf-cd { position: absolute; inset: 0; }
.phf-cd .sb { opacity: 0; transform: translateY(14px) scale(.6); transition: opacity .2s ease, transform .32s cubic-bezier(.34,1.56,.5,1); }
.phf-cd .sb.in { opacity: 1; transform: none; }
.phf-cd .th-head, .phf-cd .dev-foot { opacity: 0; transition: opacity .3s ease; }
.phf-cd.cd-in .th-head, .phf-cd.cd-in .dev-foot { opacity: 1; }
.phf-l::before {
  content: ''; position: absolute; top: 22px; left: 50%; transform: translateX(-50%);
  width: 96px; height: 26px; border-radius: var(--r-pill);
  background: #0B1726; z-index: 2;
}
/* dark face: the carousel device's language (metallic rim, black screen) */
.phf-d {
  background: linear-gradient(150deg, #3E3D43 0%, #18171B 38%, #232227 70%, #322F36 100%);
  box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.16);
  padding: 7px;
}
.phf-scr { position: absolute; inset: 7px; border-radius: 39px; background: #000; overflow: hidden; }
.phf-scr::before {
  content: ''; position: absolute; top: 11px; left: 50%; transform: translateX(-50%);
  width: 104px; height: 28px; border-radius: var(--r-pill); background: #000;
  box-shadow: inset 0 0 0 1px #161616; z-index: 4;
}
.phf-msgs { display: flex; flex-direction: column; gap: 8px; padding: 10px 14px; }
/* both real phones hide while the flyer owns the seam */
.ph-morph .dg-phone, .ph-morph .caro-dev .dev { visibility: hidden; }

/* =========================================================================
   The tapback zoom — diving INTO the 💪 the visitor just watched land:
   a yellow disc grows from the tapback's live position until its color
   owns the viewport, then melts to cream as the next section catches.
   Geometry + color are driven per-frame from JS (scroll-scrubbed).
   ========================================================================= */
.fz {
  position: fixed; z-index: 62; pointer-events: none;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  /* FEATHERED wash, never a hard-edged disc: solid heart, soft skirt.
     By full size the skirt is past the viewport, so coverage is total. */
  background: radial-gradient(circle closest-side,
    var(--v2-yellow) 60%, rgba(255,181,0,.85) 76%, rgba(255,181,0,0) 100%);
  display: grid; place-items: center;
}
.fz-e { line-height: 1; }

/* =========================================================================
   S4 · Autopilot — PINNED scroll-scrub; the five screens slide through
   the fixed frame and settle to full opacity (Extra's carousel mechanic)
   ========================================================================= */
.sc-auto { position: relative; height: 380vh; }
.auto-pin {
  position: sticky; top: 0; height: 100svh; overflow: hidden;
  display: flex; align-items: center;
  gap: clamp(30px, 4vw, 70px);
  background-image: radial-gradient(rgba(34,32,25,.06) 1px, transparent 1px);
  background-size: 24px 24px;
  padding: 0 0 0 clamp(26px, 5vw, 84px);
}
/* the copy column sits hard left (Extra's 322px rail at x=24) */
.auto-copy { flex-shrink: 0; width: min(440px, 33%); text-align: left; }
.auto-copy h2 { font-size: clamp(27px, 3.1vw, 48px); }
/* layout-locked lockup: both lines are nowrap blocks, so the rotating
   word only widens its pill rightward and the sentence NEVER re-wraps
   (no more "meetings" dropping a line) */
.auto-h { display: flex; flex-direction: column; align-items: flex-start; }
.ah-l { white-space: nowrap; }
.word-hl {
  display: inline-flex; justify-content: center; overflow: hidden; white-space: nowrap;
  vertical-align: bottom; box-sizing: border-box;
  padding: 0 16px 5px; margin: 0 4px; border-radius: 10px;
  background: linear-gradient(0deg, var(--v2-yellow) 44%, transparent 44%);
  transition: width .4s cubic-bezier(.2,.7,.25,1);
}
.word-hl .wp-txt { display: inline-block; animation: wordIn .4s cubic-bezier(.2,.8,.25,1); }
.word-pill {
  display: inline-flex; justify-content: center; overflow: hidden; white-space: nowrap;
  vertical-align: bottom; box-sizing: border-box;
  padding: 2px 20px 6px; margin: 0 4px;
  border: var(--bd); border-radius: var(--r-pill); background: var(--v2-yellow);
  box-shadow: var(--shadow-hard-sm);
  transition: width .4s cubic-bezier(.2,.7,.25,1);
}
.word-pill .wp-txt { display: inline-block; animation: wordIn .4s cubic-bezier(.2,.8,.25,1); }
@keyframes wordIn { from { opacity: 0; transform: translateY(10px); } }
.wp-meas { position: absolute; visibility: hidden; white-space: pre; pointer-events: none; }
/* the subcaption belongs to the rotating word: keyed remount replays the
   rise on every swap. Line 1 = what Chan does; line 2 (its own block,
   slightly stronger) = what you do. */
.auto-sub {
  margin: 20px 0 0; color: var(--v2-ink-soft); max-width: 400px;
  animation: subIn .45s cubic-bezier(.2,.8,.25,1) both;
}
.as-2 { display: block; margin-top: 3px; color: var(--v2-ink); font-weight: 500; }
@keyframes subIn { from { opacity: 0; transform: translateY(8px); } }

/* the stage: BIG phone (Extra's is ~400px wide, bleeding vertically),
   two ghost sheets queued to the right, running off-canvas */
.caro { flex: 1; min-width: 0; display: flex; align-items: center; gap: clamp(24px, 3vw, 44px); margin-right: clamp(-180px, -9vw, -70px); }
.caro-dev { flex-shrink: 0; }
.caro-dev .dev { width: 392px; }
.caro-dev .dev-screen { height: min(74vh, 720px); }
/* viewport + sliding strip of per-word screens (bottom stops above the
   composer + keyboard, exactly where a real mid-typing thread ends) */
.scr-vp { position: absolute; top: 118px; bottom: 236px; left: 0; right: 0; overflow: hidden; }
/* the carousel's foot carries the live composer + keyboard */
.caro-foot { gap: 7px; padding: 4px 10px 7px; }
.scr-track {
  display: flex; height: 100%; width: 500%;
  transition: transform .65s cubic-bezier(.2,.7,.2,1);
}
.scr {
  /* bottom-anchored like a real iMessage thread: the newest bubble sits
     just above the composer; history runs upward */
  width: 20%; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 8px;
  padding: 6px 14px 10px;
  opacity: .3; transition: opacity .5s ease .1s;
}
.scr.on { opacity: 1; }
.stamp { text-align: center; font-size: 10.5px; color: rgba(255,255,255,.45); margin-bottom: 4px; }
/* static bubbles for the sliding screens (packed, no entry animation) */
.sb {
  position: relative; max-width: 82%;
  padding: 9px 13px; border-radius: 18px;
  font-size: 14px; line-height: 1.35; font-weight: 400; color: #FFF;
}
.sb.chan { align-self: flex-start; background: var(--th-chan); border-bottom-left-radius: 6px; }
.sb.me   { align-self: flex-end;   background: var(--th-me);   border-bottom-right-radius: 6px; }
.sb .tap {
  position: absolute; top: -14px; right: -8px;
  background: #3A3A3C; border-radius: var(--r-pill); padding: 3px 6px; font-size: 12px;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
/* a reaction on YOUR bubble (Chan reacting to you) hangs off its left
   shoulder, like real Messages */
.sb.me .tap { right: auto; left: -8px; }
/* a pasted URL inside your own bubble (real Messages link styling) */
.sb.lnkb { text-decoration: underline; text-underline-offset: 2.5px; text-decoration-thickness: 1px; }
/* rich LINK PREVIEW card: the one attachment kind Chan really sends for
   reviews/invoices (a URL that unfurls: thumb + title + grey domain) */
.lk {
  align-self: flex-start; display: flex; align-items: center; gap: 11px;
  max-width: 88%;
  background: #1C1C1E; border: 1px solid rgba(255,255,255,.14);
  border-radius: 14px; padding: 9px 13px 9px 9px;
  color: #FFF;
}
.lk-th {
  flex-shrink: 0; width: 42px; height: 42px; border-radius: 10px;
  display: grid; place-items: center; font-size: 19px;
}
.lk-g { background: #FFF; color: #4285F4; font-weight: 700; font-family: var(--v2-body); font-size: 23px; }
.lk-s { background: #32325D; font-size: 18px; }
.lk-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lk b { font-size: 12.5px; font-weight: 600; line-height: 1.3; }
.lk b, .lk em { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lk em { font-style: normal; font-size: 10.5px; color: rgba(255,255,255,.48); }
/* the page-wide bubble law (founder): a text POPS in like it was just
   sent, it never fades in. One springy keyframe used everywhere. */
@keyframes sbPop {
  from { opacity: 0; transform: translateY(14px) scale(.6); }
  70%  { opacity: 1; transform: translateY(-2px) scale(1.03); }
  to   { opacity: 1; transform: none; }
}
/* live-tail entrances */
.sb.pop, .lk.pop { animation: sbPop .38s cubic-bezier(.2,.8,.25,1); }
.sb .tap.tp { animation: tapIn .4s cubic-bezier(.3,1.6,.4,1); }
/* history rows replay the texted-in cascade whenever a screen takes
   the stage (class re-application restarts the animation) */
.scr.on .hb { animation: sbPop .36s cubic-bezier(.2,.8,.25,1) calc(var(--hi, 0) * 70ms) both; }
/* Chan's typing dots, thread-bubble sized */
.sb-typing { display: inline-flex; gap: 4px; align-items: center; padding: 12px 14px; width: max-content; }
.sb-typing span { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,.55); animation: typingDot 1.1s ease-in-out infinite; }
.sb-typing span:nth-child(2) { animation-delay: .15s; }
.sb-typing span:nth-child(3) { animation-delay: .3s; }
/* entrance: the phone is ALWAYS present (the mega-room's digest phone
   hands off to it across the seam, so a re-entrance would break the
   object continuity); only the queued ghosts slide in from the right */
.caro:not(.seen) .ghost { opacity: 0; translate: 64px 0; }

/* ghost neighbors carry REAL greyed content (Extra's queued sheets) */
.ghost {
  width: 300px; flex-shrink: 0; align-self: center; height: min(66vh, 620px);
  border: 1.5px dashed rgba(34,32,25,.32); border-radius: 36px;
  display: flex; flex-direction: column; gap: 9px; padding: 26px 22px;
  opacity: .6; overflow: hidden;
  animation: ghostIn .5s ease;
  transition: opacity .55s ease .15s, translate .7s var(--ease-spring) .15s;
}
@keyframes ghostIn { from { opacity: 0; } to { opacity: .6; } }
.ghost-dim { opacity: .3; }
.ghost b {
  font-family: var(--v2-display); font-weight: 600; font-size: 17px;
  color: var(--v2-ink-dim); text-transform: capitalize; text-align: left; margin-bottom: 8px;
}
.gmb {
  max-width: 92%; align-self: flex-start;
  background: rgba(34,32,25,.08); color: rgba(34,32,25,.5);
  font-size: 11.5px; line-height: 1.35; text-align: left;
  padding: 7px 10px; border-radius: 12px; border-bottom-left-radius: 4px;
}
.gmb.me { align-self: flex-end; background: rgba(10,132,255,.18); color: rgba(27,57,96,.6); border-radius: 12px; border-bottom-right-radius: 4px; }

/* the switcher: iMessage PINNED CHATS, Chan's own UI metaphor (round
   contact circles, blue unread dot, preview balloon over the active pin)
   instead of Extra's borrowed app dock */
.pins {
  /* centered WITHOUT a self-transform: the reveal system resets
     transform on .seen, which silently killed a translateX(-50%) here */
  position: absolute; bottom: 22px; left: 0; right: 0; margin: 0 auto;
  width: max-content; z-index: 6;
  display: flex; align-items: flex-start; gap: clamp(10px, 1.7vw, 24px);
}
.pin-it {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 0 4px; background: none; border: none; cursor: pointer;
  font-family: var(--v2-body);
  transition: opacity .45s ease, translate .5s var(--ease-spring);
  transition-delay: calc(var(--di, 0) * 50ms);
}
/* pins pop in one by one once the carousel pins */
.pins:not(.seen) .pin-it { opacity: 0; translate: 0 18px; }
.pin-face {
  position: relative; width: 56px; height: 56px; border-radius: 50%;
  background: #FFFDF7; border: 1.5px solid rgba(34,32,25,.22);
  display: grid; place-items: center; font-size: 26px; line-height: 1;
  box-shadow: 0 2px 0 0 rgba(34,32,25,.10);
  transition: transform .18s cubic-bezier(.3,1.3,.4,1), border-color .18s ease, box-shadow .18s ease;
}
/* unread dot = the active chat */
.pin-dot {
  position: absolute; top: 0; right: -1px; width: 13px; height: 13px; border-radius: 50%;
  background: var(--v2-blue); border: 2px solid var(--v2-cream);
  transform: scale(0); transition: transform .3s cubic-bezier(.3,1.6,.4,1) .12s;
}
.pin-l { font-size: 11px; font-weight: 600; color: var(--v2-ink-dim); transition: color .18s ease; }
.pin-it:hover .pin-face { transform: translateY(-4px) scale(1.07); }
.pin-it.on .pin-face { border-color: var(--v2-ink); box-shadow: var(--shadow-hard-sm); transform: translateY(-3px) scale(1.05); }
.pin-it.on .pin-dot { transform: scale(1); }
.pin-it.on .pin-l { color: var(--v2-ink); }
/* the preview balloon Messages floats over a pinned chat with news */
.pin-bub {
  position: absolute; bottom: calc(100% + 12px); left: 50%;
  background: #FFFDF7; border: 1.5px solid rgba(34,32,25,.25); border-radius: 13px;
  padding: 6px 10px; font-size: 11px; font-weight: 500; color: var(--v2-ink-soft);
  white-space: nowrap; box-shadow: var(--shadow-hard-sm);
  transform: translateX(-50%);
  animation: bubPop .45s cubic-bezier(.3,1.4,.4,1) both;
}
/* the balloon's tail dot, pointing back at the chat circle */
.pin-bub::after {
  content: ''; position: absolute; top: calc(100% + 2px); left: 50%; transform: translateX(-50%);
  width: 7px; height: 7px; border-radius: 50%;
  background: #FFFDF7; box-shadow: inset 0 0 0 1.5px rgba(34,32,25,.25);
}
@keyframes bubPop { from { opacity: 0; transform: translateX(-50%) translateY(6px) scale(.7); } }

.beta-chip {
  font-style: normal; font-size: 10px; font-weight: 700; letter-spacing: .1em;
  background: var(--v2-yellow); color: var(--v2-ink);
  padding: 3px 8px; border-radius: var(--r-pill);
  vertical-align: middle;
}

/* =========================================================================
   S6 · Trio cards — marketing / meetings / calls (Extra's pastel trio)
   ========================================================================= */
.sc-trio { padding: clamp(70px, 10vh, 120px) var(--room-x) clamp(80px, 10vh, 130px); max-width: calc(var(--v2-max) + 44px); margin: 0 auto; }
.trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; align-items: stretch; }
.tcard {
  border: var(--bd); border-radius: 26px;
  box-shadow: 0 4px 0 0 var(--v2-ink);
  padding: 24px 24px 28px;
  display: flex; flex-direction: column;
  min-height: 380px;
  transition:
    transform .15s ease, box-shadow .15s ease,
    opacity .6s ease, translate .7s var(--ease-spring), scale .7s var(--ease-spring);
}
.tcard:hover { transform: translateY(-3px); box-shadow: 0 7px 0 0 var(--v2-ink); }
/* staggered rise (per-property delays so hover stays instant) */
.trio[data-reveal] .tcard { opacity: 0; translate: 0 36px; scale: .97; }
.trio.seen .tcard { opacity: 1; translate: 0 0; scale: 1; }
.trio.seen .tcard:nth-child(2) { transition-delay: 0s, 0s, .12s, .12s, .12s; }
.trio.seen .tcard:nth-child(3) { transition-delay: 0s, 0s, .24s, .24s, .24s; }
.tc-butter { background: var(--v2-butter); color: var(--v2-brown); }
.tc-sky    { background: var(--v2-sky-soft); color: var(--v2-navy); }
.tc-night  { background: var(--v2-night); color: #F5EFE3; }
.tcard h3 { font-size: 19px; margin: 22px 0 8px; }
.tcard p { margin: 0; font-size: 14.5px; line-height: 1.55; opacity: .82; }
.tc-ui { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 10px; }
.auto-note {
  position: relative;
  width: min(460px, 88vw); text-align: left;
  background: #201D16; color: #FFF; border-radius: 22px;
  padding: 14px 18px 16px;
  box-shadow: 0 14px 34px rgba(34,32,25,.22);
}
.an-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.an-head img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; }
.an-name { font-size: 13px; font-weight: 600; color: rgba(255,255,255,.85); }
.an-time { margin-left: auto; font-size: 12px; color: rgba(255,255,255,.45); }
.an-body { font-size: 15px; line-height: 1.45; color: rgba(255,255,255,.96); font-weight: 400; }
.tc-note { width: 100%; box-shadow: 0 10px 24px rgba(34,32,25,.25); }
.tc-bubbles { display: flex; flex-direction: column; gap: 7px; }
/* trio bubbles arrive as texts once the cards have risen */
.trio.seen .tc-bubbles .mb { animation: sbPop .4s cubic-bezier(.2,.8,.25,1) calc(var(--mi, 0) * 150ms + .4s) both; }
.tc-bubbles .mb { font-size: 13px; line-height: 1.4; padding: 8px 12px; border-radius: 14px; max-width: 88%; }
.tc-night .mb.chan { background: var(--th-chan); color: #FFF; }
.tc-call {
  display: flex; align-items: center; gap: 10px;
  background: #1C1C1E; border: 1px solid rgba(255,255,255,.14); color: #FFF;
  border-radius: 14px; padding: 11px 13px;
}

/* =========================================================================
   S7 · The payoff field — Chan artifacts floating around the headline
   (Extra's emoji scatter: 3 depth layers, blur DOF, scroll parallax)
   ========================================================================= */
/* the payoff is now the MARIGOLD room (the reel moved to the blue cosmos):
   noise scene = cream + the world's UI cards; this = yellow + Chan's own
   artifacts. Same composition, opposite world, on purpose. */
.sc-scat {
  position: relative; min-height: 108vh;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(170px, 24vh, 260px) 24px;
  margin: 0 var(--room-x); border-radius: var(--r-room);
  background:
    radial-gradient(120% 90% at 50% 38%, rgba(255,233,170,.5), transparent 60%),
    radial-gradient(130% 100% at 50% 50%, transparent 55%, rgba(122,72,0,.22) 100%),
    var(--v2-yellow);
  overflow: hidden;
}
.scat-field { position: absolute; inset: 0; pointer-events: none; }
.scit {
  position: absolute;
  transform: translateY(calc(var(--sy, 0) * var(--sp, .4) * -1px));
  will-change: transform;
}
/* bubbles (light-mode iMessage + SMS green; product-true rails) */
.sc-b {
  display: inline-block; max-width: 270px;
  padding: 13px 19px; border-radius: 24px;
  font-size: 18px; line-height: 1.35; font-weight: 500;
  white-space: nowrap;
}
/* big floating 3D emoji (Extra's scatter vocabulary, Chan's workload) */
.sc-e { display: inline-block; line-height: 1; filter: none; }
.sc-b.me   { background: var(--v2-blue); color: #FFF; border-bottom-right-radius: 7px; box-shadow: 0 10px 26px rgba(10,132,255,.3); }
.sc-b.sms  { background: #34C759; color: #FFF; border-bottom-right-radius: 7px; box-shadow: 0 10px 26px rgba(52,199,89,.3); }
.sc-b.chan { background: #E9E9EB; color: var(--v2-ink); border-bottom-left-radius: 7px; box-shadow: 0 10px 26px rgba(34,32,25,.14); }
.sc-call {
  display: inline-flex; align-items: center; gap: 12px;
  background: #FFFFFF; border: 1.5px solid rgba(34,32,25,.18); color: var(--v2-ink);
  border-radius: 17px; padding: 14px 18px; font-size: 15.5px;
  box-shadow: 0 12px 30px rgba(34,32,25,.16);
  white-space: nowrap;
}
.sc-call .call-dur { color: rgba(34,32,25,.5); }
.sc-tap {
  display: inline-flex; align-items: center; justify-content: center;
  background: #FFFDF7; border: 1.5px solid var(--v2-ink); border-radius: var(--r-pill);
  padding: 9px 14px; font-size: 24px; box-shadow: var(--shadow-hard-sm);
}
.scat-field .fchip { font-size: 16px; padding: 10px 20px; }
.scat-field .logo-chip { position: absolute; font-size: 15px; }
.scat-field .logo-chip img { width: 24px; height: 24px; }
/* depth layers (Extra: sharp mid, blurred small back, big blurred front).
   Layer scale lives in --ls so the assembly spring can animate scale too. */
.l-b { --ls: .85; filter: blur(2.2px); opacity: .62; }
.l-m { --ls: 1; z-index: 1; }
.l-f { --ls: 2.2; filter: blur(6px); opacity: .5; z-index: 3; }
/* spring assembly: items wait small + low, pop to their layer scale
   (Extra parks all 43 stickers at op:0 scale(.8) and springs them in) */
.scit {
  opacity: 0; translate: 0 30px; scale: calc(var(--ls, 1) * .7);
  transition: opacity .55s ease, translate .65s var(--ease-spring), scale .65s var(--ease-spring);
  transition-delay: calc(var(--ci, 0) * 60ms);
}
.seen .scit { translate: 0 0; scale: var(--ls, 1); }
.seen .scit.l-m { opacity: 1; }
.seen .scit.l-b { opacity: .62; }
.seen .scit.l-f { opacity: .55; }
/* the centered copy (brown ink on the marigold room) */
.scat-copy { position: relative; z-index: 2; text-align: center; max-width: 760px; margin: 0 auto; }
.scat-copy h2 { font-size: clamp(30px, 4vw, 54px); color: var(--v2-brown); }
.scat-sub { margin: 20px auto 26px; color: rgba(74,45,0,.85); max-width: 460px; }
.scat-pill {
  display: inline-flex; align-items: center;
  font-family: var(--v2-display); font-weight: 600; font-size: 17px;
  background: #FFFDF7; border: var(--bd); border-radius: var(--r-pill);
  padding: 10px 22px; box-shadow: var(--shadow-hard-sm);
}

/* =========================================================================
   S8 · Integrations — sky room, bordered chips, edge-fade marquee
   ========================================================================= */
.sc-integr {
  margin: 0 var(--room-x); border-radius: var(--r-room);
  background:
    radial-gradient(110% 80% at 50% 0%, rgba(255,255,255,.4), transparent 60%),
    var(--v2-sky);
  color: var(--v2-navy);
  padding: clamp(70px, 10vh, 120px) 0 clamp(60px, 8vh, 90px); text-align: center; overflow: hidden;
}
.sc-integr h2 { font-size: var(--fs-h2); padding: 0 24px; color: var(--v2-navy); }
.integr-sub { margin: 16px auto 48px; color: rgba(27,57,96,.8); }
.integr-sub code {
  background: #FFFDF7; border: 1.5px solid var(--v2-ink); border-radius: 9px;
  padding: 3px 10px; font-family: var(--v2-body); font-weight: 600; font-size: 15px;
  color: var(--v2-ink);
  box-shadow: var(--shadow-hard-sm);
}
.integr-rows {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.logo-row { display: flex; gap: 14px; width: max-content; animation: drift 36s linear infinite; margin-bottom: 16px; }
.logo-row.rev { animation-direction: reverse; }
.logo-row:hover { animation-play-state: paused; }
.logo-chip {
  display: flex; align-items: center; gap: 10px;
  background: #FFFDF7; border: 1.5px solid var(--v2-ink); border-radius: 13px;
  padding: 11px 18px;
  font-weight: 600; font-size: 14px; color: var(--v2-ink);
  box-shadow: var(--shadow-hard-sm);
  transition: transform .15s ease, box-shadow .15s ease;
}
.logo-chip:hover { transform: translateY(2px); box-shadow: 0 0 0 0 var(--v2-ink); }
.logo-chip img { width: 22px; height: 22px; }
@keyframes drift { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* =========================================================================
   S9 · Close — warm night room; the compose bar comes back
   ========================================================================= */
.sc-close {
  position: relative; margin: clamp(60px, 9vh, 110px) var(--room-x) 22px; border-radius: var(--r-room);
  background:
    radial-gradient(820px 460px at 28% 14%, rgba(10,132,255,.16), transparent 60%),
    radial-gradient(700px 520px at 78% 84%, rgba(255,181,0,.12), transparent 62%),
    var(--v2-night);
  color: #F5EFE3; text-align: center;
  padding: clamp(110px, 16vh, 180px) 24px 44px;
  overflow: hidden;
}
.grain::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border-radius: inherit;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: .07; mix-blend-mode: overlay;
}
.sc-close > * { position: relative; z-index: 2; }
.sc-close h2 { font-size: var(--fs-h2); max-width: 720px; margin: 0 auto 36px; }
/* idle starburst (Extra keeps a slow rotate(360) running on its badges) */
.spin-star {
  position: absolute; top: 44px; right: 52px; z-index: 2;
  width: 92px; height: 92px; fill: var(--v2-yellow); opacity: .9;
  animation: spinStar 18s linear infinite;
}
@keyframes spinStar { to { rotate: 360deg; } }
.compose-bar {
  display: inline-flex; align-items: center; gap: 16px;
  background: #FFFDF7; border: var(--bd); border-radius: var(--r-pill);
  box-shadow: var(--shadow-hard);
  padding: 9px 9px 9px 24px;
  text-decoration: none; cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.compose-bar:hover { transform: translateY(2px); box-shadow: 0 1px 0 0 var(--v2-ink); }
.cb-text { font-size: 16px; font-weight: 600; color: var(--v2-ink); }
.send-circle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  background: var(--v2-blue);
}
.send-circle svg { width: 19px; height: 19px; }
.send-circle svg path { stroke: #FFF; stroke-width: 2.8; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.compose-bar.dark {
  background: #2A241C; border-color: rgba(245,239,227,.3);
  box-shadow: 0 3px 0 0 rgba(0,0,0,.55);
}
.compose-bar.dark:hover { box-shadow: 0 1px 0 0 rgba(0,0,0,.55); }
.compose-bar.dark .cb-text { color: rgba(245,239,227,.9); }
.trust { display: flex; gap: 26px; justify-content: center; flex-wrap: wrap; margin-top: 60px; font-size: var(--fs-micro); color: rgba(245,239,227,.55); }
.v2-footer {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px;
  margin-top: 80px; padding-top: 26px; border-top: 1px solid rgba(245,239,227,.15);
  font-size: var(--fs-micro); color: rgba(245,239,227,.6);
}
.v2-footer nav { display: flex; gap: 20px; }
.v2-footer a { text-decoration: none; }
.v2-footer a:hover { color: #FFF; }

/* =========================================================================
   Mobile ≤ 720px
   ========================================================================= */
@media (max-width: 720px) {
  .dev { width: 248px; border-radius: 40px; padding: 6px; }
  .dev-screen { height: 460px; border-radius: 34px; }
  .dev-status { top: 10px; left: 20px; right: 16px; }
  .ds-time { font-size: 11px; }
  .ds-icons { width: 42px; }
  .dev-island { width: 88px; height: 24px; }
  .th-head { padding-top: 48px; }
  .tb { font-size: 13px; }
  .hero-dev-wrap { top: 54px; }
  .hero-sub { max-width: 320px; }

  /* loud scene: trim the field, shrink the cards */
  .sc-loud { height: 280vh; }
  .nz.hm { display: none; }
  .nz-mail, .nz-miss { width: 172px; font-size: 10.5px; }
  .nz-mail b, .nz-miss b { font-size: 11px; }
  .nz-bub { font-size: 12.5px; padding: 9px 12px; max-width: 168px; white-space: normal; }
  .nz-inv, .nz-cal { width: 150px; font-size: 10.5px; }
  .nz-inv b, .nz-cal b { font-size: 11.5px; }
  .nz-badge { width: 46px; height: 46px; border-radius: 12px; }
  .nz-badge img { width: 24px; height: 24px; }
  .nzb-e { font-size: 24px; }
  .nz-badge i { min-width: 19px; height: 19px; font-size: 11px; }
  .nz-stack { width: 150px; height: 88px; }
  .nz-stack > span, .nzs-top { width: 128px; height: 50px; font-size: 11px; padding: 0 10px; }
  .loud-copy h2 { font-size: clamp(23px, 6.6vw, 30px); }
  .loud-thread { width: min(340px, 86vw); min-height: 148px; }
  .lt-b { font-size: 14px; }
  .lt-call { font-size: 13.5px; padding: 11px 14px; }
  .lt-att { padding: 8px 12px; gap: 9px; font-size: 12px; }
  .lt-att b { font-size: 12.5px; }
  .lt-att em { font-size: 11px; }
  .ltm-tile { width: 46px; height: 46px; }
  .ltl-thumb { width: 46px; height: 38px; font-size: 18px; }

  /* compose bridge + mega-room (merged pin) */
  .sc-compose { height: 560vh; }
  .compose-rows { gap: 11px; }
  .cr-label { width: 100%; }
  .compose-row { gap: 10px; }
  .mini-attach { transform: rotate(-1.5deg); }
  .compose-body { min-height: 190px; }
  .compose-body p { font-size: clamp(24px, 6.6vw, 30px); }
  .send-mega { font-size: clamp(26px, 8vw, 34px); padding: 16px 36px; box-shadow: 0 4px 0 0 var(--v2-ink); }
  .send-mega.armed:hover { box-shadow: 0 2px 0 0 var(--v2-ink); }
  .send-mega.fired .sm-circle { translate: 26px -110px; }

  /* the room stacks: headline, stage, rail at the bottom */
  .send-room { flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0; padding: 26px 0 0 20px; }
  .reel-left { width: auto; display: flex; flex-direction: column; padding-right: 20px; }
  .reel-left h2 { font-size: clamp(24px, 6.6vw, 30px); margin-bottom: 14px; }
  .reel-rail { order: 2; }
  .reel-stage { flex: 1; align-self: auto; margin: 8px 0 0; min-height: 0; }
  .feed-row { padding: 9px 6px; font-size: 11.5px; gap: 8px; }
  .feed-e { width: 18px; font-size: 13px; }
  .feed-from { width: 88px; }
  .fchip { font-size: 10px; padding: 4px 9px; }
  .chips-float .fchip { font-size: 13px; }
  .dg-phone { left: 0; right: 0; margin: 0 auto; width: min(330px, 86vw); top: 2vh; height: min(102vh, calc(min(330px, 86vw) * 2.12)); border-radius: 44px; padding: 8px; }
  .dg-phone::before { top: 16px; width: 80px; height: 22px; }
  .digest { inset: 8px; border-radius: 37px; padding: 48px 14px 24px; gap: 7px; }
  .dgb { font-size: 12.5px; max-width: 90%; }
  .dg-head img { width: 36px; height: 36px; }
  .reel-item .ri-cap { max-width: 280px; font-size: 13px; }

  /* carousel: stacks — copy top, phone center, pins bottom; ghosts hide */
  .auto-pin { flex-direction: column; justify-content: center; gap: 18px; padding: 70px 22px 96px; }
  .auto-copy { width: 100%; text-align: center; }
  .auto-copy h2 { font-size: clamp(22px, 6vw, 28px); }
  .auto-h { align-items: center; }
  .auto-sub { margin: 10px auto 0; font-size: 13.5px; }
  .caro { flex: 0 0 auto; margin-right: 0; }
  .ghost { display: none; }
  .caro-dev .dev { width: 258px; }
  .caro-dev .dev-screen { height: min(58vh, 470px); }
  .scr-vp { top: 114px; bottom: 168px; }
  .sb { font-size: 12.5px; }
  .lk { padding: 7px 10px 7px 7px; gap: 8px; }
  .lk-th { width: 34px; height: 34px; font-size: 15px; }
  .lk-g { font-size: 18px; }
  .lk b { font-size: 11px; }
  .lk em { font-size: 9.5px; }
  .kb { padding: 5px 2px 4px; }
  .kk { height: 22px; margin: 1.8px; font-size: 10.5px; border-radius: 4px; }
  .kk-sp, .kk-123, .kk-ret { font-size: 9px; }
  .caro-foot { gap: 5px; padding: 3px 8px 6px; }
  .th-back { left: 10px; top: 56px; }
  .th-back svg { width: 7px; height: 12px; }
  .th-back i { min-width: 17px; height: 15px; font-size: 9.5px; }
  .th-vid { right: 11px; top: 58px; }
  .th-vid svg { width: 19px; height: 13px; }
  .mb-send { width: 20px; height: 20px; }
  .mb-caret { height: 12px; }
  .pins { bottom: 12px; gap: 6px; }
  .pin-face { width: 44px; height: 44px; font-size: 20px; }
  .pin-l { font-size: 9.5px; }
  .pin-bub { font-size: 10px; padding: 5px 8px; bottom: calc(100% + 10px); }

  /* composer scales with the small frames */
  .dev-foot { gap: 6px; padding: 4px 9px 7px; }
  .mb-plus { width: 26px; height: 26px; }
  .mb-plus svg { width: 11px; height: 11px; }
  .mb-field { font-size: 12px; padding: 4px 7px 4px 11px; }
  .mb-mic { width: 13px; height: 13px; }
  .dev-home { width: 92px; height: 4px; }
  .th-msgs { padding-bottom: 64px; }

  /* scatter: trim to the mid/front layers, smaller type */
  .scit.hm { display: none; }
  .sc-b { max-width: 170px; font-size: 13px; padding: 9px 13px; white-space: normal; }
  .sc-e { font-size: 44px !important; }
  .scat-copy h2 { font-size: clamp(26px, 7.4vw, 32px); }
  .l-f { --ls: 1.3; }
  .sc-scat { min-height: 90vh; }
  .spin-star { width: 60px; height: 60px; top: 24px; right: 22px; }

  .trio { grid-template-columns: 1fr; }
  .tcard { min-height: 0; }
  .trust { flex-direction: column; gap: 10px; }
  .v2-footer { justify-content: center; text-align: center; }
}

/* =========================================================================
   Reduced motion — static, equally legible
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  [data-reveal], [data-reveal="l"], [data-reveal="r"] { opacity: 1; transform: none; transition: none; }
  .tb { animation: none; opacity: 1; transform: none; }
  .tb .tap { animation: none; transform: scale(1); }
  .tb-typing span { animation: none; opacity: .6; }
  .compose-row { opacity: 1; transform: none; transition: none; }
  .caret { animation: none; opacity: 0; }
  .send-mega { opacity: 1; transform: none; filter: none; transition: none; }
  .send-mega.armed::after, .send-mega::after { animation: none; opacity: 0; }
  .feed-row, .feed-e, .feed-row .fchip { transition: none; }
  .chips-float .fchip { transition: none; }
  /* merged compose+room pin unrolls into two static blocks: the typed
     manifesto first, then the OPEN room with the digest phone (ex is
     forced to 1 and the scene index to 2 in the component) */
  .sc-compose { height: auto; }
  .compose-pin { position: static; height: auto; overflow: visible; flex-direction: column; align-items: stretch; }
  .compose-in { order: 1; padding-bottom: 60px; }
  .send-room { position: relative; inset: auto; order: 2; height: auto; min-height: 100svh; }
  .send-room::after { transition: none; }
  .send-mega .sm-circle { transition: none; }
  .send-room .reel-left { transition: none; }
  .dg-phone { transition: none; opacity: 1; transform: none; }
  .dgb, .dgb .tap { transition: none; opacity: 1; transform: none; }
  .st-2 .dgb .tap { transform: scale(1); }
  .scr-track { transition: none; }
  .scr { transition: none; opacity: 1; }
  .ghost { animation: none; }
  .logo-row { animation: none; }
  .word-hl .wp-txt, .word-pill .wp-txt { animation: none; }
  .word-hl, .word-pill { transition: none; }
  .reel-item .ri-cap { transition: none; }
  .dev.glint .dev-screen::after { animation: none; }
  .rail-dot { transition: none; }
  .pin-it, .pin-face, .pin-dot { transition: none; }
  .pin-bub { animation: none; }
  .auto-sub { animation: none; }
  /* live tail renders complete and still */
  .sb.pop, .lk.pop, .sb .tap.tp, .mb-send { animation: none; }
  .mb-caret { animation: none; opacity: 0; }
  .sb-typing span { animation: none; opacity: .6; }
  /* texted-in cascades land instantly, fully visible */
  .scr.on .hb { animation: none; }
  .trio.seen .tc-bubbles .mb { animation: none; }
  .loud-thread.in .lt-set.on .lt-call,
  .loud-thread.in .lt-set.on .lt-att,
  .loud-thread.in .lt-set.on .lt-b { animation: none; }
  .dgb { transition: none; }
  .fz { display: none; }
  .scit { transition: none; translate: 0 0; transform: none; opacity: 1; scale: var(--ls, 1); }
  .scit.l-b, .scit.l-f { opacity: .55; }
  .cta, .tcard, .logo-chip, .compose-bar { transition: none; }
  /* loud scene: static end-state composite (REDUCE initial p = .9 puts
     rotation set 3 on stage) */
  .nz { transition: none; transform: none; }
  .lt-set, .lt-dots, .lt-dots i { transition: none; }
  .lh-fly { display: none; }
  .lt-b .tap { transition: none; }
  .loud-thread.in .lt-set.on .tap { transform: scale(1); }
  .loud-field { transition: none; }
  /* masked rises + entrances land instantly */
  .rise .rise-in { transition: none; translate: 0 0; }
  .spin-star { animation: none; }
  .trio[data-reveal] .tcard { opacity: 1; translate: 0 0; scale: 1; }
  .caro:not(.seen) .ghost { opacity: .6; translate: 0 0; }
  .caro:not(.seen) .ghost-dim { opacity: .3; }
  .ghost { transition: none; }
  .pins:not(.seen) .pin-it { opacity: 1; translate: 0 0; }
  .ph-fly { display: none; }
  :where(.sc-loud.seen) .nz.n0 { transition: none; }
}
