/* ============================================================================
   The Trading Library — "Learn" world (Phase 0/1). FULLY SCOPED under #learnview
   with --lw-* variables + a private [data-lw-theme] so its twilight palette and
   day/night toggle never touch the console's own theme. Visual target: the
   trading-library-phase0 prototype, adapted from a full-screen app into a tab.
   ========================================================================== */
@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&display=swap');

#learnview{
  /* twilight (night) palette */
  --lw-bg:#0c0820; --lw-bg2:#140d2c;
  --lw-wallL:#241a40; --lw-wallL2:#1b1330;
  --lw-wallR:#2e2150; --lw-wallR2:#22193c;
  --lw-floor1:#5b4a72; --lw-floor2:#473961; --lw-floorEdge:#6a577f;
  --lw-pit2:#332747;
  --lw-sofa:#6260e0; --lw-sofa2:#4a48b8; --lw-sofa3:#7a78ee;
  --lw-neon:#b56cff; --lw-neon2:#67e2ff; --lw-neonGlow:#c98bff;
  --lw-fire:#ff9a3c; --lw-fireCore:#ffe6b0; --lw-fireGlow:#ff8a2e;
  --lw-plant:#3aa39c; --lw-plant2:#2c7d86; --lw-plantPot:#5a4a6e;
  --lw-gold:#ffd479; --lw-wood:#6e5640; --lw-wood2:#56412f;
  --lw-ink:#f3eefe; --lw-muted:#b3a8cf; --lw-line:#3a2f56;
  --lw-panel:#1a1330f2; --lw-panelEdge:#3a2c5e;
  --lw-ok:#56d98a; --lw-warn:#ffcf5a; --lw-busy:#ff6f7d; --lw-idle:#8b86a6;
  --lw-sky1:#1a1240; --lw-sky2:#3a2168;
  --lw-grade:transparent; --lw-neonI:1; --lw-fireI:1; --lw-starsO:1;
  --lw-shadow:0 20px 50px -20px #000a, 0 6px 18px -8px #0008;
  --lw-serif:"Fraunces",Georgia,serif;
  /* scene material vars (night = the exact hexes the room used before they were parameterized,
     so night is pixel-identical; day retints the whole set instead of leaving midnight furniture
     stranded in a pastel room) */
  --lw-fur:#1c1436; --lw-furSide:#150f2e; --lw-furTop:#2a1f48; --lw-furBody:#171029; --lw-furBody2:#20153f; --lw-furSlab:#2b1e52;
  --lw-case:#221846; --lw-caseSide:#2c2054; --lw-caseTop:#382a6c; --lw-caseEdge:#251b4a; --lw-caseBack:#0b071c; --lw-caseEnd:#150e2e;
  --lw-hearth:#241a3e; --lw-hearthFace:#2a1e4a; --lw-hearthFace2:#2c2152; --lw-hearthTop:#3a2a63; --lw-hearthTop2:#38295e; --lw-hearthDark:#1a1230;
  --lw-velvet:#3b1d3e; --lw-velvet2:#2a1430; --lw-city:#141031; --lw-box1:#160a04; --lw-box2:#3b1808;
  --lw-poster:#120c22; --lw-chimney:#2b2052; --lw-skirt:#7a679b; --lw-clockFace:#e9e0c9; --lw-clockInk:#3b3050;
  /* wall joinery: picture/chair rail, wainscot field, recessed panel, skirting, corner pilaster */
  --lw-rail:#3b2c6b; --lw-wainscot:#251b48; --lw-panelIn:#2d2159; --lw-skirtBd:#1c1439; --lw-pilaster:#31245e;
  --lw-plate:#05030fee; --lw-plateInk:#05030f;
  /* SIGNAGE stack: Tahoma/Verdana are hinted for on-screen legibility at small sizes (open counters,
     wide apertures) which is exactly what shelf labels need read from across a room. Deliberately
     NOT the inherited console font, and NOT a webfont — the SW serves this room cache-first, so a
     label must never depend on a font download to stay readable. */
  --lw-sign:Tahoma,"Segoe UI",Verdana,system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif;
  --lw-chrome:#0c0820e0; --lw-inputBg:#0c0820cc; --lw-bubble:#ffffff0e;
  color:var(--lw-ink);
}
/* ── DAY: a warm morning study, not "night with pastel walls". The old day theme retinted only
   walls/floor/sky — every piece of furniture, every bookcase carcass and the ink stayed midnight
   (white text on lavender measured ~1.9:1). Day now owns the full material set. ── */
#learnview[data-lw-theme="day"]{
  --lw-bg:#e7ddf3; --lw-bg2:#f4ecfb;
  --lw-wallL:#cdbbe7; --lw-wallL2:#bda9da;
  --lw-wallR:#ddccf1; --lw-wallR2:#cbb6e6;
  --lw-floor1:#d6b48c; --lw-floor2:#c09a71; --lw-floorEdge:#8a6b4d;
  --lw-pit2:#c4a680;
  --lw-sofa:#8583f2; --lw-sofa2:#6f6cd8; --lw-sofa3:#a3a1f8;
  --lw-neon:#c76fe0; --lw-neon2:#3fb1e8; --lw-neonGlow:#d898ea;
  --lw-fire:#ff8a2e; --lw-fireCore:#fff0c8; --lw-fireGlow:#ffae54;
  --lw-plant:#3f9e77; --lw-plant2:#2f7f6e; --lw-plantPot:#a3805f;
  --lw-gold:#b8860b; --lw-wood:#a97e57; --lw-wood2:#8a6544;
  --lw-ink:#241c3a; --lw-muted:#5b4f7a; --lw-line:#c9bce0;
  --lw-panel:#f7f1fcee; --lw-panelEdge:#c9b8e6;
  --lw-ok:#1f9d5c; --lw-warn:#b07a10; --lw-busy:#d24857; --lw-idle:#7b7492;
  --lw-sky1:#a8d4f8; --lw-sky2:#ffe0b0;
  --lw-grade:#ffd28a14; --lw-neonI:.3; --lw-fireI:.75; --lw-starsO:0;
  --lw-shadow:0 20px 50px -20px #4a346f40, 0 6px 18px -8px #4a346f30;
  --lw-fur:#b3906c; --lw-furSide:#9c7b59; --lw-furTop:#d8bb95; --lw-furBody:#c4a27c; --lw-furBody2:#b08d66; --lw-furSlab:#d2b287;
  --lw-case:#c9ab86; --lw-caseSide:#b2946f; --lw-caseTop:#e6cba4; --lw-caseEdge:#bb9d77; --lw-caseBack:#8f724f; --lw-caseEnd:#a3835f;
  --lw-hearth:#b79671; --lw-hearthFace:#c7a883; --lw-hearthFace2:#d3b58f; --lw-hearthTop:#e0c49c; --lw-hearthTop2:#d9bd96; --lw-hearthDark:#8f724f;
  --lw-velvet:#8a4f7d; --lw-velvet2:#75406a; --lw-city:#a390bfd9; --lw-box1:#241007; --lw-box2:#59260c;
  --lw-chimney:#c3a37e; --lw-skirt:#8a6b4d; --lw-clockFace:#fdf6e8; --lw-clockInk:#4a3b2a;
  /* signs stay DARK plates with white type in daylight too — that's how real shelf signage works,
     and it keeps one high-contrast treatment instead of inverting per theme */
  --lw-poster:#241a33; --lw-plate:#171029f2; --lw-plateInk:#120c22;
  /* daylight joinery: painted-oak panelling rather than midnight timber */
  --lw-rail:#b9a2d4; --lw-wainscot:#c3aede; --lw-panelIn:#cdbbe7; --lw-skirtBd:#a58fc4; --lw-pilaster:#c7b3e2;
  --lw-chrome:#ffffffdb; --lw-inputBg:#ffffffcc; --lw-bubble:#4a346f14;
}

/* ---------- shell ---------- */
.lw-shell{position:relative;border-radius:20px;overflow:hidden;
  background:radial-gradient(120% 90% at 50% 0%,var(--lw-bg2),var(--lw-bg) 72%);
  border:1px solid var(--lw-panelEdge);box-shadow:var(--lw-shadow);
  transition:background .8s ease}
.lw-top{position:relative;z-index:6;display:flex;align-items:center;gap:12px;
  justify-content:space-between;padding:13px 16px 11px}
.lw-brand{display:flex;align-items:baseline;gap:9px;min-width:0}
.lw-brand .lw-dot{width:7px;height:7px;border-radius:50%;background:var(--lw-ok);
  box-shadow:0 0 10px var(--lw-ok);align-self:center;animation:lw-pulse 2.4s ease-in-out infinite}
.lw-brand h2{font-family:var(--lw-serif);font-weight:600;margin:0;letter-spacing:.2px;
  font-size:clamp(17px,2.2vw,23px);text-shadow:0 2px 18px #0008;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lw-brand .lw-sub{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--lw-muted);white-space:nowrap}
@keyframes lw-pulse{50%{opacity:.4}}

/* roster pill */
.lw-roster{display:flex;align-items:center;gap:8px;cursor:pointer;
  background:var(--lw-panel);border:1px solid var(--lw-panelEdge);border-radius:999px;
  padding:5px 12px 5px 7px;backdrop-filter:blur(8px);box-shadow:var(--lw-shadow);flex:0 0 auto}
.lw-roster .lw-stack{display:flex}
.lw-roster .lw-pin{width:26px;height:26px;border-radius:50%;margin-left:-8px;
  border:2px solid var(--lw-panel);display:grid;place-items:center;font-size:13px;background:#3a2c5e}
.lw-roster .lw-rlabel{font-size:12px;color:var(--lw-muted);white-space:nowrap}

/* ---------- stage ---------- */
/* Aspect floor 1.45 (real CONTAINER aspect via aspect-ratio, not a 100vw guess). The room itself
   uses SVG `meet`, so every bookcase, plaque, desk label and edge of space remains in frame. */
.lw-stage{position:relative;width:100%;height:auto;aspect-ratio:1.45/1;min-height:380px;
  max-height:calc(100vh - 24px);overflow:hidden;contain:layout paint;
  background:radial-gradient(120% 90% at 50% 0%,var(--lw-bg2),var(--lw-bg) 72%)}
/* the world fills the ENTIRE webscreen on desktop — full-bleed breakout (margin trick, no
   transforms so fixed/absolute descendants keep working), while the room contains without stretch */
@media(min-width:1024px){
  #learnview .lw-shell{width:100vw;margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);border-radius:0}
  /* Height is MEASURED into --lw-stageH by sizeStage(), not guessed with a calc() constant: the
     stage sits below the header, two nav rows, the Ask-Kara strip and the KB switcher, and any
     future row silently invalidates a hard-coded offset. The calc() here is only the pre-measure
     fallback. Dropping aspect-ratio lets the stage own the available viewport; the 1664:920 room
     is centered inside it with `meet`, so extra-wide screens gain space instead of losing art. */
  #learnview .lw-stage{height:var(--lw-stageH,calc(100vh - 24px));aspect-ratio:auto;
    max-height:none;min-height:420px}
}

/* ---------- THEATER: the lounge owns the viewport ----------
   Also the reason the horizontal scrollbar disappears: the full-bleed breakout above sets
   width:100vw, and 100vw INCLUDES the scrollbar gutter (measured 1920 against a 1905 clientWidth
   = 8px of overflow). position:fixed retires the margin trick, so the overflow goes with it. */
#learnview[data-lw-theater] .lw-shell{position:fixed;inset:0;z-index:60;width:auto;
  margin:0;border:0;border-radius:0;display:flex;flex-direction:column}
#learnview[data-lw-theater] .lw-top{flex:0 0 auto}
#learnview[data-lw-theater] .lw-stage{flex:1 1 auto;height:auto;min-height:0;
  max-height:none;aspect-ratio:auto}
body.lw-theater-on{overflow:hidden}
/* One symmetric control. Windowed it sits inline in the title row and reads "Theater"; in theater
   it pins to the top-right and reads "Exit". Never a one-way door. Hidden below 1024 where the
   windowed layout is already the right answer. */
.lw-exit{display:none;align-items:center;gap:7px;margin-left:auto;margin-right:10px;
  font:800 10.5px/1 var(--lw-sign);letter-spacing:.09em;text-transform:uppercase;
  color:var(--lw-ink);background:var(--lw-panel);border:1px solid var(--lw-panelEdge);
  border-radius:999px;padding:8px 13px;cursor:pointer;box-shadow:var(--lw-shadow);white-space:nowrap}
@media(min-width:1024px){ .lw-exit{display:inline-flex} }
#learnview[data-lw-theater] .lw-exit{position:absolute;top:12px;right:14px;z-index:9;
  margin:0;backdrop-filter:blur(8px)}
.lw-exit:hover{border-color:var(--lw-neon2)}
.lw-exit:focus-visible{outline:2.5px solid var(--lw-neon2);outline-offset:2px}
/* the roster keeps the right edge when the exit chip is inline beside it */
#learnview:not([data-lw-theater]) .lw-top .lw-roster{margin-left:0}
.lw-stage svg.lw-room{position:absolute;inset:0;width:100%;height:100%;display:block}
.lw-stage .lw-fx{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.lw-grade{position:absolute;inset:0;background:var(--lw-grade);mix-blend-mode:soft-light;
  pointer-events:none;transition:background .8s ease}
/* camera: a slightly longer, softer curve than the old .55s ease — and `will-change` is applied
   ONLY while a move is in flight (.lw-camming), since a permanent compositing hint on a layer this
   large costs memory and can soften text between moves */
.lw-scene{position:absolute;inset:0;transition:transform .62s cubic-bezier(.33,.02,.16,1);
  transform-origin:center center;backface-visibility:hidden}
.lw-scene.lw-camming{will-change:transform}
@media (prefers-reduced-motion:reduce){.lw-scene{transition:none}}

/* hotspots */
.lw-hot{position:absolute;border:0;background:transparent;cursor:pointer;border-radius:14px;padding:0;outline-offset:3px}
.lw-hot:focus-visible{outline:2.5px solid var(--lw-neon2)}
.lw-hot .lw-ring{position:absolute;inset:0;border:2px solid transparent;border-radius:14px;transition:.18s}
.lw-hot:hover .lw-ring,.lw-hot:focus-visible .lw-ring{border-color:var(--lw-neon2);box-shadow:0 0 22px -4px var(--lw-neon2)}
.lw-hot .lw-tag{position:absolute;left:50%;top:0;transform:translate(-50%,-130%);
  font-size:11px;background:var(--lw-panel);border:1px solid var(--lw-panelEdge);color:var(--lw-ink);
  padding:4px 9px;border-radius:999px;white-space:nowrap;opacity:0;transition:.18s;box-shadow:var(--lw-shadow);pointer-events:none}
.lw-hot:hover .lw-tag,.lw-hot:focus-visible .lw-tag{opacity:1;transform:translate(-50%,-150%)}

/* ── ROOM SIGNAGE: shelf plates, wall posters and the quest poster all use one legibility
   treatment. Font/weight/spacing live here (CSS beats SVG presentation attributes) so there is a
   single place to tune how the room reads from a distance. ── */
#lwShelves3d .lw-unit-plate text,
#learnview .lw-posters text,
#learnview #lwQuest text,
#learnview .lw-window text{
  font-family:var(--lw-sign);font-weight:700;letter-spacing:.55px;
  paint-order:stroke;stroke-linejoin:round;text-rendering:geometricPrecision}
/* the plate is the sign's backing board — keep it opaque and let the accent edge do the pointing */
#lwShelves3d .lw-unit-plate{opacity:1}
#lwShelves3d .lw-unit-plate text{font-weight:800}
/* a soft outer glow lifts the whole plate off busy shelving without washing out the type */
#lwShelves3d .lw-unit-plate rect{filter:drop-shadow(0 2px 5px #000000a6)}
#learnview[data-lw-perf="lite"] #lwShelves3d .lw-unit-plate rect{filter:none}

/* ---------- isometric bookshelves built into the walls (SVG groups) ---------- */
#lwShelves3d .lw-unit{cursor:pointer;transition:transform .16s ease,filter .18s ease;transform-box:fill-box;transform-origin:center}
#lwShelves3d .lw-unit:hover,#lwShelves3d .lw-unit:focus-visible{transform:translateY(-4px);filter:drop-shadow(0 0 13px var(--lw-accent))}
#lwShelves3d .lw-unit:focus-visible{outline:none}
#lwShelves3d .lw-unit:focus-visible .lw-unit-plate rect{stroke-width:2.4}
#lwShelves3d .lw-unit-plate{opacity:.9;transition:opacity .16s}
#lwShelves3d .lw-unit:hover .lw-unit-plate,#lwShelves3d .lw-unit:focus-visible .lw-unit-plate{opacity:1}
/* spotlight: glow the chosen unit, dim the rest (librarian "takes you there") */
#lwShelves3d.lw-spotlighting .lw-unit{opacity:.30;filter:grayscale(.45);transition:opacity .3s,filter .3s}
#lwShelves3d.lw-spotlighting .lw-unit.lw-lit{opacity:1;filter:drop-shadow(0 0 18px var(--lw-accent));animation:lw-litpulse 1.4s ease-in-out infinite}
@keyframes lw-litpulse{50%{filter:drop-shadow(0 0 26px var(--lw-accent))}}
.lw-av.lw-walking .lw-bob{animation-duration:.62s}
/* librarian desk hover (the hotspot button overlays it; this keeps the fox lively) */
.lw-deskobj .lw-deskfox{transform-box:fill-box;transform-origin:center bottom;animation:lw-bob 3.2s ease-in-out infinite}
#learnview[data-lw-calm] .lw-deskobj .lw-deskfox{animation:none}
@media (prefers-reduced-motion:reduce){#lwShelves3d .lw-unit,.lw-deskobj .lw-deskfox{transition:none;animation:none}}

/* ---------- librarian chat panel ---------- */
.lw-libpanel{width:min(440px,100%)}
.lw-libfeed{display:flex;flex-direction:column;gap:8px;max-height:38vh;overflow:auto;margin-bottom:10px;padding:2px}
.lw-libmsg{display:flex;gap:8px;align-items:flex-start;font-size:13.5px;line-height:1.45}
.lw-libmsg.me{justify-content:flex-end}
.lw-libmsg .lw-libav{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:#241a3e;display:grid;place-items:center;font-size:15px;border:1.5px solid var(--lw-gold);overflow:hidden}
.lw-libmsg .lw-libav img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.lw-libmsg .lw-libtext{background:var(--lw-bubble,#ffffff0e);border:1px solid var(--lw-panelEdge);border-radius:13px;padding:8px 12px;max-width:80%;color:var(--lw-ink)}
.lw-libmsg.me .lw-libtext{background:linear-gradient(120deg,var(--lw-neon),#8a5cff);border-color:transparent;color:#fff}
.lw-libchips{display:flex;flex-wrap:wrap;gap:7px;margin-top:8px}
.lw-libchip{font:600 12px var(--lw-serif);border:1px solid var(--lw-panelEdge);background:#ffffff10;color:var(--lw-ink);
  border-radius:999px;padding:6px 12px;cursor:pointer;transition:.14s}
.lw-libchip:hover{background:#ffffff20;border-color:var(--lw-neon)}
.lw-libchip.alt{border-color:var(--lw-gold);color:var(--lw-gold)}
.lw-libinput{display:flex;gap:8px;margin-top:12px}
.lw-libinput input{flex:1;min-width:0;background:var(--lw-inputBg,#0c0820cc);border:1px solid var(--lw-panelEdge);border-radius:11px;
  color:var(--lw-ink);font:16px/1.4 "Outfit",system-ui,sans-serif;padding:9px 12px}   /* ≥16px or iOS zooms the viewport on focus */
.lw-libinput input:focus{outline:none;border-color:var(--lw-neon)}
.lw-libinput .lw-btn{flex:0 0 auto}

/* fireplace / rain / flame motion — three layers flickering out of phase is what makes the fire
   read as alive; each is a cheap transform-only animation */
.lw-flame{transform-box:fill-box;transform-origin:center bottom;animation:lw-flick 1.8s ease-in-out infinite}
@keyframes lw-flick{0%,100%{transform:scaleY(1)}45%{transform:scaleY(1.1) translateY(-2px);opacity:.85}72%{transform:scaleY(.95) translateX(1.5px)}}
.lw-flame2{transform-box:fill-box;transform-origin:center bottom;animation:lw-flick2 2.3s ease-in-out infinite}
.lw-flame3{transform-box:fill-box;transform-origin:center bottom;animation:lw-flick3 1.4s ease-in-out infinite .3s}
@keyframes lw-flick2{0%,100%{transform:scaleY(1) skewX(0deg)}38%{transform:scaleY(1.09) skewX(2deg) translateY(-2px)}70%{transform:scaleY(.93) skewX(-1.6deg)}}
@keyframes lw-flick3{0%,100%{transform:scale(1)}30%{transform:scale(1.05,1.14) translateY(-2.5px)}62%{transform:scale(.95,.9)}}
.lw-spark{transform-box:fill-box;animation:lwSpark 2.6s ease-in infinite}
.lw-spark2{animation-duration:3.4s;animation-delay:1.1s}
.lw-spark3{animation-duration:4.1s;animation-delay:2s}
@keyframes lwSpark{0%{transform:translate(0,0);opacity:0}10%{opacity:1}65%{opacity:.7}100%{transform:translate(7px,-90px);opacity:0}}
.lw-firepool{animation:lw-glow 3.2s ease-in-out infinite}
@keyframes lw-glow{0%,100%{opacity:var(--lw-fireI)}50%{opacity:calc(var(--lw-fireI) * .6)}}
/* The .lw-rain / .lw-rain-floor layers were deleted here, not just unused: the rain spans came out
   of build() in the declutter round (they were the "lines near the window" complaint) and the window
   now shows real temperature instead. Nothing emits those classes, so the rules were dead weight in
   an asset the service worker serves cache-first. */

/* calm mode + reduced motion kill all ambient motion */
#learnview[data-lw-calm] .lw-flame,
#learnview[data-lw-calm] .lw-flame2,
#learnview[data-lw-calm] .lw-flame3,
#learnview[data-lw-calm] .lw-spark,
#learnview[data-lw-calm] .lw-firepool,
#learnview[data-lw-calm] .lw-av .lw-bob{animation:none}
#learnview[data-lw-calm] .lw-spark{opacity:0}
@media (prefers-reduced-motion:reduce){
  .lw-flame,.lw-flame2,.lw-flame3,.lw-spark,.lw-firepool,.lw-av .lw-bob,.lw-scene,.lw-brand .lw-dot{animation:none!important;transition:none!important}
  .lw-spark{opacity:0}
}

/* ---------- avatars ---------- */
.lw-avatars{position:absolute;inset:0;pointer-events:none;z-index:4}
/* SMOOTHNESS: peer avatars arrive as ≤4 Hz move frames (250ms apart), so a 150ms LINEAR tween
   finished early and then sat still — motion read as a stutter-step. A 260ms ease slightly
   overlaps the next update, which interpolates the gaps into continuous glide. */
.lw-av{position:absolute;transform:translate(-50%,-50%);pointer-events:auto;cursor:pointer;
  width:var(--lw-s,44px);height:var(--lw-s,44px);
  transition:left .26s cubic-bezier(.33,.1,.25,1),top .26s cubic-bezier(.33,.1,.25,1)}
@media (prefers-reduced-motion:reduce){.lw-av{transition:none}}
.lw-av .lw-bob{width:100%;height:100%;animation:lw-bob var(--lw-bd,3.4s) ease-in-out infinite;animation-delay:var(--lw-dl,0s)}
.lw-av .lw-ph{width:100%;height:100%;border-radius:50%;display:grid;place-items:center;font-size:19px;overflow:hidden;
  border:2.5px solid var(--lw-rc,var(--lw-ok));box-shadow:0 0 0 3px #0006,0 8px 18px -6px #000a,0 0 18px -2px var(--lw-rc,var(--lw-ok))}
.lw-av .lw-ph img{width:100%;height:100%;object-fit:cover;border-radius:50%}
.lw-av .lw-nm{position:absolute;top:104%;left:50%;transform:translateX(-50%);font-size:11px;
  background:var(--lw-chrome,#0c0820cc);border:1px solid var(--lw-panelEdge);padding:1px 7px;border-radius:999px;white-space:nowrap;color:var(--lw-ink);opacity:0;transition:.16s}
.lw-av:hover .lw-nm,.lw-av:focus-visible .lw-nm{opacity:1}
.lw-av.me .lw-ph{border-color:var(--lw-neon2);box-shadow:0 0 0 3px #0006,0 0 22px -2px var(--lw-neon2)}
@keyframes lw-bob{50%{transform:translateY(-7px)}}
/* "+N" overflow cluster when a zone is crowded */
.lw-av.lw-more .lw-ph{border-color:var(--lw-warn);font-size:14px;font-weight:800;font-family:var(--lw-serif)}

/* warm empty-state line — bottom-anchored; parked at top:30% it sat straight across the posters */
.lw-empty{position:absolute;left:50%;bottom:60px;top:auto;transform:translateX(-50%);z-index:5;text-align:center;
  pointer-events:none;   /* passive hint — it was silently swallowing clicks on whatever it covered */
  font-size:12.5px;color:var(--lw-muted);background:var(--lw-chrome,#0c0820aa);border:1px solid var(--lw-panelEdge);
  padding:7px 15px;border-radius:999px;max-width:62%;transition:opacity .5s;backdrop-filter:blur(4px)}

/* ---------- dock ---------- */
.lw-dock{position:absolute;z-index:6;top:12px;left:50%;transform:translateX(-50%);bottom:auto;
  display:flex;align-items:center;gap:6px;background:var(--lw-chrome,#0c0820e0);border:1px solid var(--lw-panelEdge);
  border-radius:18px;padding:7px;box-shadow:var(--lw-shadow);backdrop-filter:blur(10px);max-width:94%;flex-wrap:wrap;justify-content:center}
/* GROUPED WELLS: three decisions (ambience · browse · presence) instead of one row of eight icons
   divided by hair lines. Each well is a faint inset so the grouping reads even at a glance. */
.lw-dgrp{display:flex;align-items:center;gap:4px;padding:3px;border-radius:15px;
  background:#ffffff08;box-shadow:inset 0 0 0 1px #ffffff0f}
.lw-dgrp-go{background:none;box-shadow:none;padding:0}
.lw-dock button{width:42px;height:42px;border-radius:12px;border:1px solid transparent;background:transparent;
  color:var(--lw-ink);font-size:18px;cursor:pointer;display:grid;place-items:center;position:relative;
  transition:background .15s ease,transform .12s ease,color .15s ease,box-shadow .15s ease}
.lw-dock button:hover{background:#ffffff1a;color:#fff;transform:translateY(-1px)}
.lw-dock button:active{transform:translateY(0) scale(.94)}
.lw-dock button:focus-visible{outline:none;box-shadow:0 0 0 2px var(--lw-neon2),0 0 0 5px #67e2ff33}
/* ON state: a gradient pill with an inner lift and a tick underline, rather than a flat neon block.
   Prefixed with #learnview and written as LONGHANDS on purpose — at plain `.lw-dock button[...]`
   specificity it tied with `:hover` and lost to the ID-carrying day-theme rule, so the pressed pill
   rendered flat (measured). The state a control is IN must out-specify how it is being pointed at. */
#learnview .lw-dock button[aria-pressed="true"]{
  background-image:linear-gradient(160deg,var(--lw-neon),#8a5cff);background-color:transparent;
  border-color:#ffffff2b;color:#fff;box-shadow:0 0 16px -4px var(--lw-neon),inset 0 1px 0 #ffffff40}
#learnview .lw-dock button[aria-pressed="true"]::after{content:"";position:absolute;bottom:4px;left:50%;
  transform:translateX(-50%);width:12px;height:2px;border-radius:2px;background:#ffffffb3}
#learnview .lw-dock button[aria-pressed="true"]:hover{transform:translateY(-1px);background-color:#ffffff14}
/* the presence pill: a status control, so it gets a live state dot and a wider footprint */
.lw-dock .lw-go{width:auto;min-width:96px;padding:0 13px 0 11px;gap:7px;
  font:800 12px var(--lw-sign);letter-spacing:.3px;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--lw-panelEdge);background:#ffffff0d}
.lw-dock .lw-go:hover{background:#ffffff1c}
.lw-dock .lw-godot{width:7px;height:7px;border-radius:50%;flex:0 0 auto;background:var(--lw-idle);
  box-shadow:0 0 0 3px #ffffff0f;transition:background .2s}
.lw-dock .lw-go[data-pstate="on"] .lw-godot{background:var(--lw-ok);box-shadow:0 0 8px 1px var(--lw-ok)}
.lw-dock .lw-go[data-pstate="connecting"] .lw-godot{background:var(--lw-warn);animation:lwDotPulse 1.1s ease-in-out infinite}
.lw-dock .lw-go[data-pstate="fail"] .lw-godot{background:var(--lw-busy);box-shadow:0 0 8px 1px var(--lw-busy)}
@keyframes lwDotPulse{50%{opacity:.35}}
#learnview[data-lw-calm] .lw-godot,#learnview[data-lw-perf="lite"] .lw-godot{animation:none}
@media (prefers-reduced-motion:reduce){.lw-godot{animation:none!important}}
/* day theme: wells and hovers tint plum instead of white */
#learnview[data-lw-theme="day"] .lw-dgrp{background:#4a346f0a;box-shadow:inset 0 0 0 1px #4a346f14}
/* :not(pressed) again — this hover rule carries an ID AND a pseudo-class, so at (1,3,1) it beat the
   pressed pill's (1,2,1) and its `background` shorthand erased the gradient the moment you pointed
   at an ON button (measured: backgroundImage went to "none" on hover, only in day). */
#learnview[data-lw-theme="day"] .lw-dock button:not([aria-pressed="true"]):hover{background:#4a346f14;color:var(--lw-ink)}
#learnview[data-lw-theme="day"] .lw-dock .lw-go{background:#4a346f0a}

/* ---------- music player (shuffle/skip, generated tracks) ---------- */
.lw-music{position:absolute;z-index:7;bottom:12px;left:50%;transform:translateX(-50%);
  align-items:center;gap:7px;background:var(--lw-chrome,#0c0820e6);border:1px solid var(--lw-panelEdge);border-radius:999px;
  padding:5px 7px 5px 13px;box-shadow:var(--lw-shadow);backdrop-filter:blur(10px);max-width:92%;flex-wrap:wrap;justify-content:center}
.lw-mus-eq{display:flex;align-items:flex-end;gap:2px;height:14px}
.lw-mus-eq i{width:3px;height:6px;background:var(--lw-neon2);border-radius:2px;animation:lw-eq .9s ease-in-out infinite}
.lw-mus-eq i:nth-child(2){animation-delay:.2s}
.lw-mus-eq i:nth-child(3){animation-delay:.4s}
@keyframes lw-eq{0%,100%{height:5px}50%{height:14px}}
#learnview[data-lw-calm] .lw-mus-eq i{animation:none}
.lw-mus-name{font:600 12px var(--lw-serif);color:var(--lw-ink);white-space:nowrap;max-width:130px;overflow:hidden;text-overflow:ellipsis}
.lw-music button{width:30px;height:30px;border-radius:9px;border:1px solid #fff1;background:#ffffff0a;color:var(--lw-ink);font-size:13px;cursor:pointer;display:grid;place-items:center;transition:.14s}
.lw-music button:hover{background:#ffffff1a}
.lw-music button[aria-pressed="true"]{background:var(--lw-neon);border-color:transparent;color:#fff}
/* bring-your-own-music link-out row (opens below the pill when 🔗 is tapped) */
.lw-mus-linkbox{display:flex;gap:5px;align-items:center;flex-basis:100%;margin-top:3px;padding:1px 4px 2px}
.lw-mus-linkbox input{flex:1;min-width:0;background:#ffffff12;border:1px solid var(--lw-panelEdge);border-radius:8px;
  color:var(--lw-ink);font:500 11px var(--lw-serif);padding:7px 9px;outline:none}
.lw-mus-linkbox input::placeholder{color:#ffffff66}
.lw-mus-linkbox button{width:auto;height:30px;padding:0 11px;font-size:11px;white-space:nowrap}

/* ---------- scrim + panels ---------- */
.lw-scrim{position:fixed;inset:0;z-index:1200;background:#06041288;backdrop-filter:blur(3px);
  display:none;align-items:center;justify-content:center;padding:18px}
.lw-scrim.on{display:flex}
.lw-panel{width:min(640px,100%);max-height:86vh;overflow:auto;background:var(--lw-panel);
  border:1px solid var(--lw-panelEdge);border-radius:22px;box-shadow:var(--lw-shadow);
  backdrop-filter:blur(14px);animation:lw-rise .35s cubic-bezier(.3,.7,.2,1);color:var(--lw-ink)}
.lw-panel.wide{width:min(760px,100%)}
@keyframes lw-rise{from{opacity:0;transform:translateY(14px) scale(.985)}}
.lw-phead{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:19px 22px 6px}
.lw-phead .lw-eyebrow{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--lw-neonGlow)}
.lw-phead h3{font-family:var(--lw-serif);font-weight:600;margin:3px 0 0;font-size:23px;color:var(--lw-ink)}
.lw-phead p{margin:6px 0 0;color:var(--lw-muted);font-size:13.5px;max-width:48ch}
.lw-x{flex:none;width:34px;height:34px;border-radius:10px;border:1px solid var(--lw-panelEdge);background:#fff1;color:var(--lw-ink);font-size:16px;cursor:pointer}
.lw-x:hover{background:#fff2}
.lw-pbody{padding:14px 22px 22px}

.lw-tracks{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px}
.lw-track{text-align:left;background:linear-gradient(160deg,#ffffff0e,#ffffff04);border:1px solid var(--lw-panelEdge);
  border-radius:16px;padding:14px;cursor:pointer;transition:.16s;position:relative;overflow:hidden;color:var(--lw-ink)}
.lw-track:hover{transform:translateY(-2px);border-color:var(--lw-accent,var(--lw-neon))}
.lw-track .lw-ic{font-size:22px}
.lw-track h4{font-family:var(--lw-serif);font-size:16px;margin:8px 0 2px;font-weight:600}
.lw-track .lw-meta{font-size:11.5px;color:var(--lw-muted)}
.lw-track .lw-tbar{position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--lw-accent,var(--lw-neon))}

.lw-booklist{display:flex;flex-direction:column;gap:8px}
.lw-bk{display:flex;align-items:center;gap:12px;text-align:left;background:#ffffff08;border:1px solid var(--lw-panelEdge);
  border-radius:14px;padding:11px 13px;cursor:pointer;transition:.16s;color:var(--lw-ink);width:100%}
.lw-bk:hover{background:#ffffff14;transform:translateX(3px)}
.lw-bk.soon{opacity:.6;cursor:default}
.lw-bk.soon:hover{transform:none;background:#ffffff08}
.lw-bk .lw-spine{width:30px;height:40px;border-radius:4px;flex:none;box-shadow:inset 0 0 0 1px #fff2}
.lw-bk .lw-bt{flex:1;min-width:0}
.lw-bk .lw-bt b{font-family:var(--lw-serif);font-weight:600;font-size:14.5px;display:block}
.lw-bk .lw-bt span{font-size:11.5px;color:var(--lw-muted)}
.lw-bk .lw-pc{font-size:11px;color:var(--lw-neon2);white-space:nowrap}
.lw-bk .lw-pc.read{color:var(--lw-ok)}

.lw-note{font-size:11.5px;color:var(--lw-muted);margin-top:14px;border-top:1px solid var(--lw-line);padding-top:10px}
.lw-btn{font:inherit;font-size:13px;border:1px solid var(--lw-panelEdge);background:#ffffff0e;color:var(--lw-ink);
  padding:9px 16px;border-radius:11px;cursor:pointer;transition:.15s}
.lw-btn:hover{background:#ffffff1c}
.lw-btn.primary{background:linear-gradient(120deg,var(--lw-neon),#8a5cff);border-color:transparent;color:#fff}

/* profile card */
.lw-pcard{width:min(340px,100%)}
.lw-pcard .lw-ptop{display:flex;gap:13px;align-items:center;padding:18px 20px 8px}
.lw-pcard .lw-big{width:54px;height:54px;border-radius:50%;display:grid;place-items:center;font-size:25px;flex:none;overflow:hidden;
  border:2.5px solid var(--lw-rc,var(--lw-ok));box-shadow:0 0 16px -2px var(--lw-rc,var(--lw-ok))}
.lw-pcard .lw-big img{width:100%;height:100%;object-fit:cover;border-radius:50%}
.lw-pcard .lw-pwho b{font-family:var(--lw-serif);font-size:18px;display:block}
.lw-pcard .lw-pwho span{font-size:12px;color:var(--lw-muted)}
.lw-pcard .lw-pstats{display:flex;gap:8px;padding:6px 20px 4px}
.lw-chip{flex:1;text-align:center;border:1px solid var(--lw-panelEdge);border-radius:11px;padding:8px 4px;background:#ffffff08}
.lw-chip b{display:block;font-size:16px}
.lw-chip span{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--lw-muted)}

/* presence opt-in toggle row */
.lw-optrow{display:flex;align-items:center;gap:10px;padding:12px 14px;border:1px solid var(--lw-panelEdge);border-radius:14px;background:#ffffff06;margin-bottom:10px}
.lw-optrow .lw-ot{flex:1}
.lw-optrow .lw-ot b{display:block;font-size:13.5px}
.lw-optrow .lw-ot span{font-size:11.5px;color:var(--lw-muted)}
.lw-switch{position:relative;width:46px;height:26px;border-radius:999px;background:#ffffff1c;border:1px solid var(--lw-panelEdge);cursor:pointer;flex:0 0 auto;transition:.18s}
.lw-switch::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--lw-muted);transition:.18s}
.lw-switch[aria-checked="true"]{background:var(--lw-ok)}
.lw-switch[aria-checked="true"]::after{left:22px;background:#fff}

/* ---------- non-spatial LIST fallback (mandatory · §13) ---------- */
/* The list REPLACES the room (toggleList hides #lwShell), so it cannot borrow the stage's painted
   background — it had none of its own. In DAY theme that meant day ink (#241c3a) over the console's
   dark page: measured 1.3:1, the book titles were effectively invisible. Own surface, both themes. */
.lw-list{padding:12px 10px 18px;background:var(--lw-bg2);border:1px solid var(--lw-line);border-radius:14px}
.lw-list .lw-lhead{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:2px 2px 14px}
.lw-list h3{font-family:var(--lw-serif);font-weight:600;margin:0;font-size:20px}
.lw-list .lw-lcat{font-family:var(--lw-serif);font-size:15px;margin:16px 4px 8px;color:var(--lw-neonGlow);border-bottom:1px solid var(--lw-line);padding-bottom:6px}
.lw-list .lw-lbooks{display:flex;flex-direction:column;gap:7px}

/* ---------- interactions (Phase 2): action menu · toast · invite · follow chip ---------- */
.lw-pacts{display:flex;gap:8px;margin:0 0 4px;flex-wrap:wrap}
.lw-pacts .lw-btn{flex:1;min-width:90px}
.lw-btn.lw-sm{font-size:12px;padding:7px 10px}
.lw-btn.ghost{opacity:.5}
.lw-btn[disabled]{opacity:.4;cursor:default}
.lw-toast{position:absolute;left:50%;top:14px;transform:translateX(-50%) translateY(-8px);z-index:8;
  background:#0c0820ee;border:1px solid var(--lw-panelEdge);color:var(--lw-ink);font-size:12.5px;
  padding:9px 15px;border-radius:999px;box-shadow:var(--lw-shadow);max-width:88%;text-align:center;
  opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;backdrop-filter:blur(6px)}
.lw-toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
.lw-invite{position:absolute;left:50%;bottom:74px;transform:translateX(-50%);z-index:9;display:flex;
  align-items:center;gap:10px;background:#140d2cf2;border:1px solid var(--lw-neon);border-radius:16px;
  padding:11px 13px;box-shadow:0 12px 30px -10px #000c,0 0 22px -6px var(--lw-neon);max-width:92%;
  animation:lw-rise .3s cubic-bezier(.3,.7,.2,1)}
.lw-invite .lw-inv-msg{font-size:13px;color:var(--lw-ink);max-width:34ch;line-height:1.35}
.lw-invite .lw-btn{flex:0 0 auto;white-space:nowrap}
.lw-follow-chip{position:absolute;left:14px;top:14px;z-index:7;display:flex;align-items:center;gap:6px;
  background:#0c0820e0;border:1px solid var(--lw-neon2);color:var(--lw-ink);font-size:12px;font-weight:600;
  padding:6px 8px 6px 12px;border-radius:999px;box-shadow:var(--lw-shadow);backdrop-filter:blur(6px)}
.lw-follow-chip .lw-fc-nm{color:var(--lw-neon2)}
.lw-follow-chip .lw-fc-stop{width:20px;height:20px;border-radius:50%;border:1px solid var(--lw-panelEdge);
  background:#fff1;color:var(--lw-ink);font-size:11px;cursor:pointer;display:grid;place-items:center;line-height:1;padding:0}
.lw-follow-chip .lw-fc-stop:hover{background:#fff2}

/* ---------- achievements (Phase 4) ---------- */
.lw-badge{position:relative;opacity:.5;filter:grayscale(.55)}
.lw-badge.on{opacity:1;filter:none}
.lw-badge-tick{position:absolute;top:9px;right:11px;color:var(--lw-ok);font-weight:800;font-size:15px}
/* ghost readers (Phase 4) — faint, opt-in, last-known position */
.lw-av.lw-ghost{opacity:.34;filter:grayscale(.5)}
.lw-av.lw-ghost .lw-ph{border-style:dashed;box-shadow:none}
.lw-av.lw-ghost .lw-bob{animation:none}

/* ---------- co-reading session bar (Phase 3) — lives in <body>, so EXPLICIT colors (not --lw-* vars) ---------- */
.lw-coread{position:fixed;left:50%;bottom:14px;transform:translateX(-50%);z-index:100000;width:min(560px,94vw);
  background:#140d2cf7;border:1px solid #b56cff;border-radius:16px;color:#f3eefe;
  box-shadow:0 16px 40px -12px #000d,0 0 26px -8px #b56cff;backdrop-filter:blur(10px);
  font-family:"Outfit",system-ui,sans-serif;overflow:hidden;animation:lw-rise .3s cubic-bezier(.3,.7,.2,1)}
.lw-cr-top{display:flex;align-items:center;gap:9px;padding:9px 12px}
.lw-cr-title{font-weight:700;font-size:13px;white-space:nowrap}
.lw-cr-members{font-size:12px;color:#c98bff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:40%}
.lw-cr-b{border:1px solid #3a2c5e;background:#ffffff10;color:#f3eefe;border-radius:9px;padding:5px 9px;font-size:13px;cursor:pointer;transition:.14s}
.lw-cr-b:hover{background:#ffffff1f}
.lw-cr-b.lw-cr-leave{border-color:#ff5a6a55;background:#ff5a6a22;font-size:12px;font-weight:600}
.lw-cr-notes{padding:0 12px 10px}
.lw-cr-notes textarea{width:100%;box-sizing:border-box;resize:vertical;min-height:54px;background:#0c0820cc;
  border:1px solid #3a2c5e;border-radius:10px;color:#f3eefe;font:13px/1.4 "Outfit",system-ui,sans-serif;padding:8px 10px}
.lw-cr-feed{max-height:128px;overflow:auto;padding:0 12px}
.lw-cr-feed:empty{display:none}
.lw-cr-line{font-size:12px;color:#cdbfe8;padding:5px 0;border-top:1px solid #2a2148}
.lw-cr-line b{color:#f3eefe}
@media (max-width:640px){.lw-coread{bottom:8px}.lw-cr-title{font-size:12px}}

@media (max-width:640px){
  .lw-brand .lw-sub{display:none}
  .lw-roster .lw-rlabel{display:none}
  .lw-stage{height:clamp(380px,58vh,520px)}
  .lw-av{--lw-s:38px}
  .lw-dock button{width:40px;height:40px;font-size:16px}
}

/* ===== animated deep-space background (stars + planets) behind the room ===== */
.lw-bg{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;opacity:var(--lw-starsO);transition:opacity .6s}
.lw-stars{position:absolute;inset:0;background-repeat:no-repeat}
.lw-s1{background-image:
  radial-gradient(1.6px 1.6px at 12% 18%,#fff,transparent),radial-gradient(1.4px 1.4px at 27% 41%,#dce9ff,transparent),
  radial-gradient(1.8px 1.8px at 46% 11%,#fff,transparent),radial-gradient(1.3px 1.3px at 62% 31%,#cfe3ff,transparent),
  radial-gradient(1.6px 1.6px at 81% 20%,#fff,transparent),radial-gradient(1.4px 1.4px at 92% 47%,#e7d6ff,transparent),
  radial-gradient(1.5px 1.5px at 7% 63%,#fff,transparent),radial-gradient(1.3px 1.3px at 72% 69%,#d7ecff,transparent),
  radial-gradient(1.5px 1.5px at 38% 78%,#fff,transparent),radial-gradient(1.4px 1.4px at 55% 88%,#cfe3ff,transparent);
  animation:lwTwinkle 4.5s ease-in-out infinite}
.lw-s2{opacity:.72;background-image:
  radial-gradient(1.2px 1.2px at 18% 28%,#fff,transparent),radial-gradient(1.1px 1.1px at 34% 14%,#e7d6ff,transparent),
  radial-gradient(1.3px 1.3px at 52% 24%,#fff,transparent),radial-gradient(1.1px 1.1px at 67% 9%,#cfe3ff,transparent),
  radial-gradient(1.2px 1.2px at 88% 33%,#fff,transparent),radial-gradient(1.1px 1.1px at 96% 62%,#dce9ff,transparent),
  radial-gradient(1.3px 1.3px at 4% 44%,#fff,transparent),radial-gradient(1.1px 1.1px at 79% 83%,#e7d6ff,transparent),
  radial-gradient(1.2px 1.2px at 24% 92%,#fff,transparent),radial-gradient(1.1px 1.1px at 47% 60%,#fff,transparent);
  animation:lwTwinkle 7s ease-in-out infinite .9s}
/* ── SPACE BACKDROP v3 ──────────────────────────────────────────────────────────────────────
   AMBIENT COLOUR comes first: three broad, heavily-blurred washes that tint the whole sky so the
   backdrop has depth and temperature instead of being a flat dark field with objects pasted on it.
   Cool indigo aloft, a warm plum bloom behind the room's apex, and a teal counter-light low right —
   the same three-light logic you'd use to light a set. Every layer is static (no animation) so it
   costs nothing per frame and PERF LITE leaves it alone. */
.lw-amb{position:absolute;pointer-events:none;border-radius:50%;filter:blur(90px)}
.lw-amb1{left:-14%;top:-22%;width:82%;height:78%;background:radial-gradient(50% 50% at 50% 50%,#4c2a8f5c,transparent 72%)}
.lw-amb2{left:22%;top:-10%;width:66%;height:62%;background:radial-gradient(50% 50% at 50% 50%,#b0468f4a,transparent 70%)}
.lw-amb3{right:-16%;bottom:-20%;width:76%;height:70%;background:radial-gradient(50% 50% at 50% 50%,#1f7d9c52,transparent 72%)}
/* a low warm horizon bloom behind the room's apex ties the sky to the firelit interior */
.lw-amb4{position:absolute;left:14%;bottom:-26%;width:72%;height:52%;pointer-events:none;border-radius:50%;
  filter:blur(80px);background:radial-gradient(50% 50% at 50% 50%,#c9713a3d,transparent 74%)}
#learnview[data-lw-theme="day"] .lw-amb4{opacity:0}
#learnview[data-lw-theme="day"] .lw-amb{opacity:0}

/* ═══ AURORA BOREALIS ═══════════════════════════════════════════════════════════════════════
   Four curtains, each a vertical-striation gradient (the striations are what make an aurora read as
   an aurora rather than a coloured smudge), soft-masked at the edges, screen-blended over the sky.
   Two independent loops per ribbon: `auDrift*` morphs the SHAPE (skew, rotation, vertical stretch,
   travel) and `auHue` walks the HUE a full turn, so the colours and the pattern both change
   continuously without ever snapping. Long, prime-ish, negatively-offset durations mean the four
   never resynchronise into a visible repeat.
   Lead colours are green→teal on purpose: the room is violet, so a complement reads as LIGHT in the
   sky instead of more of the same haze. The hue walk carries them through jade, cyan, magenta and
   gold across a couple of minutes. ═══ */
.lw-aurora{position:absolute;inset:-16% -24% auto -24%;height:88%;pointer-events:none;
  overflow:hidden;mix-blend-mode:screen;opacity:1;filter:blur(14px) saturate(1.45)}
.lw-au{position:absolute;left:0;right:0;height:74%;transform-origin:50% 0;
  background:
    repeating-linear-gradient(94deg,transparent 0 11px,#ffffff26 11px 13px,transparent 13px 27px),
    repeating-linear-gradient(88deg,transparent 0 29px,#ffffff1a 29px 33px,transparent 33px 61px),
    linear-gradient(180deg,transparent 0,var(--c1) 22%,var(--c2) 58%,transparent 94%);
  -webkit-mask-image:radial-gradient(140% 82% at 50% 32%,#000 44%,#0009 70%,transparent 90%);
  mask-image:radial-gradient(140% 82% at 50% 32%,#000 44%,#0009 70%,transparent 90%)}
.lw-au1{--c1:#2bff9eb8;--c2:#12d0ff6b;top:-8%;animation:auDrift 53s ease-in-out infinite,auHue 118s linear infinite}
.lw-au2{--c1:#7cff5f8f;--c2:#5fb9ff5c;top:4%;height:64%;animation:auDrift2 71s ease-in-out infinite -13s,auHue 118s linear infinite -37s}
.lw-au3{--c1:#ff5fd275;--c2:#2bffd152;top:-14%;height:82%;animation:auDrift3 89s ease-in-out infinite -31s,auHue 118s linear infinite -79s}
.lw-au4{--c1:#9affc76b;--c2:#3ea0ff47;top:12%;height:52%;animation:auDrift2 101s ease-in-out infinite -47s,auHue 118s linear infinite -100s}
@keyframes auHue{to{filter:hue-rotate(360deg)}}
@keyframes auDrift{
  0%,100%{transform:skewX(-13deg) rotate(-6deg) translate3d(-5%,0,0) scaleY(1)}
  28%{transform:skewX(-3deg) rotate(-1deg) translate3d(2%,-4%,0) scaleY(1.28)}
  57%{transform:skewX(-20deg) rotate(-10deg) translate3d(7%,3%,0) scaleY(.82)}
  81%{transform:skewX(-8deg) rotate(-4deg) translate3d(-2%,-2%,0) scaleY(1.12)}}
@keyframes auDrift2{
  0%,100%{transform:skewX(11deg) rotate(4deg) translate3d(4%,2%,0) scaleY(.92)}
  34%{transform:skewX(2deg) rotate(1deg) translate3d(-4%,-3%,0) scaleY(1.22)}
  68%{transform:skewX(18deg) rotate(8deg) translate3d(6%,4%,0) scaleY(.86)}}
@keyframes auDrift3{
  0%,100%{transform:skewX(-19deg) rotate(3deg) translate3d(3%,-2%,0) scaleY(1.06)}
  40%{transform:skewX(-6deg) rotate(-5deg) translate3d(-6%,3%,0) scaleY(.88)}
  72%{transform:skewX(-24deg) rotate(6deg) translate3d(5%,-4%,0) scaleY(1.3)}}
/* stillness modes keep the curtains — they just stop moving (a static aurora is still beautiful) */
#learnview[data-lw-calm] .lw-au,#learnview[data-lw-perf="lite"] .lw-au{animation:none}
#learnview[data-lw-perf="lite"] .lw-aurora{filter:blur(18px);opacity:.7}
#learnview[data-lw-perf="lite"] .lw-au4{display:none}
@media (prefers-reduced-motion:reduce){.lw-au{animation:none!important}}
#learnview[data-lw-theme="day"] .lw-aurora{opacity:0}

/* a faint galactic band running across the sky — dense dust plus a scatter of small stars, angled
   so it crosses behind the room rather than lining up with it */
.lw-milky{position:absolute;left:-30%;top:-10%;width:160%;height:120%;pointer-events:none;
  transform:rotate(-24deg);opacity:.62;
  background:
    radial-gradient(1.1px 1.1px at 12% 46%,#fff,transparent),radial-gradient(1px 1px at 21% 52%,#e6ecff,transparent),
    radial-gradient(1.2px 1.2px at 33% 44%,#fff,transparent),radial-gradient(1px 1px at 44% 55%,#dfe8ff,transparent),
    radial-gradient(1.1px 1.1px at 56% 47%,#fff,transparent),radial-gradient(1px 1px at 67% 53%,#e9e0ff,transparent),
    radial-gradient(1.2px 1.2px at 78% 45%,#fff,transparent),radial-gradient(1px 1px at 88% 51%,#e6ecff,transparent),
    linear-gradient(0deg,transparent 42%,#c9b8ff14 48%,#e8dcff1f 50%,#c9b8ff14 52%,transparent 58%)}

/* ── banded ringed gas giant, cratered moon, ember dwarf, nebulae, comets ── */
.lw-neb{position:absolute;border-radius:50%;filter:blur(42px);pointer-events:none}
.lw-n1{width:460px;height:280px;left:6%;top:2%;background:radial-gradient(50% 50% at 50% 50%,#7c3aed24,transparent 70%)}
.lw-n2{width:560px;height:320px;right:-8%;bottom:6%;background:radial-gradient(50% 50% at 50% 50%,#2563eb20,transparent 70%)}
/* two more, warmer and cooler, to break the purple/blue duotone */
.lw-n3{width:380px;height:240px;left:38%;top:-6%;background:radial-gradient(50% 50% at 50% 50%,#e0559626,transparent 72%)}
.lw-n4{width:300px;height:200px;left:2%;bottom:12%;background:radial-gradient(50% 50% at 50% 50%,#2fb5a81f,transparent 72%)}
.lw-planet{position:absolute;border-radius:50%;will-change:transform}
/* ═══ GAS GIANT — banding in four widths instead of one repeat, a great-spot storm, limb darkening
   on the lower-right (matching the room's key light from upper-left) and the ring's own shadow cast
   across the disc. The ring gets a bright inner edge and a gap. ═══ */
.lw-p1{width:230px;height:230px;left:-64px;bottom:-60px;
  background:
    radial-gradient(circle at 32% 26%,#ffffff3d 0%,transparent 40%),
    radial-gradient(38% 13% at 62% 58%,#ffd9a84d 0%,#e8935e33 55%,transparent 78%),
    linear-gradient(172deg,transparent 0 30%,#0000004a 33% 37%,transparent 40%),
    repeating-linear-gradient(170deg,
      #9d6ff5 0 9px,#8b5cf6 9px 17px,#7440dd 17px 24px,#a97cf8 24px 30px,
      #6a33d6 30px 41px,#8b5cf6 41px 48px,#5b2ab8 48px 60px),
    radial-gradient(circle at 50% 50%,#7c3aed,#43197f);
  box-shadow:0 0 130px -10px #a855f775,inset -34px -40px 78px #000000c4,inset 12px 14px 46px #ffffff26;
  opacity:.85;animation:lwFloat 34s ease-in-out infinite}
/* the ring: two arcs so it reads as a ring WITH a gap, brighter on the sunward side */
.lw-p1::after{content:"";position:absolute;left:-28%;right:-28%;top:41%;bottom:33%;border-radius:50%;
  border:7px solid #d9c6ff3d;border-top-color:transparent;border-bottom-color:#efe4ff52;
  transform:rotate(-14deg) scaleY(.34);box-shadow:0 6px 22px #a78bfa38,inset 0 0 12px #ffffff1f}
.lw-p1::before{content:"";position:absolute;left:-20%;right:-20%;top:46%;bottom:40%;border-radius:50%;
  border:2.5px solid #f0e6ff2e;border-top-color:transparent;
  transform:rotate(-14deg) scaleY(.32)}

/* ═══ MOON — a real terminator (lit from upper-left, falling to a dark limb), maria patches, and
   craters that each carry a bright rim and an interior shadow rather than being flat dots. ═══ */
.lw-p2{width:96px;height:96px;right:7%;top:9%;
  background:
    radial-gradient(circle at 28% 26%,#ffffff26 0 12%,transparent 34%),
    radial-gradient(20% 16% at 62% 40%,#8f98cc4d,transparent 70%),
    radial-gradient(16% 13% at 38% 64%,#8992c74a,transparent 70%),
    radial-gradient(13% 11% at 70% 70%,#8b94c93d,transparent 70%),
    radial-gradient(circle at 30% 30%,#f6f7ff,#c8cdf0 42%,#9aa2d8 66%,#5f68b8 84%,#2f3470);
  box-shadow:0 0 60px -6px #9fb0ff5c,inset -13px -15px 30px #000000a3;
  opacity:.94;animation:lwFloat 42s ease-in-out infinite reverse}
/* craters: rim highlight + inner shadow, several sizes */
.lw-p2::before{content:"";position:absolute;inset:0;border-radius:50%;
  background:
    radial-gradient(circle at 63% 38%,#ffffff3d 0 6.4%,#00000042 7% 8.6%,transparent 9.4%),
    radial-gradient(circle at 40% 66%,#ffffff33 0 4.6%,#0000003b 5.2%,transparent 6.6%),
    radial-gradient(circle at 74% 68%,#ffffff2b 0 3.6%,#00000038 4.2%,transparent 5.4%),
    radial-gradient(circle at 50% 20%,#ffffff2b 0 3.2%,#00000030 3.8%,transparent 5%),
    radial-gradient(circle at 26% 44%,#ffffff26 0 2.6%,#0000002b 3.2%,transparent 4.2%),
    radial-gradient(circle at 55% 55%,#ffffff21 0 2.2%,#00000026 2.8%,transparent 3.6%)}
/* terminator — the unlit limb, plus a faint atmosphere-free hard edge */
.lw-p2::after{content:"";position:absolute;inset:0;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle at 22% 22%,transparent 44%,#0b0a1f5c 74%,#07061680 100%);
  box-shadow:inset -2px -2px 6px #0006}
.lw-p3{width:26px;height:26px;left:71%;top:5%;
  background:radial-gradient(circle at 35% 30%,#ffd9a8,#c2703d 60%,#75391a);
  box-shadow:0 0 20px -2px #ffb36b55;opacity:.85;animation:lwFloat 48s ease-in-out infinite}
.lw-shoot{position:absolute;top:16%;left:58%;width:110px;height:2.5px;border-radius:3px;
  background:linear-gradient(90deg,transparent,#cfe4ff 55%,#fff);box-shadow:0 0 9px 1px #bcd8ff59;
  opacity:0;transform:rotate(24deg);animation:lwShoot 10s ease-in infinite 3s}
.lw-shoot2{top:33%;left:44%;width:80px;animation-duration:14s;animation-delay:8s}
.lw-shoot3{top:7%;left:82%;width:128px;animation-duration:17s;animation-delay:12s}
@keyframes lwTwinkle{0%,100%{opacity:.55}50%{opacity:1}}
@keyframes lwFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-16px)}}
@keyframes lwShoot{0%{opacity:0;transform:translate(0,0) rotate(24deg) scaleX(.4)}4%{opacity:1}15%{opacity:0;transform:translate(-280px,120px) rotate(24deg) scaleX(1)}100%{opacity:0;transform:translate(-280px,120px) rotate(24deg)}}
@media (prefers-reduced-motion:reduce){.lw-s1,.lw-s2,.lw-planet,.lw-shoot{animation:none!important}.lw-shoot{display:none}}
/* the ambient washes and the galactic band are static by design — nothing to disable for LITE or
   reduced-motion, but the extra nebulae follow the same blur budget as the originals */
#learnview[data-lw-perf="lite"] .lw-n3,#learnview[data-lw-perf="lite"] .lw-n4{display:none}
#learnview[data-lw-perf="lite"] .lw-milky{opacity:.34}

/* control dock sits directly beneath the title (left-aligned), not floating centre */
.lw-shell .lw-dock{left:14px;transform:none}
/* phones: the two-row 160px dock block sat straight over the middle of the room — collapse to a
   single slim scrollable strip pinned at the stage top */
@media (max-width:640px){
  .lw-shell .lw-dock{left:8px;right:8px;transform:none;max-width:none;flex-wrap:nowrap;overflow-x:auto;
    justify-content:flex-start;padding:6px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .lw-shell .lw-dock::-webkit-scrollbar{display:none}
  .lw-shell .lw-dock button{width:38px;height:38px;flex:0 0 auto}
  .lw-shell .lw-dock .lw-go{width:auto;min-width:84px}
  .lw-shell .lw-dock .lw-dgrp{flex:0 0 auto}
}

/* "first in tonight" cozy popup (replaces the always-on centre text) */
.lw-firstpop{position:absolute;z-index:7;left:50%;top:14px;transform:translateX(-50%);max-width:min(86%,420px);
  display:flex;gap:9px;align-items:center;padding:10px 14px;border-radius:14px;
  background:linear-gradient(100deg,#241a3ee8,#1a1330e8);border:1px solid #ffd47955;
  box-shadow:0 14px 40px -12px #000a,0 0 22px -8px #ffd47966;color:#f3eefe;font-size:12.5px;line-height:1.35;
  animation:lwPopIn .32s cubic-bezier(.2,1.1,.3,1)}
.lw-firstpop .lw-fp-ic{font-size:18px;flex:0 0 auto}
@keyframes lwPopIn{from{opacity:0;transform:translate(-50%,-8px)}to{opacity:1;transform:translate(-50%,0)}}

/* ── Knowledge-base switcher above the lounge (owner request: Library pill = the room, pills ride along) ── */
.lw-kbnav{display:flex;gap:8px;flex-wrap:wrap;margin:0 auto 10px;max-width:1100px;padding:0 2px}
.lw-kbnav .atbtn{white-space:nowrap}
@media(min-width:1024px){ .lw-kbnav{max-width:none} }
/* These are the SAME six pills as #gsecswitch, rendered by the same kkKnowledgeNav(); they must
   also LOOK the same. The desktop track in client.css is ID-scoped to #gsecswitch, so it never
   reached this copy and the lounge kept the bare .atbtn.sm size — measured 124x32 @12.5px here
   against 216x52 @12.5px under Info/Help at a 1440px viewport. Leaving theater is when the
   mismatch is noticed (the room stops covering the row), but it was never a theater bug.
   learn.css loads AFTER client.css, so the numbers are restated here rather than in the peer
   rule — an equal-specificity `.lw-kbnav` there would lose the tie to line 670 above. */
@media(min-width:761px){
  /* padding:0 — the 2px side inset above is for the phone scroll row; on the desktop track it
     just pulls the pills 2px in from the room edge they are supposed to line up with. */
  .lw-kbnav{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:10px;margin-bottom:14px;padding:0}
  .lw-kbnav .atbtn{width:100%;min-height:52px;justify-content:center;gap:8px;padding:10px 12px;border-radius:14px;font-size:12.5px;letter-spacing:.04em}
  .lw-kbnav .atbtn .kk-ic{width:17px;height:17px;flex:0 0 auto}
}
@media(max-width:760px){
  .lw-kbnav{flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;padding-bottom:4px;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .lw-kbnav::-webkit-scrollbar{display:none}
  .lw-kbnav .atbtn{flex:0 0 auto;min-height:44px}
}

/* ── AUDIT/mobile pass: firelight on shelves · live screens · Kara bubble · covers · PERF LITE ── */
.lw-firewash{opacity:.32;mix-blend-mode:screen;pointer-events:none;animation:lwFireBreathe 3.4s ease-in-out infinite}
@keyframes lwFireBreathe{50%{opacity:.44}}
.lw-scr-line{stroke-dasharray:220;stroke-dashoffset:220;animation:lwScrDraw 5.5s linear infinite}
@keyframes lwScrDraw{0%{stroke-dashoffset:220}55%{stroke-dashoffset:0}82%{stroke-dashoffset:0;opacity:1}92%{opacity:.2}100%{stroke-dashoffset:220;opacity:1}}
.lw-scr-cursor{animation:lwScrBlink 1.1s steps(1) infinite}
@keyframes lwScrBlink{50%{opacity:0}}
.lw-kbubble{position:absolute;left:26%;bottom:16%;z-index:40;max-width:min(320px,72%);padding:13px 15px;border-radius:18px 18px 18px 5px;
  background:linear-gradient(135deg,#2a1a3ee8,#1b1230f0);border:1.5px solid #f472b688;color:#f3eefe;font:600 13px/1.5 system-ui,sans-serif;
  box-shadow:0 16px 44px -10px #000c,0 0 26px -8px #f472b666;animation:lwPopIn .3s cubic-bezier(.2,1.1,.3,1)}
.lw-kb-dots{display:flex;gap:5px;padding:4px 2px}
.lw-kb-dots i{width:7px;height:7px;border-radius:50%;background:#cdb8f0;animation:lwKbDot 1s ease-in-out infinite}
.lw-kb-dots i:nth-child(2){animation-delay:.16s}.lw-kb-dots i:nth-child(3){animation-delay:.32s}
@keyframes lwKbDot{40%{transform:translateY(-4px);opacity:1}80%{opacity:.4}}
.lw-kb-btns{display:flex;gap:7px;flex-wrap:wrap;margin-top:10px}
.lw-kb-btns button{background:#ffffff14;border:1px solid #ffffff2c;border-radius:11px;color:#f3eefe;font:700 11.5px system-ui,sans-serif;padding:8px 11px;cursor:pointer;min-height:36px}
.lw-kb-btns button:active{transform:scale(.96)}
/* the bubble's ✕ — it had no exit control at all, and it sits over the desk hotspot that used to be
   the only way to dismiss it. 30px clears the WCAG 2.5.8 24px target minimum. */
.lw-kb-x{position:absolute;top:6px;right:6px;width:30px;height:30px;padding:0;line-height:0;display:grid;place-items:center;
  border-radius:50%;border:1px solid #ffffff2c;background:#ffffff14;color:#f3eefe;cursor:pointer}
.lw-kb-x:hover{background:#ffffff26}
.lw-kb-x:active{transform:scale(.92)}
.lw-kb-txt{padding-right:26px}
.lw-bk .lw-spine.lw-cov{width:44px;height:60px;background:none;border-radius:5px;overflow:hidden;flex:0 0 auto}
.lw-bk .lw-spine.lw-cov svg{width:100%;height:100%;display:block}
.lw-mus-note{flex:1 1 100%;font:600 10px system-ui,sans-serif;color:#9f97c9;line-height:1.45;padding:2px 2px 4px}
/* ═══ PERF LITE (phones / low-memory): the ambient DECORATION goes static — the room, avatars,
   walking, panels are untouched. Kills the constant compositing that tanked mobile FPS. ═══ */
#learnview[data-lw-perf="lite"] .lw-neb,#learnview[data-lw-perf="lite"] .lw-shoot{display:none}
#learnview[data-lw-perf="lite"] .lw-p1,#learnview[data-lw-perf="lite"] .lw-p2,#learnview[data-lw-perf="lite"] .lw-p3,
#learnview[data-lw-perf="lite"] .lw-p1::after,#learnview[data-lw-perf="lite"] .lw-p2::before{animation:none!important}
#learnview[data-lw-perf="lite"] .lw-stars,#learnview[data-lw-perf="lite"] .lw-s1,#learnview[data-lw-perf="lite"] .lw-s2{animation:none!important}
#learnview[data-lw-perf="lite"] .lw-firewash{animation:none;opacity:.36}
#learnview[data-lw-perf="lite"] .lw-scr-line{animation:none;stroke-dashoffset:0}
/* LITE exists because phones dropped under 30fps, and three flame layers + the glow pool are
   exactly the always-on compositing it was created to kill. Keep ONE slow flame so the hearth is
   still alive; freeze the rest (they stay drawn, just static). */
#learnview[data-lw-perf="lite"] .lw-flame{animation-duration:3.2s}
#learnview[data-lw-perf="lite"] .lw-flame2,
#learnview[data-lw-perf="lite"] .lw-flame3,
#learnview[data-lw-perf="lite"] .lw-firepool{animation:none}
#learnview[data-lw-perf="lite"] .lw-spark{animation:none;opacity:0}
#learnview[data-lw-perf="lite"] .lw-dock{backdrop-filter:none;-webkit-backdrop-filter:none}
#learnview[data-lw-perf="lite"] .lw-av .lw-bob{animation:none}
#learnview[data-lw-perf="lite"] #lwCanvas{display:none}   /* the canvas carries .lw-fx + this id; there is no .lw-canvas */
#learnview[data-lw-perf="lite"] .lw-stage{contain:layout paint}

/* ═══ Room lighting detail: under-shelf LEDs, sconce cones, firelight on the floor ═══ */
.lw-uled{mix-blend-mode:screen}
.lw-neonspill{mix-blend-mode:screen;pointer-events:none}
.lw-patina{pointer-events:none;mix-blend-mode:multiply}
#learnview[data-lw-theme="day"] .lw-wallao{opacity:.08}
#learnview[data-lw-theme="day"] .lw-neonspill{opacity:.05}
.lw-sconcecone{mix-blend-mode:screen;pointer-events:none}
.lw-firefloor{mix-blend-mode:screen;pointer-events:none;animation:lwFireFloor 5.2s ease-in-out infinite}
@keyframes lwFireFloor{0%,100%{opacity:calc(var(--lw-fireI) * .85)}50%{opacity:var(--lw-fireI)}}
#learnview[data-lw-calm] .lw-firefloor,
#learnview[data-lw-perf="lite"] .lw-firefloor{animation:none}
@media (prefers-reduced-motion:reduce){.lw-firefloor{animation:none}}
/* daylight washes the warm pools out — the fire competes with the windows */
#learnview[data-lw-theme="day"] .lw-firefloor{opacity:calc(var(--lw-fireI) * .45)}
#learnview[data-lw-theme="day"] .lw-sconcecone{opacity:.04}

/* ═══ EXPANSION 1 — unread books breathe. Only BUILT + unfinished spines carry .lw-fresh, so the
   room doubles as a progress display: a faint accent glow that fades out as you finish things. ═══ */
#lwShelves3d .lw-fresh{animation:lwFresh 3.6s ease-in-out infinite;animation-delay:var(--lw-fd,0s)}
@keyframes lwFresh{0%,100%{filter:none}50%{filter:drop-shadow(0 0 5px currentColor)}}
#learnview[data-lw-calm] .lw-fresh,#learnview[data-lw-perf="lite"] .lw-fresh{animation:none}
@media (prefers-reduced-motion:reduce){#lwShelves3d .lw-fresh{animation:none}}

/* ═══ EXPANSION 4 — the daily-quest poster is a control, so it gets an affordance ═══ */
#lwQuest{transition:filter .18s ease}
#learnview .lw-hot[data-hot="quest"]:hover .lw-ring,
#learnview .lw-hot[data-hot="quest"]:focus-visible .lw-ring{border-color:var(--lw-gold);box-shadow:0 0 22px -4px var(--lw-gold)}

/* ═══ POSTER LABS — the zoomed-in, hands-on version of a poster ═══════════════════════════════
   Mounted inside .lw-stage so the room stays visible (and zoomed) behind the glass. */
/* The card is dark in BOTH themes, so pin the ink vars to their night values inside it — otherwise
   every child that reads --lw-ink / --lw-muted (the Back button, the footer note) turns dark-on-dark
   the moment the day theme is on. */
.lw-lab{--lw-ink:#f3eefe;--lw-muted:#b3a8cf;--lw-panelEdge:#3a2c5e;
  position:absolute;inset:0;z-index:60;display:grid;place-items:center;padding:16px;
  background:radial-gradient(120% 100% at 50% 0%,#0c082066,#060412cc 70%);backdrop-filter:blur(6px);
  animation:labIn .26s cubic-bezier(.2,1.05,.3,1)}
.lw-lab.out{animation:labOut .18s ease-in forwards}
@keyframes labIn{from{opacity:0}to{opacity:1}}
@keyframes labOut{to{opacity:0}}
/* Flex column so the title and the FOOTER always survive, and the instrument gives up space instead:
   the SVG carries a viewBox, so when flex shrinks its box the drawing scales to fit rather than
   reflowing. Before this, the order-flow ladder overflowed a 626px card by 48px and pushed its own
   honesty note ("Illustrative depth…") 31px below the fold, reachable only by scrolling inside the
   card. overflow:auto stays as a last resort for absurdly short viewports. */
.lw-lab-card{width:min(660px,100%);max-height:100%;overflow:auto;border-radius:22px;
  display:flex;flex-direction:column;
  background:linear-gradient(170deg,#1b1436f5,#120d28fa);border:1px solid var(--lw-panelEdge);
  box-shadow:0 26px 70px -22px #000c,0 0 40px -14px var(--lw-neon);
  animation:labCard .3s cubic-bezier(.2,1.05,.3,1)}
@keyframes labCard{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.lw-lab,.lw-lab-card{animation:none}}
.lw-lab-top{display:flex;align-items:flex-start;gap:12px;padding:14px 18px 4px;flex:0 0 auto}
.lw-lab-back{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;
  background:#ffffff10;border:1px solid var(--lw-panelEdge);color:var(--lw-ink);
  font:700 12.5px var(--lw-sign);border-radius:11px;padding:9px 13px;cursor:pointer;min-height:40px;transition:.14s}
.lw-lab-back:hover{background:#ffffff1f;border-color:var(--lw-neon2)}
.lw-lab-ttl{flex:1;min-width:0;text-align:right}
.lw-lab-eye{display:block;font:800 10px var(--lw-sign);letter-spacing:.2em;text-transform:uppercase;color:var(--lw-neonGlow)}
.lw-lab-ttl h3{margin:2px 0 0;font:800 20px var(--lw-sign);letter-spacing:.4px;color:#fff}
.lw-lab-sub{margin:3px 0 0;font:600 11.5px var(--lw-sign);color:#b9aee0;line-height:1.45;max-width:42ch;margin-left:auto}
.lw-lab-note{display:block;margin-top:5px;font:600 10.5px var(--lw-sign);font-style:normal;color:#8f86b3;line-height:1.5}
.lw-lab-svg{display:block;width:100%;height:auto;padding:6px 6px 0;touch-action:none;
  flex:1 1 auto;min-height:0}   /* min-height:0 is what lets a flex item shrink under its content */
.lw-lab-svg text{font-family:var(--lw-sign)}
.lw-lh{cursor:grab}
.lw-lh:active{cursor:grabbing}
.lw-lh circle{transition:r .12s ease}
.lw-lh:hover circle:first-of-type,.lw-lh:focus-visible circle:first-of-type{r:14}
.lw-lh:focus-visible{outline:none}
.lw-lh:focus-visible circle:first-of-type{stroke:var(--lw-gold);stroke-width:4}
.lw-lab-foot{padding:6px 20px 18px;display:flex;flex-direction:column;gap:3px;flex:0 0 auto}
.lw-lab-foot b{font:800 13.5px var(--lw-sign);color:var(--lw-neon2)}
.lw-lab-foot span{font-size:12px;color:var(--lw-muted);line-height:1.5}
/* DAY: only the scrim lightens. The lab CARD stays dark in both themes on purpose — it is an
   instrument panel, and its SVG is drawn in light-on-dark ink (axis labels, the dashed "uncapped"
   ghost line, the book's price column). Flipping the card to a light surface made all of that
   invisible in daylight; one dark treatment keeps every reading legible and matches how the shelf
   signage already behaves. */
#learnview[data-lw-theme="day"] .lw-lab{background:radial-gradient(120% 100% at 50% 0%,#e7ddf3a6,#b9a6d6cc 70%)}
@media (max-width:640px){
  .lw-lab{padding:8px}
  .lw-lab-top{flex-direction:column;align-items:stretch;gap:8px}
  .lw-lab-ttl{text-align:left}
  .lw-lab-ttl h3{font-size:17px}
}

/* ═══ EXPANSION 5 — emote bubbles + the picker strip ═══ */
/* top:78px clears the dock, which is top:12px and ~58px tall (44px buttons + 7px padding each
   side) — measured overlapping it by 8px at top:64px, and by 14px on phones */
/* top:88px — the dock is top:12 and ~64px tall with the grouped wells; an intermittent 6px overlap
   showed up at 78px, so this keeps real headroom rather than sitting on the tolerance */
.lw-emotebar{position:absolute;z-index:9;top:88px;left:14px;display:flex;gap:6px;padding:7px;
  background:var(--lw-chrome,#0c0820e0);border:1px solid var(--lw-panelEdge);border-radius:14px;
  box-shadow:var(--lw-shadow);backdrop-filter:blur(10px);animation:lwPopIn .22s cubic-bezier(.2,1.1,.3,1)}
.lw-emotebar button{width:40px;height:40px;border-radius:11px;border:1px solid #fff1;background:#ffffff0a;
  font-size:19px;cursor:pointer;display:grid;place-items:center;transition:transform .12s ease,background .12s ease;color:var(--lw-ink)}
.lw-emotebar button:hover{background:#ffffff1c;transform:translateY(-2px)}
.lw-emotebar button:active{transform:scale(.94)}
#learnview[data-lw-theme="day"] .lw-emotebar button{background:#4a346f0d;border-color:#4a346f26}
#learnview[data-lw-theme="day"] .lw-emotebar button:hover{background:#4a346f1c}
@media (max-width:640px){.lw-emotebar{top:76px;left:8px;right:8px;overflow-x:auto;scrollbar-width:none}
  .lw-emotebar::-webkit-scrollbar{display:none}.lw-emotebar button{flex:0 0 auto}}
.lw-emote{position:absolute;left:50%;bottom:104%;transform:translateX(-50%);z-index:6;
  display:flex;align-items:center;gap:5px;white-space:nowrap;pointer-events:none;
  padding:5px 10px;border-radius:13px 13px 13px 4px;background:var(--lw-chrome,#0c0820ee);
  border:1px solid var(--lw-panelEdge);box-shadow:var(--lw-shadow);
  font:600 11.5px/1 "Outfit",system-ui,sans-serif;color:var(--lw-ink);
  animation:lwEmote .28s cubic-bezier(.2,1.2,.3,1)}
.lw-emote .lw-em-g{font-size:15px;line-height:1}
@keyframes lwEmote{from{opacity:0;transform:translate(-50%,6px) scale(.9)}to{opacity:1;transform:translate(-50%,0) scale(1)}}
@media (prefers-reduced-motion:reduce){.lw-emote{animation:none}}

/* ═══ EXPANSION 2 — mantel clock: the hands are set by script; only the case gets a hover cue ═══ */
.lw-clock{transition:filter .2s ease}

/* ── day-mode chrome: every translucent-white surface tuned for midnight flips to a plum tint
   that reads on light ground (the vars flip the big surfaces; these are the small accents) ── */
/* `:not([aria-pressed="true"])` is load-bearing. This selector carries an ID, so it out-specifies
   `.lw-dock button[aria-pressed="true"]`, and `background` is a SHORTHAND — without the exclusion it
   reset background-image to none and the pressed pill's gradient vanished in daylight (measured:
   pressed.bgImg === "none"). Never let a theme override the same shorthand a state rule owns. */
#learnview[data-lw-theme="day"] .lw-dock button:not([aria-pressed="true"]),
#learnview[data-lw-theme="day"] .lw-music button{background:#4a346f0d;border-color:#4a346f26}
#learnview[data-lw-theme="day"] .lw-dock button:not([aria-pressed="true"]):hover,
#learnview[data-lw-theme="day"] .lw-music button:hover{background:#4a346f1c}
#learnview[data-lw-theme="day"] .lw-x,
#learnview[data-lw-theme="day"] .lw-btn{background:#4a346f0d}
#learnview[data-lw-theme="day"] .lw-btn:hover,
#learnview[data-lw-theme="day"] .lw-x:hover{background:#4a346f1a}
#learnview[data-lw-theme="day"] .lw-btn.primary{background:linear-gradient(120deg,var(--lw-neon),#8a5cff);color:#fff}
#learnview[data-lw-theme="day"] .lw-track{background:linear-gradient(160deg,#4a346f0e,#4a346f04)}
#learnview[data-lw-theme="day"] .lw-bk{background:#4a346f0a}
#learnview[data-lw-theme="day"] .lw-bk:hover{background:#4a346f16}
#learnview[data-lw-theme="day"] .lw-bk.soon:hover{background:#4a346f0a}
#learnview[data-lw-theme="day"] .lw-libchip{background:#4a346f0f}
#learnview[data-lw-theme="day"] .lw-libchip:hover{background:#4a346f1e}
#learnview[data-lw-theme="day"] .lw-chip,
#learnview[data-lw-theme="day"] .lw-optrow{background:#4a346f08}
#learnview[data-lw-theme="day"] .lw-roster .lw-pin{background:#e4d8f4;border-color:#f7f1fc}
#learnview[data-lw-theme="day"] .lw-libmsg.me .lw-libtext{color:#fff}
#learnview[data-lw-theme="day"] .lw-switch{background:#4a346f22}
/* daylight shadows are warm and soft, not black grime */
#learnview[data-lw-theme="day"] .lw-shade{fill:#6b563f;opacity:.16}
#learnview[data-lw-theme="day"] .lw-switch[aria-checked="true"]{background:var(--lw-ok)}

/* G10 · Group Dojo card inside the co-read feed */
.lw-cr-dojo{margin:6px 0;padding:8px 10px;border:1px solid var(--line,#3334);border-radius:10px;background:rgba(110,168,254,.06)}
.lw-cr-dq{font-size:12.5px;font-weight:600;margin-bottom:4px}
.lw-cr-spark{display:block;width:100%;max-width:220px;height:38px;margin:2px 0 6px}
.lw-cr-drow{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.lw-cr-pk{padding:4px 10px;border:1px solid var(--line,#3335);border-radius:8px;background:transparent;color:var(--ink,inherit);cursor:pointer;font-weight:600;font-size:12px}
.lw-cr-pk:hover{border-color:var(--acc,#6ea8fe)}
.lw-cr-dpicks{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}
.lw-cr-pick{font-size:10.5px;padding:2px 6px;border-radius:6px;background:rgba(127,127,127,.15);color:var(--mut,#889)}
.lw-cr-dres{font-size:12px;margin-top:5px;min-height:1px}
