/* theme-bdibranding.css — the flat bdibranding.com surface, applied ONLY under body.theme-bdibranding.

   The palette tokens live in style.css (body.theme-bdibranding). Tokens alone cannot finish the job:
   the CRT look is also baked into ~30 stylesheets as explicit VT323 declarations, black drop/inset
   shadows, scanline gradients and full-screen glass pseudo-elements that no token reaches. This file
   is the one place that strips those for this theme. It loads LAST (index.html) so it wins source
   order, and every rule is scoped to body.theme-bdibranding — the six CRT phosphor themes never see
   a byte of it.

   Measured from bdibranding.com: bg #0b0b0b, text #f2e8d6, muted copy #b8b0a3, hairline #3b3731,
   Consolas throughout, zero shadow/glow/gradient, one radius (4px), small uppercase labels at
   12px / 650 / 0.11em tracking (micro labels ~10.5px, same tracking).

   The !important declarations below are deliberate and limited to the four properties that DEFINE
   the theme (font-family, text-shadow, box-shadow, border-radius): the stylesheets they override set them with id
   selectors and deep compound selectors across dozens of files, and a theme that loses any one of
   those fights shows a stray VT323 label or a glow. Nothing else here uses !important. */

/* ---- 1 · TYPE: one face, everywhere ------------------------------------------------------------
   Every explicit `font-family: 'VT323'` in the other stylesheets resolves back to body's Consolas.
   Canvas text (ctx.font) is unaffected — it is not CSS. */
body.theme-bdibranding *,
body.theme-bdibranding *::before,
body.theme-bdibranding *::after { font-family: inherit !important; }
/* Every hard px font-size in the app was tuned for VT323, a narrow face with a small x-height.
   Consolas at the same px reads ~12% larger and ~35% wider, which wraps rails and nav items.
   font-size-adjust normalises the x-height instead of retuning hundreds of sizes: glyphs scale,
   layout boxes do not. (Consolas' own aspect is ~0.49.) Inherited, so body alone carries it. */
body.theme-bdibranding { font-size-adjust: 0.44; }
/* readability.css owns the app's type scale through named role tokens (applied with !important).
   After the x-height adjust (x0.9), prose at 18px lands on the site's 16px body copy, so it stays.
   Controls and meta text are uppercase LABELS on the site (12px), and at 16px/14px Consolas they
   overflow the 232px rail — they step down to land at ~12.6px / ~11.7px rendered. */
body.theme-bdibranding { --sn-type-control: 14px; --sn-type-meta: 13px; }

/* ---- 2 · NO GLOW, NO SHADOW --------------------------------------------------------------------
   The site has none. Box-shadow is removed wholesale; the few surfaces whose only visible edge WAS
   a box-shadow ring get a real 1px border back in section 3. Focus rings in this codebase are
   outlines (not box-shadows), so keyboard focus survives; the fallback below covers the rest. */
body.theme-bdibranding *,
body.theme-bdibranding *::before,
body.theme-bdibranding *::after { text-shadow: none !important; box-shadow: none !important; }
body.theme-bdibranding :focus-visible { outline: 1px solid var(--ph); outline-offset: 1px; }

/* ---- 3 · CRT GLASS OFF (HTML layer) ------------------------------------------------------------
   Full-screen scanlines (body::after), the curved-glass vignette (body::before), the 7s flicker,
   and the tube glass over the station feed. The feed's IN-CANVAS CRT pass (world.js drawCRT/
   drawCurve) is a separate, deliberately settings-proof layer and is not touched here. */
body.theme-bdibranding::before,
body.theme-bdibranding::after { display: none; }
body.theme-bdibranding #app { animation: none; }
body.theme-bdibranding :is(.crt-scan, .crt-vignette, .crt-band) { display: none; }
body.theme-bdibranding #stage-wrap::before { background: none; border-radius: 4px; }
body.theme-bdibranding #station { -webkit-mask-image: none; mask-image: none; }
body.theme-bdibranding #station-frame { background: var(--bg); }
body.theme-bdibranding :is(#topbar, #left, #right, #bottombar, #center)::before { background: none; }

/* frames that relied on a box-shadow ring for their edge */
body.theme-bdibranding :is(#topbar, #left, #right, #bottombar, #center, #chat-panel, .panel, .bgf-card) {
  border: 1px solid var(--bdi-line);
}
body.theme-bdibranding :is(#stage-wrap, .tb-stats, .term) { border: 1px solid var(--bdi-line); }

/* ---- 4 · FLAT SURFACES -------------------------------------------------------------------------
   The glass-demo material (on by default) is re-pointed at flat values through its own tokens, so
   every surface built from them flattens together. The compound selector outranks body.glass-demo. */
body.glass-demo.theme-bdibranding {
  --gd-edge: var(--bdi-line);
  --gd-light: transparent;
  --gd-face: var(--panel);
  --gd-hover: var(--ph-faint);
  --gd-shadow: none;
}
/* REFIT's own material tokens (refit-polish.css, declared on .refit-overlay): the glass gradient
   stays a valid image layer — it is used in comma lists ahead of a colour — just a flat one. */
body.theme-bdibranding .refit-overlay {
  --refit-glass: linear-gradient(transparent, transparent);
  --refit-edge: var(--bdi-line);
  --refit-sheet: var(--panel);
}
body.theme-bdibranding :is(#topbar, #left, #right, #bottombar, #center, .panel, .bgf-card) { background: var(--panel); }
body.theme-bdibranding .term,
body.theme-bdibranding .term.feature { background: var(--panel); }
body.theme-bdibranding :is(.ab-router, .st-card) { background: var(--ph-faint); }
body.theme-bdibranding .ov-pod::before { background: none; }
body.theme-bdibranding .fm-cover { background: var(--ph-faint); }
html:has(body.theme-bdibranding) { background: var(--bg); }

/* panel header strips (CREW / COMMS / the sessions rail head / window heads): molded phosphor
   keycap → a plain label over a hairline, the site's section-header pattern */
body.theme-bdibranding :is(#left h3, #chat-panel h3, .ws-head, .term-head) {
  background: none; border-bottom: 1px solid var(--bdi-line); color: var(--ph);
}
body.theme-bdibranding h3::after { background: none; }

/* toasts: the scanlined gradient plate and the molded lamp become flat fills */
body.theme-bdibranding .toast { background-image: none; background-color: var(--panel2); border-color: var(--bdi-line); }
body.theme-bdibranding .toast-lamp { background: var(--sev); }

/* segmented pip-boy meters → solid fills */
body.theme-bdibranding :is(#xpfill, .mc-bar > div, .rt-bar > div, .rt-ctxbar > span) { background: var(--ph); }
body.theme-bdibranding .rt-bar.low > div { background: var(--warn); }

/* ---- 5 · ONE RADIUS ----------------------------------------------------------------------------
   The site uses a single 4px corner. The scale tokens collapse onto it, and every control and
   surface kind is pinned to it — hardcoded corners (5–12px) are spread across a dozen files behind
   id/compound selectors, so this is the fourth defining property that takes !important. Round marks
   (status dots, radios, 50%/999px pills that aren't controls) are not in the list and stay round. */
body.theme-bdibranding { --r-sm: 4px; --r: 4px; --r-lg: 4px; }
body.theme-bdibranding :is(button, input:not([type=radio]), select, textarea, section,
  #topbar, #left, #right, #bottombar, #center, #chat-panel, #stage-wrap, #station-frame,
  .term, .panel, .bgf-card, .bb-menu, .toast, .hint-bubble, #nav-coach, .tb-stats, .ws-head, .refit-dock,
  [class*="card"], [class*="tab"], [class*="filter"], [class*="search"], .crew-row, .ws-row) {
  border-radius: 4px !important;
}

/* ---- 6 · LABELS: small, uppercase, tracked -----------------------------------------------------
   The VT323-era letter-spacing (2–4px) was sized for a pixel face and spreads Consolas apart. Labels
   move to the site's 12px / 650 / 0.11em; micro labels to 10.5px at the same tracking, muted. */
body.theme-bdibranding :is(#left, #right, #chat-panel) h3,
body.theme-bdibranding :is(.bb-grp, .ws-tab, #comms-title, .term-head) {
  font-size: 12px; font-weight: 650; letter-spacing: 0.11em; text-transform: uppercase;
}
body.theme-bdibranding :is(.h3-aux, .cam-label, .cam-rec, .cam-feed, .cam-alt, .tb-lbl, .tb-stat,
  .crew-room, #crew-sum, .logo-sub, .wg-add, #comms-expand, #ws-new) {
  font-size: 10.5px; letter-spacing: 0.11em; text-transform: uppercase;
}
body.theme-bdibranding :is(.h3-aux, .cam-label, .cam-feed, .cam-alt, .tb-lbl, .crew-room, #crew-sum) { color: var(--bdi-muted); }

/* the SESSIONS / PROJECTS / + NEW rail head is a 232px strip (184px of row at the AUTO 115% text
   size): the three labels need ~204px at Consolas' width. The role token is re-scoped on the head, so
   readability.css's own !important rule resolves to the micro-label size here; tracking drops too. */
body.theme-bdibranding #left .ws-head { --sn-type-control: 12px; }
body.theme-bdibranding #left :is(.ws-tab, #ws-new) { letter-spacing: 0; }
body.theme-bdibranding #left .ws-tab { padding-inline: 2px; }
body.theme-bdibranding #left #ws-new { padding: 2px 6px; }

/* dock menus: the item name is a label; its description is copy and must be readable */
body.theme-bdibranding .bb-menu .bb b { font-size: 12px; font-weight: 650; letter-spacing: 0.11em; }
body.theme-bdibranding .bb-menu .bb small { color: var(--bdi-muted); letter-spacing: 0; }

/* body copy on the site is muted; headings stay in the primary cream */
body.theme-bdibranding :is(.crew-status, .ts, .dim) { color: var(--bdi-muted); }

/* HEADINGS + DISPLAY NAMES: the site tightens them (-0.04em at 28–55px). Content h2/h3/h4 inherit
   style.css's 4px panel-header tracking, and the big nameplates carry 3–4px — both were spacing a
   pixel face. Panel-header h3s are labels, not headings, and keep section 6's rule (higher spec). */
body.theme-bdibranding :is(h1, h2, h3, h4),
body.theme-bdibranding :is(.ag-name, .ov-np-name, .ms-lvl-num, .mkt-title, .refit-title, #clock) {
  font-weight: 620; letter-spacing: -0.01em;
}
body.theme-bdibranding .mkt-title { background: none; }
/* uppercase micro labels still at 3px (~0.27em at 11px) → the site's 0.11em */
body.theme-bdibranding :is(.mkt-card-code, .mkt-dos-label, .mkt-seal-code, .mkt-config-ttl, .mkt-sect-h,
  button.mkt-archive-head, .cc-tb-tag, .cc-tb-mode, .refit-dock-head-t, .rt-sub, .fnv-speaker, .q-ns-eyebrow) {
  letter-spacing: 0.11em;
}

/* ---- 7 · BOOT VEIL + FIRST-RUN SPLASH — the light-line composition ------------------------------
   Both screens paint before StationUI.init(). app/theme-boot.js puts the saved theme class (and the
   saved TINT, from the cache applySettings() writes) on <body> at script-eval time, so they render in
   this theme's own colour instead of flashing the shipped amber or the untinted cream.

   THE BOOT VEIL is one composition drawn entirely on the existing markup's pseudo-elements, so
   index.html and every other theme's veil stay byte-identical:
     #screen-boot::before       the full-width light-line through the centre
     #screen-boot::after        HUD edge dashes: two on the left (high + low), a pair on the right by the line
     .boot-veil::before         the ring the line runs into (its fill hides the line inside it)
     .boot-veil::after          the bdibranding symbol at the centre of the ring (a mask, so it paints in --ph)
     .boot-line::before/after   light pulses that run outward along the line while loading (motion only)
   The wordmark + status sit below the ring. .boot-veil is pushed down by MARGIN, never by position or
   transform: either would make it the containing block and drag the screen-wide layers into it.
   Glow is a drop-shadow FILTER (the box-shadow strip in section 2 covers every pseudo-element), scaled
   by the LIGHT-LINES dial. The symbol itself stays crisp: its mask would cut away any glow outside it. */
body.theme-bdibranding #screen-boot { background: var(--bg); overflow: hidden; }
body.theme-bdibranding #screen-boot::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 3px; margin-top: -1.5px;
  background: var(--ph); pointer-events: none;
  filter: drop-shadow(0 0 4px rgba(var(--ph-rgb), calc(0.9 * min(1, var(--glow-level)))))
          drop-shadow(0 0 16px rgba(var(--ph-rgb), calc(0.45 * min(1, var(--glow-level)))));
}
body.theme-bdibranding #screen-boot::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(var(--ph), var(--ph)) left 0 top 5% / 36px 4px no-repeat,
    linear-gradient(var(--ph), var(--ph)) left 0 bottom 7% / 36px 4px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right 0 top calc(50% - 22px) / 36px 4px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right 0 top calc(50% + 20px) / 36px 4px no-repeat;
  filter: drop-shadow(0 0 5px rgba(var(--ph-rgb), calc(0.8 * min(1, var(--glow-level)))));
}
body.theme-bdibranding .boot-veil { opacity: 1; animation: none; margin-top: 196px; }
body.theme-bdibranding .boot-veil::before {
  content: ''; position: absolute; left: 50%; top: 50%; width: 104px; height: 104px; margin: -52px 0 0 -52px;
  z-index: 2; pointer-events: none; box-sizing: border-box;
  border: 3px solid var(--ph); border-radius: 50%; background: var(--bg);
  filter: drop-shadow(0 0 5px rgba(var(--ph-rgb), calc(0.9 * min(1, var(--glow-level)))))
          drop-shadow(0 0 18px rgba(var(--ph-rgb), calc(0.4 * min(1, var(--glow-level)))));
}
/* the symbol is masked TWICE: its own shape, intersected with a conic sweep. At rest the sweep is a full
   360deg (the whole mark); the motion section runs it from 0 so the mark traces itself round the ring. */
@property --bdi-sweep { syntax: '<angle>'; inherits: false; initial-value: 360deg; }
body.theme-bdibranding .boot-veil::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 50px; height: 50px; margin: -25px 0 0 -25px;
  z-index: 3; pointer-events: none;
  background: var(--ph);
  -webkit-mask: url(../assets/brand/bdibranding-symbol-offwhite.svg) center / contain no-repeat,
                conic-gradient(#000 var(--bdi-sweep), transparent 0);
  -webkit-mask-composite: source-in;
          mask: url(../assets/brand/bdibranding-symbol-offwhite.svg) center / contain no-repeat,
                conic-gradient(#000 var(--bdi-sweep), transparent 0);
          mask-composite: intersect;
}
body.theme-bdibranding .boot-mark { color: var(--ph); font-size: 14px; font-weight: 650; letter-spacing: 0.11em; }
body.theme-bdibranding .boot-line {
  color: var(--bdi-muted); font-size: 10.5px; letter-spacing: 0.11em; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid var(--bdi-line);
}
/* the outward pulses: white-hot segments that sit ON the line, under the ring. Invisible at rest. */
body.theme-bdibranding .boot-line::before,
body.theme-bdibranding .boot-line::after {
  content: ''; position: absolute; top: 50%; height: 3px; margin-top: -1.5px; width: 22vw;
  z-index: 1; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent, #fff, transparent);
}
body.theme-bdibranding .boot-line::before { right: 50%; }
body.theme-bdibranding .boot-line::after  { left: 50%; }

/* THE FIRST-RUN SPLASH keeps the site's hero (eyebrow, headline, one solid button) and stands it on a
   light-grid: the perspective floor comes back as glowing lines in --ph, with a horizon light-line
   where it meets the sky and the same HUD edge dashes as the veil. */
/* --bdi-horizon is where the floor meets the sky: low enough that the eyebrow, headline and button all
   stand clear of the grid (the shipped 46vh put the horizon between the eyebrow and the headline) */
body.theme-bdibranding #screen-splash { background: var(--bg); --bdi-horizon: 24vh; }   /* vh rides the TEXT SIZE zoom too: 24vh clears the button at the 115% auto size */
body.theme-bdibranding .sp-floor { height: var(--bdi-horizon); }
body.theme-bdibranding .sp-nebula { display: none; }
body.theme-bdibranding #sp-stars { opacity: 0.35; }   /* the starfield reads --ph-rgb, so it follows the tint, just quieter */
body.theme-bdibranding .sp-grid {
  background:
    repeating-linear-gradient(90deg, rgba(var(--ph-rgb), 0.7) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(0deg, rgba(var(--ph-rgb), 0.7) 0 1px, transparent 1px 56px);
  filter: drop-shadow(0 0 3px rgba(var(--ph-rgb), calc(0.8 * min(1, var(--glow-level)))));
}
body.theme-bdibranding #screen-splash::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: var(--bdi-horizon); height: 2px; pointer-events: none;
  background: var(--ph);
  filter: drop-shadow(0 0 4px rgba(var(--ph-rgb), calc(0.9 * min(1, var(--glow-level)))))
          drop-shadow(0 0 16px rgba(var(--ph-rgb), calc(0.45 * min(1, var(--glow-level)))));
}
body.theme-bdibranding #screen-splash::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(var(--ph), var(--ph)) left 0 top 5% / 36px 4px no-repeat,
    linear-gradient(var(--ph), var(--ph)) left 0 top 9% / 20px 4px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right 0 bottom calc(var(--bdi-horizon) - 24px) / 36px 4px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right 0 bottom calc(var(--bdi-horizon) + 22px) / 36px 4px no-repeat;
  filter: drop-shadow(0 0 5px rgba(var(--ph-rgb), calc(0.8 * min(1, var(--glow-level)))));
}
body.theme-bdibranding #screen-splash .cc-bracket { color: var(--bdi-line); }
/* the splash mark is an <img> of the cream PNG, which cannot take the tint: its own pixels are moved out
   of the box (object-position) and the symbol is painted through a mask in --ph instead, like the veil */
body.theme-bdibranding .sp-logo {
  order: -2; filter: none; animation: none; width: min(18vw, 150px);
  object-position: -99999px 0; background-color: var(--ph);
  -webkit-mask: url(../assets/brand/bdibranding-symbol-offwhite.svg) center / contain no-repeat;
          mask: url(../assets/brand/bdibranding-symbol-offwhite.svg) center / contain no-repeat;
}
body.theme-bdibranding .sp-center { gap: 14px; }
body.theme-bdibranding .sp-name { color: var(--ph); font-size: 40px; font-weight: 620; letter-spacing: 0.02em; }
body.theme-bdibranding .sp-tag { order: -1; color: var(--bdi-muted); font-size: 12px; font-weight: 650; letter-spacing: 0.11em; }
body.theme-bdibranding .sp-press {
  margin-top: 5vh; animation: none;
  color: var(--ink); background: var(--ph); border: 1px solid var(--ph);
  font-size: 14px; font-weight: 720; letter-spacing: 0.01em; padding: 12px 20px;
}
body.theme-bdibranding .sp-press:hover { background: var(--ph-bright); border-color: var(--ph-bright); }
body.theme-bdibranding .sp-stamp { color: var(--bdi-muted); font-size: 10.5px; letter-spacing: 0.11em; }
body.theme-bdibranding .sp-rec { animation: none; }

/* ---- 8 · LIGHT-LINE FRAMES (Tron: Legacy direction) — the five game-screen panels -------------
   Three layers, every one painted with THEME VARIABLES so the frame follows the CUSTOM PHOSPHOR tint
   (--ph), BRIGHTNESS (--panel) and the two glow dials:
     the panel     a chamfered fill — one 135deg gradient that is transparent for its first and last
                   --bdi-cut, which cuts the top-left and bottom-right corners
     ::before      the LINE: var(--ph) through a line mask (core line + accent ticks)
     ::after       the GLOW: var(--ph) through a glow mask (haze + bloom, authored at the 150% ceiling),
                   opacity = LIGHT-LINES / 1.5
   Two sizes of mask, same design:
     FULL     assets/theme/bdi-frame-{line,glow}.svg     14px chamfer, 44 slice  COMMS · crew · station
     COMPACT  assets/theme/bdi-frame-{line,glow}-sm.svg   8px chamfer, 30 slice  top bar · dock bar
   (the bars are 64/44px tall: a 44 slice would scale down out of register with the panel edge.)
   The masks are 9-slice mask-box-images on pseudo-elements that extend 12px past the panel, so the glow
   spills outside without clip-path (which would clip it away). They rasterize once — no per-repaint
   filter — and layout does not move. The glow is deliberate, so these rules out-rank section 2's
   blanket strip where they need to: among !important declarations the higher specificity wins. */
body.theme-bdibranding { --glow-level: 1; --text-glow-level: 1; }   /* applySettings() writes them inline off-default */
body.theme-bdibranding :is(#chat-panel, #left, #stage-wrap, #topbar, #bottombar) {
  --bdi-cut: 9.9px;                /* 14px chamfer legs, measured along the 135deg gradient (14 / sqrt 2) */
  --bdi-fill: var(--panel);
  border: 1px solid transparent;
  border-radius: 0 !important;
  isolation: isolate;              /* a stacking context, so the z-index -1 frame layers stay IN the panel */
  background: linear-gradient(135deg, transparent var(--bdi-cut), var(--bdi-fill) var(--bdi-cut),
                                      var(--bdi-fill) calc(100% - var(--bdi-cut)), transparent calc(100% - var(--bdi-cut)));
  /* size the gradient to the BORDER box: at the default padding-box origin it tiles into the 1px border
     strip, and the repeat puts a 1px sliver of fill inside the bottom-right cut */
  background-origin: border-box;
}
body.theme-bdibranding :is(#topbar, #bottombar) { --bdi-cut: 5.66px; }   /* 8px legs — the compact frame */
/* That isolation makes #bottombar a stacking context at the screen's base level, so its dock menus (z-index 60,
   but only INSIDE the bar) drew under the windows layer (#terms, z-index 50): a CREW/WORK/BUILD/SYSTEM menu opened
   over an open window appeared behind it. While a dock menu is open the bar is lifted over the windows layer (and
   stays under the nav coach at 70); at rest it keeps its old place, so windows still float over the bar. The other
   isolated panels need no lift: their pop-ups (COMMS' agent menu and model list) open inside their own panel. */
body.theme-bdibranding #bottombar:has(.bb-group.open) { z-index: 60; }
body.theme-bdibranding #stage-wrap { --bdi-fill: var(--bg); }             /* the feed's own dark behind the canvas */
/* these three clip their content (overflow: hidden), which would also clip the glow at the panel edge.
   overflow: clip + overflow-clip-margin keeps the content clip but lets painting reach the 12px glow
   margin (+1px border, measured from the padding box). A clip box is not a scroll container, so the
   automatic minimum size would come back — the explicit zeros keep the grid tracks exactly as they
   were. Nothing scrolls these three (they hold their own inner scrollers). */
body.theme-bdibranding :is(#left, #stage-wrap, #topbar) {
  overflow: clip; overflow-clip-margin: 13px; min-width: 0; min-height: 0;
}
/* the station canvas fills the view edge to edge — cut its corners too, or it paints over the chamfer
   (and over the frame line, which sits beneath content). 13px = the 14px legs less the 1px border. */
body.theme-bdibranding #stage-wrap > #stage {
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
}
/* both layers sit at z-index -1 inside the panel's stacking context: above its fill, below all of its
   content. inset -13px = the 1px border + the 12px glow margin, so the masks register with the border
   box. Both pseudo-elements were already spoken for — style.css's curved-glass ::before and
   panelchrome.css's 9px corner-bracket ::after (they fought the chamfers) — so every property those
   set is reset here. */
body.theme-bdibranding :is(#chat-panel, #left, #stage-wrap, #topbar, #bottombar)::before,
body.theme-bdibranding :is(#chat-panel, #left, #stage-wrap, #topbar, #bottombar)::after {
  content: ''; display: block; position: absolute; inset: -13px; z-index: -1; pointer-events: none;
  border: 0; border-radius: 0 !important; background: var(--ph); mix-blend-mode: normal;
  transform: none; animation: none;
}
body.theme-bdibranding :is(#chat-panel, #left, #stage-wrap)::before {
  opacity: 1;
  -webkit-mask-box-image: url(../assets/theme/bdi-frame-line.svg) 44 / 44px stretch;
          mask-border: url(../assets/theme/bdi-frame-line.svg) 44 / 44px stretch;
}
body.theme-bdibranding :is(#chat-panel, #left, #stage-wrap)::after {
  opacity: clamp(0, calc(var(--glow-level) / 1.5), 1);
  -webkit-mask-box-image: url(../assets/theme/bdi-frame-glow.svg) 44 / 44px stretch;
          mask-border: url(../assets/theme/bdi-frame-glow.svg) 44 / 44px stretch;
}
body.theme-bdibranding :is(#topbar, #bottombar)::before {
  opacity: 1;
  -webkit-mask-box-image: url(../assets/theme/bdi-frame-line-sm.svg) 30 / 30px stretch;
          mask-border: url(../assets/theme/bdi-frame-line-sm.svg) 30 / 30px stretch;
}
body.theme-bdibranding :is(#topbar, #bottombar)::after {
  opacity: clamp(0, calc(var(--glow-level) / 1.5), 1);
  -webkit-mask-box-image: url(../assets/theme/bdi-frame-glow-sm.svg) 30 / 30px stretch;
          mask-border: url(../assets/theme/bdi-frame-glow-sm.svg) 30 / 30px stretch;
}
/* the panel headers: the label takes a pale version of the tint and glows with GLOW (light around
   text); the rail under it is a line, so it follows LIGHT-LINES */
body.theme-bdibranding :is(#chat-panel, #left) h3 {
  color: color-mix(in srgb, var(--ph) 55%, #ffffff);
  border-bottom-color: rgba(var(--ph-rgb), 0.38);
  text-shadow: 0 0 4px rgba(var(--ph-rgb), calc(0.85 * var(--text-glow-level))),
               0 0 14px rgba(var(--ph-rgb), calc(0.35 * var(--text-glow-level))) !important;
  box-shadow: 0 8px 14px -12px rgba(var(--ph-rgb), calc(0.7 * var(--glow-level))) !important;
}
/* the composer sits 9px above the COMMS bottom-right chamfer — cut its own corner to match */
body.theme-bdibranding #chat-panel #chat-inputrow {
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%);
}
/* ...except while the MODEL DOCK is open. The dock pops UP out of this row, and a clip-path clips every
   descendant, so the chamfer swallowed the whole model picker (2026-09-26: "the models are not showing").
   The corner cut returns the moment the dock closes. */
body.theme-bdibranding #chat-panel #chat-inputrow:has(#model-dock:not([hidden])) {
  clip-path: none;
}

/* ---- 9 · LIGHT-LINE FRAMES on WINDOWS and DOCK MENUS ------------------------------------------------
   WINDOWS (#terms .term) take the panel frame exactly: the FULL masks, the chamfered fill, the same
   glow dials. They are fixed-position with their own z-index, so each is already a stacking context.
   #terms raises the specificity over the glass layer's compound .term selectors. */
body.theme-bdibranding #terms .term {
  --bdi-cut: 9.9px;
  border: 1px solid transparent;
  border-radius: 0 !important;
  background: linear-gradient(135deg, transparent var(--bdi-cut), var(--panel) var(--bdi-cut),
                                      var(--panel) calc(100% - var(--bdi-cut)), transparent calc(100% - var(--bdi-cut)));
  background-origin: border-box;
  /* the window clips its content (overflow: hidden) — keep the clip, let the glow margin paint */
  overflow: clip; overflow-clip-margin: 13px;
  /* the glass blur is a RECTANGLE: it would show as blurred squares in the cut corners, and the fill is
     near-opaque anyway, so on the flat theme it goes */
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
/* ::before was style.css's recessed curved-glass overlay (offset below the header) — fully reset */
body.theme-bdibranding #terms .term::before,
body.theme-bdibranding #terms .term::after {
  content: ''; display: block; position: absolute; inset: -13px; z-index: -1; pointer-events: none;
  border: 0; border-radius: 0 !important; background: var(--ph); mix-blend-mode: normal;
  transform: none; animation: none;
}
body.theme-bdibranding #terms .term::before {
  opacity: 1;
  -webkit-mask-box-image: url(../assets/theme/bdi-frame-line.svg) 44 / 44px stretch;
          mask-border: url(../assets/theme/bdi-frame-line.svg) 44 / 44px stretch;
}
body.theme-bdibranding #terms .term::after {
  opacity: clamp(0, calc(var(--glow-level) / 1.5), 1);
  -webkit-mask-box-image: url(../assets/theme/bdi-frame-glow.svg) 44 / 44px stretch;
          mask-border: url(../assets/theme/bdi-frame-glow.svg) 44 / 44px stretch;
}
/* the window chrome layer: four corner brackets (they sit inside the chamfers and fight the frame's own
   ticks) and a grade band hardcoded in warm amber, rgba(255, 205, 130) — a CRT leftover the audit's
   colour pass missed at its 5% alpha. The frame carries the corners now. */
body.theme-bdibranding #terms .term .term-chrome { display: none; }
/* A window takes focus when it opens, and section 2's focus fallback would draw a square outline round
   the whole chamfered frame. A window is a container, not a control: the focused one glows HOTTER
   instead (its glow layer runs at the dial's full strength rather than two thirds), which is also how
   a light-line HUD would mark it. Controls inside keep their outlines. */
body.theme-bdibranding #terms .term:focus-visible,
body.theme-bdibranding :is(#chat-panel, #left, #stage-wrap, #topbar, #bottombar):focus-visible { outline: none; }
body.theme-bdibranding #terms .term:focus-within::after { opacity: clamp(0, var(--glow-level), 1); }
/* windows float OVER the station: with the glass blur gone, the fill's 3% translucency lets the feed and
   its buttons ghost through. Where relative colour syntax exists the window fill is the same colour at
   full opacity (it still follows BRIGHTNESS, which rewrites --panel). The explicit `/ 1` matters: an
   omitted alpha in relative colour syntax inherits the ORIGIN's alpha, i.e. --panel's own 0.97. */
@supports (color: rgb(from red r g b)) {
  body.theme-bdibranding #terms .term {
    background: linear-gradient(135deg, transparent var(--bdi-cut), rgb(from var(--panel) r g b / 1) var(--bdi-cut),
                                        rgb(from var(--panel) r g b / 1) calc(100% - var(--bdi-cut)), transparent calc(100% - var(--bdi-cut)));
    background-origin: border-box;
  }
}
/* the agent dossier's portrait scan-sweep is on-theme for a light-line HUD, but hardcoded warm amber —
   it follows the tint instead */
body.theme-bdibranding .ag-psweep { background: linear-gradient(180deg, transparent, rgba(var(--ph-rgb), 0.16), transparent); }
/* the header: title glows with GLOW, the rail under it is a line (LIGHT-LINES) */
body.theme-bdibranding #terms .term .term-head {
  border-bottom-color: rgba(var(--ph-rgb), 0.38);
  box-shadow: 0 8px 14px -12px rgba(var(--ph-rgb), calc(0.7 * var(--glow-level))) !important;
}
body.theme-bdibranding #terms .term .term-title {
  color: color-mix(in srgb, var(--ph) 55%, #ffffff);
  text-shadow: 0 0 4px rgba(var(--ph-rgb), calc(0.85 * var(--text-glow-level))),
               0 0 14px rgba(var(--ph-rgb), calc(0.35 * var(--text-glow-level))) !important;
}
/* the footer strip runs flush along the bottom edge — cut its corner to the chamfer (14px less the border) */
body.theme-bdibranding #terms .term .term-foot {
  border-top-color: rgba(var(--ph-rgb), 0.24);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%);
}

/* DOCK MENUS (.bb-menu) SCROLL (overflow: auto), which rules out the pseudo-element frame: an absolute
   layer 13px past the box would add scrollable overflow and ride along with the content. So a menu's
   frame is BACKGROUND — gradients attached to the box (they never scroll), painted in var(--ph):
     one 135deg gradient   both diagonal cut-lines + the chamfered fill (10px legs: 7.07px along it)
     four 1px strips       the straight edges, each stopping at its chamfer
     four short 2px bars   the accent ticks past each cut
   and its glow is a drop-shadow FILTER, which paints outside the scroll clip. Menus are small and
   short-lived, so the filter's repaint cost is nothing like it would be on a panel.
   The selector matches glass-demo.css's own (#screen-game #bottombar .bb-menu) so it wins on source
   order — and it also out-ranks section 5's 4px corner, which rides an :is() list carrying ids. */
body.theme-bdibranding #screen-game #bottombar .bb-menu {
  --bdi-menu-fill: var(--panel);
  border-color: transparent;
  border-radius: 0 !important;
  background:
    linear-gradient(var(--ph), var(--ph)) left 12px top 0 / 10px 2px no-repeat,
    linear-gradient(var(--ph), var(--ph)) left 0 top 12px / 2px 10px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right 12px bottom 0 / 10px 2px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right 0 bottom 12px / 2px 10px no-repeat,
    linear-gradient(var(--ph), var(--ph)) right top / calc(100% - 10px) 1px no-repeat,
    linear-gradient(var(--ph), var(--ph)) left bottom / 1px calc(100% - 10px) no-repeat,
    linear-gradient(var(--ph), var(--ph)) right top / 1px calc(100% - 10px) no-repeat,
    linear-gradient(var(--ph), var(--ph)) left bottom / calc(100% - 10px) 1px no-repeat,
    linear-gradient(135deg, transparent 6.2px, var(--ph) 6.2px, var(--ph) 7.07px, var(--bdi-menu-fill) 7.07px,
                            var(--bdi-menu-fill) calc(100% - 7.07px), var(--ph) calc(100% - 7.07px),
                            var(--ph) calc(100% - 6.2px), transparent calc(100% - 6.2px)) no-repeat;
  background-origin: border-box;
  filter: drop-shadow(0 0 calc(6px * var(--glow-level)) rgba(var(--ph-rgb), calc(0.4 * min(1, var(--glow-level)))));
}
/* like windows, a menu floats over the station — full opacity where relative colour syntax exists */
@supports (color: rgb(from red r g b)) {
  body.theme-bdibranding #screen-game #bottombar .bb-menu { --bdi-menu-fill: rgb(from var(--panel) r g b / 1); }
}

/* ---- 10 · LIGHT-LINE FRAMES on the SMALL FLOATING SURFACES --------------------------------------
   Toasts, the dock tooltip and the first-run coach bubble: the dock menu's recipe (box-attached
   background gradients + a drop-shadow glow — these clip or animate, and they are small and
   short-lived) at an 8px chamfer (5.66px along the 135deg gradient). The edge colour is a variable,
   --bdi-edge, so a TOAST draws its frame in its own severity colour (--sev: the green for success,
   the Legacy orange for warnings, red for failures) while the rest draw in the tinted --ph. */
/* the variable DEFAULTS ride a :where() (no specificity of its own), so the toast's --sev override below
   wins — the frame rule's :is() list carries an id and would otherwise out-rank it */
body.theme-bdibranding :where(.toast, .hint-bubble, .station-tip, #nav-coach) { --bdi-edge: var(--ph); --bdi-fill: var(--panel2); }
body.theme-bdibranding :is(.toast, .hint-bubble, .station-tip, #nav-coach) {
  border-color: transparent;
  border-radius: 0 !important;
  background:
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) left 10px top 0 / 8px 2px no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) left 0 top 10px / 2px 8px no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) right 10px bottom 0 / 8px 2px no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) right 0 bottom 10px / 2px 8px no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) right top / calc(100% - 8px) 1px no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) left bottom / 1px calc(100% - 8px) no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) right top / 1px calc(100% - 8px) no-repeat,
    linear-gradient(var(--bdi-edge), var(--bdi-edge)) left bottom / calc(100% - 8px) 1px no-repeat,
    linear-gradient(135deg, transparent 4.8px, var(--bdi-edge) 4.8px, var(--bdi-edge) 5.66px, var(--bdi-fill) 5.66px,
                            var(--bdi-fill) calc(100% - 5.66px), var(--bdi-edge) calc(100% - 5.66px),
                            var(--bdi-edge) calc(100% - 4.8px), transparent calc(100% - 4.8px)) no-repeat;
  background-origin: border-box;
  filter: drop-shadow(0 0 calc(5px * var(--glow-level)) color-mix(in srgb, var(--bdi-edge) calc(40% * min(1, var(--glow-level))), transparent));
}
body.theme-bdibranding .toast { --bdi-edge: var(--sev); }
/* the toast's severity lamp runs its full left edge — cut its top-left to the chamfer; the dwell bar
   runs the bottom edge — it stops short of the bottom-right cut. The inner corner brackets (::after) fight the frame. */
body.theme-bdibranding .toast .toast-lamp { clip-path: polygon(7px 0, 100% 0, 100% 100%, 0 100%, 0 7px); }
body.theme-bdibranding .toast .toast-dwell { right: 8px; }
body.theme-bdibranding .toast::after { display: none; }

/* ---- 11 · MOTION — the light-lines energize and derezz --------------------------------------------
   Every effect animates the FRAME LAYERS (::before line, ::after glow) and the CONTENT, never the
   element itself: glass-demo.js owns the window element's motion (seat() writes animation:none inline
   and moveSheet() plays a 220ms slide), so animating anything else runs alongside it without a fight,
   and the exits finish inside that 220ms before closeTerm() removes the window.
   The whole section sits inside prefers-reduced-motion: no-preference — reduced motion simply gets
   none of it (the frames are complete and static without it). */
@media (prefers-reduced-motion: no-preference) {
  /* ENERGIZE — the line traces in from the top-left cut (across, then down), the glow flares and
     settles to the dial, the content comes up just behind the light */
  @keyframes bdi-trace-in {
    0%   { clip-path: inset(0 100% 100% 0); }
    45%  { clip-path: inset(0 0 100% 0); }
    100% { clip-path: inset(0 0 0 0); }
  }
  @keyframes bdi-glow-flare {
    0%   { opacity: 0; }
    55%  { opacity: 1; }
  }
  @keyframes bdi-content-in {
    from { opacity: 0; }
  }
  /* entering the station (or switching to this theme) lights the five panels in sequence */
  body.theme-bdibranding #screen-game.active :is(#topbar, #left, #stage-wrap, #chat-panel, #bottombar)::before {
    animation: bdi-trace-in 520ms cubic-bezier(.3, .7, .2, 1) backwards;
  }
  body.theme-bdibranding #screen-game.active :is(#topbar, #left, #stage-wrap, #chat-panel, #bottombar)::after {
    animation: bdi-glow-flare 700ms ease-out backwards;
  }
  body.theme-bdibranding #screen-game.active #topbar::before,
  body.theme-bdibranding #screen-game.active #topbar::after                     { animation-delay: 0ms; }
  body.theme-bdibranding #screen-game.active #left::before,
  body.theme-bdibranding #screen-game.active #left::after                       { animation-delay: 90ms; }
  body.theme-bdibranding #screen-game.active #stage-wrap::before,
  body.theme-bdibranding #screen-game.active #stage-wrap::after                 { animation-delay: 180ms; }
  body.theme-bdibranding #screen-game.active #chat-panel::before,
  body.theme-bdibranding #screen-game.active #chat-panel::after                 { animation-delay: 270ms; }
  body.theme-bdibranding #screen-game.active #bottombar::before,
  body.theme-bdibranding #screen-game.active #bottombar::after                  { animation-delay: 360ms; }

  /* a window energizing on open (and on restore from the strip — display comes back, so it replays).
     The body keeps its element across re-renders (it is refilled, not replaced), so this plays once
     per open, never on a live repaint; re-renders keep their own .swap-in crossfade. */
  body.theme-bdibranding #terms .term:not(.term-closing)::before { animation: bdi-trace-in 300ms cubic-bezier(.3, .7, .2, 1) backwards; }
  body.theme-bdibranding #terms .term:not(.term-closing)::after  { animation: bdi-glow-flare 420ms ease-out backwards; }
  body.theme-bdibranding #terms .term:not(.term-closing) > :is(.term-head, .term-body, .term-foot) {
    animation: bdi-content-in 180ms ease-out 110ms backwards;
  }

  /* DEREZZ — a closing window's light flares, then collapses to its horizontal centre line; the content
     breaks sideways in hard digital steps and drops out. 200ms, inside moveSheet's 220ms exit. */
  @keyframes bdi-derezz-line {
    0%   { clip-path: inset(0); opacity: 1; }
    35%  { clip-path: inset(0); opacity: 1; }
    100% { clip-path: inset(50% 0 50% 0); opacity: 0; }
  }
  @keyframes bdi-derezz-glow {
    0%   { opacity: 1; }
    100% { opacity: 0; }
  }
  @keyframes bdi-derezz-content {
    0%   { opacity: 1; transform: none; }
    30%  { opacity: 1; transform: translateX(-4px) skewX(-6deg); }
    60%  { opacity: .55; transform: translateX(5px) scaleY(.94); }
    100% { opacity: 0; transform: translateX(-8px) scaleY(.2); }
  }
  body.theme-bdibranding #terms .term.term-closing::before { animation: bdi-derezz-line 200ms ease-in forwards; }
  body.theme-bdibranding #terms .term.term-closing::after  { animation: bdi-derezz-glow 200ms ease-in forwards; }
  body.theme-bdibranding #terms .term.term-closing > :is(.term-head, .term-body, .term-foot) {
    animation: bdi-derezz-content 200ms steps(5, end) forwards;
  }

  /* a dock menu unfolds UP from its dock, wiping along the light-line; the inset ends 24px OUTSIDE the
     box so the last frame never clips the drop-shadow glow, and it does not fill — once it ends there
     is no clip-path at all */
  @keyframes bdi-menu-in {
    from { clip-path: inset(100% -24px -24px -24px); }
    to   { clip-path: inset(-24px); }
  }
  body.theme-bdibranding #screen-game #bottombar .bb-group.open .bb-menu { animation: bdi-menu-in 190ms cubic-bezier(.3, .7, .2, 1); }

  /* a toast arrives on a LIGHT-TRAIL: a bright streak in its severity colour runs its top edge once.
     ::after was the toast's inner corner brackets (hidden in section 10) — reused as the streak. */
  @keyframes bdi-toast-trail {
    0%   { transform: translateX(-110%); opacity: 1; }
    80%  { opacity: 1; }
    100% { transform: translateX(260%); opacity: 0; }
  }
  body.theme-bdibranding .toast::after {
    content: ''; display: block; position: absolute; top: 0; left: 0; right: auto; bottom: auto;
    width: 45%; height: 2px; opacity: 0; pointer-events: none;
    background: linear-gradient(90deg, transparent, var(--bdi-edge), transparent);
    animation: bdi-toast-trail 460ms ease-out 60ms forwards;
  }

  /* BOOT VEIL: the ring powers on, the line draws outward from it both ways, the symbol traces itself
     round the ring, the edge dashes flick on; then light pulses run outward along the line until the
     boot router swaps the screen */
  @keyframes bdi-boot-ring {
    0%   { transform: scale(0.4); opacity: 0; }
    60%  { transform: scale(1.06); opacity: 1; }
    100% { transform: scale(1); }
  }
  @keyframes bdi-boot-line { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  @keyframes bdi-boot-sweep { from { --bdi-sweep: 0deg; } to { --bdi-sweep: 360deg; } }
  @keyframes bdi-boot-dash-in { from { opacity: 0; transform: translateX(-6px); } }
  @keyframes bdi-boot-dash-idle { from { opacity: 1; } to { opacity: 0.45; } }
  @keyframes bdi-boot-pulse-r { 0% { transform: translateX(0); opacity: 0; } 12% { opacity: 1; } 100% { transform: translateX(52vw); opacity: 0; } }
  @keyframes bdi-boot-pulse-l { 0% { transform: translateX(0); opacity: 0; } 12% { opacity: 1; } 100% { transform: translateX(-52vw); opacity: 0; } }
  body.theme-bdibranding #screen-boot.active .boot-veil::before { animation: bdi-boot-ring 420ms cubic-bezier(.3, .7, .2, 1) backwards; }
  body.theme-bdibranding #screen-boot.active::before { animation: bdi-boot-line 700ms cubic-bezier(.3, .7, .2, 1) 160ms backwards; }
  body.theme-bdibranding #screen-boot.active .boot-veil::after { animation: bdi-boot-sweep 720ms ease-out 320ms backwards; }
  body.theme-bdibranding #screen-boot.active::after {
    animation: bdi-boot-dash-in 360ms ease-out 520ms backwards, bdi-boot-dash-idle 1.6s ease-in-out 900ms infinite alternate;
  }
  body.theme-bdibranding #screen-boot.active .boot-line::after  { animation: bdi-boot-pulse-r 2.2s cubic-bezier(.5, 0, .8, .4) 900ms infinite; }
  body.theme-bdibranding #screen-boot.active .boot-line::before { animation: bdi-boot-pulse-l 2.2s cubic-bezier(.5, 0, .8, .4) 900ms infinite; }
  body.theme-bdibranding #screen-boot.active .boot-mark,
  body.theme-bdibranding #screen-boot.active .boot-line { animation: bdi-content-in 400ms ease-out 700ms backwards; }

  /* FIRST-RUN SPLASH: the horizon draws outward, the dashes flick on (the grid floor already scrolls) */
  body.theme-bdibranding #screen-splash.active::before { animation: bdi-boot-line 900ms cubic-bezier(.3, .7, .2, 1) backwards; }
  body.theme-bdibranding #screen-splash.active::after {
    animation: bdi-boot-dash-in 360ms ease-out 600ms backwards, bdi-boot-dash-idle 1.6s ease-in-out 1s infinite alternate;
  }
}
