/* THE OPEN WORLD â€” the roam HUD (js/world-hud.js), linked after coffee.css (OPEN-WORLD-PROGRESS.md OW25, OW30-OW32, OW81).
   The same stickers as the rest of the car: bone and charcoal, the world's 2px ink line and a hard shadow, a little crooked;
   paper cards for what you read. Only the controls take pointers (the layer passes every other touch through to the world)
   and only the controls lock the browser's gestures (touch-action: none): the page keeps its zoom. Which controls show is
   decided by the pointer, never by the width: js/world-hud.js sets data-roam-controls="touch" from (any-pointer: coarse) or
   the first touch, and "keys" otherwise. Everything sits inside the safe area. Styles only .roam, .roam__* and
   .hub:has(.roamâ€¦) (OW81).

   KEEP CLEAR (OW32): the car's screen box and the road above it. The chase rig puts the car in the middle column (desk and
   land: about 36-64% of the width, from the horizon at about a third of the height down to 85-90%; tall: 28-72% of the
   width, 25-73% of the height, js/world-chase.js carBox()). Nothing here enters that column while driving: the bar, the
   status line, the job sticker and the banner stay above the horizon or beside it, the minimap and the chips at the sides,
   the prompt and ACTION beside or below the car, the thumbs at the bottom corners. Cards only open with the car stopped. */

.roam {
  --roam-line: #17110f; --roam-bone: #f0e2bf; --roam-paper: #ece4cf; --roam-ink: #1d1a14;
  --roam-char: rgba(23, 17, 15, .88); --roam-orange: #e7782b; --roam-brake: #8a241b; --roam-green: #a9c98a; --roam-red: #d8402a;
  --roam-target: 3rem; /* ~48 CSS px: the smallest side of any control (44 px at least, OW25) */
  --roam-left: max(var(--gutter, 1rem), calc(env(safe-area-inset-left, 0px) + .25rem));
  --roam-right: max(var(--gutter, 1rem), calc(env(safe-area-inset-right, 0px) + .25rem));
  --roam-bottom: max(.75rem, calc(env(safe-area-inset-bottom, 0px) + .25rem));
  /* below the hub's title and its MENU row (2.75rem), as the parking and race bars */
  --roam-top: calc(env(safe-area-inset-top, 0px) + clamp(.75rem, 2vw, 1.25rem) + 3.3rem);
  --roam-vw: calc((100vw - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)) / 100);
  --roam-pad-w: clamp(9.5rem, calc(44 * var(--roam-vw)), 15rem); --roam-pad-h: 4.75rem; --roam-knob: 3.5rem;
  --roam-pedal-w: clamp(4.25rem, calc(20 * var(--roam-vw)), 5.5rem); --roam-brake-h: 6rem; --roam-gas-h: 7.25rem;
  --roam-mini: 140px; /* OW32: 140 px on desktop, 100 px on a phone */
  color: var(--roam-bone); inset: 0; pointer-events: none; position: absolute; z-index: 3;
}
.roam[hidden], .roam [hidden] { display: none !important; }
.hub[data-hub-state="fallback"] .roam { display: none !important; }

/* every control: takes its own pointer, no scrolling, zooming or selection gestures, no long-press menu */
.roam :is(button, [data-roam-hold]) {
  -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; -webkit-user-select: none;
  pointer-events: auto; touch-action: none; user-select: none;
}
.roam button { cursor: pointer; font: inherit; }
.roam button:focus-visible { outline: 3px solid var(--orange, #ff4f00); outline-offset: 2px; }
/* (repair 2) the gamepad moves the focus (the D-pad): its ring shows whatever the last pointer did */
.roam[data-roam-nav="pad"] button:focus { outline: 3px solid var(--orange, #ff4f00); outline-offset: 2px; }
.roam__icon { flex: none; height: 1.1rem; width: 1.1rem; }
.roam .is-locked, .roam [aria-disabled="true"] { opacity: .55; }
.roam__sr { clip-path: inset(50%); height: 1px; margin: 0; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }

/* the curtain (the view switch, a tow): over the world, under the HUD's own stickers */
.roam__curtain { background: #050403; display: none; inset: 0; opacity: var(--roam-curtain, 0); pointer-events: none; position: absolute; }
.roam__curtain.is-on { display: block; }

/* ---------- top: the bar and the status line ---------- */
.roam__head { align-items: flex-start; display: flex; flex-wrap: wrap; gap: .45rem .7rem; left: var(--roam-left); pointer-events: none; position: absolute; top: var(--roam-top); max-width: calc(100% - var(--roam-left) - var(--roam-right)); }
.roam__bar { display: flex; flex: none; flex-wrap: wrap; gap: .4rem; }
.roam__btn {
  align-items: center; background: var(--roam-char); border: 2px solid rgba(240, 226, 191, .55); box-shadow: 3px 3px 0 var(--roam-line);
  color: var(--roam-bone); display: inline-flex; font-size: .62rem; font-weight: 900; gap: .4rem; justify-content: center; letter-spacing: .14em;
  min-height: var(--roam-target); min-width: var(--roam-target); padding: .4rem .7rem;
}
.roam__btn--off { background: var(--roam-bone); border-color: var(--roam-line); color: var(--roam-line); transform: rotate(-1deg); }
.roam__btn:active, .roam__action:active, .roam__act:active, .roam__prompt:active { box-shadow: 1px 1px 0 var(--roam-line); translate: 2px 2px; }
@media (hover: hover) { .roam__btn:hover, .roam__action:not(.is-locked):hover, .roam__place:hover { background: var(--orange, #ff4f00); border-color: var(--roam-line); color: var(--roam-line); } }
.roam__icon-play { display: none; }
.roam[data-roam-paused="true"] .roam__icon-play { display: inline; }
.roam[data-roam-paused="true"] .roam__icon-pause { display: none; }
/* VIEW: the view it shows now, in words (aria-pressed: CHASE) */
.roam__btn--view { transform: rotate(.8deg); }
.roam__btn--view[aria-pressed="true"] { background: var(--roam-orange); border-color: var(--roam-line); color: var(--roam-line); }
.roam__view-short { display: none; }

.roam__status {
  align-items: center; background: var(--roam-char); border: 2px solid var(--roam-line); box-shadow: 3px 3px 0 var(--roam-line);
  display: inline-flex; flex-wrap: wrap; font-family: 'Courier New', monospace; font-size: .78rem; font-weight: 700; gap: .2rem .6rem;
  margin: 0; max-width: 100%; min-height: 2.5rem; padding: .25rem .6rem; pointer-events: none; transform: rotate(.6deg);
}
.roam__gear { background: var(--roam-bone); border: 2px solid var(--roam-line); color: var(--roam-line); font-family: Arial, Helvetica, sans-serif; font-size: .95rem; font-weight: 900; line-height: 1; padding: .2rem .4rem; }
.roam[data-roam-gear="R"] .roam__gear { background: var(--roam-orange); }
.roam__speed { align-items: baseline; display: inline-flex; gap: .25rem; }
.roam__speed b { font-size: 1.15rem; min-width: 2.2ch; text-align: right; }
.roam__speed small { font-size: .62rem; letter-spacing: .12em; opacity: .8; }
.roam__district { font-family: Arial, Helvetica, sans-serif; font-size: .62rem; font-weight: 900; letter-spacing: .14em; }
.roam__district:empty { display: none; }
.roam__way { align-items: center; color: var(--roam-green); display: inline-flex; gap: .2rem; white-space: nowrap; }
.roam__way-arrow { display: inline-flex; rotate: var(--roam-arrow, 0deg); }
.roam__way b { font-size: .78rem; }
.roam__way.is-here { color: var(--roam-bone); }
.roam__msg { color: var(--roam-orange); letter-spacing: .06em; }
.roam__msg:empty { display: none; }
.roam__msg.is-flash { background: var(--roam-orange); color: var(--roam-line); padding: 0 .35rem; }

/* ---------- the district banner (2.5 s on entry; announced) ---------- */
.roam__banner {
  align-items: center; background: var(--roam-bone); border: 2px solid var(--roam-line); box-shadow: 4px 4px 0 var(--roam-line); color: var(--roam-line);
  display: grid; justify-items: center; left: 50%; margin: 0; padding: .35rem 1rem .45rem; pointer-events: none; position: absolute; top: 21%;
  transform: translateX(-50%) rotate(-1.2deg); max-width: calc(100% - 2 * var(--roam-left));
}
.roam__banner small { font-size: .55rem; font-weight: 900; letter-spacing: .2em; }
.roam__banner b { font-size: clamp(1.1rem, 2.6vw, 1.7rem); font-weight: 900; letter-spacing: -.01em; line-height: 1.05; text-align: center; }
.roam__banner small:last-child:not(:empty) { background: var(--roam-red); color: var(--roam-bone); margin-top: .2rem; padding: 0 .35rem; }
@media (prefers-reduced-motion: no-preference) {
  .roam__banner:not([hidden]) { animation: roam-banner .32s cubic-bezier(.2, 1.5, .45, 1); }
}
@keyframes roam-banner { from { opacity: 0; scale: .8; } }

/* ---------- the street job's sticker: its gates, the clock and the limit ---------- */
.roam__job {
  align-items: baseline; background: var(--roam-char); border: 2px solid var(--roam-line); box-shadow: 3px 3px 0 var(--roam-line); display: grid;
  gap: .05rem .6rem; grid-template-areas: "title title" "gates time" "cue cue" "missed missed"; grid-template-columns: auto 1fr;
  padding: .3rem .6rem .35rem; pointer-events: none; position: absolute; right: var(--roam-right); top: var(--roam-top); transform: rotate(-.6deg);
}
.roam__job-title { font-size: .6rem; font-weight: 900; grid-area: title; letter-spacing: .16em; }
.roam__job-gates { font-family: 'Courier New', monospace; font-size: .95rem; font-weight: 700; grid-area: gates; }
.roam__job-time { align-items: baseline; display: inline-flex; gap: .4rem; grid-area: time; justify-self: end; }
.roam__job-time b { color: var(--roam-green); font-family: 'Courier New', monospace; font-size: 1.15rem; }
.roam__job-time small { font-size: .55rem; font-weight: 900; letter-spacing: .12em; opacity: .75; }
.roam__job.is-low .roam__job-time b { color: var(--roam-orange); }
.roam__job-cue { font-size: .55rem; font-weight: 900; grid-area: cue; letter-spacing: .1em; opacity: .8; }
.roam__job-cue:empty { display: none; }
.roam__job-missed { background: var(--roam-red); color: var(--roam-bone); font-size: .62rem; font-weight: 900; grid-area: missed; letter-spacing: .1em; margin-top: .2rem; padding: .1rem .35rem; }

/* ---------- the minimap (heading-up; the car points up at its centre) ---------- */
.roam__mini {
  border-radius: 50%; bottom: calc(var(--roam-bottom) + 2.9rem); box-shadow: 3px 3px 0 var(--roam-line); height: var(--roam-mini); left: var(--roam-left);
  pointer-events: none; position: absolute; width: var(--roam-mini);
}
.roam__mini-canvas { border-radius: 50%; display: block; height: 100%; width: 100%; }
.roam[data-roam-paused="true"] .roam__mini { opacity: .6; }

/* ---------- edge chips: places within 150 m the view does not show ---------- */
.roam__chips { inset: 0; list-style: none; margin: 0; padding: 0; pointer-events: none; position: absolute; }
.roam__chip {
  --roam-chip-i: 0;
  align-items: center; background: var(--roam-char); border: 2px solid var(--roam-line); box-shadow: 2px 2px 0 var(--roam-line); column-gap: .35rem;
  display: grid; grid-template-areas: "arrow name" "arrow m"; grid-template-columns: auto minmax(0, 1fr); max-width: min(11rem, 26vw);
  padding: .2rem .45rem; position: absolute; top: calc(36% + var(--roam-chip-i) * 2.9rem);
}
.roam__chip[data-side="left"] { left: var(--roam-left); }
.roam__chip[data-side="right"] { grid-template-areas: "name arrow" "m arrow"; grid-template-columns: minmax(0, 1fr) auto; right: var(--roam-right); text-align: right; }
.roam__chip-arrow { color: var(--roam-orange); font-size: .8rem; font-style: normal; grid-area: arrow; }
.roam__chip b { -webkit-box-orient: vertical; -webkit-line-clamp: 2; display: -webkit-box; font-size: .58rem; font-weight: 900; grid-area: name; letter-spacing: .08em; line-height: 1.15; overflow: hidden; overflow-wrap: anywhere; }
.roam__chip small { font-family: 'Courier New', monospace; font-size: .7rem; font-weight: 700; grid-area: m; opacity: .85; }

/* ---------- the place prompt and STUCK? (E / START; on touch the ACTION button) ---------- */
.roam__prompt {
  align-items: center; background: var(--roam-bone); border: 2px solid var(--roam-line); bottom: 34%; box-shadow: 4px 4px 0 var(--roam-line); color: var(--roam-line);
  display: grid; font-size: .78rem; font-weight: 900; gap: .25rem; letter-spacing: .1em; max-width: min(24rem, 32vw); min-height: var(--roam-target);
  padding: .55rem .9rem; position: absolute; right: var(--roam-right); text-align: left; transform: rotate(-1deg);
}
.roam__prompt[data-kind="locked"], .roam__prompt[data-kind="lineup"] { background: var(--roam-char); border-color: var(--roam-bone); color: var(--roam-bone); }
.roam__prompt[data-kind="locked"] { border-color: var(--roam-red); }
.roam__prompt[data-kind="stuck"] { background: var(--roam-orange); }
.roam__prompt-bar { background: currentColor; display: none; height: 3px; transform: scaleX(var(--roam-left, 1)); transform-origin: 0 50%; }
.roam__prompt[data-kind="stuck"] .roam__prompt-bar { display: block; }
.roam[data-roam-controls="touch"] .roam__prompt { cursor: default; pointer-events: none; } /* (on touch, ACTION is the button) */

/* ---------- bottom: the phone controls (the steering pad, BRAKE and GAS, ACTION over GAS) ---------- */
.roam__drive { align-items: flex-end; bottom: var(--roam-bottom); display: none; gap: .75rem; justify-content: space-between; left: var(--roam-left); position: absolute; right: var(--roam-right); }
.roam[data-roam-mode="roam"][data-roam-controls="touch"] .roam__drive { display: flex; }
.roam:is([data-roam-paused="true"], [data-roam-map="open"]) .roam__drive { opacity: .5; }
.roam__pad {
  background: linear-gradient(rgba(240, 226, 191, .07), rgba(240, 226, 191, 0) 60%), var(--roam-char);
  border: 2px solid var(--roam-line); border-radius: calc(var(--roam-pad-h) / 2); box-shadow: 3px 3px 0 var(--roam-line), inset 0 0 0 2px rgba(240, 226, 191, .16);
  flex: none; height: var(--roam-pad-h); position: relative; width: var(--roam-pad-w);
}
.roam__pad-centre { background: rgba(240, 226, 191, .6); bottom: .55rem; left: 50%; position: absolute; top: .55rem; transform: translateX(-50%); width: 2px; }
.roam__pad-end { color: rgba(240, 226, 191, .5); font-size: .7rem; position: absolute; top: 50%; transform: translateY(-50%); }
.roam__pad-end--l { left: .7rem; } .roam__pad-end--r { right: .7rem; }
.roam__pad-label { color: var(--roam-bone); font-size: .55rem; font-weight: 900; left: 0; letter-spacing: .2em; position: absolute; right: 0; text-align: center; text-shadow: 0 1px 2px #000; top: -1.1rem; }
.roam__pad.is-stale .roam__pad-label { visibility: hidden; }
/* (repair 2, OW125) the knob stands at the pad's centre; js/world-hud.js moves it by a transform (whole pixels, at most knobHz):
   no layout, its own compositor layer */
.roam__pad-knob {
  background: radial-gradient(circle at 38% 34%, #1b1716 0 .2rem, transparent .21rem), radial-gradient(circle at 60% 30%, #1b1716 0 .2rem, transparent .21rem),
    radial-gradient(circle at 46% 54%, #1b1716 0 .24rem, transparent .25rem), radial-gradient(circle at 34% 28%, #6b5f57, #3a302b 45%, #201a17 75%);
  border: 2px solid var(--roam-line); border-radius: 50%; box-shadow: 2px 2px 0 var(--roam-line);
  height: var(--roam-knob); left: 50%; pointer-events: none;
  position: absolute; top: 50%; transform: translate(-50%, -50%); width: var(--roam-knob); will-change: transform;
}
.roam__pad.is-held { border-color: var(--roam-bone); }
.roam__pad.is-held .roam__pad-knob { box-shadow: 0 0 0 3px rgba(231, 120, 43, .65); }
.roam__right { align-items: end; display: grid; flex: none; gap: .6rem; justify-items: end; }
.roam__pedals { align-items: end; display: flex; gap: .5rem; }
.roam__pedal {
  align-content: center; border: 2px solid var(--roam-line); border-radius: .35rem .35rem .6rem .6rem; box-shadow: 3px 3px 0 var(--roam-line);
  display: grid; font-size: .7rem; font-weight: 900; gap: .2rem; justify-items: center; letter-spacing: .16em; position: relative; width: var(--roam-pedal-w);
}
.roam__pedal::before { background: repeating-linear-gradient(rgba(0, 0, 0, .22) 0 3px, transparent 3px 9px); border-radius: inherit; content: ''; inset: .5rem .45rem; opacity: .7; position: absolute; }
.roam__pedal > * { position: relative; }
.roam__pedal small { font-size: .46rem; letter-spacing: .08em; line-height: 1.1; opacity: .85; text-align: center; }
.roam__pedal--brake { background: var(--roam-brake); color: var(--roam-bone); height: var(--roam-brake-h); transform: rotate(-1.5deg); }
.roam__pedal--gas { background: var(--roam-orange); color: var(--roam-line); height: var(--roam-gas-h); transform: rotate(1deg); }
.roam__pedal.is-held { box-shadow: 1px 1px 0 var(--roam-line); filter: brightness(1.18); translate: 2px 3px; }
.roam__pedal.is-overruled { opacity: .7; }
.roam__lift { display: none; font-size: .5rem; letter-spacing: .1em; }
.roam .is-stale .roam__lift { display: block; }
.roam__pad .roam__lift { color: var(--roam-orange); left: 0; position: absolute; right: 0; text-align: center; text-shadow: 0 1px 2px #000; top: -1.15rem; }
.roam .is-stale { outline: 2px dashed var(--roam-orange); outline-offset: 2px; }
/* ACTION: above GAS, as wide as it; START at a place, TOW when stuck */
.roam__act {
  background: var(--roam-bone); border: 2px solid var(--roam-line); box-shadow: 3px 3px 0 var(--roam-line); color: var(--roam-line); font-size: .8rem; font-weight: 900;
  letter-spacing: .14em; min-height: var(--roam-target); padding: .3rem .6rem; transform: rotate(-1.5deg); width: calc(2 * var(--roam-pedal-w) + .5rem);
}
@media (prefers-reduced-motion: no-preference) { .roam__act:not([hidden]) { animation: roam-pop .25s cubic-bezier(.2, 1.6, .4, 1); } }
@keyframes roam-pop { from { opacity: 0; scale: .7; } }

/* ---------- keyboard players: one compact line of keys ---------- */
.roam__keys {
  background: var(--roam-char); border: 1px solid rgba(240, 226, 191, .3); bottom: var(--roam-bottom); color: var(--roam-bone); display: none;
  font-size: .6rem; font-weight: 900; left: var(--roam-left); letter-spacing: .12em; line-height: 1.9; margin: 0; max-width: calc(100% - var(--roam-left) - var(--roam-right));
  padding: .3rem .6rem; pointer-events: none; position: absolute;
}
.roam[data-roam-mode="roam"][data-roam-controls="keys"] .roam__keys { display: block; }
.roam__keys i { font-style: normal; opacity: .5; padding: 0 .2rem; }
.roam kbd { background: var(--roam-bone); border: 1px solid var(--roam-line); border-radius: 3px; box-shadow: 0 2px 0 var(--roam-line); color: var(--roam-line); font-family: inherit; font-size: .62rem; margin-right: .2rem; padding: 0 .3rem; }

/* ---------- cards: the place card, the job sheet, the pause card ---------- */
.roam__card {
  background: var(--roam-paper); box-shadow: 0 0 0 2.5px var(--roam-line), .5rem .6rem 0 rgba(10, 8, 22, .82); box-sizing: border-box; color: var(--roam-ink);
  display: grid; gap: .5rem; max-height: calc(100% - var(--roam-top) - var(--roam-bottom) - 3.75rem); overflow: auto; overscroll-behavior: contain;
  padding: .85rem 1rem 1rem; pointer-events: auto; position: absolute; z-index: 2;
}
.roam__card p { margin: 0; }
.roam__kicker { color: #6b5f4a; font-size: .58rem; font-weight: 900; letter-spacing: .16em; }
.roam__card-title { font-size: clamp(1.1rem, 1.9vw, 1.45rem); font-weight: 900; letter-spacing: -.02em; line-height: 1; }
.roam__card-title:focus { outline: none; }
.roam__card-note { color: #4f4739; font-size: .72rem; font-weight: 700; }
.roam__card-note:empty { display: none; }
.roam__card-actions { display: grid; gap: .45rem; }
.roam__action {
  align-items: center; background: var(--roam-ink); border: 2px solid var(--roam-line); box-shadow: 3px 3px 0 rgba(0, 0, 0, .35); color: var(--roam-paper); display: inline-flex;
  font-size: .68rem; font-weight: 900; gap: .45rem; justify-content: center; letter-spacing: .14em; min-height: var(--roam-target); padding: .5rem .9rem;
}
.roam__action--go { background: var(--roam-orange); color: var(--roam-line); }
.roam__action--off { background: transparent; color: var(--roam-ink); }
.roam__action--big { font-size: .82rem; min-height: 3.5rem; }
.roam__action.is-locked { border-style: dashed; cursor: default; }

/* the place card: right of the car (the car is stopped; the road stays in view) */
.roam__place-card, .roam__result { right: var(--roam-right); top: calc(var(--roam-top) + 3.6rem); transform: rotate(.5deg); width: min(25rem, calc(100% - var(--roam-left) - var(--roam-right))); }
.roam__brief { border-block: 1px dashed rgba(0, 0, 0, .35); display: grid; gap: .3rem; padding: .4rem 0; }
.roam__brief-route { font-size: .62rem; font-weight: 900; letter-spacing: .12em; }
.roam__brief-route:empty, .roam__brief-task:empty, .roam__brief-facts:empty { display: none; }
.roam__brief-task { font-family: 'Courier New', monospace; font-size: .82rem; font-weight: 700; }
.roam__brief-facts { font-family: 'Courier New', monospace; font-size: .78rem; font-weight: 700; }
.roam__grades { display: grid; gap: .12rem; list-style: none; margin: 0; padding: 0; }
.roam__grades li { align-items: center; display: flex; font-size: .6rem; font-weight: 800; gap: .5rem; letter-spacing: .05em; line-height: 1.25; }
.roam__pips { color: inherit; display: inline-flex; flex: none; gap: 2px; }
.roam__pips i { border: 1.5px solid currentColor; border-radius: 50%; height: .62rem; width: .62rem; }
.roam__pips[data-on="1"] i:nth-child(-n+1), .roam__pips[data-on="2"] i:nth-child(-n+2), .roam__pips[data-on="3"] i { background: var(--roam-orange); border-color: var(--roam-line); }
.roam__rows { display: grid; gap: 0; list-style: none; margin: 0; padding: 0; }
.roam__rows > li { align-items: center; border-top: 1px dashed rgba(0, 0, 0, .3); column-gap: .6rem; display: grid; grid-template-areas: "text pips go"; grid-template-columns: minmax(0, 1fr) auto auto; padding: .35rem 0; }
.roam__rows > li:first-child { border-top: 0; }
.roam__row-text { display: grid; grid-area: text; min-width: 0; }
.roam__row-name { font-size: .74rem; font-weight: 900; letter-spacing: .08em; line-height: 1.15; }
.roam__row-facts { font-size: .55rem; font-weight: 900; letter-spacing: .1em; opacity: .75; }
.roam__row-best { font-family: 'Courier New', monospace; font-size: .7rem; font-weight: 700; opacity: .8; }
.roam__row-facts:empty, .roam__row-best:empty { display: none; }
.roam__rows .roam__pips { grid-area: pips; }
.roam__row-go { grid-area: go; letter-spacing: .1em; min-width: 6.5rem; padding-inline: .7rem; white-space: nowrap; }
/* a one-activity place: its brief, then one big START */
.roam__place-card.is-single .roam__rows > li { grid-template-areas: "go go"; grid-template-columns: 1fr; padding-top: .1rem; }
.roam__place-card.is-single .roam__rows :is(.roam__row-text, .roam__pips) { display: none; }
.roam__place-card.is-single .roam__row-go { font-size: .82rem; min-height: 3.5rem; width: 100%; }

/* the job sheet (a street job's result) */
.roam__result-title { font-size: clamp(1.4rem, 3.2vw, 1.85rem); }
.roam__result.is-late .roam__result-title { color: var(--roam-brake); }
.roam__stamps { display: flex; gap: .55rem; }
.roam__stamps i { border: 2.5px dashed rgba(0, 0, 0, .3); border-radius: 50%; height: 2.2rem; width: 2.2rem; }
.roam__stamps[data-on="1"] i:nth-child(-n+1), .roam__stamps[data-on="2"] i:nth-child(-n+2), .roam__stamps[data-on="3"] i {
  background: radial-gradient(circle, transparent 0 38%, rgba(23, 17, 15, .35) 39% 44%, transparent 45%), var(--roam-orange); border: 3px solid var(--roam-line); rotate: -9deg;
}
.roam__stamps i:nth-child(2) { rotate: 4deg; } .roam__stamps i:nth-child(3) { rotate: -3deg; }
@media (prefers-reduced-motion: no-preference) {
  .roam__stamps[data-on="1"] i:nth-child(-n+1), .roam__stamps[data-on="2"] i:nth-child(-n+2), .roam__stamps[data-on="3"] i { animation: roam-stamp .32s cubic-bezier(.2, 1.6, .4, 1) backwards; }
  .roam__stamps i:nth-child(2) { animation-delay: .14s !important; } .roam__stamps i:nth-child(3) { animation-delay: .28s !important; }
}
@keyframes roam-stamp { from { opacity: 0; scale: 1.7; } }
.roam__figures { border-block: 1px dashed rgba(0, 0, 0, .35); display: grid; gap: .5rem; grid-template-columns: repeat(3, 1fr); margin: 0; padding: .35rem 0; }
.roam__figures dt { font-size: .55rem; font-weight: 900; letter-spacing: .14em; }
.roam__figures dd { font-family: 'Courier New', monospace; font-size: 1.02rem; font-weight: 700; margin: 0; }
.roam__result-actions { grid-template-areas: "on on" "retry back"; grid-template-columns: 1fr 1fr; }
.roam__result-actions > [data-roam-cmd="job-drive-on"] { grid-area: on; }
.roam__result-actions > [data-roam-cmd="job-retry"] { grid-area: retry; }
.roam__result-actions > [data-roam-cmd="job-tow-back"] { grid-area: back; }

/* the pause card: in the middle (nothing moves) */
.roam__pause { left: 50%; top: 50%; transform: translate(-50%, -48%) rotate(-1deg); width: min(21rem, calc(100% - var(--roam-left) - var(--roam-right))); z-index: 3; }
.roam__tows { display: grid; gap: .3rem; grid-template-columns: repeat(2, minmax(0, 1fr)); list-style: none; margin: 0; padding: 0; }
.roam__tow-to { font-size: .58rem; letter-spacing: .06em; line-height: 1.15; min-height: 2.75rem; padding: .3rem .45rem; text-align: center; width: 100%; }
/* TOW TOâ€¦ open: only the list and BACK */
.roam__pause.is-tows .roam__pause-actions > :not(.roam__tows, [data-roam-cmd="tow-list"]), .roam__pause.is-tows > .roam__card-note { display: none; }
.roam__pause.is-tows .roam__pause-actions { grid-template-columns: 1fr; }
.roam__pause.is-tows .roam__pause-actions > :is(.roam__tows, [data-roam-cmd="tow-list"]) { grid-column: 1 / -1; }

/* ---------- the full map: a dialog over the world ---------- */
.roam__map {
  background: #0d0e0b; border: 2px solid var(--roam-line); bottom: var(--roam-bottom); box-shadow: 0 0 0 2px rgba(240, 226, 191, .25), .5rem .6rem 0 rgba(10, 8, 22, .82);
  display: grid; grid-template-rows: auto minmax(0, 1fr); left: var(--roam-left); pointer-events: auto; position: absolute; right: var(--roam-right); top: var(--roam-top); z-index: 4;
}
.roam__map-head { align-items: center; background: var(--roam-bone); border-bottom: 2px solid var(--roam-line); color: var(--roam-line); display: flex; gap: .75rem; padding: .3rem .4rem .3rem .8rem; }
.roam__map-title { font-size: 1.05rem; font-weight: 900; letter-spacing: -.01em; margin: 0; }
.roam__map-title:focus { outline: none; }
.roam__map-hint { flex: 1; font-size: .55rem; font-weight: 900; letter-spacing: .12em; margin: 0; opacity: .7; }
.roam__map-close { flex: none; }
.roam__map-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(14rem, 17rem); min-height: 0; }
.roam__map-view { min-height: 0; min-width: 0; position: relative; }
.roam__map-canvas { cursor: grab; display: block; height: 100%; touch-action: none; width: 100%; }
.roam__map-zoom { bottom: .6rem; display: grid; gap: .35rem; position: absolute; right: .6rem; }
.roam__map-side { background: var(--roam-paper); border-left: 2px solid var(--roam-line); color: var(--roam-ink); display: grid; grid-template-rows: auto minmax(0, 1fr); min-height: 0; }
.roam__map-pick { border-bottom: 2px solid var(--roam-line); display: grid; gap: .35rem; padding: .6rem .7rem .7rem; }
.roam__map-pick-name { font-size: 1rem; font-weight: 900; line-height: 1.05; }
.roam__map-pick-actions { display: grid; gap: .35rem; grid-template-columns: 1fr 1fr; }
.roam__map-pick-actions .roam__action { font-size: .58rem; gap: .3rem; letter-spacing: .06em; padding-inline: .4rem; }
.roam__map-list { display: grid; gap: 2px; list-style: none; margin: 0; overflow: auto; overscroll-behavior: contain; padding: .35rem; align-content: start; }
.roam__place {
  align-items: center; background: transparent; border: 0; color: inherit; display: flex; gap: .5rem; justify-content: space-between; min-height: var(--roam-target);
  padding: .3rem .5rem; text-align: left; width: 100%;
}
.roam__place b { font-size: .66rem; font-weight: 900; letter-spacing: .08em; line-height: 1.15; }
/* (repair R4) each place's district under its name: a district is found by name in the list */
.roam__place-text { display: grid; gap: .1rem; min-width: 0; }
.roam__place-district { font-size: .56rem; font-style: normal; font-weight: 800; letter-spacing: .1em; line-height: 1.15; opacity: .6; }
.roam__place-district:empty { display: none; }
.roam__place small { flex: none; font-family: 'Courier New', monospace; font-size: .72rem; font-weight: 700; opacity: .75; }
.roam__map-list li + li { border-top: 1px dashed rgba(0, 0, 0, .25); }
.roam__place.is-picked { background: var(--roam-ink); color: var(--roam-paper); }
.roam__place.is-way b::before { color: var(--roam-orange); content: 'â—† '; }
.roam__place.is-locked { opacity: .5; }

/* ---------- phones (a coarse pointer, or a narrow screen): the 100 px minimap ---------- */
.roam[data-roam-controls="touch"] { --roam-mini: 100px; }
@media (max-width: 760px) { .roam { --roam-mini: 100px; } }

/* touch on a large landscape screen (tablets): the minimap top right, under the hub's MENU */
.roam[data-roam-controls="touch"] .roam__mini { bottom: auto; left: auto; right: var(--roam-right); top: var(--roam-top); }
.roam[data-roam-controls="touch"] .roam__job { top: calc(var(--roam-top) + var(--roam-mini) + .6rem); }
/* touch: the prompt stands left of ACTION, just above the thumbs */
.roam[data-roam-controls="touch"] .roam__prompt { bottom: calc(var(--roam-bottom) + var(--roam-gas-h) + .6rem); right: calc(var(--roam-right) + 2 * var(--roam-pedal-w) + 1.25rem); }

/* ---------- phones upright (tall: the car 25-73% of the height, 28-72% of the width) ---------- */
@media (orientation: portrait) {
  .roam { --roam-mini: 100px; }
  /* the bar shares the first row with the minimap; the status line under the bar, both above the horizon */
  .roam__head { max-width: calc(100% - var(--roam-left) - var(--roam-right) - var(--roam-mini) - .5rem); }
  .roam__mini { bottom: auto; left: auto; right: var(--roam-right); top: var(--roam-top); }
  /* the right column under the minimap (right of the car: x 282 and up on a 390 px phone): the job, then the banner */
  .roam[data-roam-mode] .roam__job { max-width: 5.75rem; top: calc(var(--roam-top) + var(--roam-mini) + .6rem); }
  .roam__job { grid-template-areas: "title" "gates" "time" "cue" "missed"; grid-template-columns: 1fr; }
  .roam__job-time { flex-wrap: wrap; gap: 0 .3rem; justify-self: start; }
  .roam__job-time b { font-size: 1rem; }
  .roam__job-missed { font-size: .5rem; }
  .roam__banner { left: auto; max-width: 5.75rem; padding: .3rem .45rem .4rem; right: var(--roam-right); top: calc(var(--roam-top) + var(--roam-mini) + .6rem); transform: rotate(-1.2deg); }
  .roam__banner b { font-size: .95rem; overflow-wrap: anywhere; }
  .roam__banner small { font-size: .45rem; letter-spacing: .12em; }
  /* (I2, P1.20) the job sticker's height varies (a wrapped title, the cue, MISSED GATE), so no fixed place under it holds:
     during a job the district banner yields here (it is still announced) */
  .roam[data-roam-job]:not([data-roam-job=""]) .roam__banner { display: none; }
  /* the prompt: the band between the car and the thumbs */
  .roam[data-roam-mode] .roam__prompt { bottom: calc(var(--roam-bottom) + var(--roam-gas-h) + .6rem); left: var(--roam-left); max-width: none; right: calc(var(--roam-right) + 2 * var(--roam-pedal-w) + 1.25rem); }
  .roam[data-roam-mode][data-roam-controls="keys"] .roam__prompt { bottom: calc(var(--roam-bottom) + 3.4rem); right: var(--roam-right); }
  .roam__chip { max-width: min(6.25rem, 24vw); top: calc(40% + var(--roam-chip-i) * 3.8rem); } /* (repair 2: a chip may take three lines) */
  /* cards: a sheet above the bottom edge (over the thumbs: the car is stopped) */
  .roam__place-card, .roam__result { bottom: var(--roam-bottom); left: var(--roam-left); max-height: calc(100% - var(--roam-top) - 3.75rem - var(--roam-bottom)); right: var(--roam-right); top: auto; transform: rotate(.4deg); width: auto; }
  /* (repair R2, P1.20) the sheet's foot covers the thumbs' band (from the bottom edge up to the GAS pedal's top): a thumb
     resting where BRAKE or GAS stand meets the note or CLOSE, never a launch */
  .roam[data-roam-controls="touch"] .roam__place-card > .roam__card-note { min-height: calc(var(--roam-gas-h) - 1.5rem - var(--roam-target) + .5rem); }
  .roam[data-roam-controls="touch"] .roam__place-card > .roam__card-note:empty + .roam__card-actions { align-content: end; min-height: calc(var(--roam-gas-h) - 1rem + .5rem); }
  .roam__map { top: calc(var(--roam-top) - .25rem); }
  /* the map over the place list: the list's row is a share of the dialog (a max-height on the list itself resolved against
     its own auto row and left a gap under it) */
  .roam__map-body { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) minmax(0, 40%); }
  .roam__map-side { border-left: 0; border-top: 2px solid var(--roam-line); }
  .roam__map-hint { display: none; }
  .roam__map-list { grid-template-columns: 1fr 1fr; }
}
/* narrow screens: the bar keeps its icons (the words stay for screen readers); VIEW shows CHASE or SEAT under its icon */
@media (max-width: 34rem) {
  .roam__bar { gap: .25rem; }
  .roam__btn:not(.roam__btn--off) .roam__word, .roam__view-word { clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }
  .roam__btn:not(.roam__btn--off) { padding-inline: .35rem; }
  .roam__btn--view { flex-direction: column; gap: .1rem; padding-block: .2rem; }
  .roam__view-short { display: block; font-size: .5rem; letter-spacing: .08em; line-height: 1; }
  /* SWITCH OFF keeps its words (never an icon alone: it is the way out), stacked */
  .roam__btn--off { gap: .25rem; letter-spacing: .04em; line-height: 1.05; padding-inline: .4rem; text-align: left; }
  .roam__btn--off span { width: min-content; }
  /* (repair 2) the place's short name in whole words: THE / WEIGHBRIDGE (79 px at .04em) fits a 6.75rem chip; at most three lines;
     the chip's inner edge stays 14 px clear of the car's box at rest (390 px wide: the car from 35%) */
  .roam__chip { column-gap: .25rem; max-width: 6.75rem; padding: .2rem .3rem; }
  .roam__chip b { -webkit-line-clamp: 3; letter-spacing: .04em; overflow-wrap: normal; }
}

/* ---------- short landscape phones (844x390: the car 36-64% of the width, from 34% down) ---------- */
@media (orientation: landscape) and (max-height: 500px) {
  .roam { --roam-pad-h: 4.25rem; --roam-knob: 3.15rem; --roam-brake-h: 5rem; --roam-gas-h: 5.75rem; --roam-pad-w: clamp(11rem, calc(30 * var(--roam-vw)), 17rem); --roam-mini: 100px; }
  .roam__pedal, .roam__pedals, .roam__act { --roam-pedal-w: clamp(4.25rem, calc(11 * var(--roam-vw)), 5.5rem); }
  /* one row: the bar, then the status line beside it, shrinking and wrapping inside itself (a second row would reach the
     road above the car) */
  .roam__head { flex-wrap: nowrap; max-width: calc(100% - var(--roam-left) - var(--roam-right) - var(--roam-mini) - .75rem); }
  .roam__bar { gap: .3rem; }
  .roam__btn:not(.roam__btn--off) .roam__word, .roam__view-word { clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }
  .roam__btn:not(.roam__btn--off) { padding-inline: .35rem; }
  .roam__btn--view { flex-direction: column; gap: .1rem; padding-block: .2rem; }
  .roam__view-short { display: block; font-size: .5rem; letter-spacing: .08em; line-height: 1; }
  .roam__btn--off { gap: .3rem; letter-spacing: .06em; line-height: 1.05; padding-inline: .45rem; text-align: left; }
  .roam__btn--off span { width: min-content; }
  .roam__status { flex: 0 1 auto; gap: 0 .5rem; min-height: var(--roam-target); min-width: 0; padding-block: .15rem; }
  .roam__status > * { line-height: 1.25; }
  .roam__mini { bottom: auto; left: auto; right: var(--roam-right); top: var(--roam-top); }
  /* the car takes the middle third from about 35% of the height down to the bottom edge: everything else stands in a
     column either side of it. Left (to 34vw): the job sticker under the bar, then one chip. Right (from 63vw): the
     minimap, then the banner or one chip, then the prompt, ACTION, the pedals. */
  .roam[data-roam-mode] .roam__job { left: var(--roam-left); right: auto; top: calc(var(--roam-top) + var(--roam-target) + .55rem); max-width: 34vw; grid-template-areas: "title title" "gates time" "missed missed"; }
  .roam__job-cue { display: none; }
  .roam__banner { left: auto; max-width: calc(37vw - var(--roam-right)); padding: .25rem .7rem .35rem; right: var(--roam-right); top: calc(var(--roam-top) + var(--roam-mini) + .55rem); transform: rotate(-1.2deg); }
  .roam__banner b { font-size: 1rem; }
  .roam__chip { max-width: 30vw; top: calc(var(--roam-top) + var(--roam-target) + .7rem); }
  .roam[data-roam-job]:not([data-roam-job=""]) .roam__chip[data-side="left"] { top: calc(var(--roam-top) + var(--roam-target) + 4rem); }
  .roam__chip[data-side="right"] { max-width: calc(37vw - var(--roam-right)); top: calc(var(--roam-top) + var(--roam-mini) + .6rem); }
  .roam__chip[data-i="1"], .roam:has(.roam__banner:not([hidden])) .roam__chip[data-side="right"] { display: none; } /* (one a side; the banner's slot) */
  /* the prompt: the right column, above ACTION */
  .roam[data-roam-mode] .roam__prompt { bottom: calc(var(--roam-bottom) + var(--roam-gas-h) + var(--roam-target) + 1.1rem); left: 63vw; max-width: none; padding: .4rem .7rem; right: var(--roam-right); }
  .roam[data-roam-mode][data-roam-controls="keys"] .roam__prompt { bottom: calc(var(--roam-bottom) + 3.4rem); }
  .roam__keys { font-size: .55rem; line-height: 1.7; }
  /* cards: the right half, from under the hub's row to the bottom (over the pedals: the car is stopped) */
  .roam__place-card, .roam__result { bottom: var(--roam-bottom); gap: .35rem; max-height: none; padding: .55rem .75rem .7rem; top: var(--roam-top); width: min(23rem, calc(36 * var(--roam-vw))); }
  .roam__card-title { font-size: 1.05rem; }
  /* (I2, P1.20) a street job's brief is taller than a phone held sideways: the brief scrolls inside the card, and its START
     row and CLOSE stay in view at the card's foot */
  .roam__place-card { display: flex; flex-direction: column; overflow: hidden; }
  .roam__place-card > * { flex: 0 0 auto; }
  .roam__place-card > .roam__brief { flex: 0 1 auto; min-height: 3rem; overflow: auto; overscroll-behavior: contain; }
  /* (repair R2, P1.20) a notice board's four rows are taller than a phone held sideways: the rows scroll inside the card,
     and the note and CLOSE stand at its foot, always in view. The foot covers the band where BRAKE and GAS stand under
     the card (bottom edge up to the GAS pedal's top), so a thumb resting there meets the note or CLOSE, never a launch. */
  .roam__place-card:not(.is-single) > .roam__rows { flex: 0 1 auto; min-height: 3.25rem; overflow: auto; overscroll-behavior: contain; }
  .roam__place-card > .roam__card-note { margin-top: auto; min-height: calc(var(--roam-gas-h) - 1.05rem - var(--roam-target) + .5rem); }
  .roam__place-card > .roam__card-note:empty + .roam__card-actions { align-content: end; margin-top: auto; min-height: calc(var(--roam-gas-h) - .7rem + .5rem); }
  .roam__rows > li { padding: .2rem 0; }
  .roam__action--big { min-height: var(--roam-target); }
  .roam__stamps i { height: 1.6rem; width: 1.6rem; }
  .roam__result-actions { grid-template-areas: "on on on" "retry retry back"; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* the pause card under the bar (RESUME stays in reach on the bar), to the bottom edge */
  .roam__pause { gap: .4rem; max-height: calc(100% - var(--roam-top) - var(--roam-target) - .6rem - var(--roam-bottom)); padding: .6rem .9rem .75rem; top: calc(var(--roam-top) + var(--roam-target) + .6rem); transform: translateX(-50%) rotate(-.6deg); width: min(30rem, calc(100% - var(--roam-left) - var(--roam-right))); }
  .roam__pause-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .roam__pause-actions > .roam__action--go, .roam__pause-actions > .roam__tows { grid-column: 1 / -1; }
  /* (I3, P1b.20) the TOW TO list was four across here, and the names ran into the next button (THE WEIGHBRIDGE, RESPRAY &
     PRAY, THE CRUSHER): `.roam button { font: inherit }` outranks `.roam__tow-to`'s .58rem, so they showed at the body's
     14 px. Now the list's own .58rem holds, three across, so the longest word (WEIGHBRIDGE, about 71 px) keeps to one line
     in its button (about 91 px inside; four across left 63); the last row sits under the card's fold, inside the card's own
     scroll. A word that still could not fit breaks inside its button, never over the next one. */
  .roam__tows { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .roam .roam__tow-to { font-size: .58rem; overflow-wrap: anywhere; }
  .roam__map { top: calc(var(--roam-top) - 2.9rem); }
  .roam__map-hint { display: none; }
  .roam__map-body { grid-template-columns: minmax(0, 1fr) minmax(12rem, 15rem); }
}

/* ---------- the VIEW button alone: parked, and inside every challenge (OW25, OW43; P1.20) ----------
   In the hub's own top row, just left of its controls (MENU; on desktop CLEAR VISUALS too, when shown), where neither the
   parking nor the race bar reaches (both run from the left, under that row) and nothing of the coffee job sits.
   js/world-hud.js measures the hub's controls into --roam-alone-right / --roam-alone-top / --roam-alone-h; without them it
   falls back to the row under MENU, at the right. */
.roam:not([data-roam-mode="roam"]) .roam__head { left: auto; max-width: none; right: var(--roam-alone-right, var(--roam-right)); top: var(--roam-alone-top, var(--roam-top)); }
.roam:not([data-roam-mode="roam"]) .roam__btn--view { min-height: var(--roam-alone-h, 2.75rem); min-width: 2.75rem; padding-block: .2rem; transform: none; }

/* ---------- the rest of the hub while roaming ---------- */
.hub:has(.roam[data-roam-mode="roam"]:not([hidden])) { min-height: 0; }
.hub:has(.roam[data-roam-mode="roam"]:not([hidden])) :is(.hub__things, .hub__email) { display: none; }
/* captions above the thumbs and the minimap */
.hub:has(.roam[data-roam-mode="roam"][data-roam-controls="touch"]:not([hidden])) .hub__subtitle { bottom: calc(max(.75rem, env(safe-area-inset-bottom, 0px)) + 11.5rem); }
@media (orientation: landscape) and (max-height: 500px) {
  .hub:has(.roam[data-roam-mode="roam"][data-roam-controls="touch"]:not([hidden])) .hub__subtitle { bottom: calc(max(.75rem, env(safe-area-inset-bottom, 0px)) + .25rem); max-width: min(20rem, 30vw); }
}
/* phones put CLEAR VISUALS on a second row at the right (hub.css): start below it */
@media (max-width: 760px), (max-width: 1050px) and (orientation: portrait) {
  .hub:has([data-hub-clear]:not([hidden])) .roam { --roam-top: calc(env(safe-area-inset-top, 0px) + 7.1rem); }
}

/* ========== PHASE 1b (H1): the handbrake, the gamepad's legend, the floor badge, the skills HUD (OW105, OW111, OW112,
   OW133; P1b.20). Every new piece is pointer-events none except the DRIFT button and the pause card's HAPTICS toggle. ==== */

/* ---------- the phone's DRIFT button: directly above GAS, in ACTION's slot (they never show together; OW112) ---------- */
.roam__drift {
  align-items: center; background: var(--roam-char); border: 2px solid var(--roam-line); border-radius: .35rem; box-shadow: 3px 3px 0 var(--roam-line);
  color: var(--roam-bone); display: grid; font-size: .74rem; font-weight: 900; justify-items: center; letter-spacing: .16em; min-height: var(--roam-target);
  padding: .3rem .4rem; transform: rotate(-1deg); width: var(--roam-pedal-w);
}
.roam__drift.is-drifting { background: var(--roam-orange); color: var(--roam-line); }
.roam__drift.is-held { box-shadow: 1px 1px 0 var(--roam-line); filter: brightness(1.15); translate: 2px 3px; }
/* (repair 2, P1b.21) HORN on the touch controls while roaming (js/world-hud.js shows it; on the keys it is H, in the seat the wheel's
   hub too): left of DRIFT, over BRAKE, as wide as a pedal, its foot on DRIFT's; never with ACTION (it takes that row). In the bar it
   pushed SWITCH OFF into the minimap on a 390 px phone */
.roam__right { position: relative; }
.roam__horn {
  align-items: center; background: var(--roam-char); border: 2px solid var(--roam-line); border-radius: .35rem; bottom: calc(var(--roam-gas-h) + .6rem);
  box-shadow: 3px 3px 0 var(--roam-line); color: var(--roam-bone); display: inline-flex; font-size: .62rem; font-weight: 900; gap: .3rem; justify-content: center;
  letter-spacing: .12em; min-height: var(--roam-target); padding: .3rem .3rem; position: absolute; right: calc(var(--roam-pedal-w) + .5rem); transform: rotate(1deg); width: var(--roam-pedal-w);
}
.roam__horn.is-held { background: var(--roam-orange); box-shadow: 1px 1px 0 var(--roam-line); color: var(--roam-line); translate: 2px 3px; }

/* ---------- a gamepad's legend in place of the key line while it drives (U24) ---------- */
.roam__padkeys {
  background: var(--roam-char); border: 1px solid rgba(240, 226, 191, .3); bottom: var(--roam-bottom); color: var(--roam-bone); display: none;
  font-size: .6rem; font-weight: 900; left: var(--roam-left); letter-spacing: .12em; line-height: 1.9; margin: 0; max-width: calc(100% - var(--roam-left) - var(--roam-right));
  padding: .3rem .6rem; pointer-events: none; position: absolute;
}
.roam__padkeys i { font-style: normal; opacity: .5; padding: 0 .2rem; }
.roam[data-roam-mode="roam"][data-roam-controls="keys"][data-roam-pad="on"] .roam__padkeys { display: block; }
.roam[data-roam-mode="roam"][data-roam-controls="keys"][data-roam-pad="on"] .roam__keys { display: none; }

/* ---------- the minimap's floor badge (OW105): UNDER, P1-P3, ROOF; in the box's free corner, outside the circle ---------- */
.roam__floor {
  background: var(--roam-bone); border: 2px solid var(--roam-line); bottom: 0; box-shadow: 2px 2px 0 var(--roam-line); color: var(--roam-line);
  font-family: Arial, Helvetica, sans-serif; font-size: .58rem; font-weight: 900; letter-spacing: .08em; line-height: 1; padding: .15rem .3rem;
  pointer-events: none; position: absolute; right: 0; transform: rotate(-3deg);
}
.roam__floor[data-kind="under"] { background: var(--roam-char); border-color: var(--roam-bone); color: var(--roam-bone); }
.roam__floor[data-kind="roof"] { background: var(--roam-orange); }

/* ---------- the skills HUD (OW133): the chain panel and the lines under it ---------- */
.roam__skills {
  display: flex; flex-direction: column; gap: .35rem; pointer-events: none; position: absolute;
  /* desktop: the right column (F26: the meter at x 1336-1584, y 324-570 at 1600 x 900) */
  right: var(--roam-right); top: 36%; width: 15.5rem;
}
.roam:not([data-roam-mode="roam"]) :is(.roam__skills, .roam__stamp, .roam__big, .roam__zone) { display: none !important; }
/* never under a card, the job sheet, the pause card or the map; while a place prompt stands (it shares the right column) */
.roam[data-roam-paused="true"] :is(.roam__skills, .roam__stamp, .roam__big), .roam[data-roam-map="open"] :is(.roam__skills, .roam__stamp, .roam__big, .roam__zone),
.roam:has(.roam__place-card:not([hidden]), .roam__result:not([hidden])) :is(.roam__skills, .roam__stamp, .roam__big, .roam__zone),
.roam[data-roam-asking="on"] .roam__skills { display: none; }
.roam__chain {
  background: var(--roam-char); border: 2px solid var(--roam-line); box-shadow: 3px 3px 0 var(--roam-line); display: grid; gap: .3rem;
  padding: .45rem .55rem .5rem; transform: rotate(-.6deg);
}
.roam__meter { display: grid; gap: .25rem; }
.roam__meter-head { align-items: baseline; display: flex; gap: .45rem; margin: 0; min-height: 1.2rem; }
.roam__meter-kind { font-size: .7rem; font-weight: 900; letter-spacing: .16em; }
.roam__meter[data-tier="great"] .roam__meter-kind, .roam__meter[data-tier="awesome"] .roam__meter-kind, .roam__meter[data-tier="ultimate"] .roam__meter-kind { color: var(--roam-orange); }
.roam__meter-pts { font-family: 'Courier New', monospace; font-size: 1.15rem; font-weight: 700; margin-left: auto; }
.roam__meter-pts:empty { display: none; }
.roam__meter-bar { background: rgba(240, 226, 191, .14); border: 1.5px solid var(--roam-line); display: block; height: .6rem; position: relative; }
.roam__meter-fill { background: var(--roam-orange); inset: 0 auto 0 0; position: absolute; width: calc(var(--roam-fill, 0) * 100%); }
.roam__meter-bar em { background: var(--roam-bone); bottom: -3px; position: absolute; top: -3px; width: 2px; }
.roam__meter-bar em:nth-of-type(1) { left: calc(600 / 3600 * 100%); }   /* GREAT */
.roam__meter-bar em:nth-of-type(2) { left: calc(1500 / 3600 * 100%); }  /* AWESOME */
.roam__meter-bar em:nth-of-type(3) { left: calc(3000 / 3600 * 100%); }  /* ULTIMATE */
.roam__chain-row { align-items: center; display: flex; gap: .55rem; margin: 0; }
/* the multiplier: its ring is the 3.0 s bank window (--roam-window 1 .. 0) */
.roam__mult { display: grid; flex: none; height: 2.6rem; place-items: center; position: relative; width: 2.6rem; }
.roam__ring { height: 100%; inset: 0; position: absolute; transform: rotate(-90deg); width: 100%; }
.roam__ring-bg, .roam__ring-arc { fill: none; stroke-width: 3.2; }
.roam__ring-bg { stroke: rgba(240, 226, 191, .18); }
.roam__ring-arc { stroke: var(--roam-orange); stroke-dasharray: calc(var(--roam-window, 1) * 100) 100; }
.roam__mult b { font-family: 'Courier New', monospace; font-size: 1rem; font-weight: 700; position: relative; }
.roam__chain[data-mult="5"] .roam__mult b { color: var(--roam-orange); }
.roam__total { background: var(--roam-bone); border: 2px solid var(--roam-line); color: var(--roam-line); display: grid; flex: 1; min-width: 0; padding: .1rem .45rem; transform: rotate(.8deg); }
.roam__total small { font-size: .7rem; font-weight: 900; letter-spacing: .12em; }
.roam__total b { font-family: 'Courier New', monospace; font-size: 1.15rem; font-weight: 700; line-height: 1.05; }
.roam__chain[data-circles="circles"] .roam__total { background: #b9ad94; }
.roam__feed { display: grid; gap: .1rem; list-style: none; margin: 0; padding: 0; }
/* (review fix M4) the skills' small text: at least 11 px on every form (it was 8-9.9 px; the first-drift hint the smallest on screen) */
.roam__feed-item { align-items: baseline; display: flex; font-size: .72rem; font-weight: 900; gap: .4rem; justify-content: space-between; letter-spacing: .08em; }
.roam__feed-item:not(:first-child) { opacity: .62; }
.roam__feed-item span { color: var(--roam-green); font-family: 'Courier New', monospace; font-size: .8rem; font-weight: 700; letter-spacing: 0; }
.roam__practice {
  align-items: baseline; background: var(--roam-char); border: 2px solid var(--roam-line); box-shadow: 2px 2px 0 var(--roam-line); display: flex; flex-wrap: wrap;
  font-size: .58rem; font-weight: 900; gap: .1rem .5rem; letter-spacing: .1em; margin: 0; padding: .25rem .5rem;
}
.roam__practice > b { color: var(--roam-orange); letter-spacing: .16em; }
.roam__practice > span:not(.roam__goals) { font-family: 'Courier New', monospace; font-size: .7rem; letter-spacing: 0; }
.roam__goals { display: inline-flex; gap: .3rem; }
.roam__goals i { border: 1.5px solid rgba(240, 226, 191, .5); font-style: normal; padding: 0 .25rem; }
.roam__goals i.is-done { background: var(--roam-green); border-color: var(--roam-line); color: var(--roam-line); }
.roam__session {
  align-items: baseline; align-self: flex-end; background: var(--roam-bone); border: 2px solid var(--roam-line); color: var(--roam-line); display: inline-flex;
  gap: .4rem; margin: 0; padding: .05rem .45rem; transform: rotate(-.8deg);
}
.roam__session small { font-size: .7rem; font-weight: 900; letter-spacing: .12em; }
.roam__session b { font-family: 'Courier New', monospace; font-size: .9rem; font-weight: 700; }
.roam__hint {
  background: var(--roam-char); border: 1px dashed rgba(240, 226, 191, .6); color: var(--roam-bone); font-size: .78rem; font-weight: 900; letter-spacing: .1em;
  margin: 0; padding: .25rem .5rem; text-align: center;
}

/* ---------- the stamps: the house style, 1.7 -> 1 (desktop: above the meter, y 217-298 at 1600 x 900) ---------- */
.roam__stamp {
  align-items: center; background: var(--roam-char); border: 2.5px solid var(--roam-line); box-shadow: 4px 4px 0 var(--roam-line); color: var(--roam-bone);
  display: grid; justify-items: center; padding: .4rem .7rem; pointer-events: none; position: absolute; right: var(--roam-right); top: 24%;
  transform: rotate(-2deg); width: 15.5rem; box-sizing: border-box;
}
.roam__stamp b { font-size: 1.15rem; font-weight: 900; letter-spacing: .02em; line-height: 1.05; text-align: center; }
.roam__stamp s { font-family: 'Courier New', monospace; font-size: .95rem; font-weight: 700; text-decoration: none; }
.roam__stamp s:empty { display: none; }
.roam__stamp[data-tone="orange"] { background: var(--roam-orange); color: var(--roam-line); }
.roam__stamp[data-tone="green"] { background: var(--roam-green); color: var(--roam-line); }
.roam__stamp[data-tone="red"] { background: var(--roam-red); color: var(--roam-bone); }
.roam__stamp[data-tone="bone"] { background: var(--roam-bone); color: var(--roam-line); }
.roam__stamp[data-kind="lost"] s { text-decoration: line-through 2px; }
@media (prefers-reduced-motion: no-preference) {
  .roam:not([data-roam-still="on"]) .roam__stamp[data-n="0"]:not([hidden]) { animation: roam-stamp-a .32s cubic-bezier(.2, 1.6, .4, 1); }
  .roam:not([data-roam-still="on"]) .roam__stamp[data-n="1"]:not([hidden]) { animation: roam-stamp-b .32s cubic-bezier(.2, 1.6, .4, 1); }
  .roam:not([data-roam-still="on"]) .roam__feed-item[data-n="0"]:not([hidden]) { animation: roam-feed-a .24s cubic-bezier(.2, 1.6, .4, 1); }
  .roam:not([data-roam-still="on"]) .roam__feed-item[data-n="1"]:not([hidden]) { animation: roam-feed-b .24s cubic-bezier(.2, 1.6, .4, 1); }
}
@keyframes roam-stamp-a { from { opacity: 0; scale: 1.7; } }
@keyframes roam-stamp-b { from { opacity: 0; scale: 1.7; } }
@keyframes roam-feed-a { from { opacity: 0; translate: .6rem 0; } }
@keyframes roam-feed-b { from { opacity: 0; translate: .6rem 0; } }

/* ---------- the live number: centred above the car's box while a drift runs (AIR and the air time in the air) ---------- */
.roam__big {
  align-items: baseline; display: flex; gap: .5rem; left: 50%; margin: 0; pointer-events: none; position: absolute; top: 27%;
  text-shadow: 3px 3px 0 var(--roam-line), -1px -1px 0 var(--roam-line), 1px -1px 0 var(--roam-line), -1px 1px 0 var(--roam-line); transform: translateX(-50%); white-space: nowrap;
}
.roam__big b { color: var(--roam-bone); font-family: 'Courier New', monospace; font-size: 2.75rem; font-weight: 700; line-height: 1; }
.roam__big small { color: var(--roam-orange); font-family: 'Courier New', monospace; font-size: 1.15rem; font-weight: 700; }
.roam__big[data-kind="air"] { flex-direction: row-reverse; }
.roam__big[data-kind="air"] small { color: var(--roam-bone); font-family: Arial, Helvetica, sans-serif; font-weight: 900; letter-spacing: .16em; }

/* ---------- the zone sticker: in the job sticker's place ---------- */
.roam__zone {
  align-items: baseline; background: var(--roam-char); border: 2px solid var(--roam-orange); box-shadow: 3px 3px 0 var(--roam-line); display: grid;
  gap: .05rem .6rem; grid-template-areas: "name name" "score stars" "next next"; grid-template-columns: auto 1fr;
  padding: .3rem .6rem .35rem; pointer-events: none; position: absolute; right: var(--roam-right); top: var(--roam-top); transform: rotate(-.6deg); max-width: 17rem;
}
.roam__zone-name { font-size: .6rem; font-weight: 900; grid-area: name; letter-spacing: .16em; }
.roam__zone-score { font-family: 'Courier New', monospace; font-size: 1.15rem; font-weight: 700; grid-area: score; }
.roam__zone-stars { color: var(--roam-orange); font-size: 1rem; grid-area: stars; justify-self: end; letter-spacing: .1em; }
.roam__zone-next { font-size: .55rem; font-weight: 900; grid-area: next; letter-spacing: .1em; opacity: .8; }
.roam__zone-next:empty { display: none; }
/* a street job's chain in its sticker: the phone forms only (below) */
.roam__job-chain { display: none; }
.roam__job { grid-template-areas: "title title" "gates time" "cue cue" "missed missed" "chain chain"; }

/* desktop: the right chips start under the skills HUD's lines (the session total and a hint stand at 36%) */
.roam__chip[data-side="right"] { top: calc(52% + var(--roam-chip-i) * 2.9rem); }

/* ---------- phones upright (P1b.20): one strip under the head, left of the minimap (F26: 16-266 x 183-250); the
   practice readout under it, then the hint and the session total on one row; the live number between them and the car ---- */
@media (orientation: portrait) {
  .roam__skills { align-items: center; flex-flow: row wrap; gap: .25rem .4rem; left: var(--roam-left); right: calc(var(--roam-right) + var(--roam-mini) + .5rem); top: max(calc(var(--roam-top) + 7.3rem), calc(var(--roam-head-b, 0px) + .45rem)); width: auto; }
  .roam__skills > :is(.roam__chain, .roam__practice) { flex: 1 1 100%; }
  .roam__chain { gap: .2rem; grid-template-areas: "meter row" "feed feed"; grid-template-columns: minmax(0, 1fr) auto; padding: .3rem .45rem .35rem; }
  .roam__meter { grid-area: meter; }
  .roam__chain-row { gap: .35rem; grid-area: row; }
  .roam__mult { height: 2.2rem; width: 2.2rem; }
  .roam__total { padding: .05rem .35rem; }
  .roam__total b { font-size: .95rem; }
  .roam__feed { gap: .6rem; grid-area: feed; grid-auto-flow: column; justify-content: start; }
  .roam__feed-item:nth-child(n+3) { display: none; }
  .roam__meter-pts { font-size: .95rem; }
  .roam__practice { font-size: .52rem; }
  .roam__hint { flex: 1 1 0; font-size: .72rem; letter-spacing: .06em; min-width: 0; text-align: left; }
  .roam__session { align-self: center; flex: none; margin-left: auto; }
  /* a stamp takes the strip's place while it shows */
  .roam__stamp { left: var(--roam-left); right: calc(var(--roam-right) + var(--roam-mini) + .5rem); top: max(calc(var(--roam-top) + 7.3rem), calc(var(--roam-head-b, 0px) + .45rem)); width: auto; }
  .roam__stamp b { font-size: 1rem; }
  .roam[data-roam-stamped="on"] .roam__skills { visibility: hidden; }
  .roam__big { top: 40%; }
  .roam__big b { font-size: 1.9rem; }
  .roam__big small { font-size: .95rem; }
  .roam__zone { grid-template-areas: "name" "score" "stars" "next"; grid-template-columns: 1fr; max-width: 5.75rem; top: calc(var(--roam-top) + var(--roam-mini) + .6rem); }
  .roam__zone-stars { justify-self: start; }
  .roam .roam__chip[data-side="right"] { top: calc(40% + var(--roam-chip-i) * 3.8rem); } /* (repair 2: a chip may take three lines) */
  /* a street job: the chain's one line under the job sticker, in it; the strip gives way */
  .roam[data-roam-job]:not([data-roam-job=""]) :is(.roam__skills, .roam__stamp) { display: none; }
  .roam__job-chain:not([hidden]) { border-top: 1px dashed rgba(240, 226, 191, .4); display: flex; gap: .3rem; grid-area: chain; margin-top: .15rem; padding-top: .1rem; }
  .roam__job-chain b { color: var(--roam-orange); font-family: 'Courier New', monospace; font-size: .8rem; }
  .roam__job-chain span { font-family: 'Courier New', monospace; font-size: .8rem; font-weight: 700; }
  .roam__job { grid-template-areas: "title" "gates" "time" "cue" "missed" "chain"; }
  /* (P1b.20, the street job's sheet with touch) its foot over the thumbs' band (from the bottom edge up past DRIFT's top)
     holds DRIVE ON alone: RETRY and TOW BACK stand above it, so a thumb resting where BRAKE, GAS or DRIFT stand never
     retries or tows (the place cards' foot rule; DRIVE ON is the sheet's way out, as CLOSE is the card's) */
  .roam[data-roam-controls="touch"] .roam__result-actions { grid-template-areas: "retry back" "on on"; }
  .roam[data-roam-controls="touch"] .roam__result-actions > [data-roam-cmd="job-drive-on"] { min-height: calc(var(--roam-gas-h) + .6rem + var(--roam-target) - 1rem + .5rem); }
}

/* ---------- short landscape phones (P1b.20): the left column under the bar, 28vw (at most 31vw: clear of the drifting
   car's box, which reaches 32vw); the zone sticker right of the live number, under the head ---------- */
@media (orientation: landscape) and (max-height: 500px) {
  .roam__skills { align-items: center; flex-flow: row wrap; gap: .2rem .35rem; left: var(--roam-left); max-width: 28vw; right: auto; top: max(calc(var(--roam-top) + var(--roam-target) + .55rem), calc(var(--roam-head-b, 0px) + .45rem)); width: 28vw; }
  .roam__skills > :is(.roam__chain, .roam__practice) { flex: 1 1 100%; }
  .roam__chain { gap: .15rem; padding: .25rem .4rem .3rem; }
  .roam__meter-head { min-height: 1rem; }
  .roam__meter-bar { height: .45rem; }
  .roam__mult { height: 2rem; width: 2rem; }
  .roam__mult b { font-size: .85rem; }
  .roam__total b { font-size: .9rem; }
  .roam__feed-item:nth-child(n+2) { display: none; }
  .roam__meter-pts { font-size: .9rem; }
  .roam__practice { font-size: .5rem; padding: .2rem .4rem; }
  .roam__hint { flex: 1 1 0; font-size: .7rem; letter-spacing: .05em; min-width: 0; padding: .2rem .35rem; text-align: left; }
  .roam__session { align-self: center; flex: none; margin-left: auto; }
  .roam__stamp { left: var(--roam-left); max-width: 28vw; padding: .3rem .5rem; right: auto; top: max(calc(var(--roam-top) + var(--roam-target) + .55rem), calc(var(--roam-head-b, 0px) + .45rem)); width: 28vw; }
  .roam__stamp b { font-size: .9rem; }
  .roam[data-roam-stamped="on"] .roam__skills { visibility: hidden; }
  .roam__big { top: calc(var(--roam-top) + var(--roam-target) + .35rem); }
  .roam__big b { font-size: 1.9rem; }
  .roam__big small { font-size: .9rem; }
  /* the zone sticker: under the head, left of the minimap and right of the drifting car (the banner and the right chip
     give way while it shows) */
  .roam__zone { grid-template-areas: "name name" "score stars" "next next"; left: 67vw; max-width: none; padding: .2rem .45rem .25rem; right: calc(var(--roam-right) + var(--roam-mini) + .6rem); top: max(calc(var(--roam-top) + var(--roam-target) + .4rem), calc(var(--roam-head-b, 0px) + .4rem)); }
  .roam__zone-name { font-size: .5rem; }
  .roam__zone-score { font-size: .9rem; }
  .roam__zone-stars { font-size: .8rem; }
  /* the left chip under the skills HUD's lines; the right one where phase 1a put it (under the minimap) */
  .roam .roam__chip[data-side="left"] { top: calc(var(--roam-top) + var(--roam-target) + 5.4rem); }
  .roam .roam__chip[data-side="right"] { top: calc(var(--roam-top) + var(--roam-mini) + .6rem); }
  .roam__drift, .roam__horn { --roam-pedal-w: clamp(4.25rem, calc(11 * var(--roam-vw)), 5.5rem); }
  .roam[data-roam-job]:not([data-roam-job=""]) :is(.roam__skills, .roam__stamp) { display: none; }
  .roam__job-chain:not([hidden]) { border-top: 1px dashed rgba(240, 226, 191, .4); display: flex; gap: .4rem; grid-area: chain; margin-top: .1rem; padding-top: .05rem; }
  .roam__job-chain b { color: var(--roam-orange); font-family: 'Courier New', monospace; font-size: .8rem; }
  .roam__job-chain span { font-family: 'Courier New', monospace; font-size: .8rem; font-weight: 700; }
  .roam[data-roam-mode] .roam__job { grid-template-areas: "title title" "gates time" "missed missed" "chain chain"; }
  /* (P1b.20, phase 1a's open note) the street job's sheet takes the place cards' foot rule: the sheet runs to the bottom
     edge over the pedals; DRIVE ON (its way out, as CLOSE is a card's) fills the column over BRAKE, GAS and DRIFT from the
     bottom edge up past DRIFT's top, and RETRY and TOW BACK stand left of it, over no thumb control, so a thumb resting
     where the pedals or DRIFT stand never retries or tows */
  .roam__result { display: flex; flex-direction: column; overflow: hidden; }
  .roam__result > * { flex: 0 0 auto; }
  .roam__result > .roam__card-note { flex: 0 1 auto; min-height: 0; overflow: auto; }
  .roam__result > .roam__result-actions { grid-template-areas: "retry on" "back on"; grid-template-columns: minmax(0, 1fr) calc(2 * clamp(4.25rem, calc(11 * var(--roam-vw)), 5.5rem) + .75rem); margin-top: auto; }
  .roam__result-actions > [data-roam-cmd="job-drive-on"] { min-height: calc(var(--roam-gas-h) + .6rem + var(--roam-target) - .7rem + .5rem); }
  .roam__result-actions > :is([data-roam-cmd="job-retry"], [data-roam-cmd="job-tow-back"]) { font-size: .6rem; letter-spacing: .05em; min-height: var(--roam-target); padding-inline: .3rem; }
  .roam__result-actions > :is([data-roam-cmd="job-retry"], [data-roam-cmd="job-tow-back"]) .roam__icon { display: none; }
  /* (P1b.20) with the touch controls the pause card stands between the steering pad and the pedals, so no thumb resting
     on either lands on SWITCH OFF HERE or a tow (phase 1a centred it over both) */
  .roam[data-roam-controls="touch"] .roam__pause { left: calc(var(--roam-left) + var(--roam-pad-w) + .6rem); right: calc(var(--roam-right) + 2 * clamp(4.25rem, calc(11 * var(--roam-vw)), 5.5rem) + .5rem + .6rem); transform: rotate(-.6deg); width: auto; }
}

/* the pause card's HAPTICS toggle (OW123): its top corner, beside PAUSED. (phones with vibration only) */
.roam__haptics { font-size: .58rem; letter-spacing: .1em; min-height: 2.75rem; padding: .3rem .6rem; position: absolute; right: .75rem; top: .6rem; }
.roam__haptics[aria-pressed="true"] { background: var(--roam-green); color: var(--roam-line); }
.roam__pause.is-tows > .roam__haptics { display: none; }

@media (prefers-reduced-motion: reduce) {
  .roam__banner, .roam__act, .roam__stamps i { animation: none !important; }
  .roam__stamp, .roam__feed-item { animation: none !important; }
}
