/* ============================================================================
   exotic — the story of your account · css/app/story.css
   ----------------------------------------------------------------------------
   Activity IS the story now. In-app, two columns: the ledger rail on the
   left (every event a commit dot — the table of contents), the story on
   the right — a sticky STAGE the visuals play on, and the script flowing
   beneath it as a scrollable document. Scroll to skim (everything is
   readable at rest); press play to be told it (words stream, the stage
   steps, the page follows); ask anything from the composer that the top
   search bar morphs into. Components live in css/kit/story-kit.css.

   ─────────────────────────────────────────────────────────
   ENTRANCE STORYBOARD (ms after load, page motion system first)
      0ms  meridian + chrome         (css/kit/motion.css, unchanged)
    350ms  search pill detaches      fixed clone glides top → bottom
                                     680ms ease-emph, label crossfades to
                                     "Ask about your story…"
    380ms  rail + beats rise         (page .mo rise, unchanged)
   1030ms  clone lands, real composer takes over (opacity swap)
    ---- scrub: stage swaps as beats cross the reading line ----
    ---- play: page auto-scrolls beat to the line · words stream ----
   ───────────────────────────────────────────────────────── */

/* ============================ page head ============================ */
/* (play lives in the composer as .th-playic — no page-level CTA) */

/* ============================ the story grid ============================ */
/* the rail carries the unexpanded ledger, so it earns real width; the
   script column caps at its measure anyway — give the slack to the left,
   and center what remains so no dead margin pools on one side */
.story{ display:grid; grid-template-columns:clamp(320px, 36vw, 520px) minmax(0,1fr);
  gap:36px; align-items:start; }
.st-beats, .st-ask{ margin-inline:auto; width:100%; }

/* -- ledger rail: the table of contents -- */
.st-rail{ position:sticky; top:14px; max-height:calc(100svh - 28px);
  display:flex; flex-direction:column; min-height:0;
  border-right:1px solid var(--hairline); padding-right:18px; }
.st-rail-h{ padding:4px 8px 8px; font-family:var(--font-num); font-size:10px;
  text-transform:uppercase; letter-spacing:.08em; color:var(--muted); flex:0 0 auto; }
/* find-what-you're-looking-for: bucket filters, scoped to the rail */
.st-filters{ display:flex; gap:6px; flex-wrap:wrap; padding:0 8px 12px; flex:0 0 auto; }
.st-filters button{ font-family:var(--font-num); font-size:9.5px; letter-spacing:.05em;
  text-transform:uppercase; color:var(--muted); background:none;
  border:1px solid transparent; border-radius:var(--rad-pill); padding:5px 11px;
  cursor:pointer; transition:color var(--t1), background var(--t1), border-color var(--t1); }
.st-filters button:hover{ color:var(--ink); }
.st-filters button.on{ color:var(--ink); background:var(--card);
  border-color:var(--hairline-2); box-shadow:var(--crisp); }
.st-rail-l{ flex:1; min-height:0; overflow-y:auto; scrollbar-width:thin; }
.st-raw{ flex:0 0 auto; margin:10px 8px 2px; font-family:var(--font-num); font-size:11px;
  color:var(--muted); text-decoration:none; transition:color var(--t1); }
.st-raw:hover{ color:var(--ink); }

/* ============================ story column ============================ */
.st-col{ min-width:0; position:relative; }

/* -- chapter progress: one slim sticky line; the page scrolls under it -- */
.st-prog{ position:sticky; top:0; z-index:8; background:var(--bg);
  padding:12px 0 8px; max-width:640px; margin-inline:auto; width:100%; }

/* -- figures live IN the text, on the page (no viewport pinning): the
   scroll that moves the words also winds each render forward and back.
   Rhythm: fig → 22px → its beats (18px apart) → 44px → the next group -- */
.st-group{ position:relative; margin-bottom:44px; }
.st-group:last-child{ margin-bottom:0; }
.st-fig{ padding:10px 0 12px; margin:0 0 22px; }
.st-fig .ths{ position:relative; inset:auto; overflow:visible; }
/* inline scale discipline — figures share the page with prose, so the
   hero sizes of the old full-height stage step down a notch here */
.st-fig .ths-big .v{ font-size:clamp(38px,5.5vw,62px); }
.st-fig .ths-big .c{ margin-top:9px; }
.st-fig .ths-rows .rw{ padding:8px 12px; margin:2px auto; }
.st-fig .ths-rows .cap{ margin-top:8px; }
.st-fig .ths-path .plot{ height:min(220px,30vh); }
.st-fig .ths-duo .cell{ min-height:118px; padding:16px; }

/* -- the script: every beat readable at rest -- */
.st-beats{ position:relative; z-index:1; padding:10px 4px 40vh; max-width:640px; }
.st-chh{ margin:64px 0 22px; display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; }
.st-ch:first-child .st-chh{ margin-top:6px; }
.st-chh .k{ font-family:var(--font-num); font-size:10.5px; text-transform:uppercase;
  letter-spacing:.12em; color:var(--muted); flex:0 0 100%; }
.st-chh h2{ font-family:var(--font-display); font-size:24px; font-weight:600;
  letter-spacing:-0.015em; color:var(--ink); margin:2px 0 0; line-height:1.1; }
.st-narr{ border:1px solid var(--hairline-2); background:var(--surface); cursor:pointer;
  font-family:var(--font-num); font-size:10px; letter-spacing:.05em; text-transform:uppercase;
  color:var(--muted); border-radius:var(--rad-pill); padding:5px 12px;
  transition:color var(--t1), border-color var(--t1), transform .15s var(--ease-out); }
.st-narr:hover{ color:var(--ink); border-color:var(--hairline); }
.st-narr:active{ transform:scale(.96); }
.st-beat{ margin:0 0 18px; max-width:62ch; cursor:default; }
.st-group .st-beat:last-child{ margin-bottom:0; }   /* the group gap carries it */
/* reading emphasis: the beat at the line carries full ink */
.st-beat{ opacity:.52; transition:opacity .35s ease; }
.st-beat.cur{ opacity:1; }
.st-beat.done{ opacity:.72; }
/* at rest the words are simply there; only a narrating beat streams */
.st-beat .w{ opacity:1; filter:none; transition:none; }
.st-beat.narr .w{ opacity:0; filter:blur(4px); transition:opacity .24s ease, filter .3s ease; }
.st-beat.narr .w.on{ opacity:1; filter:blur(0); }

/* -- the end of the story -- */
.st-end{ display:flex; gap:8px; flex-wrap:wrap; margin-top:26px; }

/* ============================ the composer ============================ */
/* sticky at the viewport's bottom edge, aligned to the column by flow */
.st-ask{ position:sticky; bottom:0; z-index:7; max-width:640px; margin-top:10px;
  padding:26px 0 14px;
  /* the script fades out under the talk row instead of colliding with it */
  background:linear-gradient(180deg, transparent, var(--bg) 40%); }
.st-ask .th-chips{ padding:4px 2px 8px; }
.st-ask .th-form{ background:color-mix(in oklab,var(--card) 86%,transparent);
  -webkit-backdrop-filter:blur(18px) saturate(1.25); backdrop-filter:blur(18px) saturate(1.25); }
/* during the entrance morph the real composer holds its breath */
.st-ask.pre .th-form{ opacity:0; }

/* -- an answer, printed into the paper at the reading position: scroll
   past it like any paragraph — no dismissal, the story keeps your notes -- */
.st-qa{ margin:8px 0 22px; padding:14px 16px 16px; background:var(--card);
  border:1px solid var(--hairline); border-radius:var(--rad-3); box-shadow:var(--crisp);
  display:flex; flex-direction:column; gap:10px;
  opacity:0; transform:translateY(10px);
  transition:opacity .32s var(--ease-out), transform .32s var(--ease-emph); }
.st-qa.on{ opacity:1; transform:none; }
.st-qa .th-line{ font-size:15.5px; }
/* a note can carry its own figure — self-contained in the paper */
.st-qa .ths{ position:relative; inset:auto; overflow:visible; margin:2px 0 4px; }
.st-qa .ths-rows{ max-height:280px; overflow-y:auto; }

/* the search pill that travels: a fixed clone, pill throughout */
.st-morph{ position:fixed; z-index:80; display:flex; align-items:center; gap:11px;
  background:var(--card); border:1px solid var(--hairline); border-radius:var(--rad-pill);
  box-shadow:var(--elev-2); padding:0 18px; color:var(--muted); overflow:hidden;
  font-family:var(--font-display); font-size:13.5px; white-space:nowrap;
  transition:transform .68s var(--ease-emph),opacity .3s var(--ease);will-change:transform; }
.st-morph .gl{ font-size:15px; color:var(--ink-2); flex:0 0 auto; }
.st-morph .a, .st-morph .b{ transition:opacity .3s ease; }
.st-morph .b{ position:absolute; left:44px; opacity:0; }
.st-morph.go .a{ opacity:0; } .st-morph.go .b{ opacity:1; }

/* ============================ the reading thread ============================ */
/* how far in, how much is left — one quiet line at the page's right edge;
   ticks mark chapters; the fill is the meridian, as light */
.st-thread{ position:fixed; right:14px; top:50%; transform:translateY(-50%);
  width:2px; height:min(52vh,440px); border-radius:1px; z-index:60;
  background:color-mix(in oklab,var(--ink) 10%,transparent); cursor:pointer; }
.st-thread::before{ content:""; position:absolute; inset:-8px -10px; }  /* hit area */
.st-thread .f{ position:absolute; inset:0; border-radius:1px; transform-origin:top;
  transform:scaleY(0); background:linear-gradient(180deg,var(--g2),var(--g3),var(--g4));
  transition:transform .15s linear; }
.st-thread .tk{ position:absolute; left:-2.5px; width:7px; height:1.5px; border-radius:1px;
  background:var(--muted); opacity:.45; pointer-events:none; }
@media (max-width:640px){
  .st-thread{ right:7px; height:34vh; }
}
@media (prefers-reduced-motion:reduce){ .st-thread .f{ transition:none; } }

/* ============================ classic ledger mode ============================ */
.act-classic{ display:flex; flex-direction:column; gap:16px; }
.act-back{ align-self:flex-start; font-family:var(--font-num); font-size:11px;
  color:var(--muted); text-decoration:none; }
.act-back:hover{ color:var(--ink); }
body.act-ledger .story, body.act-ledger .st-ask{ display:none; }

/* ============================ playing state ============================ */
body.st-playing{ scroll-behavior:auto; }   /* the engine drives; no double-smooth */
body.st-playing .st-beats{ cursor:pointer; }  /* tap = skip */

/* ============================ phone ============================ */
@media (max-width:900px){
  .story{ grid-template-columns:1fr; gap:0; }
  .st-rail{ display:none; }
}
@media (max-width:640px){
  /* the slim progress owns the top strip when the app bar hides on scroll */
  .st-prog{ padding-top:calc(env(safe-area-inset-top, 0px) + 10px); }
  .st-beats{ padding:12px 2px 34vh; }
  .st-chh{ margin:42px 0 14px; }
  .st-chh h2{ font-size:21px; }
  .st-beat{ margin-bottom:16px; }
  /* the composer floats above the dock — the talk bar and the nav share
     the bottom shelf, talk on top */
  .st-ask{ bottom:calc(var(--ap-dock-h, 66px) + var(--ap-dock-b, 12px) + 10px); }
  /* and the script fades out before it reaches the dock: a fixed wash
     fills the strip below the composer (under the dock's z, over text) */
  .st-ask::after{ content:""; position:fixed; left:0; right:0; bottom:0; z-index:-1;
    height:calc(var(--ap-dock-h, 66px) + var(--ap-dock-b, 12px) + 46px);
    background:linear-gradient(0deg, var(--bg) 72%, transparent); pointer-events:none; }
  .st-ask .th-form input{ font-size:16px; }   /* iOS: <16px zooms on focus */
  .st-narr{ min-height:34px; }
  .th-playic, .th-send{ flex-basis:42px; height:42px; }
}

/* ============================ reduced motion ============================ */
@media (prefers-reduced-motion:reduce){
  .st-morph{ display:none !important; }
  .st-ask.pre .th-form{ opacity:1; }
  .st-beat{ transition:none; }
  .st-qa{ transition:opacity .2s ease; transform:none; }
}
