@import url('https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400..700&family=Poppins:wght@300;400;500;600;700&display=swap');
/* ─────────────────────────────────────────────────────────────────────────
   PIXL — shared web-shell design system.

   The look: the landing site (apps/landing), continued. Someone who clicks
   "enter the game" off pixl.hackclub.com should not feel like they crossed
   into a different product, so the shell and the docs now run landing's own
   neo-brutalism rather than a theme of their own:

     • cream paper (--panel-deep), near-black rules (--stroke), square corners
     • borders thin on top/left and heavy on right/bottom (--bw/--bw-heavy),
       so every box reads as a block lit from the top left
     • hard offset shadows, solid ink, never blurred (--drop/--drop-lg)
     • press-in-toward-the-light hover: shift up and left, grow the bottom edge
     • Pixelify Sans for display type (labels, nav, buttons, headings, never
       paragraphs), Poppins for body copy. Both already matched landing.

   Two currencies keep their distinct accents:
     • --gold = landing's orange, the PIXELS you earn and spend (money)
     • --teal = the RESTORATION ENERGY poured into the Core (energy)
   plus --accent, landing's red, for pure attention (active nav, menu hover).

   Token NAMES are frozen — every page (and the JS-injected tour/dialog) reads
   --gold/--teal/--panel/--pixel/etc. directly, so only their values change here.
   Values live in packages/theme/palette.json (`bun run theme:sync`).

   The Godot game is deliberately NOT part of this port yet and still runs the
   older LEDGER gold-on-charcoal out of palette.json's separate godot.* set.
   ───────────────────────────────────────────────────────────────────────── */

/* ── reset ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{font-size:15px;-webkit-text-size-adjust:100%}

:root{
  /* PIXL PAPER — the landing site's palette, verbatim: cream paper, near-black
     rules, Hack Club red and orange. The only theme, and it lives on :root so
     a page painted before pixl.js runs already looks right.

     Every surface is a warm cream on purpose. --panel started out near-white
     and the result read as white slabs floating on cream, which is the one
     thing landing never looks like. Depth here comes from the black rule and
     the hard shadow, never from lightening a surface toward white.

     Token groups: --ink/--dim/--faint/--muted are text on paper.
     --panel/--panel-2/--panel-deep are the surfaces, --panel-deep being the
     page's cream backdrop. --gold/--gold-soft are PIXELS, "coins you spend",
     now landing's orange. --accent is landing's red, the one attention color
     (active nav, dropdown hover). --teal/--teal-hover are RESTORATION ENERGY.
     --good/--bad are state colors. --stroke is the black rule every border
     draws in, which is what makes the neo-brutalist look hold together.
     --btn-ink is the cream ink sitting on a filled button.

     Values come from packages/theme/palette.json (`bun run theme:sync`) —
     the marked block below is generated, do not hand-edit it. */
  /* <pixl-theme:light> */
  --ink:#16161e;--dim:#4a4a52;--faint:#6f6f78;--muted:#9a9aa2;--panel:#faf4de;--panel-2:#ece0bd;--panel-deep:#f5eed2;--gold:#ff8c37;--gold-soft:#ffa45c;--accent:#ec3750;--teal:#52aeb9;--teal-hover:#6bc3cd;--good:#3faa5f;--bad:#ec3750;--stroke:#16161e;--btn-ink:#f5eed2;
  /* <pixl-theme:light:end> */
  /* Backing for product images/icons. A lot of shop art is a dark silhouette
     on a transparent PNG, so this stays the lightest surface on the page, but
     it's still a cream rather than the old near-white: a white tile in a grid
     of cream cards is exactly the "white slab" problem again, just smaller. */
  --img-slot:#fdf8e6;
  /* Pixelify Sans is the blocky pixel/retro display face — labels, nav,
     buttons, headings. Poppins carries all body copy + data-dense areas.
     --pixel stays the var name for the display face (used everywhere). */
  --sans:'Poppins',system-ui,-apple-system,sans-serif;
  --pixel:'Pixelify Sans',ui-monospace,system-ui,sans-serif;
  /* Hard offset shadows, no blur and no alpha: the block just sits on the page
     with a solid slab of ink behind it, exactly like landing's
     shadow-[4px_4px_0px_#000]. --dither is "none" here, the paper look has no
     scanline texture, but the token stays so panels can keep referencing it. */
  /* <pixl-theme:light:effects> */
  --drop:4px 4px 0 #16161e;--drop-lg:8px 8px 0 #16161e;--dither:none;
  /* <pixl-theme:light:effects:end> */
  /* Square. Landing never rounds a corner, and the whole look leans on that. */
  --radius:0px;--radius-sm:0px;
  /* Landing's border recipe: thin on the top/left, heavy on the right/bottom,
     so every box reads as a solid block lit from the top left. --bw-lift is
     what the bottom edge grows to on hover. */
  --bw:2px;--bw-heavy:4px;--bw-lift:8px;
  /* the pixel-stepped corner (8-bit notch). --notch is tuned per component. */
  --notch:7px;
  --np:polygon(
    0 var(--notch),var(--notch) var(--notch),var(--notch) 0,
    calc(100% - var(--notch)) 0,calc(100% - var(--notch)) var(--notch),100% var(--notch),
    100% calc(100% - var(--notch)),calc(100% - var(--notch)) calc(100% - var(--notch)),calc(100% - var(--notch)) 100%,
    var(--notch) 100%,var(--notch) calc(100% - var(--notch)),0 calc(100% - var(--notch)));
  --sidebar:260px;--toprail:54px;
}

/* PIXL PAPER DARK — the same language, deliberately not a straight inversion
   of light: ink, stroke and panel are three distinct values here (the old
   2026-08-17 attempt used the same cream for both ink and stroke, which is
   why it read as flat e-ink rather than a real dark UI). Charcoal panels
   share their DNA with the Godot game's own existing dark theme
   (godot.dark in palette.json) rather than inventing an unrelated look;
   the accent shifts from the game's yellow-leaning gold to a coral instead. */
:root[data-theme="dark"]{
  /* <pixl-theme:dark> */
  --ink:#ece8e2;--dim:#b3ada2;--faint:#847e72;--muted:#5c574c;--panel:#211f1e;--panel-2:#2a2724;--panel-deep:#171615;--gold:#ff6b4a;--gold-soft:#ff8a6b;--accent:#ff4763;--teal:#5fc2cd;--teal-hover:#7ad4de;--good:#4ade80;--bad:#ff4763;--stroke:#4a453d;--btn-ink:#171615;
  /* <pixl-theme:dark:end> */
  /* <pixl-theme:dark:effects> */
  --drop:4px 4px 0 #000000;--drop-lg:8px 8px 0 #000000;--dither:none;
  /* <pixl-theme:dark:effects:end> */
}

/* Kenney pixel cursor pack (CC0) — the arrow replaces the OS pointer everywhere
   in the web shell + docs, the pointing hand shows on anything clickable. */
body,html{
  cursor:url(/img/cursor/cursor-arrow.png) 2 0,auto;
}
a,button,label,.btn,.card,.chip.opt-choice,.tier,.tab,.theme-toggle,.rail-btn,
.docs-group-head,.docs-nav a,.docs-toc a,.section-link,.modal-close,
input[type="checkbox"],input[type="radio"],select,.level-btn,.md-btn,
.jdel,.copy-btn,[onclick],[data-claim]{
  cursor:url(/img/cursor/cursor-pointer.png) 16 16,pointer!important;
}
/* typing fields keep the OS text-beam, not the pixel pointer (selects stay
   pointer — picking an option isn't typing) */
.field:not(select),textarea,input:not([type="checkbox"]):not([type="radio"]){cursor:text}

body{
  background-color:var(--panel-deep);
  color:var(--ink);
  font-family:var(--sans);line-height:1.5;overflow-y:scroll;
  transition:color .15s ease;
}
a{color:var(--gold);text-decoration:none}
a:hover{color:var(--gold-soft)}
img{display:block}
.wrap{max-width:1120px;margin:0 auto;padding:26px 20px 72px}

/* ══════════════════════════ app shell / sidebar ══════════════════════════
   mountTopbar() (pixl.js) injects the sidebar + top rail and adds
   .has-sidebar to <body>. Pages keep their <main class="wrap"> untouched —
   the offset here shifts them without any page-level markup change. */
body.has-sidebar{padding-left:var(--sidebar);padding-top:var(--toprail)}

.sidebar{
  position:fixed;top:0;left:0;bottom:0;width:var(--sidebar);z-index:40;
  display:flex;flex-direction:column;gap:4px;
  padding:16px 12px;
  background:var(--panel);border-right:var(--bw-heavy) solid var(--stroke);
}
.sb-logo{
  display:flex;align-items:center;
  padding:6px 8px 16px;margin-bottom:6px;
  font-family:var(--pixel);font-size:26px;font-weight:600;letter-spacing:1.5px;
  color:var(--ink);
}

.nav{display:flex;flex-direction:column;gap:16px;flex:1;overflow-y:auto}
.nav-group{display:flex;flex-direction:column;gap:2px}
.nav-label{
  font-family:var(--pixel);font-size:10.5px;font-weight:600;letter-spacing:2.5px;
  color:var(--muted);padding:0 10px;margin-bottom:4px;
}
.nav a{
  display:flex;align-items:center;gap:10px;
  padding:6px 10px;border-radius:0;
  font-family:var(--pixel);font-size:14.5px;letter-spacing:.8px;font-weight:500;
  color:var(--ink);border:var(--bw) solid transparent;
  transition:color .13s ease,background .13s ease,border-color .13s ease,transform .12s ease;
}
.nav a .ic{
  width:26px;height:26px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  background:var(--panel-deep);border:var(--bw) solid var(--stroke);border-radius:0;
  transition:background .13s ease,color .13s ease;
}
.nav a svg{width:14px;height:14px;flex-shrink:0}
/* Hover is the ink block, active is the red one. Red is the louder color, so
   it marks where you *are* rather than where the pointer happens to be. */
.nav a:hover{color:var(--panel-deep);background:var(--ink);border-color:var(--stroke);transform:translateX(3px)}
.nav a:hover .ic{background:var(--panel-deep);color:var(--ink)}
.nav a.active{
  color:var(--panel-deep);background:var(--accent);border-color:var(--stroke);
}
.nav a.active .ic{background:var(--panel-deep);color:var(--ink)}
/* hovering the row you're already on keeps the red, so it doesn't look like
   the selection moved */
.nav a.active:hover{background:var(--accent)}
.sb-foot{display:flex;flex-direction:column;gap:8px;margin-top:6px}
.back-to-game .arrow{display:inline-block;transition:transform .15s ease}
.back-to-game:hover .arrow{transform:translateX(-3px)}

/* Opaque, not translucent-blurred: a frosted bar is a soft-UI idea and it
   muddies the hard rule underneath it. */
.toprail{
  position:fixed;top:0;left:var(--sidebar);right:0;height:var(--toprail);z-index:39;
  display:flex;align-items:center;justify-content:flex-end;gap:10px;
  padding:0 20px;
  background:var(--panel-deep);
  border-bottom:var(--bw-heavy) solid var(--stroke);
}

/* The MORE button and its sheet are mobile-only: the desktop rail has room for
   every link, so both stay out of the way entirely. */
.nav-more,.nav-sheet{display:none}

/* mobile: sidebar → bottom icon bar, top rail spans full width */
@media (max-width:900px){
  body.has-sidebar{padding-left:0;padding-bottom:64px}
  .sidebar{
    top:auto;left:0;right:0;bottom:0;width:auto;height:60px;
    flex-direction:row;gap:2px;padding:0 6px;
    border-right:0;border-top:var(--bw-heavy) solid var(--stroke);
  }
  .sb-logo,.sb-foot{display:none}
  .nav{flex-direction:row;gap:2px;justify-content:space-around;overflow:visible}
  .nav-group{display:contents}
  .nav-label{display:none}
  /* Ten links in a 60px row left each one about 36px wide with unreadable
     labels. The dock carries four plus MORE; the rest live in the sheet. */
  .nav a.secondary{display:none}
  .nav-more{
    display:flex;flex-direction:column;gap:3px;flex:1;
    align-items:center;justify-content:center;
    padding:8px 2px 6px;border:0;background:none;cursor:pointer;
    font-family:var(--pixel);font-size:10px;letter-spacing:.5px;
    color:var(--faint);transition:color .13s ease;
  }
  .nav-more svg{width:20px;height:20px}
  .nav-more.open{color:var(--accent);box-shadow:inset 0 3px 0 var(--accent)}
  .nav-sheet{
    display:block;position:fixed;left:0;right:0;bottom:60px;z-index:41;
    background:var(--panel);
    border-top:var(--bw-heavy) solid var(--stroke);
    padding:10px 8px calc(10px + env(safe-area-inset-bottom,0px));
    animation:pxl-sheet-up .16s ease;
  }
  .nav-sheet[hidden]{display:none}
  .nav-sheet-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
  .nav-sheet .nav-sheet-grid a{
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
    padding:12px 4px;border-radius:0;border:var(--bw) solid var(--stroke);
    background:var(--panel-deep);color:var(--ink);text-decoration:none;
    font-family:var(--pixel);font-size:11px;letter-spacing:.5px;text-align:center;
  }
  .nav-sheet .nav-sheet-grid a svg{width:20px;height:20px}
  .nav-sheet .nav-sheet-grid a.active{background:var(--accent);color:var(--panel-deep)}
  @keyframes pxl-sheet-up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  .nav a{
    flex-direction:column;gap:3px;flex:1;justify-content:center;
    padding:8px 2px 6px;font-size:10px;letter-spacing:.5px;border:0;border-radius:0;
    text-align:center;
  }
  .nav a .ic{width:auto;height:auto;background:transparent;border:0}
  .nav a svg{width:20px;height:20px}
  /* In the 60px dock a filled block would swallow the whole cell, so the
     current tab is marked with a thick rule along the top edge instead. */
  .nav a.active{background:transparent;color:var(--accent);box-shadow:inset 0 3px 0 var(--accent)}
  .nav a.active .ic{background:transparent;color:var(--accent)}
  .nav a:hover{background:transparent;color:var(--accent);transform:none}
  .nav a:hover .ic{background:transparent;color:var(--accent)}
  .toprail{left:0}
}

/* ── currency rail (top-right): three chips, deliberately distinct ── */
.wallet-chip,.rest-chip,.re-chip{
  display:flex;align-items:center;gap:8px;
  padding:5px 11px 5px 6px;border-radius:0;
  border:var(--bw) solid var(--stroke);background:var(--panel);
  font-size:13px;cursor:default;font-variant-numeric:tabular-nums;
}
/* The currency's color lives in the icon slot and the number, not in a tinted
   border: every rule on the page is the same black, that's the whole point. */
.wallet-chip .slot,.rest-chip .slot,.re-chip .slot{
  width:24px;height:24px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  border:var(--bw) solid var(--stroke);border-radius:0;
}
.wallet-chip .slot{background:var(--gold)}
.wallet-chip .slot img{width:16px;height:16px}
.wallet-chip .px{color:var(--ink);font-family:var(--sans);font-weight:700;font-size:16px;letter-spacing:.2px;font-variant-numeric:tabular-nums}
.rest-chip .slot{background:var(--teal)}
.rest-chip .slot svg{width:15px;height:15px}
.rest-chip .re{color:var(--ink);font-family:var(--sans);font-weight:700;font-size:16px;letter-spacing:.2px;font-variant-numeric:tabular-nums}
.rest-chip .rl{color:var(--dim);font-size:11px;letter-spacing:.5px}
.re-chip .slot{background:var(--accent)}
.re-chip .slot svg{width:15px;height:15px;color:var(--btn-ink)}
.re-chip .val{color:var(--ink);font-family:var(--sans);font-weight:700;font-size:16px;letter-spacing:.2px;font-variant-numeric:tabular-nums}
.re-chip .rl{color:var(--dim);font-size:11px;letter-spacing:.5px}
@media (max-width:560px){
  .rest-chip .rl{display:none}
  .rest-chip{display:none}
  .re-chip .rl{display:none}
}

/* ── theme toggle + help ── */
.theme-toggle,.rail-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:0;flex-shrink:0;
  border:var(--bw) solid var(--stroke);
  border-right-width:var(--bw-heavy);border-bottom-width:var(--bw-heavy);
  background:var(--panel);color:var(--ink);
  font-size:15px;cursor:pointer;line-height:1;font-family:var(--pixel);font-weight:700;
  transition:color .13s ease,background .13s ease,border-bottom-width .13s ease,transform .13s ease;
}
.theme-toggle:hover,.rail-btn:hover{
  background:var(--accent);color:var(--panel-deep);
  border-bottom-width:var(--bw-lift);transform:translate(-2px,-2px);
}
.theme-toggle svg,.rail-btn svg{width:16px;height:16px;image-rendering:pixelated}

/* ── theme picker menu ──
   Structurally identical to landing's LanguageSwitcher dropdown: 2px black
   rule, hard 4px offset shadow, current option is a solid black block with
   cream type, everything else flips to red on hover. */
.theme-picker{position:relative}
.theme-menu{
  position:absolute;top:calc(100% + 6px);right:0;z-index:60;min-width:170px;
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--panel);border:var(--bw) solid var(--stroke);border-radius:0;
  box-shadow:var(--drop);
}
.theme-menu[hidden]{display:none}
.theme-opt{
  display:flex;align-items:center;gap:9px;width:100%;padding:8px 11px;
  border:none;border-radius:0;background:transparent;color:var(--ink);
  font-family:var(--pixel);font-size:13.5px;letter-spacing:.3px;text-align:left;cursor:pointer;
  transition:background .12s ease,color .12s ease;
}
.theme-opt:hover{background:var(--accent);color:var(--panel-deep)}
.theme-opt.active{background:var(--ink);color:var(--panel-deep)}
.theme-opt .swatch{width:14px;height:14px;border:1px solid var(--stroke);border-radius:0;flex-shrink:0}

/* Same picker, but a full-width text trigger (not an icon square) for
   dropdowns like the ship panel's Trial picker — left-aligned menu the
   button's own width instead of the fixed 170px/right-aligned theme menu. */
.trial-picker{display:block;width:100%}
.trial-picker-btn{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  width:100%;text-align:left;cursor:pointer;
}
.trial-picker-btn::after{content:"▾";font-size:11px;color:var(--ink);flex-shrink:0}
.trial-picker .theme-menu{left:0;right:auto;width:100%;min-width:0}

/* ══════════════════════════ components ══════════════════════════ */
/* Landing's button, verbatim: filled face, black rule that's heavy on the
   right/bottom, and a hover that lifts the block up-left while the bottom edge
   grows. No box-shadow here on purpose, the thick border IS the shadow. */
.btn[hidden]{display:none}
.btn{
  display:inline-flex;align-items:center;gap:7px;
  cursor:pointer;border-radius:0;
  border:var(--bw) solid var(--stroke);
  border-right-width:var(--bw-heavy);border-bottom-width:var(--bw-heavy);
  background:var(--gold);color:var(--btn-ink);
  font-family:var(--pixel);font-size:15px;letter-spacing:.5px;font-weight:600;
  padding:9px 17px;
  transition:background .13s ease,color .13s ease,border-color .13s ease,
             border-bottom-width .13s ease,transform .13s ease;
  text-decoration:none;white-space:nowrap;
}
.btn:hover{
  background:var(--gold-soft);color:var(--btn-ink);
  border-bottom-width:var(--bw-lift);transform:translate(-2px,-2px);
}
.btn:active{border-bottom-width:var(--bw);transform:translate(0,2px)}
.btn.dark{background:var(--ink);color:var(--panel-deep)}
.btn.dark:hover{background:var(--ink);color:var(--gold)}
.btn.ghost{background:transparent;color:var(--ink)}
.btn.ghost:hover{background:var(--panel-2);color:var(--ink)}
.btn.teal{background:var(--teal);color:var(--btn-ink)}
.btn.teal:hover{background:var(--teal-hover)}
.btn.red{background:var(--bad);color:var(--panel-deep)}
.btn.red:hover{background:color-mix(in srgb,var(--bad) 85%,#fff)}
.btn:disabled{opacity:.45;cursor:default;transform:none;border-bottom-width:var(--bw-heavy)}
.btn:disabled:hover{background:var(--gold);transform:none;border-bottom-width:var(--bw-heavy)}

/* Chips carry a lot of numbers (hours, levels, px earned) — normal type
   reads faster here than the pixel display face, which blurs digits together
   at 12px. Weight + letter-spacing keep the "badge" feel without the blur. */
.chip{
  display:inline-flex;align-items:center;gap:5px;
  font-family:var(--sans);font-size:12.5px;letter-spacing:.2px;font-weight:700;
  font-variant-numeric:tabular-nums;
  padding:4px 9px;border:var(--bw) solid var(--stroke);border-radius:0;
  background:var(--panel);color:var(--ink);
}
/* Filled chips keep the black rule rather than dropping it: landing's step
   badge is a filled block with a border, and losing it makes them read as
   soft pills against the paper. */
.chip.gold{background:var(--gold);color:var(--btn-ink)}
.chip.green{background:var(--good);color:var(--ink)}
.chip.teal{background:var(--teal);color:var(--btn-ink)}
.chip.red{background:var(--bad);color:var(--panel-deep)}

.card{
  cursor:pointer;border:var(--bw) solid var(--stroke);border-radius:0;
  background:var(--panel);box-shadow:var(--drop);
  transition:box-shadow .13s ease,transform .13s ease,background-color .13s ease;
}
/* landing's card move: lift toward the light, shadow doubles, snap back on press */
.card:hover{box-shadow:var(--drop-lg);transform:translate(-2px,-2px)}
.card:active{transform:translate(0,0);box-shadow:var(--drop)}

.panel{border:var(--bw) solid var(--stroke);border-radius:0;background:var(--panel);box-shadow:var(--drop)}
.panel-deep{border:var(--bw) solid var(--stroke);border-radius:0;background:var(--panel-deep);box-shadow:var(--drop)}

/* Pixl.markdown() output — every page that renders a journal/project/idea
   body (.jbody.md, .idea-body.md, the journal composer's .md-preview) shares
   this one ruleset. It has to live here, not per-page: the global *{margin:0}
   reset above strips every element back to flat, unspaced text, so without
   this headings/paragraphs/lists/quotes/code all render as one undifferentiated
   blob wherever a page forgets to redeclare it locally. */
.md .md-h,.md-preview .md-h{font-family:var(--pixel,var(--sans));color:var(--ink);line-height:1.3;letter-spacing:.3px;margin:.9em 0 .4em}
.md>*:first-child,.md-preview>*:first-child{margin-top:0}
.md>*:last-child,.md-preview>*:last-child{margin-bottom:0}
.md h1.md-h,.md-preview h1.md-h{font-size:22px}
.md h2.md-h,.md-preview h2.md-h{font-size:19px}
.md h3.md-h,.md-preview h3.md-h{font-size:17px}
.md h4.md-h,.md-preview h4.md-h,.md h5.md-h,.md-preview h5.md-h,.md h6.md-h,.md-preview h6.md-h{font-size:15px;color:var(--faint)}
.md .md-p,.md-preview .md-p{margin:0 0 .7em}
.md .md-list,.md-preview .md-list{margin:0 0 .7em;padding-left:1.4em}
.md .md-list li,.md-preview .md-list li{margin:.25em 0}
.md .md-quote,.md-preview .md-quote{margin:0 0 .7em;padding:6px 12px;border-left:3px solid var(--teal);background:color-mix(in srgb,var(--teal) 10%,transparent);color:var(--faint)}
.md .md-hr,.md-preview .md-hr{border:none;border-top:var(--bw) solid var(--stroke);margin:.9em 0}
.md .md-pre,.md-preview .md-pre{margin:0 0 .7em;padding:10px 12px;background:var(--panel-deep);border:var(--bw) solid var(--stroke);border-radius:0;overflow-x:auto;font-size:13px;line-height:1.5}
.md code,.md-preview code{font-family:ui-monospace,"SF Mono",Menlo,Consolas,monospace;font-size:.9em;background:var(--panel-deep);border:1px solid var(--stroke);padding:1px 5px}
.md .md-pre code,.md-preview .md-pre code{background:none;border:none;padding:0}
.md img,.md-preview img{max-width:100%;max-height:260px;display:block;margin:.35rem 0}

/* HUD panel — the hero surface. Landing has no pixel-notch corner anywhere, so
   the notch is gone and this is now simply the heaviest block on the page: a
   full-weight rule on every edge plus the big shadow. The class and its
   .deep/.gold/.teal variants stay so no page markup has to change. */
.hud{
  position:relative;
  border:var(--bw-heavy) solid var(--stroke);border-radius:0;
  background:var(--panel);box-shadow:var(--drop-lg);
}
.hud.deep{background:var(--panel-deep)}
.hud.gold{background:var(--gold);color:var(--btn-ink)}
.hud.teal{background:var(--teal);color:var(--btn-ink)}

/* ── page headers ── */
.page-title{
  font-family:var(--pixel);font-weight:700;font-size:34px;line-height:1.05;
  letter-spacing:1px;color:var(--ink);
}
.page-sub{
  font-family:var(--pixel);font-weight:500;font-size:13px;letter-spacing:2px;
  color:var(--dim);margin-top:8px;text-transform:uppercase;
}

/* ── restoration / progress bar ── */
.rbar{position:relative;height:16px;background:var(--panel);border:var(--bw) solid var(--stroke);border-radius:0;overflow:hidden}
/* The glow is gone: a blurred halo is the one thing this look never does. The
   two-tone stripe stays, it's what makes the fill read as pixels. */
.rbar>i{
  display:block;height:100%;
  background:repeating-linear-gradient(90deg,var(--teal) 0 7px,var(--teal-hover) 7px 14px);
  transition:width .5s ease;
}
.rbar.gold>i{background:repeating-linear-gradient(90deg,var(--gold) 0 7px,var(--gold-soft) 7px 14px)}

/* ── status dots ── */
.dot{width:9px;height:9px;border:1px solid var(--stroke);border-radius:0;display:inline-block;flex-shrink:0}
.dot.on{background:var(--good)}
.dot.off{background:var(--bad)}
.dot.gold{background:var(--gold)}
.dot.teal{background:var(--teal)}

.field{
  font-family:var(--sans);background:var(--panel);color:var(--ink);
  border:var(--bw) solid var(--stroke);border-radius:0;padding:10px 14px;font-size:15px;
  outline:none;transition:box-shadow .13s ease,transform .13s ease;
}
/* Focus pops the block forward instead of recoloring the rule: the rule is
   already black, so tinting it would read as weaker, not stronger. */
.field:focus{box-shadow:var(--drop);transform:translate(-1px,-1px)}
.field::placeholder{color:var(--muted)}
select.field{cursor:pointer}

/* Custom dropdown that replaces every native <select>'s OS chrome (rounded
   corners, system arrow, native popup) - see Pixl.enhanceSelects in pixl.js.
   The real <select> lives inside .csel, visually hidden but still the
   source of truth for .value/change events. */
/* No explicit width: a .csel is a flex item everywhere it's used (a
   column .form-row stretches it full width via align-items:stretch same as
   the bare <select> did before; a row toolbar sizes it to content same as
   a native <select> would), so it should just inherit that, not fight it. */
.csel{position:relative;display:inline-block}
.csel select{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.csel-btn{width:100%;display:flex;align-items:center;justify-content:space-between;gap:10px;text-align:left;cursor:pointer}
.csel-btn.disabled,.csel-btn:disabled{opacity:.5;cursor:default}
.csel-arrow{flex-shrink:0;font-size:10px;color:var(--dim);transition:transform .13s ease}
.csel.open .csel-arrow{transform:rotate(180deg)}
.csel-menu{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:60;background:var(--panel);border:var(--bw) solid var(--stroke);box-shadow:var(--drop);max-height:280px;overflow-y:auto}
.csel-group{font-family:var(--pixel);font-size:10.5px;letter-spacing:.5px;text-transform:uppercase;color:var(--faint);padding:8px 14px 4px}
/* Same look as .theme-opt (the theme switcher / Trial picker menu): pixel
   font, hard color-block hover/selected instead of a plain web-app highlight,
   so every custom dropdown in the shell reads as one component. */
.csel-opt{display:block;width:100%;text-align:left;background:none;border:none;font-family:var(--pixel);font-size:13.5px;letter-spacing:.3px;color:var(--ink);cursor:pointer;padding:9px 14px;transition:background .12s ease,color .12s ease}
.csel-opt:hover{background:var(--accent);color:var(--panel-deep)}
.csel-opt.on{background:var(--ink);color:var(--panel-deep)}
.csel-opt:disabled{color:var(--muted);cursor:default}
.csel-opt:disabled:hover{background:none;color:var(--muted)}

.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}
.empty-note{text-align:center;padding:40px 20px;color:var(--dim);font-size:16px;line-height:1.8;font-family:var(--pixel);letter-spacing:1px}
.divider{height:var(--bw);background:var(--stroke);margin:30px 0}
.faint{color:var(--faint)}
.muted{color:var(--muted)}
.gold{color:var(--gold)}
.teal{color:var(--teal)}
.dim{color:var(--dim)}

/* ── overlay / modal ── */
.overlay{
  position:fixed;inset:0;z-index:100;
  display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,#16161e 74%,transparent);
  opacity:0;pointer-events:none;transition:opacity .2s;
}
.overlay.show{opacity:1;pointer-events:all}
.modal{width:90%;max-width:720px;max-height:90vh;overflow-y:auto;position:relative;padding:32px 30px 24px}
.modal-close{position:absolute;top:12px;right:16px;background:none;border:none;color:var(--ink);font-size:22px;cursor:pointer;line-height:1;font-family:var(--pixel)}
.modal-close:hover{color:var(--accent)}

/* ── spinner (stepped, pixel-ish) ── */
.spin{width:30px;height:30px;margin:40px auto;border:4px solid var(--panel-2);border-top-color:var(--accent);border-radius:50%;animation:spin .7s steps(8) infinite}
.spin-sm{width:12px;height:12px;display:inline-block;vertical-align:-2px;border:2px solid var(--panel-2);border-top-color:var(--accent);border-radius:50%;animation:spin .7s steps(8) infinite}
.md-btn:disabled{opacity:.5;cursor:default}
@keyframes spin{to{transform:rotate(360deg)}}

/* ── toast ── */
.toast-slot{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:200;display:flex;flex-direction:column;gap:8px;pointer-events:none}
.toast{
  background:var(--panel);color:var(--ink);
  border:var(--bw) solid var(--stroke);border-radius:0;padding:12px 20px;
  font-size:15px;box-shadow:var(--drop);
  animation:toast-in .2s ease both;
}
.toast.bad{background:var(--bad);color:var(--panel-deep)}
@keyframes toast-in{from{opacity:0;transform:translateY(10px)}}

/* ── gate (no token) ──
   The game's own boot splash is the background, so a signed-out visitor lands
   on the same screen the game itself starts on. Cream and dark ink regardless
   of theme: it is the loading screen, not a page of the shell. The wordmark is
   in the image, which is why there is no heading here. */
.gate{
  position:fixed;inset:0;z-index:9999;
  display:flex;align-items:center;justify-content:center;
  padding:24px;background:#f5eed2;
}
/* the splash is a real element, not a background image: as a background its
   position was a percentage of the viewport, so on a tall window the wordmark
   floated hundreds of pixels above the copy. in flow, the gap is just a margin */
.gate-card{
  display:flex;flex-direction:column;align-items:center;
  text-align:center;max-width:620px;
}
/* native 1000px wide puts the wordmark at the same 640px the game's own
   loading screen draws it at, and keeps the pixels 1:1. the file carries 35%
   blank above the wordmark and 37% below, so the negative margins crop that
   padding back off, scaled to the rendered width rather than fixed. */
.gate-splash{
  --sw:min(1000px,92vw);
  display:block;width:var(--sw);height:auto;image-rendering:pixelated;
  margin-top:calc(var(--sw) * -0.19);
  margin-bottom:calc(var(--sw) * -0.20);
}
.gate-card p{color:#6b5c46;font-size:16px;line-height:1.7;margin-bottom:28px;max-width:34em}
/* the landing's dash CTA: black face, cream ink, chunky offset border */
.btn-enter{
  display:inline-block;font-family:var(--pixel);font-size:32px;line-height:1;
  padding:14px 36px;background:#000;color:#f5eed2;text-decoration:none;
  border:2px solid #000;border-right-width:8px;border-bottom-width:8px;
  transition:transform .15s ease,border-bottom-width .15s ease;
}
.btn-enter:hover{border-bottom-width:12px;transform:translate(-4px,-4px)}
.btn-enter:active{border-bottom-width:4px;transform:translate(0,2px)}
/* log in is the primary action on the gate, so "enter the game" needs a
   quieter sibling rather than two identical black slabs */
.btn-enter.ghost{background:transparent;color:#000}
.gate-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:18px}
@media (max-height:620px){
  .gate-splash{--sw:min(560px,70vw)}
  .btn-enter{font-size:24px;padding:12px 26px}
  .gate-card p{font-size:14px;margin-bottom:20px}
  .gate-actions{gap:12px}
}

/* ── misc ── */
audio{display:none}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
}
