/* Written for Rolehack by Lucas Ruiz, 2026-09-26.
   The web page's terminal: the case, keycaps, glass and popups.  Keycap and
   case recipes are the "Rolehack Terminal Mode" design canvas's; sizes in
   #case and #keys are design dp (classic scales the layers as a whole; twin
   banks, data-ui="twin", lay them out in CSS px with no scale). */

@font-face { font-family: 'VT323'; src: url('fonts/VT323-Regular.ttf') format('truetype'); font-display: swap; }
/* the message band's face: the Braille Institute's, made to be told apart at a glance */
@font-face { font-family: 'Atkinson Hyperlegible Next'; src: url('fonts/AtkinsonHyperlegibleNext-Variable.ttf') format('truetype');
             font-weight: 200 800; font-display: swap; }
@font-face { font-family: 'Plex Condensed'; src: url('fonts/IBMPlexSansCondensed-SemiBold.ttf') format('truetype');
             font-weight: 600; font-display: swap; }

:root {
  --capfont: 'Plex Condensed', 'Arial Narrow', sans-serif;
  --screenfont: 'VT323', 'Cascadia Mono', Consolas, monospace;
  --msgfont: 'Atkinson Hyperlegible Next', system-ui, sans-serif;
  --case-top: #e8dfc8; --case-bot: #d5c9ab;
  --hood-top: #3a322b; --hood-bot: #221d19;
  --well-top: #171411; --well-bot: #241f1b;
  --lip-text: #c9bea6; --well-shade: rgba(0,0,0,.7);
  --phos: #d7e3d0; --phos-dim: #8c9a88;
  --glass: #090d0a;
  /* the windows' keycaps (RhTheme CAP_DARK, and CAP_AMBER for the one that accepts):
     top face light/dark, skirt left/mid/right, legend, skirt legend */
  --cap-t1: #4b443e; --cap-t2: #35302b; --cap-sl: #3b3530; --cap-sm: #2c2723; --cap-sr: #1b1815;
  --cap-lg: #f1e8d5; --cap-hold: #f2a64a;
  --amb-t1: #f8b457; --amb-t2: #e38a26; --amb-sl: #e59633; --amb-sm: #c9761c; --amb-sr: #9f5b12;
  --amb-lg: #2a1503; --amb-hold: #fff3dc;
}
:root[data-skin="light"] {
  --hood-top: #aaa18c; --hood-bot: #968d79;
  --well-top: #958c78; --well-bot: #a39a86;
  --lip-text: #3b342b; --well-shade: rgba(0,0,0,.4);
}
:root[data-skin="gamecube"] {
  --case-top: #3b40a0; --case-bot: #2a2d7c;
  --hood-top: #23265e; --hood-bot: #171941;
  --well-top: #15173f; --well-bot: #1f2257;
  --lip-text: #b9bdf0;
  /* GC_DARK and GC_ORANGE */
  --cap-t1: #4a4c6e; --cap-t2: #34365a; --cap-sl: #3a3c62; --cap-sm: #2b2d4f; --cap-sr: #1a1b36;
  --cap-lg: #eef0ff; --cap-hold: #ffd21f;
  --amb-t1: #ffa347; --amb-t2: #ff6f00; --amb-sl: #f07000; --amb-sm: #d45a00; --amb-sr: #9c3f00;
  --amb-lg: #2a1000; --amb-hold: #fff0dc;
}
:root[data-phosphor="amber"] { --phos: #f5a93a; --phos-dim: #9c6a22; }
:root[data-phosphor="green"] { --phos: #52e472; --phos-dim: #2c8c46; }
:root[data-phosphor="white"] { --phos: #cdd4e0; --phos-dim: #7d8698; }

* { box-sizing: border-box; }
/* The root never overscrolls: a scroll that chains out of a list (the history,
   a window's body, a panel) must not pull the page to a refresh or swipe it
   back, under a game in progress (the review, 2026-10-08). */
html, body { margin: 0; height: 100%; overflow: hidden; background: #0c0b0a; overscroll-behavior: none; }
body { font-family: var(--capfont); color: #f1e8d5; -webkit-tap-highlight-color: transparent;
       user-select: none; -webkit-user-select: none; touch-action: none; }

#app { position: fixed; inset: 0; }
/* Twin banks take the window's size from this root (overlay.js watchTwin):
   the small viewport, which keeps still while a browser's toolbar comes and
   goes, so no key moves under a thumb for it.  While the setting is twin
   banks, a window that falls back to classic included. */
:root[data-svh] #app { inset: auto; left: 0; top: 0; width: 100%; height: 100vh; height: 100svh; }
/* the safe-area insets, read from its padding (overlay.js safeInsets) */
#insetprobe { position: fixed; left: 0; top: 0; width: 0; height: 0; visibility: hidden; pointer-events: none;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px); }
.layer { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
/* the case under the glass; caseless, the wells over a map that fills the window */
#case { z-index: 0; } #glass { z-index: 1; } #keys { z-index: 2; }
:root[data-case="off"] #case { z-index: 1; }
:root[data-case="off"] #glass { z-index: 0; }

/* ---- the case */
#case { background: linear-gradient(180deg, var(--case-top), var(--case-bot));
        box-shadow: inset 0 1px 0 rgba(255,255,255,.5), inset 0 -2px 0 rgba(0,0,0,.2); }
#case .well { position: absolute; border-radius: 8px;
  background: linear-gradient(180deg, var(--well-top) 0%, var(--well-bot) 100%);
  box-shadow: inset 0 2px 6px var(--well-shade), inset 0 -1px 0 rgba(255,255,255,.06), 0 1px 0 rgba(255,255,255,.35); }
#case .hood { position: absolute; border-radius: 12px;
  background: linear-gradient(180deg, var(--hood-top) 0%, var(--hood-bot) 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 -2px 0 rgba(0,0,0,.35), 0 2px 0 rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.35); }
#case .lip { position: absolute; display: flex; align-items: center; justify-content: space-between; padding: 0 22px; }
.lamps { display: flex; gap: 14px; align-items: center; font-size: 8px; font-weight: 600; letter-spacing: .12em; color: var(--lip-text); }
.lamps span { display: flex; align-items: center; gap: 5px; }
.lamps i { width: 7px; height: 7px; border-radius: 50%; box-shadow: inset 0 1px 1px rgba(0,0,0,.6); }
.lamps .search i { background: #4a3413; } .lamps .search.on i { background: #ffb347; box-shadow: 0 0 6px #ffb347, 0 0 2px #ffd9a0; }
.lamps .armed i { background: #4a1712; }  .lamps .armed.on i { background: #ff5a44; box-shadow: 0 0 6px #ff5a44, 0 0 2px #ffc2b8; }
.lamps .more i { background: #173a1d; }   .lamps .more.on i { background: #6dff7a; box-shadow: 0 0 6px #6dff7a, 0 0 2px #c9ffd0; }
.plate { display: flex; align-items: center; gap: 6px; padding: 2px 8px; border-radius: 3px;
         background: linear-gradient(180deg, #2b2a28 0%, #0e0d0c 100%); box-shadow: 0 0 0 1px #8d8a80, inset 0 1px 0 rgba(255,255,255,.2); }
.plate b { font-size: 9px; letter-spacing: .22em; color: #ebe4d3; }
.plate em { font-style: normal; font-weight: 700; font-size: 9px; letter-spacing: .06em; color: #e8763d; }
/* caseless: translucent wells over a full-screen map, the lamps on a pill */
:root[data-case="off"] #case { background: transparent; box-shadow: none; pointer-events: none; }
:root[data-case="off"] #case .well { background: rgba(23,20,17,.65); box-shadow: 0 0 0 1px rgba(255,255,255,.2); pointer-events: auto; }
:root[data-case="off"] #case .hood { display: none; }
:root[data-case="off"] #case .lip { justify-content: center; }
:root[data-case="off"] #case .lip .lamps { padding: 3px 10px; border-radius: 8px; background: rgba(7,6,5,.7); color: #d9d1bd; }
:root[data-case="off"] #case .lip .plate { display: none; }
/* twin banks: a bank's well reaches as far as its guard halo, 12 dp round the
   keys, and its rim is the halo's edge (the design's section 6) */
#case .well.twin { border-radius: 14px;
  box-shadow: inset 0 2px 6px var(--well-shade), inset 0 -1px 0 rgba(255,255,255,.06),
              0 1px 0 rgba(255,255,255,.35), 0 0 0 1.5px rgba(0,0,0,.22); }

/* ---- the glass */
#glass { position: absolute; overflow: hidden; background: #000;
         box-shadow: 0 0 0 3px #110e0c, 0 0 0 4px rgba(255,255,255,.07); }
:root[data-case="off"] #glass { box-shadow: none; }
#map { position: absolute; left: 0; top: 0; image-rendering: pixelated; touch-action: none; cursor: crosshair; }
#bands { position: absolute; pointer-events: none; font-family: var(--screenfont); color: var(--phos); }
#msgband { position: absolute; left: 0; right: 0; top: 0; background: var(--glass); pointer-events: auto;
           box-sizing: border-box; overflow: hidden;
           padding: 5px 10px 4px; line-height: 1.23; text-shadow: 0 0 3px color-mix(in srgb, var(--phos) 50%, transparent); }
/* the rows are broken by web.js (wrapRows), so the page it counts is the page shown */
#msgband .r { white-space: pre; overflow: hidden; }
:root[data-case="off"] #msgband { background: rgba(7,10,8,.78); }
#msgband .old { color: var(--phos-dim); }
/* the last row's right end: --More--, or with the pause off how many went by */
#msgband .slot { position: absolute; }
#msgband .more { color: #ffb347; }
#msgband .moreprompt { color: #090d0a; background: #ffb347; padding: 0 4px; text-shadow: none; }
/* a question stands out from the messages: amber, inverted, a size up */
#msgband .ask { padding: 0 3px; border-radius: 2px; color: #090d0a; background: #ffb347; text-shadow: none; }
#statband { position: absolute; left: 0; right: 0; bottom: 0; background: rgba(9,13,10,.6); padding: 3px 10px 4px;
            white-space: pre; text-shadow: 0 0 2.5px color-mix(in srgb, var(--phos) 45%, transparent); }
#statband .row { display: flex; align-items: center; height: var(--line); }
#statband .title { position: relative; }
#statband .hpbar { position: absolute; left: -1px; top: 0; bottom: 0; overflow: hidden; white-space: pre; }
#statband .hpbar span { display: inline-block; color: var(--glass); text-shadow: none; padding-left: 1px; }
#statband .badges { margin-left: auto; display: flex; gap: 4px; }
#statband .badge { padding: 0 3px; text-shadow: none; }
/* a style per tier, so it reads without colour (web.js TIER_STYLE; RhBadges.style) */
#statband .badge.framed { background: var(--bc); color: var(--bf); font-weight: bold;
                          box-shadow: inset 0 0 0 1px var(--bc), inset 0 0 0 2.2px var(--bf); }
#statband .badge.solid { background: var(--bc); color: var(--bf); }
#statband .badge.outline { color: var(--bc); box-shadow: inset 0 0 0 1.2px var(--bc); }
#statband .badge.plain { color: var(--bc); }
#statband .hpcrit { color: var(--glass); text-shadow: none; padding: 0 1px; }
#chips { position: absolute; left: 10px; right: 10px; display: flex; flex-wrap: wrap; gap: 6px; pointer-events: none; }
/* Twin banks: each band at the layout's own rect (web.js layoutTwinGlass).
   The status band answers a tap at --More-- itself, wherever it stands.  Over
   the banks the bands leave the glass, so each is a pane of glass of its own,
   with the glass's bezel (narrower: the panes stand 6 dp apart) and its tube. */
:root[data-ui="twin"] #statband { pointer-events: auto; }
:root[data-ui="twin"] #bands[data-over] > #msgband, :root[data-ui="twin"] #bands[data-over] > #statband {
  background: var(--glass); border-radius: 6px; box-shadow: 0 0 0 2px #110e0c, 0 0 0 3px rgba(255,255,255,.07); }
:root[data-ui="twin"] #bands[data-over] > #msgband::after, :root[data-ui="twin"] #bands[data-over] > #statband::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 70%, rgba(0,0,0,.4) 100%),
    repeating-linear-gradient(180deg, rgba(0,0,0,.24) 0px, rgba(0,0,0,.24) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 3px); }
:root[data-ui="twin"][data-case="off"] #bands[data-over] > #msgband,
:root[data-ui="twin"][data-case="off"] #bands[data-over] > #statband { background: rgba(7,10,8,.78); box-shadow: none; }
:root[data-ui="twin"][data-case="off"] #bands[data-over] > *::after { display: none; }
/* Twin banks' panels, the message log and the inventory (web.js layoutPanels):
   in the glass a part of it, under its tube; out of it (#panes: the tray
   between the banks, over the banks) a pane of glass of its own, as the bands
   are over the banks.  Each scrolls on its own; a tap opens what it copies. */
#panes { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.rhpanel { position: absolute; display: flex; flex-direction: column; overflow: hidden; pointer-events: auto;
  background: var(--glass); color: var(--phos); line-height: 1.25;
  text-shadow: 0 0 3px color-mix(in srgb, var(--phos) 50%, transparent); }
.rhpanel[data-pane] { border-radius: 6px; box-shadow: 0 0 0 2px #110e0c, 0 0 0 3px rgba(255,255,255,.07); }
.rhpanel[data-pane]::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 70%, rgba(0,0,0,.4) 100%),
    repeating-linear-gradient(180deg, rgba(0,0,0,.24) 0px, rgba(0,0,0,.24) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 3px); }
:root[data-case="off"] .rhpanel { background: rgba(7,10,8,.78); }
:root[data-case="off"] .rhpanel[data-pane] { box-shadow: none; }
:root[data-case="off"] .rhpanel::after { display: none; }
.rhpanel .ptitle { flex: none; padding: 6px 10px 0; font: 600 9px var(--capfont); letter-spacing: .22em;
  text-transform: uppercase; color: var(--phos-dim); text-shadow: none; }
.rhpanel .ptitle[hidden] { display: none; }
.rhpanel .pbody { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; padding: 3px 10px 5px;
  overflow-wrap: anywhere; touch-action: pan-y; scrollbar-width: thin; scrollbar-color: var(--phos-dim) transparent; }
.rhpanel .pl { white-space: pre-wrap; color: var(--phos-dim); }
.rhpanel .pl.new { color: var(--phos); }
/* an item that wraps keeps its letter and picture by its first line */
.rhpanel .pi { display: flex; align-items: flex-start; gap: 6px; }
.rhpanel .pi .let { flex: none; min-width: .7em; }
.rhpanel .pi > span:last-child { min-width: 0; white-space: pre-wrap; }
.rhpanel .pi .cpic { width: 16px; height: 16px; margin-top: calc((1.25em - 16px) / 2); }
.rhpanel .pi .cpic.none { background: none; }
.rhpanel .ph { padding-top: 4px; color: var(--phos-dim); break-after: avoid; }
.rhpanel .ph:first-child { padding-top: 0; }
/* the inventory where the panel has room for two columns of an item's line
   or more (a monitor's tray; web.js layoutPanels): each column filled to the
   panel's foot before the next, a heading kept with its first item, no item
   split between two; a pack too long for them all scrolls sideways */
.rhpanel[data-wide] .pbody { overflow-x: auto; overflow-y: hidden; touch-action: pan-x; }
.rhpanel[data-wide] .pcols { height: 100%; columns: 26em; column-gap: 18px; column-fill: auto; }
.rhpanel[data-wide] .pcols > * { break-inside: avoid; }
/* ...and while columns run on past its right edge, that edge fades, so the
   rest of the pack is seen to be there (web.js notePlace) */
.rhpanel[data-wide][data-more] .pbody { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent); }
.rhpanel .pnote { color: var(--phos-dim); white-space: normal; }
/* the desk's key legend (web.js renderLegend): lit while the prefix waits for its key */
.rhpanel:is([data-kind="legend"], [data-kind2="legend"]) .pcols { columns: 9em; column-gap: 12px; }
.rhpanel:is([data-kind="legend"], [data-kind2="legend"]) .pi .let { min-width: 1.2em; color: var(--phos); }
.rhpanel:is([data-kind="legend"], [data-kind2="legend"]) .pi > span:last-child { color: var(--phos-dim); }
.rhpanel[data-armed] { box-shadow: 0 0 0 2px #110e0c, 0 0 0 3px rgba(255,190,80,.6); }
.rhpanel[data-armed] .ptitle { color: #ffcf6a; }
/* twin banks: choices that run past the map's bottom scroll, and only then
   take the touches between them (web.js sizeChips) */
:root[data-ui="twin"] #chips.scroll { overflow-y: auto; pointer-events: auto; touch-action: pan-y; scrollbar-width: none;
  padding-bottom: 10px; }
:root[data-ui="twin"] #chips.scroll button { touch-action: pan-y; }
/* twin banks: the MORE lamp, from the lip to the message band's right end */
#morelamp { display: none; }
:root[data-ui="twin"] #morelamp { display: block; position: absolute; right: 3px; top: 6px; width: 5px; height: 12px;
  border-radius: 2px; background: #173a1d; box-shadow: inset 0 1px 1px rgba(0,0,0,.6); pointer-events: none; }
:root[data-ui="twin"] #morelamp.on { background: #6dff7a; box-shadow: 0 0 6px #6dff7a, 0 0 2px #c9ffd0; }
/* a prompt's choices: keycaps a thumb can hit (Parhi's 9.2 mm and more), that
   press down, rather than the small pills they were (Lucas, 2026-09-27) */
#chips button { pointer-events: auto; font-family: var(--screenfont); font-size: 24px; min-width: 52px; height: 48px; padding: 0 12px;
                color: #1d0e01; background: linear-gradient(180deg, #ffc56b, #f0962a); border: 0; border-radius: 6px; cursor: pointer;
                box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 4px 0 #9f5b12, 0 6px 8px rgba(0,0,0,.45);
                transition: transform 50ms ease-out, box-shadow 50ms ease-out; touch-action: none; }
#chips button.esc { background: linear-gradient(180deg, #4b443e, #35302b); color: #f1e8d5;
                    box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 4px 0 #1b1815, 0 6px 8px rgba(0,0,0,.45); }
#chips button.pressed { transform: translateY(3px); box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 1px 0 #9f5b12, 0 2px 3px rgba(0,0,0,.4); }
#chips button.esc.pressed { box-shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 0 #1b1815, 0 2px 3px rgba(0,0,0,.4); }
#tube { position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 110% 80% at 28% 6%, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 45%),
    radial-gradient(ellipse at 50% 45%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 62%, rgba(0,0,0,.55) 100%),
    repeating-linear-gradient(180deg, rgba(0,0,0,.24) 0px, rgba(0,0,0,.24) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 3px); }
:root[data-case="off"] #tube { display: none; }

/* ---- keycaps */
#keys { pointer-events: none; }
#keys > * { pointer-events: auto; }
button.k { position: absolute; border: 0; margin: 0; padding: 0; background: transparent; cursor: pointer;
           font-family: var(--capfont); text-align: center; touch-action: none; color: inherit; outline: none; }
button.k:focus-visible { outline: 2px solid #f2a64a; outline-offset: 2px; }
.k .sh { position: absolute; left: 0; right: 0; top: 2px; bottom: 0; border-radius: var(--r);
         background: rgba(0,0,0,.55); box-shadow: 0 3px 6px rgba(0,0,0,.45); }
.k .sk { position: absolute; left: 0; top: 0; right: 0; border-radius: var(--r);
  background: linear-gradient(180deg, rgba(255,255,255,.14) 0%, rgba(255,255,255,0) 30%, rgba(0,0,0,.32) 100%),
              linear-gradient(90deg, var(--sL) 0%, var(--sM) 14%, var(--sM) 86%, var(--sR) 100%); }
.k .fr { position: absolute; left: 2px; right: 2px; font-size: 7.5px; font-weight: 700; letter-spacing: .09em;
         color: var(--hold); text-transform: uppercase; white-space: nowrap; overflow: hidden; display: flex;
         align-items: center; justify-content: center; }
.k .tp { position: absolute; border-radius: var(--fr);
  background: radial-gradient(130% 95% at 50% 15%, var(--t1) 0%, var(--t2) 85%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), inset 0 -2px 3px rgba(0,0,0,.2);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--lg); transition: transform 60ms ease-out; }
.k .lg { font-weight: 600; line-height: 1.08; letter-spacing: .05em; text-transform: uppercase; white-space: pre-line;
         max-width: 100%; }
.k.nocase .lg { text-transform: none; }
.k .rk { position: absolute; top: 2px; left: 3px; font-size: 8.5px; font-weight: 700; line-height: 1; color: var(--raw); }
/* desktop mode: a key's keyboard key in its corner (overlay.js applyLegends),
   no case taken from the key's word (^P, M-o, F); held Ctrl lights them all */
.k .rk.leg { text-transform: none; letter-spacing: .02em; }
:root[data-ctrl] .k .rk.leg { color: #ffcf6a; text-shadow: 0 0 4px rgba(255,190,80,.6); }
.k .lamp { position: absolute; top: 4px; right: 4px; width: 10px; height: 4px; border-radius: 2px; background: #4a3413;
           box-shadow: inset 0 1px 1px rgba(0,0,0,.6); }
.k .lamp.on { background: #ffb347; box-shadow: 0 0 6px #ffb347; }
/* twin banks: ARMED on the key that armed, and the pad tinted red while it is */
.k .lamp.armed { background: #4a1712; }
.k .lamp.armed.on { background: #ff5a44; box-shadow: 0 0 6px #ff5a44, 0 0 2px #ffc2b8; }
.padmold.armed .k .tp::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: rgba(255,70,50,.26); box-shadow: inset 0 0 0 1.5px rgba(255,90,68,.75); }
/* the ghost deck: the key an old spot's tap meant, lit for a moment */
.k.ghostlit .tp { box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 0 0 2px #ffb347, 0 0 12px #ffb347; }
.k.lit .lg { color: #ffc166; text-shadow: 0 0 5px rgba(255,170,60,.75); }
.k svg { display: block; }
.k.pressed .tp { transform: translateY(var(--sink)); box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 1px rgba(0,0,0,.2); }
.k.pressed .sh { top: 1px; box-shadow: 0 1px 3px rgba(0,0,0,.4); }
/* an empty pin key is a keycap like any other, its legend dimmed (RhFace: alpha 110) */
.k.ph .lg { opacity: .43; }
/* twin banks: a key's box is its hit cell, the keycap drawn inset in it
   (overlay.js Key.cell; the design's section 6).  The keycap takes no touch
   of its own: the cell does.  Hit-testable, its small boxes were what
   Chrome's touch adjustment aimed for, and a touch 2 px inside the pad's
   cell went to MSGS above it (the layers stage, 2026-10-03).  Its
   own class: .cap is the windows' keycap (capButton), whose rules would
   dress it -- their colours and a 46 px least width. */
.k > .kcap { position: absolute; display: block; pointer-events: none; }
/* a layer's place that does nothing this turn: HERE's, or a count layer's blanks */
.k.dimmed .tp { filter: brightness(.55) saturate(.35); }
.k.dimmed .lg { opacity: .45; }
/* the near-miss guard's hit areas: the halo under each bank's cells and the
   action pad's seams over its keys, invisible but for a swallow's 150 ms
   flash -- the halo's edge, or the seam -- with a light tick */
#keys > .halo, #keys > .seam { position: absolute; touch-action: none; }
#keys > .halo.flash { box-shadow: inset 0 0 0 1.5px rgba(255,179,71,.9), inset 0 0 8px rgba(255,179,71,.35); }
#keys > .seam.flash { background: rgba(255,179,71,.4); border-radius: 2px; }

/* the Rest / Long rest slot: a strip that slides sideways */
.well-slot { position: absolute; overflow: hidden; touch-action: none; }
.well-slot .strip { position: absolute; left: 0; top: 0; bottom: 0; transition: transform 140ms ease-out; }
.well-slot .strip.drag { transition: none; }
.well-slot .strip > .k { top: 0; }
.well-slot .dots { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: flex; gap: 2.5px; pointer-events: none; }
.well-slot .dots i { width: 3.6px; height: 3.6px; border-radius: 50%; background: rgba(255,255,255,.35); }
.well-slot .dots i.on { background: rgba(255,255,255,.9); }
/* twin banks: the strip stands on end, Long rest swiped up from under REST */
.well-slot.v .dots { flex-direction: column; }

/* popups over the scrim: full-size containers that only their keys make live */
#keys > .pop { position: absolute; pointer-events: none; inset: 0; }
#keys > .pop > * { pointer-events: auto; }
#keys > .pop > .wedges { pointer-events: none; }
#scrim { position: absolute; inset: 0; background: rgba(5,7,13,.62); display: none; }
#scrim.on { display: block; }
#scrim .hint { position: absolute; left: 50%; transform: translateX(-50%); padding: 3px 12px; border-radius: 99px;
               background: rgba(5,7,13,.95); color: rgba(255,255,255,.85); font-size: 9px; font-weight: 600;
               letter-spacing: .1em; white-space: nowrap; }
.lift { z-index: 10; }
.lift2 { z-index: 11; }
/* the frame and name chip round the pad while a layer is up */
#keys > .layerframe { position: absolute; display: none; pointer-events: none; box-sizing: border-box;
  border: 2px solid var(--acc); border-radius: 10px; box-shadow: 0 0 10px var(--acc); }
#keys > .layerframe.on { display: block; }
.layerframe b { position: absolute; left: 10px; top: -9px; padding: 1px 7px; border-radius: 8px; background: var(--acc);
  color: #111; font-size: 9.5px; font-weight: 700; letter-spacing: .12em; white-space: nowrap; }
/* twin banks: the layer's name on a pill inside the map, never over a key
   (the design's section 8); the frame keeps only its line */
:root[data-ui="twin"] .layerframe b { display: none; }
#keys > .layerpill { position: absolute; display: none; pointer-events: none; align-items: center; padding: 0 9px;
  border-radius: 12px; background: var(--acc); color: #111; font-size: 9.5px; font-weight: 700; letter-spacing: .12em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#keys > .layerpill.on { display: flex; }
/* desktop mode: a board that changed by itself names itself at the top of the
   map, then fades (overlay.js switchNote; Lucas, 2026-10-08) */
#keys > .switchnote { position: absolute; transform: translateX(-50%); pointer-events: none; z-index: 30;
  padding: 5px 12px; border-radius: 14px; background: rgba(12,13,11,.9); border: 1px solid rgba(255,179,71,.55);
  color: #e9e3d0; font-family: var(--msgfont); font-size: 14px; line-height: 1.2; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0,0,0,.5); transition: opacity .5s ease-out; }
#keys > .switchnote b { color: #ffc166; font-weight: 700; }
#keys > .switchnote.gone { opacity: 0; }
/* the flick key: a rubber nub standing out of the case (RhFace.drawNub) */
.k.nub .sk, .k.nub .fr, .k.nub .rk { display: none; }
.k.nub .sh { border-radius: 50%; background: rgba(0,0,0,.85); box-shadow: none; }
.k.nub .tp { border-radius: 50%; overflow: hidden;
  background: radial-gradient(circle at 32% 28%, var(--t1) 0%, var(--t2) 55%, var(--sR) 100%);
  box-shadow: 1px 4px 6px rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,255,255,.3); }
.k.nub .tp::before { content: ''; position: absolute; inset: 1px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(rgba(0,0,0,.2) 0.6px, transparent 0.9px) 0 0 / 2.6px 2.6px; }
.k.nub .lg { position: relative; }
.k.nub.pressed .tp { transform: translateY(1.5px);
  box-shadow: 1px 1.5px 3px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.15); }
.wedges { position: absolute; pointer-events: none; }
.chiprow { position: absolute; display: flex; gap: 4px; padding: 4px; background: #04070e; border-radius: 4px; }
.chiprow .k { position: relative; flex: none; }
.chiprow .k.dim { opacity: .66; }
/* the ghost deck's flash: the old key's name, and an arrow to where it went */
#keys > .ghost { position: absolute; display: none; align-items: center; gap: 4px; padding: 3px 6px 3px 10px; border-radius: 99px;
  background: rgba(5,7,13,.92); color: #ffd97a; box-shadow: 0 0 0 1.5px #ffb347; pointer-events: none;
  font: 700 11px var(--capfont); letter-spacing: .08em; white-space: nowrap; }
#keys > .ghost.on { display: flex; }
#banner { position: absolute; transform: translateX(-50%); }

/* the drawer */
#drawer { position: absolute; inset: 0; display: none; }
#drawer.on { display: block; }
#drawer .dscrim { position: absolute; inset: 0; background: rgba(2,4,9,.74); }
#drawer .panel { position: absolute; left: 50%; transform: translateX(-50%); background: #080c16;
                 border: 2px solid #fff; border-radius: 5px; display: flex; flex-direction: column; overflow: hidden; }
#drawer .title { position: relative; height: 32px; flex: none; display: flex; align-items: center; gap: 10px; padding: 0 12px;
                 background: linear-gradient(0deg, #0a1730, #1c3a68); border-bottom: 2px solid rgba(255,255,255,.5); }
#drawer .title b { font-size: 11px; letter-spacing: .06em; }
#drawer .title span { font-size: 9px; color: rgba(255,255,255,.45); }
#drawer .title .k { right: 4px; top: 3px; }
/* the grid scrolls under a drag that starts on a key (overlay.js bindDrawerScroll); the browser's own panning stays
   off so the two never scroll it at once (a key is touch-action: none anyway, so a touch on one never panned it) */
#drawer .grid { overflow-y: auto; padding: 10px; display: grid; gap: 6px; touch-action: none; scrollbar-width: thin; }
#drawer .grid .k { position: relative; }
/* a section heading: small capitals and a hairline to the right edge (RhDrawer.Heading) */
#drawer .grid .dhead { grid-column: 1 / -1; height: 20px; display: flex; align-items: flex-end; gap: 8px;
                       padding: 0 2px 4px; font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
                       color: rgba(255,255,255,.62); }
#drawer .grid .dhead::after { content: ''; flex: 1; height: 1px; margin-bottom: 4px; background: rgba(255,255,255,.2); }
#drawer .grid .dhead:not(:first-child) { margin-top: 6px; }

/* the flash */
#flash { position: absolute; padding: 2px 8px; border-radius: 99px; background: rgba(5,7,13,.92); color: #ffd97a;
         font: 700 11px var(--capfont); letter-spacing: .04em; pointer-events: none; opacity: 0;
         transition: opacity 500ms ease-in; white-space: nowrap; }
#flash.on { opacity: 1; transition: none; }

/* ---- windows (screen px).  The game's output -- menus, text, the line
   prompt -- comes up on a second monitor: the case's hood as its bezel round a
   glass like the map's, drawn the way tty draws.  The interface's own dialogs
   are a panel of the hood.  Buttons are keycaps on the bezel, with the key
   that does the same on the front skirt. */
#modal, #formwrap { position: fixed; inset: 0; background: rgba(2,4,9,.74); display: flex; align-items: center;
         justify-content: center; padding: 16px 16px calc(16px + var(--kbd-room, 0px)); z-index: 50; }
/* twin banks: the windows lift clear of the system's keyboard too (visualViewport;
   overlay.js watchTwin), which never lays the keys out again */
:root[data-ui="twin"] #modal, :root[data-ui="twin"] #formwrap {
  padding-bottom: calc(16px + max(var(--kbd-room, 0px), var(--vv-room, 0px))); }
#formwrap { z-index: 55; }
#modal[hidden], #formwrap[hidden] { display: none; }
.box { position: relative; display: flex; flex-direction: column; max-width: min(920px, 100%); max-height: 100%;
       min-width: min(440px, 100%); padding: 12px 12px 8px; border-radius: 14px;
       background: linear-gradient(180deg, var(--hood-top) 0%, var(--hood-bot) 100%);
       box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 -2px 0 rgba(0,0,0,.35), 0 0 0 1px rgba(0,0,0,.35),
                   0 14px 40px rgba(0,0,0,.65); }
.screen { position: relative; display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; overflow: hidden;
          border-radius: 7px; background: var(--glass); box-shadow: 0 0 0 3px #110e0c, 0 0 0 4px rgba(255,255,255,.07);
          font-family: var(--screenfont); color: var(--phos);
          text-shadow: 0 0 3px color-mix(in srgb, var(--phos) 50%, transparent); }
.screen::after { content: ''; position: absolute; inset: 0; pointer-events: none; border-radius: 7px;
  background:
    radial-gradient(ellipse 110% 80% at 28% 6%, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 45%),
    radial-gradient(ellipse at 50% 45%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 70%, rgba(0,0,0,.45) 100%),
    repeating-linear-gradient(180deg, rgba(0,0,0,.24) 0px, rgba(0,0,0,.24) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 3px); }
.screen .title { flex: none; padding: 10px 18px 4px; color: #ffc166; font-size: 24px; line-height: 1.1; white-space: pre-wrap; }
.screen .title[hidden] { display: none; }
.screen .body { padding: 6px 18px 12px; overflow-x: hidden; overflow-y: auto; white-space: pre-wrap; overflow-wrap: anywhere;
                font-size: 22px; line-height: 1.15;
                touch-action: pan-y; scrollbar-width: thin; scrollbar-color: var(--phos-dim) transparent; }
.screen .title:not([hidden]) + .body { padding-top: 2px; }
/* ---- the message history (web.js showHistory): the phone's screen
   (ForkFront's NHW_Text under RhDialogSkin), not a window on the bezel.  The
   whole window is the message band's glass, in the band's phosphor and face
   (web.js sets the face and size inline, as it does the band's); every kept
   message on a line of its own, and the browser scrolls it.  One keycap at
   the foot closes it; a long press on a line makes a rule.  Caseless it is
   the phone's near-opaque glass (RhDialogSkin.Glass, 0xf2090d0a), not the
   band's smoked one: a whole window of the map showing through would not
   read. */
#msglog { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column;
          background: var(--glass); color: var(--phos);
          text-shadow: 0 0 3px color-mix(in srgb, var(--phos) 50%, transparent);
          /* The lines, the hint and the key keep out of a phone's notch, corners
             and home indicator (twin banks set viewport-fit=cover, overlay.js
             setViewportFit, and lay the banks out by the same insets,
             safeInsets); the glass itself still fills the window.  The keyboard
             tray's room, while it is up, stands in for the bottom inset. */
          padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
                   max(var(--kbd-room, 0px), env(safe-area-inset-bottom, 0px)) env(safe-area-inset-left, 0px); }
:root[data-ui="twin"] #msglog {
  padding-bottom: max(var(--kbd-room, 0px), var(--vv-room, 0px), env(safe-area-inset-bottom, 0px)); }
#msglog[hidden] { display: none; }
/* the glass's tube over the text, as over the band; none caseless, as on the phone */
#msglog::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 70%, rgba(0,0,0,.4) 100%),
    repeating-linear-gradient(180deg, rgba(0,0,0,.24) 0px, rgba(0,0,0,.24) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 3px); }
#msglog .list { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; touch-action: pan-y;
                overscroll-behavior: contain;
                padding: 12px 14px; white-space: pre-wrap; overflow-wrap: anywhere;
                scrollbar-width: thin; scrollbar-color: var(--phos-dim) transparent; }
#msglog .deck { position: relative; z-index: 1;   /* over the tube: a keycap is no part of the picture */
                height: auto; padding: 8px 14px 6px; text-shadow: none;
                border-top: 1px solid color-mix(in srgb, var(--phos) 18%, transparent); }
#msglog .deck .hint { color: var(--phos-dim); }
:root[data-case="off"] #msglog { background: rgba(9,13,10,.95); }
:root[data-case="off"] #msglog::after { display: none; }
/* the band's page at the history's end is bold in weight, in the phosphor,
   under every phosphor -- the phone's ATTR_BOLD (TextAttr.style sets a bold
   StyleSpan; RhDialogSkin.glassText keeps it); the windows' tty-white bold is
   untouched.  Hyperlegible has its own 700; a mono face gets one synthesized. */
#msglog .bold { font-weight: 700; color: inherit; }
/* the history's lines: a long press (or a right click) makes a rule */
.histline { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; border-radius: 2px; }
.histline.pressing { background: color-mix(in srgb, #ffb347 22%, transparent); }

/* the bezel's deck: what to do, and the keys to do it.  The keys never move
   while a window is up: the hint (which changes -- a count, say) takes only
   the room they leave, adds nothing to the window's width, and the deck's
   height is fixed. */
.deck { flex: none; display: flex; align-items: center; gap: 12px; height: 54px; padding: 10px 2px 0; }
.deck .hint { flex: 1 1 0; min-width: 0; contain: inline-size; max-height: 2.6em; overflow: hidden; line-height: 1.3;
              font: 600 9px/1.3 var(--capfont); letter-spacing: .12em; text-transform: uppercase; color: var(--lip-text); }
.deck .hint.count { color: #ffb347; font-size: 11px; }
.deck .caps { flex: none; display: flex; gap: 8px; margin-left: auto; }

/* a keycap laid out in a row (RhFace.drawKeycap's recipe): the skirt is the
   button, the top face its span; pressed, the face drops */
.cap { --t1: var(--cap-t1); --t2: var(--cap-t2); --sl: var(--cap-sl); --sm: var(--cap-sm); --sr: var(--cap-sr);
       --lg: var(--cap-lg); --hold: var(--cap-hold);
       position: relative; flex: none; border: 0; margin: 0 0 2px; padding: 2px 3px 10px; border-radius: 6px; cursor: pointer;
       background: linear-gradient(180deg, rgba(255,255,255,.14) 0%, rgba(255,255,255,0) 30%, rgba(0,0,0,.32) 100%),
                   linear-gradient(90deg, var(--sl) 0%, var(--sm) 14%, var(--sm) 86%, var(--sr) 100%);
       box-shadow: 0 2.5px 0 rgba(0,0,0,.55), 0 3px 6px rgba(0,0,0,.45);
       font: 600 13px var(--capfont); letter-spacing: .05em; text-transform: uppercase; color: var(--lg);
       touch-action: manipulation; outline: none; }
.cap.amber { --t1: var(--amb-t1); --t2: var(--amb-t2); --sl: var(--amb-sl); --sm: var(--amb-sm); --sr: var(--amb-sr);
             --lg: var(--amb-lg); --hold: var(--amb-hold); }
.cap > span { display: block; min-width: 46px; padding: 7px 12px 6px; border-radius: 5px; white-space: nowrap;
              background: radial-gradient(130% 95% at 50% 15%, var(--t1) 0%, var(--t2) 85%);
              box-shadow: inset 0 1px 0 rgba(255,255,255,.4), inset 0 -2px 3px rgba(0,0,0,.2); transition: transform 60ms ease-out; }
.cap > b { position: absolute; left: 3px; right: 3px; bottom: 1px; height: 9px; display: flex; align-items: center;
           justify-content: center; font-size: 7.5px; font-weight: 700; letter-spacing: .09em; color: var(--hold);
           overflow: hidden; white-space: nowrap; }
.cap.pressed { box-shadow: 0 1px 0 rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.4); }
.cap.pressed > span { transform: translateY(3px); box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 1px rgba(0,0,0,.2); }

/* character creation (web.js creationKeys, after the phone's RhCreate): keycaps
   on the bezel under the glass.  Rows wrap and centre, five to a row -- six of
   the small ones -- and three in portrait, so a window that turns re-flows by
   itself; the keys scroll if the window is short, and the glass keeps its size. */
.box.creating .screen { flex: none; }
.box.creating .screen .body { white-space: normal; }
.cline { white-space: pre-wrap; font-size: 20px; line-height: 1.25; }
.cline.mid { text-align: center; }
.chero { display: flex; justify-content: center; padding: 8px 0 6px; }
.cpic { display: block; flex: none; background: var(--sheet, url('tiles.png')) no-repeat; image-rendering: pixelated; }
.ckeys { flex: 0 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: none; margin-top: 10px;
         padding: 1px 2px 4px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.cgrid { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; max-width: calc(5 * 128px + 4 * 8px); }
.cgrid.extra { max-width: calc(6 * 112px + 5 * 8px); }
.ck { width: 128px; height: 78px; font-size: 12px; }
.ck.small { width: 112px; height: 44px; font-size: 9.5px; }
.ck.answer { width: 164px; height: 50px; }
.ck.long { font-size: 10px; }
.ck.small.long { font-size: 8.5px; }
.ck > span { position: relative; height: 100%; min-width: 0; padding: 4px 6px 3px; white-space: normal;
             display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; }
.ck i { position: absolute; left: 5px; top: 3px; font: 600 9px var(--capfont); font-style: normal;
        text-transform: none; color: var(--raw, var(--lg)); opacity: .9; }
.ck em { font-style: normal; line-height: 1.12; white-space: pre-line; text-align: center; }
@media (orientation: portrait) {
  .cgrid, .cgrid.extra { max-width: calc(3 * 124px + 2 * 8px); }
  .ck, .ck.small { width: min(124px, calc((100vw - 88px) / 3)); }
  .ck.answer { width: min(124px, calc((100vw - 88px) / 3)); }
}

/* inside the glass, as tty draws a menu */
.item { cursor: pointer; margin: 0 -8px; padding: 1px 8px; border-radius: 2px; min-height: 34px; display: flex; align-items: center; }
.item:hover { background: color-mix(in srgb, var(--phos) 9%, transparent); }
.item .let { color: var(--phos); }
/* an item is one line to the game: on a narrow screen it wraps inside its row,
   keeping the letter and picture at its left, rather than scrolling sideways */
.item > span:last-child { min-width: 0; white-space: pre-wrap; }
.item.sel { background: rgba(255,179,71,.13); }
.item.sel .let, .item.sel .mark { color: #ffb347; text-shadow: 0 0 4px rgba(255,170,60,.7); }
.mtile { display: inline-block; flex: none; width: 32px; height: 32px; margin: 1px 8px 1px 0;
         background: var(--sheet, url('tiles.png')) no-repeat; background-size: var(--menu-sheet); image-rendering: pixelated; }
.mtile.none { visibility: hidden; }
.head { padding: 8px 0 2px; }
.head:first-child { padding-top: 0; }
.bold { color: #fff; } .dim { color: var(--phos-dim); } .uline { text-decoration: underline; }
.inverse { background: var(--phos); color: var(--glass); text-shadow: none; padding: 0 4px; }
input.line { display: block; width: 100%; margin: 4px 0 2px; font: 24px var(--screenfont); color: var(--phos);
             caret-color: var(--phos); background: transparent; border: 0; padding: 2px 0 4px; outline: none; user-select: text;
             border-bottom: 1px dashed var(--phos-dim); text-shadow: inherit; }
input.line::selection { background: var(--phos); color: var(--glass); }
input.line::-webkit-calendar-picker-indicator { opacity: .45; cursor: pointer; }   /* the list's own arrow */

/* the interface's own dialogs: a panel of the hood, its name on a plate */
.panel { padding: 14px 16px 8px; }
.panel > .plate { align-self: flex-start; margin-bottom: 12px; }
.panel > .plate b { font-size: 10px; text-transform: uppercase; }
.panel > .body { overflow: auto; touch-action: pan-y; padding-right: 6px;
                 scrollbar-width: thin; scrollbar-color: var(--lip-text) transparent; }
.form { display: flex; flex-direction: column; gap: 12px; min-width: min(380px, 80vw); }
/* labels keep their own case: they quote keys, and ^Dh is not ^DH */
.form label { display: flex; flex-direction: column; gap: 6px; font: 600 11px var(--capfont); letter-spacing: .05em;
              color: var(--lip-text); }
.form input { font: 22px var(--screenfont); color: var(--phos); caret-color: var(--phos); background: var(--glass);
              border: 0; border-radius: 5px; padding: 3px 10px; outline: none; user-select: text; letter-spacing: 0;
              box-shadow: inset 0 2px 6px rgba(0,0,0,.8), 0 1px 0 rgba(255,255,255,.12);
              text-shadow: 0 0 3px color-mix(in srgb, var(--phos) 50%, transparent); }
.form .seg { display: flex; flex-wrap: wrap; gap: 6px; }
.form .seg .cap { font-size: 11px; }
.form .seg .cap > span { min-width: 0; padding: 6px 10px 5px; }
.form .note { font: 12px/1.35 var(--capfont); color: var(--lip-text); opacity: .85; }
/* a group of rows (Settings' Accessibility): a box with its name on the rim, as a drawer heading */
.form fieldset.group { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 8px 12px 12px;
                       color: var(--lip-text); border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
                       border-radius: 6px; min-width: 0; }
.form fieldset.group > legend { padding: 0 6px; font: 600 9.5px var(--capfont); letter-spacing: .16em;
                                text-transform: uppercase; color: inherit; }
.form textarea { font: 20px/1.15 var(--screenfont); color: var(--phos); caret-color: var(--phos); background: var(--glass);
                 border: 1px solid color-mix(in srgb, var(--phos) 30%, transparent); border-radius: 4px; padding: 6px 8px;
                 resize: vertical; user-select: text; letter-spacing: 0; text-transform: none; }

/* caseless: the windows float as smoked glass, like the bands over the map */
:root[data-case="off"] .box { background: rgba(7,6,5,.84); box-shadow: 0 0 0 1px rgba(255,255,255,.2), 0 14px 40px rgba(0,0,0,.65); }
:root[data-case="off"] .screen { background: rgba(9,13,10,.9); box-shadow: none; }
:root[data-case="off"] .screen::after { display: none; }
:root[data-case="off"] .deck .hint, :root[data-case="off"] .form label, :root[data-case="off"] .form .note,
:root[data-case="off"] .form fieldset.group { color: #d9d1bd; }

/* the soft keyboard: keycaps in a tray of the hood, above the windows (which
   make room for it) so it can answer them */
#kbd { position: fixed; left: 50%; bottom: 8px; transform: translateX(-50%); z-index: 56; display: none;
       width: min(680px, calc(100vw - 16px)); padding: 10px 10px 8px; border-radius: 12px;
       background: linear-gradient(180deg, var(--hood-top) 0%, var(--hood-bot) 100%);
       box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 -2px 0 rgba(0,0,0,.35), 0 0 0 1px rgba(0,0,0,.35),
                   0 8px 28px rgba(0,0,0,.6); }
#kbd.on { display: block; }
/* at the desk the dock is under the map, where the soft keyboard stands: it
   comes up at the map's top instead */
:root[data-tier="desk"] #kbd { top: 72px; bottom: auto; }
#kbd .row { display: flex; gap: 4px; justify-content: center; margin-top: 4px; }
#kbd .row:first-child { margin-top: 0; }
#kbd .cap { flex: 1 1 0; min-width: 0; padding: 2px 2px 7px; text-transform: none; font-size: clamp(10px, 2.5vw, 15px);
            letter-spacing: 0; }
#kbd .cap > span { min-width: 0; padding: 8px 0 7px; overflow: hidden; }
:root[data-case="off"] #kbd { background: rgba(7,6,5,.84); box-shadow: 0 0 0 1px rgba(255,255,255,.2), 0 8px 28px rgba(0,0,0,.6); }

#boot { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center;
        font: 20px var(--screenfont); color: #9c8f78; background: #0c0b0a; z-index: 60; }
#build { position: absolute; bottom: 14px; left: 0; right: 0; text-align: center;
         font: 14px var(--screenfont); color: #6f6553; text-decoration: none; }
#build:hover { color: #9c8f78; text-decoration: underline; }
.form .note a { color: inherit; }
/* the device report: a line to read and copy, smaller than a field to type in */
.form textarea[readonly] { font-size: 14px; line-height: 1.3; opacity: .92; }
