/* The storyboard intro: full-screen rows of comic panels that wipe in one
   after another as you scroll. Text sizes use container units of the row
   (cqw), clamped so they read on a phone and stay calm on a wide screen. */
/* Colours, type and motion come from tokens.css (linked first); the old local names
   are kept as aliases so the rules below read as before. --cloud stays local: it is
   the light red used for text on ink, which the token set has no colour for. */
:root {
  --dawn-sky: var(--c-paper); --skyline: var(--c-ink); --sun-red: var(--c-art); --cloud: #F08A6A; --concrete: var(--c-muted); --ember: var(--c-art);
  --chrome: 64px; --gutter: 24px; --gap: 10px; --line: 3px;
}
@media (min-width: 900px) { :root { --chrome: 76px; --gutter: 40px; --gap: 14px; } }
*, *::before, *::after { box-sizing: border-box; }
html { background: var(--dawn-sky); }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
body { margin: 0; background: var(--dawn-sky); color: var(--skyline); font-family: var(--f-body); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
/* film grain: one fixed layer, a tile larger than the screen on every side, jumped
   between three offsets 8 times a second by a stepped transform (compositor only) */
body::after { content: ""; position: fixed; inset: -220px; z-index: 40; pointer-events: none; opacity: .5; mix-blend-mode: multiply; will-change: transform; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .32 0 0 0 0 .28 0 0 0 0 .24 0 0 0 .14 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
@keyframes grain { 0% { transform: translate3d(0, 0, 0); } 33.333% { transform: translate3d(73px, 131px, 0); } 66.667% { transform: translate3d(146px, 42px, 0); } }
@media (prefers-reduced-motion: no-preference) { body::after { animation: grain .375s steps(1, end) infinite; } }
::selection { background: var(--sun-red); color: var(--c-on-art); }
:focus-visible { outline: 3px solid var(--ember); outline-offset: 3px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.sr-only:focus { position: fixed; z-index: 60; width: auto; height: auto; clip: auto; left: var(--gutter); top: 12px; background: var(--skyline); color: var(--dawn-sky); padding: 8px 12px; font: 500 12px var(--f-mono); letter-spacing: .08em; text-transform: uppercase; }

/* chrome */
.chrome { position: fixed; z-index: 30; top: 0; left: 0; right: 0; height: var(--chrome); display: flex; justify-content: space-between; align-items: center; padding: 0 var(--gutter); pointer-events: none; }
.chrome > * { pointer-events: auto; }
.chrome .brand { font: 400 20px/1 var(--f-display); letter-spacing: .02em; text-transform: uppercase; color: var(--skyline); text-decoration: none; }
.skip { font: 500 12px var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--skyline); text-decoration: none; border-bottom: 2px solid var(--skyline); padding-bottom: 2px; transition: opacity var(--dur-hover) var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .skip:hover { opacity: .7; } }
.welcome { position: fixed; z-index: 31; top: 0; left: 0; right: 0; transform: translateY(-100%); transition: transform var(--dur-modal) var(--ease-drawer); background: var(--skyline); color: var(--dawn-sky); text-align: center; padding: 10px 56px 10px 16px; font: 500 12px/1.4 var(--f-mono); letter-spacing: .06em; }
.welcome.is-on { transform: none; }
.welcome a { color: var(--cloud); }
.welcome button { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 32px; height: 32px; border: 0; background: none; color: var(--dawn-sky); font-size: 18px; cursor: pointer; transition: transform var(--dur-press) var(--ease-out); }
.welcome button:active { transform: translateY(-50%) scale(.97); }
.chapter { position: fixed; z-index: 30; left: var(--gutter); bottom: 22px; display: flex; align-items: center; gap: 12px; font: 500 12px var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--concrete); pointer-events: none; }
.chapter i { display: block; width: 72px; height: 3px; background: rgba(22, 20, 19, .16); position: relative; overflow: hidden; }
.chapter i b { position: absolute; left: 0; top: 0; height: 100%; width: 100%; background: var(--sun-red); transform: scaleX(0); transform-origin: left; transition: transform .5s var(--ease-out); }
.rose-corner { position: fixed; z-index: 30; right: var(--gutter); bottom: 18px; width: 42px; height: 42px; border: var(--line) solid var(--skyline); background: var(--dawn-sky); display: grid; place-items: center; opacity: 0; transform: translateY(12px); transition: opacity .4s var(--ease-out), transform .6s var(--ease-out); }
.rose-corner.is-on { opacity: 1; transform: none; }
.rose-corner svg { width: 24px; height: 24px; }

/* the stage: one pinned screen; rows stack inside it */
.stage { position: relative; }
.pin { position: relative; height: 100vh; height: 100dvh; overflow: hidden; }
.row { position: absolute; inset: 0; padding: var(--chrome) var(--gutter) calc(var(--gutter) + 8px); container-type: inline-size; display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--gap); clip-path: inset(100% 0 0 0); background: var(--dawn-sky); visibility: hidden; will-change: clip-path; }
.row.is-on { visibility: visible; }
/* The last scene fills the whole screen with no frame, so when the pin lets go it slides up and the inked ground of
   the descent rises straight out of its bottom edge: one continuous drop into the town. */
.row--bleed { padding: 0; gap: 0; }
.row--bleed .panel { grid-column: 1 / -1; grid-row: 1 / -1; border: 0; }
.row--bleed .panel .n { display: none; }
.row--bleed .t.dialogue { margin-top: var(--chrome); }
.row--bleed .t.hint { margin-bottom: 34px; }
.panel { position: relative; overflow: hidden; margin: 0; border: var(--line) solid var(--skyline); background: var(--c-biz-tint); clip-path: inset(0 100% 0 0); min-height: 0; }
.panel.is-in { clip-path: inset(0 0 0 0); transition: clip-path .7s var(--ease-out); }
.panel .art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--pos, 50% 50%); transform: scale(var(--zoom, 1)); transform-origin: var(--pos, 50% 50%); will-change: transform; }
.panel .art.col { filter: none; clip-path: circle(0% at var(--cx) var(--cy)); }
.panel.full .art { filter: none; }   /* a panel that is in colour from the start */
.panel.is-in .art.col { clip-path: circle(var(--r) at var(--cx) var(--cy)); transition: clip-path .8s var(--ease-out) .15s; }
.panel.pulse.is-in .art.col { animation: pulse 1.1s var(--ease-out) .35s 1; }
@keyframes pulse { 0% { clip-path: circle(var(--r) at var(--cx) var(--cy)); } 45% { clip-path: circle(calc(var(--r) * 1.6) at var(--cx) var(--cy)); } 100% { clip-path: circle(var(--r) at var(--cx) var(--cy)); } }
.panel .n { position: absolute; z-index: 3; left: 0; top: 0; padding: 4px 8px 3px; background: var(--skyline); color: var(--dawn-sky); font: 500 clamp(12px, 1cqw, 13px) var(--f-mono); letter-spacing: .1em; }
.panel .strip { position: absolute; z-index: 2; left: 0; right: 0; overflow: hidden; border-top: var(--line) solid var(--skyline); border-bottom: var(--line) solid var(--skyline); clip-path: inset(0 100% 0 0); }
.panel .strip img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--pos); transform: scale(var(--zoom)); transform-origin: var(--pos); }
.panel.is-text .strip { clip-path: inset(0 0 0 0); transition: clip-path .9s var(--ease-out) .1s; }

/* text layers: placed by x/y in % of the panel; anchors flip past the middle.
   Entrances: opacity + 12px rise, one easing, no bounce. */
.t { position: absolute; z-index: 4; max-width: min(70%, 640px); opacity: 0; --dx: 0; --dy: 0; transform: translate(var(--dx), calc(var(--dy) + 12px)); transition: opacity .35s var(--ease-out), transform .6s var(--ease-out); }
.t.is-on { opacity: 1; transform: translate(var(--dx), var(--dy)); }
.t.right { --dx: -100%; } .t.bottom { --dy: -100%; } .t.center { --dx: -50%; }
.system { background: var(--skyline); color: var(--dawn-sky); border: var(--line) solid var(--skyline); padding: .8em 1.1em; font: 500 clamp(12px, 1.3cqw, 17px)/1.55 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; }
.system .k, .system .o { color: var(--cloud); }
.system .em, .dialogue .em { font-weight: 600; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .2em; }
.cur { display: inline-block; width: .6em; height: 1.05em; background: currentColor; vertical-align: -.18em; margin-left: .12em; animation: blink 1s steps(1) infinite; }
.t.is-done .cur { animation: none; opacity: 0; }
@keyframes blink { 50% { opacity: 0; } }
.dialogue { width: min(60%, 640px); background: var(--dawn-sky); border: var(--line) solid var(--skyline); padding: 1.3em 1.2em 1em; font-size: clamp(16px, 1.9cqw, 26px); }
.dialogue .tag { position: absolute; left: calc(var(--line) * -1); top: -1.1em; background: var(--sun-red); color: var(--c-on-art); border: var(--line) solid var(--skyline); padding: .35em .8em .25em; font: 500 clamp(12px, .95cqw, 13px) var(--f-mono); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; max-width: calc(100% + var(--line) * 2); overflow: hidden; text-overflow: ellipsis; }
.dialogue p { margin: 0; font: 400 1em/1.4 var(--f-body); letter-spacing: -.005em; min-height: 1.4em; white-space: pre-line; }
.toast { display: flex; align-items: center; gap: .7em; background: var(--skyline); color: var(--dawn-sky); border: var(--line) solid var(--skyline); padding: .6em 1.1em .6em .6em; font: 500 clamp(12px, 1.15cqw, 14px) var(--f-mono); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; max-width: none; }
.toast i { width: 2.2em; height: 2.2em; background: var(--dawn-sky); display: grid; place-items: center; }
.toast svg { width: 1.5em; height: 1.5em; }
.quest { width: min(44%, 420px); max-width: none; background: var(--dawn-sky); border: var(--line) solid var(--skyline); padding: 1.2em 1.6em 1.6em; font: 500 clamp(12px, 1.2cqw, 15px)/1.9 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; }
.quest::before, .quest::after { content: ""; position: absolute; left: calc(var(--line) * -1); right: calc(var(--line) * -1); height: 1.1em; background: var(--skyline); }
.quest::before { top: -1.1em; border-radius: .55em .55em 0 0; } .quest::after { bottom: -1.1em; border-radius: 0 0 .55em .55em; }
.quest h4 { margin: 0 0 .4em; font: 400 2.2em/1 var(--f-display); letter-spacing: .02em; }
.quest .f { opacity: 0; transform: translateX(-.6em); transition: opacity .3s var(--ease-out), transform .45s var(--ease-out); }
.quest .f.is-on { opacity: 1; transform: none; }
.quest .f b { display: inline-block; min-width: 8.4em; color: var(--concrete); font-weight: 500; }
.quest .f.red span { color: var(--ember); }
/* the scroll cue sits on its own paper plate so it reads over busy art; the arrow bobs under the words */
.hint { max-width: none; display: grid; justify-items: center; gap: .45em; padding: .8em 1.4em .55em; background: var(--dawn-sky); border: var(--line) solid var(--skyline); color: var(--skyline); font: 500 clamp(12px, 1.1cqw, 13px) var(--f-mono); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
.hint svg { width: 1.7em; height: 1.7em; animation: cue 1.6s var(--ease-out) infinite; }
@keyframes cue { 0% { transform: translateY(-.3em); opacity: 0; } 40% { opacity: 1; } 100% { transform: translateY(.6em); opacity: 0; } }
.stamp { max-width: none; font: 400 clamp(44px, 8cqw, 140px)/1 var(--f-display); letter-spacing: .02em; text-transform: uppercase; color: var(--sun-red); -webkit-text-stroke: .035em var(--skyline); paint-order: stroke fill; white-space: nowrap; padding: .12em .22em; border: .05em solid var(--skyline); rotate: -7deg; }
.t.stamp { transform: translate(var(--dx), var(--dy)) scale(1.35); } .t.stamp.is-on { transform: translate(var(--dx), var(--dy)) scale(1); transition: opacity var(--dur-hover) var(--ease-out), transform .5s var(--ease-out); }

/* the choice */
.panel.choice { background: var(--dawn-sky); }
.panel.choice .art { opacity: 1; }   /* the choice panel shows its art in full (Figma, 13 Nov) */
/* choice panel: speech box and buttons form one left-aligned stack, 14px apart, anchored bottom left */
.panel.choice { --stack-x: 3%; --stack-y: 5%; --stack-gap: 14px; }
.panel.choice .t.dialogue { left: var(--stack-x) !important; top: auto !important; bottom: calc(var(--stack-y) + var(--choices-h, 4.5em) + var(--stack-gap)); --dx: 0; --dy: 0; }
.choices { position: absolute; z-index: 4; left: var(--stack-x, 3%); bottom: var(--stack-y, 5%); display: flex; gap: 14px; flex-wrap: wrap; opacity: 0; transform: translateY(12px); transition: opacity .35s var(--ease-out), transform .6s var(--ease-out); }
.choices.is-on { opacity: 1; transform: none; }
/* The last panel's two buttons are the landing page's wood boards: same font, same colour for both, and they only
   turn sun red under a mouse pointer, keyboard focus, or once chosen. The play tip steps forward on hover. */
.btn { position: relative; display: inline-flex; align-items: center; justify-content: space-between; gap: 14px; padding: .55em .8em .55em 1em; font: 400 clamp(18px, 2.1cqw, 28px)/1 var(--f-display); letter-spacing: .02em; text-transform: uppercase; text-align: left; border: var(--line) solid var(--skyline); color: var(--skyline); background: #DDD5C3; cursor: pointer; transition: transform var(--dur-press) var(--ease-out), background-color var(--dur-hover) var(--ease-out), color var(--dur-hover) var(--ease-out); }
.btn.primary, .btn.secondary { background: #DDD5C3; color: var(--skyline); }
.btn .mk { flex: none; display: block; width: .55em; height: .62em; transition: transform var(--dur-hover) var(--ease-out); }
.btn .mk svg { display: block; width: 100%; height: 100%; }
.btn:focus-visible, .btn.is-active { background: var(--sun-red); color: var(--c-on-art); }
.btn:focus-visible { outline-offset: 4px; }
.btn:focus-visible .mk, .btn.is-active .mk { transform: translateX(4px); }
@media (hover: hover) and (pointer: fine) { .btn:not([disabled]):hover { background: var(--sun-red); color: var(--c-on-art); } .btn:not([disabled]):hover .mk { transform: translateX(4px); } }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .5; cursor: default; transform: none; } .btn.is-active[disabled] { opacity: 1; }
.gate-note { position: absolute; z-index: 4; right: 3%; bottom: 5%; padding: .5em .8em; background: var(--dawn-sky); border: var(--line) solid var(--skyline); font: 500 12px var(--f-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--concrete); opacity: 0; transition: opacity .4s var(--ease-out); }
.gate-note.is-on { opacity: 1; }
.gate-note { display: none; }   /* not in the 13 Nov layout; the two buttons speak for themselves */

/* texture motion (texture.js sets data-boil on the pin, --mx/--my; the grain is a CSS animation above).
   Ink boil: two pre-warped copies of each panel sit over the original and are
   shown in turn. The art is scaled up 4% so the cursor drift never shows a
   panel edge (!important because GSAP writes inline scale/translate: none);
   inset panels sit "closer" and travel further than the wide ones. */
.panel .art.boil { opacity: 0; }
.pin[data-boil="1"] .panel .art.f1, .pin[data-boil="2"] .panel .art.f2 { opacity: 1; }
.has-texture .panel .art { --d: 5; scale: 1.04 !important; translate: calc(var(--mx, 0) * var(--d) * -1px) calc(var(--my, 0) * var(--d) * -1px) !important; }
.has-texture .panel.main .art, .has-texture .row:not(.sub-2):not(.cols-3) .panel .art { --d: 3; }

/* looping video layers: hidden until playing, so the still (and its ink boil) shows first */
.panel .art.vid { opacity: 0; transition: opacity .5s var(--ease-out); }
.panel .art.vid.is-playing { opacity: 1; }
.panel.choice .art.vid.is-playing { opacity: 1; }
.panel:has(.art.col.vid.is-playing) .art.col:not(.vid) { opacity: 0; }
.panel.is-in .art.col.vid.is-tracking { transition: opacity .5s var(--ease-out); }

/* arriving from the entry: the red that filled the screen there wipes up to reveal the first row */
.portal-in { position: fixed; z-index: 50; inset: 0; background: var(--sun-red); pointer-events: none; clip-path: inset(0 0 0 0); }
.portal-in.is-out { clip-path: inset(0 0 100% 0); transition: clip-path .9s var(--ease-out); }

/* end */
/* the descent: 1 screen of travel after the last row. A strip of inked ground and then black
   slides up under the row; when the black fills the screen the page hands over to the town. */
.descent { position: relative; height: 200vh; height: 200dvh; background: var(--dawn-sky); }
.descent.is-short { height: 1px; overflow: hidden; } .descent.is-short .descent__pin { display: none; }
/* the fade to black at the end of the comic, above everything including the header and the motion button */
.fade-out { position: fixed; inset: 0; z-index: 100; background: #121214; opacity: 0; pointer-events: none; }
.descent__pin { position: sticky; top: 0; height: 100vh; height: 100dvh; overflow: hidden; }
.descent__strip { position: absolute; left: 0; right: 0; top: 0; height: 200vh; will-change: transform; }
.descent__ground { position: absolute; left: 0; right: 0; top: 0; height: 30%; background: var(--dawn-sky) repeating-linear-gradient(90deg, var(--skyline) 0 2px, transparent 2px 6px); clip-path: polygon(0 3%, 3% 1%, 7% 4%, 11% 0, 15% 3%, 19% 1%, 24% 4%, 28% 0, 33% 3%, 37% 1%, 41% 4%, 46% 0, 50% 3%, 55% 1%, 59% 4%, 63% 0, 68% 3%, 72% 1%, 77% 4%, 81% 0, 86% 3%, 90% 1%, 95% 4%, 100% 1%, 100% 100%, 0 100%); transform-origin: 50% 0; }
.descent__ground::after { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(180deg, transparent 0 18px, rgba(230, 224, 212, .85) 18px 22px); opacity: var(--streak, 0); }
.descent__void { position: absolute; left: 0; right: 0; top: 27%; height: 75%; background: var(--skyline); clip-path: polygon(0 3%, 4% 0, 9% 4%, 14% 1%, 20% 4%, 26% 0, 31% 3%, 37% 1%, 43% 4%, 49% 0, 55% 3%, 61% 1%, 67% 4%, 73% 0, 79% 3%, 85% 1%, 91% 4%, 96% 0, 100% 3%, 100% 100%, 0 100%); }
/* the chrome goes with the light */
html.is-descending .chrome, html.is-descending .chapter, html.is-descending .rose-corner { opacity: 0; transition: opacity .4s var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .descent { height: 40vh; } .descent__pin { height: 40vh; } .descent__strip { display: none; } }

/* phones: three-across rows restack so each panel stays readable */
@media (max-width: 599px) {
  .row { gap: 8px; }
  .row.cols-3 { grid-template-columns: 1fr 1fr; grid-template-rows: 1.4fr 1fr; }
  .row.cols-3 .panel:first-child { grid-column: 1 / -1 !important; }
  .row.cols-3 .panel:not(:first-child) { grid-column: auto !important; }
  .row.sub-2 { grid-template-columns: 1fr 1fr; grid-template-rows: 1.6fr 1fr !important; }
  .row.sub-2 .panel.main { grid-column: 1 / -1 !important; grid-row: 1 !important; }
  .row.sub-2 .panel:not(.main) { grid-column: auto !important; grid-row: 2 !important; }
  .row.cols-2 { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr; }
  .row.cols-2 .panel { grid-column: 1 / -1 !important; }
  .dialogue { width: 86%; } .quest { width: 68%; } .t { max-width: 88%; }
  .choices { gap: 10px; flex-direction: column; align-items: stretch; }   /* stacked buttons share one width */
  .chapter { bottom: max(9px, env(safe-area-inset-bottom)); }   /* sits under the row, not over its border */
}

/* reduced motion: a plain stacked comic, everything already visible */
@media (prefers-reduced-motion: reduce) {
  .pin { height: auto; overflow: visible; }
  .row { position: relative; inset: auto; min-height: 100vh; clip-path: none !important; visibility: visible !important; padding-bottom: var(--gutter); transform: none !important; opacity: 1 !important; }
  .panel, .panel .strip, .panel .art.col { clip-path: none !important; transition: none !important; animation: none !important; }
  .t, .choices, .quest .f { opacity: 1 !important; transition: none !important; }
  .t { transform: translate(var(--dx), var(--dy)) !important; }
  .cur, .hint svg { animation: none !important; }
  .chapter { display: none; }
  /* keep the short fades that explain what changed; movement is not transitioned */
  *, *::before, *::after { transition-property: opacity, color, background-color, border-color !important; transition-duration: 150ms !important; transition-delay: 0s !important; transition-timing-function: var(--ease-out) !important; }
  .welcome { transform: none; opacity: 0; visibility: hidden; transition-property: opacity, visibility !important; }
  .welcome.is-on { opacity: 1; visibility: visible; }
  .rose-corner { transform: none; }
}

/* Wide scenes shown whole (chosen 12 Nov, "version 3"): on landscape screens a wide panel takes the art's own
   shape and sits centred in the row, instead of being cropped and enlarged to fill the screen height.
   A two-level row puts its wide panel on top and its close-ups side by side underneath, each at its own shape. */
@media (min-width: 600px) and (min-aspect-ratio: 1/1) {
  .panel.wide { align-self: center; width: 100%; height: auto; max-height: 100%; aspect-ratio: var(--ar); }
  .panel.wide .art, .has-texture .panel.wide .art { scale: 1 !important; translate: 0 0 !important; object-position: 50% 50%; }
  .panel.wide .strip { display: none; }   /* the eye close-up band only made sense on the cropped panel */
  .row.sub-2 { grid-template-columns: 1fr 1fr; grid-template-rows: minmax(0, 58fr) minmax(0, 42fr) !important; }
  .row.sub-2 .panel.main { grid-column: 1 / -1 !important; grid-row: 1 !important; width: auto; height: 100%; max-width: 100%; justify-self: center; }
  .row.sub-2 .panel:not(.main) { grid-column: auto !important; grid-row: 2 !important; height: 100%; width: auto; max-width: 100%; aspect-ratio: 1808 / 1504; }
  .row.sub-2 .panel:not(.main):nth-of-type(2) { justify-self: end; }
  .row.sub-2 .panel:not(.main):nth-of-type(3) { justify-self: start; }
}
