  /* Cross-book navigation: fade the world out before leaving for the sibling subdomain. */
  body { transition: opacity .28s ease; }
  body.book-leaving { opacity: 0; pointer-events: none; }

  /* Brand display face — self-hosted from the Infinite Realms DS */
  @font-face {
    font-family:'Trajan Pro';
    src:url('fonts/TrajanPro-Regular.otf') format('opentype');
    font-weight:400; font-style:normal; font-display:swap;
  }
  @font-face {
    font-family:'Trajan Pro';
    src:url('fonts/TrajanPro-Bold.otf') format('opentype');
    font-weight:700; font-style:normal; font-display:swap;
  }

  /* =============================================================
     Tokens — Infinite Realms Design System (subset)
     ============================================================= */
  :root {
    /* Ink — the void */
    --ink-900:#05060A; --ink-800:#0B0D14; --ink-700:#121521; --ink-600:#1A1E2E; --ink-500:#262B3D;
    /* Parchment — manuscript & text */
    --parchment-50:#F5EFE1; --parchment-100:#E8DFC8; --parchment-200:#C9BFA8; --parchment-300:#8A8370;
    /* Gold — sacred accent */
    --gold-100:#F4D98A; --gold-200:#E2BA5F; --gold-400:#D4A253; --gold-500:#B8862F; --gold-700:#7C5A1F;
    /* Nebula — cosmic, used sparingly */
    --nebula-blue:#2A4A7F; --nebula-cyan:#4FA3C7; --nebula-violet:#5B3A8C;

    --fg:        var(--parchment-100);   /* primary text (inputs, messages) */
    --fg-muted:  var(--parchment-200);
    --fg-subtle: var(--parchment-300);
    --fg-display:var(--parchment-50);
    --fg-accent: var(--gold-400);

    --font-display:'Trajan Pro','Cinzel','Cormorant Garamond',Georgia,serif;
    --font-serif:'Cormorant Garamond',Georgia,serif;
    --font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
    --tracking-wider:0.18em; --tracking-widest:0.3em;

    /* Borders & dividers */
    --border:rgba(212,162,83,0.18);
    --border-strong:rgba(212,162,83,0.45);
    --border-muted:rgba(232,223,200,0.08);
    --divider:rgba(232,223,200,0.12);

    /* Signature gradients */
    --grad-gold-shimmer:linear-gradient(180deg,var(--gold-100) 0%,var(--gold-400) 35%,var(--gold-500) 65%,var(--gold-700) 100%);
    --grad-gold-horizontal:linear-gradient(90deg,var(--gold-700) 0%,var(--gold-400) 50%,var(--gold-100) 100%);

    /* Radii */
    --r-sm:2px; --r-md:4px; --r-lg:6px; --r-xl:10px; --r-pill:999px;

    /* Shadows & glows */
    --shadow-sm:0 1px 2px rgba(0,0,0,.5);
    --shadow-md:0 4px 12px rgba(0,0,0,.45);
    --shadow-lg:0 16px 40px rgba(0,0,0,.55);
    --shadow-inset-gold:inset 0 1px 0 rgba(244,217,138,.25), inset 0 -1px 0 rgba(58,42,12,.4);
    --glow-gold:0 0 24px rgba(212,162,83,.35);
    --glow-gold-strong:0 0 40px rgba(212,162,83,.55), 0 0 8px rgba(244,217,138,.6);

    /* Scene-specific derived tones (cool moonlight over ink) */
    --sea-far:#070a12; --sea-near:#03040a;
    --moonglade:#c4d4e0;
  }

  * { box-sizing: border-box; }
  html, body { height:100%; margin:0; background:#000; overflow:hidden; }
  body { font-family:var(--font-sans); }

  /* ---------- Scene stack (two cross-fading worlds) ---------- */
  /* Scenes are hidden by default; the active book's scene is the one shown, via
     `body.book-<slug> .scene-<slug>` below. Adding a book's world is then self-contained:
     one .scene-<slug> block + one show rule — no edits to existing books. */
  .scene { position:fixed; inset:0; overflow:hidden; z-index:0; opacity:0; transition:opacity 1.4s ease; }

  /* Odyssey — open moonlit sea */
  .scene-odyssey {
    background:
      radial-gradient(120% 80% at 50% 8%, rgba(42,74,127,0.18) 0%, transparent 46%),
      linear-gradient(to bottom,
        var(--ink-900) 0%,
        var(--ink-800) 32%,
        #0c1220 53%,
        var(--sea-far) 56.2%,
        var(--sea-near) 100%);
  }
  /* Iliad — the Trojan shore at night, embers beyond the walls */
  .scene-iliad {
    background:
      radial-gradient(85% 60% at 84% 72%, rgba(158,58,32,0.30) 0%, rgba(96,32,20,0.12) 34%, transparent 62%),
      radial-gradient(120% 80% at 26% 10%, rgba(64,42,74,0.16) 0%, transparent 52%),
      linear-gradient(to bottom,
        #0a0709 0%, #150b0c 28%, #200f0c 48%, #271410 56%,
        #1a0e0d 59%, #0f0a0b 100%);
  }
  /* Lost World — the plateau at dusk, warm horizon over the jungle */
  .scene-lostworld {
    background:
      radial-gradient(70% 46% at 50% 60%, rgba(240,164,92,0.22) 0%, rgba(196,110,64,0.08) 34%, transparent 62%),
      radial-gradient(120% 80% at 50% 4%, rgba(40,70,86,0.16) 0%, transparent 46%),
      linear-gradient(to bottom,
        #0a1319 0%, #0e1b1b 26%, #14211a 46%, #20291a 56%,
        #14200f 62%, #070d07 100%);
  }
  /* show the active book's scene (one line per book) */
  body.book-odyssey .scene-odyssey { opacity:1; }
  body.book-iliad   .scene-iliad   { opacity:1; }
  body.book-lostworld .scene-lostworld { opacity:1; }

  /* Shared celestial + framing layers sit above both scenes */
  .moon-layer     { position:fixed; inset:0; z-index:1; pointer-events:none; }
  .vignette-layer { position:fixed; inset:0; z-index:2; pointer-events:none; }

  /* ---------- Stars ---------- */
  .stars { position:absolute; inset:0 0 46% 0; opacity:.5; animation:twinkle 9s ease-in-out infinite; }
  .stars::before, .stars::after {
    content:""; position:absolute; inset:0;
    background-image:
      radial-gradient(1px 1px at 12% 20%, #d8e0ea 40%, transparent 42%),
      radial-gradient(1px 1px at 27% 8%,  #aeb9c8 40%, transparent 42%),
      radial-gradient(1.4px 1.4px at 44% 30%, #eef2f6 40%, transparent 42%),
      radial-gradient(1px 1px at 63% 14%, #bcc6d4 40%, transparent 42%),
      radial-gradient(1px 1px at 78% 26%, #d8e0ea 40%, transparent 42%),
      radial-gradient(1.2px 1.2px at 88% 10%, #e6ecf2 40%, transparent 42%),
      radial-gradient(1px 1px at 6% 40%,  #9aa6b6 40%, transparent 42%),
      radial-gradient(1px 1px at 54% 44%, #aeb9c8 40%, transparent 42%);
  }
  .stars::after { transform:translateY(1px); opacity:.6; animation:twinkle 6s ease-in-out infinite reverse; }
  @keyframes twinkle { 0%,100%{opacity:.4} 50%{opacity:.7} }

  /* ---------- Moon (photo with CSS fallback) ---------- */
  /* wrap is sized to the full photo frame; the visible disc fills ~72% of it */
  .moon-wrap { position:absolute; left:50%; top:11%; transform:translateX(-50%); width:150px; height:150px; }
  /* the moon is pure décor — never selectable, draggable, or a pointer/draw target */
  .moon-wrap, .moon-wrap *, .ptero-img { pointer-events:none; user-select:none;
    -webkit-user-select:none; -webkit-user-drag:none; -webkit-touch-callout:none; }
  .moon-halo {
    position:absolute; inset:-230px; border-radius:50%;
    background:radial-gradient(circle,
      rgba(180,198,216,0.26) 0%, rgba(150,172,196,0.11) 26%, rgba(120,140,160,0.04) 48%, transparent 66%);
    animation:breathe 12s ease-in-out infinite;
  }
  /* CSS fallback disc (shown only if the photo fails to load) */
  .moon-fallback {
    position:absolute; inset:0; border-radius:50%;
    background:radial-gradient(circle at 38% 36%, #fff 0%, #e9edee 42%, #c3ccce 72%, #9aa6ab 100%);
    box-shadow:0 0 40px 6px rgba(220,230,235,.32), 0 0 120px 30px rgba(150,170,190,.16);
  }
  /* The real photographic moon — clipped to a clean circle on a canvas in JS,
     so the photo's black field is removed entirely (no blend tricks needed). */
  .moon-canvas {
    position:absolute; inset:0; width:100%; height:100%; display:block; z-index:1;
    filter:drop-shadow(0 0 26px rgba(210,224,235,.40)) drop-shadow(0 0 70px rgba(150,170,190,.22));
  }
  /* single-pixel white pinline riding the disc edge — sells the lit rim / glow */
  .moon-ring {
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    width:62.6%; height:62.6%; border-radius:50%;
    border:1px solid rgba(255,255,255,0.55);
    box-shadow:0 0 6px rgba(255,255,255,0.30), inset 0 0 5px rgba(255,255,255,0.10);
    opacity:0.75;   /* softened pinline */
    z-index:2; pointer-events:none;
  }
  @keyframes breathe { 0%,100%{opacity:.85} 50%{opacity:1} }

  /* ---------- Sea ---------- */
  .sea { position:absolute; left:0; right:0; top:56%; bottom:0; overflow:hidden; }

  /* Wave lines — thin 1px bands with a repeating left→right gradient so only the
     periodic peaks catch the light. Height stays 1px at every depth; peaks drift
     sideways and their opacity ripples downward. Alternate rows are phase-offset. */
  .waves { position:absolute; inset:0; }
  .wave {
    position:absolute; left:-6%; right:-6%; opacity:0;
    -webkit-mask-image:linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
            mask-image:linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
    animation:swell var(--dur,4.5s) ease-in-out infinite var(--delay,0s);
  }
  /* vertical fade keeps only the crests bright (troughs melt away); gentle sway drifts them */
  .wave svg { display:block; width:100%; height:100%;
    -webkit-mask-image:linear-gradient(to bottom, #000 20%, rgba(0,0,0,0.25) 55%, transparent 88%);
            mask-image:linear-gradient(to bottom, #000 20%, rgba(0,0,0,0.25) 55%, transparent 88%);
    animation:wave-drift var(--mdur,22s) ease-in-out infinite var(--mdelay,0s); }
  @keyframes swell { 0%{opacity:0.45} 45%{opacity:1} 100%{opacity:0.45} }
  /* glide the crests left → right → left; each row has its own amount, pace and phase */
  @keyframes wave-drift {
    0%   { transform:translateX(calc(var(--sway,6%) * -1)); }
    50%  { transform:translateX(var(--sway,6%)); }
    100% { transform:translateX(calc(var(--sway,6%) * -1)); }
  }

  /* the shimmering vertical moonglade under the moon */
  .moonglade {
    position:absolute; left:50%; top:0; bottom:0; width:340px; transform:translateX(-50%);
    background:radial-gradient(75% 120% at 50% 0%,
      rgba(196,212,224,0.48) 0%, rgba(180,198,216,0.19) 30%, rgba(180,198,216,0.06) 60%, transparent 82%);
    -webkit-mask-image:radial-gradient(60% 115% at 50% -6%, #000 12%, transparent 72%);
            mask-image:radial-gradient(60% 115% at 50% -6%, #000 12%, transparent 72%);
    filter:blur(3px); mix-blend-mode:screen;
  }
  .glints {
    position:absolute; left:50%; top:0; bottom:0; width:320px; transform:translateX(-50%);
    background-image:repeating-linear-gradient(to bottom,
      transparent 0px, transparent 7px,
      rgba(214,228,236,0.15) 8px, rgba(214,228,236,0.03) 10px, transparent 13px);
    -webkit-mask-image:radial-gradient(52% 105% at 50% -4%, #000 8%, transparent 66%);
            mask-image:radial-gradient(52% 105% at 50% -4%, #000 8%, transparent 66%);
    opacity:.55; filter:blur(1.2px); mix-blend-mode:screen; animation:ripple 7s linear infinite;
  }
  @keyframes ripple { from{background-position-y:0} to{background-position-y:12px} }

  .sea-sheen {
    position:absolute; inset:0; mix-blend-mode:screen;
    background:linear-gradient(105deg, transparent 30%,
      rgba(120,150,180,0.05) 48%, rgba(120,150,180,0.09) 50%, rgba(120,150,180,0.05) 52%, transparent 70%);
    background-size:300% 100%; animation:sheen 26s ease-in-out infinite;
  }
  @keyframes sheen { 0%,100%{background-position:0% 0} 50%{background-position:100% 0} }

  .mist {
    position:absolute; left:0; right:0; top:52%; height:12%;
    background:linear-gradient(to bottom, rgba(120,140,160,0.09), transparent);
    filter:blur(6px); animation:drift 40s ease-in-out infinite;
  }
  @keyframes drift { 0%,100%{transform:translateX(-2%);opacity:.7} 50%{transform:translateX(2%);opacity:1} }

  /* ============================================================
     Lost World — plateau at dusk
     Layer stack (back → front): stars · warm haze · far mesa ·
     near mesa · gliding pterodactyl · canopy ridge · foreground
     jungle · fern fronds. The shared moon still crowns the title.
     ============================================================ */
  .scene-lostworld .stars { opacity:.32; inset:0 0 56% 0; }

  /* warm dusk glow banked along the horizon, behind the plateaus */
  .lw-haze {
    position:absolute; left:0; right:0; top:38%; height:30%;
    background:radial-gradient(58% 100% at 50% 64%,
      rgba(244,168,96,0.24), rgba(210,118,68,0.08) 46%, transparent 74%);
    filter:blur(10px); pointer-events:none;
    animation:breathe 14s ease-in-out infinite;
  }
  /* the plateau */
  .lw-mesa { position:absolute; left:-2%; width:104%; pointer-events:none; }
  /* long, thin, staggered dusk cloud layers — soft, semi-opaque, slow drift */
  .lw-cloud { position:absolute; pointer-events:none; border-radius:50%;
    background:linear-gradient(to right, transparent, rgba(150,168,194,0.9) 26%, rgba(150,168,194,0.9) 74%, transparent);
    filter:blur(9px); }
  /* one-directional, VERY slow left→right drift; each wraps off-screen so the loop is
     seamless. Staggered sizes + negative delays keep the sky varied. */
  .lw-cloud-1 { left:0; top:21%; width:48%; height:3.4vh; opacity:.28; animation:cloud-cross 680s linear -120s infinite; }
  .lw-cloud-2 { left:0; top:29%; width:36%; height:2.8vh; opacity:.20; animation:cloud-cross 840s linear -430s infinite; }
  .lw-cloud-3 { left:0; top:15%; width:30%; height:2.4vh; opacity:.16; animation:cloud-cross 560s linear -260s infinite; }
  @keyframes cloud-cross { from { transform:translateX(-74vw); } to { transform:translateX(160vw); } }
  /* THE plateau — sheer flat-topped cliff. Its summit sits BELOW the title (the rim
     must never cut through the lettering); a faint moonlit glow lifts it off the sky. */
  .lw-mesa-near { bottom:24%; height:37vh; color:#1a0d0a;
                  filter:drop-shadow(0 -2px 24px rgba(138,168,212,0.12)); }
  /* the plateau's red-earth mass continues to the foot of the screen, behind the jungle */
  .lw-base { position:absolute; left:0; right:0; bottom:0; height:44%; z-index:0; pointer-events:none;
             background:linear-gradient(to bottom, transparent 0%, rgba(28,14,10,0.72) 22%, #170b08 56%, #0c0605 100%); }

  /* cool mist band between the plateau base and the jungle — softens the layering */
  .lw-mist {
    position:absolute; left:-4%; right:-4%; bottom:16%; height:20%;
    background:radial-gradient(120% 100% at 50% 100%,
      rgba(150,172,200,0.16), rgba(120,140,170,0.06) 46%, transparent 76%);
    filter:blur(16px); z-index:1; pointer-events:none;
    animation:drift 46s ease-in-out infinite;
  }
  /* Depth ladder: nearest = darkest, farther = lighter greys (tints baked into the
     webp masks). Each silhouette shows its OWN solid base down to the bottom (no crop
     line), and its base is masked to melt into the dark ground — no harsh seams. */
  /* Tile horizontally at natural proportions — repeat, never stretch, on wide windows.
     background-size:auto 100% keeps the tree aspect (height fills, width follows). */
  .lw-canopy { position:absolute; left:0; bottom:19%; width:100%; height:16vh; z-index:1; opacity:.88;
               background:url(../shared/assets/lostworld-canopy.webp) repeat-x center bottom / auto 100%;
               -webkit-mask-image:linear-gradient(to bottom, #000 62%, transparent);
               mask-image:linear-gradient(to bottom, #000 62%, transparent); }
  /* dense foreground jungle — real tropical silhouette, solid base to the bottom */
  .lw-fore { position:absolute; left:0; bottom:0; width:100%; height:30vh; z-index:2;
             background:url(../shared/assets/lostworld-foreground.webp) repeat-x center bottom / auto 100%;
             -webkit-mask-image:linear-gradient(to bottom, #000 78%, rgba(0,0,0,0.86));
             mask-image:linear-gradient(to bottom, #000 78%, rgba(0,0,0,0.86)); }
  .lw-frond { position:absolute; bottom:-12px; width:min(30vw,260px); height:auto;
              color:#02150c; z-index:3; opacity:.96;
              filter:drop-shadow(0 0 14px rgba(0,0,0,.5)); }
  .lw-frond-l { left:-2%; transform:rotate(-3deg); transform-origin:bottom left; }
  .lw-frond-r { right:-2%; transform:rotate(3deg); transform-origin:bottom right; }

  /* pterodactyl — a RARE, quick flyby, ABOVE the moon (z-index:3 > moon 1, < UI 5) so it
     drifts in FRONT of the moon and the plateau. Right → left with a gentle, monotonic
     descent (no swoop): high past the moon, lower toward the plateau as it exits. */
  /* ONE straight, constant-speed pass: transform is keyed only at the two ends, so it
     interpolates as a single linear segment — no midpoint, no slowing at the moon.
     linear timing = even speed the whole way across; then it waits off-screen. */
  /* The bird lives ABOVE the scene stacking context (to pass in front of the moon), so
     .scene-lostworld's opacity no longer hides it on other books — scope it explicitly. */
  .ptero-track { display:none; position:fixed; top:0; left:0; width:88px; z-index:3;
                 animation:ptero-flyby 50s linear 2s infinite both; }
  body.book-lostworld .ptero-track { display:block; }
  @keyframes ptero-flyby {
    0%    { transform: translate(114vw, 14vh) scale(0.6); opacity:0; }   /* off right */
    1.5%  { opacity:1; }
    16.5% { opacity:1; }
    18%   { transform: translate(-30vw, 20vh) scale(0.6); opacity:0; }   /* off left — crossed */
    100%  { transform: translate(-30vw, 20vh) scale(0.6); opacity:0; }   /* wait, off-screen */
  }
  /* a gentle nose-down glide tilt */
  .ptero { position:relative; width:88px; transform-origin:50% 50%; transform:rotate(-4deg);
           filter:drop-shadow(0 4px 8px rgba(0,0,0,.5)); }
  /* faked wing-beat: a slow horizontal sweep narrows the wingspan on the downstroke
     (reads as flapping for a bird seen from below) — gentle so it never looks mechanical.
     ptero-backlit shares the flyby's 50s/2s/linear clock: as the bird crosses the bright
     moon (~8% of the pass) it darkens to a full black silhouette, then returns to
     moonlit grey against the night sky. */
  .ptero-img { display:block; width:100%; height:auto; transform-origin:50% 45%;
               animation:ptero-flap 2.6s ease-in-out infinite,
                         ptero-backlit 50s linear 2s infinite both; }
  @keyframes ptero-backlit {
    0%, 6%    { filter:brightness(1); }     /* grey against the sky */
    7.4%, 8.7%{ filter:brightness(0); }     /* black, in front of the moon */
    10%, 100% { filter:brightness(1); }     /* grey again */
  }
  @keyframes ptero-flap {
    0%,100% { transform:scaleX(1)    scaleY(1); }
    50%     { transform:scaleX(0.9)  scaleY(1.06); }
  }

  /* ---------- The ship ---------- */
  /* The ship drifts diagonally: in from the left horizon, across and down to the
     lower-right, then reverses back up to the left — flipping to face each heading.
     A gentle rock (no oar-rowing) makes it read as drifting. Scale sells depth. */
  /* The -432s delay is load-bearing: it starts the cycle exactly on the 12% keyframe, so
     the FIRST thing you see is the ship standing on the horizon in the upper-left third,
     alongside the title. The 12%/88% pair gives it a horizon dwell to sit in — without
     them the path descends too steeply for "left third" and "on the horizon" to ever
     coincide. Sea starts at 56vh; the hull rides just into the mist band above it. */
  .ship-track { position:absolute; top:0; left:0; width:300px; animation:drift 3600s linear -432s infinite; }
  @keyframes drift {
    0%   { transform: translate(calc(-4vw - 220px), 44vh) scale(0.68); } /* off left, at the horizon  */
    12%  { transform: translate(2vw, calc(50vh - 92px)) scale(0.82); }   /* left third, on the horizon */
    50%  { transform: translate(calc(100vw + 60px), 82vh) scale(1.62); } /* off lower-right, near      */
    88%  { transform: translate(2vw, calc(50vh - 92px)) scale(0.82); }   /* back through the horizon  */
    100% { transform: translate(calc(-4vw - 220px), 44vh) scale(0.68); }
  }
  .ship { position:relative; width:300px; transform-origin:50% 50%;
          animation:ship-orient 3600s linear -432s infinite;
          filter:drop-shadow(0 8px 14px rgba(0,0,0,.55)); }
  /* face right on the way down, flip to face left on the way back — flip happens
     at the corners while the ship is off-screen. Gentle sway = drifting. */
  @keyframes ship-orient {
    0%    { transform: scaleX(-1) rotate(-0.8deg); }
    25%   { transform: scaleX(-1) rotate(0.9deg); }
    49.9% { transform: scaleX(-1) rotate(-0.3deg); }
    50%   { transform: scaleX(1)  rotate(-0.8deg); }
    75%   { transform: scaleX(1)  rotate(0.9deg); }
    100%  { transform: scaleX(1)  rotate(-0.8deg); }
  }
  .ship svg { display:block; width:100%; height:auto; }
  /* photographic longship, darkened to sit in the moonlit night */
  .ship-photo { display:block; width:100%; height:auto;
    filter:brightness(0.52) contrast(1.05) saturate(0.82); }
  /* dark overlay clipped to the ship's silhouette — deepens it into the night */
  .ship::after {
    content:''; position:absolute; inset:0; pointer-events:none;
    background:rgba(6,10,20,0.55);
    -webkit-mask-image:url('assets/odysseus-ship.png?v=20260721a'); mask-image:url('assets/odysseus-ship.png?v=20260721a');
    -webkit-mask-size:100% 100%; mask-size:100% 100%;
    -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
    /* fades out near the horizon (moonlit), deepens as the ship nears — synced to drift */
    animation:ship-shade 3600s linear -900s infinite;
  }
  @keyframes ship-shade {
    0%   { opacity:0.08; }   /* at the horizon — the moon lights it more strongly */
    50%  { opacity:1; }      /* near the viewer — deeper shadow */
    100% { opacity:0.08; }
  }
  .oars { animation:row 4.5s ease-in-out infinite; transform-box:fill-box; transform-origin:50% 0%; }
  @keyframes row { 0%,100%{transform:rotate(-4deg)} 50%{transform:rotate(6deg)} }
  .ship-reflection { margin-top:-4px; transform:scaleY(-0.5); opacity:.16; filter:blur(1.5px);
    -webkit-mask-image:linear-gradient(to bottom,#000,transparent 70%);
            mask-image:linear-gradient(to bottom,#000,transparent 70%); }

  /* =============================================================
     Iliad — Trojan shore at night
     ============================================================= */
  .stars-warm::before, .stars-warm::after { filter:sepia(.5) hue-rotate(-18deg) saturate(1.2) brightness(.95); }

  /* dark sea between horizon and beach, faintly catching moon + embers */
  .troy-sea { position:absolute; left:0; right:0; top:56%; height:23%; overflow:hidden;
    background:linear-gradient(to bottom, #1c1113 0%, #140d0f 55%, #0d0a0b 100%); }
  .troy-shimmer { position:absolute; inset:0;
    background:
      radial-gradient(46% 120% at 50% 0%, rgba(196,212,224,0.16) 0%, transparent 70%),   /* cool moon glade */
      radial-gradient(60% 120% at 86% 0%, rgba(180,80,44,0.18) 0%, transparent 68%);      /* warm ember glow */
    -webkit-mask-image:linear-gradient(to bottom,#000, transparent 92%);
            mask-image:linear-gradient(to bottom,#000, transparent 92%);
    filter:blur(2px); animation:sheen 30s ease-in-out infinite; }

  /* the sand */
  .troy-beach { position:absolute; left:0; right:0; bottom:0; height:23%;
    background:linear-gradient(to bottom, #2c1d15 0%, #221610 42%, #180f0b 100%); }
  /* ocean lapping the sand — a soft foam line that advances and recedes */
  .troy-foam { position:absolute; left:-5%; right:-5%; top:-7px; height:18px;
    background:linear-gradient(to bottom, rgba(214,196,184,0.22), rgba(214,196,184,0.05) 55%, transparent);
    filter:blur(3px); animation:lap 9s ease-in-out infinite; }
  .troy-foam.two { top:-2px; opacity:.6; animation-duration:12s; animation-delay:-3s; }
  @keyframes lap { 0%,100%{transform:translateY(0); opacity:.55} 50%{transform:translateY(7px); opacity:1} }

  /* walls of Troy — a tall pillar flush to the right edge; base bleeds off-bottom */
  .troy-walls { position:absolute; right:0; bottom:-8%; width:clamp(140px, 18vw, 300px); height:auto;
    filter:drop-shadow(-8px 0 24px rgba(0,0,0,.5)); }
  .troy-walls svg { width:100%; height:auto; display:block; }

  /* the Trojan horse, standing peacefully on the shore */
  /* anchor to the LEFT edge, then pull left by a fraction of the horse's OWN width
     (translateX % is element-relative) so a consistent slice stays on-screen at any
     window width — a viewport-% left offset bleeds off entirely on wide monitors. */
  .trojan-horse { position:absolute; left:0; bottom:-4%; height:68vh; max-height:760px;
    transform:translateX(-46%);
    filter:drop-shadow(8px 8px 18px rgba(0,0,0,.55)); }
  .trojan-horse svg { height:100%; width:auto; display:block; }
  /* woodcut horse (black on transparent): lift the blacks to a warm dark wood so
     the silhouette reads against the near-black sand instead of vanishing into it. */
  /* darker, recessive silhouette — just enough lift to separate from the sand,
     no more. The horse stays static; only the ship moves. */
  /* the horse itself stays black; a dark dark-brown backlight rim is the only
     separation from the sand. */
  .horse-photo { height:100%; width:auto; display:block;
    filter:drop-shadow(0 0 3px rgba(74,46,24,0.85))
           drop-shadow(0 0 12px rgba(52,33,17,0.55)); }

  /* sea birds — loose gull flocks drifting across on occasion */
  .birds { position:absolute; inset:0 0 34% 0; pointer-events:none; overflow:hidden; }
  .flock { position:absolute; left:0; top:0; width:210px; height:130px; opacity:0; animation:flyflock linear infinite; }
  .gull  { position:absolute; }
  .gull svg { display:block; width:100%; height:auto; animation:flap var(--f,.55s) ease-in-out infinite; transform-origin:50% 42%; }
  @keyframes flyflock {
    0%   { transform:translate(-24vw, 30vh); opacity:0; }
    12%  { opacity:.6; }
    88%  { opacity:.6; }
    100% { transform:translate(122vw, 5vh);  opacity:0; }
  }
  @keyframes flap { 0%,100%{transform:scaleY(1)} 50%{transform:scaleY(.5)} }

  /* ---------- Cinematic vignette ---------- */
  .vignette { position:absolute; inset:0; pointer-events:none;
    background:radial-gradient(120% 90% at 50% 42%, transparent 55%, rgba(0,0,0,0.6) 100%); }

  /* =============================================================
     App chrome over the scene — floating conversation column
     ============================================================= */
  .app { position:fixed; inset:0; z-index:5; display:flex; flex-direction:column; }

  /* Top bar: wordmark · book switcher · checked-out status */
  .topbar { display:flex; align-items:center; justify-content:flex-start; gap:24px;
    padding:18px 26px; }
  .brand { display:inline-flex; align-items:center; gap:12px; color:var(--gold-400);
    font-family:var(--font-display); font-size:12px; letter-spacing:var(--tracking-widest); white-space:nowrap; }
  .brand::before { content:''; width:26px; height:1px; background:var(--grad-gold-horizontal); opacity:.7; }

  .switcher { display:inline-flex; align-items:center; gap:6px; }
  .book-tab { font-family:var(--font-display); text-transform:uppercase; letter-spacing:var(--tracking-wider);
    /* 9/7 top/bottom (not 8/8): the uppercase display font sits ~1px high, so this nudges the
       glyphs down to sit optically centred without changing the button's height. */
    font-size:13px; padding:9px 16px 7px; border-radius:var(--r-md); cursor:pointer; white-space:nowrap;
    display:inline-flex; align-items:center;
    background:transparent; border:1px solid transparent; color:var(--parchment-200); transition:all .18s ease; }
  .book-tab[aria-selected="true"] { color:var(--gold-100); border-color:var(--border-strong);
    background:rgba(212,162,83,0.06); box-shadow:var(--glow-gold); }
  .book-tab:hover { color:var(--parchment-100); }
  /* occupancy lock — a small grey padlock that fades in when another explorer holds the
     book, and clears (width→0) the moment it frees. Stays grey even on the selected tab. */
  .book-tab .bt-lock { flex:none; width:0; height:11px; margin-left:0; color:var(--parchment-300);
    opacity:0; transition:opacity .28s ease, width .28s ease, margin-left .28s ease; }
  .book-tab.locked .bt-lock { width:11px; margin-left:6px; opacity:.7; }

  /* Book-state chip — colour + text driven by data-state (single-tenant lock) */
  .status-chip {
    --sc-border:rgba(107,138,181,0.4); --sc-color:#9FB6D8; --sc-bg:rgba(107,138,181,0.08); --sc-dot:#6B8AB5;
    position:relative; display:inline-flex; align-items:center; gap:7px; padding:5px 12px; border-radius:var(--r-pill);
    font-family:var(--font-mono); font-size:10px; letter-spacing:0.1em; white-space:nowrap;
    border:1px solid var(--sc-border); color:var(--sc-color); background:var(--sc-bg);
    transition:color .35s ease, border-color .35s ease, background .35s ease; }
  /* subtle moonlight sheen on the pin line, brightest at the lower-left edge */
  .status-chip::before {
    content:''; position:absolute; inset:0; border-radius:inherit; padding:1px; pointer-events:none;
    background:linear-gradient(to top right, rgba(224,233,244,0.5) 0%, rgba(224,233,244,0.08) 42%, rgba(224,233,244,0) 60%);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor; mask-composite:exclude; }
  .status-chip[data-state="available"]   { --sc-border:rgba(111,168,136,0.45); --sc-color:#9FD1B6; --sc-bg:rgba(111,168,136,0.09); --sc-dot:#6FA888; cursor:pointer; }
  .status-chip[data-state="available"]:hover { --sc-bg:rgba(111,168,136,0.18); --sc-border:rgba(111,168,136,0.6); box-shadow:0 0 14px rgba(111,168,136,0.22); }
  .status-chip[data-state="available"]:active { transform:translateY(1px); }
  .status-chip[data-state="available"]:focus-visible { outline:none; box-shadow:0 0 0 3px rgba(111,168,136,0.32); }
  .status-chip[data-state="soon"]        { --sc-border:var(--border-strong);     --sc-color:var(--gold-200); --sc-bg:rgba(212,162,83,0.08); --sc-dot:var(--gold-400); }
  .status-chip[data-state="unavailable"] { --sc-border:rgba(185,74,72,0.5);       --sc-color:#E08280; --sc-bg:rgba(185,74,72,0.09); --sc-dot:#B94A48; }
  .status-chip[data-state="engaged"]     { --sc-border:rgba(107,138,181,0.45);    --sc-color:#9FB6D8; --sc-bg:rgba(107,138,181,0.09); --sc-dot:#6B8AB5; cursor:pointer; }
  /* the engaged chip is clickable → "put the book down"; hint it on hover */
  .status-chip[data-state="engaged"]:hover, .status-chip[data-state="soon"]:hover {
    --sc-bg:rgba(107,138,181,0.16); --sc-border:rgba(107,138,181,0.62); box-shadow:0 0 14px rgba(107,138,181,0.18); }
  .status-chip[data-state="soon"] { cursor:pointer; }
  .status-chip .dot { flex:none; width:6px; height:6px; border-radius:50%; background:var(--sc-dot);
    box-shadow:0 0 8px var(--sc-dot); animation:pulse 3.2s ease-in-out infinite; }
  .status-chip .who { display:inline-block; max-width:170px; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; vertical-align:bottom; }
  .status-chip .sep { opacity:.55; margin:0 5px; }
  .status-chip .timer { font-variant-numeric:tabular-nums; letter-spacing:0.06em; }
  /* queue-depth cue shown to the engaged reader — implies extensions are paused while others wait */
  .status-chip .waiting { color:var(--gold-200); font-variant-numeric:tabular-nums; white-space:nowrap; }
  .status-chip .waiting::before { content:'·'; color:currentColor; opacity:.55; margin:0 6px; }
  .status-chip .waiting svg { width:10px; height:10px; vertical-align:-1px; margin-right:3px; opacity:.9; }
  @keyframes pulse { 0%,100%{opacity:.5} 50%{opacity:1} }

  /* right cluster: checked-out status + feedback button (far right) */
  .topbar-right { display:inline-flex; align-items:center; gap:12px; margin-left:auto; }
  .feedback-btn { position:relative; display:inline-flex; align-items:center; justify-content:center;
    width:32px; height:32px; border-radius:var(--r-pill); border:1px solid var(--border);
    background:transparent; color:var(--gold-200); cursor:pointer; transition:all .16s ease; }
  .feedback-btn svg { width:16px; height:16px; }
  .feedback-btn:hover { border-color:var(--border-strong); background:rgba(212,162,83,0.08);
    color:var(--gold-100); box-shadow:var(--glow-gold); }           /* brighter gold on hover */
  .feedback-btn:active { transform:translate(-1px,-1px); }          /* subtle nudge on click */
  /* hover tooltip */
  .feedback-btn::after {
    content:attr(data-tip); position:absolute; top:calc(100% + 9px); right:0;
    background:var(--ink-700); color:var(--parchment-100); border:1px solid var(--border);
    border-radius:var(--r-md); padding:6px 10px; font-family:var(--font-sans); font-size:11px;
    letter-spacing:0.03em; text-transform:none; white-space:nowrap; box-shadow:var(--shadow-md);
    opacity:0; transform:translateY(-4px); pointer-events:none; transition:opacity .16s ease, transform .16s ease; }
  .feedback-btn:hover::after, .feedback-btn:focus-visible::after { opacity:1; transform:translateY(0); }

  /* "Restore prior conversation" — a subtle floating pill under the header on a clean
     hero when this explorer has a saved thread. Opt-in, never auto-restored. */
  .restore-pill { position:fixed; top:70px; left:50%; transform:translateX(-50%); z-index:40;
    display:inline-flex; align-items:center; gap:8px; padding:8px 15px; border-radius:var(--r-pill);
    font-family:var(--font-sans); font-size:12px; letter-spacing:0.03em; cursor:pointer; color:var(--gold-100);
    border:1px solid var(--border-strong);
    background:linear-gradient(180deg, rgba(18,21,33,0.94), rgba(11,13,20,0.94));
    box-shadow:0 10px 34px rgba(0,0,0,0.5), 0 0 18px rgba(212,162,83,0.12);
    -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
    animation:restore-in .3s ease; transition:border-color .18s ease, box-shadow .2s ease; }
  .restore-pill:hover { box-shadow:0 10px 34px rgba(0,0,0,0.55), 0 0 26px rgba(212,162,83,0.24); }
  .restore-pill:active { transform:translate(-50%,1px); }
  .restore-pill svg { width:14px; height:14px; opacity:.9; flex:none; }
  .restore-pill em { font-style:normal; font-size:10px; opacity:.75; background:rgba(212,162,83,0.14);
    border-radius:99px; padding:1px 7px; }
  @keyframes restore-in { from { opacity:0; transform:translate(-50%,-8px); } to { opacity:1; transform:translate(-50%,0); } }
  @media (max-width:640px) { .restore-pill { top:60px; font-size:11px; padding:7px 13px; } }

  /* Thread — floating centered column, scene visible around it */
  .thread-area { position:relative; flex:1; display:flex; min-height:0; }
  .thread-wrap { flex:1; overflow-y:auto; display:flex; justify-content:center;
    scrollbar-width:none; }                               /* native bar hidden; we draw our own */
  .thread-wrap::-webkit-scrollbar { width:0; height:0; }
  /* jump-to-top / jump-to-latest icons at the ends of the scrollbar */
  .cscroll-top, .cscroll-bottom { position:absolute; right:0; width:20px; height:20px; border-radius:50%;
    display:flex; align-items:center; justify-content:center; border:1px solid var(--border);
    background:rgba(11,13,20,0.78); color:var(--gold-200); cursor:pointer; z-index:7;
    opacity:0; transform:scale(.88); pointer-events:none;
    transition:opacity .25s ease, transform .2s ease, color .18s ease, border-color .18s ease; }
  .cscroll-top { top:8px; } .cscroll-bottom { bottom:8px; }
  .cscroll-top.show, .cscroll-bottom.show { opacity:1; transform:scale(1); pointer-events:auto; }
  .cscroll-top:hover, .cscroll-bottom:hover { color:var(--gold-100); border-color:var(--border-strong); box-shadow:var(--glow-gold); }
  .cscroll-top:active { transform:translateY(-1px); } .cscroll-bottom:active { transform:translateY(1px); }
  .cscroll-top svg, .cscroll-bottom svg { width:12px; height:12px; }
  /* custom always-visible scrollbar (track sits between the two end icons) */
  .cscroll { position:absolute; top:38px; bottom:38px; right:6px; width:8px; border-radius:99px;
    background:rgba(255,255,255,0.05); opacity:0; transition:opacity .25s ease; pointer-events:none; z-index:6; }
  .cscroll.show { opacity:1; pointer-events:auto; }
  .cscroll-thumb { position:absolute; left:0; right:0; top:0; min-height:30px; border-radius:99px;
    background:rgba(212,162,83,0.5); cursor:grab; transition:background .18s ease; }
  .cscroll-thumb:hover { background:rgba(212,162,83,0.75); }
  .cscroll.dragging .cscroll-thumb { background:rgba(212,162,83,0.9); cursor:grabbing; }
  .thread { width:100%; max-width:664px; padding:8px 24px 12px; display:flex; flex-direction:column; gap:20px; }

  /* Poster stack: the moon crowns the header, so clear its zone before the title.
     The whole block is pinned (sticky) so its space never scrolls — scrolling just
     fades it out; once faded it releases and everything scrolls off. */
  .title-lockup { text-align:center; margin:0 0 3.5vh; display:flex; flex-direction:column; align-items:center; gap:0;
    padding-top:calc(clamp(184px, 27vh, 268px) - 40px);
    position:sticky; top:0; pointer-events:none; will-change:opacity; }
  .lk-head { display:flex; flex-direction:column; align-items:center; }
  .lk-body { display:flex; flex-direction:column; align-items:center; }
  .title-lockup .t { font-family:var(--font-display); text-transform:uppercase; letter-spacing:var(--tracking-wider);
    font-size:clamp(30px,5vw,52px); color:var(--fg-display); line-height:1; white-space:nowrap;
    text-shadow:0 2px 40px rgba(0,0,0,.6); }
  /* the rule under the title */
  .title-lockup .divide { width:min(250px,54%); height:1px; opacity:.85; margin:20px 0 17px;
    background:linear-gradient(90deg,
      transparent 0%, rgba(212,162,83,0.12) 20%, var(--gold-400) 50%, rgba(212,162,83,0.12) 80%, transparent 100%); }
  /* author credit — refined serif, tracked caps */
  /* the lockup can overhang the moonlit horizon; a soft dark halo keeps the
     provenance + invitation legible where they cross the bright sea sheen */
  .title-lockup .author,
  .title-lockup .date,
  .title-lockup .edition,
  .title-lockup .s { text-shadow:0 1px 3px rgba(5,6,10,.92), 0 0 18px rgba(5,6,10,.72); }
  .title-lockup .author { font-family:var(--font-serif); font-weight:500; text-transform:uppercase;
    letter-spacing:0.22em; font-size:clamp(15px,1.9vw,19px); color:var(--parchment-100); }
  /* date written, and the edition being read — same quiet italic serif, each set off
     by its own break so the provenance has room to breathe */
  .title-lockup .date,
  .title-lockup .edition { font-family:var(--font-serif); font-style:italic; font-size:15px;
    letter-spacing:0.02em; color:var(--parchment-300); }
  .title-lockup .date    { margin-top:16px; }
  .title-lockup .edition { margin-top:10px; }
  /* the invitation — kept just clear of the horizon so it doesn't land on the sheen */
  .title-lockup .s { font-family:var(--font-serif); font-style:italic; color:var(--parchment-100);
    font-size:18px; margin-top:24px; }
  /* entrance choreography: title → Homer → rule → date → prompt, staggered */
  .title-lockup .t      { animation:lk-reveal .8s ease .20s backwards; }
  .title-lockup .author { animation:lk-reveal .8s ease .55s backwards; }
  .title-lockup .divide { animation:lk-draw   .7s ease .90s backwards; transform-origin:center; }
  .title-lockup .date    { animation:lk-reveal .8s ease 1.20s backwards; }
  .title-lockup .edition { animation:lk-reveal .8s ease 1.38s backwards; }
  .title-lockup .s       { animation:lk-reveal .8s ease 1.66s backwards; }
  @keyframes lk-reveal { from { opacity:0; transform:translateY(9px); } to { opacity:1; transform:none; } }
  @keyframes lk-draw   { from { opacity:0; transform:scaleX(0.15); } to { opacity:.85; transform:scaleX(1); } }

  .msg { max-width:82%; display:flex; flex-direction:column; }
  .msg .who { font-size:10px; letter-spacing:0.2em; text-transform:uppercase; margin-bottom:7px; color:var(--parchment-300); }
  .msg-book { align-self:flex-start; }
  .msg-book .who { color:var(--gold-400); }
  .msg-book .bubble { font-family:var(--font-serif); font-size:19px; line-height:1.62; color:var(--parchment-100);
    background:linear-gradient(180deg, rgba(18,21,33,0.74), rgba(11,13,20,0.74));
    border:1px solid var(--border); border-left:2px solid var(--gold-700); border-radius:var(--r-md);
    padding:16px 20px; -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px); box-shadow:var(--shadow-md); }
  /* markdown range within a book reply — headers, emphasis, lists, quotes, code */
  .msg-book .bubble > :first-child { margin-top:0; }
  .msg-book .bubble > :last-child  { margin-bottom:0; }
  .msg-book .bubble p { margin:0 0 .7em; }
  .msg-book .bubble h1 { font-family:var(--font-serif); font-weight:600; font-size:1.22em; line-height:1.2;
    color:var(--fg-display); margin:.1em 0 .45em; }
  .msg-book .bubble h2 { font-family:var(--font-serif); font-weight:600; font-size:1.08em; line-height:1.25;
    color:var(--gold-200); margin:.2em 0 .4em; }
  .msg-book .bubble h3 { font-family:var(--font-sans); font-weight:700; font-size:.98em; line-height:1.3;
    color:var(--gold-200); margin:.7em 0 .3em; }
  .msg-book .bubble h4 { font-family:var(--font-sans); font-weight:600; font-size:.9em; line-height:1.3;
    color:var(--parchment-200); margin:.6em 0 .25em; }
  .msg-book .bubble strong, .msg-book .bubble b { color:var(--fg-display); font-weight:600; }
  .msg-book .bubble em, .msg-book .bubble i { font-style:italic; }
  .msg-book .bubble ul, .msg-book .bubble ol { margin:.35em 0 .7em; padding-left:1.5em; }
  .msg-book .bubble li { margin:.28em 0; padding-left:.15em; }
  .msg-book .bubble li::marker { color:var(--gold-400); }
  /* nested lists sit tight under their parent item */
  .msg-book .bubble li > ul, .msg-book .bubble li > ol { margin:.28em 0 .35em; }
  .msg-book .bubble blockquote { border-left:2px solid var(--border-strong); margin:.5em 0; padding-left:.9em;
    color:var(--parchment-200); font-style:italic; }
  .msg-book .bubble hr { border:0; border-top:1px solid var(--border); margin:.9em 0; }
  .msg-book .bubble code { font-family:var(--font-mono); font-size:.82em; background:rgba(255,255,255,0.06);
    padding:.1em .35em; border-radius:3px; color:var(--gold-100); }
  .msg-book .bubble pre { margin:.5em 0 .7em; padding:.7em .9em; overflow-x:auto; border-radius:var(--r-md);
    background:rgba(0,0,0,0.28); border:1px solid var(--border-muted); }
  .msg-book .bubble pre code { display:block; background:none; padding:0; color:var(--parchment-100);
    font-size:.8em; line-height:1.5; white-space:pre; }
  .msg-book .bubble a { color:var(--gold-200); text-underline-offset:2px; }
  /* GFM tables — the prose is serif, but tabular DATA is set in Lato (sans) so it scans.
     Clean style: horizontal rules only (no vertical grid), subtle zebra, gold header;
     scrolls horizontally on narrow screens so a wide table never breaks the bubble. */
  .msg-book .bubble .md-table { margin:.7em 0 .9em; overflow-x:auto; -webkit-overflow-scrolling:touch;
    border:1px solid var(--border); border-radius:var(--r-md); }
  .msg-book .bubble table { border-collapse:collapse; width:100%;
    font-family:'Lato', var(--font-sans); font-size:.86em; line-height:1.45; }
  .msg-book .bubble th, .msg-book .bubble td { padding:8px 13px; text-align:left; vertical-align:top; }
  .msg-book .bubble thead th { background:rgba(212,162,83,0.07); color:var(--gold-100);
    font-weight:700; font-size:.95em; letter-spacing:.01em; white-space:nowrap;
    border-bottom:1px solid var(--border-strong); }
  .msg-book .bubble tbody td { border-top:1px solid var(--border-muted); color:var(--parchment-100); }
  .msg-book .bubble tbody tr:first-child td { border-top:0; }
  .msg-book .bubble tbody tr:nth-child(even) td { background:rgba(255,255,255,0.02); }
  .msg-book .bubble tbody td:first-child { color:var(--parchment-50); }   /* row label reads brighter */
  .msg-me { align-self:flex-end; }
  .msg-me .who { align-self:flex-end; color:var(--parchment-300); }
  .msg-me .bubble { font-family:'Lato', var(--font-sans); font-weight:300; font-size:15px; line-height:1.6; color:var(--parchment-100);
    background:rgba(26,30,46,0.5); border:1px solid var(--border-muted); border-radius:var(--r-md);
    padding:12px 16px; -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px); }

  /* the book "thinking" — three drifting gold points */
  .typing { display:inline-flex; gap:6px; padding:4px 2px; }
  .typing i { width:6px; height:6px; border-radius:50%; background:var(--gold-400); opacity:.4;
    animation:think 1.3s ease-in-out infinite; }
  .typing i:nth-child(2){ animation-delay:.18s } .typing i:nth-child(3){ animation-delay:.36s }
  @keyframes think { 0%,100%{opacity:.25; transform:translateY(0)} 50%{opacity:1; transform:translateY(-3px)} }
  /* "wait here" — a big friendly clock, tabular so the digits don't jitter as they tick */
  .wl-clock { font-family:var(--font-serif); font-weight:600; font-size:clamp(48px,12vw,76px);
    line-height:1.05; letter-spacing:0.02em; color:var(--gold-100); margin:0 0 18px;
    font-variant-numeric:tabular-nums; text-shadow:0 0 28px rgba(226,186,95,0.20); }
  /* label above the clock, and the queue line beneath it */
  /* the lead already carries 22px beneath it — don't stack another 18 on top of that */
  .wl-clock-label { font-family:var(--font-sans); font-size:11px; letter-spacing:0.18em;
    text-transform:uppercase; color:var(--gold-400); margin-top:2px; }
  .wl-queue { font-family:var(--font-serif); font-style:italic; font-size:15px;
    color:var(--parchment-200); margin:0 0 6px; }
  /* when the wait length isn't known, words instead of a giant empty clock face */
  .wl-clock.wl-clock-soft { font-size:clamp(22px,5vw,32px); font-style:italic; letter-spacing:0.01em;
    color:var(--gold-200); opacity:.9; text-shadow:none; }
  /* the waitlist ask — a question, so it carries a touch more weight than fine print */
  /* slow-response reassurance (ERR-7) — grounding on the whole poem takes ~10s+ */
  .typing-note { display:block; margin-top:2px; line-height:1.4; font-family:var(--font-sans);
    font-size:12px; letter-spacing:.04em; color:var(--parchment-300); font-style:italic; }
  /* retry affordance on a failed reply (ERR-1/ERR-4) — compact, not a full-width modal button */
  .msg-book .bubble .retry-btn { display:inline-block; width:auto; margin:.5em 0 0; padding:4px 10px;
    font-size:13px; border:1px solid var(--border); border-radius:var(--r-md); color:var(--gold-200); }
  .msg-book .bubble .retry-btn:hover { border-color:var(--border-strong); background:rgba(212,162,83,0.08); }

  /* GB-1 taste — preset questions, answered from pre-generated text. Sits above the
     composer so a visitor with no session still gets proof before the email gate. */
  .taste { width:100%; max-width:664px; box-sizing:border-box; padding:0 4px 12px;
    animation:fade-in .6s ease both; }
  .taste-label { font-family:var(--font-sans); font-size:10px; letter-spacing:0.2em;
    text-transform:uppercase; color:var(--gold-400); opacity:.8; margin-bottom:8px; }
  .taste-btns { display:flex; flex-wrap:wrap; gap:8px; }
  .taste-btn { font-family:var(--font-serif); font-style:italic; font-size:14px;
    color:var(--parchment-100); background:rgba(255,255,255,0.035); cursor:pointer;
    border:1px solid var(--border); border-radius:var(--r-pill); padding:7px 14px;
    transition:border-color .18s ease, background .18s ease, color .18s ease; }
  .taste-btn:hover { border-color:var(--border-strong); background:rgba(212,162,83,0.09);
    color:var(--fg-display); }
  .taste-btn[disabled] { opacity:.38; cursor:default; }
  .taste-ask { font-family:var(--font-serif); font-style:italic; font-size:15px;
    color:var(--parchment-200); margin:14px 0 0; }
  .taste-cta { font-family:var(--font-sans); font-size:11px; letter-spacing:0.14em;
    text-transform:uppercase; font-weight:600; color:var(--ink-900); cursor:pointer;
    background:linear-gradient(180deg, var(--gold-100), var(--gold-400));
    border:none; border-radius:var(--r-md); padding:7px 14px; margin-left:8px;
    vertical-align:baseline; }
  .taste-cta:hover { filter:brightness(1.06); }
  @media (max-width:560px) { .taste-cta { display:block; margin:10px 0 0; } }

  /* Composer */
  /* column, so the taste block stacks ABOVE the composer rather than beside it */
  .composer-wrap { display:flex; flex-direction:column; align-items:center; padding:12px 24px 26px; }
  .composer { width:100%; max-width:664px; display:flex; gap:10px; align-items:flex-end;
    background:rgba(5,6,10,0.55); border:1px solid var(--border); border-radius:var(--r-lg);
    padding:8px 8px 8px 16px; -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px); box-shadow:var(--shadow-lg); }
  .composer { transition:border-color .2s ease, box-shadow .25s ease; }
  .composer:focus-within { border-color:var(--gold-400);
    box-shadow:0 0 0 3px rgba(212,162,83,0.14), 0 0 30px 2px rgba(212,162,83,0.28), var(--shadow-lg); }
  .composer textarea { flex:1; background:transparent; border:none; resize:none; color:var(--fg);
    font-family:'Lato', var(--font-sans); font-weight:300; font-size:15px; line-height:1.5; padding:8px 0; max-height:140px; outline:none; }
  .composer textarea::placeholder { color:var(--parchment-300); font-style:italic; font-family:var(--font-serif); font-size:16px;
    transition:color .18s ease, opacity .18s ease; }
  /* hide the prompt text as soon as the field is focused */
  .composer textarea:focus::placeholder { color:transparent; opacity:0; }
  .send-btn { display:inline-flex; align-items:center; gap:8px; border:none; cursor:pointer;
    padding:12px 18px; border-radius:var(--r-md); font-family:var(--font-sans); font-size:12px; font-weight:600;
    letter-spacing:0.14em; text-transform:uppercase; color:var(--ink-900); background:var(--grad-gold-shimmer);
    box-shadow:var(--shadow-inset-gold), var(--glow-gold);
    transition:transform .12s cubic-bezier(.34,1.56,.64,1), box-shadow .18s ease, filter .18s ease; }
  .send-btn:hover { transform:translateY(-1px); filter:brightness(1.06);
    box-shadow:var(--shadow-inset-gold), var(--glow-gold-strong); }
  /* satisfying press: quick punch down with a snug glow */
  .send-btn:active { transform:translateY(0.5px) scale(0.975); filter:brightness(0.975);
    box-shadow:var(--shadow-inset-gold), 0 0 8px rgba(212,162,83,0.3); transition-duration:.04s; }
  .send-btn:disabled { opacity:.45; cursor:default; box-shadow:none; transform:none; filter:none; }

  /* ---------- Email capture gate ---------- */
  .email-gate { position:fixed; inset:0; z-index:20; display:flex; align-items:center; justify-content:center; padding:24px; }
  .email-gate[hidden] { display:none; }
  .email-gate-backdrop { position:absolute; inset:0; background:rgba(2,3,6,0.62);
    -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px); }
  .email-gate-card { position:relative; width:min(440px,100%); text-align:center;
    background:linear-gradient(180deg, rgba(18,21,33,0.97), rgba(11,13,20,0.97));
    border:1px solid var(--border-strong); border-radius:var(--r-lg); padding:34px 30px 26px;
    box-shadow:var(--shadow-lg), var(--glow-gold); -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
    animation:eg-in .26s ease both; }
  @keyframes eg-in { from{opacity:0; transform:translateY(10px) scale(.98)} to{opacity:1; transform:none} }
  .eg-close { position:absolute; top:11px; right:14px; background:none; border:none; color:var(--parchment-300);
    font-size:24px; line-height:1; cursor:pointer; transition:color .15s ease; }
  .eg-close:hover { color:var(--parchment-100); }
  .eg-overline { font-family:var(--font-sans); font-weight:600; font-size:11px; letter-spacing:var(--tracking-widest);
    text-transform:uppercase; color:var(--gold-400); }
  .eg-overline .lbl-ir  { font-family:var(--font-display); font-weight:400; letter-spacing:0.16em; color:var(--gold-400); }
  .eg-overline .lbl-dot { color:var(--gold-400); opacity:.65; margin:0 8px; }
  .eg-overline .lbl-story { font-weight:500; color:var(--gold-200); }   /* lighter than Infinite Realms */
  .eg-overline .lbl-os    { font-weight:400; color:var(--gold-100); }   /* lighter still, but not white */
  .eg-title { font-family:var(--font-display); text-transform:uppercase; letter-spacing:var(--tracking-wider);
    font-size:28px; color:var(--fg-display); margin:12px 0 8px; }
  .eg-lead { font-family:var(--font-serif); font-style:italic; font-size:16px; color:var(--parchment-200);
    margin:0 0 22px; line-height:1.6; }
  .eg-lead .eg-key        { color:var(--gold-200); }   /* the ask */
  .eg-lead .eg-key-strong { color:var(--gold-100); }   /* the key figure — session length */
  .eg-form { text-align:left; }
  .eg-label { display:block; font-family:var(--font-sans); font-size:11px; letter-spacing:0.2em;
    text-transform:uppercase; color:var(--gold-400); font-weight:600; margin-bottom:8px; }
  .eg-input { width:100%; box-sizing:border-box; background:var(--ink-900); border:1px solid var(--border);
    border-radius:var(--r-md); padding:12px 14px; color:var(--fg);
    font-family:'Lato', var(--font-sans); font-weight:300; font-size:15px; transition:border-color .18s ease, box-shadow .18s ease; }
  .eg-input:focus { outline:none; border-color:var(--gold-400); box-shadow:0 0 0 3px rgba(212,162,83,0.15); }
  .eg-textarea { min-height:96px; resize:vertical; line-height:1.5; }
  /* feedback: the last-reply snapshot attached to the note */
  .fb-context { margin-top:14px; border:1px solid var(--border); border-radius:var(--r-md);
    background:rgba(212,162,83,0.045); padding:11px 13px; }
  .fb-context-label { font-family:var(--font-sans); font-size:10px; letter-spacing:0.12em; text-transform:uppercase;
    color:var(--gold-400); margin-bottom:6px; }
  .fb-snapshot { font-family:var(--font-serif); font-style:italic; font-size:14px; line-height:1.5;
    color:var(--parchment-200); max-height:88px; overflow:hidden; }
  .eg-error { color:#E08280; font-family:var(--font-sans); font-size:12px; margin-top:8px; }
  .eg-check { display:flex; align-items:center; gap:9px; margin-top:14px; cursor:pointer;
    font-family:var(--font-sans); font-size:13px; color:var(--parchment-200); }
  .eg-check input { flex:none; width:15px; height:15px; accent-color:var(--gold-400); cursor:pointer; }
  .eg-submit { width:100%; justify-content:center; margin-top:16px; }
  .eg-textbtn { display:block; width:100%; margin:12px 0 0; padding:6px; background:none; border:none; cursor:pointer;
    font-family:var(--font-sans); font-size:12px; letter-spacing:0.04em; color:var(--parchment-300);
    transition:color .18s ease; } .eg-textbtn:hover { color:var(--gold-200); }
  .eg-fine { font-family:var(--font-sans); font-size:11px; color:var(--parchment-300); margin:16px 0 0; line-height:1.55; }
  .eg-fine a { color:var(--gold-200); text-underline-offset:2px; } .eg-fine a:hover { color:var(--gold-100); }
  /* the waitlist ask — a question, so it gets weight and room on both sides. Must sit
     AFTER .eg-fine: it's `class="eg-fine eg-ask"`, equal specificity, so source order wins. */
  .eg-ask { margin:26px 0 18px; font-size:13px; font-style:normal; color:var(--parchment-200); }

  /* subtle footer privacy link */
  .privacy-link { position:fixed; left:18px; bottom:8px; z-index:7;
    font-family:var(--font-sans); font-size:10px; letter-spacing:0.12em; text-transform:uppercase;
    color:var(--parchment-300); text-decoration:none; opacity:.55; transition:opacity .18s ease, color .18s ease; }
  .privacy-link:hover { opacity:1; color:var(--gold-200); }
  @media (max-width:640px){ .privacy-link { left:14px; bottom:6px; font-size:9px; } }

  /* gentle fade-in for the heavy scene art as it decodes */
  .moon-canvas, .ship-photo, .horse-photo { animation:fade-in 1.2s ease both; }
  @keyframes fade-in { from{opacity:0} to{opacity:1} }

  /* ---------- Responsive ---------- */
  @media (max-width:920px) {
    .brand { display:none; }
    .topbar { padding:16px 20px; }
  }
  @media (max-width:640px) {
    /* Single clean row — never wrap (a wrapped 2nd row overlaps the fixed moon).
       Tabs left, compact status + feedback right. */
    .topbar { padding:12px 14px; gap:8px; flex-wrap:nowrap; }
    .brand { display:none; }
    .switcher { gap:4px; min-width:0; }
    .book-tab { font-size:12px; padding:7px 10px 6px; letter-spacing:.1em; }
    .book-tab.locked .bt-lock { width:10px; margin-left:5px; }
    .title-lockup .t { white-space:normal; }   /* let the big title wrap on small screens */
    .topbar-right { gap:8px; flex:none; }
    .feedback-btn { width:30px; height:30px; }
    /* compact the status chip: drop the email + queue cue, keep the dot + timer/label */
    .status-chip { font-size:9px; padding:4px 9px; letter-spacing:0.08em; }
    .status-chip .who, .status-chip .sep, .status-chip .waiting { display:none; }
    .moon-wrap { width:118px; height:118px; top:9%; }
    .title-lockup { padding-top:calc(clamp(150px,24vh,210px) - 10px); }
    .title-lockup .t { font-size:clamp(26px,8vw,34px); }
    .title-lockup .s { font-size:15px; }
    .thread { padding:8px 16px 12px; }
    .msg { max-width:94%; }
    .msg-book .bubble { font-size:17px; }
    .composer-wrap { padding:10px 14px 18px; }
    .send-btn { padding:11px 14px; }
    .troy-walls { width:30vw; bottom:-6%; }
    .trojan-horse { height:52vh; transform:translateX(-30%); }
  }

  @media (prefers-reduced-motion: reduce) {
    .ship-track,.ship,.ship::after,.oars,.glints,.sea-sheen,.mist,.moon-halo,.stars,.wave,.status-chip .dot,.typing i,
    .troy-shimmer,.troy-foam,.horse-photo,.flock,.gull svg,
    .ptero-track,.ptero,.ptero-img,.lw-haze,
    .title-lockup .t,.title-lockup .author,.title-lockup .divide,.title-lockup .date,.title-lockup .s { animation:none !important; }
    .ship-track { transform: translate(66vw, calc(50vh - 80px)) scale(0.62); }  /* match first-load framing */
    .ship { transform: scaleX(1); }
    .ship::after { opacity:0.5; }
    .wave { opacity:.4; }
    .birds { display:none; }
    /* pterodactyl rests mid-beat on the horizon, upper-left, matching first-load framing */
    .ptero-track { transform: translate(6vw, 17vh) scale(0.72); }
    .ptero { transform: scaleX(1); }
  }
