/* The site's three levels (Ryan, 28 Oct 2026): the dashboard (/), a room (/room/) and a game
   (/game/), one stylesheet. Game screens, not web pages (game-ui): the viewport is the frame and
   the facility's grid is behind it, plates have the hub's cut corners, numbers are big and labels
   quiet, every action is a key with its hint, and nothing scrolls. */
:root {
  --hull: #080B0D; --plate: #121A1F; --plate-2: #172128; --edge: #2E3D45; --ground: #0E1418; --rule: #1B2831;
  --amber: #FFB23F; --up: #3FD98A; --fault: #FF4D4D; --ink: #D7E1E6; --quiet: #8496A4; --dim: #5C6E7A;
  --cut: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
}
* { box-sizing: border-box; margin: 0; }
html, body { height: 100%; overflow: hidden; color: var(--ink); }
body {
  background:
    linear-gradient(var(--rule) 1px, transparent 1px) 0 0 / 40px 40px,
    linear-gradient(90deg, var(--rule) 1px, transparent 1px) 0 0 / 40px 40px,
    radial-gradient(ellipse at 40% 45%, #0f171c 0%, var(--hull) 70%);
  background-color: var(--hull);
  display: flex; flex-direction: column; gap: 12px; padding: 16px 18px;
}
[hidden] { display: none !important; }
/* A key's short hint is a narrow belt's (site.js key): on a phone a game's page holds Tutorial,
   Sound, your profile and the boards, and with their whole names they ran 57 px past a 390 px
   screen; on an upright tablet its desk's belt took a third row and cut a level's card. */
.hint .short { display: none; }
@media (max-width: 900px) {
  .belt .hint:has(.short) .long { display: none; }
  .belt .hint .short { display: inline; }
}
.plate { background: var(--plate); border: 1px solid var(--edge); clip-path: var(--cut); padding: 14px 18px; }
small, .label { display: block; color: var(--quiet); font-size: 12px; letter-spacing: .18em; text-transform: uppercase; }

/* ---- the top bar: where you are, and who you are ---- */
.top { display: flex; gap: 12px; align-items: stretch; flex: none; }
.brand { flex: none; cursor: pointer; }
/* The one-colour logo (public/brand/logo-mono.svg) as a mask, so it takes a colour of ours: the
   sign's white-hot core, with its blue neon round it (docs/marketing/strategy.md, Visual identity).
   At 15 px (12 on a short screen) it fills the box the name did in text, to the pixel in height and
   2 px narrower, so nothing below the bar moves. The glow is on the box and the mask on what it
   holds: an element's filter runs before its own mask, which would cut the glow away. */
.brand b { display: block; height: 15px; aspect-ratio: 6875 / 875; margin: 4px 0 6px;
  filter: drop-shadow(0 0 1px #2A6BFF) drop-shadow(0 0 3px #2A6BFF); }
.brand b::before { content: ''; display: block; height: 100%; background: #DDF6FF;
  -webkit-mask: url(/brand/logo-mono.svg) center / contain no-repeat; mask: url(/brand/logo-mono.svg) center / contain no-repeat; }
/* Forced colours (Windows' contrast themes) paint every background the plate's colour, which would
   leave the logo a hole in nothing: it takes the theme's text colour instead, as the name did. */
@media (forced-colors: active) {
  .brand b { filter: none; }
  .brand b::before { forced-color-adjust: none; background: CanvasText; }
}
.crumbs { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; font-size: 13px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--quiet); }
/* A step up is a key with its cap (H, ESC), the same key the belt binds. */
.crumbs .ctl .hint { font-size: 13px; letter-spacing: .14em; }
.crumbs .here { color: var(--ink); }
/* The floor's hint shows where the crumbs have a line's room for it: it says what to do to a newcomer,
   whose "You" plate is narrow; beside a returning player's stats it ran to three lines and raised the
   bar 28 px at 1024×768 (P1-307). */
.crumbs { container-type: inline-size; }
@container (max-width: 260px) { .crumbs .tip { display: none; } }
.you { flex: none; display: flex; gap: 22px; align-items: center; }
.you .who b { display: block; font-size: 16px; letter-spacing: .12em; }
/* A name gives way before the crumbs do: about thirteen capitals (10em; about nine on a phone or a
   tablet, 6.5em), then an ellipsis (its full text stays for a screen reader). A 20-character name
   ran the bar's "You" plate off a phone's screen and squeezed the crumbs from 667 to 1180 px wide
   (P1-307, `2026-10-28-site-laptops#11`). */
.you .who b { max-width: 10em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 1000px), (max-height: 520px) { .you .who b { max-width: 6.5em; } }   /* beside the brand on a tablet, and at 901 px, where the brand comes back */
.stat b { display: block; color: var(--amber); font-size: 24px; line-height: 1; font-weight: 700; }
.stat b span { color: var(--quiet); font-size: 14px; }
.stat small { margin-top: 4px; letter-spacing: .1em; }

/* ---- keys: a cap and a quiet hint; every action has one ---- */
.ctl { background: none; border: 0; color: inherit; font: inherit; display: inline-flex; align-items: center; cursor: pointer; padding: 0; }
.key { display: inline-block; min-width: 26px; padding: 3px 7px; margin-right: 6px; border: 1px solid var(--edge);
  border-bottom-width: 3px; color: var(--ink); font: inherit; font-size: 12px; text-align: center; }
.hint { color: var(--quiet); font-size: 12px; letter-spacing: .16em; text-transform: uppercase; }
.ctl:hover .key, .ctl:focus-visible .key { background: #1c2830; }
.ctl:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }
.ctl.armed .key { border-color: var(--amber); color: var(--amber); border-bottom-width: 1px; transform: translateY(2px); }
.ctl.go .key { border-color: var(--amber); color: var(--amber); }
.ctl.go .hint { color: var(--amber); }
/* A key that does nothing here says so: dimmed, with no hand (P1-314 PR 3's playtest: an amber Step
   up in a zone with nothing to play looked live). */
.ctl:disabled { opacity: .35; cursor: default; }
.ctl:disabled:hover .key { background: none; }
.belt { flex: none; display: flex; gap: 18px; align-items: center; justify-content: flex-end; flex-wrap: wrap; padding: 10px 16px; }

/* ---- a game's picture, framed, as the hub's room cards are ---- */
.art { display: block; width: 100%; object-fit: cover; border: 1px solid #4a3d24; background: var(--ground); }

/* ---- stars and level tiles ---- */
.stars { color: var(--amber); letter-spacing: .08em; }
.stars.full { color: var(--up); }
.none { color: var(--quiet); }
.chip { display: inline-block; font-size: 12px; letter-spacing: .06em; padding: 3px 8px; border: 1px solid var(--edge); }
.chip.mine { color: var(--amber); border-color: #5a4a2a; }
.chip.new { color: var(--quiet); }

/* ---- the faults, said in the world's terms ---- */
.fault { border-color: var(--fault); }
.status { font-size: 13px; line-height: 1.5; }

/* No entrance yet: the old landing page's power-on went with it (P1-312), and the site's motion waits
   on its feel brainstorm (P1-303). A key's press is its only movement. */

/* Where there is no keyboard the belt goes, and every action is a tap on its panel or key; the keys
   with nowhere else to be tapped (the profile, the boards) stay, worded for a finger. */
@media (max-width: 720px), (pointer: coarse) {
  .belt { padding: 6px 12px; gap: 10px; justify-content: flex-start; }
  .belt .tap { border: 1px solid var(--edge); padding: 8px 12px; min-height: 40px; }
  .belt .tap .hint { color: var(--ink); }
  /* Without the belt the crumbs become the way up: a tap key each, sized for a finger and pressed
     as the belt's taps are. */
  .crumbs .ctl { border: 1px solid var(--edge); padding: 6px 10px; min-height: 40px; }
  .crumbs .ctl .hint { color: var(--ink); }
  .crumbs .ctl.armed { border-color: var(--amber); }
}
/* One press state for a key without its cap: its edge lights amber and its face darkens in the
   frame it's pressed, as the crumbs' did alone; the belt's taps (Your profile, Leaderboards) and the
   cabinet's keys showed none, their press being the cap's, which touch hides (#194's gate-review). */
@media (pointer: coarse) {
  .ctl.armed { border-color: var(--amber); background: #1c2830; }
}
/* The keys with nowhere to be tapped (the arrows, Enter, Esc) go where none can be pressed, and
   where the belt has no room for them: under 640 px wide, and under 560 px tall. A mouse from 640
   to 720 px wide and 560 px tall or more keeps them, on the desk's belt (below): measured, they
   ran the floor's belt off the screen's edge at 480×640, took it to two rows at 667×375, and with
   two rows cost a level's card 4 px of its page at 720×521 (P1-307 PRs 14 and 15, #219's and
   #221's gate-reviews). */
@media (pointer: coarse), (width < 640px), (max-width: 720px) and (height < 560px) {
  .belt .ctl:not(.tap) { display: none; }
  .belt:not(:has(.tap)) { display: none; }
}
/* One rule for caps: a cap shows wherever its key can be pressed and its row has room, so touch
   drops them, and so does a window 400 px wide or less, where with their caps the crumbs took three
   rows and the cabinet's panels two, and the panel had 57 px (360×560 with a mouse; the keys still
   work). By width alone, a mouse in a narrow window (667×375, a laptop's half-screen 683×657) got
   the taps with no cap, and nothing named the keys that worked (P1-307, `2026-10-28-site-sizes#5`,
   `2026-10-28-site-phones#6`). */
@media (pointer: coarse), (max-width: 400px) {
  .belt .tap .key { display: none; }
  .crumbs .key { display: none; }
}
@media (max-height: 520px) {
  /* No room for where you are as well: the cover or the aisle already names it, so the crumbs
     keep only the steps up. */
  .crumbs .sep + .here { display: none; }
  body { padding: 8px 12px; gap: 8px; }
  .plate { padding: 8px 14px; }
  .brand small { display: none; }
  .brand b { height: 12px; margin: 3px 0 4px; }
  .stat b { font-size: 18px; }
  .belt { gap: 12px; padding: 6px 12px; }
  .belt .hint { letter-spacing: .06em; }
}
/* The separator before it, apart: a browser without `:has` drops a whole rule that names it, and in
   one list with the rule above it took the page's name back with it (#194's gate-review). */
@media (max-height: 520px) {
  .crumbs .sep:has(+ .here) { display: none; }
}
/* A phone on its side under 721 px wide: one row has no room for the brand as well, so it gives way;
   the crumbs' Floor goes home as it does, and the street carries the name (P1-307, at 667×375). */
@media (max-width: 720px) and (max-height: 520px) {
  .top .brand { display: none; }
}
/* A phone held upright, in its browser: 390×664 in Safari, 360×560 in Chrome, not the 390×844 of its
   screen. The brand gave way to a third row of bar, and with touch the belt's three taps to a second
   row, so the cabinet's panel was 0 px tall and the floor's last zones ran under the belt (P1-307).
   The brand goes, as on its side; the belt's taps keep one row. The crumbs wrap, so the floor's hint,
   a newcomer's one cue that a zone can be picked, takes a line of its own, and "The floor" keeps its
   line (half-screen#7: squeezed beside it, both broke in two). */
@media (max-width: 720px) and (min-height: 521px) {
  .top .brand { display: none; }
  .crumbs { flex-wrap: wrap; row-gap: 2px; }
  .belt { flex-wrap: nowrap; gap: 8px; }
  .belt .tap { padding: 8px; white-space: nowrap; }
  .belt .hint { letter-spacing: .06em; }
}
/* A mouse from 640 to 720 px wide and 560 px tall or more keeps the desk's belt, the arrows, Enter
   and Esc among its keys, plain as above 720 px rather than half a phone's, and wrapping to a
   second row where one row runs past the screen: a returning player's, with your profile's key,
   ran its last key to 693 px at 640×600 and 683×657 (#221's gate-review). Its bounds are the rule
   above's, turned over, so a window between two whole pixels, or with no pointer at all, gets one
   or the other, and it sits right, as the desk's does (#221's gate-review, notes 2 and 3). */
@media (not (pointer: coarse)) and (width >= 640px) and (max-width: 720px) and (height >= 560px) {
  .belt { flex-wrap: wrap; row-gap: 6px; justify-content: flex-end; }
  .belt .tap { border: 0; padding: 0; min-height: 0; }
  .belt .tap .hint { color: var(--quiet); }
}
/* A small phone's browser, up to 700 px tall (375×553, an iPhone SE's Safari; 360×560, a small
   Android's Chrome): who you are gives way to where you are, since the belt's profile tap has your
   stats, and there the plate took the room a page of the cabinet's panel needs (P1-307). */
@media (max-width: 720px) and (min-height: 521px) and (max-height: 700px) {
  .top .you { display: none; }
}
/* A phone 400 px wide or less: the name gives way sooner, since at 360 px a returning player's
   four stats ran the plate off the screen (P1-307). The guest's own label is no name: at 5em it read
   "NEW HE…" at 393×727, and "NEW HERE" needs 92 px (P1-307's PR 8 dry run). */
@media (max-width: 400px) and (min-height: 521px) {
  .you .who b { max-width: 5em; }
  .you .who b.guest { max-width: 6em; }
}
/* A tablet held upright: the bar takes two rows, the crumbs the second, as a phone's does: on one
   the crumbs were squeezed to "H FLO" at 768 px (P1-307). */
@media (min-width: 721px) and (max-width: 900px) and (min-height: 521px) {
  .top { flex-wrap: wrap; }
  .crumbs { order: 3; flex-basis: 100%; }
}
/* From 721 px wide the crumbs wrap within their plate rather than cut, and its padding narrows so
   two lines keep the bar's height: a long name squeezed the floor's crumbs to "ESC OUTSIDE › T F" at
   1024×768 (P1-307, `2026-10-28-site-laptops#11`). Wrapped, the floor's hint keeps a line of its own,
   the only words on an iPad on its side saying what to do (#12); above 1180 px, unwrapped, it broke
   "The floor" and itself into two lines each beside a returning player's stats (half-screen#7). */
@media (min-width: 721px) and (min-height: 521px) {
  .crumbs { flex-wrap: wrap; row-gap: 2px; align-content: center; padding-top: 8px; padding-bottom: 8px; }
}
/* A half-screen window (721 to 900 px wide, over 520 tall, and not an upright tablet, `TABLET` in
   site.js, whose complement this is): the bar keeps one row and leaves the brand, as a phone on its
   side does (the crumbs' Floor goes home); in two rows it took 137 px of 600 at 800×600 (P1-307,
   `2026-10-28-site-laptops#10`). */
@media (min-width: 721px) and (max-width: 900px) and (min-height: 521px) and ((aspect-ratio > 4/5) or (height < 980px)) {
  .top { flex-wrap: nowrap; }
  .top .brand { display: none; }
  .crumbs { order: 0; flex-basis: auto; }
}
/* A phone held upright: the bar takes two rows. On its side it keeps one, as a short screen does. */
@media (max-width: 720px) and (min-height: 521px) {
  body { padding: 10px; gap: 8px; }
  .top { flex-wrap: wrap; gap: 8px; }
  .brand b { height: 12px; margin: 3px 0 4px; }
  .crumbs { order: 3; flex-basis: 100%; font-size: 12px; }
  .you { gap: 12px; }
  .stat b { font-size: 18px; }
  .stat small { font-size: 12px; letter-spacing: 0; }
}
