/* poi-lab bench — "enter the world" first-person player.
   Same TE front panel language as the bench, but as an instrument overlay:
   ink panels, cream silkscreen, one orange signal, sitting on top of the 3D. */

/* scoped to the player document only — this sheet is also loaded by the SPA
   for the portal control, and must not touch the bench's own page */
body.play {
  margin: 0; padding: 0; height: 100vh; min-height: 0;
  background: #0b1a2a; overflow: hidden;
}
body.play canvas { display: block; position: fixed; left: 0; top: 0; }
body.play > div[hidden], body.play .play-donor { display: none !important; }

/* ------------------------------------------------------------------ booting */
.pboot {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: var(--ground);
  transition: opacity .25s ease-out;
}
.pboot.is-gone { opacity: 0; pointer-events: none; }
.pboot__card {
  width: min(420px, 86vw);
  background: var(--panel); border: 1px solid var(--seam-hard); border-radius: var(--r);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .28);
}
.pboot__hd {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 12px; border-bottom: 1px solid var(--seam);
}
.pboot__bd { padding: 13px 12px 14px; display: grid; gap: 10px; }
.pboot__bar { height: 6px; background: var(--panel-3); border: 1px solid var(--seam-hard); border-radius: 2px; overflow: hidden; }
.pboot__bar i { display: block; height: 100%; width: 38%; background: var(--accent); animation: pslide 1.15s ease-in-out infinite; }
@keyframes pslide { 0% { margin-left: -40% } 100% { margin-left: 102% } }
.pboot__msg {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}

/* --------------------------------------------------------------- not playable */
.pfail { position: fixed; inset: 0; display: grid; place-items: center; padding: 22px; background: var(--ground); }
.pfail__panel { width: min(560px, 92vw); }
.pfail__reason { font-size: 14px; font-weight: 650; margin-bottom: 9px; }
.pfail__detail {
  font-family: var(--mono); font-size: 11px; background: var(--panel-2);
  border: 1px solid var(--seam); border-radius: var(--r-sm);
  padding: 8px 9px; margin: 0 0 10px; white-space: pre-wrap; word-break: break-word; color: var(--ink-2);
}
.pfail__hint { font-size: 12.5px; color: var(--ink-2); }
.pfail__hint code { font-family: var(--mono); font-size: 11.5px; background: var(--panel-2); padding: 1px 4px; border-radius: 3px; }

/* ---------------------------------------------------------------------- hud */
.phud { position: fixed; inset: 0; z-index: 20; pointer-events: none; }

.phud__cross {
  position: absolute; left: 50%; top: 50%; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%; background: rgba(255, 255, 255, .92);
  box-shadow: 0 0 0 1.5px rgba(23, 22, 20, .55), 0 0 6px rgba(0, 0, 0, .35);
}
.phud .is-hidden { display: none; }
.phud__cross.is-hidden { display: none; }

.pchip {
  background: rgba(23, 22, 20, .82); color: var(--panel);
  border: 1px solid rgba(244, 241, 234, .22); border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; padding: 6px 9px; line-height: 1.5;
}

.phud__read {
  position: absolute; left: 14px; top: 14px;
  display: grid; gap: 3px; min-width: 168px;
}
.phud__read .k { color: #a49d90; }
.phud__read .v { color: var(--panel); font-variant-numeric: tabular-nums; }
.phud__read .r { display: flex; justify-content: space-between; gap: 14px; }
.phud__title { display: flex; align-items: center; gap: 7px; }
.phud__title .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
.phud__title b { color: var(--panel); font-weight: 700; letter-spacing: .1em; }

.phud__legend {
  position: absolute; left: 14px; bottom: 14px;
  display: flex; gap: 5px; flex-wrap: wrap; max-width: 60vw;
}
.pkey {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(23, 22, 20, .82); color: #cdc7ba;
  border: 1px solid rgba(244, 241, 234, .22); border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; padding: 5px 8px;
}
.pkey b { color: var(--panel); background: rgba(244, 241, 234, .13); border-radius: 2px; padding: 1px 4px; letter-spacing: .06em; }
.pkey.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.pkey.is-on b { background: rgba(0, 0, 0, .22); color: #fff; }

.phud__read .v.is-hot { color: var(--accent); }

/* trick stamp: the big centre-screen "360!" (the in-world 3D skis replaced the
   old CSS rails — see main.js). One orange signal, briefly enormous. */
.phud__trick {
  position: absolute; left: 50%; top: 30%; transform: translateX(-50%);
  text-align: center; pointer-events: none;
}
.phud__trick[hidden] { display: none; }
.phud__trick-big {
  font-family: var(--mono); font-size: 46px; font-weight: 800; letter-spacing: .14em;
  color: var(--accent);
  text-shadow: 0 0 1.5px rgba(23, 22, 20, .9), 0 2px 14px rgba(0, 0, 0, .5);
}
.phud__trick-sub {
  margin-top: 2px;
  font-family: var(--mono); font-size: 12px; font-weight: 700; letter-spacing: .3em;
  text-transform: uppercase; color: var(--panel);
  text-shadow: 0 1px 6px rgba(0, 0, 0, .6);
}
.phud__trick.is-wipe .phud__trick-big { color: var(--p-cream); }   /* specs/0055 §1.1 */
.phud__trick.is-pop { animation: ptrick .45s cubic-bezier(.2, 1.6, .4, 1) both; }
@keyframes ptrick {
  0% { transform: translateX(-50%) scale(.4); opacity: 0; }
  100% { transform: translateX(-50%) scale(1); opacity: 1; }
}

/* rocket fuel (boost.js) — one slim bar, on screen only while it is burning or
   refilling. Bottom RIGHT: the legend owns the bottom-left and wraps to two or
   three rows as keys are added, so anything centred there eventually collides
   with it. */
/* AS PICKED — A, "ticked gauge at ⅓ and ⅔, BOOST label"
   (specs/0055 §4/§5 (W7, Greg 2026-09-06)). Measured off `#k-rocket-fuel-bar`'s
   A cell at 1:1: row `flex`, `align-items:center`, gap 9; label BOOST mono 9 px
   / 400 / .18em (1.62 px) uppercase; trough 148 × 5, `rgba(23,22,20,.72)`, NO
   border and NO radius; two 1 × 11 px ticks at 33 % and 66 %, `top:-3px` so they
   stand 3 px proud top and bottom, in `rgba(244,241,234,.5)`; fill blue idle
   (`--p-grad-to`) and orange burning (`--p-hazard`), with the label taking the
   same colour as the fill. Footprint unchanged — 148 × 5 is what shipped.
   The ticks are the DIAL'S tick marks: §1.10 wants one idea of "a fraction" in
   the HUD, and this is the gauge that shows one. */
.phud__fuel {
  position: absolute; right: 14px; bottom: 14px;
  display: flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: 9px; font-weight: 400; letter-spacing: .18em;
  text-transform: uppercase; color: var(--p-cream);
  text-shadow: 0 1px 5px rgba(0, 0, 0, .8);
}
.phud__fuel[hidden], .phud__fuel.is-hidden { display: none; }
.phud__fuel-bar {
  position: relative;
  display: block; width: 148px; height: 5px;
  background: rgba(23, 22, 20, .72);
  /* no border, no radius, `overflow:visible` — the ticks are 11 px tall and
     stand OUT of the 5 px trough, which is the whole read: they are marks on a
     ruler, not segments of the fill. */
}
.phud__fuel-fill {
  display: block; height: 100%; width: 100%;
  background: var(--p-grad-to);
  transition: width .06s linear;
}
/* the two marks. `top:-3px; height:11px` centres an 11 px tick on a 5 px bar. */
.phud__fuel-tick {
  position: absolute; top: -3px; width: 1px; height: 11px;
  background: rgba(244, 241, 234, .5);
}
.phud__fuel-tick.is-t1 { left: 33%; }
.phud__fuel-tick.is-t2 { left: 66%; }
/* burning is the ONE place the orange signal survives in register 1: the rocket
   pack is equipment, not a number the rider earned, so it keeps the signal
   colour rather than taking the gradient (the cell's own note). */
.phud__fuel.is-burn { color: var(--accent); }
.phud__fuel.is-burn .phud__fuel-fill { background: var(--accent); }
/* ran dry — dim until there is enough charge to relight */
.phud__fuel.is-dry { color: #7d766c; }
.phud__fuel.is-dry .phud__fuel-fill { background: #7d766c; }

/* THE PUMP ARC IS GONE — specs/0055 §4/§5 (W7, Greg 2026-09-06: "remove pump
   arc"). What used to be here: `.phud__pump` / `.phud__pump-arc` / `.is-hot` /
   `.is-cold` / `.is-rel` — a 58 px conic-gradient ring under the crosshair,
   masked to a band, that filled with the carve bank and flashed on release.
   REMOVED OUTRIGHT, and nothing takes its place: not the arc, not §1.10's 2 px
   gauge, not a rule. The lookbook's own alternate for this row (B, "a rule, not
   an arc") was not picked either — the row was cut, not restyled.
   The DATA is untouched: ski.js still banks `pumpQ`, scores `pumpEta` and pays
   out on `releasing`, `skiState()` still reports all three, and tricks.js's
   `pumpLink()` still carries a combo across a clean transition. The crosshair
   simply stops narrating it. */

/* THE TRICK HUD IS NOT IN THIS FILE ANY MORE (specs/0048).
   The live timer (`.phud__atime`), the combo meter (`.phud__combo`), its grace
   bar (`.phud__grace`) and the receipt (`.phud__cend`) are all styled from the
   `hudType` object in js/play/hud.js, which injects one <style id="phud-type">
   built from those constants at import time. The speedometer's canvas reads the
   SAME object, so the family, the 12° oblique, the 0.06em tracking, the
   purple→blue gradient and the flat deep indigo exist once and are shared rather
   than typed out twice and left to drift.

   What used to be here: a mono bottom-centre strip with the unbanked total and
   an orange multiplier, and a four-line receipt (cap / total / trick list /
   degrees) at 62%. Both went with the language, not just with the position. */

/* leaderboard breadcrumb (§4.3) — one dim dot under the fps chip. It is the
   only thing on screen that admits the board exists, and its title is `L L`. */
.phud__bdot {
  position: absolute; right: 19px; top: 44px;
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(244, 241, 234, .34);
  box-shadow: 0 0 0 1px rgba(23, 22, 20, .5);
  pointer-events: auto; cursor: help;
}
.phud__bdot[hidden], .phud__bdot.is-hidden { display: none; }
.phud__bdot:hover { background: var(--accent); }

.phud__toast {
  position: absolute; left: 50%; top: 58%; transform: translateX(-50%);
  border-color: var(--accent); color: var(--panel);
}
.phud__toast[hidden] { display: none; }

/* contextual offer under the crosshair — "F ride red dog express" (lift.js) */
.phud__prompt {
  position: absolute; left: 50%; top: calc(50% + 26px); transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  border-color: var(--accent); color: var(--panel);
}
.phud__prompt[hidden] { display: none; }
.phud__prompt b {
  color: #fff; background: var(--accent); border-radius: 2px;
  padding: 1px 5px; letter-spacing: .06em;
}

/* TOUCH (2026-09-05) — the same chip, promoted to a tap target. Every
   location-based offer in the game is written to `.phud__prompt` (lift.js's
   "ride RED DOG", guide.js's "race RED DOG SLALOM"), and both are keyed F,
   which a phone does not have. hud.js adds `--tap` on a coarse pointer only, so
   every rule above is exactly what it was on a desktop.

   BOTTOM CENTRE, not under the crosshair: on a coarse pointer hud.js hides the
   key legend, so this takes the strip the key chips vacated, and a 60 px slab
   in the middle of the screen would sit over the snow you are aiming at. It is
   also the seam between the two thumbs — touch.js gives the left half of the
   glass to the stick and the right half to look/jump — so either one reaches it
   without a re-grip. 60 px tall is the floor, not the target: the padding takes
   a long lift name past it. */
.phud__prompt--tap {
  left: 50%; top: auto;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  pointer-events: auto;
  min-height: 60px; min-width: 190px; max-width: calc(100vw - 32px);
  justify-content: center; gap: 10px;
  padding: 0 20px; font-size: 13px;
  overflow: hidden;
  background: rgba(23, 22, 20, .92);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .45);
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}
.phud__prompt--tap span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.phud__prompt--tap b { font-size: 12px; padding: 5px 9px; letter-spacing: .1em; flex: none; }
/* the press state — the finger is on it, before the key goes out */
.phud__prompt--tap.is-press { background: var(--accent); }
.phud__prompt--tap.is-press b { background: rgba(23, 22, 20, .85); }

.phud__fps { position: absolute; right: 14px; top: 14px; }
.phud__fps .v { color: var(--panel); font-variant-numeric: tabular-nums; }

/* reference-bundle viewer: B toggles, [ ] cycle */
.phud__ref {
  position: absolute; right: 14px; top: 52px;
  width: min(38vw, 560px); padding: 6px;
  display: grid; gap: 5px;
}
/* `display: grid` above outranks the UA's [hidden] rule, so say it here or the
   viewer sits on screen as an empty black bar with B never having been pressed */
.phud__ref[hidden] { display: none; }
.phud__ref-img {
  display: block; width: 100%; max-height: 58vh; object-fit: contain;
  background: #000; border-radius: 2px;
}
.phud__ref-cap { color: #cdc7ba; letter-spacing: .1em; }

/* ---------------------------------------------------------------- dev mode
   F8. A fly-camera readout, a reference-compare layer under the HUD chips, a
   toolbar, and the "match this view" dialog. See harness/TUNING.md. */

.phud__dev {
  position: absolute; left: 14px; top: 14px;
  display: grid; gap: 3px; min-width: 230px; max-width: 300px;
  border-color: var(--accent);
}
.phud__dev[hidden] { display: none; }
.phud__dev.is-hidden { display: none; }
.phud__dev .k { color: #a49d90; }
.phud__dev .v { color: var(--panel); font-variant-numeric: tabular-nums; }
.phud__dev .r { display: flex; justify-content: space-between; gap: 14px; }
.phud__dev-url {
  margin-top: 4px; padding: 5px 6px;
  background: rgba(244, 241, 234, .1); border-radius: 2px;
  color: #ffd9c8; letter-spacing: .04em; text-transform: none;
  word-break: break-all; user-select: text;
}
.phud__dev-btns { display: flex; gap: 5px; margin-top: 4px; pointer-events: auto; }

/* ================================================================ specs/0055
   §2 (lab dialect) + §1.9 (hazard stripe) + §5.5 (F8 dev bar B, annotate A).
   The lab dialect is register 3's board in MONO with NO gradient at all and a
   4 px `--accent` hazard rule on the top edge. Stripe = not shipping.
   Three of §1.9's eight striped surfaces live in this file: `.pdev-bar`,
   `dev-tuning-match-dialog` (`.pdev-modal__panel`) and `dev-tuning-annotate`
   (`.pdev-paint__panel`, in dev.js's PAINT_CSS). The other five are hud.js's.
   ------------------------------------------------------------------------ */
.pdev-lab {
  background: rgba(23, 22, 20, .90);
  border-top: 4px solid var(--accent);
  border-radius: 0 0 2px 2px;
  font-family: var(--mono); color: #e8e4da;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .45);
}
.pdev-lab__hd {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 6px 10px 5px; border-bottom: 1px solid rgba(244, 241, 234, .16);
  font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase; color: #ff9153;
}
.pdev-lab__bd { padding: 7px 10px 8px; font-size: 10.5px; letter-spacing: .04em; }

/* specs/0055 §5.5 — dev actions are prompts too, so they take register 2's
   `key -> verb` grammar: the key on a plate, the verb reading beside it. */
.pdev-key {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .06em;
  background: var(--accent); color: #fff; border-radius: 2px;
  padding: 3px 6px; min-width: 13px; text-align: center; line-height: 1.3;
  flex: none; text-transform: uppercase;
}
/* specs/0055 §1.8 — the severity alphabet's red X, the system's mark for
   "closed / nothing here". The reference viewer's honest empty state (A). */
.pdev-x {
  position: relative; display: block; width: 11px; height: 11px; flex: none;
}
.pdev-x::before, .pdev-x::after {
  content: ""; position: absolute; left: 0; top: 4px; width: 11px; height: 3px;
  background: #ff5c8a;
}
.pdev-x::before { transform: rotate(45deg); }
.pdev-x::after { transform: rotate(-45deg); }
.pdev-x[hidden] { display: none; }   /* `display: block` above outranks [hidden] */

.pdev-btn {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #cdc7ba; cursor: pointer;
  background: rgba(244, 241, 234, .1); border: 1px solid rgba(244, 241, 234, .28);
  border-radius: var(--r-sm); padding: 5px 8px;
}
.pdev-btn:hover { background: rgba(244, 241, 234, .2); color: var(--panel); }
.pdev-btn.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.pdev-btn--accent { background: var(--accent); border-color: #a83300; color: #fff; }
.pdev-btn--accent:hover { background: #f04800; color: #fff; }
.pdev-btn:disabled { opacity: .4; cursor: default; }
.pdev-btn--sm { padding: 3px 6px; font-size: 9px; }
/* specs/0055 §5.5 — the key-plate button: a `.pdev-key` and its verb inside one
   hit target, so M / P / J read the way E / F / T read in the world. */
.pdev-btn--key {
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 1px solid rgba(244, 241, 234, .22);
  padding: 3px 8px 3px 3px; letter-spacing: .13em; border-radius: 2px;
}
.pdev-btn--key:hover { background: rgba(244, 241, 234, .12); color: var(--panel); }
.pdev-btn--key:disabled .pdev-key { background: rgba(244, 241, 234, .18); color: #cdc7ba; }

.pdev-lbl {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #a49d90;
}
.pdev-lbl--v { color: var(--panel); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }

/* compare layer — deliberately BELOW the hud chips (z 20) and above the canvas */
.pdev-compare { position: fixed; inset: 0; z-index: 15; pointer-events: none; }
.pdev-compare[hidden] { display: none; }
.pdev-compare__ref { position: absolute; inset: 0; overflow: hidden; background: #0b1a2a; }
.pdev-compare__ref--side { right: 50%; border-right: 1px solid var(--accent); }
.pdev-compare__ref--overlay, .pdev-compare__ref--wipe { background: transparent; }
.pdev-compare__img { width: 100%; height: 100%; object-fit: contain; display: block; }
.pdev-compare__seam {
  position: absolute; top: 0; bottom: 0; width: 1px; margin-left: -.5px;
  background: var(--accent);
}
.pdev-compare__seam[hidden], .pdev-compare__handle[hidden] { display: none; }
/* specs/0055 §1.10 — 2 px radius on caps, and the lab dialect's square edge:
   the wipe handle is a plate, not a pill. */
.pdev-compare__handle {
  position: absolute; top: 50%; width: 26px; height: 54px; margin: -27px 0 0 -13px;
  border-radius: 2px; background: var(--accent); border: 1px solid #a83300;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .4);
  cursor: ew-resize; pointer-events: auto; touch-action: none;
}

/* ---- specs/0055 §5.5 (D17) — the F8 dev bar takes lookbook STYLE B: one
   full-bleed band across the TOP edge under a single 4 px hazard rule, holding
   the mode, the reference state, and every control §0 pins — the four `MODES`,
   the opacity slider, `match this view · M`, `snapshot + annotate · P`,
   `file trace · J`. Nothing shipped ever paints the top edge, so this is the
   most unmistakable "you are in dev mode" frame available. */
.pdev-bar {
  position: fixed; left: 0; right: 0; top: 0; z-index: 22;
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px;
  padding: 7px 14px; pointer-events: auto;
  background: rgba(23, 22, 20, .90);
  border-top: 4px solid var(--accent);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em;
  text-transform: uppercase; color: #cdc7ba;
}
.pdev-bar[hidden] { display: none; }
.pdev-bar__title {
  display: flex; align-items: center; gap: 7px; flex: none;
  font-size: 9.5px; font-weight: 700; letter-spacing: .18em; color: #ff9153;
}
/* specs/0055 §5.5 — reference A: the honest empty state. No bundle dropped is
   not an error, it is a refusal, so it gets §1.8's red X and no colour of its
   own; once a photo lands the same slot carries its name, roman, untracked. */
.pdev-bar__ref {
  display: flex; align-items: center; gap: 7px;
  flex: 1 1 120px; min-width: 0; color: #9aa0ad; font-size: 9px; letter-spacing: .13em;
}
.pdev-bar__ref b {
  min-width: 0; font-weight: 400; color: #e8e4da; letter-spacing: .04em;
  text-transform: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pdev-bar__row { display: flex; align-items: center; gap: 5px; flex: none; }
.pdev-bar__row .pdev-btn { text-align: center; padding: 4px 7px; letter-spacing: .1em; }
/* every control keeps its own width — a shrunken flex item spills its label
   over its neighbour, which is what the band must never do (specs/0055 §10.9:
   ALL the buttons stay, so they must all stay READABLE) */
.pdev-bar > .pdev-btn { flex: none; }
/* te.css:223's `input[type="range"] { width: 100% }` outranks a bare class, so
   the band's own slider width has to be scoped to the bar to win */
.pdev-bar .pdev-slider { width: 88px; flex: none; accent-color: var(--accent); }
.pdev-slider { accent-color: var(--accent); }
.pdev-bar .pdev-btn--accent { padding: 3px 8px 3px 3px; text-align: left; }
/* The band owns the top edge, so the lab surfaces anchored at `14, 14` drop
   below it rather than under it (specs/0055 §2 — one arrival at a time). The
   class is set by dev.js on the body; nothing shipped is anchored up there. */
body.play.is-devbar .phud__dev,
body.play.is-devbar .phud__read,
body.play.is-devbar .phud__lip,
body.play.is-devbar .phud__fps { margin-top: 34px; }

/* match dialog */
.pdev-modal {
  position: fixed; inset: 0; z-index: 45;
  display: grid; place-items: center; padding: 20px;
  background: rgba(23, 22, 20, .5); backdrop-filter: blur(3px);
}
.pdev-modal[hidden] { display: none; }
/* specs/0055 §1.9 + §2 — `dev-tuning-match-dialog` is one of the eight lab
   surfaces, so the cream board becomes register 3's board IN MONO: ink slab, no
   gradient anywhere, 4 px hazard rule on the top edge. Every control §0 pins
   stays exactly where it was — the two shots, the note, `confirm`, `cancel`. */
.pdev-modal__panel {
  width: min(680px, 94vw);
  background: rgba(23, 22, 20, .93); border: 0; border-top: 4px solid var(--accent);
  border-radius: 0 0 2px 2px; color: #e8e4da;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
}
.pdev-modal__panel .panel__hd {
  background: none; border-radius: 0; border-bottom: 1px solid rgba(244, 241, 234, .16);
  padding: 6px 11px 5px;
}
.pdev-modal__panel .panel__hd::before { display: none; }
.pdev-modal__panel .panel__hd .lbl { font-size: 9.5px; letter-spacing: .18em; color: #ff9153; }
.pdev-modal__panel .panel__hd .lbl:not(.lbl--accent) { color: #6f7891; }
.pdev-modal__bd { display: grid; gap: 11px; padding: 10px 11px 12px; }
.pdev-modal__shots { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.pdev-shot { margin: 0; display: grid; gap: 5px; }
.pdev-shot__img {
  display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: contain;
  background: #0b1a2a; border: 1px solid rgba(244, 241, 234, .22); border-radius: 2px;
}
.pdev-shot__cap {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #6f7891;
}
.pdev-modal__ask {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: #e8e4da;
}
.pdev-modal__note { display: grid; gap: 4px; }
.pdev-note {
  width: 100%; box-sizing: border-box; resize: vertical;
  font-family: var(--mono); font-size: 11.5px; line-height: 1.5; color: #e8e4da;
  background: rgba(244, 241, 234, .08); border: 1px solid rgba(244, 241, 234, .22);
  border-radius: 2px; padding: 7px 8px;
}
.pdev-note:focus { outline: none; border-color: var(--accent); }
.pdev-modal__row { display: flex; gap: 8px; align-items: center; }
.pdev-modal__row .btn { border-radius: 2px; }
.pdev-modal__row .btn--ghost { background: none; border-color: rgba(244, 241, 234, .22); color: #cdc7ba; }
.pdev-modal__row .btn--ghost:hover { background: rgba(244, 241, 234, .12); color: var(--panel); }
.pdev-modal__stat { color: #9aa0ad; }

/* --------------------------------------------------------------- gear menu
   Hold E. Same panel language as pause, sized like a context menu. */
.pgearmenu {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  pointer-events: auto; z-index: 30;
}
.pgearmenu[hidden] { display: none; }
.pgearmenu__panel { width: min(280px, 80vw); box-shadow: 0 14px 40px rgba(0, 0, 0, .3); }
.pgearmenu__bd { display: grid; gap: 4px; padding: 8px; }
.pgearmenu__row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 9px; border-radius: var(--r-sm); border: 1px solid transparent;
  cursor: pointer; user-select: none;
}
.pgearmenu__row .cap {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  background: var(--panel-2); border: 1px solid var(--ink); border-radius: 3px;
  padding: 2px 6px; box-shadow: 0 1px 0 var(--seam-hard);
}
.pgearmenu__row .name {
  flex: 1; font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink);
}
.pgearmenu__row .tag {
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.pgearmenu__row.is-sel { background: var(--accent); border-color: #a83300; }
.pgearmenu__row.is-sel .name, .pgearmenu__row.is-sel .tag { color: #fff; }
.pgearmenu__row.is-sel .cap { background: rgba(0, 0, 0, .22); color: #fff; border-color: #a83300; box-shadow: none; }

/* --------------------------------------------------------------- inventory
   I. The locker: tabs across the top, a live 3D preview of the body on the
   left, a grid of equipment squares on the right, and the stat strip under it.
   Same TE panel language as pause — this is an instrument, not a storefront. */
.pinv {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center; padding: 18px;
  background: rgba(23, 22, 20, .58);
  backdrop-filter: blur(5px) saturate(.85);
  pointer-events: auto;
}
.pinv[hidden] { display: none; }
.pinv__panel {
  width: min(1180px, 96vw); height: min(780px, 92vh);
  display: flex; flex-direction: column; min-height: 0;
  box-shadow: 0 22px 60px rgba(0, 0, 0, .42);
}
.pinv__bd {
  flex: 1; min-height: 0;
  display: grid; grid-template-rows: auto 1fr; gap: 11px;
}
.pinv__tabs {
  display: flex; align-items: center; gap: 6px;
  border-bottom: 1px solid var(--seam); padding-bottom: 9px;
}
.pinv__tab {
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-2); cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--seam-hard);
  border-radius: var(--r-sm); padding: 7px 13px;
}
.pinv__tab:hover { background: var(--panel-3); color: var(--ink); }
.pinv__tab.is-on { background: var(--accent); border-color: #a83300; color: #fff; }
.pinv__hint {
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}

.pinv__body {
  min-height: 0; display: grid; grid-template-columns: 330px 1fr; gap: 14px;
}
.pinv__preview {
  min-height: 0; display: grid; grid-template-rows: 1fr auto;
  background: linear-gradient(180deg, #16283a 0%, #0b1a2a 62%, #091420 100%);
  border: 1px solid var(--seam-hard); border-radius: var(--r-sm); overflow: hidden;
}
.pinv__stage { position: relative; min-height: 0; }
/* two selectors deep on purpose: `body.play canvas` above pins every canvas in
   this document to fixed 0,0 for the world renderer, and the preview is the one
   canvas that must stay inside its box */
.pinv__stage .pinv__canvas { display: block; position: absolute; inset: 0; width: 100%; height: 100%; }
.pinv__cap {
  padding: 9px 11px; border-top: 1px solid rgba(244, 241, 234, .16);
  background: rgba(11, 26, 42, .7);
}
.pinv__cap-brand {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .22em;
  text-transform: uppercase; color: #8fa3b5;
}
.pinv__cap-name {
  font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: .06em;
  color: var(--panel); margin-top: 3px;
}

/* rows are named explicitly because a tab with one filter group hides the chip
   row entirely, and implicit placement would then hand the 1fr to the detail
   strip instead of to the grid */
.pinv__right { min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 10px; }
.pinv__filters { grid-row: 1; display: flex; gap: 5px; flex-wrap: wrap; }
.pinv__filters[hidden] { display: none; }
.pinv__chip {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); cursor: pointer;
  background: transparent; border: 1px solid var(--seam-hard);
  border-radius: 999px; padding: 4px 11px;
}
.pinv__chip:hover { color: var(--ink); border-color: var(--ink); }
.pinv__chip.is-on { background: var(--ink); border-color: var(--ink); color: var(--panel); }

.pinv__grid {
  grid-row: 2; min-height: 0; overflow-y: auto; align-content: start;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(152px, 1fr)); gap: 10px;
  padding-right: 4px;
}
.pinv__card {
  position: relative; display: grid; gap: 6px; text-align: left; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--seam);
  border-radius: var(--r-sm); padding: 8px;
}
.pinv__card:hover { border-color: var(--seam-hard); }
.pinv__card.is-sel {
  background: var(--panel); border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-dim);
}
.pinv__art {
  display: block; background: var(--panel-3); border: 1px solid var(--seam);
  border-radius: 3px; padding: 5px 4px;
}
.pinv__img { display: block; width: 100%; height: auto; }
.pinv__name {
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .04em;
  color: var(--ink); line-height: 1.35;
  min-height: 2.7em;               /* two lines, so a wrapped name never jogs the row */
}
.pinv__tag {
  font-family: var(--mono); font-size: 8.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
}
.pinv__eq {
  position: absolute; right: 6px; top: 6px;
  font-family: var(--mono); font-size: 7.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #fff; background: var(--accent);
  border-radius: 2px; padding: 2px 5px;
}

.pinv__detail { grid-row: 3; border-top: 1px solid var(--seam); padding-top: 10px; display: grid; gap: 7px; align-content: start; }
.pinv__d-top { display: flex; align-items: baseline; gap: 10px; }
.pinv__d-name { font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: .04em; color: var(--ink); }
.pinv__d-tag {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--accent);
}
.pinv__d-blurb { font-size: 12px; line-height: 1.5; color: var(--ink-2); max-width: 78ch; }
.pinv__d-cols { display: grid; grid-template-columns: minmax(220px, 1fr) minmax(220px, 1fr); gap: 8px 22px; }

.pinv__bars { display: grid; gap: 5px; align-content: start; }
.pinv__bar { display: grid; grid-template-columns: 64px 1fr 26px; align-items: center; gap: 9px; }
.pinv__bar-k {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
}
.pinv__bar-t {
  display: block; height: 7px; background: var(--panel-3);
  border: 1px solid var(--seam-hard); border-radius: 2px; overflow: hidden;
}
.pinv__bar-t i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .12s ease-out; }
.pinv__bar-v {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; text-align: right;
}

.pinv__facts { display: grid; grid-template-columns: 1fr 1fr; gap: 3px 16px; align-content: start; }
.pinv__fact { display: flex; justify-content: space-between; gap: 10px; }
.pinv__fact .k {
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.pinv__fact .v {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 880px) {
  .pinv__body { grid-template-columns: 1fr; grid-template-rows: 220px 1fr; }
  .pinv__d-cols { grid-template-columns: 1fr; }
}

/* W1 TOOK THE HAND-OFF (specs/0055 §1.1). The colours W4 typed here are tokens
   hud.js owns; its injected `:root` block publishes each as a custom property,
   so the three §10.3 reserves are now read by name in this sheet and typed in
   none of it. This sheet still declares NO token of its own — §1.1's rule —
   only `--pf` at :166, which is a layout number, not a design token.
   The cream/ink/seam names below that W4 left in place are the same sweep. */
/* ------------------------------------------------------------------- pause
   specs/0055 5.1 - PAUSE **B** (D14). The panel was already cream, which the
   0055 audit called "the right instinct"; what it was not was a MAP BOARD. It
   is one now: 2 px ink mounting rule under the header (1.10), 2 px radius,
   hairline row rules, ink key plates in a fixed 66 px column so the verbs form
   a hard left edge, and the resume button as a solid ink plate. The credit line
   is verbatim and sets in 9 px mono the way a map carries its attribution.

   TWO COLUMNS, AND NO ROW COUNT ANYWHERE IN THIS SHEET. The lab tier lists 31
   rows and the shipped tier lists five (hud.js FIVE_ROWS / LAB_ROWS), and the
   spec's ask is that "30 rows fit one screen for the first time" with ONE code
   path for both. grid-auto-flow:column over a fixed 16-row template does
   exactly that, and is honest about which is which: five rows fill rows 1-5 of
   column one and the panel stays a single column; 31 rows fill column one and
   spill 15 into column two, IN READING ORDER - which a plain two-column
   grid-template-columns cannot do, because it interleaves the list.

   Arrival and exit are 6's RISE / FALL at 1.11 timings, and the rows do not
   stagger: a paused game should be paused, not performing. */
.ppause {
  position: fixed; inset: 0; z-index: 40;
  display: grid; place-items: center;
  background: rgba(23, 22, 20, .42);
  backdrop-filter: blur(4px) saturate(.8);
  animation: p55-rise 220ms cubic-bezier(.16, 1, .3, 1) both;
}
.ppause[hidden] { display: none; animation: none; }
.ppause__panel {
  width: max-content; max-width: min(96vw, 900px);
  border-radius: 2px; border-color: var(--ink);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .3);
}
/* 1.10 - the 2 px mounting rule. .panel__hd already draws a 1 px seam; the
   board's rule is the heavier one, and it is ink rather than accent because the
   header word PAUSED is the accent on this panel. */
.ppause__panel > .panel__hd { border-bottom: 2px solid var(--ink); border-radius: 2px 2px 0 0; }
.ppause__bd { display: grid; gap: 10px; padding: 12px 14px 12px; }
.ppause__keys {
  display: grid;
  /* max-content/auto rather than four fixed tracks: an EMPTY column 3-4 has to
     collapse to nothing, or the shipped five-row tier reserves the lab tier's
     second column and sits in a board twice as wide as its own content. The
     widths live on the cells instead. */
  grid-template-columns: max-content auto max-content auto;
  grid-auto-flow: row dense;
  gap: 0 14px;
}
/* TWO COLUMNS OF PAIRS, COLUMN-MAJOR, WITHOUT A WRAPPER ELEMENT AND WITHOUT A
   ROW COUNT IN THE JS. hud.js emits a flat run of .cap/.what siblings, so the
   only lever this sheet has is which grid column each sibling takes. The first
   16 pairs (32 children) take columns 1-2 and the rest take 3-4; `row dense`
   then back-fills columns 3-4 from row 1 instead of continuing down the page.
   The 32 is the ONE number here, it is a CAPACITY and not a count, and it
   degrades in the right direction: the shipped five-row tier (10 children) is
   entirely inside the first 32 and renders as a single column — which is the
   "one code path, both tiers" §5.1 asks for. */
.ppause__keys > :nth-child(-n+32):nth-child(odd)  { grid-column: 1; }
.ppause__keys > :nth-child(-n+32):nth-child(even) { grid-column: 2; }
.ppause__keys > :nth-child(n+33):nth-child(odd)   { grid-column: 3; }
.ppause__keys > :nth-child(n+33):nth-child(even)  { grid-column: 4; }
/* The hairline row rule (§1.10) sits at the ROW's bottom, not under the text,
   so a two-line verb still rules level with its key. Both halves stretch to the
   row and carry the rule; the key PLATE is therefore painted INSIDE the cap
   cell — an 18 px band at the top — rather than being the cell's own box. */
.ppause__keys .cap,
.ppause__keys .what {
  align-self: stretch;
  border-bottom: 1px solid var(--seam);
  padding-bottom: 5px; margin-bottom: 5px;
}
.ppause__keys .cap {
  position: relative;
  height: auto; min-height: 17px; min-width: 62px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
  text-align: center; color: var(--ink); line-height: 17px;
  background-image: linear-gradient(var(--panel-2), var(--panel-2));
  background-repeat: no-repeat; background-size: 100% 17px;
  white-space: nowrap; overflow: hidden;
}
/* the plate's 1 px ink edge, 2 px radius (§1.10) — an overlay so it hugs the
   18 px band and never the whole stretched cell */
.ppause__keys .cap::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 17px;
  box-shadow: inset 0 0 0 1px var(--ink); border-radius: 2px; pointer-events: none;
}
.ppause__keys .what {
  max-width: 336px;
  font-family: var(--mono); font-size: 9.5px; line-height: 17px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-2);
}
.ppause__keys .is-hidden { display: none; }
.ppause__row { display: flex; gap: 8px; align-items: center; }
/* the action is an ink plate, the way the lookbook's resume plate is. specs/0055
   §5.1 (any key, Greg 2026-09-06) — the WORDS on it are now ANY KEY TO RESUME /
   TOUCH TO RESUME (hud.js picks by `pointer: coarse`); the plate is unchanged,
   and `flex: 1` means it is the board's width either way, not the sentence's. */
.ppause__big {
  flex: 1; justify-content: center; padding: 11px 12px; font-size: 11px;
  background: var(--ink); border-color: var(--ink); color: var(--panel);
  border-radius: 2px; letter-spacing: .16em;
}
.ppause__big:hover { background: #2b2925; }

/* -------------------------------------------------------------- leaderboard
   Double-tap L (4.3). specs/0055 5.1 - RESULTS **A** (D14): the lift-shack
   results sheet. Cream board, 2 px mounting rule, a mono column header ruled in
   ink, hairline row rules, everything else ink and mono the way a race result
   pinned in a lift shack is - and the SCORE is the one gradient number allowed
   anywhere in register 3 (1.5: the gradient belongs to the rider, and the score
   is the rider's). Per D18 that gradient carries NO stroke, no paint-order and
   no text-shadow. The zebra stripe is gone: a ruled sheet does not need two
   devices for the same job. */
.pboard {
  position: fixed; inset: 0; z-index: 42;
  display: grid; place-items: center;
  background: rgba(23, 22, 20, .42);
  backdrop-filter: blur(4px) saturate(.8);
  animation: p55-rise 220ms cubic-bezier(.16, 1, .3, 1) both;
}
.pboard[hidden] { display: none; animation: none; }
.pboard__panel {
  width: min(760px, 94vw);
  border-radius: 2px; border-color: var(--ink);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .3);
}
.pboard__panel > .panel__hd { border-bottom: 2px solid var(--ink); border-radius: 2px 2px 0 0; }
.pboard__bd { display: grid; gap: 0; padding: 10px 14px 14px; }
.pboard__row {
  display: grid; align-items: baseline; gap: 10px;
  grid-template-columns: 22px 96px 44px minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) 82px;
  padding: 9px 0; border-radius: 0; border: 0;
  border-bottom: 1px solid var(--seam);
  font-family: var(--mono); font-size: 11px; letter-spacing: .06em; color: var(--ink);
}
.pboard__row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pboard__row .rk { color: var(--muted); font-variant-numeric: tabular-nums; }
/* THE ONE GRADIENT IN REGISTER 3. hudType.gradFrom -> hudType.gradTo at the
   shipping 96deg, two stops, no border (D18). It is typed here rather than read
   from a token because play.css declares no design token and gains none (1.1) -
   hud.js stays the single source. */
.pboard__row .sc {
  /* `background-clip: text` paints the ELEMENT's box, so the span has to hug
     the number or a three-digit score lands on one end of the ramp and reads
     as a flat blue. `width: max-content` + `justify-self: end` keeps the column
     right-aligned and runs the full purple->blue across the digits themselves —
     the DOM answer to the same problem §1.4 solves on canvas by building the
     ramp along the arc's start->tip line instead of the bounding box. */
  justify-self: end; width: max-content;
  font-family: var(--sans); font-weight: 700; font-size: 22px; letter-spacing: .02em;
  font-variant-numeric: tabular-nums; text-align: right;
  background: var(--p-grad);   /* specs/0055 §1.4 (D18) — two stops, no border */
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.pboard__row .mu { color: var(--muted); font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
.pboard__row .bt { font-weight: 700; text-transform: uppercase; letter-spacing: .1em; }
.pboard__row .sk, .pboard__row .tr, .pboard__row .wh { color: var(--ink-2); text-transform: uppercase; }
.pboard__row .wh { text-align: right; color: var(--muted); }
.pboard__row--hd {
  font-size: 9px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted);
  border-bottom: 1px solid var(--ink); padding: 0 0 5px; margin-bottom: 0;
}
.pboard__row--hd .sc {
  font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .16em;
  background: none; -webkit-background-clip: border-box; background-clip: border-box;
  color: var(--muted);
}
.pboard__row--hd .mu, .pboard__row--hd .bt { color: var(--muted); font-weight: 700; }
/* your own row is marked by the accent on the rank and the trick, not by a
   filled bar: one mark per plate, and the sheet stays a sheet */
.pboard__row.is-you { background: transparent; color: var(--ink); }
.pboard__row.is-you .rk, .pboard__row.is-you .bt { color: var(--accent); }
/* 1.8's alphabet in the empty state: a black diamond, not an icon */
.pboard__empty {
  font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted); padding: 34px 7px 30px; text-align: center;
}
.pboard__empty::before {
  content: ""; display: block; width: 14px; height: 14px; margin: 0 auto 12px;
  background: var(--seam); transform: rotate(45deg);
}

/* 1.11 RISE - 220 ms, opacity 0 -> 1 and +10 px. The one arrival verb every
   register-3 surface uses; nothing else in this sheet may invent a duration. */
@keyframes p55-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------------- portal
   A physical hatch: bezel, screwed-down corners, a caged key that lights
   orange when a world is behind it. Lives on run pages and run rows. */
.portal {
  display: inline-flex; align-items: stretch; gap: 0;
  border: 1px solid var(--ink); border-radius: var(--r-sm);
  background: var(--panel-2); overflow: hidden;
  box-shadow: 0 2px 0 var(--seam-hard);
  cursor: pointer; user-select: none; text-decoration: none;
}
.portal:active { transform: translateY(2px); box-shadow: 0 0 0 var(--seam-hard); }
.portal__hatch {
  width: 34px; flex: none; position: relative;
  background:
    repeating-linear-gradient(45deg, rgba(0, 0, 0, .05) 0 3px, transparent 3px 6px),
    var(--panel-3);
  border-right: 1px solid var(--ink);
  display: grid; place-items: center;
}
.portal__iris {
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--panel); border: 1px solid var(--ink);
  box-shadow: inset 0 0 0 3px var(--panel-3);
}
.portal__lbl {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 12px 7px 10px;
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink);
}
.portal__sub { color: var(--muted); letter-spacing: .1em; }

.portal.is-armed { background: var(--accent); border-color: #a83300; }
.portal.is-armed .portal__lbl { color: #fff; }
.portal.is-armed .portal__sub { color: rgba(255, 255, 255, .78); }
.portal.is-armed .portal__hatch {
  background:
    repeating-linear-gradient(45deg, rgba(0, 0, 0, .13) 0 3px, transparent 3px 6px),
    #7a2600;
  border-right-color: #4d1800;
}
.portal.is-armed .portal__iris {
  background: #ffd9c8; border-color: #4d1800;
  box-shadow: inset 0 0 0 3px #ff7a3d, 0 0 7px rgba(255, 217, 200, .9);
  animation: pblink 2.2s ease-in-out infinite;
}
@keyframes pblink { 0%, 100% { opacity: 1 } 50% { opacity: .72 } }
.portal.is-armed:hover { background: #f04800; }

.portal.is-dead { cursor: default; opacity: .55; box-shadow: none; background: var(--panel-2); }
.portal.is-dead:active { transform: none; }

.portal--sm { box-shadow: 0 1px 0 var(--seam-hard); }
.portal--sm .portal__hatch { width: 22px; }
.portal--sm .portal__iris { width: 10px; height: 10px; box-shadow: inset 0 0 0 2px var(--panel-3); }
.portal--sm .portal__lbl { padding: 4px 8px 4px 7px; font-size: 9px; letter-spacing: .12em; }
.portal--sm.is-armed .portal__iris { box-shadow: inset 0 0 0 2px #ff7a3d, 0 0 6px rgba(255, 217, 200, .9); }
