/* ═══════════════════════════════════════════════════════════════════════════
   GERMAN DOMINION — the haven theme.

   Loaded LAST on every page. `dominion.css` keeps its job and its written
   promise: it is the STRUCTURE (grid, panels, tables, controls, page heads) and
   it contains no hue. This file is the LOOK he approved: his red-eye plate as
   a living background, an engraved roman serif in red, a centre axis and
   rounded corners.

   ★ IT IS A LAYER, NOT AN EDIT. Either look is one <link> away, and the sheet
     underneath never has to be un-picked to get back to it. It is loaded after
     a page's own stylesheet too, because `home.css`/`map.css`/`live.css` must
     not be able to out-cascade the theme — the first pass loaded it earlier and
     `home.css` quietly took the boot readout back to grey, with correct bytes
     and a clean console.

   ★★★★★ THE ONE LAW: RED IS LIGHT, NEVER INK.
   Nothing you have to read is red on black at body size. Red is what the scene
   is lit by, it is the wordmark, and it is the live channel. The word / fill /
   hatching status vocabulary underneath survives untouched, so a red-blind
   reader loses nothing they had before. `check_contrast.py` reads these tokens
   straight out of this file and refuses the build if that slips.

   Sections
     1  tokens                     6  data tables + status
     2  the scene                  7  controls
     3  type: the engraved serif   8  the hero + the figure strip
     4  chrome                     9  page furniture
     5  panels as cards           10  motion, reduced motion, responsive
   ═══════════════════════════════════════════════════════════════════════════ */

/* Cinzel is the wordmark voice he approved. Self-hosted like the rest, so the
   site still downloads nothing from anyone. */
@font-face {
  font-family:"Cinzel"; font-style:normal; font-weight:400 900; font-display:swap;
  src:url("fonts/cinzel-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family:"Cinzel"; font-style:normal; font-weight:400 900; font-display:swap;
  src:url("fonts/cinzel-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* ── 1. tokens ───────────────────────────────────────────────────────────── */
:root {
  --void:#000000; --ground:#050408; --panel:#0b0810; --panel-up:#131019;
  --panel-hi:#1a1522;
  --line:#241b2d; --line-up:#33263f; --line-hot:#5b3a6b;

  /* ink stays bone. measured against --panel by check_contrast.py */
  --t-hi:#f6f4f7; --t-body:#cfcad3; --t-sec:#a6a1ab; --t-ter:#948e99;
  --t-dim:#8b8691; --t-off:#5d5566; --blown:#ffffff;

  /* ★★★★★ THE PLATE CHANGED, SO THE LIGHT CHANGED - BUT THE TOKEN NAMES DID
     NOT, AND THAT IS DELIBERATE. He replaced the red-eyed animal with the
     purple one whose eye burns GOLD. Renaming `--ember-*` to `--gold-*` would
     have touched every rule in this sheet, the contrast gate's own token list,
     and any page sheet another wave is writing right now - a rename is the
     most expensive way to record a colour change and the easiest way to break
     a file you are not looking at. The names stay; the VALUES move. "Ember"
     was always the better word for this colour than it was for red.
     The animal's flanks burn violet, so violet is a second family rather than
     a replacement: GOLD is the eye, the wordmark and the live channel; VIOLET
     is the smoke, the flanks and the cold half of the scene. */
  --ember-core:#ffc64d;   /* the lit iris. small text, numbers   12.7:1 */
  --ember-ink:#ffb020;    /* live labels, hot links              10.9:1 */
  --ember:#e8901a;        /* fills, bars, the light source              */
  --ember-deep:#8a5200;   /* the far edge of the glow                   */
  --ember-char:#3a2408;   /* where the smoke meets the dark             */

  --violet-core:#e06bf0;  /* the brightest flame                        */
  --violet-ink:#c24be0;   /* carries a word:                      5.1:1 */
  --violet:#a32bc8;       /* the flanks, the smoke                      */
  --violet-deep:#5b1a73;  /* the far smoke                              */

  /* his reference rounds its corners. dominion.css cuts them; this wins. */
  --cut:10px; --cut-sm:7px; --r:9px; --r-pill:999px;

  --display:"Cinzel", Georgia, "Times New Roman", serif;
  --ui:"Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;
  --data:"JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  --glow-2:0 0 22px -6px rgba(232,144,26,.55);
  --glow-3:0 0 60px -10px rgba(232,144,26,.40);
  --charline:linear-gradient(90deg, rgba(255,176,32,0) 0%, rgba(255,176,32,.45) 22%,
             rgba(255,176,32,.12) 56%, rgba(255,176,32,0) 100%);
  --crush:0 26px 60px -34px #000;
  --lit-edge:inset 0 1px 0 rgba(255,198,77,.10);
  --quick:150ms cubic-bezier(.22,.61,.36,1);
}

html { background:var(--void); scrollbar-color:var(--line-up) var(--void); }
body { background:transparent; color:var(--t-body); }
::selection { background:var(--ember); color:#fff; }
:focus-visible { outline:2px solid var(--ember-core); outline-offset:3px; }
.skip { background:var(--ember); color:#fff; border-radius:var(--r); }

/* ── 2. the scene ────────────────────────────────────────────────────────
   Four plies behind every page. Each can carry the look alone, so a refused
   canvas or a plate that will not decode is a downgrade, never a hole. */
.deep {
  position:fixed; inset:0; z-index:-1; overflow:hidden;
  background:var(--void); pointer-events:none;
}
/* ★ PLACED, NOT COVER-FIT, AND THE ZOOM IS MEASURED.
   RE-MEASURED 2026-08-21 for the purple plate, by the same method: threshold
   the LIT iris (gold now, not red), take the median. It sits at 56.4% / 23.5%
   of a 1536x1024 plate — **a different aspect, 1.5 rather than 1.7275**, so
   the one place this sheet still names an aspect (the --pz max() clause) moved
   with it. `height:auto` carries the rest, which is why the swap was cheap.
   The offsets put the pupil back at 49% / 29% of the frame, where his approved
   layout puts it, WHILE KEEPING THE FLAME FLANKS IN SHOT: this plate is
   composed with the eye top-centre and fire down both sides, and a crop tight
   enough to fill the frame with the eye would throw away the half of the
   picture that makes it this picture. */
.deep-plate {
  --pz:max(118vw, calc(118vh * 1.5));
  --pdx:-7.2%; --pdy:9.8%;
  position:absolute; left:50%; top:50%; max-width:none;
  width:var(--pz); height:auto; opacity:.92;
  transform:translate(-50%,-50%) translate(var(--pdx),var(--pdy))
            translate3d(var(--px,0px),var(--py,0px),0);
  transition:opacity 600ms linear;
}
.deep-cast {
  position:absolute; inset:-10%;
  background:
    radial-gradient(26% 22% at 49% 29%, rgba(255,176,32,.13), rgba(255,176,32,0) 72%),
    radial-gradient(46% 62% at 8% 62%,  rgba(163,43,200,.13), rgba(0,0,0,0) 76%),
    radial-gradient(46% 62% at 92% 58%, rgba(163,43,200,.13), rgba(0,0,0,0) 76%);
  mix-blend-mode:screen;
  transform:translate3d(calc(var(--px,0px) * 2.2), calc(var(--py,0px) * 2.2), 0);
}
#gd-smoke {
  position:absolute; inset:0; width:100%; height:100%;
  mix-blend-mode:screen; opacity:0; transition:opacity 900ms ease-out;
}
#gd-smoke.lit { opacity:.86; }
/* the pupil's glow. Placed on the MEASURED point haven.js publishes, so this
   element and the shader's light source can never drift apart. */
.deep-eye {
  position:absolute; left:var(--eye-x,49%); top:var(--eye-y,29%);
  width:24vmax; height:24vmax; margin:-12vmax 0 0 -12vmax; border-radius:50%;
  background:radial-gradient(circle, rgba(255,198,77,.20) 0%,
    rgba(255,176,32,.10) 20%, rgba(163,43,200,.045) 42%, rgba(0,0,0,0) 70%);
  mix-blend-mode:screen; opacity:var(--eye,.8);
  transform:translate3d(calc(var(--px,0px) * 3), calc(var(--py,0px) * 3), 0);
}
.deep-scrim {
  position:absolute; inset:0;
  background:
    radial-gradient(64% 46% at 50% 40%, rgba(4,2,7,.62), rgba(4,2,7,0) 78%),
    linear-gradient(180deg, rgba(4,2,7,.54) 0%, rgba(4,2,7,.30) 26%,
                    rgba(4,2,7,.52) 58%, rgba(4,2,7,.86) 78%, rgba(4,2,7,.96) 100%);
  opacity:var(--scrim,1);
}
/* ★ HIS CALL, 2026-08-21: "for every tab. it should have the main page
   background. every single tab."
   The earlier build pulled the plate, the smoke and the eye back on every page
   that was not the front door. That is gone. The scene is now IDENTICAL on all
   seventeen pages — same plate, same zoom, same pupil, same smoke — and the
   READABILITY is bought where it belongs instead: the content sits on its own
   panels, which are opaque enough to carry a table over a lit photograph. The
   `data-deep` attribute is still written by the build, but it now only tunes
   the scrim behind long pages of body copy, never the plate itself. */
[data-deep="quiet"] .deep-scrim {
  background:
    radial-gradient(64% 46% at 50% 40%, rgba(4,2,7,.66), rgba(4,2,7,0) 78%),
    linear-gradient(180deg, rgba(4,2,7,.58) 0%, rgba(4,2,7,.40) 26%,
                    rgba(4,2,7,.60) 58%, rgba(4,2,7,.90) 78%, rgba(4,2,7,.96) 100%);
}

/* ── 3. type: the engraved serif ─────────────────────────────────────────── */
.display {
  font-family:var(--display); font-weight:700; font-stretch:normal;
  letter-spacing:.012em; line-height:1.04; text-transform:uppercase;
  color:var(--t-hi);
}
.d1 { font-size:clamp(26px,5.4vw,78px); }
.d2 { font-size:clamp(28px,4.2vw,54px); }
/* mark.js displaces these into bands and snaps them into register on entrance;
   inline-block on the baseline opens a hole under the line, so it sits top */
.display .tear { vertical-align:top; }

/* ★ THE BRACKETS COME OFF, BOTH OF THEM.
   dominion.css draws "[" and "]" around every .inst as ::before/::after. The
   haven look has no brackets - and overriding only ::before left a stray "]"
   sitting after every section head on the built site: a real orphan, on every
   page, that a passing build and a clean console had nothing to say about.
   Kill the PAIR, then re-add the one mark this look does want. */
.inst {
  font-family:var(--display); font-weight:700; font-size:15px;
  letter-spacing:.05em; text-transform:uppercase; color:var(--t-hi);
  gap:0;
}
.inst::before, .inst::after { content:none; }
.inst.plain { font-family:var(--data); }
.lede { color:var(--t-body); }
.k { color:var(--t-dim); }
h3, .panel-h h3 { font-family:var(--display); letter-spacing:.04em; }

/* the rules become a filament: lit at one end, gone at the other */
hr.shard, .rule { border:0; height:1px; background-image:var(--charline);
  background-color:transparent; opacity:.95; }
hr.shard.tall { height:1px; }

/* a section head is centred and carries an eyebrow, the way his hero does */
.sec-h { align-items:center; }
/* a section head, not a page title: big enough to lead, small enough that
   "Filter" over a row of chips does not read as a chapter opening */
.sec-h .inst { font-size:clamp(16px,1.8vw,23px); letter-spacing:.03em; }
.sec-h .inst::before {
  content:""; display:inline-block; flex:0 0 auto;
  width:6px; height:6px; margin-right:11px;
  border-radius:50%; background:var(--ember); box-shadow:var(--glow-2);
}
/* the filament to the right of a section head: lit at the left end, gone by
   the right. At 1px against this ground it needs the extra opacity or it
   simply is not there. */
.sec-h .rule { height:1px; opacity:1;
  background-image:linear-gradient(90deg, rgba(255,176,32,.42) 0%,
                   rgba(255,176,32,.10) 45%, rgba(255,176,32,0) 100%); }
.panel-h .inst { font-size:13px; letter-spacing:.06em; }

/* ── 4. chrome ───────────────────────────────────────────────────────────── */
.chrome {
  background:linear-gradient(180deg, rgba(4,3,4,.88), rgba(4,3,4,.42));
  backdrop-filter:blur(16px) saturate(1.1);
  -webkit-backdrop-filter:blur(16px) saturate(1.1);
  border-bottom:1px solid var(--line);
}
.brand img { filter:drop-shadow(0 0 11px rgba(232,144,26,.6)); }
.brand:hover img { filter:drop-shadow(0 0 17px rgba(255,90,80,.85)); }
.brand-txt b {
  font-family:var(--display); font-weight:700; font-size:13px;
  letter-spacing:.09em; text-transform:uppercase; color:var(--t-hi);
}
.brand-txt span { color:var(--t-dim); }

/* the nav loses its brackets too, and the current page is marked by a lit
   underline instead - the same signal, in this look's own vocabulary */
.nav a { border-radius:var(--r); position:relative; }
.nav a i { display:none; }
.nav a[aria-current="page"] { color:var(--t-hi); }
.nav a[aria-current="page"]::after {
  content:""; position:absolute; left:10px; right:10px; bottom:4px; height:2px;
  border-radius:2px; background:var(--ember); box-shadow:var(--glow-2);
}
.drawer-p a[aria-current="page"] { color:var(--ember-core); }

.tool { border-radius:var(--r); border-color:var(--line-up); }
.tool:hover { border-color:var(--line-hot); color:var(--t-hi); }
.tool[aria-pressed="true"] { color:var(--t-hi); border-color:var(--ember-deep);
  background:rgba(232,144,26,.14); }
kbd { border-radius:5px; border-color:var(--line-up); }
.who-btn, .who-menu { border-radius:var(--r); }
.who-btn img { border-radius:50%; }
.drawer-p { background:rgba(6,5,6,.96); }

.preview-band {
  background:rgba(58,13,14,.5); border-bottom:1px solid var(--line-up);
  color:var(--t-sec);
}

/* ── 5. panels as cards ──────────────────────────────────────────────────
   ★ backdrop-filter is on the chrome and the strips ONLY. An early pass put it
     on every panel; seventeen pages of blurred glass moved a scroll on this box
     from smooth to visibly stepping. Panels get a flat tinted plate that reads
     identically at rest and costs nothing. */
.panel {
  border:1px solid var(--line); border-radius:var(--r);
  background:linear-gradient(180deg, rgba(21,15,16,.94), rgba(8,6,7,.97));
  box-shadow:var(--lit-edge), var(--crush);
  clip-path:none;                      /* the cut corners belong to the old look */
  transition:border-color var(--quick);
}
.panel:hover { border-color:var(--line-up); }
.panel::before, .panel::after { clip-path:none; }
.panel-h {
  border-bottom:1px solid var(--line);
  background:linear-gradient(180deg, rgba(255,176,32,.05), rgba(0,0,0,0)), var(--panel-up);
  border-radius:var(--r) var(--r) 0 0;
}
.panel-f { border-top:1px solid var(--line); background:rgba(6,5,6,.72);
  border-radius:0 0 var(--r) var(--r); }
/* the lit top edge that says this panel carries something live */
.panel.bracketed { position:relative; }
.panel.bracketed::after {
  content:""; position:absolute; left:14px; right:14px; top:0; height:1px;
  background:var(--charline); opacity:.9; pointer-events:none;
}

/* ── 6. data tables + status ─────────────────────────────────────────────── */
.readout tbody tr:hover { background:rgba(232,144,26,.05); }
.readout .ix { color:var(--t-off); font-family:var(--data); }
.readout th { color:var(--t-dim); }
.v.live, .live-b { color:var(--ember-core); text-shadow:0 0 18px rgba(232,144,26,.5); }

.tag { border-radius:var(--r-pill); border-color:var(--line-up); color:var(--t-sec); }
.tag.on {
  color:#fff; border-color:rgba(255,198,77,.55);
  background:linear-gradient(180deg, var(--ember), var(--ember-deep));
  box-shadow:var(--glow-2);
}
.dot { border-radius:50%; }
.dot.live { background:var(--ember-core);
  box-shadow:0 0 0 3px rgba(232,144,26,.18), 0 0 13px 2px rgba(232,144,26,.8); }
.dot.stop { background:var(--t-off); box-shadow:none; }
.bar, .bar > * { border-radius:var(--r-pill); }

/* ── 7. controls ─────────────────────────────────────────────────────────── */
.btn, .act {
  border-radius:var(--r); clip-path:none;
  border:1px solid rgba(255,255,255,.15);
  background:rgba(12,9,10,.62);
  white-space:nowrap;
  transition:transform var(--quick), border-color var(--quick), background var(--quick);
}
.btn:hover, .act:hover {
  transform:translateY(-1px); border-color:rgba(255,198,77,.5);
  background:rgba(22,13,14,.72);
}
.btn.go {
  background:linear-gradient(180deg,#f0a01e,#9a5c05); border-color:#ffc64d; color:#fff;
  box-shadow:0 10px 30px -14px rgba(232,144,26,.9), inset 0 1px 0 rgba(255,255,255,.22);
}
.btn.go:hover { background:linear-gradient(180deg,#ffb92e,#a86608); }
.act i { color:var(--ember-ink); }
input, select, textarea { border-radius:var(--r); }
.seek, .seek-in input { border-radius:var(--r); }

/* ── 8. the hero + the figure strip ──────────────────────────────────────
   Only index.html carries these. They are the layout he approved, and the
   pieces are named for what they are so nothing here collides with the
   structure sheet's vocabulary. */
.hero {
  position:relative; min-height:min(88svh,880px);
  display:grid; place-items:center; padding:clamp(36px,7vh,86px) 20px clamp(36px,7vh,74px);
}
.hero-frame { position:absolute; inset:14px; border:1px solid rgba(255,255,255,.055);
  border-radius:4px; pointer-events:none; }
.hero-in { position:relative; width:100%; max-width:980px; margin:0 auto; text-align:center; }

.pill {
  display:inline-flex; align-items:center; gap:10px; margin:0 0 22px;
  padding:9px 20px; border:1px solid rgba(255,255,255,.13);
  border-radius:var(--r-pill); background:rgba(4,3,4,.6);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  font:600 10px/1 var(--data); letter-spacing:.20em; text-transform:uppercase;
  color:var(--t-sec);
}
.pill .dot.live { animation:gd-pulse 2.4s ease-in-out infinite; }
@keyframes gd-pulse { 0%,100%{opacity:1} 50%{opacity:.45} }

/* ★ ONE LINE. In the layout he approved the wordmark is a single line across
   roughly 44% of the frame. Wrapped to two it doubles the height of the block,
   pushes the pill up over the animal's eye, and loses the engraved-plate look
   the reference gets from one long horizontal. */
.wm {
  margin:0 0 16px; white-space:nowrap;
  font:700 clamp(26px,5.4vw,78px)/1.06 var(--display);
  letter-spacing:.012em; text-transform:uppercase; color:var(--ember);
  text-shadow:0 0 28px rgba(232,144,26,.55), 0 0 90px rgba(232,144,26,.34),
              0 2px 0 rgba(0,0,0,.6);
}
.wm i { font-style:normal; font-size:1.2em; line-height:0; }

.creed {
  margin:0 0 22px; font:600 clamp(12px,1.35vw,17px)/1.4 var(--ui);
  letter-spacing:.34em; text-indent:.34em;    /* the trailing space, undone */
  text-transform:uppercase; color:#e6e2e2;
}
.hero-lede { margin:0 auto 30px; max-width:56ch; color:var(--t-sec);
  font-size:clamp(14px,1.15vw,16px); }
.hero-acts { display:flex; justify-content:center; flex-wrap:wrap; gap:12px; }
.hero-acts .btn { padding:16px 26px; min-height:52px;
  font:700 11px/1 var(--data); letter-spacing:.18em; text-transform:uppercase; }
.slash { width:22px; height:16px; fill:none; stroke:currentColor; stroke-width:2.6;
  stroke-linecap:round; }

.cue { display:inline-flex; flex-direction:column; align-items:center; gap:7px;
  margin-top:clamp(26px,4vh,44px); color:var(--t-off); padding:6px 12px; }
.cue svg { width:20px; height:12px; fill:none; stroke:var(--ember); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; animation:gd-nudge 2.2s ease-in-out infinite; }
.cue span { font:500 9px/1 var(--data); letter-spacing:.30em; text-transform:uppercase; }
@keyframes gd-nudge { 0%,100%{transform:translateY(0)} 50%{transform:translateY(4px)} }

.figures {
  display:grid; grid-template-columns:repeat(4,1fr);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  background:linear-gradient(180deg, rgba(6,5,6,.74), rgba(4,3,4,.88));
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
}
.fig { padding:30px 18px; text-align:center; border-right:1px solid var(--line); }
.fig:last-child { border-right:0; }
.fig .ic { width:32px; height:24px; margin:0 auto 12px; fill:none;
  stroke:var(--ember-ink); stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round;
  filter:drop-shadow(0 0 10px rgba(232,144,26,.55)); }
.fig b { display:block; margin-bottom:6px;
  font:700 clamp(22px,2.4vw,32px)/1 var(--display);
  letter-spacing:.02em; text-transform:uppercase; color:var(--t-hi); }
.fig span { font:500 9.5px/1.4 var(--data); letter-spacing:.20em;
  text-transform:uppercase; color:var(--t-dim); }

/* ── 9. page furniture ───────────────────────────────────────────────────
   Every page that is not the front door gets the same centred head, so a
   reader always lands on the same shape. */
.page-head { text-align:center; }
.page-head .row { display:block; }
.page-head .copy { max-width:74ch; margin:0 auto; }
.page-head .display { margin-bottom:14px; }
.page-head .lede { margin-left:auto; margin-right:auto; max-width:64ch; }
.page-head .page-sub, .page-head .mono {
  color:var(--t-dim); letter-spacing:.2em;
}
.page-head .facts {
  display:flex; flex-wrap:wrap; justify-content:center; gap:0;
  margin:26px auto 0; max-width:920px;
  border:1px solid var(--line); border-radius:var(--r);
  background:rgba(6,5,6,.6);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  overflow:hidden;
}
.page-head .facts > div {
  flex:1 1 0; min-width:150px; padding:14px 18px;
  border-right:1px solid var(--line); text-align:center;
}
.page-head .facts > div:last-child { border-right:0; }
.page-head .facts .k { display:block; margin-bottom:6px;
  font:500 9.5px/1 var(--data); letter-spacing:.2em; text-transform:uppercase; }
.page-head .facts .v { font:500 15px/1 var(--data); color:var(--t-hi); }

.foot { border-top:1px solid var(--line); background:rgba(4,2,7,.72); }
.foot h3 { font-family:var(--display); letter-spacing:.06em; color:var(--t-sec); }
.foot a:hover { color:var(--ember-core); }
.fine { color:var(--t-off); }

/* ★ The skin plates are drawn procedurally in MONOCHROME by shop.js and
   studio.js, which is correct - a skin's texture is data, not decoration, and
   tinting the CANVAS would be lying about what the game will paint. So the
   tint is a CSS filter on the presentation only: the pixels underneath stay
   exactly what the workshop authored. */
.skin-plate canvas, .sheet-plate {
  filter:saturate(.2) sepia(.42) hue-rotate(-24deg) saturate(1.5) brightness(.94);
}
.skin-plate { border-radius:var(--r) var(--r) 0 0; }
.skin, .card, .tile { border-radius:var(--r); }

/* the torn-G canvases inside panels catch the same light as the brand */
canvas[data-mark] { filter:drop-shadow(0 0 26px rgba(232,144,26,.4)); }

/* ── 9b. the live bar ──────────────────────────────────────
   The framework's own strip (`webcore` builds `#wc-livebar` with exactly these
   class names), dressed for this look. It sits fixed at the foot on every page,
   which is where webcore docks it by default.

   ★ The page reserves its height with padding-bottom rather than the bar
     overlapping the footer, so the last line of a page is never hidden behind
     a strip that is always there. */
:root { --livebar-h: 34px; }
body { padding-bottom: var(--livebar-h); }

#wc-livebar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  height: var(--livebar-h);
  display: flex; align-items: center; gap: var(--s4);
  padding: 0 clamp(12px, 2.4vw, 26px);
  background: linear-gradient(180deg, rgba(6,5,6,.86), rgba(4,2,7,.96));
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  border-top: 1px solid var(--line);
  font: 500 10px/1 var(--data); letter-spacing: .16em; text-transform: uppercase;
  color: var(--t-dim);
  /* ★ It is decoration over the page, never a lid on it: a click meant for
     the content behind the strip must not be eaten. The bar itself takes
     pointer events back on. */
  pointer-events: none;
}
#wc-livebar > * { pointer-events: auto; }
#wc-livebar::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: var(--charline); opacity: .55; pointer-events: none;
}

/* ★ .lb-wx IS IN THIS LIST. It is a single child of .lb-mid, so the parent's
   gap does nothing for the two spans INSIDE it - the label and the value ran
   together as one word ("WETTERREGEN") and read as a typo. */
.lb-left, .lb-mid, .lb-right, .lb-wx, .lb-rs {
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
.lb-mid { margin: 0 auto; }
.lb-right { margin-left: auto; }
.lb-k { color: var(--t-off); white-space: nowrap; }
.lb-v { color: var(--t-hi); letter-spacing: .10em; font-weight: 500; white-space: nowrap; }
/* the countdown goes hot in the last quarter of an hour - the WORD is still
   there, the colour is only the fourth signal */
.lb-v.soon { color: var(--ember-core); text-shadow: 0 0 14px rgba(232,144,26,.6); }

.lb-pulse { width: 8px; height: 8px; flex: 0 0 auto; }
.lb-pulse i {
  display: block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--t-off);
}
.lb-pulse.on i {
  background: var(--ember-core);
  box-shadow: 0 0 0 3px rgba(232,144,26,.18), 0 0 12px 2px rgba(232,144,26,.8);
  animation: gd-pulse 2.4s ease-in-out infinite;
}
.lb-pulse.part i { background: #d9d3d4; box-shadow: 0 0 0 3px rgba(255,255,255,.10); }

/* the sparkline. Heights are set by livebar.js on its own one-second tick. */
.lb-bars { display: flex; align-items: flex-end; gap: 2px; height: 13px; }
.lb-bars i {
  display: block; width: 2px; height: 3px; border-radius: 1px;
  background: var(--ember-ink); opacity: .75;
  transition: height 380ms cubic-bezier(.22,.61,.36,1);
}

.lb-sep { width: 1px; height: 12px; background: var(--line-up); flex: 0 0 auto; }

.lb-src {
  padding: 4px 10px; border-radius: var(--r-pill);
  border: 1px solid var(--line-up); color: var(--t-dim);
  letter-spacing: .18em; white-space: nowrap;
}
.lb-src.on {
  color: #fff; border-color: rgba(255,198,77,.5);
  background: linear-gradient(180deg, var(--ember), var(--ember-deep));
  box-shadow: var(--glow-2);
}
.lb-src.part { color: var(--t-hi); border-color: var(--line-hot); }

/* ★ On a phone the middle segment is what goes, not the state. The chip and
   the player count are the two things worth a strip at all. */
@media (max-width: 780px) {
  :root { --livebar-h: 32px; }
  #wc-livebar { gap: 10px; font-size: 9.5px; letter-spacing: .12em; }
  .lb-mid { display: none; }
  .lb-bars { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .lb-pulse.on i { animation: none; }
  .lb-bars i { transition: none; }
}
@media print { #wc-livebar { display: none; } body { padding-bottom: 0; } }

/* ── 10. motion, reduced motion, responsive ─────────────────────────────── */
@media (max-width:900px) {
  /* a phone is portrait: at this zoom the desktop offset would bring the
     plate's own top edge into shot, so it sits higher */
  .deep-plate { --pdy:5%; opacity:.86; }
  .deep-eye { width:40vmax; height:40vmax; margin:-20vmax 0 0 -20vmax; }
  .wm { white-space:normal; font-size:clamp(30px,10vw,52px); }
  .creed { letter-spacing:.22em; text-indent:.22em; }
  .figures { grid-template-columns:repeat(2,1fr); }
  .fig:nth-child(2) { border-right:0; }
  .fig:nth-child(-n+2) { border-bottom:1px solid var(--line); }
  .page-head .facts > div { flex-basis:50%; }
  .chrome { backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px); }
}
@media (prefers-reduced-motion:reduce) {
  /* ★★★★★ NEVER `transform:none` HERE. The plate is PLACED with
     translate(-50%,-50%) plus its two offsets - the parallax is only the third
     term. Killing the whole transform to "stop the motion" threw the plate half
     its own size down and to the right, so a reduced-motion reader got a
     composition nobody ever designed, on every page. The motion is already off
     for them: haven.js zeroes the drift and draws ONE frame, so --px/--py stay
     at 0 and there is nothing left to disable. */
  #gd-smoke { transition:none; }
  .pill .dot.live, .cue svg { animation:none; }
  .btn:hover, .act:hover, .panel:hover { transform:none; }
}
@media print { .deep { display:none; } }

/* ── the chrome's Discord control ─────────────────────────────────────────
   HIS ASK put a Discord button on the front page AND in the chrome, so it is
   one press from all seventeen pages. It lives in the theme layer because the
   chrome is on every page and home.css is only on the front door.

   ★ IT IS NOT RED INK. The label keeps the same bone `--t-sec` as every other
     tool; the brand colour arrives as a border and a glow on hover. A 10px
     uppercase word in red on black is exactly what "RED IS LIGHT, NEVER INK"
     forbids, and a button is not an exception to it.

   ★ THE LABEL SHEDS BEFORE THE TOOL ROW DOES, AND THE TOOL SHEDS BEFORE THE
     ROW OVERFLOWS. Adding a seventh control squeezed `.who-btn` to 18px wide
     at 430px - under the 22px floor `eyeball.py` refuses - so the word goes at
     1180 and the whole control goes at 860, where the burger takes over and
     the drawer carries Discord instead. A control that survives by shrinking
     the control next to it has not survived. */
.dc-tool { text-decoration:none; }
.dc-tool:hover { border-color:var(--line-hot); color:var(--t-hi);
  box-shadow:0 0 18px -8px rgba(232,144,26,.9); }
.dc-tool .dc-ic { color:var(--ember-ink); }
.dc-tool:hover .dc-ic { color:var(--ember-core); }
@media (max-width:1180px) { .dc-tool .dc-tool-t { display:none; }
  .dc-tool { padding:0 9px; } }
@media (max-width:860px) { .chrome-tools .dc-tool { display:none; } }
.drawer-p .dc-drawer { color:var(--ember-ink); }

/* ★ AND BELOW 360px THE NAME GOES TOO, ON EVERY PAGE.
   This one is older than the Discord control and was never mine: at 320px
   `.who-btn` measures 21px wide on index, market, voice and hall alike - under
   the 22px floor - because the avatar plus the name plus the burger plus two
   language buttons will not fit a 320px row however politely they are asked.
   It was invisible because `eyeball.py` tests 1440 and 430 and 320 is neither:
   **a gate's widths are a choice, and a defect can live in the gap between
   two of them.** The name sheds and the avatar keeps the full target. */
@media (max-width:360px) {
  .who-btn b { display:none; }
  .who-btn { padding:0 6px; gap:0; min-width:32px; justify-content:center; }
}
