:root { --fg: #f4f1ea; --dim: rgba(244,241,234,.6); --bg: #0d0d0f; --accent: #e8b04a;
  /* DESIGN.md, "Calm and round" (owner, 14 Oct 2026): the logo's colours only */
  --navy: #1B2A63; --sun: #FFC21A; --ink: #0B1029; --soft: #E9ECF4; --dim-ink: #4A5170; --float: rgba(27,42,99,.72);
  --shadow: 0 10px 28px rgba(11,16,41,.4); }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--fg);
  font: 14px/1.5 Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; overflow: hidden; }
canvas { display: block; }
button:focus-visible { outline: 2px solid var(--sun); outline-offset: 2px; }
#recent, #saved { display: grid; gap: 8px; }
/* The start screen (body.start, no room, main.js): plain dark navy behind, the buttons left, MetaXCity right */
body.start #overlay { background: var(--ink); backdrop-filter: none; }
body.start .menu { width: min(860px, 100%); }
body.start #panels { max-height: min(520px, calc(100dvh - 90px)); }
body.start #continue, body.start #to-entrance, body.start #to-start, body.start .menu h1 { display: none; }
#panel-welcome:not([hidden]) { display: grid; place-content: center; justify-items: center; gap: 12px; min-height: 100%; text-align: center; }
#panel-welcome img { width: min(320px, 100%); height: auto; }
#panel-welcome p { max-width: 36ch; font-size: 16px; }
/* All places: a card per room */
#all-places { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.menu .place { display: grid; align-content: start; gap: 2px; padding: 8px; line-height: 1.3; }
.menu .place img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: 8px; margin-bottom: 4px; }
.menu .place span { font-weight: 500; font-size: 13px; opacity: .8; }
.menu .place .chip { justify-self: start; padding: 1px 8px; border-radius: 999px; background: var(--sun); color: var(--ink); opacity: 1; }
#places-back { margin-right: 8px; }
#colours .swatches { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
#colours .swatches button { width: 48px; padding: 0; border: 2px solid rgba(255,255,255,.25); border-radius: 50%; }
#colours .swatches button.picked { outline: 3px solid #fff; outline-offset: 2px; }
#panels p { margin: 0 0 10px; }
/* What you have and have booked: a white card (DESIGN.md, "Cards") */
#panels:has(#panel-inventory:not([hidden])) { background: #fff; color: var(--ink); }
#panel-inventory h3 { color: var(--dim-ink); }
#panels .lbl { font: 600 12px Inter, sans-serif; color: var(--dim-ink); }
#wallet-history .line { display: flex; justify-content: space-between; align-items: center; gap: 12px; min-height: 32px; padding: 4px 0; border-bottom: 1px solid var(--soft); }
#wallet-history .lbl { margin-top: 8px; }
#wallet-history .amount { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
#wallet-history .link, #wallet-history .more, .menu #by-phone, .menu #forgot { min-height: 48px; padding: 0; background: none; color: var(--navy); font: inherit; text-align: left; text-decoration: underline; }
#wallet-history .more { margin-top: 8px; }
#panels .balance { font-family: Rubik, ui-sans-serif, sans-serif; font-size: 30px; font-weight: 800; line-height: 1.1; }
#panel-options, #login, #signup, #code-form { display: grid; gap: 6px; }
#panel-options[hidden] { display: none; }
/* the touch settings show only once touch is on (body.touch), never by screen width; Vibration only where it works */
#touch-options { display: none; }
body.touch #touch-options { display: grid; gap: 6px; margin-top: 8px; }
#touch-options.no-vibrate .vibrate { display: none; }
#touch-options label span { font-weight: 400; }
#touch-reset { margin-top: 8px; }
#options-back[hidden] { display: none; }
/* Top up, inside My inventory (white): the fields get an edge, the accounts a row each with a Copy button */
.menu input[type=number], .menu input[type=file] { min-height: 48px; padding: 0 12px; border: 0; border-radius: 12px; background: #fff; color: var(--ink); font: 500 16px Inter, ui-sans-serif, system-ui, sans-serif; }
.menu input[type=file] { padding: 10px 12px; }
#panel-inventory :is(input, select) { border: 1px solid #c9cedd; }
#panel-inventory button { background: var(--navy); color: #fff; }   /* the menu's see-through ones vanish on white */
/* on white: navy a little lighter (DESIGN.md); not the links, nor the sun Send button */
#panel-inventory button:not(.link, .more, [type=submit]):focus-visible { background: #2E3F86; color: #fff; }
@media (hover: hover) { :where(#overlay:not(.by-keys)) #panel-inventory button:not(.link, .more, [type=submit], :disabled):hover { background: #2E3F86; color: #fff; } }
#open-topup { margin: 8px 0 4px; }
#topup-form { display: grid; gap: 6px; }
#topup-form label { margin-top: 6px; font-weight: 600; }
#topup-form button[type=submit] { margin-top: 8px; background: var(--sun); color: var(--ink); }
#panel-inventory .bank { display: grid; grid-template-columns: 32px 1fr auto; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--soft); }
#panel-inventory .bank .number { font-variant-numeric: tabular-nums; word-break: break-all; }
#panel-inventory .line { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--soft); }
#panel-inventory .chip { padding: 1px 8px; border-radius: 999px; background: var(--sun); color: var(--ink); font: 600 12px Inter, sans-serif; white-space: nowrap; }
#panel-inventory .reason { color: var(--dim-ink); font-size: 14px; }
#topup-note:empty { display: none; }
#login, #signup, #code-form { display: none; padding: 12px 14px; }
#login, #signup, #code-form { gap: 6px; }
/* on the navy card; their 48 px touch targets overlap the gaps around them instead of making the menu taller (360 px phone) */
.menu #by-phone, .menu #forgot { justify-self: start; margin: -12px 0 -6px; padding: 0 4px; color: #fff; font-weight: 600; }
#code-form:not(.reset) #reset-password { display: none; }
#name-form { display: grid; gap: 6px; }
#name-form[hidden] { display: none; }
.menu #name-form .pair { grid-template-columns: 1fr auto; }
#name-note:empty { display: none; }
#login > label, #signup > label, #code-form > label { font-family: Rubik, ui-sans-serif, sans-serif; font-size: 18px; font-weight: 800; }
#login-note, #signup-note, #code-note { min-height: 1.5em; }
.menu .choice { display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 0 12px; border-radius: 12px; background: rgba(255,255,255,.12); font-weight: 600; cursor: pointer; }
.menu .choice input { width: 20px; height: 20px; accent-color: var(--sun); }
.menu .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.menu .pair > input { width: 100%; min-width: 0; }
/* a phone held upright: one field a row */
@media (max-width: 560px) { #signup .pair:has(> input) { grid-template-columns: 1fr; } }
#overlay.logging-in:not([data-step]) #login, #overlay.logging-in[data-step=signup] #signup, #overlay.logging-in[data-step=code] #code-form { display: grid; }
#overlay.logging-in nav, #overlay.logging-in #panels, #overlay.logging-in #who { display: none; }
/* the login alone: one column, not a form pushed right of an empty side */
#overlay.logging-in .menu { grid-template-columns: 1fr; width: min(480px, 100%); }
#overlay.logging-in .side { display: none; }
#who:empty, #status:empty { display: none; }
.no-run .run-only, .no-run #sprint { display: none; }
#who { font-weight: 600; }
/* Until the whole room has arrived the menu is only a bar filling up (track in src/core/util.js). After the
   logging-in rules: it wins over them. */
#load { display: none; height: 12px; border-radius: 6px; background: rgba(255,255,255,.12); overflow: hidden; }
#bar { width: 0; height: 100%; background: var(--sun); transition: width .2s; }
#overlay.loading #load { display: block; }
#overlay.loading nav, #overlay.loading #panels, #overlay.loading #login, #overlay.loading #who { display: none; }
#overlay.loading #status { font-size: 14px; }
@media (prefers-reduced-motion: reduce) { #bar, .menu button { transition: none; } }
.keys { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; text-align: left; width: fit-content; }
kbd { font: 12px ui-monospace, monospace; padding: 2px 7px; border-radius: 6px;
  border: 1px solid rgba(255,255,255,.25); background: rgba(255,255,255,.06); }
/* Every key named in the room's screens is a key cap: bold, boxed, a darker lip under it (owner, 26 Oct: "should be bold
   or clearly shown"). White with ink on navy; on white an outline too; the prompt's is sun (below). */
:is(.menu, #edit, #marks, #mark-btn, #popup) kbd { min-width: 22px; padding: 1px 6px; border: 0; border-radius: 6px;
  background: #fff; color: var(--ink); font: 800 12px/20px Rubik, sans-serif; text-align: center; white-space: nowrap;
  box-shadow: inset 0 -2px 0 rgba(11,16,41,.22); opacity: 1; }
:is(#edit, #marks, #mark-btn, #popup) kbd { display: inline-block; }   /* not the menu's: its help list hides some by display */
#popup kbd { box-shadow: inset 0 0 0 1px rgba(11,16,41,.28), inset 0 -2px 0 rgba(11,16,41,.22); }
.menu kbd { align-self: start; justify-self: start; }
#status { color: rgba(255,255,255,.75); font-size: 12px; min-height: 1em; }
#crosshair { position: fixed; left: 50%; top: 50%; width: 6px; height: 6px; margin: -3px 0 0 -3px;
  border-radius: 50%; background: rgba(255,255,255,.8); pointer-events: none; z-index: 5; }
/* Over the walk: see-through navy, a sun key cap, then what the key does (world/hotspots.js) */
/* quieter than the other floating objects (owner, 15 Oct: TODO item 3): a lighter navy, the key cap carries it */
/* It fades in and out (.on, with a short hold against flicker in hotspots.js); the key cap looks like a key: a darker lip under it */
#prompt { position: fixed; left: 50%; top: calc(50% + 18px); transform: translate(-50%, 4px); display: flex; align-items: center; gap: 8px;
  padding: 5px 12px 5px 6px; white-space: nowrap; border-radius: 12px; background: rgba(27,42,99,.38); backdrop-filter: blur(2px);
  color: #fff; font: 600 13px Inter, sans-serif; text-shadow: 0 1px 2px rgba(11,16,41,.5);
  pointer-events: none; z-index: 5; opacity: 0; visibility: hidden; transition: opacity .15s, transform .15s, visibility 0s .15s; }
#prompt.on { opacity: 1; visibility: visible; transform: translate(-50%, 0); transition: opacity .15s, transform .15s; }
#prompt kbd { display: inline-grid; place-items: center; min-width: 24px; height: 24px; padding: 0 6px; border: 0; border-radius: 6px;
  background: var(--sun); color: var(--ink); font: 800 14px Rubik, sans-serif; text-shadow: none; box-shadow: inset 0 -3px 0 rgba(11,16,41,.22); }
/* a phone: the words alone and smaller; the Use button, lit, is the key (owner, 19 Oct: the full prompt was too big there) */
body.touch #prompt { padding: 3px 10px; font-size: 12px; }
body.touch #prompt kbd { height: 20px; }
/* A popup: white, the name left and the price right, plain words, then what the keys do */
#popup { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); width: min(340px, calc(100vw - 32px)); padding: 14px 16px;
  border-radius: 18px; background: #fff; color: var(--ink); box-shadow: var(--shadow); pointer-events: none; z-index: 6; }
#popup .row { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 4px; }
#popup h2 { margin: 0; font: 800 18px/1.2 Rubik, sans-serif; }
#popup .tag { font: 600 14px Inter, sans-serif; color: var(--dim-ink); text-align: right; }
#popup p { margin: 0 0 10px; font-size: 13px; white-space: pre-line; }
#popup img { display: block; max-width: 100%; max-height: 40vh; object-fit: contain; border-radius: 12px; margin-bottom: 10px; }
#popup img[hidden] { display: none; }
#popup .hint { display: flex; align-items: center; gap: 4px; white-space: pre; font: 600 13px Inter, sans-serif; color: var(--ink); }
#popup .hint:empty { display: none; }
/* Close (quiet) and Pay (sun), of equal width, each with its key on it; a phone taps them */
#popup .acts { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px; margin-top: 10px; }
#popup .acts button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; padding: 0 12px;
  border: 0; border-radius: 12px; font: 600 15px Rubik, sans-serif; color: var(--ink); cursor: pointer; pointer-events: auto; }
#popup .acts button[hidden] { display: none; }
#popup .acts .quiet { background: var(--soft); }
#popup .acts .main { background: var(--sun); }
body.touch #popup .acts kbd { display: none; }
/* The heart: H, or a tap (it alone takes touches; the popup lies over the touch controls for it) */
#popup .save { flex: none; width: 48px; height: 48px; margin: -12px -10px -12px 0; border: 0; background: none; color: #e0245e;
  font-size: 26px; cursor: pointer; pointer-events: auto; }
body.touch #popup { z-index: 8; }
#popup.hidden { display: none; }
#popup:not(.hidden) { animation: popup-in .15s ease-out; }
@keyframes popup-in { from { opacity: 0; transform: translate(-50%, 8px); } }
/* the button Enter presses: a navy ring, as the sun one vanishes on the sun button */
#popup button:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
@media (hover: hover) { #popup .acts button:hover { filter: brightness(.95); } }
#dim, #fade { position: fixed; inset: 0; opacity: 0; pointer-events: none; transition: opacity .5s; }
#dim { background: rgba(4,6,22,.68); z-index: 4; }
#fade { background: #000; z-index: 8; display: grid; place-items: center; text-align: center;
  white-space: pre-line; font-size: 18px; }
#dim.on, #fade.on { opacity: 1; }
/* The developer's keys, the HUD line and stats for nerds: staff only (body.dev-tools, src/ui/menu.js) */
body:not(.dev-tools) .dev-only, body:not(.dev-tools) #hud, body:not(.dev-tools) #stats { display: none; }
/* Showcase mode (body.showcase, src/ui/menu.js): what needs an account goes */
body.showcase .not-showcase { display: none !important; }
/* The access screen (showcase and the edit link ?edit, not logged in): only the login, no menu, no sign-up */
body.access #overlay .side, body.access #forgot { display: none !important; }
#hud { position: fixed; left: 12px; bottom: 12px; font: 12px ui-monospace, monospace;
  color: var(--dim); background: rgba(0,0,0,.35); padding: 6px 9px; border-radius: 6px; pointer-events: none; z-index: 5; }
/* Marking (M, src/ui/marks.js): the button in the developer's corner, the layer that takes the clicks, the panel */
#mark-btn { position: fixed; left: max(12px, env(safe-area-inset-left)); top: max(12px, env(safe-area-inset-top)); min-width: 48px; min-height: 48px;
  padding: 0 12px; border: 0; border-radius: 12px; background: var(--float); color: #fff; font: 600 14px Rubik, sans-serif; z-index: 5; }
body.touch #mark-btn kbd { display: none; }
#compass { position: fixed; left: calc(max(12px, env(safe-area-inset-left)) + 96px); top: max(12px, env(safe-area-inset-top)); width: 48px; height: 48px;
  border-radius: 50%; background: var(--float); pointer-events: none; z-index: 5; }
#compass::after { content: ''; position: absolute; left: 21px; top: -4px; border: 3px solid transparent; border-bottom: 5px solid var(--sun); }   /* where you face */
#compass .dial { position: absolute; inset: 0; font: 700 11px/1 Rubik, sans-serif; color: #fff; }
#compass .dial > * { position: absolute; width: 14px; text-align: center; font-weight: 700; }
#compass b { left: 17px; top: 4px; color: var(--sun); }
#compass .e { right: 3px; top: 18px; } #compass .s { left: 17px; bottom: 4px; } #compass .w { left: 3px; top: 18px; }
#marks-layer { position: fixed; inset: 0; width: 100%; height: 100%; cursor: crosshair; touch-action: none; z-index: 7; }
#marks { position: fixed; left: max(12px, env(safe-area-inset-left)); top: max(12px, env(safe-area-inset-top)); width: min(340px, calc(100% - 24px));
  display: grid; gap: 8px; padding: 12px; border-radius: 16px; background: #fff; color: var(--ink); box-shadow: var(--shadow); font: 500 14px Inter, sans-serif; z-index: 8; }
#marks p { margin: 0; color: var(--dim-ink); }
#marks textarea { padding: 8px; border: 1px solid var(--soft); border-radius: 10px; font: 500 15px Inter, sans-serif; resize: vertical; }
#marks pre { margin: 0; max-height: 120px; overflow: auto; font: 12px ui-monospace, monospace; }
#marks pre:empty { display: none; }
#marks .acts { display: flex; gap: 8px; }
#marks .acts button { flex: 1; min-height: 48px; border: 0; border-radius: 12px; background: var(--soft); color: var(--ink); font: 600 14px Rubik, sans-serif; cursor: pointer; }
#marks .acts .main { background: var(--sun); }
#marks.hidden, #marks-layer.hidden { display: none; }
/* The music disc (L or the disc button, ui/disc.js): a white card at the top middle, clear of the joystick, the
   buttons and the row on top; its list scrolls. Hidden while the menu is up (it comes back with Continue). */
#disc { position: fixed; left: 50%; top: max(12px, env(safe-area-inset-top)); transform: translateX(-50%); width: min(320px, calc(100% - 24px));
  max-height: calc(100dvh - 24px); display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto auto auto; gap: 8px; padding: 12px;
  border-radius: 16px; background: #fff; color: var(--ink); box-shadow: var(--shadow); font: 500 14px Inter, sans-serif; z-index: 8; }
body.touch #disc { top: calc(64px + env(safe-area-inset-top)); max-height: calc(100dvh - 72px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }
#disc.hidden, #overlay:not(.hidden) ~ #disc { display: none; }
#disc .head { display: flex; align-items: center; gap: 12px; }
#disc .head b { font: 800 18px/1.2 Rubik, sans-serif; }
#disc-list { display: grid; gap: 6px; overflow: auto; }
#disc button { min-height: 48px; padding: 0 12px; border: 0; border-radius: 12px; background: var(--soft); color: var(--ink); font: 600 15px Rubik, sans-serif; cursor: pointer; }
#disc-list button { display: grid; justify-items: start; padding: 6px 12px; text-align: left; line-height: 1.3; }
#disc-list button span { font: 500 12px Inter, sans-serif; color: var(--dim-ink); }
/* the song playing: a navy edge on the left (the one sun is Play) */
#disc-list button[aria-current] { box-shadow: inset 3px 0 0 var(--navy); background: #dde2ee; }
#disc .acts { display: grid; grid-template-columns: 1fr 2fr 1fr; gap: 8px; }
#disc .acts .main { background: var(--sun); }
#disc p { margin: 0; color: var(--dim-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#disc label { font: 600 12px Inter, sans-serif; color: var(--dim-ink); }
#disc input[type=range] { width: 100%; min-height: 32px; accent-color: var(--navy); }
#disc kbd { display: inline-block; margin-left: 4px; min-width: 22px; padding: 1px 6px; border: 0; border-radius: 6px; background: #fff; color: var(--ink);
  font: 800 12px/20px Rubik, sans-serif; box-shadow: inset 0 0 0 1px rgba(11,16,41,.28), inset 0 -2px 0 rgba(11,16,41,.22); }
body.touch #disc kbd { display: none; }
@media (hover: hover) { #disc button:hover { filter: brightness(.95); } }
#disc button:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
/* Stats for nerds (N or ?stats): one box per section from the top left, in as many columns as the height needs.
   The height stops above the HUD line. */
#stats { position: fixed; left: 12px; right: 12px; top: 12px; height: calc(100% - 70px); column-width: 290px;
  column-gap: 6px; column-fill: auto; font: 11px/1.35 ui-monospace, monospace; pointer-events: none; z-index: 5; }
#stats.hidden { display: none; }
#stats div { margin-bottom: 6px; padding: 5px 8px; border-radius: 6px; background: rgba(0,0,0,.6);
  white-space: pre-wrap; overflow-wrap: anywhere; break-inside: avoid; }
#stats b { display: block; color: var(--accent); break-after: avoid; }

/* Edit mode (?edit): a bar along the top and a panel down the right, as in a design tool. Desktop only. Navy like the
   main menu (DESIGN.md): its buttons, its labels, Save the one sun.
   --edit-side and --edit-bar are read by edit.js too: the room is drawn in the middle of what they leave free. */
#edit { position: fixed; inset: 0; z-index: 11; pointer-events: none; --edit-side: 320px; --edit-bar: 56px; font-size: 14px; color: #fff; }
#edit.hidden { display: none; }
body.free-mouse #crosshair { display: none; }   /* the cursor points now */
#edit-bar, #edit-side { pointer-events: auto; background: var(--navy); }
#edit-bar { position: absolute; left: 0; right: 0; top: 0; height: var(--edit-bar); display: flex; align-items: center; gap: 8px; padding: 0 12px; box-shadow: var(--shadow); }
#edit-bar > b { margin-right: 12px; font: 800 18px/1.2 Rubik, sans-serif; white-space: nowrap; }
#edit-bar .space { flex: 1; }
#edit-bar .group { display: flex; align-items: center; gap: 6px; font: 600 12px Inter, sans-serif; color: rgba(255,255,255,.7); }
#edit-side { position: absolute; right: 0; top: var(--edit-bar); bottom: 0; width: var(--edit-side); overflow: auto; padding: 4px 14px 16px; }
#edit h3 { margin: 18px 0 8px; font: 600 12px Inter, sans-serif; color: rgba(255,255,255,.7); }
#edit p { margin: 0; color: rgba(255,255,255,.75); }
#edit-name { display: block; margin-bottom: 6px; font: 800 18px/1.2 Rubik, sans-serif; }
#edit-what { margin: 0 0 10px; font-size: 13px; }
/* the menu's button on navy: white at 10%, hover sun with a 2 px lift, pressed a shade darker */
#edit button { min-height: 48px; padding: 0 12px; border: 0; border-radius: 12px; background: rgba(255,255,255,.1); color: #fff;
  font: 600 15px Rubik, ui-sans-serif, system-ui, sans-serif; cursor: pointer; white-space: nowrap;
  transition: background .15s, transform .15s, box-shadow .15s; }
/* the bar's buttons wrap their words rather than run off the right edge (Save went out of sight at 1280 px) */
#edit-bar button { white-space: normal; line-height: 1.15; }
#edit button:focus-visible { background: var(--sun); color: var(--ink); transform: translateY(-2px); box-shadow: 0 4px 10px rgba(11,16,41,.35); }
@media (hover: hover) { #edit button:hover:not(:disabled) { background: var(--sun); color: var(--ink); transform: translateY(-2px); box-shadow: 0 4px 10px rgba(11,16,41,.35); }
  #edit-list .row:hover, #edit-back .row:hover { background: rgba(255,255,255,.08); } }
#edit button:active:not(:disabled) { filter: brightness(.9); transform: none; box-shadow: none; }
#edit button:disabled { opacity: .6; cursor: default; }
#edit kbd { margin-left: 4px; }
#edit .tools { display: flex; gap: 8px; margin-bottom: 8px; }
#edit .tools button { flex: 1; }
#edit-remove { width: 100%; }
#edit .row { display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 4px 8px; border-radius: 12px; cursor: pointer; }
/* Add: a card per object, its picture and its name, like All places' cards in the menu */
#edit-add { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; }
#edit #edit-add button { display: flex; flex-direction: column; gap: 4px; padding: 8px; white-space: normal; font-size: 13px; line-height: 1.3; text-align: center; }
#edit-add img { width: 100%; aspect-ratio: 1; border-radius: 8px; object-fit: cover; }
#edit-add-doors { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; }
#edit #edit-add-doors button { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 8px; white-space: normal; font-size: 13px; line-height: 1.3; text-align: center; }
#edit #edit-add-doors button[aria-pressed=true] { background: #fff; color: var(--ink); }
#edit-add-doors canvas { height: 96px; border-radius: 4px; }
#edit-door-remove { width: 100%; }
#edit .pick { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 13px; color: rgba(255,255,255,.75); }
#edit .pick select { flex: 1; min-height: 48px; padding: 0 10px; border: 0; border-radius: 12px; background: rgba(255,255,255,.1); color: #fff; font: inherit; }
#edit .pick select option { color: var(--ink); }
/* the chosen row: as the menu's chosen button, a white edge on the left (the one sun is Save) */
#edit .row.chosen { background: rgba(255,255,255,.16); box-shadow: inset 3px 0 0 #fff; }
#edit .row button { margin-left: auto; flex: none; min-height: 40px; }
#edit-list:empty::after { content: 'Nothing here can be moved.'; color: rgba(255,255,255,.75); }
#edit #edit-save { min-width: 96px; background: var(--sun); color: var(--ink); }
/* a room shut to visitors, and Fly inside while on: white, as the menu's chosen button */
#edit #edit-close.warn, #edit #edit-fly[aria-pressed=true] { background: #fff; color: var(--ink); }
#edit-note { margin-top: 18px; min-height: 1.5em; font-weight: 600; }
#edit .tips { margin-top: 12px; font-size: 12px; }
/* over the chosen object, placed by edit.js every frame: see-through navy, as whatever floats over the room */
#edit-float { position: absolute; left: 0; top: 0; display: flex; gap: 4px; padding: 4px; border-radius: 12px; background: var(--float); backdrop-filter: blur(4px); pointer-events: auto; }
#edit-float[hidden] { display: none; }
#edit-why { position: absolute; left: 0; top: 0; max-width: 280px; padding: 6px 10px; border-radius: 8px; background: #b91c1c; color: #fff; font-size: 13px; pointer-events: none; }
#edit-why[hidden] { display: none; }
#edit #edit-float button { min-width: 40px; min-height: 40px; padding: 0; font-size: 16px; }
@media (prefers-reduced-motion: reduce) { #edit button { transition: none; } }

/* ── Touch screens ───────────────────────────────────────────
   Which help text the start screen shows is decided by the device (finger or mouse).
   The controls themselves appear once the start screen has been tapped: body.touch, set in src/player/touch.js. */
html, body { overscroll-behavior: none; }
.touch-only { display: none; }
@media (hover: none) and (pointer: coarse) {
  .touch-only { display: revert; }
  .keys.touch-only { display: grid; }
  .mouse-only { display: none; }
}
#touch { display: none; position: fixed; inset: 0; z-index: 7; touch-action: none;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
body.touch #touch { display: block; }
body.touch #hud { bottom: auto; top: calc(8px + env(safe-area-inset-top)); left: calc(8px + env(safe-area-inset-left)); font-size: 10px; }
/* Mark and the compass under the HUD line, not over it (30 Oct) */
body.touch #mark-btn, body.touch #compass { top: calc(36px + env(safe-area-inset-top)); }
/* below the HUD (two lines on a narrow phone), above the joystick and buttons */
body.touch #stats { left: calc(8px + env(safe-area-inset-left)); right: calc(8px + env(safe-area-inset-right));
  top: calc(92px + env(safe-area-inset-top)); column-width: 170px; font-size: 10px;
  height: calc(100% - 92px - 225px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }
body.touch #stats div { break-inside: auto; }   /* a short phone screen needs sections split across columns */
body.touch #popup { width: 300px; bottom: calc(8px + env(safe-area-inset-bottom)); }   /* between the joystick and the buttons, under the dot */
/* Button size and Button opacity (Options, ui/menu.js) set --btn-scale and --btn-opacity on #touch */
#touch { --btn-scale: 1; --btn-opacity: 1; --btn: calc(64px * var(--btn-scale)); }
#stick { position: absolute; left: calc(90px + env(safe-area-inset-left)); top: calc(100% - 110px - env(safe-area-inset-bottom));
  width: calc(110px * var(--btn-scale)); height: calc(110px * var(--btn-scale)); margin: calc(-55px * var(--btn-scale)) 0 0 calc(-55px * var(--btn-scale)); border-radius: 50%; pointer-events: none;
  background: var(--float); opacity: .45; }
#stick.held { opacity: 1; }
#knob { position: absolute; left: 50%; top: 50%; width: calc(48px * var(--btn-scale)); height: calc(48px * var(--btn-scale)); margin: calc(-24px * var(--btn-scale)) 0 0 calc(-24px * var(--btn-scale));
  border-radius: 50%; background: rgba(255,255,255,.5); }
/* The run target above the joystick: shown while the thumb is down, lit while running is locked. */
#sprint { position: absolute; left: 50%; bottom: calc(100% + 40px); transform: translateX(-50%); padding: 6px 10px; border-radius: 999px;
  background: var(--float); color: #fff;
  font: 600 11px Rubik, ui-sans-serif, system-ui, sans-serif; opacity: 0; }
#stick.held #sprint { opacity: 1; }
#stick.sprint { opacity: 1; }
#stick.sprint #sprint { opacity: 1; background: var(--sun); color: var(--ink); }
/* A room the admin has shut while he edits it (world/room.js): over everything, the menu too. Not in Edit mode. */
#closed { display: none; z-index: 19; }   /* its look: error.css */
body.room-closed:not(.free-mouse) #closed { display: grid; }
/* A phone held upright: ask for landscape (Android turns by itself when the page may lock the screen). */
#rotate { display: none; position: fixed; inset: 0; z-index: 20; place-items: center; background: var(--navy); color: #fff;
  font: 600 18px Rubik, ui-sans-serif, system-ui, sans-serif; }
@media (orientation: portrait) { body.touch #rotate { display: grid; } }
#buttons { position: absolute; right: calc(16px + env(safe-area-inset-right)); bottom: calc(22px + env(safe-area-inset-bottom));
  display: grid; grid-template-columns: var(--btn) var(--btn); gap: 12px; }
/* round on a phone (owner, 15 Oct 2026: DESIGN.md, "Shapes") */
#touch button { width: var(--btn); height: var(--btn); border: 0; border-radius: 50%; background: var(--float); backdrop-filter: blur(4px);
  opacity: var(--btn-opacity);
  color: #fff; font: 600 13px Rubik, ui-sans-serif, system-ui, sans-serif;
  touch-action: none; -webkit-tap-highlight-color: transparent; }
#touch button:active { background: rgba(27,42,99,.95); }
/* pause and, left of it, the gear (straight to Options): 48 px, whatever Button size says, 8 px apart */
#touch #btn-pause, #touch #btn-gear { position: absolute; top: calc(8px + env(safe-area-inset-top)); right: calc(12px + env(safe-area-inset-right));
  width: 48px; height: 48px; }
#touch #btn-gear { right: calc(68px + env(safe-area-inset-right)); font-size: 20px; }
/* the music disc (ui/disc.js), left of the gear */
#touch #btn-disc { position: absolute; top: calc(8px + env(safe-area-inset-top)); right: calc(124px + env(safe-area-inset-right)); width: 48px; height: 48px; font-size: 20px; }
/* staff only (.dev-only): F on a phone, left of the disc; sun while flying, when Jump goes up and Crouch down */
#touch #btn-fly { position: absolute; top: calc(8px + env(safe-area-inset-top)); right: calc(180px + env(safe-area-inset-right)); width: 48px; height: 48px; }
body.flying #touch #btn-fly { background: var(--sun); color: var(--ink); opacity: 1; }
#buttons #btn-jump, #buttons #btn-crouch { grid-column: 2; }
#touch #btn-crouch[aria-pressed="true"] { background: var(--sun); color: var(--ink); opacity: 1; }
/* Use lights up sun while something is aimed at (world/hotspots.js): the phone's prompt */
#touch #btn-use { transition: background .15s, color .15s, box-shadow .15s; }
#touch #btn-use.ready { background: var(--sun); color: var(--ink); box-shadow: 0 0 0 4px rgba(255,194,26,.35); opacity: 1; }
/* one fewer, one more: only while a popup sells pieces (has-count, world/hotspots.js) */
#buttons #btn-less, #buttons #btn-more { display: none; font-size: 26px; }
body.has-count #buttons #btn-less, body.has-count #buttons #btn-more { display: block; }
/* The connection (world/booking.js, docs/PAGE.md "Errors"): dropped, a spinner over the room and the player stands
   still; slow answers, the spinner alone and small at the top middle (free on a phone: the developer line is top
   left, pause top right). */
#reconnect { position: fixed; z-index: 40; display: none; align-items: center; justify-content: center; gap: 12px; pointer-events: none;
  color: #fff; font: 600 16px Rubik, ui-sans-serif, system-ui, sans-serif; }
#reconnect i { width: 32px; height: 32px; border: 3px solid rgba(255,255,255,.25); border-top-color: var(--sun); border-radius: 50%; animation: spin 1s linear infinite; }
body.net-down #reconnect { display: flex; inset: 0; background: rgba(11,16,41,.6); }
body.net-slow:not(.net-down) #reconnect { display: flex; left: 50%; top: max(8px, env(safe-area-inset-top)); transform: translateX(-50%);
  padding: 6px; border-radius: 50%; background: var(--float); }
body.net-slow:not(.net-down) #reconnect i { width: 18px; height: 18px; border-width: 2px; }
body.net-slow:not(.net-down) #reconnect span { display: none; }
@keyframes spin { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) { #reconnect i { animation-duration: 3s; } }
