/* Touch presentation. The boot's body.mobile class keeps device selection in
   one place and allows the same layout in a resized/coarse-pointer game frame. */
.mobile-start-tip,.mobile-help { display:none; }
body:not(.mobile) #touch-controls { display:none!important; }
body.mobile {
  --mobile-top:env(safe-area-inset-top,0px);
  --mobile-bottom:env(safe-area-inset-bottom,0px);
  --mobile-left:env(safe-area-inset-left,0px);
  --mobile-right:env(safe-area-inset-right,0px);
  --mobile-paper:#fff6e4;
  --mobile-ink:#183b46;
  --mobile-sea:#8de1d2;
  --mobile-sun:#ffce7c;
  -webkit-user-select:none;
  user-select:none;
}
body.mobile #world { height:100dvh; }
/* The renderer writes the canvas's CSS size in px on every resize. A static canvas wider than the layout viewport
   widens the page; Chrome's mobile emulation then zooms out to fit it, innerWidth grows and the next resize keeps it
   that way (rig: 1024px layout width at a 390px viewport, visualViewport.scale 0.38). Real-phone rotation was not
   tested here. Fixed to the viewport the canvas cannot widen the page, and the clamp keeps it the size of the frame. */
body.mobile #world { position:fixed;top:0;left:0;max-width:100%;max-height:100%; }
/* A paintball card parks 8px beyond the right edge while idle (translateX(24px) from right:16px); that widened
   the page too, so the browser zoomed the whole game out. Clip the HUD layer to the screen. */
body.mobile #interface { overflow:hidden;overflow:clip; }
body.mobile input,body.mobile textarea { -webkit-user-select:text;user-select:text; }
body.mobile button,body.mobile summary,body.mobile a { touch-action:manipulation; }
/* Robustness (U09): no iOS long-press callout / image drag, no double-tap zoom on bare text, and no landscape text inflation. */
body.mobile { -webkit-touch-callout:none;touch-action:manipulation; }
body.mobile img { -webkit-touch-callout:none;-webkit-user-drag:none; }
@media(hover:none) and (pointer:coarse) { html { -webkit-text-size-adjust:100%;text-size-adjust:100%; } }
/* U03 touch hardening. The game is one fixed screen: any child that pokes past the right edge (an off-canvas card,
   the tool strip) widened the layout viewport and Chrome/Safari shrink-to-fit zoomed the whole page out (measured
   visualViewport.scale 0.38, controls scattered across a 1024px layout). A fixed, clipped body cannot grow the
   document. Long-press must not raise the iOS callout/selection menu over the controls. */
html:has(body.mobile) { overflow:hidden;overscroll-behavior:none; }
body.mobile { position:fixed;inset:0;width:100%;overflow:hidden;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent; }
body.mobile #interface { height:100dvh;background:linear-gradient(#17394735,transparent 28%,transparent 70%,#17394735); }

/* A scrollable strip keeps every existing tool available without shrinking
   buttons into tiny targets. Pause stays fixed above it, within thumb reach. */
body.mobile #interface header {
  top:calc(var(--mobile-top) + 10px);left:calc(var(--mobile-left) + 14px);right:calc(var(--mobile-right) + 14px);
  display:grid;grid-template-columns:minmax(0,1fr);gap:10px;align-items:center;
}
body.mobile #interface header .wordmark { font-size:23px;letter-spacing:2px;min-height:34px;max-width:220px;filter:none;opacity:1; }
body.mobile #interface header .wordmark span { display:none; }
body.mobile .top-actions {
  min-width:0;max-width:100%;width:100%;height:50px;gap:7px;display:flex;flex-wrap:nowrap;justify-content:flex-start;
  overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;touch-action:pan-x;pointer-events:auto;
  scrollbar-width:thin;scrollbar-color:#fff6e440 transparent;padding:0 0 4px;
}
body.mobile .top-actions>* { flex:none; }
body.mobile .top-actions button,body.mobile .top-actions .pill {
  min-height:44px;height:44px;border-radius:14px;background:#173947ec;color:var(--mobile-paper);
  border:1px solid #fff6e45c;backdrop-filter:none;-webkit-backdrop-filter:none;
  box-shadow:0 2px 0 #102b3680;font-size:12px;
}
body.mobile .top-actions .icon-btn { min-width:44px;width:44px;font-size:19px; }
body.mobile .top-actions .lkg-game-trigger { order:-2;padding-inline:13px!important;font-size:13px!important; }
body.mobile #online-count { order:-1;max-width:190px;overflow:hidden;text-overflow:ellipsis;padding:0 10px;font-size:11px; }
body.mobile #mode-btn { padding:0 11px;min-width:48px; }
body.mobile #mode-btn span { max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
body.mobile #pause-btn {
  position:absolute;top:calc(var(--mobile-top) + 8px);right:calc(var(--mobile-right) + 14px);bottom:auto;left:auto;
  width:44px;height:44px;min-width:44px;transform:none;border-radius:13px;background:#173947ef;border:1px solid #fff6e46b;
  color:var(--mobile-paper);font-size:24px;box-shadow:0 2px 0 #102b3680;
}
body.mobile #compass { display:none; }
body.mobile footer { display:none; }

/* Navigation sits above the left thumb, leaving the centre and right camera
   area open. The whole map and its open button are useful touch targets. */
body.mobile.playing .map-wrap {
  left:calc(var(--mobile-left) + 14px);right:auto;top:calc(var(--mobile-top) + 110px);bottom:auto;
  width:112px;opacity:.95;border-radius:14px;border:1px solid #fff6e47a;background:#173947e8;
  box-shadow:0 3px 12px #102b3624;overflow:hidden;
}
body.mobile.playing #minimap { width:112px;height:78px;display:block; }
body.mobile.playing .map-wrap>div { display:flex;align-items:center;min-height:44px;padding:0 4px 0 8px;gap:2px; }
body.mobile.playing .map-wrap>div>span { min-width:0;font-size:9px;letter-spacing:.04em; }
body.mobile #map-btn { flex:none;min-width:44px;width:44px;height:44px;font-size:23px; }
body.mobile.playing .location,body.mobile.playing .location.fresh {
  left:calc(var(--mobile-left) + 140px);right:calc(var(--mobile-right) + 14px);top:calc(var(--mobile-top) + 112px);bottom:auto;
  max-width:none;text-align:left;pointer-events:none;
}
body.mobile.playing .location .eyebrow,body.mobile.playing .location p { display:none; }
body.mobile.playing .location h1,body.mobile.playing .location.fresh h1 {
  font-size:22px;line-height:1.1;letter-spacing:.02em;margin:0;color:var(--mobile-paper);animation:none;
  text-shadow:0 2px 3px #173947bd;
}
body.mobile.playing .location h1::after { width:35px;height:3px;margin:7px 0 0;background:var(--mobile-sea);box-shadow:none; }
body.mobile.playing .flight-hud {
  left:calc(var(--mobile-left) + 140px);right:auto;top:calc(var(--mobile-top) + 160px);bottom:auto;text-align:left;
  max-width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 156px);color:var(--mobile-paper);
}
body.mobile.playing .flight-hud strong,body.mobile.playing.on-foot-grounded .flight-hud strong { font-size:24px;line-height:1; }
body.mobile.playing .flight-hud strong small { font-size:10px; }
body.mobile #motion-label { font-size:10px;letter-spacing:.09em; }
body.mobile .flight-hud>div { display:none; }
body.mobile.playing #flight-btn { min-height:44px;min-width:88px;font-size:11px;padding:7px 10px;opacity:1;border-radius:12px;background:#173947e8; }
body.mobile #flight-btn kbd { display:none; }
body.mobile #destination { top:calc(var(--mobile-top) + 244px);right:calc(var(--mobile-right) + 14px);width:180px; }
body.mobile #challenge-btn { min-height:44px;font-size:12px; }
body.mobile #course-invite { top:calc(var(--mobile-top) + 112px);right:calc(var(--mobile-right) + 14px);max-width:220px; }
body.mobile #course-invite button { min-height:44px; }
body.mobile #move-prompts { display:none!important; }
body.mobile #action-prompt { top:auto!important;left:50%!important;bottom:calc(var(--mobile-bottom) + 262px);height:max-content;transform:translateX(-50%)!important;max-width:calc(100vw - 32px);padding:8px 12px;border-radius:12px;font-size:12px; }
body.mobile #action-prompt .key { display:none; }
body.mobile #action-prompt .what { white-space:normal;font-size:11px; }
body.mobile #traversal-hint.visible { bottom:calc(var(--mobile-bottom) + 250px);max-width:calc(100vw - 36px);font-size:12px;padding:8px 12px; }
/* Robustness (U09): with left:50% the shrink-to-fit width is capped at half the screen, so a long Spanish toast or prompt wrapped
   into a 160-195px column (4-7 lines, mid-screen). max-content leaves the per-layout max-width as the only limit. */
body.mobile .toast,body.mobile #action-prompt { width:max-content;overflow-wrap:break-word; }
body.mobile .toast { top:auto;bottom:calc(var(--mobile-bottom) + 248px);height:max-content;max-width:calc(100vw - 32px);font-size:13px; }
body.mobile #flow-hud { bottom:calc(var(--mobile-bottom) + 240px);left:calc(var(--mobile-left) + 14px); }
body.mobile .reticle span { max-width:180px;font-size:11px; }

/* Every control owns at least48px. Solid painted surfaces avoid the cost of a
   live blur on eight overlays while giving reliable contrast over bright sand. */
body.mobile #touch-controls { display:block;position:absolute;inset:0;pointer-events:none; }
body.mobile #joystick {
  position:absolute;left:calc(var(--mobile-left) + 16px);bottom:calc(var(--mobile-bottom) + 30px);
  width:120px;height:120px;border:2px solid #fff6e478;border-radius:50%;background:#17394770;
  box-shadow:inset 0 0 0 12px #17394726,0 3px 0 #1435413b;pointer-events:auto;touch-action:none;
}
body.mobile #joystick i {
  left:37px;top:37px;width:42px;height:42px;background:#a5e7d6e8;border:2px solid #fff6e4;
  box-shadow:0 3px 0 #14354170;pointer-events:none;
}
body.mobile #joystick>span { position:absolute;left:0;right:0;bottom:12px;text-align:center;font:700 9px/1 system-ui,sans-serif;letter-spacing:.12em;color:#fff6e4b3;pointer-events:none; }
body.mobile #touch-controls button {
  display:flex;align-items:center;justify-content:center;position:absolute;width:48px;height:48px;min-width:48px;min-height:48px;
  margin:0;padding:4px;border:2px solid #fff6e4a6;border-radius:16px;background:#173947ef;color:var(--mobile-paper);
  box-shadow:0 4px 0 #102c37a1,0 4px 12px #102c3724;font:800 10px/1.15 var(--fl-cond,system-ui,sans-serif);
  letter-spacing:.02em;text-align:center;pointer-events:auto;touch-action:none;backdrop-filter:none;-webkit-backdrop-filter:none;
  -webkit-user-select:none;user-select:none;transition:transform .08s,background .08s,box-shadow .08s;
}
body.mobile #touch-controls button.held,body.mobile #touch-controls button:active { transform:translateY(3px) scale(.96);box-shadow:0 1px 0 #102c3799;background:#2b5862; }
body.mobile #touch-controls #touch-swing {
  right:calc(var(--mobile-right) + 8px);bottom:calc(var(--mobile-bottom) + 18px);width:74px;height:74px;
  border-radius:25px;background:var(--mobile-sea);border-color:var(--mobile-paper);color:#153943;font-size:12px;
}
body.mobile #touch-controls #touch-jump {
  right:calc(var(--mobile-right) + 92px);bottom:calc(var(--mobile-bottom) + 20px);width:64px;height:64px;
  border-radius:22px;background:var(--mobile-sun);border-color:var(--mobile-paper);color:#153943;font-size:12px;
}
body.mobile #touch-controls #touch-trick { right:calc(var(--mobile-right) + 166px);bottom:calc(var(--mobile-bottom) + 24px); }
body.mobile #touch-controls #touch-zip { right:calc(var(--mobile-right) + 38px);bottom:calc(var(--mobile-bottom) + 112px); }
body.mobile #touch-controls #touch-fire {
  right:calc(var(--mobile-right) + 98px);bottom:calc(var(--mobile-bottom) + 106px);width:64px;height:64px;
  border-radius:21px;background:#ef8c87;color:#382c3b;border-color:#fff6e4;font-size:11px;
}
body.mobile #touch-controls #touch-weapon { right:calc(var(--mobile-right) + 174px);bottom:calc(var(--mobile-bottom) + 114px); }
body.mobile #touch-controls #touch-ride { right:calc(var(--mobile-right) + 12px);bottom:calc(var(--mobile-bottom) + 186px);background:#f1bd81;color:#193b46; }
/* W1 siren: SIRENA only exists while driving a police car or ambulance (main.js refreshState shows it). It takes the free
   JUMP slot beside FRENO (JUMP is hidden in a car): 64x64, clear of FRENO, TURBO and SALIR in portrait and landscape. */
body.mobile #touch-controls #touch-siren { right:calc(var(--mobile-right) + 92px);bottom:calc(var(--mobile-bottom) + 20px);width:64px;height:64px;border-radius:22px;background:#c4342b;border-color:var(--mobile-paper);color:#fff6e4;font-size:11px; }
body.mobile #touch-controls #touch-siren.on { background:#1f55d6;animation:w1-siren-flash .7s steps(1) infinite; }
@keyframes w1-siren-flash { 0%{background:#c4342b} 50%{background:#1f55d6} }
@media(prefers-reduced-motion:reduce) { body.mobile #touch-controls #touch-siren.on { animation:none; } }
body.mobile #touch-controls #touch-interact { right:calc(var(--mobile-right) + 72px);bottom:calc(var(--mobile-bottom) + 188px);width:72px;height:48px;background:#f8ead0;color:#193b46; }
body.mobile #touch-controls #touch-torch { display:none!important;left:calc(var(--mobile-left) + 76px);right:auto;bottom:calc(var(--mobile-bottom) + 180px);width:48px;height:48px;font-size:9px; }
body.mobile.nv-dark.playing #touch-controls #touch-torch { display:flex!important; }
/* Wave 5: night-vision.js injects its own right:184px;bottom:124px for this button (higher specificity), which parked it on the joystick ring on phones. */
body.mobile.nv-dark.playing #touch-controls #touch-torch { left:calc(var(--mobile-left) + 76px)!important;right:auto!important;bottom:calc(var(--mobile-bottom) + 180px)!important; }
body.mobile .snap-btn { left:calc(var(--mobile-left) + 16px);top:auto;bottom:calc(var(--mobile-bottom) + 180px);width:48px;height:48px;backdrop-filter:none;-webkit-backdrop-filter:none; }
/* U03: the photo button sat at z-index 1400 (snapshot.js) and stayed tappable on top of full-screen panels (mission
   journal z26, relics z60) while the stick and action pad were correctly covered. Put it on the control layer, above
   the HUD but under every panel, so a modal hides it exactly like the rest of the pad. */
body.mobile .snap-btn { z-index:1; }
body.mobile #touch-look-hint { position:absolute;left:50%;top:58%;width:180px;transform:translateX(-50%);text-align:center;font:600 11px/1.4 system-ui,sans-serif;color:var(--mobile-paper);text-shadow:0 1px 3px #173947;pointer-events:none; }
body.mobile.settled #touch-look-hint { display:none; }
body.mobile:not(.playing) #touch-controls,body.mobile.cinema #touch-controls { display:none!important; }
body.mobile .start-hint { bottom:calc(var(--mobile-bottom) + 24px);max-width:calc(100vw - 36px); }
body.mobile #play-btn { min-height:52px;border-radius:15px;font-size:18px; }
body.mobile .desktop-start-tip { display:none; }
body.mobile .mobile-start-tip { display:block!important;font-size:14px;line-height:1.5; }
/* U01 intro/menu screen (body.mobile:not(.playing)): the wallet chip, the place copy and the Play card each own a lane, so nothing stacks.
   Portrait: toolbar, wallet chip, place copy, then the Play card pinned above the home indicator. Every edge adds the safe-area inset. */
body.mobile:not(.playing) .mi-wallet { left:calc(var(--mobile-left) + 14px);top:calc(var(--mobile-top) + 116px); }
body.mobile:not(.playing) .location { left:calc(var(--mobile-left) + 18px);right:calc(var(--mobile-right) + 18px);top:calc(var(--mobile-top) + 200px);max-width:none; }
body.mobile:not(.playing) .location h1 { font-size:clamp(38px,11.5vw,56px);margin:12px 0 10px; }
body.mobile:not(.playing) .location p { max-width:min(360px,100%);font-size:15px; }
body.mobile:not(.playing) .start-hint { width:min(420px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 28px));max-width:none; }
body.mobile:not(.playing) .mobile-start-tip { max-width:none;font-size:13px;line-height:1.45;letter-spacing:.02em; }
/* Landscape (phone held sideways): copy on the left, wallet chip top right under the toolbar, Play card bottom centre. The pause button is
   hidden here, so the toolbar may run to the right edge instead of reserving its gutter. */
@media(orientation:landscape) and (min-width:560px) and (max-height:560px) {
  body.mobile:not(.playing) #interface header { right:calc(var(--mobile-right) + 14px); }
  body.mobile:not(.playing) .mi-wallet { left:auto;right:calc(var(--mobile-right) + 14px);top:calc(var(--mobile-top) + 70px); }
  body.mobile:not(.playing) .location { top:calc(var(--mobile-top) + 68px);right:calc(var(--mobile-right) + 138px); }
  body.mobile:not(.playing) .location h1 { font-size:clamp(30px,10vh,46px);margin:6px 0 6px; }
  body.mobile:not(.playing) .location p { max-width:none;font-size:14px;line-height:1.45; }
  body.mobile:not(.playing) .start-hint { bottom:calc(var(--mobile-bottom) + 14px);width:min(560px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 28px)); }
  body.mobile:not(.playing) #play-btn { min-height:48px;padding-block:12px; }
  body.mobile:not(.playing) .mobile-start-tip { font-size:12px;line-height:1.4;margin:8px 0 0; }
}

/* Native dialogs retain a scrollable, comfortably sized close/action path
   when the keyboard or browser bars reduce the available dynamic height. */
body.mobile dialog {
  width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px);max-width:560px;
  max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 24px);margin:auto;padding:24px 20px;
  overflow-y:auto;overscroll-behavior:contain;border-radius:20px;
}
body.mobile dialog h2 { font-size:30px;line-height:1.12;margin-right:30px; }
body.mobile dialog p { font-size:14px;line-height:1.5; }
body.mobile dialog button,body.mobile dialog summary { min-height:44px; }
body.mobile dialog .close { width:44px;height:44px;right:10px;top:10px;padding:0;font-size:27px;border-radius:13px; }
body.mobile dialog button.primary,body.mobile dialog button.secondary { min-height:48px;border-radius:13px;font-size:16px; }
body.mobile #pause-dialog { padding:28px 22px; }
body.mobile #pause-dialog>button { width:100%;margin-top:10px; }
body.mobile .mobile-help { display:block;background:#ffffff08;border:1px solid #fff6e425;border-radius:13px;padding:0 14px;margin:12px 0 20px; }
body.mobile .mobile-help+.help-grid { display:none; }
body.mobile .sensitivity-option { grid-template-columns:1fr;gap:4px; }
body.mobile .sensitivity-option input { min-height:44px; }
body.mobile #map-dialog { padding:24px 16px; }
body.mobile #island-map { max-width:100%; }
body.mobile #landmarks { grid-template-columns:1fr;gap:8px; }
body.mobile #landmarks button { min-height:52px; }
body.mobile #exit-photo { min-height:48px;bottom:calc(var(--mobile-bottom) + 20px); }
/* U01: photo-mode exit clears the right notch (landscape) as well as the home indicator. */
body.mobile #exit-photo { right:calc(var(--mobile-right) + 25px); }
/* U01: the discoveries panel hugs the right edge (22px, or 8px at <=700px wide, as in discoveries.js): add the right inset for landscape notches. */
@media(min-width:701px) { body.mobile .dsc-panel { right:calc(var(--mobile-right) + 22px); } }
@media(max-width:700px) { body.mobile .dsc-panel { right:calc(var(--mobile-right) + 8px); } }
/* U01: the taxi and plane job result cards size with 100vh in their own CSS, which iOS Safari makes taller than the visible area (their
   centred card then crops top and bottom). Same widths as taxi-job.js / plane-mission.js, but dynamic height and safe-area aware. */
body.mobile .tx-card { width:min(660px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px));max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 24px); }
body.mobile .pm-card { width:min(600px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px));max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 24px); }
body.mobile .lkg-dialog { padding:26px 22px;max-width:440px; }
body.mobile .lkg-dialog .lkg-close { width:44px;height:44px;min-height:44px;right:10px;top:10px; }
body.mobile .lkg-dialog .lkg-input { min-height:52px;font-size:22px; }
body.mobile .lkg-dialog .lkg-code { min-height:84px;font-size:34px; }
body.mobile .lkg-title-trigger { min-height:48px;min-width:150px; }
body.mobile #lk-acct { width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px);max-width:520px;max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 24px);padding:24px 20px; }
body.mobile #lk-acct input[type=text],body.mobile #lk-acct input[type=password],body.mobile #lk-acct textarea { min-height:48px;font-size:16px; }
body.mobile #lk-acct button,body.mobile .lk-acct-btn { min-height:44px; }
body.mobile .nv-row { display:grid;grid-template-columns:1fr auto;gap:4px 10px; }
body.mobile .nv-row input { grid-column:1/-1;grid-row:2;min-height:44px; }
body.mobile .snap-modal { padding:calc(var(--mobile-top) + 12px) calc(var(--mobile-right) + 12px) calc(var(--mobile-bottom) + 12px) calc(var(--mobile-left) + 12px);backdrop-filter:none;-webkit-backdrop-filter:none; }
body.mobile .snap-card { width:100%;max-height:none;gap:14px; }
body.mobile .snap-side button { min-height:48px; }
body.mobile .snap-card img { max-height:48dvh; }

/* ---- Wave 4 U07: modal screens (rewards, invite, discoveries, course, map, pause, photo) ----
   Every modal sits inside the safe area, scrolls inside itself, keeps a >=44px close in reach and
   hides the HUD beneath it. Touch/narrow only: all selectors live under body.mobile. */
body.mobile:has(dialog[open]) #interface,body.mobile:has(dialog[open]) .snap-btn { visibility:hidden; }
body.mobile dialog p a { display:inline-block;padding:13px 0; }
/* The shop owns its header/tab chrome: the generic dialog padding and 560px cap inset it and squeeze the header. */
body.mobile .lkr-dialog { padding:0;overflow:hidden;width:min(950px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 16px));max-width:950px;max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 16px);border-radius:22px; }
/* The shop is mounted inside #interface, so the wordmark-bar rules (`body.mobile #interface header`, `.playing header`) also hit
   its <header>: they shifted it 14px right and (landscape) squeezed the title into a 100px column. Restore its own layout. */
body.mobile #interface .lkr-header { left:auto;right:auto;top:auto;gap:20px;grid-template-columns:1fr auto; }
@media(max-width:580px) { body.mobile #interface .lkr-header { grid-template-columns:1fr;gap:14px; } }
body.mobile:has(.dsc-panel:not([hidden])) #interface>:not(.dsc-panel),body.mobile:has(.dsc-panel:not([hidden])) .snap-btn { visibility:hidden; }
/* Discoveries list: a safe-area sheet above the controls with thumb-sized close and filters. */
body.mobile .dsc-panel { position:fixed;top:calc(var(--mobile-top) + 8px);bottom:calc(var(--mobile-bottom) + 8px);left:calc(var(--mobile-left) + 8px);right:calc(var(--mobile-right) + 8px);width:auto;border-radius:16px;overscroll-behavior:contain; }
body.mobile .dsc-close { width:44px;height:44px;top:10px;right:10px;font-size:20px; }
body.mobile .dsc-head { padding-right:64px; }
body.mobile .dsc-head h2 { font-size:32px; }
body.mobile .dsc-tab { min-height:36px;padding:8px 13px; }
body.mobile .dsc-region { min-height:40px; }
body.mobile .dsc-list { overscroll-behavior:contain; }
body.mobile .inv-dlg .inv-dlg-x { display:grid;place-items:center;position:absolute;top:10px;right:10px;width:44px;height:44px;padding:0;font-size:27px; }
body.mobile:has(.snap-modal:not([hidden])) #interface,body.mobile:has(.snap-modal:not([hidden])) .snap-btn { visibility:hidden; }
/* Photo result: opaque so the HUD never ghosts through, and a card taller than the screen scrolls from its top
   (a centred flex child overflows upward and loses its first rows). */
body.mobile .snap-modal { background:#030f1af5;align-items:flex-start;justify-content:flex-start; }
body.mobile .snap-card { margin:auto; }
body.mobile .snap-card img { max-height:min(48dvh,max(140px,calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 404px))); }
body.mobile #exit-photo { right:calc(var(--mobile-right) + 16px); }
body.mobile #exit-photo kbd { display:none; }
body.mobile .course-close { width:44px;height:44px;top:10px;right:10px; }
.map-tip-m { display:none; }
body.mobile .map-tip-d { display:none; }
body.mobile .map-tip-m { display:inline; }
@media(orientation:landscape) and (max-height:480px) {
  body.mobile dialog { width:min(calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px),720px);max-width:none;max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 16px);padding:14px 18px;border-radius:16px; }
  body.mobile dialog h2 { font-size:24px;margin:2px 52px 6px 0; }
  body.mobile dialog p { font-size:13px;line-height:1.4;margin:4px 0 8px; }
  body.mobile dialog .eyebrow { margin:0;font-size:10px; }
  body.mobile dialog .close,body.mobile .course-close,body.mobile .inv-dlg .inv-dlg-x { top:6px;right:6px; }
  body.mobile #map-dialog>p { display:none; }
  body.mobile #map-dialog { padding:12px 14px; }
  body.mobile #pause-dialog { padding:12px 18px 14px; }
  body.mobile #pause-dialog h2 { font-size:26px;margin:2px 0 2px; }
  body.mobile #pause-dialog[open] { display:grid;grid-template-columns:1fr 1fr;gap:8px 10px;align-content:start; }
  body.mobile #pause-dialog>:not(button),body.mobile #pause-dialog>#resume-btn { grid-column:1/-1; }
  body.mobile #pause-dialog>button { margin-top:0;min-height:44px;font-size:14px; }
  body.mobile .lkr-dialog { padding:0;width:min(950px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px)); }
  body.mobile #interface .lkr-header { display:flex;align-items:center;gap:12px;padding:8px 64px 8px 18px; }
  body.mobile .lkr-heading { flex:1;min-width:0;padding:0; }
  body.mobile .lkr-eyebrow,body.mobile .lkr-description { display:none; }
  body.mobile .lkr-title { font-size:22px; }
  body.mobile .lkr-wallet { flex:none;margin:0;padding:5px 12px; }
  body.mobile .lkr-status { min-height:0;padding-block:4px; }
  body.mobile .lkr-wallet strong { font-size:20px; }
  body.mobile .lkr-tabs { padding:8px 18px 6px; }
  body.mobile .lkr-body { padding:0 18px 12px; }
  body.mobile .lkr-art { height:84px; }
  body.mobile .dsc-panel { left:max(calc(var(--mobile-left) + 8px),calc(50vw - 340px));right:max(calc(var(--mobile-right) + 8px),calc(50vw - 340px)); }
  body.mobile .dsc-head { display:flex;flex-wrap:wrap;align-items:baseline;gap:0 14px;padding:8px 64px 6px 14px; }
  body.mobile .dsc-head .dsc-eyebrow { display:none; }
  body.mobile .dsc-head h2 { font-size:24px;margin:0; }
  body.mobile .dsc-sum { margin:0;font-size:15px; }
  body.mobile .dsc-bar { flex:1 0 100%;margin-top:6px; }
  body.mobile .dsc-tabs { padding:6px 14px 2px; }
  body.mobile .inv-dlg p { display:none; }
  body.mobile .inv-dlg .inv-link { margin:0 0 8px;padding:6px 8px;font-size:12px; }
  body.mobile .inv-dlg .inv-row { grid-template-columns:repeat(3,1fr);gap:6px; }
  body.mobile .inv-dlg .inv-row .inv-cp { grid-column:auto; }
  body.mobile .inv-dlg .inv-back { margin-top:6px;padding:0;min-height:44px; }
}

/* Keyboard open (modal-keyboard.js): pin modals to the visible box so inputs and buttons stay above the keys. */
body.mobile.kb-open dialog[open] { max-height:calc(var(--lk-vvh,100dvh) - 16px);margin-top:calc(var(--lk-vvt,0px) + 8px);margin-bottom:auto; }
body.mobile.kb-open #lk-acct { max-height:calc(var(--lk-vvh,100dvh) - 16px); }
body.mobile.kb-open .icr.icr { height:var(--lk-vvh,100dvh);top:var(--lk-vvt,0px);bottom:auto; }

/* The title and dressing room use higher-specificity selectors so late
   component-style injection cannot undo touch sizes or safe-area padding. */
body.mobile .lki.lki { height:100dvh;padding:var(--mobile-top) var(--mobile-right) var(--mobile-bottom) var(--mobile-left); }
body.mobile .lki .lki-top { padding:14px 18px 0; }
body.mobile .lki .lki-mark { font-size:20px;letter-spacing:2px; }
body.mobile .lki .lki-coords { display:none; }
body.mobile .lki .lki-hero { flex:0 0 auto;min-height:0;padding-top:22px; }
body.mobile .lki .lki-title { font-size:clamp(48px,14vw,80px); }
body.mobile .lki .lki-tag { font-size:12px;letter-spacing:.16em; }
body.mobile .lki .lki-ask { font-size:16px;letter-spacing:.02em; }
body.mobile .lki .lki-choices { flex:1 0 auto;flex-direction:column;padding:0 16px;gap:12px;margin:14px 0; }
body.mobile .lki .lki-card { width:100%;padding:15px 17px;gap:8px;border-radius:20px;background:linear-gradient(#1c414aef,#15333eeb);box-shadow:0 4px 0 #10212e7a; }
body.mobile .lki .lki-card.sel { transform:none; }
body.mobile .lki .lki-ic { width:44px;height:44px; }
body.mobile .lki .lki-name { font-size:30px; }
body.mobile .lki .lki-sub { min-height:0;font-size:14px;line-height:1.3; }
body.mobile .lki .lki-line { letter-spacing:.06em;font-size:14px; }
body.mobile .lki .lki-cta { min-height:46px;height:46px;font-size:19px; }
body.mobile .lki .lki-foot { padding-bottom:16px;gap:12px; }
body.mobile .lki .lki-keys,body.mobile .lki .lki-key { display:none; }
body.mobile .lki .lki-status { font-size:12px;letter-spacing:.04em; }
body.mobile .icr.icr { height:100dvh;display:flex;flex-direction:column;overflow:hidden;padding:var(--mobile-top) var(--mobile-right) var(--mobile-bottom) var(--mobile-left); }
body.mobile .icr .icr-top { position:sticky;top:0;z-index:3;flex:none;min-height:56px;padding:10px 14px;gap:8px;background:#17333eeb; }
body.mobile .icr .icr-mark { font-size:23px;letter-spacing:1px; }
body.mobile .icr .icr-tag,body.mobile .icr .icr-coords { display:none; }
body.mobile .icr .icr-back,body.mobile .icr .icr-modepill { min-height:44px;height:44px;letter-spacing:.04em;padding:0 10px; }
body.mobile .icr .icr-stage { flex:none;height:min(34dvh,300px);min-height:220px; }
body.mobile .icr .icr-plate { left:16px;bottom:12px;max-width:calc(100% - 32px); }
body.mobile .icr .icr-heroname { font-size:28px; }
body.mobile .icr .icr-hint { font-size:10px;top:12px;right:16px;bottom:auto;letter-spacing:.08em; }
body.mobile .icr .icr-panel { flex:1;min-height:0;margin:0 10px 12px;background:#15333ef5;border-radius:20px;overflow:hidden;backdrop-filter:none;-webkit-backdrop-filter:none;box-shadow:0 8px 20px #10212e45; }
body.mobile .icr .icr-scroll { flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:16px 14px 10px;gap:16px; }
body.mobile .icr .icr-ghost { min-height:44px;height:44px;padding:0 12px; }
body.mobile .icr .icr-sw,body.mobile .icr .icr-street .icr-sw { width:44px;height:44px;padding:8px; }
body.mobile .icr .icr-sw span { width:28px;height:28px; }
body.mobile .icr .icr-row { grid-template-columns:1fr;gap:7px; }
body.mobile .icr .icr-swatches { gap:4px; }
body.mobile .icr .icr-preset { min-height:48px;font-size:14px;padding:9px 7px; }
body.mobile .icr .icr-seg span { min-height:44px;display:grid;place-items:center; }
body.mobile .icr .icr-tab { min-height:52px;font-size:10px; }
body.mobile .icr .icr-tabs { grid-template-columns:repeat(4,minmax(0,1fr));gap:6px; }
body.mobile .icr .icr-type>span { min-height:60px;grid-template-columns:1fr; }
body.mobile .icr .icr-type svg { display:none; }
body.mobile .icr .icr-field input { min-height:50px;font-size:20px; }
body.mobile .icr .icr-num input { min-height:44px; }
body.mobile .icr .icr-actions { flex:none;position:relative;z-index:2;padding:12px 14px;background:#17333efa;border-radius:0 0 20px 20px; }
body.mobile .icr .icr-primary,body.mobile .icr .icr-go .icr-ghost { min-height:52px;height:52px; }
body.mobile .icr .icr-tip { display:none; }
body.mobile .icr .icr-status { font-size:13px;line-height:1.4; }

/* These systems inject their own styles; leave concise state above the controls
   and turn long lists into scrollable sheets rather than covering the thumbs. */
body.mobile .pb-hud { --pb-right:calc(var(--mobile-right) + 16px);--pb-bottom:calc(var(--mobile-bottom) + 252px); }
body.mobile .pb-card .pb-hint { display:none; }
body.mobile .pb-card .pb-ammo b { font-size:30px; }
body.mobile .pb-card .pb-name { font-size:17px; }
body.mobile .mph-root { --mp-feed-left:calc(var(--mobile-left) + 14px);--mp-feed-bottom:calc(var(--mobile-bottom) + 245px); }
body.mobile .mph-root.has-peers .mph-btn { display:flex;height:44px;top:calc(var(--mobile-top) + 244px);right:calc(var(--mobile-right) + 14px); }
body.mobile .mph-list { top:calc(var(--mobile-top) + 110px);width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px);max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 126px);border-radius:18px; }
body.mobile .mph-close { width:44px;height:44px; }
body.mobile .mph-lf { display:none; }
body.mobile #online-nearby { max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 130px); }

/* Cash and the current objective share the navigation column rather than the
   toolbar. Mission choices and journals use scrollable sheets on short screens. */
body.mobile .mi-wallet { left:calc(var(--mobile-left) + 14px);top:calc(var(--mobile-top) + 244px);width:112px;height:auto;max-height:72px;display:grid;gap:4px;padding:8px 10px;box-sizing:border-box;border-radius:12px;background:#173947ed; }
body.mobile .mi-cash { min-width:0;font-size:22px;line-height:1; }
body.mobile .mi-lvl b { display:none; }
body.mobile .mi-lvl small { font-size:9px;line-height:1.15;letter-spacing:.03em;margin:0; }
body.mobile .mi-bar { height:3px;margin-top:4px; }
body.mobile .mi-gain { left:calc(var(--mobile-left) + 138px);top:calc(var(--mobile-top) + 250px);font-size:17px; }
body.mobile .mi-track { left:calc(var(--mobile-left) + 14px);top:calc(var(--mobile-top) + 324px);width:min(230px,calc(100vw - 48px));padding:10px 12px;border-radius:12px;background:#173947ed; }
body.mobile .mi-kick { font-size:9px;letter-spacing:.08em; }
body.mobile .mi-title { font-size:15px;margin-block:4px; }
body.mobile .mi-step { font-size:14px;line-height:1.3; }
body.mobile .mi-stat { font-size:12px; }
body.mobile .mi-hint { display:none; }
body.mobile .mi-toasts { top:calc(var(--mobile-top) + 248px);width:calc(100vw - 32px); }
body.mobile .mi-toast { font-size:14px;padding:8px 12px;border-radius:12px; }
body.mobile .mi-sub { bottom:calc(var(--mobile-bottom) + 250px);font-size:16px;max-width:calc(100vw - 28px); }
body.mobile.mi-cine #touch-controls,body.mobile.mi-cine .snap-btn { display:none!important; }
/* U06 story surfaces. Dialogue: anchored between the safe-area insets (the desktop centring transform is dropped so a
   one-sided notch cannot push the box under it), with real Seguir / Salir buttons and a screen-wide tap layer. */
body.mobile .mi-dlg { left:calc(var(--mobile-left) + 12px);right:calc(var(--mobile-right) + 12px);width:auto;max-width:960px;margin-inline:auto;bottom:calc(var(--mobile-bottom) + 12px);transform:translateY(24px); }
body.mobile .mi-dlg.on { transform:none; }
body.mobile .mi-dlg-portrait { width:52px;height:52px; }
body.mobile .mi-dlg-box { padding:16px 14px 18px 20px;border-radius:16px;max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 90px);overflow-y:auto;overscroll-behavior:contain; }
body.mobile .mi-dlg-name { font-size:19px;gap:7px;flex-wrap:wrap; }
body.mobile .mi-dlg-name small { font-size:11px; }
body.mobile .mi-dlg-text { font-size:19px;line-height:1.35;min-height:44px; }
body.mobile .mi-dlg-choice { min-height:48px;font-size:16px;line-height:1.3;padding:9px 10px; }
body.mobile .mi-dlg-choice b { min-width:26px;height:26px;font-size:17px; }
body.mobile .mi-dlg-hint { display:none; }
body.mobile .mi-dlg-next { display:none; }
/* The 8.5vh letterbox bars would cut the toolbar and the box already is the lower frame: phones drop them. */
body.mobile .mi-bars { display:none; }
body.mobile .mi-dlg-acts { display:flex;justify-content:flex-end;gap:8px;margin-top:8px; }
body.mobile .mi-dlg-acts button {
  box-sizing:border-box;min-width:96px;min-height:44px;padding:0 18px;border:1px solid #ffffff38;border-radius:12px;background:#ffffff14;color:#fff;
  font:700 15px/1 var(--fl-cond,"Barlow Condensed",system-ui,sans-serif);letter-spacing:.08em;text-transform:uppercase;cursor:pointer;touch-action:manipulation;
}
body.mobile .mi-dlg-acts button.mi-dlg-go { background:var(--fl-sun,#ffd23f);border-color:transparent;color:var(--fl-ink,#0b0a14); }
body.mobile .mi-dlg-acts button[hidden] { display:none; }
body.mobile .mi-dlg-acts:not(:has(button:not([hidden]))) { display:none; }
/* Tapping anywhere below the toolbar strip advances a line without choices (the pause button stays reachable). */
body.mobile .mi-dlg-tap.on { display:block;position:fixed;left:0;right:0;bottom:0;top:calc(var(--mobile-top) + 64px);z-index:29;-webkit-tap-highlight-color:transparent; }
/* While a conversation or the dialogue letterbox is up, the HUD that would sit behind the banner (minimap, place and speed
   readouts, cash, objective card) steps aside; the touch controls are already hidden by body.mi-cine above. */
body.mobile.mi-cine .map-wrap,body.mobile.mi-cine .location,body.mobile.mi-cine .flight-hud,body.mobile.mi-cine #destination,body.mobile.mi-cine #course-invite,
body.mobile.mi-cine .mi-wallet,body.mobile.mi-cine .mi-track,body.mobile.mi-cine .mi-gain,body.mobile.mi-cine .mi-sub,body.mobile.mi-cine .mi-toasts,body.mobile.mi-cine .mi-wp { opacity:0!important;pointer-events:none!important; }
/* Cash, level and the objective card mean nothing on the title screen and sat on the place name / description there. */
body.mobile:not(.playing) .mi-hud { display:none; }
/* U06 mission banner (start / complete): wraps between the safe-area insets and, while it plays, owns the stage: the HUD
   that would sit under it fades out (the same :has() pattern the sports and ship HUDs use). */
body.mobile .mi-ban { box-sizing:border-box;padding:0 calc(var(--mobile-right) + 16px) 0 calc(var(--mobile-left) + 16px); }
body.mobile .mi-ban small { font-size:13px;letter-spacing:.3em; }
body.mobile .mi-ban h2 { font-size:clamp(28px,8.5vw,44px); }
body.mobile .mi-ban p { max-width:30em;font-size:17px;line-height:1.3; }
body.mobile .mi-ban .rw { flex-wrap:wrap;justify-content:center;gap:8px; }
body.mobile .mi-ban .rw span { font-size:20px;padding:2px 10px; }
body.mobile .mi-hud.ban .mi-track,body.mobile .mi-hud.ban .mi-sub,body.mobile .mi-hud.ban .mi-toasts,body.mobile .mi-hud.ban .mi-wallet,body.mobile .mi-hud.ban .mi-gain,
body.mobile:has(.mi-hud.ban) .map-wrap,body.mobile:has(.mi-hud.ban) .location,body.mobile:has(.mi-hud.ban) .flight-hud,body.mobile:has(.mi-hud.ban) #destination,body.mobile:has(.mi-hud.ban) #course-invite { opacity:0!important;pointer-events:none!important; }
/* U06 objective card: a compact stack (title and step clamp, no pip row) whose timer chip sits below the step instead of on
   top of the "Paso n/m" counter, and bark subtitles ride above the hint / prompt / toast band instead of on it. */
body.mobile .mi-title { display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden; }
body.mobile .mi-step { display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden; }
body.mobile .mi-pips { display:none; }
body.mobile .mi-tip { position:static;display:block;width:max-content;max-width:100%;margin-top:6px;font-size:13px; }
body.mobile .mi-tip[hidden] { display:none; }
/* Off-screen objective arrows keep only the distance on a phone: a long label ran off the screen edge, and the card names the target. */
body.mobile .mi-wp.edge b { display:none; }
body.mobile .mi-sub { bottom:calc(var(--mobile-bottom) + min(312px,42dvh));max-width:calc(100vw - 2 * max(var(--mobile-left),var(--mobile-right)) - 28px); }
/* On screens up to 760px tall the spoken line and the objective card compete for the same middle band: the card yields while it plays. */
@media(max-height:760px) { body.mobile .mi-hud.bark .mi-track { opacity:0!important; } }
/* U06 story surfaces, phone landscape (any width, short height). The dialogue becomes a wide, low panel: portrait and line on
   the left, the answers on the right (two columns from three answers up), so the player stays visible. */
@media(orientation:landscape) and (max-height:560px) {
  body.mobile .mi-dlg { bottom:calc(var(--mobile-bottom) + 8px); }
  body.mobile .mi-dlg-portrait { width:48px;height:48px;margin-bottom:4px; }
  body.mobile .mi-dlg-box { padding:10px 12px 10px 18px;max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 20px); }
  body.mobile .mi-dlg-name { font-size:17px; }
  body.mobile .mi-dlg-text { font-size:17px;line-height:1.3;margin:6px 0 2px;min-height:0; }
  body.mobile .mi-dlg-choices { margin-top:0;gap:5px; }
  body.mobile .mi-dlg-choice { font-size:15px;padding:6px 10px; }
  body.mobile .mi-dlg.has-choices .mi-dlg-box { display:grid;grid-template-columns:minmax(0,1fr) minmax(0,46%);column-gap:14px;align-items:start; }
  body.mobile .mi-dlg.has-choices .mi-dlg-name,body.mobile .mi-dlg.has-choices .mi-dlg-text { grid-column:1; }
  body.mobile .mi-dlg.has-choices .mi-dlg-choices { grid-column:2;grid-row:1/span 3; }
  body.mobile .mi-dlg.many .mi-dlg-box { grid-template-columns:minmax(0,36%) minmax(0,1fr); }
  body.mobile .mi-dlg.many .mi-dlg-choices { display:grid;grid-template-columns:repeat(2,minmax(0,1fr)); }
  body.mobile .mi-dlg-acts { margin-top:4px; }
  body.mobile .mi-sub { bottom:calc(var(--mobile-bottom) + 146px);max-width:44vw;font-size:14px; }
  body.mobile .mi-title { -webkit-line-clamp:1; }
  body.mobile .mi-step { -webkit-line-clamp:2; }
  body.mobile .mi-ban { top:18%; }
  /* Journal: list and detail side by side on any short landscape screen (the stacked layout below 721px left one row of the
     list and three lines of detail), both panes scrolling inside the card, the actions in reach. */
  body.mobile .mi-jr-head { padding:6px 14px; }
  body.mobile .mi-jr-head h2 { font-size:22px; }
  body.mobile .mi-jr-body { grid-template-columns:minmax(170px,36%) minmax(0,1fr);grid-template-rows:minmax(0,1fr); }
  body.mobile .mi-jr-list { max-height:none;min-height:0;border-right:1px solid #ffffff1c;border-bottom:0; }
  body.mobile .mi-jr-det { max-height:none;min-height:0;padding:10px 16px; }
  body.mobile .mi-jr-foot { padding:6px 14px;font-size:14px; }
  body.mobile .mi-ban h2 { font-size:clamp(26px,5vw,40px); }
  body.mobile .mi-ban p { font-size:16px; }
}

/* U06 cinematics: Saltar is a real >=44px touch target at the top-right (clear of the caption), inside the safe areas, with no
   keyboard wording; the caption wraps between the insets instead of running under the button. */
body.mobile #lk-cine .skip {
  top:calc(env(safe-area-inset-top,0px) + 12px);right:calc(env(safe-area-inset-right,0px) + 14px);bottom:auto;
  min-width:96px;min-height:44px;padding:0 20px;font-size:14px;touch-action:manipulation;
}
body.mobile #lk-cine .skip .kb { display:none; }
body.mobile #lk-cine .cap { left:calc(env(safe-area-inset-left,0px) + 16px);right:calc(env(safe-area-inset-right,0px) + 16px);bottom:calc(env(safe-area-inset-bottom,0px) + 12vh); }

body.mobile .mi-jr { padding:calc(var(--mobile-top) + 12px) calc(var(--mobile-right) + 12px) calc(var(--mobile-bottom) + 12px) calc(var(--mobile-left) + 12px);backdrop-filter:none;-webkit-backdrop-filter:none; }
body.mobile .mi-jr-card { width:100%;max-height:100%;border-radius:18px; }
body.mobile .mi-jr-head { padding:10px 14px;gap:8px;align-items:center; }
body.mobile .mi-jr-head h2 { font-size:25px; }
body.mobile .mi-jr-head span { font-size:10px; }
body.mobile .mi-jr-head .kb { display:none; }
body.mobile .mi-jr-btn,body.mobile .mi-jr-row { min-height:44px; }
body.mobile .mi-jr-row { font-size:16px; }
body.mobile .mi-jr-det { padding:14px 16px; }
body.mobile .mi-jr-det p { font-size:16px;line-height:1.4; }
body.mobile .mi-jr-steps li { font-size:15px; }
/* U06 job payout cards (taxi shift, mail flight): inside the safe areas, >=44px buttons, no Enter / Esc wording on a phone. */
body.mobile .tx-pay,body.mobile .pm-pay { box-sizing:border-box;padding:calc(var(--mobile-top) + 12px) calc(var(--mobile-right) + 12px) calc(var(--mobile-bottom) + 12px) calc(var(--mobile-left) + 12px);backdrop-filter:none;-webkit-backdrop-filter:none; }
body.mobile .tx-card,body.mobile .pm-card { width:min(660px,100%);max-height:100%; }
body.mobile .tx-btn,body.mobile .pm-btn { display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 18px;font-size:16px; }
body.mobile .tx-btn .kb,body.mobile .pm-btn .kb { display:none; }
body.mobile .rl-root { padding:calc(var(--mobile-top) + 12px) calc(var(--mobile-right) + 12px) calc(var(--mobile-bottom) + 12px) calc(var(--mobile-left) + 12px);backdrop-filter:none;-webkit-backdrop-filter:none; }
body.mobile .rl-panel { width:100%;max-height:100%;padding:20px 16px; }
body.mobile .rl-close,body.mobile .rl-btn,body.mobile .rl-chip { min-height:44px; }
body.mobile .rl-chip { left:calc(var(--mobile-left) + 16px);bottom:calc(var(--mobile-bottom) + 240px); }

/* A match's own score replaces exploration readouts, while the unified fire
   button remains the only touch action. The ship retains tappable telegraph. */
body.mobile .sp-act { display:none!important; }
body.mobile .sp-board { top:calc(var(--mobile-top) + 112px);width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 28px);min-width:0;gap:8px;padding:8px 10px;border-radius:16px;box-sizing:border-box; }
body.mobile .sp-team { font-size:15px;overflow:hidden;text-overflow:ellipsis; }
body.mobile .sp-score { font-size:28px; }
body.mobile .sp-mid { min-width:86px; }
body.mobile .sp-status { font-size:13px; }
body.mobile .sp-power { bottom:calc(var(--mobile-bottom) + 246px); }
body.mobile .sp-hint { bottom:calc(var(--mobile-bottom) + 220px);font-size:11px; }
body.mobile:has(.sp-hud:not([hidden])) .map-wrap,body.mobile:has(.sp-hud:not([hidden])) .location,body.mobile:has(.sp-hud:not([hidden])) .flight-hud { display:none; }
body.mobile .shd { top:calc(var(--mobile-top) + 110px);bottom:auto;width:min(440px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 28px));max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 350px);padding:10px;gap:10px;box-sizing:border-box;overflow-y:auto;justify-content:center;pointer-events:auto;backdrop-filter:none;-webkit-backdrop-filter:none;border-radius:16px; }
body.mobile .shd-tele { display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;flex:1 0 100%;min-width:0; }
body.mobile .shd-row { display:grid;place-items:center;min-height:44px;padding:4px;font-size:11px;letter-spacing:.02em;background:#ffffff10;border-radius:8px; }
body.mobile .shd-mid { min-width:100px; }
body.mobile .shd-kn { font-size:25px; }
body.mobile .shd-un { font-size:9px; }
body.mobile .shd-hdg,body.mobile .shd-dist,body.mobile .shd-hint { font-size:11px; }
body.mobile .shd-side { min-width:130px; }
body.mobile .shd-btns { display:flex;flex-direction:row;flex:1 0 100%;gap:6px; }
body.mobile .shd-btns button { flex:1;min-height:44px;padding:8px;font-size:11px;border-radius:10px; }
body.mobile .shd-keys { display:none; }
body.mobile:has(.shd:not([hidden])) .map-wrap,body.mobile:has(.shd:not([hidden])) .location,body.mobile:has(.shd:not([hidden])) .flight-hud { display:none; }
body.mobile #jet-hud #jh-head { top:calc(var(--mobile-top) + 244px);font-size:11px; }
body.mobile #jet-hud .cell { top:40%;min-width:72px;padding:7px;backdrop-filter:none;-webkit-backdrop-filter:none; }
body.mobile #jet-hud #jh-speed { left:calc(var(--mobile-left) + 12px); }
body.mobile #jet-hud #jh-alt { right:calc(var(--mobile-right) + 12px); }
body.mobile #jet-hud .cell b { font-size:17px; }
body.mobile #jet-hud .cell small { font-size:8px; }
body.mobile #jet-hud #jh-warn { top:calc(var(--mobile-top) + 276px);font-size:13px;white-space:normal;width:max-content;max-width:calc(100vw - 36px); }

@media(min-width:640px) and (max-height:560px) {
  body.mobile #interface header { grid-template-columns:100px minmax(0,1fr);gap:12px;right:calc(var(--mobile-right) + 70px); }
  body.mobile #interface header .wordmark { font-size:20px; }
  body.mobile .top-actions { height:48px; }
  body.mobile.playing .map-wrap { top:calc(var(--mobile-top) + 70px);width:100px; }
  body.mobile.playing #minimap { width:100px;height:70px; }
  body.mobile.playing .location { top:calc(var(--mobile-top) + 72px);left:calc(var(--mobile-left) + 126px);right:auto;max-width:200px; }
  body.mobile.playing .location h1,body.mobile.playing .location.fresh h1 { font-size:18px; }
  body.mobile.playing .flight-hud { top:calc(var(--mobile-top) + 112px);left:calc(var(--mobile-left) + 126px);max-width:190px; }
  body.mobile.playing #flight-btn { min-height:44px; }
  body.mobile #joystick { bottom:calc(var(--mobile-bottom) + 16px); }
  body.mobile #touch-controls #touch-swing { bottom:calc(var(--mobile-bottom) + 12px); }
  body.mobile #touch-controls #touch-jump { bottom:calc(var(--mobile-bottom) + 14px); }
  body.mobile #touch-controls #touch-trick { bottom:calc(var(--mobile-bottom) + 18px); }
  body.mobile #touch-controls #touch-ride { bottom:calc(var(--mobile-bottom) + 174px); }
  body.mobile #touch-controls #touch-siren { bottom:calc(var(--mobile-bottom) + 14px); }
  body.mobile #touch-controls #touch-interact { bottom:calc(var(--mobile-bottom) + 176px); }
  body.mobile #action-prompt { bottom:calc(var(--mobile-bottom) + 224px); }
  body.mobile #traversal-hint.visible,body.mobile .toast { bottom:calc(var(--mobile-bottom) + 230px);font-size:11px; }
  body.mobile .pb-hud { --pb-bottom:calc(var(--mobile-bottom) + 236px); }
  body.mobile .snap-btn { left:calc(var(--mobile-left) + 146px);bottom:calc(var(--mobile-bottom) + 16px); }
  body.mobile #touch-controls #touch-torch { left:calc(var(--mobile-left) + 204px);bottom:calc(var(--mobile-bottom) + 16px); }
  body.mobile.nv-dark.playing #touch-controls #touch-torch { left:calc(var(--mobile-left) + 204px)!important;bottom:calc(var(--mobile-bottom) + 16px)!important; }
  body.mobile .mi-wallet { top:calc(var(--mobile-top) + 194px);width:100px; }
  body.mobile .mi-gain { top:calc(var(--mobile-top) + 196px); }
  body.mobile .mi-track { left:calc(var(--mobile-left) + 336px);top:calc(var(--mobile-top) + 72px);width:min(220px,27vw);padding:8px 10px; }
  body.mobile .mi-pips { display:none; }
  body.mobile .mi-toasts { top:calc(var(--mobile-top) + 70px);width:min(320px,40vw); }
  body.mobile .mi-sub { bottom:calc(var(--mobile-bottom) + 146px);max-width:44vw;font-size:14px; }
  body.mobile .mph-root.has-peers .mph-btn { top:calc(var(--mobile-top) + 70px); }
  body.mobile .mph-list { top:calc(var(--mobile-top) + 65px);max-width:640px;max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 80px); }
  body.mobile .sp-board { top:calc(var(--mobile-top) + 70px);width:min(360px,46vw); }
  body.mobile .sp-power { bottom:calc(var(--mobile-bottom) + 84px);width:220px; }
  body.mobile .sp-hint { bottom:calc(var(--mobile-bottom) + 60px);max-width:40vw; }
  body.mobile .shd { top:calc(var(--mobile-top) + 70px);max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 95px);width:min(380px,46vw); }
  body.mobile #jet-hud #jh-head { top:calc(var(--mobile-top) + 70px); }
  body.mobile #jet-hud #jh-warn { top:calc(var(--mobile-top) + 102px); }
  body.mobile #jet-hud .cell { top:43%; }
  body.mobile #jet-hud #jh-speed { left:calc(var(--mobile-left) + 250px); }
  body.mobile #jet-hud #jh-alt { right:calc(var(--mobile-right) + 250px); }
  body.mobile .snap-card { flex-direction:row;gap:20px;max-width:720px; }
  body.mobile .snap-card img { max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 32px);max-width:40vw; }
  body.mobile .lki .lki-top { padding-top:10px; }
  body.mobile .lki .lki-hero { padding-top:8px; }
  body.mobile .lki .lki-title { font-size:46px; }
  body.mobile .lki .lki-tag { margin-top:5px;font-size:10px; }
  body.mobile .lki .lki-ask,body.mobile .lki .lki-desc,body.mobile .lki .lki-sub { display:none; }
  body.mobile .lki .lki-choices { flex-direction:row;margin:12px 0;gap:12px; }
  body.mobile .lki .lki-card { width:50%;padding:12px 16px;gap:6px; }
  body.mobile .lki .lki-name { font-size:25px; }
  body.mobile .lki .lki-foot { padding-bottom:8px;gap:6px; }
  body.mobile .icr.icr { display:grid;grid-template-columns:minmax(240px,.85fr) minmax(0,1.15fr);grid-template-rows:auto minmax(0,1fr);overflow:hidden; }
  body.mobile .icr .icr-top { grid-column:1/-1;min-height:52px;padding-block:5px; }
  body.mobile .icr .icr-stage { height:auto;min-height:0; }
  body.mobile .icr .icr-panel { margin:0 10px 10px 0;min-height:0;overflow:hidden; }
  body.mobile .icr .icr-scroll { overflow-y:auto;min-height:0;padding-top:10px;gap:12px; }
  body.mobile .icr .icr-actions { flex:none;position:static;padding:8px 12px; }
  body.mobile .icr .icr-primary,body.mobile .icr .icr-go .icr-ghost { height:46px;min-height:46px; }
  body.mobile .icr .icr-tabs { grid-template-columns:repeat(8,minmax(0,1fr));gap:2px; }
  body.mobile .icr .icr-status { margin:5px 0 0;font-size:12px; }
}
@media(max-width:360px) {
  body.mobile #joystick { left:calc(var(--mobile-left) + 10px);width:116px;height:116px; }
  body.mobile #joystick i { left:35px;top:35px; }
  body.mobile .lki .lki-card { padding:12px 14px; }
  body.mobile .icr .icr-mark { font-size:19px; }
}
@media(max-width:699px) and (max-height:600px) {
  body.mobile .icr .icr-stage { height:25dvh;min-height:140px; }
  body.mobile .icr .icr-heroname { font-size:23px; }
  body.mobile .icr .icr-actions { padding:8px 12px; }
  body.mobile .icr .icr-status { margin-block:5px 0;font-size:12px; }
}
/* Short landscape phones under 700px (667x375, 640x360) keep the portrait HUD, whose
   minimap column reaches 235px from the top and covers the stick's upper rim; park the
   stick beside the minimap so the map button stays fully tappable. */
@media(min-width:560px) and (max-width:639px) and (max-height:420px) and (orientation:landscape) {
  body.mobile #joystick { left:calc(var(--mobile-left) + 132px); }
  /* The stacked wordmark + tool strip reached y=104 and covered the top of ENTRAR/ACCIÓN (568x320): put the wordmark
     beside the strip, as the 640px+ landscape block does, so the strip ends at y=58. */
  body.mobile #interface header { grid-template-columns:100px minmax(0,1fr);gap:12px;right:calc(var(--mobile-right) + 70px); }
  body.mobile #interface header .wordmark { font-size:20px; }
  body.mobile .top-actions { height:48px; }
  /* The toast, hint and prompt sat at y~16-72, which was just above the old strip; keep them below the new one. */
  body.mobile #action-prompt { bottom:calc(var(--mobile-bottom) + 218px); }
  body.mobile #traversal-hint.visible { bottom:calc(var(--mobile-bottom) + 214px); }
  body.mobile .toast { bottom:calc(var(--mobile-bottom) + 200px); }
}
@media(prefers-reduced-motion:reduce) {
  body.mobile #touch-controls button,body.mobile .lki,body.mobile .icr { transition:none; }
}
/* Robustness (U09): several modules inject their own keyframes (police, paintball, jet HUD, snapshot, discoveries...) without a
   reduced-motion branch. Shrink every animation/transition to a single imperceptible step (not `none`, so animationend still fires). */
@media(prefers-reduced-motion:reduce) {
  *,*::before,*::after { animation-duration:.01ms!important;animation-delay:0s!important;animation-iteration-count:1!important;transition-duration:.01ms!important;transition-delay:0s!important;scroll-behavior:auto!important; }
}

/* ===== Phone HUD (U02): one folded top bar, a clear column per kind of readout ===========================
   Top row: wordmark, then [mph] [⋯] [pause] at the right edge (44px each, 8px apart). The toolbar keeps
   the four tools a player reaches for most (GRUPOS, the online pill, missions, discoveries); swag, time
   of day, photo, sound, rooftops and help sit behind the ⋯ button, which opens them as a second row of the
   same bar (hud-more.js). Nothing scrolls sideways any more, so nothing hides off-screen.
   Portrait: map, wallet and objective stack on the left; place, speed, combo and route card on the right.
   Landscape: see the media block below. Desktop is untouched (everything is under body.mobile). */
#hud-more { display:none; }
/* Before play the wallet only sat on top of the place description (390x844: "$40 / NIVEL 1" over the second line). */
body.mobile:not(.playing) .mi-wallet,body.mobile:not(.playing) .mi-gain,body.mobile:not(.playing) .mi-track { display:none; }
body.mobile #hud-more {
  display:flex;align-items:center;justify-content:center;position:absolute;z-index:9;
  top:calc(var(--mobile-top) + 8px);right:calc(var(--mobile-right) + 66px);width:44px;height:44px;min-width:44px;padding:0;
  border-radius:50%;border:1px solid var(--mg-line);background:var(--mg-glass);box-shadow:var(--mg-lift);
  color:var(--mobile-paper);font:800 22px/1 var(--fl-cond,system-ui,sans-serif);pointer-events:auto;touch-action:manipulation;
}
body.mobile #hud-more[aria-expanded=true] { background:var(--mobile-sea);color:#153943;border-color:var(--mobile-paper); }
body.mobile #interface header { z-index:9; }
body.mobile.playing #interface header .wordmark { width:max-content;max-width:150px;justify-self:start;align-self:start;pointer-events:none; }
body.mobile .top-actions {
  height:44px;padding:0;overflow:visible;flex-wrap:wrap;align-content:flex-start;touch-action:auto;
}
/* A zero-height full-row item sits between the primary tools (order <= 0) and the folded ones (order 5). */
body.mobile .top-actions::after { content:"";order:4;flex:0 0 100%;height:0; }
body.mobile .top-actions>:is(#rewards-btn,#mode-btn,#photo-btn,#sound-btn,#course-btn,#help-btn) { order:5; }
body.mobile .top-actions:not(.more-open)>:is(#rewards-btn,#mode-btn,#photo-btn,#sound-btn,#course-btn,#help-btn) { display:none; }
body.mobile .top-actions.more-open {
  height:auto;row-gap:7px;box-sizing:content-box;width:100%;margin:-3px -6px -6px;padding:3px 6px 6px;border:1px solid var(--mg-line);border-radius:28px;
  background:#12333ff2;box-shadow:0 10px 28px #04141b66;
}
body.mobile #online-count { max-width:150px; }
body.mobile.playing .mph-root.has-peers .mph-btn { top:calc(var(--mobile-top) + 8px);right:calc(var(--mobile-right) + 118px); }
/* The players list is a sheet: it has to sit above the wallet, objective and photo button, not under them. */
body.mobile .mph-root.list-open { z-index:12; }
body.mobile:has(.mph-root.list-open) .snap-btn { visibility:hidden; } /* the photo button (z-index 1400, outside the HUD layer) floated over the rows */
/* The nearby-players panel is placed by script to end at the pill's right edge; the pill now sits left of centre,
   so on a phone it would run off the left edge. Anchor it to the left gutter instead. */
body.mobile #online-nearby { left:calc(var(--mobile-left) + 10px)!important;right:auto!important; }
/* Combo meter: it was left:14px but still carried the desktop translateX(-50%), so half of it sat off the left
   edge, and it sat in the hint/toast band. It now owns a slot under the speed readout, right-aligned. */
body.mobile.playing #flow-hud {
  left:auto;right:calc(var(--mobile-right) + 14px);top:calc(var(--mobile-top) + 208px);bottom:auto;transform:none;
  width:min(220px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 156px));justify-items:end;
}
body.mobile.playing #flow-hud .flow-score { justify-content:flex-end; }
body.mobile.playing #flow-hud .flow-feed { top:100%;bottom:auto;right:0;margin:6px 0 0;align-items:flex-end;max-width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 28px); }
body.mobile.playing #flow-hud .flow-pop:nth-child(n+3) { display:none; }
/* The cards on the right share one slot below the combo meter. */
body.mobile #destination,body.mobile #course-invite { top:calc(var(--mobile-top) + 290px); }
body.mobile #course-invite { max-width:min(220px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 156px)); }
/* On a narrow portrait phone the route card (right) and the objective (left) share the width: narrow both a little. */
@media(max-width:480px) {
  body.mobile.route-on #destination { width:156px; }
  body.mobile.route-on .mi-track { width:min(230px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 192px)); }
}
body.mobile .top-actions #course-btn { min-width:44px; }
/* Short screens (small portrait phones and every landscape phone): the map's label row cost 44px of a column that
   also holds the wallet and the objective, and the card ran into the photo button. The ↗ button now overlays the
   map's corner and the label (which only repeats the place name) is dropped. */
@media(max-height:700px) {
  body.mobile.playing #interface .map-wrap>div { position:absolute;right:0;bottom:0;display:block;min-height:0;padding:0;border:0;background:none; }
  body.mobile.playing #interface .map-wrap>div>span#map-location { display:none; }
  body.mobile.playing #map-btn { background:#173947d9;border-radius:12px 0 0 0; }
}
@media(max-height:700px) and (max-width:639px) and (orientation:portrait) {
  body.mobile .mi-wallet { top:calc(var(--mobile-top) + 196px); }
  body.mobile .mi-gain { top:calc(var(--mobile-top) + 202px); }
  body.mobile .mi-track { top:calc(var(--mobile-top) + 276px); }
  body.mobile.playing #reward-boost-status { bottom:calc(var(--mobile-bottom) + 160px); }
}
@media(max-height:560px) and (min-width:640px) {
  /* Landscape: the screen is wide and short. Map and wallet stack in the left column (map label dropped, its
     button overlays the corner), place and speed take the next column, the objective and the route card follow. */
  body.mobile.playing .map-wrap { top:calc(var(--mobile-top) + 62px); }
  body.mobile.playing #minimap { height:70px; }
  body.mobile .mi-wallet { top:calc(var(--mobile-top) + 138px);padding:6px 10px; }
  body.mobile .mi-gain { top:calc(var(--mobile-top) + 140px);left:calc(var(--mobile-left) + 120px); }
  body.mobile .mi-cash { font-size:20px; }
  body.mobile.playing .location { top:calc(var(--mobile-top) + 64px);max-width:136px; }
  body.mobile.playing .flight-hud { max-width:136px; }
  body.mobile.playing #flow-hud {
    left:calc(var(--mobile-left) + 126px);right:auto;top:calc(var(--mobile-top) + 156px);width:136px;justify-items:start;
  }
  body.mobile.playing #flow-hud .flow-score { justify-content:flex-start; }
  body.mobile.playing #flow-hud .flow-score strong { font-size:22px; }
  body.mobile.playing #flow-hud .flow-score span { display:none; }
  body.mobile.playing #flow-hud .flow-feed { right:auto;left:0;align-items:flex-start; }
  body.mobile .mi-track { left:calc(var(--mobile-left) + 266px);top:calc(var(--mobile-top) + 62px);width:min(220px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 474px)); }
  body.mobile #destination,body.mobile #course-invite { top:calc(var(--mobile-top) + 62px); }
  body.mobile.playing #reward-boost-status { bottom:calc(var(--mobile-bottom) + 124px); }
}

/* ---- Wave 4 V2: overlaps left by the UX matrix (photo button, cinematic, account, invite) ---- */
/* Photo button (V2-a). The mission journal is a body-level modal (z26, 80% scrim): the HUD layer and the photo button stayed
   painted/clickable under it and showed through, so hide them while it is open like every other modal (dialog[open],
   discoveries, photo result). */
body.mobile:has(.mi-jr.on) #interface,body.mobile:has(.mi-jr.on) .snap-btn { visibility:hidden; }
/* Short portrait phones (360x640, 375x667): the objective card ran 180px tall straight into the photo button above the stick.
   The button drops to sit just over the stick (its FOTO label still clears the ring) and the card is capped to the space
   above it: the step clamps to 2 lines (the title to 1 on the shortest) so the cap never cuts a chip. */
@media(max-height:700px) and (max-width:639px) and (orientation:portrait) {
  body.mobile .snap-btn { bottom:calc(var(--mobile-bottom) + 158px); }
  body.mobile .mi-track { max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 430px);overflow:hidden; } /* R16: was 490px = 78px at 320x568, which cut the status and timer lines; 430px ends above HABLAR (y332) at 568, 640 and 667 tall */
  body.mobile .mi-step { -webkit-line-clamp:2; }
}
@media(max-height:659px) and (max-width:639px) and (orientation:portrait) { body.mobile .mi-title { -webkit-line-clamp:1; } }
/* Cinematic (V2-b): the Saltar button sits BELOW the top letterbox bar (it used to straddle it), >=44px, inside the safe
   areas; the bars grow to cover the notch / home indicator. The HUD under the z9000 cover is hidden, not just covered. */
body.mobile #lk-cine .bar.t { height:max(9vh,var(--mobile-top)); }
body.mobile #lk-cine .bar.b { height:max(9vh,var(--mobile-bottom)); }
body.mobile #lk-cine .skip { top:calc(max(9vh,var(--mobile-top)) + 10px); }
body.mobile #lk-cine .prog { bottom:max(9vh,var(--mobile-bottom)); }
body.mobile:has(#lk-cine.on) #interface,body.mobile:has(#lk-cine.on) .snap-btn { visibility:hidden; }
/* Account modal (V2-d): Cerrar floats right; the title and subtitle are block boxes that spanned underneath it. As
   flow-root boxes they sit beside the float (and drop below it, never under it, when a long account name does not fit). */
body.mobile #lk-acct h2,body.mobile #lk-acct .lk-sub { display:flow-root; }
/* Invite dialog (V2-e): the 44px close button is absolute at the top-right; eyebrow and title keep clear of it. */
body.mobile .inv-dlg .inv-eyebrow,body.mobile .inv-dlg h2 { margin-right:52px; }
/* Invite card inside the notice lane (as narrow as 170px in portrait): a 2-column grid that may shrink, Instagram/Facebook
   share a row, WhatsApp and Copiar enlace take full rows and their labels wrap. It was an `auto auto 1fr` grid whose
   min-content ran 40-70% past the screen edge. Close is a 40px target. */
body.mobile.nl-on #notice-lane>.inv-card.on .inv-row { grid-template-columns:repeat(2,minmax(0,1fr));gap:6px; }
body.mobile.nl-on #notice-lane>.inv-card.on .inv-row button { min-width:0;min-height:40px;padding:6px 10px;justify-content:center; }
body.mobile.nl-on #notice-lane>.inv-card.on .inv-row .inv-wa,body.mobile.nl-on #notice-lane>.inv-card.on .inv-row .inv-cp { grid-column:1/-1;font-size:14px;line-height:1.15; }
body.mobile.nl-on #notice-lane>.inv-card.on .inv-row button span { min-width:0;overflow-wrap:anywhere;text-align:left; }
body.mobile.nl-on #notice-lane>.inv-card.on .inv-x { min-width:40px;min-height:40px;display:grid;place-items:center;padding:0;right:4px;top:4px; }
body.mobile.nl-on #notice-lane>.inv-card.on h3 { margin-right:44px; }
/* On a portrait phone the lane is 170-320px wide and shares the right column with prompts: keep the card to the two share
   routes that matter (WhatsApp, copy link); Instagram/Facebook stay in the Invita a tu pana dialog (and in landscape they were already hidden). */
@media(max-width:480px) and (orientation:portrait) { body.mobile.nl-on #notice-lane>.inv-card.on .inv-row .inv-ig,body.mobile.nl-on #notice-lane>.inv-card.on .inv-row .inv-fb { display:none; } }
/* Clipped text (V2-f): line-clamped text already ends in an ellipsis; saying so lets tools (and engines without
   line-clamp) see a clean truncation. */
body.mobile .mi-title,body.mobile .mi-step,body.mobile.playing #interface .map-wrap>div>span { text-overflow:ellipsis; }

/* Show loading before the mode cards, including the early boot before main.js
   classifies the device. The ready screen keeps its existing card layout. */
#graphics-recovery .lk-desktop-note { display:none; }
.lk-desktop-note strong,.lki-desktop-note strong { display:block; }
.lk-desktop-note span,.lki-desktop-note span { display:block;margin-top:3px; }
/* Q04: touch devices only. "or (max-width:1100px)" gave every narrow DESKTOP window the phone loading card on top of the title and told a computer user "En computadora se disfruta mucho mejor". */
@media(pointer:coarse) {
  body .lki.lki:not(.lki-ready) {
    height:100dvh;padding:env(safe-area-inset-top,0px) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);
  }
  body .lki.lki:not(.lki-ready) .lki-top { order:-2;padding:12px 16px 10px; }
  body .lki.lki:not(.lki-ready) .lki-coords { display:none; }
  body .lki.lki:not(.lki-ready) .lki-foot {
    order:-1;position:sticky;top:env(safe-area-inset-top,0px);z-index:2;align-self:stretch;
    margin:0 12px;padding:13px 15px;gap:0;min-height:0;
    border:1px solid #8de1d252;border-radius:18px;background:#133440f5;box-shadow:0 4px 14px #081b2b30;
  }
  body .lki.lki:not(.lki-ready) .lki-load { width:100%;max-width:620px;align-items:stretch;gap:7px; }
  body .lki.lki:not(.lki-ready) .lki-wait { order:0;font-size:18px;line-height:1.2;letter-spacing:.025em;text-align:left; }
  body .lki.lki:not(.lki-ready) .lki-status { order:1;font-size:12px;line-height:1.4;letter-spacing:.025em;text-align:left;color:#b9f6e9; }
  body .lki.lki:not(.lki-ready) .lki-meter { order:2;height:9px;flex:none;border-color:#ffffff50; }
  body .lki.lki:not(.lki-ready) .lki-desktop-note {
    display:block;order:3;max-width:none;margin:3px 0 0;padding-top:9px;border-top:1px solid #ffffff21;
    font:500 12px/1.4 var(--body,system-ui);text-align:left;color:#c8e9e5;
  }
  body .lki.lki:not(.lki-ready) .lki-desktop-note strong { font-size:13px;font-weight:800;color:#fff1c9; }
  body .lki.lki:not(.lki-ready) .lki-load-note { order:4;max-width:none;font-size:11px;line-height:1.4;text-align:left;color:#d2e0e4; }
  body .lki.lki:not(.lki-ready) .lki-keys { display:none; }
  body .lki.lki:not(.lki-ready) .lki-hero { flex:0 0 auto;min-height:0;padding-top:14px; }
  body .lki.lki:not(.lki-ready) .lki-title { font-size:clamp(40px,12vw,64px); }

  #loading {
    height:100dvh;justify-content:flex-start;gap:16px;overflow-y:auto;overscroll-behavior:contain;
    padding:calc(env(safe-area-inset-top,0px) + 14px) calc(env(safe-area-inset-right,0px) + 16px) calc(env(safe-area-inset-bottom,0px) + 16px) calc(env(safe-area-inset-left,0px) + 16px);
    background:linear-gradient(160deg,#133440f5,#111329f5);
  }
  #loading>.wordmark { flex:none;font-size:20px; }
  #loading>.wordmark span { display:none; }
  #loading>div { display:flex;flex-direction:column;gap:14px;margin:0; }
  #loading .lk-loading-info {
    order:-1;display:flex;flex-direction:column;gap:7px;padding:13px 15px;margin:0;
    border:1px solid #8de1d252;border-radius:18px;background:#133440f5;
  }
  #loading .lk-loading-info>p { margin:0; }
  #loading .lk-wait { order:0;font-size:18px;line-height:1.2;letter-spacing:.025em;text-shadow:none; }
  #loading #load-status { order:1;font-size:12px;line-height:1.4;letter-spacing:.025em;color:#b9f6e9; }
  #loading .load-line { order:2;flex:none;width:100%;height:9px;margin:0;border:1px solid #ffffff50;box-shadow:none; }
  #loading .lk-desktop-note {
    display:block;order:3;max-width:none;margin-top:3px;padding-top:9px;border-top:1px solid #ffffff21;font-size:12px;line-height:1.4;color:#c8e9e5;
  }
  #loading .lk-desktop-note strong { font-size:13px;font-weight:800;color:#fff1c9; }
  #loading .lk-load-note { order:4;max-width:none;font-size:11px;line-height:1.4;color:#d2e0e4; }
  #loading h1.lk-title { margin:8px 0 0;font-size:clamp(40px,12vw,64px);transform:none;-webkit-text-stroke:0;filter:none; }
  #loading .lk-tag { margin:0;font-size:12px;letter-spacing:.06em;text-shadow:none; }
  #loading>small { margin-top:auto;padding-top:12px; }

  #graphics-recovery {
    height:100dvh;place-items:start center;overflow-y:auto;overscroll-behavior:contain;
    padding:calc(env(safe-area-inset-top,0px) + 24px) calc(env(safe-area-inset-right,0px) + 20px) calc(env(safe-area-inset-bottom,0px) + 24px) calc(env(safe-area-inset-left,0px) + 20px);
  }
  #graphics-recovery>div { width:100%;max-width:560px; }
  #graphics-recovery h2 { margin:18px 0 10px;font-size:26px;line-height:1.15; }
  #graphics-recovery p { font-size:14px;line-height:1.45; }
  #graphics-recovery .lk-desktop-note { display:block;margin:12px 0;font-size:12px;line-height:1.4; }
  #graphics-recovery button { min-height:48px;margin-top:8px;max-width:100%;white-space:normal; }
}
@media(pointer:coarse) and (orientation:landscape) {
  body .lki.lki:not(.lki-ready) .lki-foot { padding:10px 14px; }
  body .lki.lki:not(.lki-ready) .lki-load,#loading .lk-loading-info {
    display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:6px 20px;align-items:start;
  }
  body .lki.lki:not(.lki-ready) .lki-wait,#loading .lk-wait { grid-column:1;grid-row:1; }
  body .lki.lki:not(.lki-ready) .lki-status,#loading #load-status { grid-column:1;grid-row:2; }
  body .lki.lki:not(.lki-ready) .lki-meter,#loading .load-line { grid-column:1;grid-row:3; }
  body .lki.lki:not(.lki-ready) .lki-desktop-note,#loading .lk-desktop-note { grid-column:2;grid-row:1/3;border:0;padding:0;margin:0; }
  body .lki.lki:not(.lki-ready) .lki-load-note,#loading .lk-load-note { grid-column:2;grid-row:3; }
  body .lki.lki:not(.lki-ready) .lki-hero { padding-top:8px; }
  body .lki.lki:not(.lki-ready) .lki-title { font-size:42px; }
  body .lki.lki:not(.lki-ready) .lki-ask { display:none; }
  #loading { gap:10px; }
  #graphics-recovery { padding-top:calc(env(safe-area-inset-top,0px) + 14px); }
  #graphics-recovery h2 { margin-top:10px;font-size:24px; }
  #graphics-recovery p { margin:8px 0; }
}
/* Q04: a landscape phone (height <= 450) showed the loading card at ~140px and pushed SOLO / MULTIJUGADOR below the fold
   (scrollHeight 475 in a 390px viewport). Dropping the wordmark strip and the desktop upsell while loading, and tightening
   the status line and card padding, brings the CTAs into view at 844x390, 932x430, 896x414, 812x375 (measured). The load
   note ("deja esta pantalla abierta") stays: it is what tells the player the wait is not a freeze. */
@media(pointer:coarse) and (orientation:landscape) and (max-height:450px) {
  body .lki.lki:not(.lki-ready) .lki-top,body .lki.lki:not(.lki-ready) .lki-desktop-note { display:none; }
  body .lki.lki:not(.lki-ready) .lki-wait { font-size:16px; }
  body .lki.lki:not(.lki-ready) .lki-foot { padding:8px 14px; }
}

/* Phone polish. One calm, consistent surface for every HUD element: a lit
   tropical-night glass (gradient + hairline + top highlight), a single type
   voice for labels, and soft depth instead of hard slab shadows. Everything
   here is static paint: no backdrop blur, no animated shadows or filters, and
   nothing that changes per frame, so the GPU and main thread cost is nil. */
body.mobile {
  --mg-glass:linear-gradient(180deg,#235a69e6 0%,#173f4deb 55%,#12333fee 100%);
  --mg-line:#fff6e433;
  --mg-lift:inset 0 1px 0 #ffffff21,0 6px 16px #04141b40;
  --mg-press:inset 0 1px 0 #ffffff14,0 2px 6px #04141b40;
  /* The toolbar scrolls sideways (overflow clips): keep its depth inside it. */
  --mg-chip:inset 0 1px 0 #ffffff21,0 2px 4px #04141b38;
}
/* Wordmark: same sunset gradient, now legible over bright sky and sand. */
body.mobile #interface header .wordmark { filter:drop-shadow(0 2px 0 #0d2b36b3); }
/* Toolbar chips and the pause button. */
body.mobile #interface .top-actions button,
body.mobile #interface .top-actions .pill {
  border-radius:22px;border:1px solid var(--mg-line);background:var(--mg-glass);box-shadow:var(--mg-chip);
  font:800 13px/1 var(--fl-cond,system-ui,sans-serif);letter-spacing:.07em;text-transform:uppercase;color:var(--mobile-paper);
}
body.mobile #interface .top-actions .lkg-game-trigger { background:var(--mg-glass)!important; }
body.mobile #interface .top-actions .icon-btn { border-radius:50%;font-size:18px;letter-spacing:0; }
body.mobile #interface #pause-btn { border-radius:50%;border:1px solid var(--mg-line);background:var(--mg-glass);box-shadow:var(--mg-lift);font-size:20px; }
/* Navigation column: map, wallet and objective share one card style. */
body.mobile.playing #interface .map-wrap { border-radius:18px;border:1px solid var(--mg-line);background:var(--mg-glass);box-shadow:var(--mg-lift); }
body.mobile.playing #interface .map-wrap>div>span { display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;line-height:1.2; }
body.mobile .mi-hud .mi-wallet { border:1px solid var(--mg-line);border-left:3px solid var(--fl-sun,#ffd23f);border-radius:16px;background:var(--mg-glass);box-shadow:var(--mg-lift); }
/* The objective keeps its own left accent (pink main story, cyan side job). */
body.mobile .mi-hud .mi-track { border-top:1px solid var(--mg-line);border-right:1px solid var(--mg-line);border-bottom:1px solid var(--mg-line);border-radius:16px;background:var(--mg-glass);box-shadow:var(--mg-lift); }
body.mobile.playing #interface #flight-btn { border-radius:22px;border:1px solid var(--mg-line);background:var(--mg-glass);box-shadow:var(--mg-lift); }
/* Readouts: crisp outlines. The old 10px glow was clipped by overflow:hidden
   into a dark box behind short labels such as "A PIE". */
body.mobile.playing #interface #motion-label { text-shadow:0 1px 0 #000c,0 1px 3px #0009;padding-block:1px; }
body.mobile.playing #interface .location h1,
body.mobile.playing #interface .location.fresh h1 { text-shadow:0 1px 0 #0d2b36,0 2px 8px #0d2b3699; }
/* Hints, toasts and prompts read as the same glass, centred and calm. */
body.mobile #interface #traversal-hint.visible,
body.mobile #interface .toast,
body.mobile #interface #action-prompt {
  border:1px solid var(--mg-line);border-radius:16px;background:var(--mg-glass);box-shadow:var(--mg-lift);color:var(--mobile-paper);
}
/* Touch controls keep their colours and places; they gain a soft top light
   and real depth, and press down cleanly. */
body.mobile #interface #touch-controls button {
  background-image:linear-gradient(180deg,#ffffff2e,#ffffff00 58%);
  box-shadow:inset 0 1px 0 #ffffff59,0 3px 0 #0e2a34a6,0 8px 18px #04141b4d;
}
body.mobile #interface #touch-controls button.held,
body.mobile #interface #touch-controls button:active { background-image:linear-gradient(180deg,#ffffff12,#ffffff00 58%);box-shadow:inset 0 1px 0 #ffffff33,0 1px 0 #0e2a3499,0 3px 8px #04141b40; }
body.mobile #interface #joystick { background:radial-gradient(circle at 50% 42%,#2a5f6c80,#17394770 62%); }
body.mobile #interface #joystick i { box-shadow:inset 0 1px 0 #ffffffa6,0 3px 0 #14354170,0 6px 14px #04141b4d; }
/* Phone landscape: the wordmark stays on one line, and hints/toasts sit in the
   free band between the thumbs instead of colliding with the speed readout. */
@media(min-width:640px) and (max-height:560px) {
  body.mobile #interface header .wordmark { white-space:nowrap;font-size:17px;letter-spacing:1px; }
  /* Centred between the thumb clusters: clear of the joystick, photo and
     torch buttons on the left and the trick button on the right. */
  body.mobile #interface #traversal-hint.visible,
  body.mobile #interface .toast,
  body.mobile #interface #action-prompt { max-width:max(150px,calc(100vw - 2 * (max(var(--mobile-left), var(--mobile-right)) + 262px))); }
  body.mobile #interface #traversal-hint.visible,
  body.mobile #interface .toast { bottom:calc(var(--mobile-bottom) + 16px); }
  body.mobile #interface #action-prompt { bottom:calc(var(--mobile-bottom) + 76px)!important; }
}
/* No live backdrop blur over the moving 3D view on phones: every frame the
   browser would re-blur what is behind it. These surfaces are already nearly
   opaque, so the look holds; the photo-mode exit just gets a firmer fill. */
body.mobile #interface .toast,body.mobile #flight-btn,body.mobile .traversal-course-card,
body.mobile #exit-photo,body.mobile .tx-pay,body.mobile .pm-pay { backdrop-filter:none;-webkit-backdrop-filter:none; }
body.mobile #exit-photo { background:#0c2936d9; }

/* ---- Wave 4 U04: Help overlay on touch ---------------------------------
   The touch help is the short .mobile-help card. The keyboard tables, the
   key-only note and their headings are desktop content: hide them here so the
   sheet stays short, scrolls, and never names a key the player does not have. */
body.mobile #help-dialog .help-category,
body.mobile #help-dialog > p.note:not(#swing-control-help),
body.mobile #help-dialog > p:not(.note):not(.session-stats) { display:none; }
body.mobile #help-dialog { padding:22px 18px calc(18px + var(--mobile-bottom)); }
body.mobile #help-dialog h2 { font-size:26px;margin-bottom:10px; }
body.mobile #help-dialog .mobile-help { margin:10px 0 14px;padding:2px 14px; }
body.mobile #help-dialog .mobile-help p { margin:10px 0;font-size:13px;line-height:1.45; }
body.mobile #help-dialog .help-section-title { margin:16px 0 10px; }
body.mobile #help-dialog #swing-control-help { font-size:12px;line-height:1.4; }
/* Landscape phones: use the width. Two text columns, a tighter title, and a close button that stays reachable while the sheet scrolls. */
@media(orientation:landscape) and (max-height:560px) {
  body.mobile #help-dialog {
    width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 24px);max-width:900px;
    max-height:calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 16px);padding:14px 18px calc(12px + var(--mobile-bottom));
  }
  body.mobile #help-dialog h2 { font-size:21px;line-height:1.05;margin:2px 44px 8px 0; }
  body.mobile #help-dialog .mobile-help { column-count:2;column-gap:20px;padding:12px 14px 0; }
  body.mobile #help-dialog .mobile-help p { break-inside:avoid;margin:0 0 12px; }
  body.mobile #help-dialog .close { position:sticky;top:0;float:right;right:auto;margin:-2px -4px 0 8px;z-index:2;background:#122f37; }
}

/* ---- Wave 4 U04: hint lane --------------------------------------------
   The traversal tip, the vehicle prompt and the "drag to look" line share ONE
   slot (hint-presenter.js shows only one at a time and keeps them off toasts,
   captions and dialogs). The slot sits just above the right thumb cluster in
   portrait and in the free band between the thumbs in landscape. --lk-slot is
   that bottom offset; text wraps inside the lane and clamps instead of growing
   into the controls. Measured on the rig: right cluster tops out at 236px
   (ENTRAR/HABLAR); bottom-row controls end at x=194 (FOTO) and begin 214px
   from the right edge (TRUCO). */
body.mobile { --lk-slot:250px;--lk-lines:3; }
body.mobile #interface #traversal-hint.visible,
body.mobile #interface #action-prompt,
body.mobile #touch-look-hint {
  bottom:calc(var(--mobile-bottom) + var(--lk-slot))!important;box-sizing:border-box;width:max-content;
  max-width:calc(100vw - var(--mobile-left) - var(--mobile-right) - 36px);text-align:center;white-space:normal;overflow-wrap:break-word;line-height:1.35;
}
body.mobile #interface #traversal-hint.visible,
body.mobile #touch-look-hint { display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--lk-lines);overflow:hidden; }
body.mobile #touch-look-hint {
  position:absolute;left:50%;top:auto;transform:translateX(-50%);padding:8px 12px;font:600 12px/1.35 system-ui,sans-serif;
  border:1px solid var(--mg-line);border-radius:16px;background:var(--mg-glass);box-shadow:var(--mg-lift);text-shadow:none;
}
/* Only the presenter's winner is on screen. */
body.mobile:not([data-lk-hint="look"]) #touch-look-hint { visibility:hidden; }
/* Short portrait phones (360x640, 375x667): the crosshair distance label ends at y=352 on 640 tall, so the lane
   moves 10px down (still 4px above ENTRAR/HABLAR at y=404) and shrinks to two compact lines. */
@media(max-height:700px) and (orientation:portrait) {
  body.mobile { --lk-slot:240px;--lk-lines:2; }
  body.mobile #interface #traversal-hint.visible,body.mobile #interface #action-prompt,body.mobile #touch-look-hint { padding:6px 10px;font-size:11px;line-height:1.3; }
}
@media(max-height:560px) and (min-width:640px) {
  body.mobile { --lk-slot:16px;--lk-lines:4; }
  body.mobile #interface #traversal-hint.visible,
  body.mobile #interface #action-prompt,
  body.mobile #touch-look-hint { max-width:min(440px,max(150px,calc(100vw - 2 * (max(var(--mobile-left),var(--mobile-right)) + 214px)))); }
}
@media(min-width:560px) and (max-width:639px) and (max-height:420px) and (orientation:landscape) { body.mobile { --lk-slot:214px;--lk-lines:3; } }

/* ===== Wave 4 V1: story surfaces own the stage (QA round 2) =====
   Dialogue (.mi-dlg), journal (.mi-jr) and native modals sit on top of the world: the crosshair and the control hint have
   no meaning under them and used to collide with them, so they step aside (the hint presenter also queues the tip, main.js). */
body.mobile:has(.mi-dlg.on,.mi-jr.on,dialog[open]) #reticle { visibility:hidden!important; }
body.mobile:has(.mi-dlg.on,.mi-jr.on) #traversal-hint { visibility:hidden!important; }
/* The tall invite card has no room on a 640px phone that does not touch the crosshair distance label: the label waits (the dot stays). */
body.mobile:has(#notice-lane>.inv-card.on) .reticle span { visibility:hidden; }
/* Short portrait phones (360x640, 375x667): the objective card (title 1 line, step 2 lines) ends above the photo button instead of on top of it. */
@media(max-height:700px) and (orientation:portrait) {
  body.mobile .mi-track { top:calc(var(--mobile-top) + 266px);padding:8px 12px; }
  body.mobile .mi-title { -webkit-line-clamp:1; }
  body.mobile .mi-step { -webkit-line-clamp:2; }
}
/* The journal is a full-screen modal over an 80% scrim: everything behind it (wallet, minimap, joystick, buttons, flight HUD,
   top actions, the photo button) is hidden, so nothing shows through or can be tapped. Only a live notice stays readable. */
body.mobile:has(.mi-jr.on) #interface,body.mobile:has(.mi-jr.on) .snap-btn { visibility:hidden!important; }
body.mobile:has(.mi-jr.on) #interface #notice-lane:not(.nl-idle):not(:empty) { visibility:visible!important; }
/* Centre thirds: the player and the crosshair live at the screen centre, so the story banner and the dialogue keep to the upper / lower third.
   Portrait: the banner starts under the two rows of top buttons; the dialogue card is capped so it stays in the lower half. */
@media(orientation:portrait) {
  body.mobile .mi-ban { top:calc(var(--mobile-top) + 104px); }
  body.mobile .mi-ban h2 { font-size:clamp(24px,7.2vw,40px); }
  body.mobile .mi-dlg-box { max-height:min(calc(100dvh - var(--mobile-top) - var(--mobile-bottom) - 90px),max(52dvh,320px)); }
}
/* Landscape phone: a compact banner right under the top button row (it was a 70px-tall title in the middle of the stage). */
@media(orientation:landscape) and (max-height:560px) {
  body.mobile .mi-ban { top:calc(var(--mobile-top) + 54px); }
  body.mobile .mi-ban h2 { font-size:clamp(20px,6.2vh,30px);margin:0; }
  body.mobile .mi-ban small { font-size:11px; }
  body.mobile .mi-ban p { font-size:14px;margin-top:2px; }
  body.mobile .mi-ban .rw { margin-top:4px; }
  body.mobile .mi-ban .rw span { font-size:16px;padding:0 8px; }
}
/* V3 (mp list): the players list is a modal sheet. While it is open the HUD blocks it would collide with (place name,
   speed, minimap, wallet and its cash pop, route card, hints) are hidden, not just covered, so nothing shows through or
   pokes out at its edges in portrait or landscape. They come back when it closes. */
body.mobile:has(.mph-root.list-open) :is(.location,#flight-hud,.map-wrap,.mi-wallet,.mi-gain,#destination,#traversal-hint,#action-prompt,.mi-track,#anchor-label,#touch-ride) { visibility:hidden; }
/* V3 (flight HUD): on a narrow phone landscape (640-699px wide) the place/speed pair (left edge 126px, 190px wide in
   style.css) reaches into the centre 30% box. Keep it to the 94px that clear it and stack label over speed (a single
   column; the label ellipsises as before). Same selector as style.css so source order decides. */
@media(min-width:640px) and (max-width:699px) and (max-height:560px) {
  body.mobile.playing #interface #flight-hud { width:94px;grid-template-columns:minmax(0,1fr);row-gap:0; }
}
/* V3 (online pill): phone landscape has the whole top band free right of the pill; let the longest label
   ("PANAS7 · 12+ EN LÍNEA · INVITA") show in full instead of being cut to "PANAS7 · 12+ EN L…". Portrait keeps the 150px cap. */
@media(max-height:560px) and (min-width:640px) {
  body.mobile #online-count { max-width:260px; }
}
/* V3 (nearby panel): the panel the online pill opens ("Cerca de ti") is a popover over the top-left HUD. While it is open the
   readouts it would cover (place, speed, objective, route card, cash pop) are hidden so their edges do not poke out
   from under it, and the keyboard hint in its footer ("MANTÉN Z") is dropped on touch. Portrait also hides the minimap and wallet
   (the panel covers both); landscape moves the panel right of that column so the minimap, wallet and joystick stay usable. */
body.mobile #online-nearby .onb-f { display:none; }
body.mobile:has(#online-nearby:not([hidden])) :is(.location,#flight-hud,.mi-gain,#flow-hud,#destination,.mi-track,#anchor-label) { visibility:hidden; }
@media(orientation:portrait) { body.mobile:has(#online-nearby:not([hidden])) :is(.map-wrap,.mi-wallet) { visibility:hidden; } }
@media(max-height:560px) and (min-width:640px) {
  body.mobile #online-nearby { left:calc(var(--mobile-left) + 140px)!important;width:min(300px,calc(100vw - var(--mobile-left) - var(--mobile-right) - 266px)); } /* R16: 126 left the panel 10px over the stick (x16-136) */
}
/* Wave 5 live check (landscape phone, police chase): the wanted-stars panel (right:38px, 190px wide) sat over the SALIR/TURBO column. Keep it left of the right-hand button column. */
@media(orientation:landscape) and (max-height:560px) and (min-width:560px) {
  body.mobile.playing .pl-hud { right:calc(var(--mobile-right) + 108px); }
}
/* Minimap -> bottom-left on portrait phones (owner request; landscape keeps the top-left column). It sits on top of the
   joystick, so the top-left HUD column holds only the wallet; the photo button sits beside the map and the torch above it. The map is 98px wide on short portrait phones so its edge stays clear of the character. */
@media(orientation:portrait) {
  body.mobile.playing #interface .map-wrap { top:auto;bottom:calc(var(--mobile-bottom) + 158px); }
  body.mobile.playing #interface .map-wrap>div { position:absolute;right:0;bottom:0;display:block;min-height:0;padding:0;border:0;background:none; }
  body.mobile.playing #interface .map-wrap>div>span#map-location { display:none; }
  body.mobile.playing #map-btn { background:#173947d9;border-radius:12px 0 0 0; }
  body.mobile.playing #minimap { height:78px; }
  /* Photo beside the map; the torch above it. The strip between the stick and the action pad belongs to TRUCO and the weapon button. */
  body.mobile .snap-btn { left:calc(var(--mobile-left) + 134px);bottom:calc(var(--mobile-bottom) + 164px); }
  body.mobile #touch-controls #touch-torch { left:calc(var(--mobile-left) + 12px);bottom:calc(var(--mobile-bottom) + 246px); }
  body.mobile.nv-dark.playing #touch-controls #touch-torch { left:calc(var(--mobile-left) + 12px)!important;bottom:calc(var(--mobile-bottom) + 246px)!important; }
  body.mobile .mi-wallet { top:calc(var(--mobile-top) + 110px); }
  body.mobile .mi-gain { top:calc(var(--mobile-top) + 116px); }
  body.mobile .mi-track { top:calc(var(--mobile-top) + 190px); }
}
@media(orientation:portrait) and (max-height:700px) {
  body.mobile.playing #interface .map-wrap { width:98px; }
  body.mobile.playing #minimap { width:98px;height:68px; }
}

/* R16 (wave 6 layout matrix). Each rule names the measurement that found it (game/scripts/hud-overlap-check.mjs, notch emulated). */
/* Wanted panel (police.js: right:38px, top:74px, 22px state line, 190px bar). Portrait phones: it sat across the pause / more buttons (a notch pushes them to y55-99),
   the tool strip, the area label and the speed readout. Park a compact version (stars 26px, one state line, no flavour line) under that stack on the right edge.
   Landscape phones: it covered the HABLAR button column (36x36 px at 844x390): tuck it up under the top row and drop the flavour line there too. */
body.mobile.playing .pl-stars { font-size:26px;gap:3px; }
body.mobile.playing .pl-state { font-size:17px;margin-top:2px; }
body.mobile.playing .pl-sub { display:none; }
body.mobile.playing .pl-bar { width:104px;margin-top:4px; }
@media(orientation:portrait) { body.mobile.playing .pl-hud { top:calc(var(--mobile-top) + 186px);right:calc(var(--mobile-right) + 6px); } }
@media(orientation:landscape) and (max-height:560px) { body.mobile.playing .pl-hud { top:calc(var(--mobile-top) + 58px); } }
/* The map dialog sets its own width / max-height by id (style.css: calc(100vw - 56px), 94vh), so the generic safe-area sizing of "body.mobile dialog" never reached it:
   its close button sat 11 px inside the top inset (390x844 notch) and its left edge / close button inside the landscape notch bands (844x390). */
body.mobile #map-dialog { width:min(1050px,calc(100vw - 2*max(var(--mobile-left),var(--mobile-right)) - 24px));max-height:calc(100dvh - 2*max(var(--mobile-top),var(--mobile-bottom)) - 24px); } /* margin:auto centres it, so the clear band is symmetric */
