/* ==========================================================================
   BLOCKHAVEN -- site chrome.
   Deliberately period-correct: fixed width column, Verdana, beveled buttons,
   gradient panel headers, 1px borders everywhere.

   Every colour in the file comes from a token on :root so the dark theme is a
   second, hand-built palette rather than an inverted copy of the light one --
   the chrome keeps its bevels and gradients, it just lights them from a night
   sky instead of a white one.  Themes are selected by data-theme on <html>;
   "auto" follows the operating system.
   ========================================================================== */

:root {
  /* page */
  --bg: #dfe7ee;
  --bg-weave-a: #dbe4ec;
  --bg-weave-b: #e2eaf1;
  --bg-veil: rgba(255, 255, 255, .55);

  /* ink */
  --ink: #22303c;
  --ink-strong: #1b3d5f;
  --ink-soft: #6f8095;
  --ink-label: #35506b;
  --link: #0b52a1;
  --link-hover: #c4281c;
  --link-visited: #4a4fa8;

  /* surfaces */
  --panel: #ffffff;
  --panel-alt: #f4f8fb;
  --panel-foot: #f1f5f9;
  --sunken: #eef3f8;
  --line: #9fb6c9;
  --line-soft: #cfdbe5;
  --line-dot: #cfdbe5;
  --shadow: rgba(20, 60, 100, .12);
  --shadow-lift: rgba(20, 60, 100, .2);

  /* header chrome */
  --topbar: linear-gradient(#2d7dc4, #14548e 48%, #0d3f6f);
  --topbar-edge: #062a4d;
  --topbar-ink: #eaf4ff;
  --topbar-tag: #bfe0ff;
  --tabbar: linear-gradient(#8c1c15, #6e120c);
  --tabbar-edge: #3c0705;
  --tabbar-ink: #ffdede;
  --tabbar-hover: #a3251c;
  --tab-on-bg: #e9eef3;
  --brand-red: #c4281c;

  /* panel heads */
  --head-blue: linear-gradient(#6fa9d8, #3d7fb4 55%, #2f6f9f);
  --head-blue-edge: #2a5d86;
  --head-red: linear-gradient(#c9503f, #a3281c 55%, #8c1c15);
  --head-red-edge: #6e120c;
  --head-green: linear-gradient(#6bbd6b, #3f8f45 55%, #2f7a38);
  --head-green-edge: #276330;
  --head-gold: linear-gradient(#f0cf6a, #d9a824 55%, #b98d10);
  --head-gold-edge: #8f6c07;
  --head-purple: linear-gradient(#a86ede, #7a34c4 55%, #5d1f9c);
  --head-purple-edge: #451573;
  --head-ink: #ffffff;

  /* controls */
  --btn: linear-gradient(#ffffff, #dfe8f0 55%, #ccd9e5);
  --btn-hover: linear-gradient(#fff, #eaf2f8 55%, #d8e4ee);
  --btn-edge: #8ba5bb;
  --btn-ink: #1b3d5f;
  --btn-gloss: #ffffff;
  --field: #ffffff;
  --field-edge: #9fb6c9;
  --field-ink: #22303c;
  --focus: #ffd95e;

  /* feedback */
  --ok-bg: #eafbe7; --ok-edge: #8fbf8f; --ok-ink: #275e2b;
  --bad-bg: #fdecea; --bad-edge: #dd9999; --bad-ink: #8c1c15;
  --info-bg: #eaf3fb; --info-edge: #9fc0dd; --info-ink: #1b3d5f;
  --warn-bg: #fffbe6; --warn-edge: #d8c98a; --warn-ink: #6a5a1f;

  /* accents */
  --gold: #f5c518;
  --badge-bg: #f5c518; --badge-ink: #4a3800; --badge-edge: #b8900d;
  --alert-bg: #d93025; --alert-ink: #ffffff; --alert-edge: #8c1c15;
  --unusual: #7a34c4;
  --unusual-soft: #b98be0;
  --unusual-ink: #5d1f9c;
  --tile-normal: linear-gradient(160deg, #fdf3cf, #f6dd8e);
  --tile-unusual: linear-gradient(160deg, #b98be0, #6f2bb5);
  /* The rim around an ordinary item tile.  An Unusual announces itself with a
     purple edge and a glint, so a Normal needs an edge of its own or it reads
     as an unfinished tile floating on the panel -- most visible in the light
     theme, where the old hairline all but disappeared. */
  --tile-edge: #9aa7b4;
  /* Character previews keep their own sky in both themes.  The 3D scene
     inside them is lit for a dark background, and an avatar that changed
     colour every time somebody flipped the toggle read as a rendering fault
     rather than as a theme.  It is a lifted slate rather than near-black, so
     a dark-haired or dark-clothed character still has something to stand
     against.  These two are deliberately not restated in the dark palettes
     below. */
  --preview-bg: linear-gradient(#41556b, #2b3a4a);
  --preview-edge: #55708c;
  --hero: linear-gradient(#1c5a94, #0e3c68);
  --hero-edge: #0a3252;
  --ticker-bg: #fffbe6;
  --ticker-edge: #d8c98a;
  --ticker-ink: #6a5a1f;
  --ticker-tag: #8c1c15;
  --scrim: rgba(8, 16, 26, .72);
  --dot-on: #3fbf4a;
  --dot-off: #b9c3cc;

  --radius: 4px;
  color-scheme: light;
}

/* --------------------------------------------------------------- dark theme
   Not an inversion: the page becomes a deep slate-navy night, panels become
   raised steel plates lit from above, and the two signature bars keep their
   blue/red identity at lower luminance so the layout still reads at a glance.
   Accents (gold, Unusual purple) are pushed brighter to survive the dark
   ground, and every border gains a faint inner highlight so the 1px bevelled
   chrome does not dissolve. */
:root[data-theme="dark"] {
  --bg: #0d141c;
  --bg-weave-a: #101822;
  --bg-weave-b: #0d151e;
  --bg-veil: rgba(90, 150, 210, .07);

  --ink: #cfdceb;
  --ink-strong: #eaf3fc;
  --ink-soft: #8798ab;
  --ink-label: #9fb4c9;
  --link: #6fc1ff;
  --link-hover: #ff9b8c;
  --link-visited: #b0a4f2;

  --panel: #17212c;
  --panel-alt: #1c2733;
  --panel-foot: #141d27;
  --sunken: #101922;
  --line: #31435a;
  --line-soft: #273548;
  --line-dot: #2b3a4d;
  --shadow: rgba(0, 0, 0, .45);
  --shadow-lift: rgba(0, 0, 0, .6);

  --topbar: linear-gradient(#1f5f95, #103f68 48%, #0a2b48);
  --topbar-edge: #04121f;
  --topbar-ink: #dcecfb;
  --topbar-tag: #8fc3ef;
  --tabbar: linear-gradient(#7a1810, #4d0d07);
  --tabbar-edge: #250402;
  --tabbar-ink: #ffcfc8;
  --tabbar-hover: #99271d;
  --tab-on-bg: #17212c;
  --brand-red: #b8241a;

  --head-blue: linear-gradient(#33739f, #1f4f74 55%, #183f5e);
  --head-blue-edge: #12314a;
  --head-red: linear-gradient(#9c4437, #75231a 55%, #5d1811);
  --head-red-edge: #3f0d08;
  --head-green: linear-gradient(#3f8d55, #266739 55%, #1d532f);
  --head-green-edge: #143c21;
  --head-gold: linear-gradient(#b28f34, #8a6a18 55%, #6d520c);
  --head-gold-edge: #4e3a06;
  --head-purple: linear-gradient(#7c4fb0, #52288a 55%, #3e1d6b);
  --head-purple-edge: #2a1149;
  --head-ink: #f4f9ff;

  --btn: linear-gradient(#2c3c4e, #1f2b39 55%, #1a2532);
  --btn-hover: linear-gradient(#38495e, #273546 55%, #202d3c);
  --btn-edge: #3d5169;
  --btn-ink: #d3e3f4;
  --btn-gloss: rgba(255, 255, 255, .14);
  --field: #0f1822;
  --field-edge: #31455c;
  --field-ink: #dceaf7;
  --focus: #ffcf4d;

  --ok-bg: #12261a; --ok-edge: #2f6b42; --ok-ink: #9be0b2;
  --bad-bg: #2a1315; --bad-edge: #8c3830; --bad-ink: #ffb0a5;
  --info-bg: #10202e; --info-edge: #2f5f86; --info-ink: #a2d3f7;
  --warn-bg: #262012; --warn-edge: #6b5c20; --warn-ink: #ecd88f;

  --gold: #ffd247;
  --badge-bg: #d8a417; --badge-ink: #2a1f00; --badge-edge: #8f6c07;
  --alert-bg: #d0362b; --alert-ink: #fff3f1; --alert-edge: #7d1c14;
  --unusual: #b478f0;
  --unusual-soft: #8b57c9;
  --unusual-ink: #d9bcff;
  --tile-normal: linear-gradient(160deg, #38301a, #211c0e);
  --tile-unusual: linear-gradient(160deg, #4b2b7c, #26114a);
  --tile-edge: #46586a;
  --hero: linear-gradient(#123049, #071624);
  --hero-edge: #0a2437;
  --ticker-bg: #15202b;
  --ticker-edge: #2c3d51;
  --ticker-ink: #d2c08a;
  --ticker-tag: #ff9b8c;
  --scrim: rgba(2, 7, 13, .78);
  --dot-on: #4fd45c;
  --dot-off: #4a5a6a;

  color-scheme: dark;
}

/* "auto" (no explicit choice) follows the operating system */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d141c;
    --bg-weave-a: #101822;
    --bg-weave-b: #0d151e;
    --bg-veil: rgba(90, 150, 210, .07);
    --ink: #cfdceb;
    --ink-strong: #eaf3fc;
    --ink-soft: #8798ab;
    --ink-label: #9fb4c9;
    --link: #6fc1ff;
    --link-hover: #ff9b8c;
    --link-visited: #b0a4f2;
    --panel: #17212c;
    --panel-alt: #1c2733;
    --panel-foot: #141d27;
    --sunken: #101922;
    --line: #31435a;
    --line-soft: #273548;
    --line-dot: #2b3a4d;
    --shadow: rgba(0, 0, 0, .45);
    --shadow-lift: rgba(0, 0, 0, .6);
    --topbar: linear-gradient(#1f5f95, #103f68 48%, #0a2b48);
    --topbar-edge: #04121f;
    --topbar-ink: #dcecfb;
    --topbar-tag: #8fc3ef;
    --tabbar: linear-gradient(#7a1810, #4d0d07);
    --tabbar-edge: #250402;
    --tabbar-ink: #ffcfc8;
    --tabbar-hover: #99271d;
    --tab-on-bg: #17212c;
    --brand-red: #b8241a;
    --head-blue: linear-gradient(#33739f, #1f4f74 55%, #183f5e);
    --head-blue-edge: #12314a;
    --head-red: linear-gradient(#9c4437, #75231a 55%, #5d1811);
    --head-red-edge: #3f0d08;
    --head-green: linear-gradient(#3f8d55, #266739 55%, #1d532f);
    --head-green-edge: #143c21;
    --head-gold: linear-gradient(#b28f34, #8a6a18 55%, #6d520c);
    --head-gold-edge: #4e3a06;
    --head-purple: linear-gradient(#7c4fb0, #52288a 55%, #3e1d6b);
    --head-purple-edge: #2a1149;
    --head-ink: #f4f9ff;
    --btn: linear-gradient(#2c3c4e, #1f2b39 55%, #1a2532);
    --btn-hover: linear-gradient(#38495e, #273546 55%, #202d3c);
    --btn-edge: #3d5169;
    --btn-ink: #d3e3f4;
    --btn-gloss: rgba(255, 255, 255, .14);
    --field: #0f1822;
    --field-edge: #31455c;
    --field-ink: #dceaf7;
    --focus: #ffcf4d;
    --ok-bg: #12261a; --ok-edge: #2f6b42; --ok-ink: #9be0b2;
    --bad-bg: #2a1315; --bad-edge: #8c3830; --bad-ink: #ffb0a5;
    --info-bg: #10202e; --info-edge: #2f5f86; --info-ink: #a2d3f7;
    --warn-bg: #262012; --warn-edge: #6b5c20; --warn-ink: #ecd88f;
    --gold: #ffd247;
    --badge-bg: #d8a417; --badge-ink: #2a1f00; --badge-edge: #8f6c07;
    --alert-bg: #d0362b; --alert-ink: #fff3f1; --alert-edge: #7d1c14;
    --unusual: #b478f0;
    --unusual-soft: #8b57c9;
    --unusual-ink: #d9bcff;
    --tile-normal: linear-gradient(160deg, #38301a, #211c0e);
    --tile-unusual: linear-gradient(160deg, #4b2b7c, #26114a);
    --tile-edge: #46586a;
    --hero: linear-gradient(#123049, #071624);
    --hero-edge: #0a2437;
    --ticker-bg: #15202b;
    --ticker-edge: #2c3d51;
    --ticker-ink: #d2c08a;
    --ticker-tag: #ff9b8c;
    --scrim: rgba(2, 7, 13, .78);
    --dot-on: #4fd45c;
    --dot-off: #4a5a6a;
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  font-family: Verdana, Geneva, Tahoma, Arial, sans-serif;
  font-size: 11px;
  color: var(--ink);
  background: var(--bg);
  background-image:
    linear-gradient(var(--bg-veil), rgba(255,255,255,0) 220px),
    repeating-linear-gradient(45deg, var(--bg-weave-a) 0 8px, var(--bg-weave-b) 8px 16px);
}
body { overflow-x: hidden; }
html.theme-swap body, html.theme-swap body * {
  transition: background-color .25s ease, color .25s ease, border-color .25s ease;
}

a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; color: var(--link-hover); }
a:visited { color: var(--link-visited); }
img { border: 0; max-width: 100%; }
h1, h2, h3, h4 { margin: 0 0 6px 0; font-weight: bold; }
h1 { font-size: 20px; color: var(--ink-strong); }
h2 { font-size: 15px; color: var(--ink-strong); }
h3 { font-size: 12px; color: var(--ink-strong); }
p { margin: 0 0 8px 0; line-height: 1.55; }
hr { border: 0; border-top: 1px dotted var(--line); margin: 10px 0; }
small { font-size: 10px; }
canvas { max-width: 100%; }

/* ------------------------------------------------------------------ layout */
.wrap { width: 100%; max-width: 1024px; margin: 0 auto; padding: 0 12px; }
.row { display: flex; gap: 12px; align-items: flex-start; }
.row.tight { gap: 8px; }
.col { flex: 1 1 auto; min-width: 0; }
.col-side { width: 300px; flex: 0 0 300px; min-width: 0; }
.col-narrow { width: 220px; flex: 0 0 220px; min-width: 0; }
.spread { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.stack > * + * { margin-top: 10px; }
.center { text-align: center; }
.right { text-align: right; }
.muted { color: var(--ink-soft); }
.tiny { font-size: 10px; }
.nowrap { white-space: nowrap; }
.grow { flex: 1 1 auto; min-width: 0; }
.hidden { display: none !important; }
/* Doubled class so this beats the element's own display rule (.pill,
   .notice, .tabbar a) without reaching for !important, which the mobile
   overrides below would then have to fight. */
.only-mobile.only-mobile { display: none; }

/* ------------------------------------------------------------------ header */
.topbar {
  background: var(--topbar);
  border-bottom: 2px solid var(--topbar-edge);
  box-shadow: 0 2px 0 rgba(255,255,255,.22) inset;
}
/* The bar is sized by padding around its tallest child rather than by a fixed
   height, so the logo sets how tall it is and keeps its own air above and
   below at every width. */
.topbar .wrap {
  display: flex; align-items: center; gap: 12px;
  min-height: 52px; padding-top: 12px; padding-bottom: 12px;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; flex: 0 0 auto; }
.brand:hover { text-decoration: none; }
/* Height drives it and the width follows the artwork, so the lockup cannot be
   squashed by a narrow bar; the drop shadow is the one the logo already has,
   continued, so it sits on the blue rather than floating over it. */
.brand-logo {
  display: block; height: 44px; width: auto; flex: 0 0 auto;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .38));
  transition: transform .15s ease;
}
.brand:hover .brand-logo { transform: translateY(-1px) scale(1.015); }
.brand:active .brand-logo { transform: translateY(0) scale(.995); }
.brand-tag { color: var(--topbar-tag); font-size: 10px; font-style: italic; }

.topnav { display: flex; gap: 2px; }
.topnav.push { margin-left: auto; }
.topnav a {
  color: var(--topbar-ink); padding: 6px 10px; font-weight: bold;
  border-radius: 3px 3px 0 0; white-space: nowrap;
}
.topnav a:hover { background: rgba(255,255,255,.18); text-decoration: none; }
.topnav a.on { background: var(--tab-on-bg); color: var(--link); }

.searchbox { display: flex; min-width: 0; }
.searchbox input {
  width: 180px; min-width: 0; border: 1px solid var(--topbar-edge); padding: 4px 6px;
  font-size: 11px; font-family: inherit; border-radius: 3px 0 0 3px;
  background: var(--field); color: var(--field-ink);
}
.searchbox button {
  border: 1px solid var(--topbar-edge); border-left: 0; background: var(--btn);
  color: var(--btn-ink);
  padding: 4px 9px; cursor: pointer; border-radius: 0 3px 3px 0; font-size: 11px;
}
.wallet {
  display: flex; align-items: center; gap: 6px; color: #fff !important; font-weight: bold;
  background: rgba(0,0,0,.26); padding: 5px 9px; border-radius: 3px;
  border: 1px solid rgba(255,255,255,.25); white-space: nowrap;
}
.wallet:visited, .wallet:hover { color: #fff !important; }
.wallet #wallet-amount { color: #fff; }
.coin, .wallet .coin {
  width: 13px; height: 13px; border-radius: 50%; display: inline-block;
  background: radial-gradient(circle at 32% 30%, #ffe9a1, #e0a615 62%, #a97a06);
  border: 1px solid #7a5804; flex: 0 0 auto;
}

/* --------------------------------------------------- dark mode toggle */
.themetoggle {
  position: relative; width: 46px; height: 24px; flex: 0 0 auto; padding: 0;
  border-radius: 13px; cursor: pointer; overflow: hidden;
  border: 1px solid rgba(255,255,255,.4);
  background: linear-gradient(#7fc2f0, #3e8ec9);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.35);
  transition: background .35s ease, border-color .35s ease;
}
.themetoggle .knob {
  position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
  border-radius: 50%; overflow: hidden;
  background: radial-gradient(circle at 34% 30%, #fff6cf, #ffce3d 62%, #e5a411);
  box-shadow: 0 1px 3px rgba(0,0,0,.45), 0 0 8px rgba(255,214,90,.85);
  transition: transform .35s cubic-bezier(.5,-0.3,.4,1.4), background .35s ease,
              box-shadow .35s ease;
}
/* The moon is built the way the sky builds it: half the disc lit, half in
   shadow, and an ellipse across the middle whose width is how far round the
   terminator has swung.  Site.moonPhase() works out tonight's phase and sets
   the three custom properties, so the knob shows a crescent on a crescent
   night and a full disc on a full one instead of one fixed cartoon bite.
   Both layers only exist in dark mode -- in light mode the knob is the sun. */
.themetoggle .knob .limb,
.themetoggle .knob .term { display: none; }
.themetoggle[aria-pressed="true"] .knob {
  --moon-lit: #f2f6fd;
  --moon-dark: #16212e;
}
.themetoggle[aria-pressed="true"] .knob .limb,
.themetoggle[aria-pressed="true"] .knob .term {
  display: block; position: absolute; top: -1px; bottom: -1px;
}
.themetoggle[aria-pressed="true"] .knob .limb {
  width: 52%; left: var(--limb-side, 0%); background: var(--moon-dark);
}
.themetoggle[aria-pressed="true"] .knob .term {
  left: 50%; width: var(--term-w, 0%); transform: translateX(-50%);
  border-radius: 50%; background: var(--term-fill, var(--moon-dark));
  transition: width .4s ease, background .4s ease;
}
/* A hairline rim, so a new moon is still a disc you can see and press rather
   than a hole in the switch. */
.themetoggle[aria-pressed="true"] .knob::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid rgba(196,220,248,.45); pointer-events: none;
}
.themetoggle .sky { position: absolute; inset: 0; pointer-events: none; }
.themetoggle .sky i {
  position: absolute; width: 2px; height: 2px; border-radius: 50%;
  background: #fff; opacity: 0; transition: opacity .35s ease;
}
.themetoggle .sky i:nth-child(1) { left: 9px; top: 6px; }
.themetoggle .sky i:nth-child(2) { left: 15px; top: 14px; }
.themetoggle .sky i:nth-child(3) { left: 20px; top: 7px; width: 3px; height: 3px; }
.themetoggle .sky i:nth-child(4) { left: 27px; top: 16px; }
.themetoggle[aria-pressed="true"] {
  background: linear-gradient(#152a44, #060e18);
  border-color: rgba(140,190,240,.4);
}
/* A touch smaller than the sun: the moon is the smaller light. */
.themetoggle[aria-pressed="true"] .knob {
  transform: translateX(23px) scale(.82);
  background: radial-gradient(circle at 38% 34%, #f7faff, #dbe6f3 62%, #b6c6d8);
  box-shadow: 0 1px 3px rgba(0,0,0,.6), 0 0 9px rgba(190,215,245,.55);
}
.themetoggle[aria-pressed="true"] .sky i { opacity: .9; }
.themetoggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* mobile hamburger */
.navtoggle {
  display: none; width: 38px; height: 30px; border-radius: 4px; cursor: pointer;
  background: rgba(0,0,0,.24); border: 1px solid rgba(255,255,255,.3);
  padding: 6px 8px; flex: 0 0 auto;
}
.navtoggle i {
  display: block; height: 2px; background: #fff; border-radius: 2px;
  transition: transform .25s ease, opacity .2s ease;
}
.navtoggle i + i { margin-top: 4px; }
.navtoggle.on i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.navtoggle.on i:nth-child(2) { opacity: 0; }
.navtoggle.on i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* second nav strip */
.tabbar { background: var(--tabbar); border-bottom: 2px solid var(--tabbar-edge); }
.tabbar .wrap { display: flex; gap: 1px; }
.tabbar a {
  color: var(--tabbar-ink); padding: 6px 13px; font-weight: bold; font-size: 11px;
  border-right: 1px solid rgba(255,255,255,.12); white-space: nowrap;
}
.tabbar a:hover { background: var(--tabbar-hover); color: #fff; text-decoration: none; }
.tabbar a.on { background: var(--tab-on-bg); color: var(--ink-strong); }
.tabbar a.off {
  opacity: .48; cursor: not-allowed; color: var(--tabbar-ink);
  background: rgba(0,0,0,.18);
}
.tabbar a.off:hover { background: rgba(0,0,0,.18); color: var(--tabbar-ink); text-decoration: none; }
.tabbar .badge { margin-left: 5px; }
.tabbar .soon {
  font-size: 8px; text-transform: uppercase; letter-spacing: .5px;
  opacity: .8; margin-left: 4px; vertical-align: 1px;
}

.badge {
  display: inline-block; min-width: 15px; padding: 0 4px; border-radius: 8px;
  background: var(--badge-bg); color: var(--badge-ink); font-size: 10px;
  font-weight: bold; text-align: center; border: 1px solid var(--badge-edge);
  line-height: 14px;
}
.badge.alert { background: var(--alert-bg); color: var(--alert-ink); border-color: var(--alert-edge); }
.badge.pop { animation: badgepop .5s ease-out; }
@keyframes badgepop {
  0% { transform: scale(.4); } 60% { transform: scale(1.35); } 100% { transform: scale(1); }
}

/* ticker */
.ticker {
  background: var(--ticker-bg); border-bottom: 1px solid var(--ticker-edge);
  overflow: hidden; font-size: 10px; color: var(--ticker-ink); height: 20px;
  line-height: 20px;
}
.ticker .wrap { display: flex; align-items: center; gap: 8px; }
.ticker b { color: var(--ticker-tag); flex: 0 0 auto; }
.ticker-window { position: relative; overflow: hidden; height: 20px; flex: 1 1 auto; }
/* Slow enough to actually read a headline on the way past.  The strip is one
   long line, so the duration is the whole lap: halving the speed is doubling
   this number, and hovering parks it. */
.ticker-track {
  display: inline-flex; white-space: nowrap; will-change: transform;
  animation: tick 135s linear infinite;
}
.ticker-track span { padding-right: 2.4em; }
.ticker-window:hover .ticker-track { animation-play-state: paused; }
/* the strip is rendered twice end to end, so -50% lands exactly on the seam
   and the loop never shows a gap */
@keyframes tick { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ------------------------------------------------------------------ panels */
.panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  margin-bottom: 12px; box-shadow: 0 1px 2px var(--shadow);
}
/* The home inbox button stands in the sidebar stack alongside the panels
   rather than inside one, so it carries the same 12px beneath it; without
   this it butts straight up against the friends grid below it. */
.h-messages { margin-bottom: 12px; }
.panel-head {
  background: var(--head-blue);
  color: var(--head-ink); font-weight: bold; font-size: 12px; padding: 5px 10px;
  border-bottom: 1px solid var(--head-blue-edge); border-radius: 3px 3px 0 0;
  text-shadow: 0 1px 0 rgba(0,0,0,.3);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  flex-wrap: wrap;
}
.panel-head .head-links { font-size: 10px; font-weight: normal; }
.panel-head .head-links a { color: #e6f2ff; }
.panel-head.red { background: var(--head-red); border-bottom-color: var(--head-red-edge); }
.panel-head.green { background: var(--head-green); border-bottom-color: var(--head-green-edge); }
.panel-head.gold { background: var(--head-gold); border-bottom-color: var(--head-gold-edge); }
.panel-head.purple { background: var(--head-purple); border-bottom-color: var(--head-purple-edge); }
.panel-body { padding: 10px; }
.panel-body.flush { padding: 0; }
.panel-foot {
  padding: 6px 10px; background: var(--panel-foot); border-top: 1px solid var(--line-soft);
  font-size: 10px; border-radius: 0 0 3px 3px;
}

/* ------------------------------------------------------------------ forms */
input[type=text], input[type=password], input[type=number], input[type=search],
input[type=email], textarea, select {
  font-family: inherit; font-size: 11px; padding: 5px 6px;
  border: 1px solid var(--field-edge); border-radius: 3px;
  background: var(--field); color: var(--field-ink);
  box-shadow: 0 1px 1px rgba(0,0,0,.06) inset;
  max-width: 100%;
}
input:focus, textarea:focus, select:focus { outline: 2px solid var(--focus); outline-offset: -1px; }
textarea { width: 100%; resize: vertical; min-height: 60px; line-height: 1.5; }
label { display: block; font-weight: bold; margin: 8px 0 3px; color: var(--ink-label); }
.field { margin-bottom: 8px; }
.field input, .field select { width: 100%; }
.inline-form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

.btn {
  display: inline-block; font-family: inherit; font-size: 11px; font-weight: bold;
  padding: 5px 12px; cursor: pointer; color: var(--btn-ink); text-decoration: none;
  background: var(--btn);
  border: 1px solid var(--btn-edge); border-radius: 3px;
  box-shadow: 0 1px 0 var(--btn-gloss) inset, 0 1px 1px rgba(0,0,0,.1);
}
.btn:hover { background: var(--btn-hover); text-decoration: none; color: var(--link); }
.btn:active { box-shadow: 0 1px 3px rgba(0,0,0,.25) inset; transform: translateY(1px); }
.btn[disabled], .btn.disabled { opacity: .55; cursor: not-allowed; }
.btn.primary {
  color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,.35);
  background: linear-gradient(#6fb4ea, #2c7fc0 55%, #1e6ca8); border-color: #17557f;
}
.btn.primary:hover { color: #fff; background: linear-gradient(#84c2f2, #3a8dcd 55%, #2578b6); }
.btn.danger {
  color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,.35);
  background: linear-gradient(#e0705f, #bc3626 55%, #a0281a); border-color: #7d1d12;
}
.btn.danger:hover { color: #fff; }
.btn.go {
  color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,.35);
  background: linear-gradient(#7ed07e, #3f9d47 55%, #2f8438); border-color: #256a2c;
}
.btn.go:hover { color: #fff; }
.btn.small { padding: 3px 8px; font-size: 10px; }
.btn.big { padding: 9px 22px; font-size: 14px; }
.btn.block { display: block; width: 100%; text-align: center; }

/* ------------------------------------------------------------------ alerts */
.notice {
  padding: 7px 10px; border-radius: 3px; margin-bottom: 10px; font-weight: bold;
  border: 1px solid var(--ok-edge); background: var(--ok-bg); color: var(--ok-ink);
}
.notice.bad { border-color: var(--bad-edge); background: var(--bad-bg); color: var(--bad-ink); }
.notice.info { border-color: var(--info-edge); background: var(--info-bg); color: var(--info-ink); }
.notice.warn { border-color: var(--warn-edge); background: var(--warn-bg); color: var(--warn-ink); }

/* ------------------------------------------------------------------ tables */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.grid { width: 100%; border-collapse: collapse; }
table.grid th {
  background: var(--panel-alt); text-align: left;
  padding: 5px 8px; border-bottom: 1px solid var(--line); color: var(--ink-label);
  font-size: 10px; text-transform: uppercase; letter-spacing: .4px;
}
table.grid td { padding: 5px 8px; border-bottom: 1px dotted var(--line-dot); vertical-align: middle; }
table.grid tr:nth-child(even) td { background: var(--panel-alt); }
table.grid tr:hover td { background: var(--warn-bg); }

dl.stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 0;
}
dl.stats > div {
  background: var(--panel-alt); border: 1px solid var(--line-soft); border-radius: 3px;
  padding: 6px 4px; text-align: center; min-width: 0;
}
dl.stats dt {
  font-size: 9px; color: var(--ink-soft); text-transform: uppercase;
  letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
dl.stats dd {
  /* numbers used to run out of the box on wide values; clamp and ellipsise */
  margin: 2px 0 0; font-size: 14px; font-weight: bold; color: var(--ink-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
dl.stats.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ------------------------------------------------------------- online dots */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; border: 1px solid rgba(0,0,0,.3); }
.dot.on { background: var(--dot-on); animation: pulse 2.4s ease-in-out infinite; }
.dot.off { background: var(--dot-off); }
.dot.game { background: var(--gold); animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(63,191,74,.6);} 60% { box-shadow: 0 0 0 4px rgba(63,191,74,0);} }

/* ----------------------------------------------------------- avatar tiles */
/* A grid rather than a wrapping flex row: the cards share out whatever width
   the panel has, so a list of players reaches the right-hand edge instead of
   stopping short of it with a ragged gap. */
.userlist {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
}
.usercard {
  min-width: 0; text-align: center; padding: 4px; border: 1px solid var(--line-soft);
  border-radius: 4px; background: var(--panel-alt); transition: transform .12s, box-shadow .12s;
}
.usercard:hover { transform: translateY(-2px); box-shadow: 0 3px 6px var(--shadow-lift); border-color: var(--line); }
.usercard .thumb {
  width: 100%; max-width: none; aspect-ratio: 1 / 1; height: auto;
  margin: 0 auto 3px; border-radius: 3px;
  background: var(--preview-bg); border: 1px solid var(--line-soft);
  display: block;
}
.usercard .uname { display: block; font-size: 10px; font-weight: bold; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The narrow profile column wants smaller tiles, but still a full row of
   them -- the track minimum is what decides how many fit. */
.userlist:has(.usercard.small) {
  grid-template-columns: repeat(auto-fill, minmax(68px, 1fr));
}

/* ------------------------------------------------------------ folded lists
   A long list shows its first few and keeps the rest behind one button.  The
   whole list is in the markup either way: the fold is only applied once the
   script has run, so a reader without JavaScript gets everything rather than
   a button that does nothing.  The button is centred on its own line, which
   is what makes it land under the thumb on a phone rather than off in a
   corner. */
.folded .fold-extra { display: none; }
.foldbar { display: flex; justify-content: center; margin-top: 9px; }
.foldbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 132px; max-width: 100%;
}
.foldbtn .chev {
  font-size: 8px; line-height: 1; transition: transform .2s ease;
  position: relative; top: -1px;
}
.foldbtn.open .chev { transform: rotate(180deg); }

/* --------------------------------------------------------------- item tiles */
.itemgrid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(126px, 1fr)); gap: 9px;
}
.itemgrid.compact { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 6px; }
.item {
  border: 2px solid var(--tile-edge); border-radius: 4px; background: var(--panel);
  overflow: hidden; position: relative; transition: transform .12s, box-shadow .12s;
  min-width: 0;
}
.item:hover { transform: translateY(-2px); box-shadow: 0 4px 9px var(--shadow-lift); }
.item .thumb-wrap {
  position: relative; aspect-ratio: 1 / 1; display: flex;
  align-items: center; justify-content: center;
  background: var(--tile-normal);
  border-bottom: 1px solid var(--line-soft); overflow: hidden;
}
.item.tier-unusual .thumb-wrap { background: var(--tile-unusual); }
.item.tier-unusual { border-color: var(--unusual); box-shadow: 0 0 0 1px rgba(139,63,214,.35); }
/* The Unusual glint.  This used to be an animated background-position on a
   background-size wider than the tile, which tiles by default: several
   highlights at once, and a hard jump at the wrap.  It is a single narrow
   element swept with a transform instead -- one highlight, GPU-composited,
   and because it starts and ends completely outside the tile the cycle joins
   itself with nothing on screen at the seam.  The sweep is the first 55% of
   the cycle and the rest is the tile at rest, so it reads as a glint every
   few seconds rather than a constant strobe. */
.item.tier-unusual::after {
  content: ""; position: absolute; pointer-events: none;
  top: -25%; bottom: -25%; left: 0; width: 38%;
  background: linear-gradient(90deg,
              rgba(255,255,255,0) 0%, rgba(255,255,255,.10) 30%,
              rgba(255,255,255,.42) 50%,
              rgba(255,255,255,.10) 70%, rgba(255,255,255,0) 100%);
  animation: shimmer 5.2s linear infinite;
}
@keyframes shimmer {
  0%        { transform: translateX(-180%) skewX(-10deg); }
  55%, 100% { transform: translateX(400%) skewX(-10deg); }
}
/* Pinned items sit still: the pin row (on the profile and in the pin editor)
   shows the tier by its border and plate, not the sweep. */
.pinrow .item::after { content: none; animation: none; }
.item .thumb { width: 92%; height: auto; aspect-ratio: 1 / 1; display: block; image-rendering: auto; }
.item .meta { padding: 6px 7px; min-width: 0; }
.item .iname { font-weight: bold; font-size: 11px; display: block; margin-bottom: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item .islot { font-size: 9px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .4px;
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item .price { font-weight: bold; color: var(--ink-strong); }
.item .price .coin { width: 11px; height: 11px; vertical-align: -1px; }

/* The tier is carried by the glowing tile background; the word only appears
   when the pointer is actually on the item (and is never shown on touch,
   where there is no hover to reveal it). */
.tier-flag {
  position: absolute; top: 5px; left: 5px; font-size: 9px; font-weight: bold;
  padding: 1px 5px; border-radius: 2px; letter-spacing: .5px; text-transform: uppercase;
  background: var(--badge-bg); color: var(--badge-ink); border: 1px solid var(--badge-edge);
  opacity: 0; transform: translateY(-4px); pointer-events: none;
  transition: opacity .16s ease, transform .16s ease;
}
.item:hover .tier-flag, .pick:hover .tier-flag { opacity: 1; transform: none; }
.tier-flag.static { position: static; display: inline-block; opacity: 1; transform: none; }
.tier-flag.unusual {
  background: linear-gradient(var(--unusual-soft), var(--unusual)); color: #fff;
  border-color: var(--head-purple-edge);
  box-shadow: 0 0 6px rgba(199,139,255,.85);
}
.owned-flag {
  position: absolute; top: 5px; right: 5px; font-size: 9px; font-weight: bold;
  padding: 1px 5px; border-radius: 2px; background: #3f8f45; color: #fff; border: 1px solid #276330;
}
.effect-flag {
  position: absolute; bottom: 5px; left: 5px; right: 5px; font-size: 9px; text-align: center;
  padding: 1px 3px; border-radius: 2px; background: rgba(30,10,50,.72); color: #e8d5ff;
  border: 1px solid rgba(199,139,255,.5);
  opacity: 0; transition: opacity .16s ease;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.item:hover .effect-flag, .pick:hover .effect-flag { opacity: 1; }

/* --------------------------------------------------------------- world cards */
.worldgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.worldcard { border: 1px solid var(--line); border-radius: 4px; overflow: hidden; background: var(--panel); min-width: 0; }
.worldcard:hover { box-shadow: 0 4px 10px var(--shadow-lift); }
.worldcard .shot { aspect-ratio: 16 / 9; position: relative; overflow: hidden; display: block; }
.worldcard .shot canvas, .worldcard .shot img {
  width: 100%; height: 100%; display: block; object-fit: cover;
}
.worldcard .live {
  position: absolute; top: 6px; left: 6px; background: rgba(0,0,0,.62); color: #fff;
  font-size: 10px; padding: 2px 7px; border-radius: 10px; font-weight: bold;
  display: flex; align-items: center; gap: 5px;
}
.worldcard .genre {
  position: absolute; top: 6px; right: 6px; background: rgba(255,255,255,.85);
  color: #1b3d5f; font-size: 9px; padding: 2px 6px; border-radius: 2px; font-weight: bold;
  text-transform: uppercase; letter-spacing: .4px;
}
.worldcard .wbody { padding: 8px 10px; }
.worldcard .wtitle { font-size: 13px; font-weight: bold; color: var(--ink-strong); }
.worldcard .wtag { color: var(--ink-soft); font-style: italic; margin: 2px 0 6px; }
.worldcard .wstats { display: flex; gap: 10px; font-size: 10px; color: var(--ink-label); margin-bottom: 7px; flex-wrap: wrap; }
.worldcard .wstats b { color: var(--ink-strong); }

.ratingbar { height: 7px; background: var(--sunken); border-radius: 4px; overflow: hidden; border: 1px solid var(--line-soft); }
.ratingbar i { display: block; height: 100%; background: linear-gradient(#7ed07e, #3f9d47); }

/* ------------------------------------------------------------------- posts */
.post { border-bottom: 1px dotted var(--line-dot); padding: 8px 0; }
.post:last-child { border-bottom: 0; }
.post .who { font-weight: bold; }
.post .when { color: var(--ink-soft); font-size: 10px; }
.post .body { margin: 4px 0 5px; line-height: 1.55; white-space: pre-wrap; word-wrap: break-word; }
.post .actions { display: flex; gap: 10px; font-size: 10px; align-items: center; flex-wrap: wrap; }
.post .actions a { cursor: pointer; }
.comment { border-left: 2px solid var(--line-soft); margin: 5px 0 0 12px; padding: 3px 0 3px 8px; }
.comment .when { color: var(--ink-soft); }

.commentbox { display: flex; gap: 6px; margin-top: 6px; }
.commentbox input { flex: 1 1 auto; min-width: 0; }

/* ---------------------------------------------------------------- avatar 3d */
.avatar-view {
  background: var(--preview-bg); border: 1px solid var(--preview-edge);
  border-radius: 4px; position: relative; overflow: hidden;
}
.avatar-view canvas { display: block; width: 100%; height: 100%; cursor: grab; }
.avatar-view canvas:active { cursor: grabbing; }
/* The panel behind these is dark whatever the page is doing, so they are
   light-on-dark in every theme rather than following the palette. */
.avatar-view .hint {
  position: absolute; bottom: 4px; right: 6px; font-size: 9px; color: #cfe0f0;
  background: rgba(10,20,30,.72); padding: 1px 5px; border-radius: 2px;
}

/* ------------------------------------------------------------------ swatches */
/* Body colours sits under the hotbar, the full width of the editor, so the
   six parts flow across it instead of stacking into a very long panel.  Each
   group keeps its own swatch grid, which is what keeps a swatch a chip rather
   than a slab stretched across a seventh of the column. */
#body-colors {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(212px, 1fr));
  gap: 10px 14px; align-items: start;
}
#body-colors .field { margin-bottom: 0; }
.swatches { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.swatch {
  height: 22px; border-radius: 3px; border: 1px solid rgba(0,0,0,.28); cursor: pointer;
  position: relative; transition: transform .1s;
}
.swatch:hover { transform: scale(1.12); z-index: 2; }
.swatch.on { outline: 2px solid var(--gold); outline-offset: 1px; }

.slotpick { display: flex; gap: 6px; flex-wrap: wrap; }
.slotpick .pick {
  width: 74px; text-align: center; border: 2px solid var(--tile-edge); border-radius: 3px;
  padding: 3px; cursor: pointer; background: var(--panel-alt); position: relative;
}
.slotpick .pick.on { border-color: var(--gold); background: var(--warn-bg); box-shadow: 0 0 0 1px var(--gold); }
.slotpick .pick canvas { width: 64px; height: 64px; display: block; margin: 0 auto; }
.slotpick .pick span { display: block; font-size: 9px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slotpick .pick.unusual { border-color: var(--unusual); background: var(--tile-unusual); color: #fff; }

/* --------------------------------------------------------- body type picker
   Two builds, so two buttons, side by side.  Each is half of the row rather
   than a fixed width, so the pair fills the editor's sidebar on a desktop and
   the full width of the panel on a phone from the same rule, and each carries
   a figure drawn at that build's proportions above its name.  The whole
   button is the target -- 44px tall at its smallest -- so it is as easy to
   hit with a thumb as with a pointer. */
.bodypick { display: flex; gap: 8px; }
.bodyopt {
  flex: 1 1 0; min-width: 0; cursor: pointer; font-family: inherit;
  background: var(--panel-alt); border: 1px solid var(--line-soft);
  border-radius: 4px; padding: 8px 6px 7px; color: var(--ink);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 44px; text-align: center;
  transition: border-color .15s, box-shadow .15s, transform .12s;
}
.bodyopt:hover { transform: translateY(-1px); border-color: var(--line); }
.bodyopt:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.bodyopt.on { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold); background: var(--warn-bg); }
.bodyopt .bodylabel { display: block; font-size: 11px; font-weight: bold; margin-top: 5px; }
.bodyopt .bodyhint {
  display: block; font-size: 9px; line-height: 1.3; margin-top: 1px;
  color: var(--ink-soft); max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.bodyicon { display: block; width: 36px; height: 36px; margin: 0 auto; position: relative; }
.bodyicon i { position: absolute; background: currentColor; border-radius: 3px; opacity: .85; }
/* head -- the same on both builds, because the rig's head is */
.bodyicon i:nth-child(1) { left: 50%; top: 0; width: 38%; height: 29%; margin-left: -19%;
  border-radius: 40%; }
/* torso and legs, each drawn at its own build's width: the broad one is
   nearly as wide as its shoulders all the way down, the slighter one comes
   in at the waist and stands on narrower legs */
.bodyicon.male i:nth-child(2) { left: 50%; top: 32%; width: 53%; height: 35%; margin-left: -26.5%; }
.bodyicon.male i:nth-child(3) { left: 50%; top: 66%; width: 47%; height: 34%; margin-left: -23.5%; }
.bodyicon.female i:nth-child(2) { left: 50%; top: 32%; width: 41%; height: 35%; margin-left: -20.5%;
  border-radius: 26% 26% 14% 14%; }
.bodyicon.female i:nth-child(3) { left: 50%; top: 66%; width: 38%; height: 34%; margin-left: -19%; }

.hotbar { display: flex; gap: 6px; }
.hotslot {
  flex: 1 1 0; min-width: 0; border: 2px solid var(--line); border-radius: 4px;
  background: var(--panel-alt);
  text-align: center; padding: 4px; min-height: 84px; cursor: pointer; position: relative;
}
.hotslot.on { border-color: var(--gold); background: var(--warn-bg); }
.hotslot .num {
  position: absolute; top: 2px; left: 4px; font-size: 9px; font-weight: bold; color: var(--ink-soft);
}
.hotslot canvas { width: 100%; max-width: 56px; height: auto; aspect-ratio: 1/1; display: block; margin: 2px auto 0; }
.hotslot span { display: block; font-size: 9px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------------------------------- footer */
.footer {
  margin: 18px 0 26px; padding: 12px 0; border-top: 1px solid var(--line);
  color: var(--ink-soft); font-size: 10px; text-align: center;
}
.footer a { color: var(--ink-label); margin: 0 6px; }

/* ------------------------------------------------------------------ landing */
.hero {
  background: var(--hero);
  border: 1px solid var(--hero-edge); border-radius: 5px; color: #eaf4ff; overflow: hidden;
  position: relative;
}
.hero .inner { padding: 20px 22px; position: relative; z-index: 2; }
.hero h1 { color: #fff; font-size: 27px; text-shadow: 2px 2px 0 rgba(0,0,0,.35); margin-bottom: 4px; }
.hero p { color: #bfe0ff; font-size: 12px; max-width: 560px; }
.hero .cloud {
  position: absolute; border-radius: 50%; background: rgba(255,255,255,.07);
  box-shadow: 0 0 40px 24px rgba(255,255,255,.05);
  animation: drift 40s linear infinite; z-index: 1;
}
@keyframes drift { from { transform: translateX(-140px);} to { transform: translateX(1200px);} }

.steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.steps .step { background: var(--panel); border: 1px solid var(--line-soft); border-radius: 4px; padding: 10px; }
.steps .n {
  display: inline-block; width: 20px; height: 20px; line-height: 20px; text-align: center;
  border-radius: 50%; background: var(--brand-red); color: #fff; font-weight: bold; margin-bottom: 5px;
}

/* ------------------------------------------------------- event / spotlight */
.eventbar {
  position: relative; overflow: hidden; border-radius: 5px;
  border: 1px solid var(--hero-edge); background: var(--hero);
  color: #eaf4ff; margin-bottom: 12px;
}
.eventbar .glow {
  position: absolute; inset: -40% -10% auto -10%; height: 220%;
  background: radial-gradient(closest-side, rgba(255,210,90,.26), transparent 70%);
  animation: sweep 9s ease-in-out infinite alternate;
}
@keyframes sweep { from { transform: translateX(-18%); } to { transform: translateX(18%); } }
.eventbar .inner {
  position: relative; z-index: 2; display: flex; align-items: center; gap: 14px;
  padding: 12px 16px; flex-wrap: wrap;
}
.eventbar .tagline { flex: 1 1 240px; min-width: 0; }
.eventbar .kicker {
  display: inline-block; font-size: 9px; font-weight: bold; letter-spacing: 1.2px;
  text-transform: uppercase; background: var(--brand-red); color: #fff;
  padding: 2px 7px; border-radius: 2px; margin-bottom: 5px;
}
.eventbar h2 { color: #fff; font-size: 17px; margin: 0 0 3px; }
.eventbar p { color: #cfe6ff; margin: 0; font-size: 11px; }
.eventbar .countdown {
  display: flex; gap: 6px; flex: 0 0 auto;
}
.eventbar .unit {
  background: rgba(0,0,0,.32); border: 1px solid rgba(255,255,255,.22);
  border-radius: 4px; padding: 5px 8px; text-align: center; min-width: 46px;
}
.eventbar .unit b { display: block; font-size: 16px; color: #ffe08a; font-variant-numeric: tabular-nums; }
.eventbar .unit span { font-size: 8px; text-transform: uppercase; letter-spacing: .6px; color: #bfe0ff; }

.spotgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.spotcard {
  border: 1px solid var(--line-soft); border-radius: 4px; background: var(--panel-alt);
  padding: 9px 10px; min-width: 0;
}
.spotcard .lead { font-size: 12px; font-weight: bold; color: var(--ink-strong); }
.spotcard .sub { font-size: 10px; color: var(--ink-soft); margin-top: 2px; }

/* --------------------------------------------------------------- scrollbars */
.scroll { overflow-y: auto; }
.scroll::-webkit-scrollbar { width: 10px; }
.scroll::-webkit-scrollbar-track { background: var(--sunken); border-left: 1px solid var(--line-soft); }
.scroll::-webkit-scrollbar-thumb { background: var(--btn); border-radius: 5px; border: 1px solid var(--btn-edge); }

/* -------------------------------------------------------------------- misc */
.kv { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 3px 8px; }
.kv dt { color: var(--ink-soft); }
.kv dd { margin: 0; font-weight: bold; color: var(--ink-strong); overflow-wrap: anywhere; }
.pill {
  display: inline-block; padding: 1px 7px; border-radius: 9px; font-size: 10px;
  background: var(--info-bg); border: 1px solid var(--info-edge); color: var(--info-ink); font-weight: bold;
}
.pill.red { background: var(--bad-bg); border-color: var(--bad-edge); color: var(--bad-ink); }
.pill.green { background: var(--ok-bg); border-color: var(--ok-edge); color: var(--ok-ink); }
.pill.purple { background: var(--tile-unusual); border-color: var(--unusual); color: #fff; }
.team-red { color: #b8383b; font-weight: bold; }
.team-blue { color: #2f6f9f; font-weight: bold; }

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 10px;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs a {
  padding: 5px 12px; background: var(--panel-alt); border: 1px solid var(--line); border-bottom: 0;
  border-radius: 3px 3px 0 0; font-weight: bold; color: var(--ink-label);
  white-space: nowrap; cursor: pointer;
}
.tabs a.on { background: var(--panel); color: var(--link-hover); position: relative; top: 1px; }

.progress { height: 12px; background: var(--sunken); border: 1px solid var(--line-soft); border-radius: 3px; overflow: hidden; }
.progress i { display: block; height: 100%; background: linear-gradient(#7bb8ea, #2c7fc0); }

.loading { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--line-soft);
  border-top-color: #2c7fc0; border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------ modal dialogs
   Every confirmation in the site uses this instead of window.confirm, so the
   buy flow and the sell flow look like the rest of the chrome. */
.modal-scrim {
  position: fixed; inset: 0; background: var(--scrim); z-index: 900;
  display: flex; align-items: center; justify-content: center; padding: 16px;
  animation: fadein .16s ease-out;
}
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
.modal-scrim .panel {
  width: 380px; max-width: 100%; margin: 0; animation: popin .2s cubic-bezier(.3,1.4,.5,1);
  max-height: 92vh; overflow: auto;
}
@keyframes popin { from { transform: scale(.9) translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; flex-wrap: wrap; }
.modal-actions .btn { min-width: 92px; text-align: center; }

/* ------------------------------------------------------------ message inbox */
.msglist { border-top: 1px solid var(--line-soft); }
.msgrow {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px;
  border-bottom: 1px solid var(--line-soft); cursor: pointer; position: relative;
  color: inherit; text-decoration: none;
}
.msgrow:hover { background: var(--panel-alt); text-decoration: none; }
.msgrow:visited { color: inherit; }
.msgrow.unread { background: var(--info-bg); }
.msgrow.unread::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--alert-bg);
}
.msgrow .who-thumb {
  width: 40px; height: 40px; flex: 0 0 40px; border-radius: 4px;
  background: var(--preview-bg); border: 1px solid var(--line-soft); display: block;
}
.msgrow .msgmain { flex: 1 1 auto; min-width: 0; }
.msgrow .msgtop { display: flex; align-items: baseline; gap: 8px; }
.msgrow .msgwho { font-weight: bold; color: var(--ink-strong); flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgrow.unread .msgwho::after {
  content: "NEW"; font-size: 8px; background: var(--alert-bg); color: var(--alert-ink);
  border-radius: 2px; padding: 1px 4px; margin-left: 6px; vertical-align: 1px;
}
.msgrow .msgwhen { font-size: 10px; color: var(--ink-soft); flex: 0 0 auto; }
.msgrow .msgsubject { display: block; font-size: 11px; font-weight: bold; margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgrow .msgpreview { display: block; font-size: 10px; color: var(--ink-soft); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgrow .msgdelete {
  flex: 0 0 auto; align-self: center; font-size: 10px; color: var(--ink-soft);
  border: 1px solid var(--line-soft); border-radius: 3px; padding: 3px 7px;
  background: var(--panel); cursor: pointer; font-family: inherit;
}
.msgrow .msgdelete:hover { color: var(--bad-ink); border-color: var(--bad-edge); }

.thread { display: flex; flex-direction: column; gap: 8px; }
.bubble {
  max-width: 78%; padding: 8px 11px; border-radius: 10px; line-height: 1.55;
  white-space: pre-wrap; word-wrap: break-word; font-size: 12px;
}
.bubble.them { align-self: flex-start; background: var(--panel-alt); border: 1px solid var(--line-soft);
  border-bottom-left-radius: 3px; }
.bubble.me { align-self: flex-end; background: var(--info-bg); border: 1px solid var(--info-edge);
  border-bottom-right-radius: 3px; }
.bubble .stamp { display: block; font-size: 9px; color: var(--ink-soft); margin-top: 4px; }

/* -------------------------------------------------------- floating messenger
   A small docked chat launcher.  It is deliberately absent from the Game View
   (that page never loads site.js) and remembers whether it was open. */
[hidden] { display: none !important; }
.dock {
  position: fixed; right: 14px; bottom: 14px; z-index: 880;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
}
/* A deeper blue than the chrome around it: the bubble floats over whatever
   page is underneath, so it has to read as a control rather than as part of
   the panel it happens to be sitting on. */
.dock-toggle {
  display: flex; align-items: center; gap: 7px; cursor: pointer; font-family: inherit;
  font-size: 11px; font-weight: bold; color: #fff;
  background: linear-gradient(#1d5a94, #0d3a63);
  border: 1px solid #07243d;
  border-radius: 22px; padding: 9px 14px;
  box-shadow: 0 4px 14px rgba(0,0,0,.42);
  transition: transform .15s ease, box-shadow .15s ease;
}
.dock-toggle:hover { transform: translateY(-2px); box-shadow: 0 7px 18px rgba(0,0,0,.4); }
.dock-toggle .chev { transition: transform .25s ease; }
.dock.open .dock-toggle .chev { transform: rotate(180deg); }
.dock-toggle .dockbadge {
  background: var(--alert-bg); color: var(--alert-ink); border-radius: 9px;
  min-width: 16px; padding: 0 5px; font-size: 10px; line-height: 15px; text-align: center;
}
.dock-panel {
  width: 310px; max-width: calc(100vw - 28px); max-height: 60vh;
  display: none; flex-direction: column; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
  box-shadow: 0 10px 30px rgba(0,0,0,.4);
  transition: max-height .3s cubic-bezier(.3, .8, .35, 1);
}
.dock.open .dock-panel { display: flex; animation: popin .18s ease-out; }
.dock-panel .dock-head {
  background: var(--head-blue); color: var(--head-ink); padding: 7px 10px;
  font-weight: bold; font-size: 11px; display: flex; justify-content: space-between;
  align-items: center; gap: 8px;
}
.dock-panel .dock-head a { color: #e6f2ff; font-size: 10px; font-weight: normal; }
.dock-body { overflow-y: auto; flex: 1 1 auto; }
.dock-body .msgrow { padding: 7px 9px; }
.dock-body .msgrow .who-thumb { width: 30px; height: 30px; flex-basis: 30px; }
.dock-foot { padding: 7px 9px; border-top: 1px solid var(--line-soft); background: var(--panel-foot); }

/* ------------------------------------------------------------------ toasts */
#site-toasts {
  position: fixed; right: 14px; bottom: 14px; z-index: 999;
  display: flex; flex-direction: column; gap: 6px; align-items: flex-end;
  max-width: calc(100vw - 28px);
}
.dock ~ #site-toasts, body.has-dock #site-toasts { bottom: 68px; }

/* ------------------------------------------------------------ pinned items */
.pinrow { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; }
.pinrow .item .thumb-wrap { aspect-ratio: 1 / 1; }
.pinslot {
  border: 2px dashed var(--tile-edge); border-radius: 4px; background: var(--panel-alt);
  display: flex; align-items: center; justify-content: center; text-align: center;
  color: var(--ink-soft); font-size: 10px; padding: 10px 6px; aspect-ratio: 1 / 1;
}

/* ---------------------------------------------------------------- responsive
   Phone layout.  The site is a companion to the game here: messaging,
   profile editing and browsing.  The Game View itself is desktop only, so the
   Load/Play controls are removed rather than left to fail. */
@media (max-width: 1000px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .row { flex-wrap: wrap; }
  .col-side, .col-narrow { width: 100%; flex: 1 1 100%; }
  .wrap { padding: 0 10px; }

  .only-mobile.only-mobile { display: block; }
  .pill.only-mobile.only-mobile { display: inline-block; }
  .no-mobile { display: none !important; }

  /* top bar: brand, wallet, burger -- everything else moves into the drawer */
  .topbar .wrap {
    min-height: 56px; padding: 10px 10px; gap: 8px; flex-wrap: nowrap;
  }
  .brand-logo { height: 34px; }
  .brand-tag { display: none; }
  .topbar .searchbox { display: none; }
  .topbar .topnav { display: none; }
  .topbar .themetoggle { display: none; }
  .topbar .wallet { margin-left: auto; padding: 4px 7px; font-size: 11px; }
  /* Its own auto margin, so the burger sits against the right edge whether or
     not there is a wallet beside it to push it there. */
  .navtoggle { display: block; margin-left: auto; }

  /* the red strip becomes the drawer instead of a row that overflows */
  .tabbar { border-bottom-width: 0; }
  .tabbar .wrap {
    display: none; flex-direction: column; gap: 0; padding: 0 10px 8px;
  }
  .tabbar.open { border-bottom-width: 2px; }
  .tabbar.open .wrap { display: flex; animation: drawer .2s ease-out; }
  @keyframes drawer { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
  .tabbar a {
    border-right: 0; border-bottom: 1px solid rgba(255,255,255,.14);
    padding: 11px 6px; font-size: 12px; display: flex; align-items: center; gap: 8px;
  }
  .tabbar a.on { border-radius: 4px; }
  .tabbar a.only-mobile.only-mobile { display: flex; }
  .drawer-extra.only-mobile.only-mobile {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 11px 6px 4px; color: var(--tabbar-ink); font-weight: bold; font-size: 12px;
  }
  .drawer-search.only-mobile.only-mobile { display: flex; padding: 9px 0 4px; }
  .drawer-search input { flex: 1 1 auto; border-radius: 3px 0 0 3px; }
  .drawer-search button { border-radius: 0 3px 3px 0; }

  .itemgrid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 7px; }
  .itemgrid.compact { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); }
  .worldgrid { grid-template-columns: minmax(0, 1fr); }
  .userlist { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
  .userlist:has(.usercard.small) {
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  }
  dl.stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  dl.stats dd { font-size: 13px; }
  .kv { grid-template-columns: 92px minmax(0, 1fr); }
  .panel-head { font-size: 11px; padding: 7px 10px; }
  .panel-body { padding: 9px; }
  .bubble { max-width: 88%; }
  /* a thumb-sized target, centred, rather than a desktop-width pill */
  .foldbar .foldbtn { width: 100%; max-width: 280px; padding: 9px 12px; font-size: 12px; }
  .slotpick .pick { width: calc(25% - 5px); }
  .slotpick .pick canvas { width: 100%; height: auto; aspect-ratio: 1/1; }
  /* The two build buttons stay side by side on a phone -- there are only two
     of them and they are the width of the panel between them already.  They
     just get roomier, because here a build is picked with a thumb. */
  .bodypick { gap: 10px; }
  .bodyopt { padding: 11px 8px 10px; min-height: 62px; }
  .bodyopt .bodylabel { font-size: 12px; }
  .bodyopt .bodyhint { font-size: 10px; }
  .bodyicon { width: 42px; height: 42px; }
  .hotslot { min-height: 70px; }
  /* Up off the very bottom edge, clear of a home indicator and of the
     browser's own bottom chrome -- and, while a keyboard is up, off the top
     of the keyboard as well.  --dock-lift is how far the on-screen keyboard
     has eaten into the window; site.js measures it from visualViewport,
     which is the only thing on a phone that actually knows. */
  .dock {
    right: 10px; bottom: calc(26px + env(safe-area-inset-bottom, 0px));
    transform: translateY(calc(-1 * var(--dock-lift, 0px)));
    transition: transform .2s ease;
  }
  /* Opening a conversation raises the window: a list of names reads fine in
     a short box, a conversation does not.  Closing it puts the box back.
     Both are capped by what is actually on screen (--vvh is the visual
     viewport, so it shrinks with the keyboard), which is what stops the
     panel growing up past the top of the window on a small phone. */
  .dock-panel {
    width: calc(100vw - 20px); min-height: 0;
    max-height: min(58vh, calc(var(--vvh, 100vh) - 96px));
    transition: min-height .3s cubic-bezier(.3, .8, .35, 1),
                max-height .3s cubic-bezier(.3, .8, .35, 1);
  }
  /* min-height rather than max-height, because a panel that is only capped
     stays the size of its own contents -- and a conversation with two lines
     in it is shorter than the list of names it replaced, which is the exact
     opposite of what opening one should do. */
  .dock.dm-open .dock-panel {
    min-height: min(78vh, calc(var(--vvh, 100vh) - 96px));
    max-height: min(86vh, calc(var(--vvh, 100vh) - 96px));
  }
  .dock-thread { min-height: 80px; }
  .dock ~ #site-toasts, body.has-dock #site-toasts {
    bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  }
  /* A sheet glued to the bottom edge is right for a yes/no.  Anything you are
     meant to look at -- an item preview above all -- sits in the middle of the
     screen with a gutter down each side instead. */
  .modal-scrim { align-items: flex-end; padding: 0; }
  .modal-scrim .panel { width: 100%; border-radius: 8px 8px 0 0; max-height: 86vh; }
  .modal-scrim.centered { align-items: center; padding: 14px; }
  .modal-scrim.centered .panel {
    width: 100%; border-radius: 6px; max-height: calc(100vh - 28px);
  }
  .footer { margin-bottom: 96px; }
  .hero .inner { padding: 16px; }
  .hero h1 { font-size: 21px; }
  .eventbar .inner { padding: 12px; gap: 10px; }
  .eventbar .countdown { width: 100%; }
  .eventbar .unit { flex: 1 1 0; min-width: 0; }
}

@media (max-width: 480px) {
  .steps { grid-template-columns: minmax(0, 1fr); }
  .itemgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .userlist, .userlist:has(.usercard.small) {
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  }
  .swatches { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  /* a narrow phone: the pair still shares the row, with the label carrying
     the name and the hint dropping out rather than being clipped */
  .bodypick { gap: 8px; }
  .bodyopt { padding: 10px 5px 9px; }
  .bodyopt .bodyhint { display: none; }
  dl.stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pinrow { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
  .slotpick .pick { width: calc(33.333% - 4px); }
  .msgrow { padding: 8px 8px; gap: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .ticker-track, .item.tier-unusual::after, .hero .cloud, .eventbar .glow,
  .dot.on, .dot.game { animation: none !important; }
  * { transition-duration: .01ms !important; }
}

/* ==========================================================================
   WELCOME HERO
   The first screen a visitor sees.  One character on a stage, a sky that
   moves, and numbers that count themselves up -- all of it built out of the
   same 3D rig and the same catalogue the rest of the site runs on, so it is
   a demonstration rather than a picture of one.
   ========================================================================== */
.hero {
  position: relative; overflow: hidden; isolation: isolate;
  border: 1px solid var(--hero-edge); border-radius: 7px;
  background: var(--hero); color: #eaf4ff;
}
.hero-sky { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.hero-sky .sun {
  position: absolute; right: -70px; top: -90px; width: 280px; height: 280px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,226,143,.42), rgba(255,226,143,0) 66%);
}
.hero-sky .cloud {
  position: absolute; left: -30%; top: var(--top, 20%);
  width: var(--w, 150px); height: var(--h, 32px); border-radius: 999px;
  background: rgba(255,255,255,.085);
  box-shadow: 0 0 40px 22px rgba(255,255,255,.045);
  animation: heroDrift var(--dur, 60s) linear infinite;
  animation-delay: var(--delay, 0s);
}
@keyframes heroDrift {
  from { transform: translateX(-14vw); }
  to   { transform: translateX(128vw); }
}
/* Loose bricks bobbing in the background: the platform's own vocabulary,
   used as scenery rather than as another gradient. */
.hero-sky .brick {
  position: absolute; left: var(--x, 10%); top: var(--y, 40%);
  width: 15px; height: 15px; border-radius: 3px; background: var(--c, #f5cd30);
  opacity: .2; box-shadow: inset 0 -4px 0 rgba(0,0,0,.28);
  animation: heroFloat var(--d, 9s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}
@keyframes heroFloat {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-18px) rotate(16deg); }
}

.hero-inner {
  position: relative; z-index: 1; display: grid; gap: 22px;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  align-items: center; padding: 26px 24px 22px;
}
/* Sits under the lede as a plain reassurance line, not a status light. */
.hero-kicker {
  display: inline-flex; align-items: center;
  font-size: 10px; font-weight: bold; letter-spacing: .8px; text-transform: uppercase;
  color: #cfe6ff; background: rgba(0,0,0,.28); border: 1px solid rgba(255,255,255,.2);
  border-radius: 999px; padding: 4px 11px; margin-top: 11px;
}
.hero-copy h1 {
  color: #fff; font-size: 38px; line-height: 1.04; margin: 0 0 8px;
  text-shadow: 0 3px 0 rgba(0,0,0,.32);
}
.hero-copy h1 em {
  font-style: normal;
  background: linear-gradient(92deg, #ffd95e, #ff9d5c 45%, #ffd95e);
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: heroSheen 7s ease-in-out infinite;
}
@keyframes heroSheen {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}
.hero-lede { color: #cfe6ff; font-size: 12.5px; line-height: 1.6; max-width: 46ch; }
.hero-lede .unu { color: #d8aaff; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.btn.hollow {
  background: rgba(255,255,255,.08); color: #eaf4ff !important;
  border-color: rgba(255,255,255,.38); text-shadow: none;
}
.btn.hollow:hover { background: rgba(255,255,255,.18); }

.hero-facts {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px; margin: 16px 0 0; padding: 0; list-style: none;
}
.hero-facts li {
  background: rgba(0,0,0,.26); border: 1px solid rgba(255,255,255,.16);
  border-radius: 5px; padding: 7px 8px; min-width: 0;
}
.hero-facts b {
  display: block; font-size: 17px; color: #ffe08a; font-variant-numeric: tabular-nums;
}
.hero-facts span {
  display: block; font-size: 8.5px; text-transform: uppercase; letter-spacing: .6px;
  color: #bfe0ff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ------------------------------------------------------------- the stage */
.hero-stage { position: relative; display: flex; flex-direction: column; gap: 8px; }
.avatar-view.hero-avatar {
  height: 320px; border-radius: 10px;
  background: radial-gradient(ellipse at 50% 38%, rgba(120,190,255,.20),
              rgba(4,14,26,.42) 68%);
  border: 1px solid rgba(140,190,240,.36);
  box-shadow: inset 0 0 60px rgba(0,0,0,.35);
}
/* the stage is dark in both themes, so its labels are light in both */
.avatar-view.hero-avatar .hint {
  background: rgba(6,18,30,.6); color: #cfe0f0; border-color: rgba(140,190,240,.3);
}
.hero-look { text-align: center; min-height: 34px; }
.hero-look-name {
  display: block; font-size: 12px; font-weight: bold; color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hero-look-name.unu { color: #d8aaff; text-shadow: 0 0 12px rgba(199,139,255,.5); }
.hero-chips {
  display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; margin-top: 5px;
}
.hero-chips .chip, .net-near .chip {
  font-size: 9px; padding: 2px 7px; border-radius: 999px;
  background: rgba(0,0,0,.3); border: 1px solid rgba(255,255,255,.2); color: #cfe6ff;
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hero-chips .chip.body { background: rgba(44,127,192,.34); }
.hero-chips .chip.pose { background: rgba(63,143,69,.32); }
.hero-chips .chip.unusual {
  background: rgba(139,63,214,.44); border-color: rgba(199,139,255,.6); color: #f0e2ff;
}

/* ==========================================================================
   PHONE ORDERING
   Three pages want a different vertical order on a phone from the one the
   three-column desktop layout gives them.  Rather than duplicate the markup,
   the columns become `display: contents` at phone width so every panel is a
   direct child of the row and can be ordered on its own.
   ========================================================================== */
@media (max-width: 860px) {
  /* Two inherited values have to go for the stacked layout to behave.
     `.row` aligns to flex-start, which along a column axis means every panel
     shrinks to its own content -- that is what left Site statistics as a
     half-width box.  And `.row` wraps, which in a column container means
     wrapping into *columns*: the panels then get stretched to fill a wrap
     line, which is what blew the friends panel up to four times its content.
     Stacked, they want full width and one single column. */
  .profile-row, .landing-row {
    display: flex; flex-direction: column; flex-wrap: nowrap;
    align-items: stretch; gap: 0;
  }
  .profile-row > .col, .profile-row > .col-side, .profile-row > .col-narrow,
  .landing-row > .col, .landing-row > .col-side { display: contents; }

  /* Profile: who they are, what they chose to show off, then the numbers. */
  .profile-row .p-character { order: 1; }
  .profile-row .p-bio       { order: 2; }
  .profile-row .p-pinned    { order: 3; }
  .profile-row .p-badges    { order: 4; }
  .profile-row .p-stats     { order: 5; }
  .profile-row .p-items     { order: 6; }
  .profile-row .p-friends   { order: 7; }
  .profile-row .p-fav       { order: 8; }
  .profile-row .p-wall      { order: 10; }

  /* Avatar editor: the character, then the build, then the things you put on
     it -- the item picker and the hotbar -- and the colour swatches last.
     Six colour groups is a long scroll to push past on a phone before
     reaching the wardrobe, and the wardrobe is what people came for.  The
     panels are in that order in the markup now, so these only pin it. */
  .avatar-row {
    display: flex; flex-direction: column; flex-wrap: nowrap;
    align-items: stretch; gap: 0;
  }
  .avatar-row > .col, .avatar-row > .col-side { display: contents; }
  .avatar-row .av-preview { order: 1; }
  .avatar-row .av-build   { order: 2; }
  .avatar-row .av-items   { order: 3; }
  .avatar-row .av-hotbar  { order: 4; }
  .avatar-row .av-colors  { order: 5; }

  /* Welcome page: the pitch, then the size of the place, then the detail. */
  .landing-row .l-stats   { order: 1; }
  .landing-row .l-worlds  { order: 2; }
  .landing-row .l-how     { order: 3; }
  .landing-row .l-newest  { order: 4; }

  /* Signed-in home.  The three columns stop being columns so that every
     panel on the page can be ordered against every other one -- the same
     display:contents trick as .landing-row and .avatar-row above.  Ordering
     only within the sidebar would leave "Coming up" stranded at the very
     bottom behind the activity feed, which is a long way
     to scroll for the one panel that is about what happens next.

     So the phone gets: who you are, what is coming up, your inbox, your
     friends, the worlds, then the activity feed -- and "Online now", which is a
     glance rather than a destination, goes to the end where "Coming up"
     used to sit. */
  /* align-items on .row is flex-start, which in a column means the cross
     axis is horizontal -- so without stretch every panel shrinks to the
     width of its own text.  The gap goes too: each panel already carries
     its own 12px below it, and .row's would double every gap. */
  .home-row {
    flex-direction: column; flex-wrap: nowrap;
    align-items: stretch; gap: 0;
  }
  .home-row > .col-side,
  .home-row > .col,
  .home-row > .col-narrow { display: contents; }
  .home-row .h-me       { order: 1; }
  .home-row .h-requests { order: 2; }
  .home-row .h-soon     { order: 3; }
  .home-row .h-messages { order: 4; }
  .home-row .h-friends  { order: 5; }
  .home-row .h-jump     { order: 6; }
  .home-row .h-activity { order: 9; }
  .home-row .h-online   { order: 10; }
  /* Every panel carries its own 12px, so the stack needs no gap of its own. */
  .home-row .h-messages {
    display: flex; align-items: center; justify-content: center; gap: 6px;
    margin-bottom: 12px;
  }

  /* The character goes first on a phone.  The pitch is worth reading, but a
     screen of it above the fold buries the thing a visitor actually came to
     look at, and the stage is the one part of this page that sells itself. */
  .hero-inner { grid-template-columns: minmax(0, 1fr); padding: 18px 14px 16px; gap: 16px; }
  .hero-stage { order: 1; }
  .hero-copy  { order: 2; }
  .hero-copy h1 { font-size: 27px; }
  .hero-lede { font-size: 12px; }
  .hero-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* A phone stage is wide and short, and the vertical field of view is what
     sizes the character -- so a squarer box is what makes it read big enough
     to be the first thing on the page. */
  .avatar-view.hero-avatar { height: 292px; }
  .hero-cta .btn { flex: 1 1 160px; text-align: center; }
}

@media (max-width: 480px) {
  .hero-copy h1 { font-size: 23px; }
  .avatar-view.hero-avatar { height: 274px; }
}

/* ==========================================================================
   FLOATING MESSENGER -- the two screens
   The bubble carries a conversation list and a direct-message view on one
   track.  Opening a conversation slides across instead of navigating, and
   Back slides straight home, so writing a note never costs the page you were
   reading.  It is the same two screens on a phone, just wider.
   ========================================================================== */
.dock-head .dock-title { display: flex; align-items: center; gap: 6px; min-width: 0; }
.dock-head .dock-back {
  display: none; width: 20px; height: 20px; padding: 0; flex: 0 0 auto;
  border-radius: 4px; cursor: pointer; font-family: inherit; font-size: 13px;
  line-height: 1; color: #eaf4ff; background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.28);
}
.dock-head .dock-back.on { display: block; }
.dock-head .dock-back:hover { background: rgba(255,255,255,.28); }
.dock-head #dock-heading {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dock-headlinks { font-size: 10px; font-weight: normal; flex: 0 0 auto; }
.dock-headlinks a { color: #e6f2ff; }

.dock-screens {
  display: flex; width: 200%; flex: 1 1 auto; min-height: 0;
  transition: transform .3s cubic-bezier(.35, .85, .35, 1);
}
.dock-screens.at-dm { transform: translateX(-50%); }
.dock-screen {
  width: 50%; flex: 0 0 50%; display: flex; flex-direction: column; min-height: 0;
}
.dock-dm { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.dock-to {
  display: flex; align-items: center; gap: 7px; padding: 7px 9px;
  border-bottom: 1px solid var(--line-soft); background: var(--panel-alt);
}
.dock-to.hidden { display: none; }
.dock-to label { font-size: 10px; color: var(--ink-soft); flex: 0 0 auto; margin: 0; }
.dock-to .ac-wrap { flex: 1 1 auto; min-width: 0; }
.dock-to input { width: 100%; }
.dock-thread {
  flex: 1 1 auto; min-height: 120px; overflow-y: auto; padding: 9px;
  display: flex; flex-direction: column; gap: 6px;
}
.dock-thread .bubble { max-width: 86%; }
.dock-compose { display: flex; gap: 6px; align-items: flex-end; }
.dock-compose textarea {
  flex: 1 1 auto; min-width: 0; resize: none; font-size: 11px; line-height: 1.4;
}
.dock-compose .btn { flex: 0 0 auto; }
.dock-blank {
  padding: 22px 14px; text-align: center; color: var(--ink-soft); font-size: 11px;
}
.dock-blank b { display: block; color: var(--ink-strong); margin-bottom: 3px; }

/* ==========================================================================
   TYPE-AHEAD
   One list, shared by the compose page and the messenger, anchored to the
   field itself so a phone keyboard sliding the page around cannot strand it.
   ========================================================================== */
.ac-wrap { position: relative; }
.ac-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 2px); z-index: 40;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 4px; box-shadow: 0 8px 22px var(--shadow-lift);
  max-height: 46vh; overflow-y: auto;
}
.ac-row {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 6px 8px; background: none; border: 0; cursor: pointer;
  font-family: inherit; font-size: 11px; color: var(--ink);
  border-bottom: 1px solid var(--line-dot);
}
.ac-row:last-child { border-bottom: 0; }
.ac-row:hover, .ac-row.on { background: var(--info-bg); }
.ac-face {
  width: 26px; height: 26px; flex: 0 0 26px; border-radius: 3px;
  background: var(--preview-bg); border: 1px solid var(--line-soft);
}
.ac-name {
  flex: 1 1 auto; min-width: 0; font-weight: bold; color: var(--ink-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ac-when { flex: 0 0 auto; font-size: 9px; color: var(--ok-ink); }

.compose-panel { max-width: 640px; }
.compose-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.compose-actions .btn { flex: 0 1 auto; }

/* ==========================================================================
   SWITCHES
   ========================================================================== */
.switch {
  position: relative; width: 42px; height: 22px; flex: 0 0 auto; padding: 0;
  border-radius: 11px; cursor: pointer; border: 1px solid var(--line);
  background: var(--sunken); transition: background .25s ease, border-color .25s ease;
}
.switch i {
  position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--btn); border: 1px solid var(--btn-edge);
  transition: transform .25s cubic-bezier(.5, -0.2, .4, 1.4);
}
.switch[aria-checked="true"] { background: var(--head-green); border-color: var(--head-green-edge); }
.switch[aria-checked="true"] i { transform: translateX(20px); background: #fff; border-color: #fff; }
.switch:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* ==========================================================================
   PINNED ITEMS -- drag and drop
   ========================================================================== */
.pin-targets .pinslot {
  position: relative; flex-direction: column; gap: 3px; overflow: hidden;
  transition: border-color .15s ease, background .15s ease, transform .12s ease;
  touch-action: none;
}
.pin-targets .pinslot .slot-n {
  position: absolute; top: 4px; left: 5px; font-size: 9px; font-weight: bold;
  color: var(--ink-soft); opacity: .75;
}
.pin-targets .pinslot .slot-hint { padding: 0 6px; }
.pin-targets .pinslot.filled {
  border-style: solid; padding: 0; cursor: grab; display: block; aspect-ratio: auto;
}
.pin-targets .pinslot.filled:active { cursor: grabbing; }
.pin-targets .pinslot.filled .thumb-wrap { aspect-ratio: 1 / 1; }
.pin-targets .pinslot.filled .meta { padding: 4px 6px; }
.pin-targets .pinslot .slot-clear {
  position: absolute; top: 3px; right: 3px; z-index: 3; width: 18px; height: 18px;
  padding: 0; line-height: 1; border-radius: 3px; cursor: pointer;
  font-family: inherit; font-size: 13px; color: var(--bad-ink);
  background: var(--panel); border: 1px solid var(--line);
}
.pin-targets .pinslot .slot-clear:hover { background: var(--bad-bg); }
.pin-targets .pinslot.over {
  border-color: var(--gold); background: var(--warn-bg);
  box-shadow: 0 0 0 2px var(--gold); transform: translateY(-2px);
}
.pin-pool { touch-action: none; }
.pin-pool .pick { cursor: grab; }
.pin-pool .pick:active { cursor: grabbing; }
.pin-pool.over { outline: 2px dashed var(--line); outline-offset: 3px; border-radius: 4px; }
.pin-pool .pick.dragging, .pin-targets .pinslot.dragging { opacity: .35; }
body.pin-dragging, body.item-dragging { user-select: none; -webkit-user-select: none; }
/* The ghost that follows the pointer.  Shared, because the gesture is:
   whatever you are dragging -- a pin or a hotbar item -- picks up the same
   tile and drops it the same way. */
.pin-ghost, .drag-ghost {
  position: fixed; top: 0; left: 0; z-index: 1200; pointer-events: none;
  width: 68px; padding: 4px; text-align: center; border-radius: 4px;
  background: var(--panel); border: 1px solid var(--gold);
  box-shadow: 0 8px 20px rgba(0,0,0,.4); opacity: .95;
}
.pin-ghost canvas, .drag-ghost canvas {
  width: 56px; height: 56px; display: block; margin: 0 auto;
}
.pin-ghost span, .drag-ghost span {
  display: block; font-size: 9px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==========================================================================
   THE HOTBAR -- drag and drop
   The five seats are an arrangement, not a set of switches, so setting them
   up is the same drag as the pinned items: pull an item out of the pool into
   a seat, drop one seat on another to swap them, and drag a seat back down
   into the pool to empty it.  Clicking still works exactly as it did.
   ========================================================================== */
/* The tiles themselves claim the gesture, so a drag never turns into a page
   scroll halfway through -- but the gaps around them do not, so a thumb that
   lands between two tiles still scrolls the page. */
.hotbar .hotslot, #usable-pool .pick { touch-action: none; }
.hotslot.filled { cursor: grab; }
.hotslot.filled:active { cursor: grabbing; }
.hotslot.picked { outline: 2px solid var(--focus); outline-offset: 1px; }
.hotslot.over {
  border-color: var(--gold); background: var(--warn-bg);
  box-shadow: 0 0 0 2px var(--gold); transform: translateY(-2px);
}
.hotslot { transition: border-color .15s ease, background .15s ease, transform .12s ease; }
#usable-pool .pick { cursor: grab; }
#usable-pool .pick:active { cursor: grabbing; }
#usable-pool.over { outline: 2px dashed var(--line); outline-offset: 3px; border-radius: 4px; }
#usable-pool .pick.dragging, .hotslot.dragging { opacity: .35; }

/* ==========================================================================
   ADMIN -- the connection map
   A canvas that fills the panel and re-fits itself, with the controls and the
   key floating over it so the graph keeps the whole box.  The aspect ratio is
   the thing that changes between a landscape monitor and a phone held
   upright: tall and narrow gets a taller box, not a letterbox.
   ========================================================================== */
.netgraph {
  position: relative; width: 100%; height: 60vh; min-height: 320px;
  max-height: 720px; overflow: hidden;
  background:
    radial-gradient(circle at 50% 40%, var(--panel-alt), var(--panel) 72%);
  border-bottom: 1px solid var(--line-soft);
}
.netgraph canvas { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; }
.net-empty {
  position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; color: var(--ink-soft); font-size: 11px;
  pointer-events: none;
}
.net-toolbar {
  position: absolute; top: 8px; left: 8px; display: flex; flex-wrap: wrap; gap: 4px;
  z-index: 3;
}
.net-toolbar .btn[aria-pressed="false"] { opacity: .55; }
.net-key {
  position: absolute; top: 8px; right: 8px; z-index: 3; width: 172px;
  display: flex; flex-direction: column; gap: 3px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 5px;
  padding: 8px 9px; font-size: 10px; box-shadow: 0 4px 14px var(--shadow);
}
.net-key b { font-size: 10px; color: var(--ink-strong); }
.net-key span { display: flex; align-items: center; gap: 6px; color: var(--ink-soft); }
.net-key i { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.net-key u { width: 16px; height: 0; flex: 0 0 auto; border-top: 2px solid; }
.net-key u.e-friend  { border-color: var(--link); border-top-style: solid; }
.net-key u.e-pending { border-color: #f0b429; border-top-style: dashed; }
.net-key u.e-follow  { border-color: var(--ink-soft); border-top-style: dotted; }
.net-key hr { margin: 4px 0; }
.net-stats {
  position: absolute; left: 8px; bottom: 8px; z-index: 3; display: flex;
  flex-wrap: wrap; gap: 4px; max-width: calc(100% - 16px);
}
.net-stats span {
  background: var(--panel); border: 1px solid var(--line-soft); border-radius: 999px;
  padding: 2px 9px; font-size: 10px; color: var(--ink-soft);
}
.net-stats b { color: var(--ink-strong); }
.net-card {
  position: absolute; right: 8px; bottom: 8px; z-index: 4; width: 232px;
  max-width: calc(100% - 16px);
  background: var(--panel); border: 1px solid var(--line); border-radius: 5px;
  padding: 9px 10px; font-size: 11px; box-shadow: 0 6px 18px var(--shadow-lift);
}
.net-card-close {
  position: absolute; top: 4px; right: 5px; width: 18px; height: 18px; padding: 0;
  line-height: 1; cursor: pointer; font-family: inherit; font-size: 13px;
  color: var(--ink-soft); background: none; border: 0;
}
.net-near { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 6px; }
.net-near .chip {
  background: var(--panel-alt); border: 1px solid var(--line-soft);
  color: var(--ink); cursor: pointer; font-family: inherit;
}
.net-near .chip:hover { border-color: var(--link); color: var(--link-hover); }
.net-near .chip.more { cursor: default; opacity: .7; }
.net-card-links { display: flex; gap: 5px; margin-top: 8px; }

/* The phone-only fold-out button, and the map when it is folded in under the
   overview rather than standing on its own tab. */
.btn.netfold { width: 100%; margin-top: 10px; text-align: center; }
[data-admin-panel].admin-inline { margin-top: 12px; }
[data-admin-panel].admin-inline .netgraph { height: 58vh; min-height: 320px; }

@media (max-width: 860px) {
  /* Narrow enough that the floating panels have to take turns down the
     screen instead of sitting in opposite corners: toolbar, then the running
     totals, then the graph itself, with the key laid out as a strip along the
     bottom and any selected node's card just above it. */
  .netgraph { height: 66vh; min-height: 380px; }
  .net-toolbar { right: 8px; }
  .net-stats { top: 46px; bottom: auto; left: 8px; right: 8px; max-width: none; }
  /* The key starts closed on a phone so the graph keeps the whole box, and
     opens as a strip right under the totals rather than in a corner there is
     no room for. */
  .net-key {
    top: 78px; bottom: auto; left: 8px; right: 8px; width: auto;
    flex-direction: row; flex-wrap: wrap; align-items: center;
    gap: 3px 10px; font-size: 9px; padding: 6px 8px;
  }
  .net-key b { flex-basis: 100%; }
  .net-key hr, .net-key .tiny { display: none; }
  .net-card { left: 8px; right: 8px; width: auto; bottom: 8px; }
}
@media (orientation: portrait) and (max-width: 860px) {
  /* Held upright there is height to spare and none to waste sideways. */
  .netgraph { height: 62vh; }
}

/* ==========================================================================
   ODDS AND ENDS
   ========================================================================== */
.finish-avatar { margin-top: 10px; }

/* ==========================================================================
   BOTS ZONE -- the admin dashboard's control room for synthetic players.
   Drawn by static/js/ui/bots_admin.js.  Everything leans on the site's own
   palette variables, so it follows the light and dark themes like the rest
   of the chrome; the few colours of its own are the presence states.
   ========================================================================== */
:root {
  --bz-online: #37c26a;
  --bz-playing: #f0b429;
  --bz-waking: #2fb3c4;
  --bz-offline: #9aa3ae;
  --bz-bot: #9a5fe0;
  --bz-bot-soft: rgba(154, 95, 224, .13);
  --bz-target: #5a7fa8;
}
:root[data-theme="dark"] { --bz-bot-soft: rgba(179, 124, 242, .16); --bz-target: #8fb2d8; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --bz-bot-soft: rgba(179, 124, 242, .16); --bz-target: #8fb2d8; }
}
.pill.bot { background: var(--bz-bot-soft); border-color: var(--bz-bot); color: var(--bz-bot); }
.net-key i.k-bot { background: #b37cf2; box-shadow: 0 0 0 2px rgba(179,124,242,.35); }
.net-key small { font-weight: normal; opacity: .75; }
.tabs a.bz-tab { display: inline-flex; align-items: center; gap: 5px; }
.bz-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--bz-offline); }
.bz-tab-dot.on { background: var(--bz-bot); box-shadow: 0 0 0 3px var(--bz-bot-soft); }

.bz-hero .panel-body { display: flex; flex-direction: column; gap: 10px; }
.bz-hero-row { display: flex; gap: 14px; align-items: stretch; flex-wrap: wrap; }
.bz-master { display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  border: 1px solid var(--line-soft); border-radius: 6px; background: var(--panel-alt);
  flex: 0 0 250px; box-sizing: border-box; }
.bz-master b { font-size: 13px; }
.switch.big { width: 54px; height: 28px; border-radius: 14px; }
.switch.big i { width: 22px; height: 22px; }
.switch.big[aria-checked="true"] i { transform: translateX(26px); }
.switch.bot[aria-checked="true"] { background: linear-gradient(#b784ee, #8a4fd4); border-color: #6b35ad; }
.bz-kpis { flex: 1 1 420px; display: grid; gap: 6px;
  grid-template-columns: repeat(4, minmax(0, 1fr)); }
.bz-kpi { margin: 0; border: 1px solid var(--line-soft); border-radius: 6px; padding: 6px 9px;
  background: var(--panel-alt); position: relative; overflow: hidden; min-width: 0; }
.bz-kpi::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--kpi, var(--line)); }
.bz-kpi dt { font-size: 9px; text-transform: uppercase; letter-spacing: .4px; color: var(--ink-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bz-kpi dd { margin: 2px 0 0; font-size: 17px; font-weight: bold; color: var(--ink-strong);
  font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bz-kpi small { display: block; font-size: 9px; color: var(--ink-soft); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.bz-chart-wrap { position: relative; }
.bz-chart { width: 100%; height: 120px; display: block; border: 1px solid var(--line-soft);
  border-radius: 6px; background: var(--sunken); }
.bz-chart.tall { height: 170px; }
.bz-chart-key { position: absolute; right: 8px; top: 6px; display: flex; gap: 10px;
  color: var(--ink-soft); background: var(--panel); padding: 2px 7px; border-radius: 9px;
  border: 1px solid var(--line-soft); }
.bz-chart-key span { display: inline-flex; align-items: center; gap: 4px; }
.bz-chart-key i { width: 10px; height: 3px; border-radius: 2px; display: inline-block; }
.bz-chart-key i.dash { background: repeating-linear-gradient(90deg, var(--bz-target) 0 3px, transparent 3px 5px); }

.bz-layout { display: flex; gap: 12px; align-items: flex-start; }
.bz-nav { flex: 0 0 196px; position: sticky; top: 10px; display: flex; flex-direction: column;
  gap: 3px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px; box-shadow: 0 1px 2px var(--shadow); }
.bz-nav button { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  font: inherit; font-size: 11px; font-weight: bold; color: var(--ink-label); background: transparent;
  border: 1px solid transparent; border-radius: 4px; padding: 6px 8px; cursor: pointer; }
.bz-nav button:hover { background: var(--panel-alt); border-color: var(--line-soft); }
.bz-nav button.on { background: var(--bz-bot-soft); border-color: var(--bz-bot); color: var(--ink-strong); }
.bz-nav .ico { width: 18px; text-align: center; font-size: 13px; flex: 0 0 auto; }
.bz-nav .lbl { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bz-nav .state { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: transparent; }
.bz-nav .state.on { background: var(--bz-online); }
.bz-nav .state.off { background: var(--bz-offline); }
.bz-main { flex: 1 1 auto; min-width: 0; }
.bz-main .panel-head .head-links b { color: #fff; }
.bz-intro { color: var(--ink-soft); margin: 0 0 10px; }

/* feature switch cards: every feature's on/off sits at the top of its own tab */
.bz-feature { display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  border: 1px solid var(--line-soft); border-left: 4px solid var(--bz-offline);
  border-radius: 6px; background: var(--panel-alt); margin-bottom: 8px; }
.bz-feature.on { border-left-color: var(--bz-online); }
.bz-feature b { display: block; color: var(--ink-strong); font-size: 12px; }
.bz-feature .tiny { color: var(--ink-soft); }
.bz-feature .grow { flex: 1 1 auto; min-width: 0; }
.bz-feature .state-word { font-size: 10px; font-weight: bold; text-transform: uppercase;
  letter-spacing: .5px; color: var(--bz-offline); }
.bz-feature.on .state-word { color: var(--ok-ink); }

/* settings forms */
.bz-form { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 8px; }
.bz-field { border: 1px solid var(--line-soft); border-radius: 6px; padding: 8px 10px;
  background: var(--panel); display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.bz-field.wide { grid-column: 1 / -1; }
.bz-field.dirty { border-color: var(--bz-bot); box-shadow: 0 0 0 2px var(--bz-bot-soft); }
.bz-field-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.bz-field-head label { margin: 0; font-size: 11px; }
.bz-field .help { font-size: 10px; color: var(--ink-soft); line-height: 1.45; }
.bz-scope { font-size: 9px; font-weight: bold; padding: 1px 6px; border-radius: 8px;
  text-transform: uppercase; letter-spacing: .3px; white-space: nowrap; border: 1px solid; }
.bz-scope.universal { color: var(--info-ink); border-color: var(--info-edge); background: var(--info-bg); }
.bz-scope.per-bot { color: var(--bz-bot); border-color: var(--bz-bot); background: var(--bz-bot-soft); }
.bz-scope.base { color: var(--warn-ink); border-color: var(--warn-edge); background: var(--warn-bg); }
.panel-head .bz-scope { box-shadow: 0 1px 0 rgba(0,0,0,.15); }
.panel-head .bz-scope.per-bot { background: #f4ecfe; color: #6b35ad; border-color: #d9c2f5; }
.bz-ctl { display: flex; align-items: center; gap: 6px; }
.bz-ctl input[type=number] { width: 88px; }
.bz-ctl input[type=range] { flex: 1 1 auto; min-width: 60px; accent-color: var(--bz-bot); }
.bz-ctl input[type=text], .bz-ctl input[type=password], .bz-ctl input[type=date],
.bz-ctl select { flex: 1 1 auto; min-width: 0; }
.bz-ctl .unit { color: var(--ink-soft); font-size: 10px; white-space: nowrap; }
.bz-ctl .sep { color: var(--ink-soft); }
.bz-band { height: 6px; border-radius: 3px; background: var(--sunken); position: relative;
  border: 1px solid var(--line-soft); }
.bz-band i { position: absolute; top: -1px; bottom: -1px; border-radius: 3px;
  background: linear-gradient(90deg, #b784ee, #8a4fd4); }
.bz-clock { height: 12px; border-radius: 3px; position: relative; overflow: hidden;
  background: linear-gradient(90deg, #1c2a44 0%, #3b5f8f 25%, #9cc8ee 50%, #3b5f8f 75%, #1c2a44 100%);
  border: 1px solid var(--line-soft); }
.bz-clock i { position: absolute; top: 0; bottom: 0; background: rgba(240,180,41,.75); }
.bz-field textarea { font-family: Consolas, Menlo, monospace; font-size: 11px; }
.bz-savebar { position: sticky; bottom: 0; z-index: 5; display: flex; gap: 8px; align-items: center;
  justify-content: flex-end; padding: 8px 10px; margin-top: 8px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 -2px 10px var(--shadow); }
.bz-savebar .grow { flex: 1 1 auto; font-size: 10px; color: var(--ink-soft); }
.bz-savebar.dirty { border-color: var(--bz-bot); }
.bz-weights { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 4px 12px; }
.bz-weights h4 { grid-column: 1 / -1; margin: 8px 0 2px; font-size: 10px; text-transform: uppercase;
  letter-spacing: .5px; color: var(--ink-label); border-bottom: 1px dotted var(--line-dot); padding-bottom: 2px; }
.bz-weight { display: grid; grid-template-columns: minmax(0, 1fr) 90px 36px; gap: 6px; align-items: center; }
.bz-weight .name { font-size: 11px; font-weight: bold; color: var(--ink-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bz-weight .name small { display: block; font-weight: normal; color: var(--ink-soft); font-size: 9px; }
.bz-weight input[type=range] { width: 100%; accent-color: var(--bz-bot); }
.bz-weight output { font-size: 10px; text-align: right; font-variant-numeric: tabular-nums; }
.bz-weight .share { grid-column: 1 / -1; height: 3px; background: var(--sunken); border-radius: 2px; }
.bz-weight .share i { display: block; height: 100%; background: var(--bz-bot); border-radius: 2px; }

/* the bot table */
.bz-filters { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
.bz-filters input[type=search] { flex: 1 1 160px; min-width: 0; }
.bz-filters select { flex: 0 1 150px; min-width: 0; }
.bz-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 4px; overflow: hidden; }
.bz-seg button { font: inherit; font-size: 10px; font-weight: bold; padding: 4px 9px; border: 0;
  background: var(--panel-alt); color: var(--ink-label); cursor: pointer; border-right: 1px solid var(--line-soft); }
.bz-seg button:last-child { border-right: 0; }
.bz-seg button.on { background: var(--bz-bot); color: #fff; }
table.bz-table { width: 100%; border-collapse: collapse; }
table.bz-table th { background: var(--panel-alt); text-align: left; padding: 5px 8px; font-size: 9px;
  text-transform: uppercase; letter-spacing: .4px; color: var(--ink-label); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 1; }
table.bz-table td { padding: 6px 8px; border-bottom: 1px dotted var(--line-dot); vertical-align: top; }
table.bz-table tr { cursor: pointer; }
table.bz-table tr:hover td { background: var(--bz-bot-soft); }
.bz-who { display: flex; gap: 8px; align-items: flex-start; min-width: 170px; }
.bz-avatar { width: 28px; height: 28px; border-radius: 6px; flex: 0 0 auto; display: flex;
  align-items: center; justify-content: center; color: #fff; font-weight: bold; font-size: 12px;
  text-shadow: 0 1px 0 rgba(0,0,0,.3); }
.bz-who b { color: var(--ink-strong); }
.bz-tags { display: flex; flex-wrap: wrap; gap: 2px; margin-top: 3px; }
.bz-tag { font-size: 9px; padding: 0 5px; border-radius: 7px; background: var(--sunken);
  border: 1px solid var(--line-soft); color: var(--ink-label); white-space: nowrap; }
.bz-tag.g-schedule { border-color: #7fb1e0; } .bz-tag.g-skill { border-color: #e0a07f; }
.bz-tag.g-focus { border-color: #8fd08f; } .bz-tag.g-social { border-color: #e08fbf; }
.bz-tag.g-voice { border-color: #c0b36a; } .bz-tag.g-world { border-color: #f0b429; }
.bz-tag.g-custom { border-color: var(--bz-bot); }
.bz-state { display: inline-flex; align-items: center; gap: 5px; font-weight: bold; font-size: 10px;
  white-space: nowrap; }
.bz-state i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.bz-state.offline i { background: var(--bz-offline); }
.bz-state.waking i { background: var(--bz-waking); }
.bz-state.online i { background: var(--bz-online); animation: pulse 2.4s ease-in-out infinite; }
.bz-state.playing i { background: var(--bz-playing); animation: pulse 1.4s ease-in-out infinite; }
.bz-sub { display: block; font-size: 9px; color: var(--ink-soft); font-weight: normal; white-space: nowrap; }
.bz-quote { font-size: 10px; color: var(--ink); max-width: 260px; overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.bz-num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.bz-meter { height: 4px; border-radius: 2px; background: var(--sunken); margin-top: 3px; width: 60px; }
.bz-meter i { display: block; height: 100%; border-radius: 2px; background: var(--bz-bot); }
.bz-pager { display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 8px 0 0; font-size: 10px; color: var(--ink-soft); }
.bz-worlds { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 6px;
  margin-bottom: 10px; }
.bz-world { border: 1px solid var(--line-soft); border-radius: 6px; padding: 7px 9px; background: var(--panel-alt);
  display: flex; flex-direction: column; gap: 4px; text-align: left; font: inherit; color: inherit;
  cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.bz-world { min-width: 0; }
.bz-world .tiny { flex-wrap: wrap; }
.bz-world:hover { border-color: var(--bz-bot); }
.bz-world.on { border-color: var(--bz-bot); box-shadow: 0 0 0 2px var(--bz-bot-soft); }
.bz-world-head { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; }
.bz-world b { color: var(--ink-strong); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bz-world-count { font-size: 16px; font-weight: bold; color: var(--ink-strong); font-variant-numeric: tabular-nums; }
.bz-world .bz-split { height: 8px; border-radius: 4px; overflow: hidden; display: flex;
  background: var(--sunken); }
.bz-world .bz-split i { display: block; height: 100%; }
.bz-world .bz-split i.p { background: var(--link); }
.bz-world .bz-split i.l { background: var(--bz-playing); }
.bz-world .bz-split i.s { background: var(--bz-bot); opacity: .7; }
.bz-world .tiny { display: flex; justify-content: space-between; gap: 4px; }
.bz-world i.k { display: inline-block; width: 7px; height: 7px; border-radius: 2px; margin-right: 3px; vertical-align: 0; }
.bz-world i.k.p { background: var(--link); }
.bz-world i.k.l { background: var(--bz-playing); }
.bz-world i.k.s { background: var(--bz-bot); opacity: .7; }
.bz-results { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 0 0 6px; }
.bz-results select { margin-left: 4px; }

/* the detail drawer */
.bz-drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 100vw); z-index: 950;
  background: var(--panel); border-left: 1px solid var(--line); box-shadow: -8px 0 30px var(--shadow-lift);
  display: flex; flex-direction: column; animation: bz-slide .22s ease-out; }
@keyframes bz-slide { from { transform: translateX(40px); opacity: 0; } to { transform: none; opacity: 1; } }
.bz-drawer-head { display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 9px 12px; background: var(--head-purple); color: #fff; }
.bz-drawer-head b { font-size: 13px; text-shadow: 0 1px 0 rgba(0,0,0,.3); }
.bz-drawer-body { overflow: auto; padding: 12px; flex: 1 1 auto; }
.bz-drawer section { margin-bottom: 14px; }
.bz-drawer h4 { margin: 0 0 6px; font-size: 10px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--ink-label); border-bottom: 1px solid var(--line-soft); padding-bottom: 3px; }
.bz-traits { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px 12px; }
.bz-trait { display: grid; grid-template-columns: 76px minmax(0, 1fr) 30px; gap: 5px; align-items: center;
  font-size: 10px; }
.bz-trait .bar { height: 5px; border-radius: 3px; background: var(--sunken); }
.bz-trait .bar i { display: block; height: 100%; border-radius: 3px; background: var(--bz-bot); }
.bz-list { display: flex; flex-direction: column; gap: 4px; }
.bz-list .row { padding: 5px 7px; border: 1px solid var(--line-soft); border-radius: 5px;
  background: var(--panel-alt); font-size: 11px; }
.bz-list .row .tiny { color: var(--ink-soft); }
.bz-logs { display: flex; flex-wrap: wrap; gap: 4px; }
.bz-logs button { font: inherit; font-size: 10px; padding: 3px 7px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel-alt); color: var(--ink-label); }
.bz-logs button.on { background: var(--bz-bot); color: #fff; border-color: var(--bz-bot); }
.bz-logview { margin-top: 6px; max-height: 320px; overflow: auto; border: 1px solid var(--line-soft);
  border-radius: 6px; background: var(--sunken); padding: 6px; font-size: 11px; }
.bz-logview .line { padding: 3px 4px; border-bottom: 1px dotted var(--line-dot); }
.bz-logview .line.me { background: var(--bz-bot-soft); }
.bz-logview .line b { color: var(--ink-strong); }
.bz-logview .line .t { float: right; font-size: 9px; color: var(--ink-soft); }
.bz-actions { display: flex; flex-wrap: wrap; gap: 5px; }
.bz-profiles { margin: 0 0 10px; padding: 8px 10px; border: 1px solid var(--line-soft);
  border-radius: 6px; background: var(--panel-alt); }
.bz-profiles-head { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; margin-bottom: 6px; }
.bz-profiles-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.bz-profiles-row select { min-width: 180px; max-width: 100%; }
.bz-profiles-row input { flex: 1 1 180px; min-width: 0; }
.bz-profiles-sep { width: 1px; align-self: stretch; background: var(--line-soft); margin: 0 4px; }
#bz-profile-about { margin-top: 6px; overflow-wrap: anywhere; }
.bz-kv { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 3px 8px; font-size: 11px; }
.bz-kv dt { color: var(--ink-soft); }
.bz-kv dd { margin: 0; font-weight: bold; color: var(--ink-strong); overflow-wrap: anywhere; }

/* creation, jobs, the model */
.bz-generate { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.bz-generate input[type=number] { width: 110px; font-size: 14px; font-weight: bold; }
.bz-job { border: 1px solid var(--line-soft); border-radius: 6px; padding: 8px 10px; margin-top: 8px;
  background: var(--panel-alt); }
.bz-job .progress { margin: 6px 0; height: 14px; }
.bz-job .progress i { background: linear-gradient(#c79bf2, #8a4fd4); transition: width .5s; }
.bz-joblog { max-height: 150px; overflow: auto; font-family: Consolas, Menlo, monospace; font-size: 10px;
  color: var(--ink-soft); margin-top: 6px; }
.bz-names { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.bz-names span { font-size: 11px; padding: 2px 8px; border-radius: 10px; background: var(--bz-bot-soft);
  border: 1px solid var(--bz-bot); color: var(--ink-strong); }
.bz-danger { border: 1px solid var(--bad-edge); background: var(--bad-bg); border-radius: 6px; padding: 10px; }
.bz-danger b { color: var(--bad-ink); }
.bz-status { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; }
.bz-status .cell { border: 1px solid var(--line-soft); border-radius: 6px; padding: 6px 8px; background: var(--panel-alt); }
.bz-status .cell dt { font-size: 9px; text-transform: uppercase; letter-spacing: .4px; color: var(--ink-soft); }
.bz-status .cell dd { margin: 2px 0 0; font-weight: bold; color: var(--ink-strong); overflow-wrap: anywhere; }
.bz-ok { color: var(--ok-ink); } .bz-bad { color: var(--bad-ink); }
.bz-code { font-family: Consolas, Menlo, monospace; font-size: 11px; white-space: pre-wrap;
  background: var(--sunken); border: 1px solid var(--line-soft); border-radius: 6px; padding: 8px;
  max-height: 55vh; overflow: auto; }
.bz-feed { display: flex; flex-direction: column; gap: 3px; max-height: 260px; overflow: auto; }
.bz-feed .row { display: block; font-size: 11px; padding: 4px 6px; border-radius: 4px; background: var(--panel-alt);
  border: 1px solid var(--line-soft); }
.bz-feed .row .k { font-size: 9px; font-weight: bold; text-transform: uppercase; color: var(--bz-bot); margin-right: 5px; }
.bz-feed .row .t { float: right; font-size: 9px; color: var(--ink-soft); }
.bz-grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 10px; }

@media (max-width: 860px) {
  .bz-layout { flex-direction: column; align-items: stretch; }
  .bz-nav { position: static; flex: none; width: 100%; flex-direction: row; overflow-x: auto;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .bz-nav::-webkit-scrollbar { display: none; }
  .bz-nav button { width: auto; flex: 0 0 auto; }
  .bz-nav button.child { margin-left: 0; width: auto; }
  .bz-form { grid-template-columns: minmax(0, 1fr); }
  .bz-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); flex-basis: 100%; }
  .bz-master { flex: 1 1 100%; }
  .bz-drawer { width: 100vw; }
  table.bz-table .hide-sm { display: none; }
  .bz-traits { grid-template-columns: minmax(0, 1fr); }
  .bz-worlds { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bz-rounds, .bz-groups { grid-template-columns: minmax(0, 1fr); }
  .bz-round { grid-template-columns: 30px 44px minmax(0, 1fr) minmax(0, 1fr); }
  .bz-round .bz-meter { display: none; }
  .bz-main .panel-head .head-links { display: none; }
  .bz-filters .bz-seg { order: 3; width: 100%; }
  .bz-filters .bz-seg button { flex: 1 1 auto; }
  .bz-filters select { flex: 1 1 120px; }
}

/* persona catalogue */
.bz-lead { margin: 0 0 10px; font-size: 11px; line-height: 1.55; color: var(--ink); max-width: 760px; }
.bz-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 8px; }
.bz-group { border: 1px solid var(--line-soft); border-radius: 6px; padding: 7px 9px; background: var(--panel-alt); }
.bz-group-head { display: flex; justify-content: space-between; align-items: center; gap: 6px; }
.bz-group-head b { text-transform: capitalize; color: var(--ink-strong); }
.bz-group .bz-tags { margin-top: 5px; gap: 3px; }
.bz-group .bz-tag { font-size: 10px; padding: 1px 6px; cursor: help; }
.bz-group .bz-tag small { opacity: .7; font-size: 9px; }

/* rounds right now */
.bz-h { margin: 12px 0 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .4px; color: var(--ink-soft); }
.bz-rounds { display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: 8px; }
.bz-round-world { border: 1px solid var(--line-soft); border-radius: 6px; padding: 7px 9px; background: var(--panel-alt); }
.bz-round-world > b { display: block; margin-bottom: 4px; color: var(--ink-strong); }
.bz-round { display: grid; grid-template-columns: 34px 48px minmax(0, 1fr) 54px minmax(0, 1fr); gap: 6px;
  align-items: center; padding: 3px 0; border-top: 1px dotted var(--line-soft); font-size: 10px; }
.bz-round-id { font-weight: bold; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.bz-round-state { font-size: 9px; font-weight: bold; text-transform: uppercase; text-align: center;
  border-radius: 7px; padding: 0 4px; }
.bz-round.live .bz-round-state { background: rgba(55,194,106,.16); color: #1f8a47; }
.bz-round.asleep .bz-round-state { background: var(--bz-bot-soft); color: var(--bz-bot); }
.bz-round-who, .bz-round-score { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bz-round-score { text-align: right; font-variant-numeric: tabular-nums; }
.bz-round .bz-meter { margin: 0; width: auto; }

/* social feeds */
.bz-status .cell { margin: 0; }
.bz-status.compact { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
.bz-feed-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 5px; }
.bz-feed.tall { max-height: 520px; }
.bz-feed .row .say { margin-top: 2px; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.bz-feed .row .k.request { color: var(--bz-target); }
.bz-feed .row .k.friends { color: #1f8a47; }
.bz-feed .row .k.post { color: #b0761a; }
.bz-name { font-weight: bold; }
.bz-name.bot { color: var(--bz-bot); }
.pill.tiny-pill { font-size: 8px; padding: 0 4px; vertical-align: 1px; }

/* speech event chances and live modifier tables */
.bz-chances { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 4px 14px; }
.bz-chances h4 { grid-column: 1 / -1; margin: 10px 0 2px; font-size: 10px; text-transform: uppercase;
  letter-spacing: .4px; color: var(--ink-soft); border-bottom: 1px dotted var(--line-soft); padding-bottom: 2px; }
.bz-chance { display: grid; grid-template-columns: minmax(0, 1fr) 110px 40px; gap: 8px; align-items: center;
  padding: 3px 0; }
.bz-chance .name { font-size: 11px; font-weight: bold; color: var(--ink-strong); min-width: 0; }
.bz-chance .name small { display: block; font-weight: normal; color: var(--ink-soft); font-size: 9px; }
.bz-chance output { font-size: 11px; font-weight: bold; text-align: right; font-variant-numeric: tabular-nums;
  color: var(--bz-bot); }
.bz-chance.off .name, .bz-chance.off output { color: var(--ink-soft); font-weight: normal; }
.bz-chance input[type=range] { width: 100%; accent-color: var(--bz-bot); }
/* profile setting shares: options that always add up to 100% */
.bz-shares { display: flex; flex-direction: column; gap: 2px; }
.bz-shares-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; margin: 2px 0 4px;
  background: var(--panel-alt); border: 1px solid var(--line-soft); }
.bz-shares-bar i { display: block; height: 100%; transition: width .15s; }
.bz-shares .s0 { background: var(--bz-online); }
.bz-shares .s1 { background: var(--bz-target); }
.bz-shares .s2 { background: var(--bz-offline); }
.bz-share { display: grid; grid-template-columns: minmax(0, 1fr) 120px 40px; gap: 8px; align-items: center; }
.bz-share .name { font-size: 11px; color: var(--ink-strong); min-width: 0; }
.bz-share .dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 5px;
  vertical-align: 0; }
.bz-share output { font-size: 11px; font-weight: bold; text-align: right; font-variant-numeric: tabular-nums;
  color: var(--bz-bot); }
.bz-share input[type=range] { width: 100%; accent-color: var(--bz-bot); }
.bz-nav button.child { margin-left: 14px; width: calc(100% - 14px); font-size: 11px; padding-top: 4px;
  padding-bottom: 4px; }
.bz-family { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
#bz-llm-recent .bz-why { color: var(--ink-soft); font-size: 10px; }
.bz-warn { color: var(--warn-ink); font-weight: bold; }
table.bz-mod-table { width: 100%; }
table.bz-mod-table td, table.bz-mod-table th { font-size: 11px; vertical-align: top; }
.bz-meter.wide { width: 70px; display: block; }

/* live round chat sessions */
.bz-session { border: 1px solid var(--line-soft); border-radius: 6px; background: var(--panel-alt);
  padding: 6px 8px; margin-bottom: 6px; max-height: 280px; overflow: auto; }
.bz-session-head { font-size: 11px; margin-bottom: 4px; }
.bz-line { font-size: 11px; padding: 1px 0; overflow-wrap: anywhere; }
.bz-line.bot b { color: var(--bz-bot); }
.bz-line.event { color: var(--ink-soft); font-style: italic; }
.bz-line.pending { opacity: .7; }

/* --------------------------------------------------- Last Light world page */
.ll-places { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.ll-place .ll-shot { aspect-ratio: 16 / 9; border: 1px solid var(--preview-edge); border-radius: 4px;
  overflow: hidden; margin-bottom: 6px; }
.ll-place .ll-shot canvas { width: 100%; height: 100%; display: block; }
.ll-place p { margin: 3px 0 0; }
.ll-beasts { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.ll-beast canvas { width: 100%; aspect-ratio: 22 / 26; display: block; border-radius: 4px;
  border: 1px solid var(--preview-edge); background: #1a1d24; }
.ll-beast-name { display: flex; justify-content: space-between; align-items: center; margin-top: 5px; gap: 6px; }
.ll-beast p { margin: 4px 0 0; }
.ll-beast .ll-tip { opacity: .8; font-style: italic; }

/* ------------------------------------------------ event world pages */
.ev-howto { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
.ev-step { border: 1px solid var(--line-soft); border-radius: 4px; padding: 7px 9px;
  background: var(--panel-alt, rgba(127,127,127,.06)); }
.ev-step b { display: block; font-size: 12px; margin-bottom: 2px; }
.ev-step p { margin: 0; }
