@font-face{font-family:"Fraunces";src:url(/static/fonts/fraunces-var.woff2) format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Bitter";src:url(/static/fonts/bitter-var.woff2) format("woff2");font-weight:300 800;font-display:swap}
@font-face{font-family:"Source Sans 3";src:url(/static/fonts/source-sans-3-var.woff2) format("woff2");font-weight:200 900;font-display:swap}
:root{--head:57px;--vitality:1;--vit:1;
  --landwash:#071219; --water-deep:#0a1c22; --water-lit:#144b4a; --night:#14202C;
  --board:#1b1a17; --board-grain:rgba(255,236,200,.035); --board-edge:rgba(217,164,65,.30);
  --sack:#F6F1E7; --fog:#e8e4dc; --fog-dim:#a7a99f; --fog-mute:#6f716a; --tweed:#8A8F94;
  --dory:#D9A441; --harbour-light:var(--dory); --harbour-glow:rgba(217,164,65,.18); --slicker:#e9b425;
  --berry:#A8323A; --kelp:#3E5F4A; --store-red:var(--berry); --crisis:#7fa7c9; --navy:#1F3550;
  --paper:#e6dcc3; --paper-ink:#2a2622; --pencil:#5c554b;
  --r-board:10px; --r-chip:999px; --r-paper:3px;
  --font-voice:"Fraunces","Iowan Old Style","Palatino Linotype",Georgia,serif;
  --font-slab:"Bitter","Zilla Slab",Georgia,serif;
  --font-ui:"Source Sans 3",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --safe-b:env(safe-area-inset-bottom,0px); --safe-t:env(safe-area-inset-top,0px);
  --ease-out:cubic-bezier(.2,.7,.2,1); --ease-in-out:cubic-bezier(.45,0,.2,1);
  --tx:0; --ty:0; --sy:0; --kb:0px; --wharf:60px; --travel:28px;
}
@property --tx{syntax:"<number>";inherits:true;initial-value:0} @property --ty{syntax:"<number>";inherits:true;initial-value:0} @property --sy{syntax:"<number>";inherits:true;initial-value:0}

/* ---------- ground ---------- */
*{box-sizing:border-box}
html{font-size:17px;overflow-x:hidden;background:var(--landwash);color-scheme:dark}
html,body{margin:0;min-height:100%;color:var(--fog);font-family:var(--font-ui);line-height:1.5}
/* the ground is on html so the fixed harbour behind the page is not painted over */
html{background:var(--landwash)}
body{background:transparent}
/* clip, not hidden: hidden turned body into a scroll container that never
   scrolls, so the top bar's sticky had nothing to stick to (hidden stays as
   the fallback for a browser that does not know clip) */
body{touch-action:manipulation;max-width:100vw;overflow-x:hidden;overflow-x:clip}
p,h1,h2,h3,button,a,input,textarea,label,td,th,li{overflow-wrap:anywhere}
button,a,input,textarea,select{font:inherit;color:inherit}
button{cursor:pointer}
[hidden]{display:none !important}
.sr-only{position:absolute;width:1px;height:1px;clip:rect(0 0 0 0);overflow:hidden;white-space:nowrap}
:focus{outline:none}
:focus-visible{outline:2px solid var(--dory);outline-offset:2px}
a{color:var(--dory);text-decoration:none}
a:hover,a:focus-visible{text-decoration:underline}

[data-view]{display:none;min-height:100%}
[data-view][data-active]{display:block}
[data-view="home"][data-active]{position:relative}
main{display:block}
main > section[data-active]{padding-bottom:calc(var(--wharf) + var(--safe-b) + 24px)}

/* ---------- the harbour ---------- */
.scene{position:relative;height:100vh;height:100svh;overflow:hidden;background:var(--landwash);isolation:isolate}
.scene.harbour{height:100svh}
.layer{position:absolute;inset:0;background-size:cover;background-position:center bottom;background-repeat:no-repeat;--d:0;
  transform:translate3d(calc(var(--tx) * var(--d) * var(--travel) * -1), calc((var(--ty) + var(--sy)) * var(--d) * var(--travel) * -1), 0)}
.layer-sky{background-image:url(/static/scene/sky.svg);--d:.05;z-index:0}
.layer-farshore{background-image:url(/static/scene/farshore.svg);--d:.12;z-index:1}
.layer-water{background:transparent;--d:.35;z-index:2}
.wave{position:absolute;inset:0;background-repeat:no-repeat;background-size:cover;background-position:center bottom;opacity:.9}
.wave.a{background-image:url(/static/scene/wave-a.svg)}
.wave.b{background-image:url(/static/scene/wave-b.svg)}
.light-smear{position:absolute;right:8%;bottom:26%;width:20%;height:30%;
  background:radial-gradient(ellipse at center,rgba(217,164,65,.38),transparent 70%);pointer-events:none;opacity:.36}
.layer-fog{background-image:url(/static/scene/fog.svg);--d:.18;z-index:3;opacity:.13}
.layer-dory{background-image:none;--d:.55;z-index:5}
.layer-dory::before{content:"";position:absolute;inset:0;background-image:url(/static/scene/dory.svg);
  background-size:92% auto;background-position:8% 78%;background-repeat:no-repeat}
.layer-stage{background-image:url(/static/scene/stage.svg);--d:.20;z-index:4}
.hero-film{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 50%;
  z-index:6;background:var(--landwash);pointer-events:none;transition:opacity 800ms var(--ease-out)}
.hero-film.fade-out{opacity:0}
/* while the film is up the drawn layers wait underneath */
.scene.has-film .layer-sky,.scene.has-film .layer-farshore,.scene.has-film .layer-water,
.scene.has-film .layer-fog,.scene.has-film .layer-dory,.scene.has-film .layer-stage{opacity:0}
.scene.film-out .layer-sky,.scene.film-out .layer-farshore,.scene.film-out .layer-water,
.scene.film-out .layer-fog,.scene.film-out .layer-dory,.scene.film-out .layer-stage{opacity:1;transition:opacity 800ms var(--ease-out)}
.scene.film-out .layer-fog{opacity:.13}
.lantern{position:absolute;left:0;top:0;width:140px;height:140px;margin:-70px 0 0 -70px;z-index:7;
  background:radial-gradient(circle,rgba(217,164,65,.10),transparent 70%);
  mix-blend-mode:screen;pointer-events:none;opacity:0;will-change:transform}
.ripple{position:absolute;z-index:7;width:0;height:0;pointer-events:none}
.ripple i{position:absolute;left:0;top:0;width:0;height:0;margin:0;border:1px solid rgba(232,228,220,.12);border-radius:50%}

/* chrome on the film */
.skip,.sound{position:absolute;top:calc(16px + var(--safe-t));min-width:48px;min-height:48px;padding:0 14px;
  border:1px solid var(--board-edge);border-radius:var(--r-chip);background:var(--board);color:var(--fog);
  opacity:.92;font:600 16px var(--font-ui);z-index:12}
.skip{right:16px}
.sound{left:16px}
.skip:hover,.skip:focus-visible,.sound:hover,.sound:focus-visible{opacity:1;border-color:var(--dory);color:var(--dory)}
.sound[aria-pressed="true"]{border-color:var(--dory);color:var(--dory)}
/* the word on the film: under Sound on a phone (the dock owns the bottom), top-left on a desk */
.wordmark{position:absolute;left:16px;top:calc(76px + var(--safe-t));margin:0;z-index:11;
  font:600 24px/1 var(--font-voice);letter-spacing:-.01em;font-variation-settings:"opsz" 24}

/* the harbour is the backdrop; the dock owns the first screen and the strips scroll over both */
[data-view="home"] .scene.harbour{position:fixed;inset:0;height:100svh;z-index:0}
/* the dock owns the bottom 34 vh (UIUX §3.1), not the bottom 43: when it
   rode higher its board sat at eyebrow level over the film and the Skipper
   came up out of the water with no face on him. */
.intro-dock{position:relative;z-index:10;min-height:100svh;min-height:100vh;
  display:flex;flex-direction:column;justify-content:flex-end;
  /* the dock is a fade over the film: the film's own chrome stays reachable */
  pointer-events:none;
  padding:14px 16px calc(12px + var(--safe-b));
  background:linear-gradient(transparent 46%,rgba(7,18,25,.55) 62%,rgba(7,18,25,.92) 82%,var(--landwash) 98%)}
.intro-dock > *{pointer-events:auto}
.him-wrap{display:flex;gap:10px;align-items:flex-end}
.face{width:72px;height:72px;border-radius:50%;border:1px solid var(--dory);display:block;object-fit:cover;
  object-position:50% 28%;box-shadow:0 0 22px var(--harbour-glow)}
.intro-dock .face{width:56px;height:56px;flex:none;margin-bottom:2px}
.board{background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge);border-radius:var(--r-board);padding:14px 16px}
.intro-dock .board{flex:1;min-width:0;min-height:96px;padding:12px 14px;position:relative}
.frame{margin:0;font:500 1.53rem/1.25 var(--font-voice);color:var(--fog);text-wrap:pretty;min-height:3.2rem}
.frame .past{opacity:.55;display:block;transform:translateY(-8px)}
.empty-title{margin:0 0 6px;font:500 1.5rem/1.25 var(--font-voice)}
.empty-line{margin:0;font:400 17px/1.45 var(--font-voice);color:var(--fog-dim)}
/* during the film the board types; the two home lines wait (visibility, so Fraunces still loads) */
.scene.has-film ~ .intro-dock .empty-title,
.scene.has-film ~ .intro-dock .empty-line{visibility:hidden;position:absolute;pointer-events:none}
/* while the film is up the typed board keeps to one line and a half, so its
   top edge stays below the Skipper's chin — the film is 9:16 and the phone
   shows all of it; the board was riding up over his beard (owner QC). */
.scene.has-film ~ .intro-dock .frame{min-height:2.55rem}
.scene.film-out ~ .intro-dock .empty-title,
.scene.film-out ~ .intro-dock .empty-line{visibility:visible;position:static}
.scene.film-out ~ .intro-dock .frame,
.scene:not(.has-film) ~ .intro-dock .frame{display:none}
.cta{display:block;width:100%;max-width:320px;min-height:52px;margin:12px auto 0;padding:12px 22px;
  border:1px solid var(--dory);border-radius:var(--r-chip);background:transparent;color:var(--dory);
  font:600 16px var(--font-ui);box-shadow:0 0 24px var(--harbour-glow)}
.doors{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}
.door{display:block;min-height:64px;padding:10px 12px;border-radius:var(--r-board);
  background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge);color:var(--fog);text-decoration:none;position:relative}
.door:hover,.door:focus-visible{border-top-color:var(--dory);text-decoration:none}
.door-name{display:block;font:600 20px/1.2 var(--font-voice)}
.door-name::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:8px;
  background:var(--dory);box-shadow:0 0 8px var(--harbour-glow);vertical-align:middle}
.door-line{display:block;margin-top:2px;font:400 14px/1.35 var(--font-ui);color:var(--fog-dim)}
.watch-again{display:block;margin:10px 0 0 auto;min-height:44px;min-width:44px;padding:10px 4px;border:0;
  background:transparent;color:var(--fog-dim);font:400 13px var(--font-ui);text-decoration:underline}

/* home strips */
.strips{position:relative;z-index:2;background:rgba(7,18,25,.92);padding:24px 16px calc(var(--wharf) + var(--safe-b) + 24px)}
.strip{margin:0 0 26px}
.strip h2{margin:0 0 10px;font:700 20px/1.2 var(--font-slab)}
.rows{display:flex;flex-direction:column;gap:10px}
.row{display:grid;grid-template-columns:88px 1fr;gap:12px;align-items:start;min-height:64px;
  background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge);border-radius:var(--r-board);padding:12px;color:var(--fog);text-decoration:none}
.row:hover,.row:focus-visible{border-top-color:var(--dory);text-decoration:none}
.thumb{width:88px;height:50px;border-radius:4px;background-size:cover;background-position:center;background-color:var(--water-deep)}
.row-title{margin:0 0 4px;font:600 18px/1.3 var(--font-voice)}
.row-hook{margin:0;font:400 15px/1.45 var(--font-ui);color:var(--fog-dim)}
.foot{margin-top:28px;text-align:center;color:var(--fog-dim);font:400 15px/1.55 var(--font-ui)}
.foot .crest-full{width:96px;height:96px;margin:0 auto 10px;display:block;opacity:.85}
.foot p{margin:0 0 6px}
.foot .best{font:500 19px/1.3 var(--font-voice);color:var(--fog)}

/* the harbour behind every interior surface: the page floats on the water */
.page-harbour{position:fixed;inset:-4%;height:108vh;z-index:-1;pointer-events:none;background:var(--landwash)}
/* the real water at dusk under the drawn layers, dim enough that a board still reads */
.page-harbour::before{content:"";position:absolute;inset:0;
  background:url(/static/media/harbour-plate.webp) center 58% / cover no-repeat;
  filter:brightness(.42) saturate(.6) contrast(1.02);opacity:.9}
.page-harbour .layer-farshore{opacity:.55;background-position:center 70%}
.page-harbour .layer-stage{opacity:.5;background-position:110% 108%;background-size:130% auto}
.page-harbour .layer-water{opacity:.5}
.page-harbour .wave{background-position:center 84%}
.page-harbour .layer-fog{opacity:.09}
.page-harbour .light-smear{right:4%;bottom:10%;width:26%;height:24%;opacity:.28}
/* the lamp's walk on the water: the one moving thing on a quiet page */
.walk{position:absolute;left:-20%;right:-20%;bottom:16%;height:16%;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(217,164,65,.26) 42%,rgba(232,228,220,.12) 52%,rgba(217,164,65,.22) 62%,transparent)}

/* ---------- the bands on interior pages ---------- */
.band{--pan:32px;position:relative;height:26vh;min-height:170px;max-height:240px;overflow:hidden;
  background:linear-gradient(180deg,#0a1c22 0%,#132c32 55%,#05080c 100%)}
/* the roadhead stands against the real water at dusk, not a flat gradient */
.band::before{content:"";position:absolute;inset:-6%;z-index:0;
  background:url(/static/media/harbour-band-phone.webp) center 40% / cover no-repeat;
  opacity:.82;filter:saturate(.7) brightness(.62) contrast(1.04)}
.band .layer{z-index:1}
.band::after{content:"";position:absolute;left:0;right:0;bottom:0;height:8px;
  background:linear-gradient(transparent,var(--landwash));pointer-events:none;z-index:3}
.band .layer{--d:.08;transform:none;will-change:transform}
.band .layer.roadhead{background-size:cover;background-position:center 62%}
.band .layer.stage-layer{background-image:url(/static/scene/stage.svg);background-position:center bottom}
.band.door-band{background:
  repeating-linear-gradient(90deg,#14100c 0 22px,#0e0c0a 22px 24px),
  linear-gradient(180deg,#1b1a17,#0e0c0a);
  height:34vh;max-height:280px;display:flex;align-items:center;justify-content:center}
.notice{position:relative;width:min(78vw,320px);padding:20px 18px 16px;background:var(--paper);color:var(--paper-ink);
  transform:rotate(-1.5deg);box-shadow:0 2px 6px rgba(0,0,0,.45)}
.notice::before,.notice::after{content:"";position:absolute;top:8px;width:8px;height:8px;border-radius:50%;
  background:#5a5348;box-shadow:inset 0 1px 0 #2a2622}
.notice::before{left:10px}
.notice::after{right:10px}
.notice .wm{margin:0 0 8px;font:600 13px var(--font-voice);letter-spacing:.04em}
.notice h1{margin:0;font:500 24px/1.2 var(--font-voice)}
.scene-shallow{height:38vh;max-height:300px}
.ask-harbour{height:38vh;max-height:300px}
/* once the talk starts, a phone gives the words the room: the harbour steps
   back to a strip with the weather on it (ask.js sets .talking) */
@media (max-width:1023px){
  [data-view="ask"].talking .ask-harbour{height:76px}
}
@media (max-width:1023px) and (prefers-reduced-motion:no-preference){
  .ask-harbour{transition:height 320ms var(--ease-out)}
}
.ask-harbour .plate{position:absolute;inset:0;z-index:0}
.ask-harbour .plate img{width:100%;height:100%;object-fit:cover;object-position:center 44%;display:block}
/* over a photograph the sheets are a glaze: the water shows, the picture stays */
.ask-harbour .layer-water{opacity:.3;top:auto;height:46%}
.ask-harbour .layer-fog{opacity:.08}
.ask-harbour .wave{background-position:center bottom}
/* the lamp's walk lies on the water in every band that has water */
.ask-harbour .layer-water::after,.games-window .layer-water::after{content:"";position:absolute;
  left:-20%;right:-20%;bottom:14%;height:26%;
  background:linear-gradient(90deg,transparent,rgba(217,164,65,.26) 44%,rgba(232,228,220,.12) 52%,rgba(217,164,65,.22) 60%,transparent)}
.games-window{height:22vh;min-height:150px;max-height:220px}
.weather{position:absolute;left:16px;bottom:12px;z-index:4;margin:0;font:600 12px/1 var(--font-slab);
  letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.skipper-line{margin:16px 16px 12px;font:400 18px/1.5 var(--font-voice);text-wrap:pretty;max-width:42rem}
.skipper-line::before{content:"\201C";color:var(--dory);margin-right:2px}

/* ---------- the band header and the harbour bar ---------- */
.band-head{position:sticky;top:0;z-index:8;display:flex;align-items:center;gap:10px;min-height:56px;
  padding:0 12px;background:var(--navy) url(/static/brand/herringbone.svg);background-blend-mode:soft-light;
  border-bottom:1px solid var(--board-edge)}
.band-head .crest{display:flex;align-items:center;justify-content:center;min-width:44px;min-height:44px}
.wordmark-slab{font:700 16px/1 var(--font-slab);letter-spacing:.06em;color:var(--fog)}
.head-doors{display:flex;gap:2px;margin-left:auto}
/* the skip link is hidden until a keyboard reaches it; then it is a real,
   visible button, not a focused 1 px box */
a.sr-only:focus-visible{position:fixed;left:12px;top:calc(12px + var(--safe-t));width:auto;height:auto;margin:0;
  clip:auto;overflow:visible;white-space:nowrap;z-index:50;padding:12px 16px;border:1px solid var(--dory);
  border-radius:var(--r-chip);background:var(--board);color:var(--fog);font:600 16px var(--font-ui);text-decoration:none}
/* Under 1024 the wharf is the way between doors; the same four words again
   up top were a second layer of the same thing, and at 390 they broke
   mid-word ("Pla / n"). The bar keeps the crest, the name and Sound. */
@media (max-width:1023px){
  .head-doors{display:none}
  .band-head .sound.small{margin-left:auto}
}
/* an in-page anchor lands below the sticky bar, not under it */
html{scroll-padding-top:64px}
.head-doors a{display:flex;align-items:center;min-height:44px;min-width:44px;padding:0 10px;
  color:var(--fog-dim);font:600 15px var(--font-ui);text-decoration:none;justify-content:center}
.head-doors a[aria-current="page"]{color:var(--fog);box-shadow:inset 0 -2px 0 var(--dory)}
.sound.small{position:static;min-width:44px;min-height:44px;padding:0 10px;font-size:14px;opacity:1}
.wharf{position:fixed;left:0;right:0;bottom:0;z-index:6;display:flex;
  height:calc(var(--wharf) + var(--safe-b));padding-bottom:var(--safe-b);
  background:var(--landwash);border-top:1px solid var(--board-edge)}
.plank{flex:1;display:flex;align-items:center;justify-content:center;min-height:44px;border:0;background:transparent;
  color:var(--fog-dim);font:600 15px var(--font-ui);padding:0 2px;white-space:nowrap;text-decoration:none}
.plank[aria-current="page"]{color:var(--fog);box-shadow:inset 0 2px 0 var(--dory)}
.plank:hover,.plank:focus-visible{text-decoration:none;color:var(--fog)}
@media (max-width:430px){.plank{font-size:13px}}
.kb-open .wharf{transform:translateY(110%)}

/* ---------- Ask ---------- */
[data-view="ask"][data-active]{display:flex;flex-direction:column;height:100svh;overflow:hidden;padding-bottom:0}
.ask-col{flex:1;min-height:0;display:flex;flex-direction:column;position:relative;overflow:hidden}
.ask-col.scene{height:auto;background:var(--night);isolation:auto}
.ask-col > .layer-water{position:absolute;inset:0;z-index:0;opacity:.45;pointer-events:none}
.ask-col > .layer-water .wave{background-position:center 88%}
.ask-head,.empty,.log,.composer,.ask-col .chips{position:relative;z-index:1}
.ask-head{flex:0 0 auto;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;padding:0 8px;min-height:56px;gap:4px}
.head-btn{min-height:44px;min-width:44px;padding:0 10px;border:0;background:transparent;color:var(--fog);
  font:600 16px var(--font-ui);text-align:center;text-decoration:none;display:flex;align-items:center;justify-content:center}
.ask-head .head-btn:last-child{justify-self:end}
/* The mark is the road home on this screen: Ask is one of the two views
   that stand down the bottom nav, and V1 §4.3 says no screen ends
   without a way out. B0's crawl found this one on desk. */
.ask-mark{margin:0;font:600 20px/1 var(--font-voice);letter-spacing:-.01em;text-align:center;
  color:var(--fog);text-decoration:none;display:inline-flex;align-items:center;
  justify-content:center;min-height:44px;padding:0 10px}
.ask-mark:hover,.ask-mark:focus-visible{color:var(--dory);text-decoration:none}
.empty{flex:1;overflow-y:auto;padding:8px 16px calc(var(--wharf) + 88px + var(--safe-b))}
.empty-core{padding:4px 0 12px}
.empty-hail{max-width:100%;margin:0 0 14px;align-items:flex-start}
.empty-hail .board{flex:1}
.hails{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.hail-btn{display:inline-flex;align-items:center;gap:8px;width:100%;min-height:48px;padding:10px 14px;text-align:left;
  border:1px solid var(--board-edge);border-radius:var(--r-chip);background:var(--board);color:var(--fog);
  font:400 16px/1.3 var(--font-voice)}
.hail-btn:hover,.hail-btn:focus-visible{border-color:var(--dory)}
.hail-btn::before{content:"";width:7px;height:7px;border-radius:50%;flex:none;background:var(--dory);
  box-shadow:0 0 8px var(--harbour-glow)}
.log{flex:1;overflow-y:auto;padding:8px 16px calc(var(--wharf) + 88px + var(--safe-b));display:flex;flex-direction:column;gap:10px}
.log:empty{display:none !important}
.board-dim{border-top-color:var(--fog-mute)}
.board-listing{border-top-color:rgba(233,180,37,.55)}
.board-sent{border-top:2px solid var(--kelp)}
.turn-face{width:28px;height:28px;border-radius:50%;border:1px solid var(--board-edge);flex:none;object-fit:cover;
  object-position:50% 28%;margin-top:6px}
.log .him-wrap{max-width:88%;align-items:flex-start}
.turn-him{flex:1;font:400 18px/1.5 var(--font-voice);text-wrap:pretty;white-space:pre-wrap}
.turn-me{align-self:flex-end;max-width:80%;background:var(--water-deep);border-radius:var(--r-board);padding:14px 16px;
  color:var(--fog);font:400 17px/1.45 var(--font-ui)}
.think-lab{margin:8px 0 0;font:400 13px var(--font-ui);color:var(--fog-dim)}
.dots{display:flex;gap:6px;align-items:center;min-height:18px}
.dots i{display:block;width:6px;height:6px;border-radius:50%;background:var(--fog-dim);opacity:.3}
.where{margin-top:12px;padding-top:10px;border-top:1px solid var(--board-edge);display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.where-lab,.lab{font:600 12px/1 var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.where a{color:var(--dory)}
.tag{margin-left:auto;font:600 12px/1 var(--font-slab);letter-spacing:.06em;text-transform:uppercase;padding:5px 8px;
  border:1px solid var(--fog-dim);border-radius:var(--r-chip);color:var(--fog-dim)}
.tag-yarn{border-color:var(--berry);color:var(--fog-dim)}
.tag-false{border-color:var(--fog);color:var(--fog)}
.tag-listing{border-color:var(--slicker);color:var(--slicker)}
.tag-ex{border-color:var(--fog-dim);color:var(--fog-dim)}
.board-crisis{background:var(--water-deep);border-top:2px solid var(--crisis);border-radius:var(--r-board);padding:14px 16px;
  font:400 16px/1.5 var(--font-ui)}
.crisis-link{color:var(--fog);text-decoration:underline;text-underline-offset:3px;overflow-wrap:anywhere}
.crisis-row{display:flex;align-items:center;min-height:52px;width:100%;margin-top:8px;border:0;border-left:3px solid var(--crisis);
  background:transparent;color:var(--fog);font:400 16px var(--font-ui);text-align:left;padding:8px 12px;text-decoration:none}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.chip{min-height:44px;display:inline-flex;align-items:center;padding:0 14px;border:1px solid var(--board-edge);
  border-radius:var(--r-chip);background:var(--board);color:var(--fog);font:400 16px var(--font-ui);text-decoration:none}
.chip-voice{font-family:var(--font-voice)}
.chip-quiet{border:0;background:transparent;color:var(--fog-dim);text-decoration:underline}
.composer{position:fixed;left:0;right:0;bottom:calc(var(--wharf) + var(--safe-b) + var(--kb));z-index:6;display:none;
  gap:8px;align-items:flex-end;padding:8px 12px;
  background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge)}
[data-view="ask"][data-active] .composer{display:flex}
.composer textarea{flex:1;min-height:52px;max-height:calc(1.5em * 5 + 28px);resize:none;border:1px solid var(--board-edge);
  border-radius:var(--r-board);background:var(--water-deep);color:var(--fog);font:400 17px var(--font-ui);padding:14px 12px}
.send{min-width:48px;min-height:48px;border:0;border-radius:var(--r-chip);background:var(--dory);color:var(--landwash);
  font:600 18px var(--font-ui);box-shadow:0 0 16px var(--harbour-glow)}
.kb-open .composer{bottom:var(--kb)}
.latest{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(var(--wharf) + 76px + var(--safe-b) + var(--kb));z-index:5}

/* ---------- lists and articles ---------- */
.list-wrap{padding:0 16px 24px;max-width:46rem;margin:0 auto}
.road-sec{margin:0 0 24px}
.road-sec h2{margin:0 0 10px;font:700 20px/1.2 var(--font-slab)}
.article{padding:0 16px 32px;max-width:44rem;margin:0 auto}
.article h1{margin:8px 0 6px;font:700 24px/1.2 var(--font-slab)}
.eyebrow{margin:0 0 12px;font:600 12px/1 var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.article h2{margin:20px 0 6px;font:700 18px/1.2 var(--font-slab)}
.article p,.article li{font:400 15px/1.5 var(--font-ui)}
.article ul,.article ol{margin:6px 0 0;padding-left:20px}
.article li{margin:0 0 6px}
.gloss{font:700 22px/1.3 var(--font-slab);margin:0 0 8px}
.more{display:inline-flex;align-items:center;min-height:44px;padding:0 16px;margin:16px 16px 0;
  border:1px solid var(--dory);border-radius:var(--r-chip);color:var(--dory);font:600 16px var(--font-ui);text-decoration:none}
.safety{margin:0 0 8px;font:400 14px/1.4 var(--font-ui);color:var(--fog)}
.safety::before{content:"! ";color:var(--berry);font-weight:700}

/* ---------- games, rooms ---------- */
.games-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:0 16px}
.card{display:block;padding:14px;border-radius:var(--r-board);color:var(--fog);text-decoration:none;
  background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge);min-height:96px}
.card:hover,.card:focus-visible{border-top-color:var(--dory);text-decoration:none}
.card .glyph{width:24px;height:24px;display:block;margin-bottom:8px;color:var(--dory)}
.card-name{display:block;font:600 20px/1.2 var(--font-voice)}
.card-line{display:block;margin-top:4px;font:400 14px/1.35 var(--font-ui);color:var(--fog-dim)}
/* The wide Rooms card is gone (evolve V1 §3.1); the rule stays one week so
   a rollback finds it (HANDHOLD B8 rollback line). Nothing renders it. */
.rooms-card{margin:0 16px 10px;display:block}

/* Got a code? — the slim strip under the Skipper line (UIUX §2.1).
   56 tall, Night at 88 %, and the hub does not resolve the code: the games
   host does, because only that host can ask both table services. */
.code-wrap{margin:0 16px 14px}
.code-strip{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  min-height:56px;padding:0 12px;border-radius:var(--r-board);
  background:color-mix(in srgb,var(--night) 88%,transparent);
  border:1px solid var(--board-edge)}
.code-label{font:600 14px/1.2 var(--font-ui);color:var(--fog-dim);flex:none}
.code-strip input{flex:1 1 7ch;min-width:7ch;min-height:44px;padding:0 10px;
  font:600 17px/1 var(--font-voice);letter-spacing:.06em;color:var(--fog);
  background:transparent;border:1px solid var(--board-edge);border-radius:var(--r-paper)}
.code-strip input::placeholder{color:var(--fog-dim);opacity:.85;letter-spacing:.06em}
.code-go{flex:none;min-height:44px;padding:0 16px;border:0;border-radius:var(--r-chip);
  font:600 15px/1 var(--font-ui);color:var(--navy);background:var(--dory);cursor:pointer}
.code-error{margin:6px 2px 0;min-height:1.2em;font:400 14px/1.35 var(--font-ui);color:var(--berry)}

/* The card's one quiet second door. Its own 44 px rect inside the card's. */
.card{position:relative}
.card-friends{display:flex;align-items:center;justify-content:flex-end;
  width:fit-content;margin:8px 0 0 auto;padding-left:12px;min-height:44px;
  font:400 14px/1.3 var(--font-ui);color:var(--dory);
  text-decoration:underline;text-underline-offset:3px}
.card-friends:hover,.card-friends:focus-visible{color:var(--dory);text-decoration:underline}
.games-boards{display:inline-flex;align-items:center;min-height:44px;margin:12px 16px 0}
/* thumbnails: image on top, same card below; the frame is reserved by the
   aspect-ratio box so nothing shifts when the webp lands (no CLS). */
.card-thumb{display:block;width:100%;aspect-ratio:4/3;height:auto;object-fit:cover;
  border-radius:calc(var(--r-board) - 4px);border:1px solid var(--board-edge);
  margin:-2px -2px 12px;background:var(--board);content-visibility:auto}
.rooms-card .card-thumb{aspect-ratio:16/9;max-height:300px}
.board-card{display:block;margin:0 16px}
.board-card .card-thumb{aspect-ratio:21/9;max-height:280px}
.card .glyph{margin-top:2px}
.table-talk{margin:16px 16px;font:400 17px/1.45 var(--font-voice);color:var(--fog-dim)}
.rooms-grid{display:grid;gap:10px;padding:0 16px}
.room-grid{display:grid;gap:12px;padding:0 16px}
.code-card{text-align:center}
.room-code{display:block;margin:6px 0 10px;font:700 42px/1 var(--font-slab);letter-spacing:.12em;color:var(--fog)}
.chair{display:flex;align-items:center;gap:10px;min-height:44px;padding:8px 4px;border-bottom:1px solid var(--board-edge)}
.chair .who{font:400 17px var(--font-voice)}
.chair .kind{margin-left:auto;font:600 12px var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}

/* ---------- trivia and the board (carried) ---------- */
#triviaMount,#boardMount{padding:8px 16px 28px}
.trivia-core{max-width:720px;margin:0 auto}
.piles{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:10px}
.pile{min-height:44px;padding:8px 10px;border:1px solid var(--board-edge);border-radius:var(--r-board);
  background:var(--board);color:var(--fog);font:600 13px/1.2 var(--font-ui);text-align:left}
.opt{width:100%;min-height:52px;display:flex;gap:12px;align-items:center;margin-top:8px;background:var(--water-deep);
  border:0;border-radius:var(--r-board);color:var(--fog);text-align:left;padding:8px 12px}
.opt .ltr{color:var(--fog-dim);font:600 14px var(--font-ui);width:1.2em;flex:none}
.opt.picked{outline:2px solid var(--dory);outline-offset:0}
.opt.yes{border-top:2px solid var(--dory)}
.opt.no{outline:1px solid var(--berry)}
.trivia-q{font:400 18px/1.5 var(--font-voice);margin:6px 0 0}
.trivia-note{margin:10px 0 0;font:400 13px var(--font-ui);color:var(--fog-dim)}
.hear{display:inline-flex;align-items:center;gap:6px;min-height:44px;margin-top:8px;padding:0 12px;
  border:1px solid var(--board-edge);border-radius:var(--r-chip);background:transparent;color:var(--fog);font:600 14px var(--font-ui)}
.board-table{width:100%;border-collapse:collapse}
.board-table th{font:600 12px var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim);text-align:left;padding:8px 6px}
.board-table td{padding:10px 6px;font:400 15px var(--font-ui);vertical-align:middle}
.board-table td.name{font:400 17px var(--font-voice)}
.board-table td.rank,.board-table td.streak{color:var(--fog-dim);font-size:13px}
.board-table tr:nth-child(even) td{background:rgba(10,28,34,.4)}
.board-table tr.me td{box-shadow:inset 2px 0 0 var(--dory)}
.name-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px}
.name-row label{flex:1 0 100%;font:600 14px var(--font-ui);color:var(--fog-dim)}
.name-row input{min-width:0}
.name-row .outline-btn{white-space:nowrap}
.name-row input{flex:1;min-height:44px;border:0;border-bottom:1px solid var(--board-edge);background:var(--water-deep);
  color:var(--fog);padding:8px 10px}
.outline-btn{min-height:44px;display:inline-flex;align-items:center;justify-content:center;padding:0 14px;
  border:1px solid var(--dory);border-radius:var(--r-chip);background:transparent;color:var(--dory);font:600 16px var(--font-ui);
  text-decoration:none}
.field-msg{margin:6px 0 0;font:400 14px var(--font-ui);color:var(--fog-dim)}

/* ---------- Plan: the trip desk (carried from the concept) ---------- */
/* Plan is a fixed desk under the top bar (--head), so the page itself never scrolls */
[data-view="plan"][data-active]{display:flex;flex-direction:column;height:calc(100svh - var(--head));overflow:hidden;
  padding-bottom:calc(var(--wharf) + var(--safe-b));background:transparent}
[data-view="plan"] .band{flex:none;--pan:70px;height:30vh;max-height:280px}
#tripMount{flex:1;min-height:0;display:flex;flex-direction:column}
.trip-desk{display:grid;grid-template-rows:minmax(0,1fr);flex:1;min-height:0;overflow:hidden;background:transparent}
.trip-desk.has-plan{grid-template-rows:minmax(150px,28vh) minmax(0,1fr)}
.trip-map{min-height:210px;height:100%;min-width:0;background:var(--water-deep);border-bottom:1px solid var(--board-edge);
  z-index:1;overflow:hidden;order:-1}
.trip-map .leaflet-container{height:100%;width:100%;min-height:210px}
.trip-wrap{padding:8px 10px 12px;min-width:0}
.trip-desk .trip-wrap{overflow:auto;position:relative;z-index:2;margin:0;padding:12px 14px calc(var(--wharf) + 28px);background:transparent}
.paper{position:relative;max-width:92vw;margin:0 auto;padding:16px 14px 12px;background:var(--paper);color:var(--paper-ink);
  border-radius:var(--r-paper);box-shadow:0 2px 6px rgba(0,0,0,.4)}
.trip-desk .paper,.trip-desk .paper.scrap,.trip-desk .paper.trip-rail,.trip-desk .paper.tight{
  transform:none;width:100%;max-width:100%;margin:0;padding:16px 14px 14px;color:var(--fog);
  background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge);border-radius:var(--r-board);box-shadow:0 2px 10px rgba(0,0,0,.35)}
.scrap-mark{margin:0 0 12px;font:600 12px/1 var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--dory)}
.scrap-stack{display:flex;flex-direction:column;gap:4px}
.q-lab{margin:10px 0 8px;font:600 12px/1 var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.scrap-chips{display:flex;flex-wrap:wrap;gap:6px 8px;margin:0}
.scrap-chip,.pick,.day-tile{min-height:44px;display:inline-flex;align-items:center;padding:8px 14px;
  border:1px solid var(--board-edge);border-radius:var(--r-chip);background:var(--board);color:var(--fog);
  font:400 16px/1.3 var(--font-voice)}
.scrap-chip.on,.pick.on,.day-tile.on{border-color:var(--dory);color:var(--dory);background:rgba(217,164,65,.12);
  box-shadow:0 0 16px var(--harbour-glow)}
.scrap-tick{display:flex;align-items:baseline;gap:10px;width:100%;min-height:44px;padding:4px 2px;border:0;
  border-bottom:1px dashed var(--board-edge);background:transparent;color:var(--fog);text-align:left;font:500 17px/1.3 var(--font-voice)}
.scrap-tick .q-lab{margin:0;flex:none}
.pick-rows{display:flex;flex-wrap:wrap;gap:6px 8px}
.day-tiles{display:flex;flex-wrap:wrap;gap:8px}
.stack-it{display:block;width:100%;min-height:52px;margin:16px 0 0;padding:0 16px;border:1px solid var(--dory);
  border-radius:var(--r-chip);background:var(--dory);color:var(--landwash);font:600 16px var(--font-ui)}
.stack-it:disabled{opacity:.38;background:transparent;color:var(--dory)}
.your-trips{margin:16px 0 0}
.your-trips h2{margin:0 0 8px;font:600 13px var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.stop{position:relative;display:grid;grid-template-columns:1fr 44px;gap:8px;margin:10px 0;color:var(--fog);
  background:var(--board) repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
  border-top:1px solid var(--board-edge);border-radius:var(--r-board);padding:14px 8px 14px 16px}
.stop.listing{border-top-color:rgba(233,180,37,.55)}
.stop.is-on{border-top-color:var(--dory);box-shadow:0 0 18px var(--harbour-glow)}
.stop-body{min-width:0}
.stop-title{margin:4px 0 6px;font:600 20px/1.3 var(--font-voice)}
.stop-hook{margin:0 0 10px;font:400 15px/1.5 var(--font-ui);color:var(--fog-dim)}
.how{margin:0 0 8px;font:400 15px/1.5 var(--font-ui)}
.day-head{display:flex;align-items:baseline;justify-content:space-between;margin:18px 4px 4px;font:600 12px/1 var(--font-slab);
  letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.leg{display:flex;align-items:center;justify-content:space-between;margin:4px 8px;font:400 13px var(--font-ui);color:var(--fog-dim)}
.stop-tools{display:flex;flex-direction:column;width:44px}
.stop-tools button{height:44px;min-width:44px;border:0;background:transparent;color:var(--fog-dim);font:600 16px var(--font-ui)}
.trip-bar{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.share-code{margin:12px 4px 0;font:600 22px/1 var(--font-slab);letter-spacing:.08em}
.thin-note{margin:8px 4px;font:400 15px var(--font-voice);color:var(--fog-dim)}
.day-tabs{display:flex;gap:6px;padding:8px 12px;overflow-x:auto}
.leaflet-container{background:var(--water-deep);font:12px var(--font-ui);color:var(--fog)}
.leaflet-tile-pane{filter:saturate(.45) brightness(.52) sepia(.34) hue-rotate(8deg) contrast(1.06)}
.leaflet-popup-content-wrapper{border-radius:var(--r-board);background:var(--board);color:var(--fog);border-top:1px solid var(--board-edge)}
.leaflet-popup-content{margin:10px 12px;font:600 15px var(--font-voice);color:var(--fog)}
.leaflet-popup-tip{background:var(--board)}
.leaflet-bar{border:0;box-shadow:none}
.leaflet-bar a,.leaflet-bar a:hover{background:var(--board);color:var(--fog);border:1px solid var(--board-edge);
  width:36px;height:36px;line-height:34px}
.leaflet-control-attribution{background:rgba(7,18,25,.72) !important;color:var(--fog-dim);font:11px var(--font-ui)}
.leaflet-control-attribution a{color:var(--fog-dim)}
.leaflet-marker-icon.stop-pin,.leaflet-div-icon.stop-pin{width:28px !important;height:28px !important;display:flex;
  align-items:center;justify-content:center;background:var(--dory) !important;color:var(--landwash) !important;
  border:2px solid var(--fog) !important;border-radius:50% !important;font:700 12px/1 var(--font-ui) !important;line-height:24px !important}

/* ---------- Advertise ---------- */
.ad-body{padding:18px 16px 32px;max-width:640px;margin:0 auto}
.ad-copy{margin:0 0 22px;font:400 16px/1.5 var(--font-ui);color:var(--fog)}
.ad-lab{margin:0 0 10px;font:600 12px var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.tier{margin:0 0 10px}
.tier h3{margin:0 0 4px;font:700 18px/1.2 var(--font-slab)}
.tier p{margin:0 0 4px;font:400 15px/1.45 var(--font-ui);color:var(--fog-dim)}
.tier .rate{color:var(--fog)}
.list-card .who{margin:8px 0 0;font:400 15px var(--font-ui);color:var(--fog-dim)}
.ad-form{margin-top:22px}
.fld{display:block;margin:0 0 14px}
.fld span{display:block;margin-bottom:6px;font:600 12px var(--font-slab);letter-spacing:.06em;text-transform:uppercase;color:var(--fog-dim)}
.fld input,.fld textarea{width:100%;min-height:52px;border:1px solid var(--board-edge);border-radius:var(--r-board);
  background:var(--water-deep);color:var(--fog);padding:12px;font:400 16px var(--font-ui)}
.fld textarea{min-height:6.2em;resize:vertical}
.honeypot{position:absolute;left:-9999px}
.send-along{display:block;width:100%;min-height:52px;margin-top:8px;border:1px solid var(--dory);border-radius:var(--r-chip);
  background:transparent;color:var(--dory);font:600 16px var(--font-ui);box-shadow:0 0 18px var(--harbour-glow)}
.ad-foot{margin-top:28px;font:400 13px/1.55 var(--font-ui);color:var(--fog-dim)}
.ad-foot p{margin:0 0 10px}

/* ---------- drawers, dialog, toast ---------- */
#shade{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:11}
.drawer{position:fixed;top:0;bottom:0;left:0;width:88vw;max-width:400px;z-index:12;background:var(--landwash);
  padding:16px 16px calc(16px + var(--safe-b));overflow-y:auto;transform:translateX(-110%);border-right:1px solid var(--board-edge)}
.drawer.open{transform:none}
.drawer-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.drawer-head h2{margin:0;font:600 22px/1.2 var(--font-voice)}
.x{min-width:48px;min-height:48px;border:0;background:transparent;color:var(--fog);font:600 22px var(--font-ui)}
.conv-row,.trip-row{display:flex;align-items:center;width:100%;min-height:44px;padding:8px 4px;border:0;
  border-bottom:1px solid var(--board-edge);background:transparent;color:var(--fog);text-align:left}
.conv-row .when,.trip-row .when{margin-left:auto;color:var(--fog-dim);font:400 13px var(--font-ui);padding-left:8px}
.forget{min-height:44px;padding:0 12px;border:0;background:var(--berry);color:var(--fog);font:600 14px var(--font-ui)}
.conv-line{display:flex;align-items:stretch;border-bottom:1px solid var(--board-edge)}
.conv-line .conv-row{flex:1;min-width:0;border-bottom:0}
.conv-line .forget{align-self:center;margin-left:8px}
.conv-new{color:var(--dory);font:600 16px var(--font-ui)}
dialog#legal{width:100%;max-width:640px;height:100%;max-height:100%;margin:auto;border:0;background:var(--landwash);
  color:var(--fog);padding:56px 20px 32px;font:400 15px/1.55 var(--font-ui)}
dialog#legal::backdrop{background:var(--landwash)}
dialog#legal .x{position:absolute;top:8px;right:8px}
.toast{position:fixed;left:50%;bottom:calc(var(--wharf) + 16px + var(--safe-b));transform:translateX(-50%);z-index:20;
  min-height:44px;white-space:nowrap}

/* ---------- motion ---------- */
@media (prefers-reduced-motion:no-preference){
  .wave.a{animation:waveA 12s linear infinite alternate}
  .wave.b{animation:waveB 16s linear infinite alternate}
  .light-smear{animation:breatheLamp 3.2s var(--ease-in-out) infinite}
  /* the evening comes and goes over the whole harbour: the fog drifts and breathes */
  .layer-fog{animation:fogDrift 24s linear infinite alternate, fogBreath 9s linear infinite alternate}
  .layer-dory::before{animation:bob 3.2s var(--ease-in-out) infinite}
  .layer-dory.knock::before{animation:knock 280ms var(--ease-out)}
  .layer-stage.nudge{animation:nudge 120ms var(--ease-out)}
  .scene.drift{animation:drift 24s var(--ease-in-out) infinite}
  .band .layer{animation:bandPan 7s linear infinite alternate}
  /* on Plan the band is the road going by, so it moves at the road's speed */
  [data-view="plan"] .band .layer{animation-duration:5s}
  [data-view="plan"] .band::before{animation-duration:5s}
  .band::before{animation:plateDrift 9s linear infinite alternate}
  /* the plate breathes: a harbour photograph drifting, not a frozen postcard */
  .ask-harbour .plate img{animation:plateDrift 11s linear infinite alternate}
  @media (max-width:1023px){ .scene.harbour .layer-sky{animation:plateDrift 11s linear infinite alternate} }
  .layer-dory::before{animation:bob 2.8s linear infinite alternate}
  .walk,.ask-harbour .layer-water::after,.games-window .layer-water::after{
    animation:walkSlide 7s linear infinite alternate}
  .page-harbour .layer-water,.ask-col > .layer-water{animation:swell 6s linear infinite alternate}
  /* the whole harbour sways, the way it does when you are standing in a boat */
  .page-harbour{animation:sway 8s linear infinite alternate}
  .notice{animation:breathe 10s ease-in-out infinite}
  /* Paper on a nail: it swings once when it goes up and then settles at its
     angle. It used to sway for ever, which looked right and meant the Stack
     the lot button underneath never stopped moving — hard to hit with a mouse,
     impossible for a pointer that waits for the target to be still. */
  .trip-desk:not(.has-plan) .paper.scrap{animation:pinned 1.6s var(--ease-out) 1 both}
  .dots i{animation:dot 1.4s var(--ease-in-out) infinite}
  .dots i:nth-child(2){animation-delay:.2s}
  .dots i:nth-child(3){animation-delay:.4s}
  .frame.jolt{animation:jolt 260ms var(--ease-out)}
  .turn-me,.log .him-wrap,.board-crisis{animation:rise 160ms var(--ease-out)}
  .cta:not([hidden]){animation:rise 320ms var(--ease-out)}
  .door,.plank,.card,.row{transition:transform 160ms var(--ease-out),border-color 160ms var(--ease-out)}
  .door:hover,.card:hover,.row:hover{transform:translateY(-2px)}
  .entering{animation:slideIn 240ms var(--ease-out)}
  .ripple i{animation:ring 700ms var(--ease-out) forwards}
  .ripple i:nth-child(2){animation-delay:90ms}
  .chair.regular{animation:rise 320ms var(--ease-out) both}
  .wharf.rising{animation:wharfUp 360ms 260ms var(--ease-out) both}
  /* THE HARBOUR KEEPS HOURS (taste ruling 2026-09-19): the six ambient
     keyframes read --vit (the eased vitality scene.js writes, 1 → 0 across
     the settle). The percentage distances stay — they are the geometry of
     the harbour — and the pixel amplitudes scale by the number, so the
     slow-down is continuous and a paused wave holds its phase rather than
     jumping. UI-affecting one-shots (knock, nudge, rise, jolt...) never
     read the number: they are taps, not weather. */
  @keyframes waveA{from{transform:translate3d(calc(-6% * var(--vit,1)),calc(-7px * var(--vit,1)),0)}
                   to{transform:translate3d(0,calc(7px * var(--vit,1)),0)}}
  @keyframes waveB{from{transform:translate3d(0,calc(6px * var(--vit,1)),0)}
                   to{transform:translate3d(calc(-6% * var(--vit,1)),calc(-6px * var(--vit,1)),0)}}
  @keyframes fogDrift{from{transform:translateX(0)}to{transform:translateX(calc(4% * var(--vit,1)))}}
  @keyframes fogBreath{from{opacity:calc(.08 + .045 * (1 - var(--vit,1)))}to{opacity:calc(.08 + .09 * var(--vit,1))}}
  @keyframes breatheLamp{0%,100%{opacity:calc(.26 + .06 * (1 - var(--vit,1)))}50%{opacity:calc(.26 + .22 * var(--vit,1))}}
  @keyframes bob{from{transform:translateY(calc(-4px * var(--vit,1))) rotate(calc(-.4deg * var(--vit,1)))}
                 to{transform:translateY(calc(4px * var(--vit,1))) rotate(calc(.6deg * var(--vit,1)))}}
  @keyframes knock{0%{transform:translateX(0)}40%{transform:translateX(6px)}100%{transform:translateX(-2px)}}
  @keyframes nudge{0%,100%{transform:translateY(0)}50%{transform:translateY(1px)}}
  @keyframes drift{0%,100%{--tx:calc(-.3 * var(--vit,1));--ty:0}50%{--tx:calc(.3 * var(--vit,1));--ty:calc(.08 * var(--vit,1))}}
  @keyframes breathe{0%,100%{opacity:calc(.92 + .04 * (1 - var(--vit,1)))}50%{opacity:1}}
  @keyframes pinned{0%{transform:rotate(-.9deg) translateY(-4px)}55%{transform:rotate(.5deg) translateY(2px)}100%{transform:rotate(-.35deg) translateY(0)}}
  @keyframes dot{0%,80%,100%{opacity:.3}40%{opacity:1}}
  @keyframes jolt{0%{transform:translateY(0)}35%{transform:translateY(6px)}100%{transform:translateY(0)}}
  @keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
  @keyframes slideIn{from{opacity:0;transform:translateX(24px)}to{opacity:1;transform:none}}
  @keyframes ring{from{width:0;height:0;margin:0;opacity:.9}to{width:90px;height:90px;margin:-45px 0 0 -45px;opacity:0}}
  @keyframes bandPan{from{transform:translate3d(calc(var(--pan) * -1),0,0) scale(1.14)}
                     to{transform:translate3d(var(--pan),2%,0) scale(1.26)}}
  @keyframes walkSlide{from{transform:translateX(calc(-16% * var(--vit,1)))}to{transform:translateX(calc(16% * var(--vit,1)))}}
  @keyframes plateDrift{from{transform:scale(1.1) translate3d(calc(-1.2% * var(--vit,1)),calc(.6% * var(--vit,1)),0)}
                        to{transform:scale(1.1) translate3d(calc(1.2% * var(--vit,1)),calc(-.6% * var(--vit,1)),0)}}
  @keyframes swell{from{transform:translateY(calc(-7px * var(--vit,1)))}to{transform:translateY(calc(7px * var(--vit,1)))}}
  @keyframes sway{from{transform:translate3d(calc(-1.1% * var(--vit,1)),calc(5px * var(--vit,1)),0) rotate(calc(-.18deg * var(--vit,1))) scale(1.03)}
                  to{transform:translate3d(calc(1.1% * var(--vit,1)),calc(-5px * var(--vit,1)),0) rotate(calc(.18deg * var(--vit,1))) scale(calc(1.03 + .07 * var(--vit,1)))}}
  @keyframes wharfUp{from{transform:translateY(110%)}to{transform:none}}
  /* asleep, every keyframe in this sheet is parked at its settled value: the
     lamp holds its ember (the floor of breatheLamp), the water is still, and
     0 frames run — scene.js has cancelled the rAF and nothing else asks for
     one. Verified by measurement: 0 rAF over 3s, 0 running animations. */
  [data-hours-asleep] .wave,
  [data-hours-asleep] .light-smear,
  [data-hours-asleep] .layer-fog,
  [data-hours-asleep] .layer-dory::before,
  [data-hours-asleep] .scene.drift,
  [data-hours-asleep] .band .layer,
  [data-hours-asleep] .band::before,
  [data-hours-asleep] .walk,
  [data-hours-asleep] .ask-harbour .plate img,
  [data-hours-asleep] .ask-harbour .layer-water::after,
  [data-hours-asleep] .games-window .layer-water::after,
  [data-hours-asleep] .page-harbour,
  [data-hours-asleep] .page-harbour .layer-water,
  [data-hours-asleep] .ask-col > .layer-water,
  [data-hours-asleep] .layer-sky,
  [data-hours-asleep] .notice,
  [data-hours-asleep] .dots i{animation-play-state:paused !important}
}
@media (prefers-reduced-motion:reduce){
  .layer,.wave,.layer-dory::before,.scene.drift,.notice,.dots i,.band .layer,.band::before,.walk,.ask-harbour .plate img,
  .ask-harbour .layer-water::after,.games-window .layer-water::after,
  .page-harbour,.page-harbour .layer-water,.ask-col > .layer-water{animation:none}
  .layer{transform:none}
  .door:hover,.card:hover,.row:hover{transform:none}
  .lantern,.ripple{display:none}
}
@media (prefers-contrast:more){
  .board,.card,.row,.door{border:1px solid var(--fog)}
  .row-hook,.door-line,.card-line,.tag,.where-lab{color:var(--fog)}
}

/* ---------- the phone room ----------
   The drawn harbour is a landscape composition; a 390-wide window crops it to a
   slice with nothing in it. On a phone the film settles into its own last frame
   instead — the same man, the same stage, the same lamp — with the drawn water,
   the fog and the lamp's walk moving over it. Nothing is lost and nothing is a cut. */
@media (max-width:1023px){
  .scene.harbour{background:var(--landwash)}
  .scene.harbour .layer-sky{background-image:url(/static/media/harbour-room-phone.webp);
    background-position:center 38%;background-size:cover}
  .scene.harbour .layer-farshore,
  .scene.harbour .layer-dory,.scene.harbour .layer-stage{display:none}
  .scene.harbour .layer-water{inset:0;opacity:.42}
  /* the sheets sit on the water in the picture, not under the dock */
  .scene.harbour .wave{background-size:100% auto;background-position:center 44%}
  .scene.harbour .layer-fog{opacity:.10;background-size:130% auto;background-position:center 34%}
  .scene.harbour .light-smear{right:28%;bottom:78%;width:28%;height:15%}
  .scene.harbour .walk{bottom:50%;height:14%}
}

/* ---------- 720–1023: the phone composition centred, the harbour behind ---------- */
@media (min-width:720px) and (min-height:500px) and (max-width:1023px){
  .intro-dock,.ask-col,.list-wrap,.article,.ad-body,.games-grid,.rooms-grid,.room-grid,.strips{
    max-width:720px;margin-left:auto;margin-right:auto}
  .wharf,.composer{left:50%;right:auto;width:100%;max-width:720px;transform:translateX(-50%)}
  .kb-open .wharf{transform:translateX(-50%) translateY(110%)}
}

/* ---------- desk ≥ 1024: its own compositions ---------- */
@media (min-width:1024px){
  :root{--web-inset:4vw;--ask-col:420px}
  .wharf{display:none}
  main > section[data-active]{padding-bottom:40px}
  .hero-film{object-position:50% 48%}
  .wordmark{left:var(--web-inset);top:24px;bottom:auto;font-size:32px}
  .skip{right:16px}
  .sound{left:auto;right:82px}
  /* the stage edge: a band across the bottom — the hail board left, the door boards right */
  .intro-dock{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:16px 24px;
    align-content:end;padding:16px 4vw 20px}
  .intro-dock .him-wrap{align-items:flex-end}
  .intro-dock .board{min-height:112px}
  /* The four door boards stand in one row across the stage edge. Beside a
     520 px hail board they would each be under 160 px at 1440 — under the
     UIUX floor of 200 — so they take the full width of the dock instead. */
  .doors{grid-column:1 / -1;grid-row:2;grid-template-columns:repeat(4,minmax(200px,1fr));gap:16px;margin-top:0}
  .door{min-height:96px;padding:12px 14px}
  .door-name{font-size:22px}
  .cta{position:absolute;left:50%;bottom:210px;transform:translateX(-50%);margin:0;width:220px}
  .watch-again{grid-column:2;grid-row:1;margin:0 0 0 auto;align-self:end}
  .strips{max-width:none;padding:32px var(--web-inset) 48px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px}
  .strips .foot{grid-column:1 / -1}
  /* Ask: the plate full height left, the column right */
  [data-view="ask"][data-active]{display:grid;grid-template-columns:1fr var(--ask-col);height:100svh;overflow:hidden;padding:0}
  [data-view="ask"] .ask-harbour{grid-column:1;grid-row:1;height:100%;max-height:none;position:relative}
  [data-view="ask"] .ask-harbour .plate img{object-position:center 40%}
  .ask-col{grid-column:2;grid-row:1;height:100%;background:var(--night)
    repeating-linear-gradient(0deg,transparent 0 5px,var(--board-grain) 5px 6px);
    border-left:1px solid var(--board-edge);overflow:hidden}
  .empty{display:flex;flex-direction:column;justify-content:center;padding:8px 20px}
  .log{padding:8px 20px}
  [data-view="ask"] .composer{position:relative;left:auto;right:auto;bottom:auto;background:transparent;
    border-top:1px solid var(--board-edge)}
  [data-view="ask"] .weather{left:24px;bottom:24px}
  /* interior surfaces */
  .band{--bh:clamp(170px,26vh,300px);height:var(--bh);max-height:none;--pan:3.6%}
  [data-view="plan"] .band{--bh:clamp(170px,26vh,260px);height:var(--bh);min-height:0;max-height:none}
  /* A roadhead is a 16:9 scene. Covering a 6:1 desk band sliced it to a
     quarter of its height, so Cabot Tower read as two black blocks. Here the
     whole scene stands at band height, centred, its sides feathered into
     the band's own dusk gradient (the art's sky, stop for stop). The
     photograph behind it is his jacket at this width, so it stands down. */
  .band[data-art]::before,.band.roadhead::before{display:none}
  .band .layer.roadhead{background-size:auto 100%;background-position:center bottom;background-repeat:no-repeat;
    -webkit-mask:linear-gradient(90deg,transparent,#000 22%,#000 78%,transparent) center / calc(var(--bh) * 16 / 9) 100% no-repeat;
    mask:linear-gradient(90deg,transparent,#000 22%,#000 78%,transparent) center / calc(var(--bh) * 16 / 9) 100% no-repeat}
  .skipper-line{margin:20px var(--web-inset) 14px}
  .list-wrap{max-width:1120px;padding:0 var(--web-inset) 40px;columns:2;column-gap:32px}
  .road-sec{break-inside:avoid}
  .article{max-width:720px}
  .games-grid{grid-template-columns:repeat(4,minmax(220px,1fr));padding:0 var(--web-inset)}
  /* one control, one margin: The Board sits on the same --web-inset grid as
     the cards above it, not out at the viewport edge (owner QC: squared up). */
  .more{margin-left:var(--web-inset);margin-right:var(--web-inset)}
  .rooms-card{margin:0 var(--web-inset) 12px}
  .code-wrap{margin:0 var(--web-inset) 16px;max-width:460px}
  .games-boards{margin:14px var(--web-inset) 0}
  .board-card{margin:0 var(--web-inset)}
  .rooms-grid{grid-template-columns:1fr 1fr;padding:0 var(--web-inset)}
  .room-grid{grid-template-columns:380px 1fr;padding:0 var(--web-inset)}
  .table-talk{margin:16px var(--web-inset)}
  /* The door with the notice on it stands down the left, and the shop window
     — the paragraph, the tiers, the example and the form — is beside it. */
  [data-view="advertise"][data-active]{display:grid;grid-template-columns:34% 1fr;
    gap:0 32px;align-items:start;padding:0 var(--web-inset) 48px}
  [data-view="advertise"] .band.door-band{grid-column:1;height:auto;min-height:72vh;
    position:sticky;top:72px;margin:0}
  [data-view="advertise"] #adMount{grid-column:2;padding-top:24px}
  .ad-body{max-width:none;padding:0;display:block}
  [data-view="plan"][data-active]{height:calc(100svh - var(--head));padding-bottom:0}
  .trip-desk{display:flex;flex-direction:row;gap:12px;padding:12px}
  .trip-desk .trip-wrap{order:-1;width:min(380px,34vw);max-width:380px;padding:0;overflow:auto}
  .trip-map{flex:1;height:auto;min-height:0;border:1px solid var(--board-edge);border-radius:var(--r-board);order:0}
  .trip-map .leaflet-container{min-height:0}
}
@media (min-width:1440px){
  :root{--web-inset:7.5vw;--ask-col:480px}
  .strips{grid-template-columns:repeat(3,minmax(0,1fr))}
  .list-wrap{columns:2}
  /* the four doors stand in one row once there is room for them at ≥ 200 px */
  .intro-dock{grid-template-columns:minmax(0,420px) minmax(0,1fr)}
  .doors{grid-template-columns:repeat(4,minmax(200px,1fr))}
}
@media (orientation:landscape) and (max-width:1023px){
  .ask-harbour{height:min(38vh,160px);max-height:160px}
  .band{height:min(22vh,140px);min-height:0}
  .trip-desk{grid-template-rows:minmax(140px,1fr) auto}
  .trip-map,.trip-map .leaflet-container{min-height:140px}
}

/* --- Rooms: the porch (CORRECTION_ROOMS.md B6.5.2, translated to the hub2
   tokens per the HANDHOLD B6 delta 1: navy/sack/rule/surface/ink become the
   harbour's fog, board and board-edge; the house is dark, so there is no
   light-scheme block). Text on Dory is Navy (brand §4.2). --- */
.rooms-grid,.room-grid{display:grid;gap:14px;margin:14px 0}
.game-chip{min-height:44px;padding:0 16px;border:1px solid var(--fog);border-radius:var(--r-chip);background:transparent;color:var(--fog);font:inherit;font-weight:600}
.game-chip[aria-checked="true"]{background:var(--dory);color:var(--navy);border-color:var(--dory)}
.game-chip[disabled]{opacity:.45}
.stepper{display:flex;align-items:center;gap:12px;margin:12px 0}
.stepper button{min-width:44px;min-height:44px;border:1px solid var(--board-edge);border-radius:var(--r-board);background:var(--board);color:var(--fog);font-size:1.2rem}
.stepper button[disabled]{opacity:.4}
.eyebrow{font-size:.85rem;letter-spacing:.04em;color:var(--fog-dim);margin:0}
.room-code{font-family:var(--font-slab);font-weight:700;font-size:2.6rem;letter-spacing:.12em;margin:4px 0 8px;color:var(--fog)}
.share-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.share-link{flex:1;min-width:0;overflow-wrap:anywhere;font-size:.95rem;color:var(--fog-dim)}
.chairs{list-style:none;padding:0;margin:0 0 12px}
.chair{display:flex;justify-content:space-between;align-items:center;gap:8px;min-height:44px;border-top:1px solid var(--board-edge);padding:6px 0}
.chair:first-child{border-top:0}
.chair .who{font-weight:600}
.chair.open .who{color:var(--fog-dim);font-weight:400}
.chair .note{font-size:.85rem;color:var(--fog-dim)}
.chair .tag{font-size:.8rem;letter-spacing:.04em;color:var(--fog-dim)}
.go{display:block;text-align:center;line-height:44px;text-decoration:none;margin-top:12px}
.mine{list-style:none;padding:0;margin:0 0 8px}
.mine li{min-height:44px;display:flex;align-items:center}
@media (min-width:1024px){.rooms-grid{grid-template-columns:1fr 1fr}.room-grid{grid-template-columns:380px 1fr}}
/* The porch's two button weights. Forty-four is the floor, everywhere. */
.primary,.secondary{min-height:44px;padding:0 18px;border-radius:var(--r-board);font:inherit;font-weight:600;cursor:pointer}
.primary{background:var(--dory);color:var(--navy);border:1px solid var(--dory)}
.primary[disabled]{opacity:.5;cursor:default}
.secondary{background:transparent;color:var(--fog);border:1px solid var(--board-edge)}
.field{display:block;margin:12px 0}
.field span{display:block;font-size:.9rem;color:var(--fog-dim);margin-bottom:4px}
.field input{width:100%;min-height:44px;box-sizing:border-box;padding:0 12px;border:1px solid var(--board-edge);border-radius:var(--r-board);background:var(--landwash);color:var(--fog);font:inherit}
.field-error{color:var(--berry);min-height:1.2em;margin:6px 0 0}
/* A chair's tag is a word — Host, In, Regular, Empty — not a label shout. */
.chair .tag{text-transform:none;letter-spacing:0;font:600 13px var(--font-ui);color:var(--fog-dim);margin-left:auto;padding:0}

/* The one control a spoken Skipper line gets (FABLE_SKIPPER_VOICE_V1 §1.4).
   Native controls, never autoplay, no avatar, no "Skipper is typing" — brand §6.
   It is only in the document at all when the voice manifest says the owner heard
   that exact file; there is no hidden or disabled state to style. */
.skipper-say{display:block;margin:0 16px 14px;max-width:22rem;width:100%;height:32px}
.skipper-say::-webkit-media-controls-panel{background:var(--fog)}
@media (min-width:900px){.skipper-say{margin:0 var(--web-inset) 12px}}

/* The living clock on the hub (evolve V1 §1.4). The hub takes the clock and
   nothing else — sky, the far-shore lights, the lamp and the moon over the
   drawn harbour. No weather layers here: the weather belongs to the room on
   the games host.

   The drawn harbour is already built in layers, so the wash goes on them
   and not over the whole scene: the sky tone on the sky and the far shore,
   a quieter water tone on the water. One wash over everything at the alpha
   the sky needs flattens the harbour into a rectangle, which is what the
   first still of this showed. Every value comes from static/js/env.js and
   nothing in this block animates on its own. */
.scene.games-window .layer-sky::after,
.scene.games-window .layer-farshore::after,
.scene.harbour .layer-sky::after,
.scene.harbour .layer-farshore::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to bottom,var(--env-sky-top,#2B3B50),var(--env-sky-bottom,#8A5A4A));
  opacity:var(--env-sky-a,0)}
.scene.games-window .layer-water::after,
.scene.harbour .layer-water::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:var(--env-sky-bottom,#8A5A4A);
  opacity:calc(var(--env-sky-a,0) * .55)}
/* The crossfade is armed only once the first write has landed (env.js sets
   `data-env-eased`), so arriving is instant and only an hour that turns under
   you fades. Before B14 these three transitioned up from the stylesheet's
   zero on first paint: ninety seconds of running animation on a page whose
   budget is two, for a fade nobody was there to see the start of. */
html[data-env-eased] .scene.games-window .layer-sky::after,
html[data-env-eased] .scene.games-window .layer-farshore::after,
html[data-env-eased] .scene.games-window .layer-water::after,
html[data-env-eased] .scene.harbour .layer-sky::after,
html[data-env-eased] .scene.harbour .layer-farshore::after,
html[data-env-eased] .scene.harbour .layer-water::after{transition:opacity 90s linear}
.scene .env-moon{position:absolute;left:16%;top:12%;z-index:3;opacity:.9;pointer-events:none}
/* the moon is drawn for the drawn harbour; under 1024 Home is a photograph,
   and a drawn disc pasted on it sat under the wordmark */
@media (max-width:1023px){ .scene.harbour .env-moon{display:none} }
/* Still mode. B12's reduced-motion check found these two still crossfading
   over ninety seconds: the override was written `.scene .layer-sky::after`,
   which is one class short of the rule it was meant to beat
   (`.scene.harbour .layer-sky::after`), so it lost on specificity and did
   nothing. The full selectors, so it wins. UIUX §1: a still-mode fade is
   300 ms at the most and only ever on opacity, which these are. */
@media (prefers-reduced-motion:reduce){
  html[data-env-eased] .scene.games-window .layer-sky::after,
  html[data-env-eased] .scene.games-window .layer-farshore::after,
  html[data-env-eased] .scene.games-window .layer-water::after,
  html[data-env-eased] .scene.harbour .layer-sky::after,
  html[data-env-eased] .scene.harbour .layer-farshore::after,
  html[data-env-eased] .scene.harbour .layer-water::after{transition-duration:300ms}
}
