/* NETWAR — world.html styles, part 9 of 9: Visual rounds: the chrome reskin that overrides the rules above.
   Moved out of world.html's <style> block unchanged (2026-10-03); the files load in this
   order, which is the old cascade order — a later file still overrides an earlier one. */
/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 1 (see project doc
   claude/main-map-neon-hud-v2.md). Same angular clip-path panel
   language + Chakra Petch headings already used in #safehouse —
   no IDs renamed, no gameplay logic touched, every real data
   field and JS-toggled state class (.on / .on-cooldown / etc.)
   keeps working exactly as before. Purely additive shape + type.
   ============================================================ */

/* ---- Header bar ---- */
#bar {
  background: linear-gradient(180deg, rgba(16,11,30,0.97), #08050f 75%);
  border-bottom: 1px solid rgba(55,213,245,0.28);
  box-shadow: 0 8px 22px -16px rgba(0,0,0,0.9);
}
#bar .t { font-family: 'Chakra Petch', var(--chrome-display); }

/* Faction influence — static angular chips (real per-syndicate Influence %
   from the server), replacing the old scrolling marquee tape. */
#inf-ticker {
  height: auto; min-height: 30px; overflow: visible; border-left: none; padding-left: 0;
}
#inf-ticker .inf-ticker-tag { display: none; }
#inf-ticker .inf-ticker-clip {
  overflow: visible; mask-image: none; -webkit-mask-image: none; height: auto;
  flex-wrap: wrap;
}
#inf-ticker .inf-ticker-track {
  animation: none; width: auto; height: auto;
  display: flex; flex-wrap: wrap; gap: 6px;
}
#inf-ticker .fac-chip {
  position: relative; display: flex; align-items: center; gap: 7px;
  height: 28px; padding: 0 9px 0 7px;
  background: linear-gradient(180deg, rgba(16,11,30,0.95), rgba(8,5,16,0.95));
  border: 1px solid rgba(55,213,245,0.2);
  clip-path: polygon(0 0,100% 0,100% calc(100% - 7px),calc(100% - 7px) 100%,0 100%);
  transition: border-color 0.15s, box-shadow 0.15s;
}
#inf-ticker .fac-chip:hover { border-color: rgba(55,213,245,0.5); }
#inf-ticker .fac-chip .fac-bar {
  width: 3px; height: 16px; flex-shrink: 0; border-radius: 0;
  background: var(--syn-color, var(--chrome-muted)); box-shadow: 0 0 7px var(--syn-color, transparent);
}
#inf-ticker .fac-chip .fac-text { display: flex; flex-direction: column; gap: 1px; line-height: 1; }
#inf-ticker .fac-chip .fac-name {
  font-family: 'Chakra Petch', var(--chrome-display); font-weight: 600; font-size: 10px;
  letter-spacing: 0.14em; color: #dff0f5;
}
#inf-ticker .fac-chip .fac-pct {
  font-size: 9px; letter-spacing: 0.06em; color: var(--chrome-muted);
  font-variant-numeric: tabular-nums;
}
#inf-ticker .fac-chip .fac-lead-badge {
  font-size: 8px; font-weight: 700; letter-spacing: 0.12em; padding: 1px 5px;
  background: rgba(245,163,55,0.18); border: 1px solid rgba(245,163,55,0.55); color: #ffd15c;
}
@media (max-width: 900px) { #inf-ticker .fac-chip .fac-text { display: none; } }

/* Utility buttons + NEURAL LINK + LIVE badge — angular notch, small status LED */
.info-array {
  background: rgba(9,24,34,0.6); border-color: rgba(55,213,245,0.18);
}
.info-array button {
  display: inline-flex; align-items: center; gap: 6px;
}
.info-array button::before {
  content: ''; width: 5px; height: 5px; flex-shrink: 0; background: var(--chrome-muted);
  box-shadow: 0 0 6px var(--chrome-muted);
}
#btn-sound.on::before { background: #37f5a3; box-shadow: 0 0 7px #37f5a3; }
#btn-manual::before, #btn-feedback::before { background: #f5a337; box-shadow: 0 0 7px #f5a337; }
#btn-app::before { background: #37d5f5; box-shadow: 0 0 7px #37d5f5; }
#bar .live {
  display: inline-flex; align-items: center;
  clip-path: polygon(7px 0,100% 0,100% 100%,0 100%,0 7px);
}
#btn-neural-link {
  clip-path: polygon(7px 0,100% 0,100% calc(100% - 7px),calc(100% - 7px) 100%,0 100%,0 7px);
}

/* ---- Action tiles (#toolbar-actions) — angular notch + Chakra Petch label.
   Every per-action color / .on / .on-cooldown / low-nrg rule above is untouched;
   this only adds shape and heading type on top of it. */
#toolbar-actions button {
  clip-path: polygon(0 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) 100%,0 100%);
}
#toolbar-actions .act-btn-label { font-family: 'Chakra Petch', var(--chrome-display); }

/* ---- Round 11: action-tile hover, taken verbatim from the reference's
   command-bar "glitchLift" hover (a brief jittery lift + brightness pop,
   settling 4px higher) — keyframes copied as-is from the .dc.html file.
   Layered on top of every existing per-action hover rule (the ones above
   that add a stronger box-shadow glow, plus the Round 4 .sh-tile-load-btn
   scan-sweep overlay already reused on these same buttons) — this only
   adds the motion/brightness, doesn't replace any of that real-status
   coloring. */
#toolbar-actions button {
  transition: transform 0.14s ease, filter 0.14s ease, box-shadow 0.14s ease;
}
#toolbar-actions button:hover:not(:disabled) {
  filter: brightness(1.22);
  animation: act-btn-glitch-lift 0.42s steps(2) forwards;
}
#toolbar-actions button:active:not(:disabled) {
  transform: translateY(0) scale(0.985);
}
@keyframes act-btn-glitch-lift {
  0% { transform: translateY(0); }
  8% { transform: translate(-3px,-2px) skewX(2deg); filter: brightness(1.5) saturate(1.4); }
  14% { transform: translate(3px,-5px) skewX(-2deg); }
  20% { transform: translate(-1px,-4px); }
  26% { transform: translate(2px,-3px) skewX(1.5deg); filter: brightness(1.35); }
  34%, 100% { transform: translateY(-4px) skewX(0); }
}

/* ---- Round 12: same reference-sourced "glitch hover" family extended to
   every clickable box/chip/card across the whole game, per the user's own
   "every box in the game" answer. Two more keyframe variants copied
   verbatim from the reference (glitchFlat → small chips/buttons/tabs,
   glitchSlide → multi-line cards); the big command-bar tiles already use
   act-btn-glitch-lift (Round 11), reused here for the couple of other
   "big tile" elements (SITREP pod-cards, Safehouse's own action buttons —
   same shared .sh-tile-load-btn component family as the command bar).
   Every rule below only ADDS an `animation`/`transition` property to an
   element's OWN existing hover — none of the real per-element hover
   colors/borders/box-shadows from earlier rounds are touched.
   Deliberately EXCLUDED: elements that already carry their own bespoke
   hover transform (`.sh-deck-card-wrap` variants — already have a real
   translateY lift, would fight this), the deck-swap drop-target indicator
   (`.sh-bay.swap-target` — its box-shadow already means something
   specific, a jitter would read as noise on a drag target), plain text
   links / table rows / tiny opacity-only reveals (`.mo-nav a`, `tbody tr`,
   `.sitrep-ref`, `.hud-toggle`) which aren't really "boxes", and 4 controls
   that already carry their OWN distinct pre-existing glitch animation from
   an earlier round (`#btn-manual`, `#btn-feedback` → `nl-glitch`;
   `#neural-link .nl-close`, `#neural-link .nl-tab` → `nl-glitch`/
   `nl-glitch-text`) — adding a second `animation` would just silently
   replace those, not layer on top, since it's the same CSS property.
   No `transition` additions here either: several of these elements
   (`#btn-neural-link`, `#inf-ticker .fac-chip`, `#hud .event-card`,
   `.sh-shelf`, `.sh-bay`, `#sh-actions button`, `.mo-card`) already have
   their own base `transition` for border-color/background/box-shadow —
   a same-selector `transition` rule here would replace that list wholesale
   instead of extending it, silently breaking their existing smooth
   mouse-out. The trade-off: the new jitter itself still plays in full via
   the `animation`, only the very last instant (transform snapping back to
   rest right as the mouse leaves) isn't eased on these specific elements. */
@keyframes glitch-flat-hover {
  0% { transform: translate(0); }
  12% { transform: translate(-2px,1px) skewX(3deg); filter: brightness(1.45); }
  22% { transform: translate(2px,-1px) skewX(-2deg); }
  32% { transform: translate(-1px,0); }
  40%, 100% { transform: translate(0) skewX(0); }
}
@keyframes glitch-slide-hover {
  0% { transform: translateX(0); }
  10% { transform: translate(-4px,2px) skewX(-3deg); filter: brightness(1.4); }
  20% { transform: translate(6px,-2px) skewX(2deg); }
  30% { transform: translate(1px,1px); }
  38%, 100% { transform: translateX(3px) skewX(0); }
}
@keyframes glitch-nudge-hover {
  0% { transform: translateX(0); }
  10% { transform: translate(6px,-2px) skewX(-3deg); filter: brightness(1.5); }
  18% { transform: translate(-2px,2px) skewX(2deg); }
  26% { transform: translate(5px,-1px); }
  34%, 100% { transform: translateX(4px) skewX(0); }
}

/* -- flat (small chip/button/tab elements) -- */
#inf-ticker .fac-chip:hover,
#btn-support:hover, .btn-sound:hover,
#btn-neural-link:hover,
#hud .hud-season:hover,
#hud .event-card .ev-goto:hover,
#inspect #btn-abandon-sector:hover,
#inspect #btn-backdoor-agree:hover:not(:disabled),
#inspect #btn-backdoor-create:hover,
#feed-wrap .feed-filter:hover, #feed-expand:hover,
#support-overlay .sp-close:hover, #support-overlay .sp-open:hover,
#feedback-overlay .fb-close:hover, #feedback-overlay .fb-send:hover,
#manual-overlay .mo-close:hover, #manual-overlay .mo-card:hover,
#deploy-cancel:hover, #deploy-confirm:hover,
#map-confirm-cancel:hover, #map-confirm-apply:hover:not(:disabled),
.loot-toast-x:hover, .loot-chip-hoverable:hover,
#demo-cta-btn:hover, #demo-cta-restore:hover,
#sh-pane-tabs button:hover:not(.active),
.sh-shelf:hover,
#sh-market-buy:hover:not(:disabled),
.sh-ice-stepper button:hover:not(:disabled),
#sh-defense-save:not(:disabled):hover, #sh-defense-clear:hover,
.sh-filter-group-pills button:hover:not(.active),
.sh-empty-cta button:hover,
#sh-ram-zero .sh-ram-zero-chip:hover,
#sh-templates button:hover,
#sh-confirm-apply:hover, #sh-confirm-cancel:hover,
#sh-deck-stats .sh-stats-head:hover {
  animation: glitch-flat-hover 0.32s steps(2) forwards;
}

/* -- lift (big tile-shaped elements — same family as the command bar) -- */
/* Round 12 added this hover rule but it never fired: #hud is deliberately
   click-through (pointer-events: none, see the comment near [data-gloss]/
   [data-tip] above) and .hud-stat-box was never opted back in, unlike
   .event-card — so the browser's hit-test skips straight through these
   pod-cards to the map underneath and :hover never matches. Same
   no-cursor-implies-not-clickable treatment as [data-gloss]: opted back
   into pointer-events so the hover (and its animation) can register, but
   kept `cursor: default` since these aren't actually clickable, only
   hoverable-for-flair, matching the reference. */
#hud .hud-stat-box { pointer-events: auto; cursor: default; transition: border-color 0.15s ease, background 0.15s ease; }
#hud .hud-stat-box:hover {
  border-color: rgba(69,255,240,0.55);
  background: linear-gradient(160deg, rgba(20,54,68,0.95), rgba(7,22,31,0.95));
}
#hud .hud-stat-box:hover,
#sh-actions button:hover:not(:disabled) {
  animation: act-btn-glitch-lift 0.38s steps(2) forwards;
}

/* -- slide (multi-line cards) -- */
#hud .event-card:hover {
  animation: glitch-slide-hover 0.4s steps(2) forwards;
}

/* -- nudge (list-row items) -- */
.sw-mod:hover {
  animation: glitch-nudge-hover 0.4s steps(2) forwards;
}

#btn-home-core, #btn-safehouse {
  clip-path: polygon(0 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) 100%,0 100%);
}
#btn-home-core .act-btn-label, #btn-safehouse .act-btn-label { font-family: 'Chakra Petch', var(--chrome-display); }

/* ---- Module rack (.sw-mod) — angular notch + blinking mount LED, same
   rack-shelf-LED language as Safehouse's loadout bay ejector. */
.sw-mod {
  position: relative;
  clip-path: polygon(0 0,100% 0,100% calc(100% - 7px),calc(100% - 7px) 100%,0 100%);
}
.sw-mod::after {
  content: ''; position: absolute; top: 6px; right: 7px;
  width: 5px; height: 5px; background: #241a38; box-shadow: inset 0 0 2px rgba(0,0,0,0.6);
}
.sw-mod.on::after {
  background: #37f5a3; box-shadow: 0 0 6px #37f5a3;
  animation: sw-mod-led-blink 1.7s steps(1, end) infinite;
}
@keyframes sw-mod-led-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.sw-mod-name { font-family: 'Chakra Petch', var(--chrome-display); }

/* ---- SITREP panel (#hud) — angular bottom-corner notch + diagonal-stripe
   head band + accent bar, matching the mockup's floating SITREP panel.
   Bottom-only cut keeps the top-right minimize/expand toggle untouched. */
#hud {
  clip-path: polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,12px 100%,0 calc(100% - 12px));
}
#hud .hud-head {
  position: relative; margin: -8px -10px 8px; padding: 9px 12px 9px 16px;
  background: repeating-linear-gradient(135deg, rgba(55,213,245,0.14) 0 8px, rgba(55,213,245,0.04) 8px 16px);
  border-bottom: 1px solid rgba(55,213,245,0.32);
}
#hud .hud-head::before {
  content: ''; position: absolute; left: 0; top: 6px; bottom: 6px; width: 3px;
  background: var(--chrome-cyan); box-shadow: 0 0 8px var(--chrome-cyan);
}
#hud .sitrep { font-family: 'Chakra Petch', var(--chrome-display); font-size: 14px; }

/* ---- TARGET panel (#inspect) — mirrors #hud's treatment. Note: the
   head itself keeps its own amber styling (Round 15, see project doc);
   only the outer corner-notch and title font are shared with #hud. */
#inspect {
  clip-path: polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,12px 100%,0 calc(100% - 12px));
}
#inspect .sitrep-title { font-family: 'Chakra Petch', var(--chrome-display); }

/* ---- Influence standing bar inside SITREP — already-styled, previously
   unused function (influenceStandingHtml) now wired into renderSituationHud(). */
#hud .syn-standing { margin-top: 9px; padding-top: 8px; border-top: 1px solid #2c1a55; }

/* ---- PACKET FEED (#feed-wrap) — angular filter pills + FULL button. */
#feed-wrap .feed-head-title { font-family: 'Chakra Petch', var(--chrome-display); letter-spacing: 0.2em; }
#feed-wrap .feed-filter {
  clip-path: polygon(0 0,100% 0,100% calc(100% - 5px),calc(100% - 5px) 100%,0 100%);
}
#feed-expand {
  clip-path: polygon(0 0,100% 0,100% calc(100% - 6px),calc(100% - 6px) 100%,0 100%);
}

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 2 (see project doc
   claude/main-map-neon-hud-v2.md). Round 1 only added shape +
   type on top of the old dark-violet chrome; this pass matches
   the mockup's actual palette (bright cyan-glass panels instead
   of tinted-violet ones) plus two structural changes the mockup
   specifically shows: SITREP as a grid of boxed stats (not text
   lines) and the action tiles grouped under NAVIGATE/MODE/RECON/
   STRIKE headers. Still additive: no ID renamed, no data-act/
   click wiring touched (verified `ev.target.closest('button')`
   in the delegated handler still finds every button through the
   new wrapper divs), every per-action color/.on/.on-cooldown
   rule from the base stylesheet is untouched underneath this.
   ============================================================ */

/* ---- Brighter cyan-glass palette for the chrome bands ---- */
#bar {
  background: linear-gradient(180deg,#071722 0%,#050f18 70%,rgba(5,15,24,0) 100%);
  border-bottom: 1px solid rgba(0,255,245,0.28);
}
.info-array { background: rgba(9,24,34,0.7); border-color: rgba(0,255,245,0.16); }
#btn-neural-link {
  color: #00201f; border-color: #eafffe;
  background: linear-gradient(180deg,#9dfffa 0%,#00fff5 45%,#00c6c2 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.85), 0 0 20px rgba(0,255,245,0.55);
  text-shadow: none;
}
#btn-neural-link::before { background: #00201f; border-color: #00201f; box-shadow: none; }
#btn-neural-link:hover, #btn-neural-link:focus-visible {
  color: #00201f; border-color: #eafffe;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 0 28px rgba(0,255,245,0.75);
}
#bar .live {
  color: #04180f; border-color: transparent;
  background: linear-gradient(180deg,#4dff9f,#1ea86a);
  box-shadow: 0 0 16px -4px rgba(43,255,142,0.75);
}
/* No uplink / connecting: the same solid badge as LIVE STREAM, in alert red. */
#bar .live.off {
  color: #1f0307; border-color: transparent;
  background: linear-gradient(180deg, #ff7b8a, #d0223c);
  box-shadow: 0 0 16px -4px rgba(255,60,80,0.8);
}
#bar .live.off::before { animation: blink 1.6s infinite; }
#hud, #inspect {
  background: linear-gradient(180deg, rgba(6,24,34,0.94), rgba(4,14,22,0.94));
  border-color: rgba(0,255,245,0.3);
  box-shadow: 0 0 40px -14px rgba(0,0,0,0.9), inset 0 0 40px -30px rgba(0,255,245,0.3);
}
#hud .hud-head {
  background: repeating-linear-gradient(135deg, rgba(0,255,245,0.16) 0 8px, rgba(0,255,245,0.05) 8px 16px);
}
#hud .hud-head::before {
  background: #00fff5; box-shadow: 0 0 10px #00fff5;
}
#toolbar {
  background: linear-gradient(180deg, rgba(6,22,31,0.95), rgba(3,11,18,0.97));
  border-top: 1px solid rgba(0,255,245,0.28);
}
#stats, #software-zone { border-right-color: rgba(0,255,245,0.14); }
.sw-mod { background: rgba(8,22,30,0.75); border-color: rgba(0,255,245,0.16); }
.sw-mod:hover { border-color: rgba(0,255,245,0.4); }
#toolbar-actions button { background: rgba(6,16,22,0.9); }
#feed-wrap { background: rgba(3,11,18,0.92); border-top-color: rgba(0,255,245,0.22); }
#feed-wrap .feed-filter { background: rgba(6,16,22,0.85); border-color: rgba(0,255,245,0.14); }
#feed-wrap .feed-filter:hover { border-color: #00fff5; color: #aefffb; }

/* ---- SITREP stat-box grid — real NETWORK/SECTORS/SHIELD/BREACH/CORE/HEAT,
   replacing the old plain-text lines. Color classes (.ok/.warn/.alert/.dim)
   come from the shared #hud rules already defined above — .hsb-value itself
   deliberately carries no color so it never out-specifies those. */
#hud .hud-stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; margin-bottom: 2px; }
#hud .hud-stat-box {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
  padding: 5px 7px 6px; color: var(--chrome-text);
  background: rgba(4,14,22,0.55); border: 1px solid rgba(0,255,245,0.16);
}
#hud .hsb-label {
  font-size: 8px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--chrome-muted);
}
#hud .hsb-value {
  font-family: 'Chakra Petch', var(--chrome-display); font-weight: 700; font-size: 14px;
  line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#hud .hsb-hint {
  font-size: 8px; letter-spacing: 0.02em; color: var(--chrome-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 1400px) {
  #hud .hud-stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Action tiles grouped under NAVIGATE / MODE / RECON / STRIKE headers,
   matching the mockup's cb-actions layout. */
#toolbar-actions { align-items: flex-start; }
#toolbar-actions .act-group {
  display: flex; flex-direction: column; gap: 3px;
  padding: 4px 6px 5px; background: rgba(4,14,22,0.4);
  border: 1px solid rgba(0,255,245,0.12);
}
#toolbar-actions .act-group-label {
  font-family: 'Chakra Petch', var(--chrome-display); font-size: 8px; font-weight: 700;
  letter-spacing: 0.2em; color: rgba(168,198,207,0.55); padding-left: 1px;
}
#toolbar-actions .act-row { display: flex; gap: 5px; }
@media (max-width: 900px) { #toolbar-actions .act-group-label { display: none; } }

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 3 (see project doc
   claude/main-map-neon-hud-v2.md). Header brand mark, RAM meter
   made prominent (tick texture, same real free/overhead/breach
   data — no new field), a new real NRG bar (energy/energy_max,
   both already sent to the client), and MODULES restyled from
   small pill cards to full-width AVAILABLE/SELECTED rows. No
   markup touched for RAM; `.sw-mod` badge text comes from CSS
   ::before content keyed off the existing `.on` class — no
   change to buildSoftwarePicker()'s DOM at all.
   ============================================================ */

/* ---- Header brand mark ---- */
.brand-mark {
  position: relative; flex-shrink: 0; width: 26px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, #00fff5, #0a4048);
  clip-path: polygon(50% 0,100% 26%,100% 74%,50% 100%,0 74%,0 26%);
}
.brand-mark::after {
  content: 'N'; position: absolute; inset: 2px;
  background: #04121a; clip-path: polygon(50% 0,100% 26%,100% 74%,50% 100%,0 74%,0 26%);
  display: flex; align-items: center; justify-content: center;
  color: #00fff5; font-family: 'Chakra Petch', var(--chrome-display); font-weight: 700; font-size: 13px;
}

/* ---- RAM meter — same real free/overhead/breach data, just more prominent
   and textured with a tick overlay, matching the mockup's vitals bars. */
#ram-meter-wrap { position: relative; max-width: min(210px, 100%); }
#ram-meter { height: 10px; border-color: rgba(0,255,245,0.22); background: #050d12; }
/* Round 10 replaces the old scanline ::after overlay with a coarser
   repeating-chunk fill (see below) that matches the HEAT bar's own
   pip texture, so the finer overlay was retired to avoid a moiré clash. */

/* ---- NRG bar — real energy/energy_max, wired in updateStats(). ---- */
#nrg-meter-wrap { position: relative; max-width: min(210px, 100%); margin-top: 5px; }
#nrg-meter {
  height: 8px; border: 1px solid rgba(0,255,245,0.2); background: #050d12; overflow: hidden;
}
#nrg-meter-fill {
  height: 100%; background: linear-gradient(90deg, #0a5a3a, #37f5a3 65%, #b6ffdf);
  transition: width 0.25s ease; min-width: 0;
}
/* Round 10 overrides #nrg-meter-fill to a repeating-chunk pattern further below. */
#nrg-meter-label {
  font-size: 9px; color: var(--chrome-muted); letter-spacing: 0.08em; margin-top: 2px;
}

/* ---- MODULES — full-width AVAILABLE/SELECTED rows instead of small pill
   cards, matching the mockup's cb-modules list. Badge text is pure CSS
   (::before content keyed off the .on class JS already toggles) — no DOM
   change needed in buildSoftwarePicker(). */
#software-picker { flex-direction: column; gap: 3px; width: 100%; max-width: 230px; }
.sw-mod {
  flex-direction: row; align-items: center; justify-content: flex-start;
  gap: 8px; min-width: 0; width: 100%; padding: 4px 8px 4px 18px; position: relative;
}
.sw-mod::after { top: 50%; left: 6px; right: auto; transform: translateY(-50%); }
.sw-mod-name { min-width: 62px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-mod-ram { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-mod::before {
  content: 'AVAILABLE'; flex-shrink: 0;
  font-size: 7px; font-weight: 700; letter-spacing: 0.1em;
  padding: 1px 5px; background: rgba(0,255,245,0.08); border: 1px solid rgba(0,255,245,0.25);
  color: rgba(168,198,207,0.7);
}
.sw-mod.on::before {
  content: 'SELECTED'; background: rgba(55,245,163,0.18); border-color: #37f5a3; color: #37f5a3;
}
@media (max-width: 1100px) {
  #software-picker { max-width: 190px; }
  .sw-mod::before { display: none; }
}

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 4 (see project doc
   claude/main-map-neon-hud-v2.md). Two additive polish items:
   (1) reuse Safehouse's existing globally-scoped "loading scan"
   hover effect (.sh-tile-load-btn / .sh-tile-load) on all 9
   main-map action tiles — zero new CSS/JS, pure markup reuse,
   the driving IIFE already queries document-wide; (2) a header
   brand sub-line under the NETWAR wordmark showing the same real
   season/rank/points/ends fields already used by the SITREP
   season chip (seasonHudChipHtml), just mirrored into the header
   the way the mockup shows a sub-line under its brand mark.
   ============================================================ */

/* ---- Brand block — wraps the mark + title row (Round 7 removed the
   sub-line entirely: the user's originally-approved real-data preview
   never had one under the wordmark — "Отдолу няма такъв надпис като при
   нас, махни го" — this was an unrequested Round 4 embellishment). ---- */
.brand-block {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0; min-width: 0;
}
.brand-text {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 5 (see project doc
   claude/main-map-neon-hud-v2.md). User feedback after Round 4:
   still not matching the design — this pass pushes every
   remaining region as close to the mockup as real data allows,
   in one comprehensive pass rather than another small addition.
   Still fully additive: no ID renamed, no click/data-act wiring
   touched, every existing status color rule (.ok/.warn/.alert/
   .dim, per-action colors, event-card type colors) is preserved
   — this only adds shape, accent, and typography on top. Where
   the mockup's color choice conflicts with this app's own
   established semantic color language (e.g. CAPTURE reads as
   the app's universal "success" green everywhere else in SITREP,
   not the mockup's arbitrary amber), the app's own convention
   wins — visual fidelity never overrides real meaning.
   ============================================================ */

/* ---- Header utility chips — single angular notch on the whole joined
   strip (kept as one strip, not split into gapped chips, since the
   shared-border layout is an existing, deliberate compact design). ---- */
.info-array {
  clip-path: polygon(6px 0,100% 0,100% calc(100% - 6px),calc(100% - 6px) 100%,0 100%,0 6px);
}

/* ---- OPERATOR line — same real name/shield/sectors/deck text that was
   already in #st-name, just promoted to a header row above the vitals
   (flex `order`, no markup/JS change) with a Chakra Petch label, matching
   the mockup's "OPERATOR  ELI · 1 SECTOR · DECK 16/16GB" row. ---- */
#st-name {
  order: -1; display: block; margin-bottom: 5px; padding-bottom: 5px;
  border-bottom: 1px solid rgba(0,255,245,0.14);
  font-size: 10px; letter-spacing: 0.1em; color: #cfe8ee;
}
#st-name::before {
  content: attr(data-label); display: inline-block; margin-right: 8px;
  font-family: 'Chakra Petch', var(--chrome-display); font-weight: 700;
  font-size: 10px; letter-spacing: 0.22em; color: #6ffff4;
  text-shadow: 0 0 10px rgba(0,255,245,0.4);
}

/* ---- SITREP stat boxes → true pod-cards: angular notch + a left accent
   bar colored by the same .ok/.warn/.alert/.dim class already on the real
   value (via :has(), already used elsewhere in this stylesheet at
   #inspect-dock:has(#inspect.show)) — no new data, just reads the
   existing status class from the outside. ---- */
#hud .hud-stat-box {
  position: relative;
  padding: 5px 7px 6px 10px;
  clip-path: polygon(0 0,calc(100% - 8px) 0,100% 8px,100% 100%,0 100%);
}
#hud .hud-stat-box::before {
  content: ''; position: absolute; left: 0; top: 5px; bottom: 5px; width: 2px;
  background: var(--chrome-cyan); opacity: 0.65;
}
#hud .hud-stat-box:has(.hsb-value.ok)::before { background: var(--chrome-ok); opacity: 1; box-shadow: 0 0 6px var(--chrome-ok); }
#hud .hud-stat-box:has(.hsb-value.warn)::before { background: var(--chrome-warn); opacity: 1; box-shadow: 0 0 6px var(--chrome-warn); }
#hud .hud-stat-box:has(.hsb-value.alert)::before { background: var(--chrome-alert); opacity: 1; box-shadow: 0 0 6px var(--chrome-alert); }
#hud .hud-stat-box:has(.hsb-value.dim)::before { background: var(--chrome-muted); opacity: 0.4; }
/* Round 8j: accent bars for the new gold-core/gold-heat text colors —
   opacity 0.7 matches the reference's own bar opacity for these two
   pod-cards exactly (same lines cited above), rather than reusing the
   1/0.4 opacities the real status colors use. */
#hud .hud-stat-box:has(.hsb-value.gold-core)::before { background: #ffd15c; opacity: 0.7; box-shadow: 0 0 6px #ffd15c; }
#hud .hud-stat-box:has(.hsb-value.gold-heat)::before { background: #ffb01f; opacity: 0.7; box-shadow: 0 0 6px #ffb01f; }

/* ---- TARGET panel section headers (REGISTRY / MISSION COSTS / TACTICAL
   INTEL / etc.) — Chakra Petch to match every other heading in the reskin.
   Single-property override; the tier color-coding (DECISION red accent,
   REFERENCE dimming) from the base stylesheet is untouched. ---- */
#inspect .sitrep-section-title { font-family: 'Chakra Petch', var(--chrome-display); }

/* ---- Active-ops event cards → op-cards: angular bottom-left/top-right
   notch, Chakra Petch title, and a small colored "jump" chip (same real
   goto text, now a pill instead of a plain link) tinted per event type
   using each type's own existing border-left color. ---- */
#hud .event-card {
  position: relative;
  clip-path: polygon(0 0,calc(100% - 12px) 0,100% 12px,100% 100%,12px 100%,0 calc(100% - 12px));
}
#hud .event-card .ev-title { font-family: 'Chakra Petch', var(--chrome-display); }
#hud .event-card .ev-goto {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 7px;
  padding: 3px 8px; font-family: 'Chakra Petch', var(--chrome-display); font-weight: 600;
  font-size: 9px; letter-spacing: 0.14em; color: #04121a;
  background: var(--chrome-cyan);
  clip-path: polygon(5px 0,100% 0,100% calc(100% - 5px),calc(100% - 5px) 100%,0 100%,0 5px);
}
/* Round 8k: user wants the JUMP button itself to have a hover state, not
   just ride along with the whole card's hover. The reference file gives
   it its own dedicated `.jump-btn:hover` treatment (brightness bump +
   wider letter-spacing + a colored glow), separate from the card's own
   `.op-card:hover` — see netwar-map-hud-real-preview.html ~L96. Matched
   that here (using our real --ev-color instead of its --jb, so the glow
   still tracks each event's real color) rather than the previous
   card-hover-driven brightness-only rule. */
#hud .event-card .ev-goto:hover {
  filter: brightness(1.2); letter-spacing: 0.24em;
  box-shadow: 0 0 22px -4px var(--ev-color, #45fff0);
}
/* Per-kind .ev-goto background colors used to be hardcoded here too (6
   lines) — same Round 8 --ev-color refactor as the border-left/hover
   colors above; see that comment. backdoor keeps its own rule. */
#hud .event-card.backdoor .ev-goto { background: #f5c842; }

/* ---- Module rack — small ring "disk" icon before each module's name
   (decorative only, no new data), spinning + glowing on the mounted
   (.on) module the same way the mockup's resident program disk spins.
   `.sw-mod::before`/`::after` are already used (AVAILABLE/SELECTED badge,
   mount LED) so this lives on `.sw-mod-name::before` instead. ---- */
.sw-mod-name::before {
  content: ''; display: inline-block; width: 9px; height: 9px; margin-right: 6px;
  border: 2px solid currentColor; border-radius: 50%; opacity: 0.5; vertical-align: middle;
}
.sw-mod.on .sw-mod-name::before {
  border-color: #37f5a3; opacity: 1; box-shadow: 0 0 6px #37f5a3;
  animation: sw-disk-spin 3.2s linear infinite;
}
@keyframes sw-disk-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* ---- CAPTURE/RAID — stronger always-on background tint so the STRIKE
   group carries real visual weight at rest, matching the mockup's bold
   filled tiles, instead of only coloring on hover/.on. Hue stays this
   app's own (CAPTURE green = the same "success" color SITREP already
   uses for a ready capture verdict; RAID magenta, unchanged) — only the
   intensity changes. `.on-cooldown`'s `!important` overrides still win. */
#toolbar-actions button[data-act="capture"] {
  background: linear-gradient(180deg, rgba(55,245,163,0.16), rgba(10,40,28,0.9));
}
#toolbar-actions button[data-act="raid"] {
  background: linear-gradient(180deg, rgba(255,43,214,0.22), rgba(60,10,42,0.9));
}

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 6 (see project doc
   claude/main-map-neon-hud-v2.md). User: "доста неща не ми
   харесват но искам да завършиш всичките си стъпки преди аз да
   се намеся" — finishing the concrete gaps already identified
   from the Round 5 screenshot review before handing back for
   targeted feedback. CSS-only again: no markup, no data-act/
   click wiring, no JS touched.
   ============================================================ */

/* ---- Action tiles → tall cards instead of flat compact rows, matching
   the mockup's icon-badge-top / title-bottom layout. `clamp()` (not a
   fixed px value) so this scales down on its own at narrow widths
   without needing to re-fight every old breakpoint's min-height rule —
   same reasoning as the earlier `max-width: min(210px, 100%)` fix for
   the RAM/NRG meters. No hotkey letter chip: this game has no real
   keyboard shortcuts bound to these actions (checked — only Escape
   exists, for dialogs), so the mockup's corner hotkey tag would be
   fabricated data and is left out entirely. */
#toolbar-actions button { min-height: clamp(58px, 6.5vw, 90px); }
#toolbar-actions .act-btn-inner {
  justify-content: space-between; align-items: flex-start;
  min-height: clamp(58px, 6.5vw, 90px);
}
#toolbar-actions .act-btn-row {
  flex-direction: column; align-items: flex-start; gap: 6px; width: 100%;
}
#toolbar-actions .act-btn-icon {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex-shrink: 0; box-sizing: border-box;
  border: 1px solid currentColor; opacity: 1; font-size: 12px;
}
#toolbar-actions .act-btn-label { font-size: 12px; font-family: 'Chakra Petch', var(--chrome-display); }
#toolbar-actions .act-btn-meta { text-align: left; }
@media (max-width: 900px) {
  /* Narrow layout already stacks the toolbar into one column (existing
     900px rule) — the tall-card look is a wide-screen flourish; keep
     the compact row here so small screens don't get overly tall tiles. */
  #toolbar-actions button { min-height: 44px; }
  #toolbar-actions .act-btn-inner { min-height: 44px; justify-content: center; align-items: center; }
  #toolbar-actions .act-btn-row { flex-direction: row; align-items: center; }
  #toolbar-actions .act-btn-icon { width: auto; height: auto; border: none; font-size: 11px; }
  #toolbar-actions .act-btn-meta { text-align: center; }
}

/* ---- SITREP pod-card accent bar — bolder so the per-status color
   reads clearly at a glance (was easy to miss at 2px/0.65 opacity). */
#hud .hud-stat-box::before { width: 3px; opacity: 0.8; }
#hud .hud-stat-box:has(.hsb-value.dim)::before { opacity: 0.45; }

/* ---- PACKET FEED — a small colored tag badge per line (SYS/OK/WARN/
   ERR/DUEL), matching the mockup's tag chips. The category was already
   real (the same `cls` the filter buttons already group by); this only
   labels it visually — no new data, no JS/paintFeedLine() change. */
#feed > div { position: relative; padding-left: 42px; }
#feed > div::before {
  content: 'SYS'; position: absolute; left: 0; top: 1px;
  font-family: 'Chakra Petch', var(--chrome-display); font-weight: 700;
  font-size: 8px; letter-spacing: 0.1em; padding: 1px 4px;
  color: #9a90c0; background: rgba(106,96,136,0.16); border: 1px solid rgba(106,96,136,0.45);
}
#feed > div.ok::before {
  content: 'OK'; color: var(--chrome-ok);
  background: rgba(55,245,163,0.14); border-color: rgba(55,245,163,0.5);
}
#feed > div.warn::before {
  content: 'WARN'; color: var(--chrome-warn);
  background: rgba(245,163,55,0.14); border-color: rgba(245,163,55,0.5);
}
#feed > div.err::before {
  content: 'ERR'; color: var(--chrome-alert);
  background: rgba(245,88,88,0.14); border-color: rgba(245,88,88,0.5);
}
#feed > div.battle::before {
  content: 'DUEL'; color: var(--chrome-cyan);
  background: rgba(55,213,245,0.14); border-color: rgba(55,213,245,0.5);
}
/* The time each line arrived (packet feed review 2026-09-29). */
#feed .feed-t { margin-right: 6px; color: var(--chrome-muted); opacity: 0.75; font-variant-numeric: tabular-nums; }

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 7 (see project doc
   claude/main-map-neon-hud-v2.md). User: "Да започнем с header-a...
   Не си измисляй, а виж в HTML който ти пратих всички стойности" —
   header-only pass, values taken directly from the user's own
   previously-approved real-data preview file
   (netwar-map-hud-real-preview.html), not the generic mockup used
   for Rounds 1-6. Still CSS-only except three small, safe changes:
   (1) markup — drop the unrequested Round 4 brand sub-line, split
   the title into 3 sibling spans (.t / .beta-mark / .rt-tag) instead
   of 2 nested ones; (2) world.js — delete the brand-subline
   population block that fed the removed span; (3) syndicate.js —
   add a 4th STATE chip (stateChipHtml()), using the real
   STATE_MAP_COLOR constant already defined for map-fill, not an
   invented color. No click/data-act wiring touched anywhere. */

/* ---- #bar — wider, matching .hud-header's 10px/22px + 14px/20px gap.
   clamp() (not a fixed value) so this still degrades toward the old
   narrow-width padding/gap on its own, same reasoning as the Round 3/6
   clamp fixes — an unconditional rule placed after the old @media
   (max-width:1400px) #bar rule always wins once that media condition
   is true, so a fixed value here would silently undo the narrow-screen
   compaction; clamp keeps this rule graceful at every width instead. */
#bar {
  padding: clamp(7px, 0.7vw, 10px) clamp(12px, 1.6vw, 22px);
  gap: clamp(10px, 1.2vw, 20px);
}

/* ---- Brand block — divider + row gap matching .hdr-brand exactly. ---- */
.brand-block {
  gap: 14px; padding-right: clamp(12px, 1.8vw, 22px);
  border-right: 1px solid rgba(0,255,245,0.16);
}
/* Title row is now a single line (NETWAR / BETA / // RUNTIME siblings) —
   the subline column layout is gone with the subline itself. */
.brand-text {
  flex-direction: row; align-items: baseline; gap: 8px;
}

/* ---- Brand mark — 34x38 outer / 4px-inset 26x30 inner, matching the
   reference exactly (was 26x28 / 2px-inset, and the wrong gradient
   end-color #0a4048 instead of the reference's #16626b). ---- */
.brand-mark {
  width: 34px; height: 38px;
  background: linear-gradient(160deg, #00fff5, #16626b);
}
.brand-mark::after {
  inset: 4px; font-size: 15px;
}

/* ---- Title — clamp so it can reach the reference's 22px on wide
   screens while still shrinking toward the old 12px narrow-width floor
   on its own (same clamp-over-fixed-value reasoning as #bar above: this
   rule sits after the old @media (max-width:1400px)/(max-width:1100px)
   #bar .t rules and would otherwise always beat them once narrow). */
#bar .t {
  font-size: clamp(12px, 1.1vw, 22px);
}

/* ---- BETA badge — full pink chip (was plain muted superscript text:
   no background/border/clip-path at all, which is why it read as an
   afterthought rather than the reference's actual badge). ---- */
.beta-mark {
  letter-spacing: 0.22em; opacity: 1; margin-left: 0; vertical-align: baseline;
  padding: 2px 6px; color: #ff86d4;
  background: rgba(255,47,174,0.16); border: 1px solid rgba(255,47,174,0.5);
  clip-path: polygon(0 0,100% 0,100% 60%,calc(100% - 5px) 100%,0 100%);
}

/* ---- "// RUNTIME" — now its own sibling span (was glued onto .t's text
   node with no space and no independent styling of its own). ---- */
.rt-tag {
  font-family: 'Chakra Petch', var(--chrome-display); font-weight: 600;
  font-size: 13px; letter-spacing: 0.2em; color: #00fff5;
  white-space: nowrap;
}

/* ---- Faction chips — upscaled to the reference's real dimensions
   (was 28px/3px-bar/10px-name, reference is 40px/4px-bar/12px-name).
   Real syndicate hue values (SYNDICATES.*.color / STATE_MAP_COLOR) are
   already wired via the --syn-color custom property in facChipHtml()/
   stateChipHtml() — only sizing changes here. */
#inf-ticker .fac-chip {
  height: 40px; padding: 0 14px 0 10px; gap: 10px;
  background: linear-gradient(180deg, rgba(14,34,46,0.95), rgba(7,20,29,0.95));
  border-color: rgba(0,255,245,0.18);
  clip-path: polygon(0 0,100% 0,100% calc(100% - 9px),calc(100% - 9px) 100%,0 100%);
}
#inf-ticker .fac-chip:hover { border-color: rgba(0,255,245,0.6); box-shadow: 0 6px 18px -8px rgba(0,255,245,0.6); }
#inf-ticker .fac-chip .fac-bar { width: 4px; height: 24px; }
#inf-ticker .fac-chip .fac-name { font-size: 12px; }

/* ---- Round 7b had added a per-chip tinted border + box glow here,
   reading the earlier "виж как имат glow като неон" note as "every box
   needs its own colored glow". The user's follow-up screenshots (a
   freshly re-attached copy of netwar-map-hud-real-preview.html side by
   side with the live client) corrected that: every chip's background
   AND border are meant to be identical — `background:
   linear-gradient(180deg,rgba(14,34,46,.95),rgba(7,20,29,.95))`,
   `border:1px solid rgba(0,255,245,.18)`, same for all 4 — only the
   left accent bar (`.fac-bar`, untouched, already real per-syndicate
   color + its own glow) is meant to differ. Reverted the per-chip
   border/box tint entirely rather than re-guessing a lighter version of
   it — the reference has no box-level glow on the base chip at all,
   only a uniform cyan `:hover` state that was already correct before
   Round 7b touched this. */

/* ---- SOUND/MANUAL/FEEDBACK/SUPPORT — un-joined into individually
   gapped, fully-bordered chips (was one seamless strip with only a
   hairline divider between buttons — "бутоните ... са ясни има
   пространство между тях"). Each button's own label/color/LED-dot or
   caret ::before is untouched; #bar .info-array button (1 id + 1 class
   + 1 type) outranks each button's bare-ID base rule (1 id + 0 + 0),
   so the border/background/clip-path below applies cleanly on top. */
.info-array {
  gap: 8px; background: transparent; border: none; box-shadow: none;
}
#bar .info-array button {
  border: 1px solid rgba(0,255,245,0.14) !important;
  background: rgba(9,24,34,0.7);
  clip-path: polygon(6px 0,100% 0,100% calc(100% - 6px),calc(100% - 6px) 100%,0 100%,0 6px);
}

/* ---- NEURAL LINK — real root cause found: the font/weight fix above
   (Chakra Petch 700/12px) wasn't the actual problem. This button has
   always carried `animation: nl-hdd-tick 4.6s steps(1,end) infinite`
   (a pre-existing "HDD activity LED flicker" flavor detail), and that
   keyframe animation drives `color`/`text-shadow` directly — it was
   overriding the static #00201f-on-bright-gradient color from Round 2
   for nearly the whole 4.6s loop, cycling the label through cyan
   (#37d5f5, low-contrast against this button's own cyan gradient fill)
   and brief near-black flashes instead. That's the actual "black font,
   can't read it" the user kept seeing — not the deliberate dark base
   color itself. Disabling the flicker here (keeping it defined/unused
   in case a non-reskinned caller still wants it) fixes it outright. */
#btn-neural-link {
  font-family: 'Chakra Petch', var(--chrome-display);
  font-weight: 700; font-size: 12px; letter-spacing: 0.2em;
  padding: 7px 16px;
  animation: none;
  color: #00201f;
  text-shadow: 0 0 10px rgba(255,255,255,0.55);
}

/* ---- LIVE STREAM — same missing-type-treatment issue as NEURAL LINK
   above; color/background were already correct (Round 2). ---- */
#bar .live {
  font-family: 'Chakra Petch', var(--chrome-display);
  font-weight: 700; font-size: 12px; letter-spacing: 0.2em;
  padding: 7px 14px 7px 16px;
}

/* ---- NEURAL LINK "HDD activity" blink — restored, the reference-accurate
   way. User noticed it was gone after the animation:none fix above and
   asked where it went. Turns out the pre-existing `nl-hdd-tick` animation
   (the one that had to be disabled — it drove the label's own text color
   and was the real legibility bug) was never what the reference actually
   does for this effect: the reference's HDD blink is a small square LED
   dot before the text and a scrolling "data cable" stripe after it, both
   only ever animating opacity/background-position via `hddIdle`/
   `dataStream` — never the label text's color. Reproducing that exactly
   (values straight from netwar-map-hud-real-preview.html) gets the blink
   back with zero risk to legibility, since it never touches `color`. */
@keyframes hddIdle {
  0%,10% { opacity: 0.28; } 11% { opacity: 1; } 12% { opacity: 0.28; } 13.5% { opacity: 1; } 15% { opacity: 0.28; }
  16% { opacity: 1; } 18% { opacity: 0.28; } 19% { opacity: 1; } 20.5% { opacity: 0.28; }
  21%,54% { opacity: 0.28; } 55% { opacity: 1; } 56% { opacity: 0.28; } 57% { opacity: 1; } 59% { opacity: 0.28; }
  60.5% { opacity: 1; } 62% { opacity: 0.28; } 63%,100% { opacity: 0.28; }
}
@keyframes dataStream {
  0% { background-position: 0 0; } 100% { background-position: 26px 0; }
}
#btn-neural-link::before {
  box-shadow: 0 0 10px rgba(0,32,31,0.9);
  animation: hddIdle 9s steps(1) infinite;
}
#btn-neural-link:not(.has-inbox)::after {
  content: '';
  display: inline-block; width: 22px; height: 12px; margin-left: 7px; vertical-align: middle;
  background-image: repeating-linear-gradient(90deg, rgba(0,32,31,0.85) 0 2px, transparent 2px 6px);
  animation: dataStream 0.55s linear infinite, hddIdle 9s steps(1) infinite;
}
/* NEURAL LINK button in the drawer's own colours (2026-09): pink-magenta →
   violet fill, dark violet label / LED / data stripe, pink glow — so the button
   and the drawer it opens read as one thing, apart from the cyan HUD chrome. */
#btn-neural-link {
  color: #1a0628; border-color: #ffd6f6;
  background: linear-gradient(180deg, #ffb8f0 0%, #ff4fd8 48%, #b04ce0 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 0 20px rgba(255,79,216,0.55);
  text-shadow: 0 0 8px rgba(255,255,255,0.45);
}
#btn-neural-link::before { background: #1a0628; border-color: #1a0628; box-shadow: 0 0 10px rgba(26,6,40,0.9); }
#btn-neural-link:not(.has-inbox)::after {
  background-image: repeating-linear-gradient(90deg, rgba(26,6,40,0.85) 0 2px, transparent 2px 6px);
}
#btn-neural-link:hover, #btn-neural-link:focus-visible {
  color: #1a0628; border-color: #fff0fc;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 0 28px rgba(255,79,216,0.8);
}
/* open: the drawer is showing — lilac rim + a slow breathing glow, label stays dark */
#btn-neural-link.on {
  color: #1a0628; border-color: #d77bff;
  background: linear-gradient(180deg, #f0c4ff 0%, #d77bff 48%, #8f3fd0 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 0 24px rgba(215,123,255,0.7);
}

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 8 (see project doc
   claude/main-map-neon-hud-v2.md). User: "добре сега да видим какво
   се случва с десният sitrep , почти нищо общо нямат... Вземи
   всичко което ти трябва от HTML-a. Има един ред в момента MAP -
   syndicate - него го махаме не ни трябва горе си ги имаме във
   header-a." — full SITREP panel pass, values taken directly from
   the user's own real-data preview file
   (netwar-map-hud-real-preview.html). Two JS removals per the
   explicit instruction: the "MAP <syndicate legend>" row
   (syndicateMapLegendHtml, now redundant with the header's faction
   chips) and, as a judgment call flagged in chat, the "◈ INFLUENCE ·
   UTC DAY" bar (influenceStandingHtml) — same redundancy, just not
   explicitly named. Every real per-status/per-kind color already in
   this codebase (HEAT/SHIELD/BREACH .ok/.warn/.alert/.dim, each
   EVENT_UI.<kind>.color) is kept as-is rather than switched to the
   reference's flat illustrative hues — same precedent as Round 1's
   CAPTURE color and the EVENT_UI colors noted in the project doc. */

/* ---- SITREP head band — 46px tall, wider 9x20 glow tab (was a thin
   3px accent strip), 17px title (was 14px). Round 8 kept the real
   name/badges/subtitle here instead of the reference's decorative
   "./sitrep --home eli" prompt; Round 8e reversed that call per an
   explicit screenshot + instruction to match the reference exactly —
   see the .sitrep-prompt rule below and the world.js comment on
   renderSituationHud()'s opPrompt. */
#hud .hud-head { min-height: 46px; padding: 0 16px 0 25px; gap: 12px; }
#hud .hud-head::before { top: 13px; bottom: 13px; width: 9px; box-shadow: 0 0 12px var(--chrome-cyan); }
#hud .sitrep { font-size: 17px; }
/* Round 8e: "./sitrep --home <real operator name>" prompt line, replacing
   the WARLORD/shield/PATRON badges that used to sit here — same style as
   the reference's own subtitle. */
#hud .sitrep-prompt { font-size: 11px; letter-spacing: 0.08em; color: #4dff9f; }
/* Round 8f: glow tab moved inward — was flush at the panel's left edge
   (left:0, a leftover from the original Round 1 thin-accent-bar version);
   the reference sits it 16px in, as a flex child inside the head's own
   16px padding rather than an edge-flush absolute bar. Text padding-left
   bumped to clear the tab's new position (16px + 9px width + ~12px gap). */
#hud .hud-head::before { left: 16px; }
#hud .hud-head { padding-left: 37px; }

/* ---- SITREP pod-cards — richer background gradient + 19px value
   (was 14px) + wider label/hint letter-spacing, matching the
   reference's pod-card exactly. The per-status accent-bar coloring
   (.ok/.warn/.alert/.dim, from Round 5/6) is real live data and is
   kept instead of the reference's flat per-box hue scheme. */
#hud .hud-stat-box {
  padding: 10px 11px 10px 13px; gap: 6px;
  background: linear-gradient(160deg, rgba(12,34,45,0.9), rgba(5,17,25,0.9));
  border-color: rgba(0,255,245,0.16);
}
#hud .hsb-label { font-size: 9px; letter-spacing: 0.2em; color: #8fb3bd; }
#hud .hsb-value { font-size: 19px; letter-spacing: 0.06em; text-shadow: 0 0 14px rgba(0,255,245,0.35); }
#hud .hsb-hint { font-size: 9px; letter-spacing: 0.12em; color: #8fb3bd; }

/* ---- SEASON row — full rewrite: label / big amber rank / decorative
   fill bar / PTS·ENDS meta, replacing the old single text line.
   .hud-season (click handler) and .hud-season-ends (live clock
   ticker, tickHudLiveClocks()) are unchanged so both keep working. */
#hud .hud-season {
  display: flex; align-items: center; gap: 12px; flex-wrap: nowrap;
  padding: 10px 12px; margin-top: 6px;
  background: rgba(8,24,33,0.8); border: 1px solid rgba(0,255,245,0.14);
  clip-path: polygon(0 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) 100%,0 100%);
}
#hud .hud-season:hover { border-color: rgba(0,255,245,0.4); color: inherit; text-decoration: none; }
#hud .hud-season-label { font-size: 10px; letter-spacing: 0.2em; color: rgba(168,198,207,0.6); flex-shrink: 0; }
#hud .hud-season-rank { font-family: 'Chakra Petch', var(--chrome-display); font-weight: 700; font-size: 16px; color: #ffd15c; flex-shrink: 0; }
#hud .hud-season-bar { flex: 1; min-width: 20px; height: 6px; background: rgba(255,255,255,0.06); position: relative; overflow: hidden; }
#hud .hud-season-bar-fill { position: absolute; inset: 0; width: 34%; background: repeating-linear-gradient(90deg, #ffb01f 0 6px, rgba(255,176,31,0.35) 6px 9px); }
#hud .hud-season-meta { font-size: 10px; letter-spacing: 0.14em; color: rgba(168,198,207,0.75); white-space: nowrap; flex-shrink: 0; }
@media (max-width: 1400px) {
  #hud .hud-season { flex-wrap: wrap; }
  #hud .hud-season-bar { flex-basis: 100%; order: 5; }
}

/* ---- "ACTIVE OPS ---- N LIVE" section title — new, sits above the
   event-card list. N is a real count (world events + open/claimed
   backdoor contracts, computed in renderSituationHud()), not a
   fabricated number. */
#hud .hud-ops-title { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
#hud .hud-ops-label { font-family: 'Chakra Petch', var(--chrome-display); font-weight: 600; font-size: 12px; letter-spacing: 0.24em; color: #6ffff4; }
#hud .hud-ops-rule { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(0,255,245,0.45), transparent); }
#hud .hud-ops-count { font-size: 10px; letter-spacing: 0.16em; color: #8fb3bd; flex-shrink: 0; }

/* ---- Op-cards — icon badge + timer badge, single-row head (was a
   bare emoji beside a stacked title+timer column). --ev-color (set
   per card in renderEventCardsHtml()/renderContractCardsHtml()) also
   replaces the 8 hardcoded per-kind border/hover/goto-background rules
   removed above/near the Round 5 block — this is the fix for both the
   missing scrubbing_run border and the barbarian_raid hover mismatch
   noted there. */
#hud .event-card {
  border-left-color: var(--ev-color, #3a2170);
  background: linear-gradient(160deg, color-mix(in srgb, var(--ev-color, #3a2170) 24%, #14101f), rgba(12,20,26,0.9));
}
#hud .event-card:hover {
  border-color: var(--ev-color, #37d5f5);
  background: linear-gradient(160deg, color-mix(in srgb, var(--ev-color, #3a2170) 34%, #182030), rgba(18,24,30,0.95));
}
#hud .event-card .ev-head { align-items: flex-start; gap: 10px; }
#hud .event-card .ev-icon {
  width: 22px; height: 22px; flex-shrink: 0; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px;
  background: var(--ev-color, #3a2170);
  clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
}
/* Round 8e: title used to clip to one line with an ellipsis (full text
   only reachable by hovering the tooltip) — user wants the whole title
   always visible. Wraps onto a second line instead when the panel isn't
   wide enough for it, rather than hiding any of it. */
#hud .event-card .ev-title {
  flex: 1; min-width: 0; font-size: 12px;
  white-space: normal; overflow: visible; text-overflow: clip;
}
#hud .event-card .ev-timer {
  flex-shrink: 0; margin-top: 0; display: flex; align-items: center; gap: 6px;
  padding: 3px 8px; background: rgba(0,0,0,0.4);
  border: 1px solid color-mix(in srgb, var(--ev-color, #3a2170) 45%, transparent);
  font-size: 10px; letter-spacing: 0.14em; color: #dff0f5;
  animation: none; text-shadow: none;
}
#hud .event-card .ev-goto {
  padding: 7px 12px; font-size: 11px; letter-spacing: 0.18em;
  background: var(--ev-color, var(--chrome-cyan));
  cursor: pointer; transition: filter 0.15s ease, letter-spacing 0.15s ease, box-shadow 0.15s ease;
}
/* Round 8i: JUMP button text should stay the same dark color always — a
   leftover base rule (#hud .event-card:hover .ev-goto { color:#5ee8ff })
   was turning it light cyan on hover, out-specificity-ing the Round 5
   #04121a here because ":hover" makes that older selector more specific.
   Matching its specificity to force the dark color back on hover too. */
#hud .event-card:hover .ev-goto { color: #04121a; }

/* ---- Shared HP pool — label row moved above the bar ("SHARED HP
   POOL  cur / max", matching the reference), replacing the old
   below-bar "cur / max HP" line. Track/fill keep this game's real
   virus/worm purple gradient — see the world.js comment on
   virusHpBarHtml() for why the reference's magenta example isn't used. */
#hud .event-card .ev-hp-label-row {
  display: flex; justify-content: space-between; margin-top: 8px;
  font-size: 9px; letter-spacing: 0.18em; color: rgba(168,198,207,0.65);
}
#hud .event-card .ev-hp-track { margin-top: 4px; height: 8px; }

/* ---- Round 8c — SITREP panel widened a bit ("разшири SITREP по
   широчина малко повече"). Base rule (line ~390) caps #hud at
   min(340px, 36vw); bumped here to min(400px, 40vw) — still well
   under the reference's fixed 496px (a small widen, not a jump to
   the reference's exact number, per "малко повече"). The narrower
   max-width steps at smaller breakpoints (min(310px,30vw) and down)
   are untouched — they only kick in below those viewport widths,
   where this wider cap wouldn't apply anyway. */
#hud { max-width: min(400px, 40vw); }

/* ============================================================
   MAIN MAP — NEON HUD v2 reskin, Round 9 (see project doc
   claude/main-map-neon-hud-v2.md). User supplied a Claude Design
   canvas file (.dc.html) for the bottom command bar — OPERATOR
   vitals / PROGRAMS / NAVIGATE / RECON / STRIKE — and asked for it
   "точно така както е в HTML ... можеш да вземеш всичко" (exactly
   as it is in the HTML, take everything). Two things in that file
   don't correspond to anything real in this game and were left out
   after asking: a per-tile hotkey-letter badge (H/J/Q/W/E/R) and a
   per-module numeric badge (1/2/3) — neither key actually does
   anything (checked: only Escape is bound to anything), so either
   would read as a working shortcut that silently does nothing.
   Everything else — colors, layout, the label+bar+value row shape,
   the tall icon-badge tile shape — is matched to the reference.
   MODE (FORTIFY/RELEASE/SELECT) has no counterpart in the reference
   (this game's real toolset is bigger than the mockup's NAVIGATE/
   RECON/STRIKE) — user's call: keep it, give it the same visual
   language as the other groups rather than leaving it looking dated
   next to them.
   ============================================================ */

/* ---- OPERATOR header line — no change needed here: an earlier round
   already promotes #st-name to the top of #stats (order:-1) with a
   CSS ::before "OPERATOR" label (see the #st-name rule above), which
   is exactly the reference's "OPERATOR {name} · {sectors} SECTOR ·
   DECK {ram}/{max}GB" row already. #stats now being a vitals list
   below it (next block) is the only actual change here. */

/* ---- Vitals rows — RAM/NRG/HEAT/CR/NEMESIS as label + bar + value
   lines, matching the reference's vitals list. CR and NEMESIS have
   no real "% of a cap" to visualize, so they skip the bar rather
   than fake one — a spacer keeps their value column aligned with
   the rows that do have a real bar. */
/* Round 9b: the pre-existing #stats max-width (220px, from long before
   this reskin) left almost no room for a real bar once the label (32px)
   and value (56px min) columns were accounted for — measured at 177px
   actual row width. Widened so the vitals bars read as real bars, not
   slivers; #toolbar-actions' own flex fix above absorbs the difference
   since it now actually grows to fill whatever's left. */
/* Wider block, shorter bars: the numbers (RAM, NRG +rate, CR +rate/h) need room to grow
   (four-digit CR, a boosted NRG cap) and the bars read fine at this length. */
#stats { display: flex; flex-direction: column; gap: 4px; justify-content: center; flex: 0 1 310px; max-width: 330px; }
.hud-vital-row { display: flex; align-items: center; gap: 8px; }
.hud-vital-label {
  width: 32px; flex-shrink: 0; font-size: 9px; letter-spacing: 0.14em;
  color: rgba(168,198,207,0.7);
}
.hud-vital-spacer { flex: 1; }
.hud-vital-value {
  min-width: 56px; flex: 1 0 auto; text-align: right; white-space: nowrap;
  font-family: 'Chakra Petch', var(--chrome-display); font-weight: 600;
  font-size: 11px; letter-spacing: 0.04em;
}
.hud-vital-value small { font-size: 8px; letter-spacing: 0.02em; color: rgba(168,198,207,0.6); font-weight: normal; }
#ram-meter-wrap, #nrg-meter-wrap, #heat-meter-wrap { flex: 0 1 150px; min-width: 0; max-width: 150px; margin: 0; }
#heat-meter {
  height: 8px; border: 1px solid rgba(255,176,31,0.3); background: #050d12; overflow: hidden; position: relative;
}
#heat-meter-fill {
  height: 100%; width: 0%;
  background: repeating-linear-gradient(90deg, #ffb01f 0 8px, rgba(0,0,0,0.35) 8px 11px);
  box-shadow: 0 0 10px rgba(255,176,31,0.6); transition: width 0.25s ease;
}
.hud-vital-row[data-vital="ram"] .hud-vital-value { color: var(--chrome-cyan); }
.hud-vital-row[data-vital="nrg"] .hud-vital-value { color: var(--chrome-ok); }
#st-heat-chip { cursor: pointer; }
/* [hidden] must win over the rows' / tiles' own display rules. */
.hud-vital-row[hidden], #toolbar-actions button[hidden] { display: none !important; }
/* Warrants (STATE_PURSUIT_PLAN stage 2): a state file is open on you. */
#st-warrant-chip .hud-vital-value, #st-warrant-chip .hud-vital-label { color: var(--chrome-warn); }
#st-warrant-chip.crit .hud-vital-value, #st-warrant-chip.crit .hud-vital-label { color: var(--chrome-alert); animation: heat-chip-pulse 1.1s ease-in-out infinite; }
#st-heat-chip.tier-low .hud-vital-value { color: #ffb01f; }
#st-heat-chip.tier-high .hud-vital-value { color: var(--chrome-warn); }
#st-heat-chip.tier-crit .hud-vital-value { color: var(--chrome-alert); animation: heat-chip-pulse 1.1s ease-in-out infinite; }
#st-heat-chip.bountied .hud-vital-value { color: var(--chrome-alert); }
#st-heat-chip.tier-high #heat-meter-fill, #st-heat-chip.bountied #heat-meter-fill {
  background: repeating-linear-gradient(90deg, var(--chrome-warn) 0 8px, rgba(0,0,0,0.35) 8px 11px);
  box-shadow: 0 0 10px rgba(245,163,55,0.6);
}
#st-heat-chip.tier-crit #heat-meter-fill {
  background: repeating-linear-gradient(90deg, var(--chrome-alert) 0 8px, rgba(0,0,0,0.35) 8px 11px);
  box-shadow: 0 0 10px rgba(245,88,88,0.6);
}
.hud-vital-value.cr { color: #ffd15c; }
#st-nemesis-chip { cursor: default; }
.hud-vital-value.nemesis { color: #b98fff; }
#st-nemesis-chip.agency .hud-vital-value.nemesis { color: #9a9ab9; }
#ram-meter-label, #ram-meter-hint { font-size: 8px; letter-spacing: 0.06em; color: var(--chrome-muted); margin-left: 40px; }
#ram-meter-hint:not(:empty) { color: #f55858; }

/* ---- PROGRAMS / module rack — real RESIDENT/IDLE/NO MEM status text
   (refreshSoftwarePickerStatus() in world.js) replaces the older
   two-state AVAILABLE/SELECTED ::before badge with the reference's
   own three real states, plus a real load bar under the spec line.
   The icon is a plain ring (not the reference's spinning-disk
   animation) — that spin was tied to "actively reading/writing",
   which isn't a real client-observable state here, and animating it
   unconditionally would read as fake activity. */
.sw-mod::before, .sw-mod::after { display: none; }
.sw-mod {
  flex-direction: row; align-items: stretch; gap: 0; padding: 0; overflow: hidden;
  min-height: 42px;
}
.sw-mod-icon {
  flex-shrink: 0; width: 32px; display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.35); border-right: 1px solid rgba(0,255,245,0.16);
}
.sw-mod-dot {
  width: 15px; height: 15px; border: 2px solid currentColor; border-radius: 50%;
  opacity: 0.5; position: relative; display: block;
}
.sw-mod-dot::after {
  content: ''; position: absolute; top: 50%; left: 50%; width: 3px; height: 3px;
  border-radius: 50%; background: currentColor; transform: translate(-50%, -50%);
}
.sw-mod-name::before { display: none; }
.sw-mod.on .sw-mod-dot {
  opacity: 1;
  color: #4dff9f;
  border-color: #4dff9f;
  box-shadow: 0 0 8px #4dff9f;
  animation: sw-hdd-seek 1.85s steps(1, end) infinite;
}
.sw-mod.on .sw-mod-dot::after {
  width: 7px; height: 7px;
  background: #4dff9f;
  box-shadow: 0 0 6px #4dff9f;
}
@keyframes sw-hdd-seek {
  0%, 6% { opacity: 1; }
  7% { opacity: 0.18; }
  9% { opacity: 1; }
  11% { opacity: 0.3; }
  13% { opacity: 1; }
  28% { opacity: 1; }
  29% { opacity: 0.12; }
  31% { opacity: 1; }
  33% { opacity: 0.22; }
  35% { opacity: 1; }
  36% { opacity: 0.4; }
  38% { opacity: 1; }
  58% { opacity: 1; }
  59% { opacity: 0.2; }
  61% { opacity: 1; }
  76% { opacity: 1; }
  77% { opacity: 0.28; }
  79% { opacity: 1; }
  91% { opacity: 1; }
  92% { opacity: 0.15; }
  94% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .sw-mod.on .sw-mod-dot { animation: none; }
}
.sw-mod-body { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 3px; padding: 5px 9px; }
.sw-mod-head { display: flex; align-items: center; gap: 7px; }
.sw-mod-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-mod-status {
  font-size: 7px; letter-spacing: 0.1em; padding: 1px 5px; flex-shrink: 0;
  color: rgba(168,198,207,0.7); background: rgba(255,255,255,0.04); border: 1px solid rgba(168,198,207,0.3);
}
.sw-mod-status.resident { color: #04180f; background: #4dff9f; border-color: #4dff9f; }
.sw-mod-status.no-mem { color: #ffd970; background: rgba(255,176,31,0.14); border-color: rgba(255,176,31,0.5); }
.sw-mod-specrow { display: flex; align-items: center; gap: 8px; }
.sw-mod-ram { flex-shrink: 0; }
.sw-mod-load-track { flex: 1; min-width: 24px; height: 4px; background: rgba(0,0,0,0.5); position: relative; overflow: hidden; }
.sw-mod-load-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0%; color: rgba(150,180,195,0.65);
  background: repeating-linear-gradient(90deg, currentColor 0 4px, rgba(0,0,0,0.4) 4px 6px);
  transition: width 0.25s ease;
}
.sw-mod.on .sw-mod-load-fill { color: #4dff9f; }
.sw-mod:has(.sw-mod-status.no-mem) .sw-mod-load-fill { color: rgba(255,176,31,0.6); }
#software-picker { max-width: 300px; }

/* ---- Round 10: PROGRAMS panel header (real mem used/total + a per-GB
   pip bar), the whole resident row highlighted green to match its
   RESIDENT badge/load-bar color, and a real "last load" console line —
   all per a fresh reference screenshot the user re-supplied. mem value
   is the resident program's own real RAM cost (softwareCatalog[name].ram),
   same number already shown per-row and used by the RAM meter elsewhere —
   not an invented percentage. No numeric hotkey badge (1/2/3) added —
   same no-fabricated-shortcuts call as Round 9. */
.programs-panel { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; min-width: 0; }
.sw-panel-head { display: flex; align-items: center; gap: 10px; }
.sw-panel-title {
  font-family: 'Chakra Petch', var(--chrome-display); font-size: 11px; font-weight: 700;
  letter-spacing: 0.22em; color: var(--chrome-cyan); flex-shrink: 0;
}
.sw-panel-mem { font-size: 9px; letter-spacing: 0.06em; color: var(--chrome-muted); flex-shrink: 0; white-space: nowrap; }
.sw-panel-mem b { color: var(--chrome-cyan); font-weight: 700; }
.sw-mem-pips { display: flex; gap: 2px; flex: 1; min-width: 50px; height: 8px; }
.sw-mem-pip { flex: 1; min-width: 0; background: rgba(0,255,245,0.08); border: 1px solid rgba(0,255,245,0.14); }
/* Round 14: TRACE budget moved from its own orphan column beside PROGRAMS
   (where it floated alone at a mismatched height and read as a stray
   element) into a proper full-width row inside the PROGRAMS card itself,
   right under the mem/pip header — same real per-selected-software trace
   goal as before (traceGoalForSoftware(), driven by updateSoftwarePreview()),
   just given an actual home instead of orphaned real estate. */
.sw-trace-row { display: flex; align-items: center; gap: 8px; }
.sw-trace-row .bar-lbl { font-size: 9px; letter-spacing: 0.1em; color: var(--chrome-warn); flex-shrink: 0; white-space: nowrap; }
.sw-trace-row .bar-lbl b { color: var(--chrome-warn); font-weight: 700; }
.sw-trace-row .trace-demo-slot { flex: 1; min-width: 40px; height: 8px; }
.sw-mem-pip.filled {
  background: linear-gradient(180deg, #8affff, #00fff5); border-color: rgba(0,255,245,0.7);
  box-shadow: 0 0 6px rgba(0,255,245,0.55);
}

.sw-mod.on {
  border-color: rgba(77,255,159,0.55); color: #8dffc4;
  background: linear-gradient(90deg, rgba(15,46,32,0.6), rgba(8,22,20,0.88));
  box-shadow: inset 0 0 0 1px rgba(77,255,159,0.18);
}
.sw-mod.on .sw-mod-name { color: #eafff2; }

.sw-console-line {
  font-family: 'Chakra Petch', var(--chrome-display); font-size: 9px; letter-spacing: 0.03em;
  color: rgba(168,198,207,0.75); padding: 3px 2px 0;
}
.sw-console-prompt { color: #4dff9f; font-weight: 700; margin-right: 2px; }
.sw-console-ok { color: #4dff9f; font-weight: 700; }
.sw-console-cursor {
  display: inline-block; width: 6px; height: 10px; margin-left: 4px; vertical-align: -1px;
  background: #4dff9f; box-shadow: 0 0 6px rgba(77,255,159,0.7);
  animation: sw-mod-led-blink 1s steps(1, end) infinite;
}
@media (max-width: 1100px) {
  .sw-mem-pips { display: none; }
  .sw-panel-mem { display: none; }
}

/* ---- Round 10: RAM/NRG bars switched from a smooth gradient fill to the
   same repeating-chunk "pip" texture the HEAT bar already uses, matching
   the reference's segmented-tick vitals bars. Same real free/overhead/
   breach flex ratios and the same real energy % as before — only the
   fill's own texture and RAM's "free" hue changed (free was an odd
   legacy red for the *available* segment; now cyan, matching the RAM
   value text's own color and the reference). */
#ram-seg-free {
  background: repeating-linear-gradient(90deg, #00fff5 0 8px, rgba(0,0,0,0.35) 8px 11px) !important;
  box-shadow: 0 0 8px rgba(0,255,245,0.45);
}
#ram-seg-overhead {
  background: repeating-linear-gradient(90deg, var(--chrome-warn) 0 8px, rgba(0,0,0,0.35) 8px 11px) !important;
  box-shadow: 0 0 8px rgba(245,163,55,0.45);
}
#ram-seg-breach {
  background: repeating-linear-gradient(90deg, #37f5a3 0 8px, rgba(0,0,0,0.35) 8px 11px) !important;
  box-shadow: 0 0 8px rgba(43,255,142,0.45);
}
#nrg-meter-fill {
  background: repeating-linear-gradient(90deg, #37f5a3 0 8px, rgba(0,0,0,0.35) 8px 11px) !important;
  box-shadow: 0 0 8px rgba(43,255,142,0.45);
}

/* CR bar — explicitly decorative, per the user's own call after being asked:
   real credits are uncapped, so this fill is a fixed width, not a computed
   percentage of anything. Same "reference declares it non-data, draw it
   anyway" precedent as the SEASON row's rank-progress bar (Round 8). */
.cr-meter-wrap { flex: 0 1 150px; max-width: 150px; min-width: 0; height: 8px; border: 1px solid rgba(255,209,92,0.25); background: #050d12; overflow: hidden; }
.cr-meter-fill {
  height: 100%; width: 42%;
  background: repeating-linear-gradient(90deg, #ffd15c 0 8px, rgba(0,0,0,0.35) 8px 11px);
  box-shadow: 0 0 8px rgba(255,209,92,0.4);
}

/* ---- Command bar action-tile groups — real per-group header color +
   thin gradient rule (the reference's g.accent / g.line), replacing
   the flat gray label + boxed-container look. MODE gets the same
   treatment with its own accent (amber) since it has no reference
   counterpart to match. */
/* Round 9b: the actual "proportions aren't respected" bug — groups and
   tiles had no flex-grow, so they only ever sized to their own content's
   minimum width and the leftover row width just sat empty. The reference
   gives every group a real `flex` share and every tile `flex:1` inside
   its group so tiles read as wide ~2.6:1 cards, not tall narrow columns.
   Measured on the live page before this fix: NAVIGATE's CORE tile was
   72×105px (0.7:1, taller than wide) at a 1920px window — this is what
   that looked like. Groups get a `flex` share close to the reference's
   own g.flex values (recon 1, strike 1.45 — wider for the "commit"
   cluster). flex-wrap:nowrap keeps groups from wrapping onto their own
   line at the container's normal widths — the existing 900px/640px
   breakpoints below still collapse everything for narrow screens.
   NAVIGATE is back to a plain 2-tile group (CORE/SAFEHOUSE) now that
   SELECT has no toolbar tile at all — the former MODE group
   (FORTIFY/RELEASE/SELECT) was removed once the hex context radial made
   all three either a one-off per-hex action or a pure implicit default
   state; see the toolbar markup above for the fuller reasoning. */
#toolbar-actions { flex-wrap: nowrap; }
#toolbar-actions .act-group {
  background: none; border: none; padding: 0; gap: 7px;
  flex: 1 1 0; min-width: 0;
}
#toolbar-actions .act-group[data-group="navigate"] { flex-grow: 1; }
#toolbar-actions .act-group[data-group="recon"] { flex-grow: 1; }
#toolbar-actions .act-group[data-group="strike"] { flex-grow: 1.45; }
#toolbar-actions .act-row { flex-wrap: nowrap; }
/* No min-width:0 here on purpose — the existing 72px/86px min-width
   rules elsewhere stay as the hard floor so tiles never shrink past
   legibility; flex:1 only grows them beyond that floor when there's
   room, it doesn't remove the floor. */
#toolbar-actions .act-row button { flex: 1 1 0; }
@media (max-width: 900px) {
  #toolbar-actions { flex-wrap: wrap; }
  #toolbar-actions .act-group { flex: 1 1 auto; }
  #toolbar-actions .act-row { flex-wrap: wrap; }
  #toolbar-actions .act-row button { flex: 1 1 auto; }
}
#toolbar-actions .act-group-head { display: flex; align-items: center; gap: 9px; }
#toolbar-actions .act-group-label {
  font-size: 11px; letter-spacing: 0.22em; padding-left: 0; white-space: nowrap;
}
#toolbar-actions .act-group-rule { flex: 1; height: 1px; min-width: 10px; }
#toolbar-actions .act-group[data-group="navigate"] .act-group-label { color: #aefffb; }
#toolbar-actions .act-group[data-group="navigate"] .act-group-rule { background: linear-gradient(90deg, rgba(0,255,245,0.4), transparent); }
#toolbar-actions .act-group[data-group="recon"] .act-group-label { color: #8dffc4; }
#toolbar-actions .act-group[data-group="recon"] .act-group-rule { background: linear-gradient(90deg, rgba(43,255,142,0.4), transparent); }
#toolbar-actions .act-group[data-group="strike"] .act-group-label { color: #ff86d4; }
#toolbar-actions .act-group[data-group="strike"] .act-group-rule { background: linear-gradient(90deg, rgba(255,47,174,0.45), transparent); }
@media (max-width: 900px) { #toolbar-actions .act-group-head { display: none; } }

/* Round 14: gap between the 4 groups was the same 5px as the gap between
   buttons inside one group (both from the base #toolbar-actions/.act-row
   rules above), so nothing but the header label ever told two adjacent
   groups apart — user feedback: "искам бутоните ... да са разделени, за
   да се вижда, а не така едни до други". The reference's own actionGroups
   wrapper (`Netwar HUD v2 neon.dc.html`, the div holding the sc-for over
   actionGroups) uses gap:14px between groups and gap:9px between the
   buttons within one group — used those exact values instead of guessing
   at new ones. */
#toolbar-actions { gap: 14px; }
#toolbar-actions .act-row { gap: 9px; }
@media (max-width: 1400px) { #toolbar-actions { gap: 8px; } }

/* ---- Tiles — taller cards closer to the reference's 104px, and real
   per-action colors matched to it: SCAN/DEEP SCAN move from this
   session's own violet/cyan convention to the reference's green
   (matching the RECON group they sit under); CAPTURE moves from this
   session's green to the reference's gold; RAID becomes a solid
   pink-gradient filled tile with dark text instead of a dark tile
   with a magenta outline. CORE/SAFEHOUSE get the reference's exact
   background saturation. FORTIFY/RELEASE/SELECT (MODE, not in the
   reference) get matching gradient-tinted backgrounds in their own
   existing hues for visual consistency with the rest. All .on /
   hover / on-cooldown / low-nrg / ready-nrg functional states above
   are untouched — only the resting-state look changes here. */
#toolbar-actions button { min-height: clamp(64px, 7vw, 104px); }
#toolbar-actions .act-btn-inner { min-height: clamp(64px, 7vw, 104px); }
#toolbar-actions .act-btn-icon { width: 24px; height: 24px; }
#toolbar-main #btn-home-core {
  border-color: rgba(0,255,245,0.28); color: #cfe8ee;
  background: linear-gradient(160deg, rgba(12,34,45,0.9), rgba(5,17,25,0.95));
}
#toolbar-main #btn-safehouse {
  color: #eddcff; border-color: rgba(196,150,255,0.75);
  background: linear-gradient(160deg, rgba(72,36,126,0.95), rgba(24,12,52,0.95));
  box-shadow: 0 0 26px -8px rgba(178,120,255,0.7), inset 0 0 26px -10px rgba(196,150,255,0.45);
}
#toolbar-main #btn-safehouse:hover:not(:disabled) {
  border-color: #eafffe; box-shadow: 0 0 34px -2px rgba(69,255,240,1);
}
#toolbar-actions button[data-act="fortify"]:not(.on) {
  background: linear-gradient(160deg, rgba(10,42,30,0.7), rgba(5,18,18,0.95));
}
#toolbar-actions button[data-act="release"]:not(.on) {
  background: linear-gradient(160deg, rgba(58,40,10,0.7), rgba(18,14,5,0.95));
}
#toolbar-actions button[data-act="select"]:not(.on) {
  background: linear-gradient(160deg, rgba(10,34,45,0.7), rgba(5,17,25,0.95));
}
#toolbar-actions button[data-act="scan"]:not(.on) {
  border-color: rgba(43,255,142,0.4); color: #8dffc4;
  background: linear-gradient(160deg, rgba(10,42,30,0.9), rgba(5,18,18,0.95));
  box-shadow: inset 0 0 24px -8px rgba(43,255,142,0.5);
}
#toolbar-actions button[data-act="deepscan"]:not(.on) {
  border-color: rgba(43,255,142,0.3); color: #8dffc4;
  background: linear-gradient(160deg, rgba(10,42,30,0.7), rgba(5,18,18,0.95));
}
#toolbar-actions button[data-act="scan"]:hover:not(:disabled),
#toolbar-actions button[data-act="deepscan"]:hover:not(:disabled) {
  border-color: #2bff8e; color: #aeffda; box-shadow: 0 0 26px -8px rgba(43,255,142,0.7);
}
#toolbar-actions button[data-act="scan"] .act-btn-fill,
#toolbar-actions button[data-act="deepscan"] .act-btn-fill {
  background: linear-gradient(180deg, rgba(43,255,142,0.12), rgba(43,255,142,0.42));
}
#toolbar-actions button[data-act="capture"] {
  border-color: #ffb01f; color: #ffe86b;
  background: linear-gradient(160deg, rgba(86,58,6,0.95), rgba(26,20,8,0.95));
  box-shadow: 0 0 32px -6px rgba(255,176,31,0.75), inset 0 0 30px -10px rgba(255,176,31,0.5);
}
#toolbar-actions button[data-act="capture"] .act-btn-icon { border-color: #ffb01f; }
#toolbar-actions button[data-act="capture"] .act-btn-fill {
  background: linear-gradient(180deg, rgba(255,176,31,0.14), rgba(255,176,31,0.45));
}
#toolbar-actions button[data-act="capture"].on,
#toolbar-actions button[data-act="capture"]:hover:not(:disabled) {
  box-shadow: 0 0 34px -6px rgba(255,176,31,0.9);
}
#toolbar-actions button[data-act="raid"] {
  border-color: rgba(255,180,220,0.6); color: #1c0512;
  background: linear-gradient(180deg, #ff5cc0, #b82a78);
  box-shadow: 0 0 30px -6px rgba(255,47,174,0.8);
}
#toolbar-actions button[data-act="raid"] .act-btn-icon { border-color: rgba(255,180,220,0.6); }
#toolbar-actions button[data-act="raid"]:not(.ready-nrg):not(.low-nrg) .act-btn-meta { color: rgba(28,5,18,0.8); }
#toolbar-actions button[data-act="raid"] .act-btn-fill {
  background: linear-gradient(180deg, rgba(0,0,0,0.05), rgba(0,0,0,0.28));
}
#toolbar-actions button[data-act="raid"].on,
#toolbar-actions button[data-act="raid"]:hover:not(:disabled) {
  box-shadow: 0 0 40px -6px rgba(255,47,174,1);
}

/* F5 — mockup stack: feed under tiles. Tiles grow to fill leftover
   toolbar-main width (no empty strip on the right). */
#toolbar-ops {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
}
#toolbar-actions {
  flex: 0 0 auto;
  justify-content: flex-start;
  gap: 10px;
  width: 100%;
}
#toolbar-actions .act-group,
#toolbar-actions .act-group[data-group="navigate"],
#toolbar-actions .act-group[data-group="recon"],
#toolbar-actions .act-group[data-group="strike"] {
  flex: 1 1 0;
  min-width: 0;
}
#toolbar-actions .act-group[data-group="strike"] { flex-grow: 1.2; }
#toolbar-actions .act-row { gap: 5px; width: 100%; }
#toolbar-actions .act-row button {
  flex: 1 1 0;
  width: auto;
  min-width: 64px;
  max-width: none;
}
#toolbar-actions button[data-act="capture"],
#toolbar-actions button[data-act="raid"],
#toolbar-main #btn-safehouse,
#toolbar-actions button[data-act="deepscan"] {
  width: auto;
  min-width: 64px;
  max-width: none;
}
#toolbar-actions .act-btn-inner {
  padding: 5px 6px;
}
#toolbar-actions .act-btn-label { font-size: 10px; letter-spacing: 0.06em; }
#toolbar-actions .act-btn-meta { font-size: 7px; }
#toolbar-actions button { min-height: 72px; }
#toolbar-actions .act-btn-inner { min-height: 72px; }
#feed-wrap { width: 100%; }
@media (max-width: 900px) {
  #toolbar-ops { width: 100%; flex: 1 1 100%; }
  #toolbar-actions .act-row button,
  #toolbar-actions button[data-act="capture"],
  #toolbar-actions button[data-act="raid"],
  #toolbar-main #btn-safehouse,
  #toolbar-actions button[data-act="deepscan"] {
    width: auto;
    min-width: 64px;
    max-width: none;
    flex: 1 1 auto;
  }
  #toolbar-actions button { min-height: 44px; }
  #toolbar-actions .act-btn-inner { min-height: 44px; }
}

/* Don't let the generic #toolbar button chrome restyle feed chips. */
#feed-wrap .feed-filter,
#feed-wrap #feed-expand {
  clip-path: none;
  min-height: 0;
  min-width: 0;
  animation: none;
}

/* Phone browser shell. Gated on html[data-phone] which JS sets only for
   coarse/hover-none devices — desktop mouse layouts are unchanged even
   if the window is 900px wide. */
#phone-rotate, #phone-peeks, #phone-prog-btn, #phone-op-btn { display: none; }
html[data-phone="port"] #phone-rotate {
  display: flex; position: fixed; inset: 0; z-index: 9000;
  align-items: center; justify-content: center; flex-direction: column; gap: 10px;
  background: #05030a; color: #e8fbff; text-align: center; padding: 24px;
  font: 700 14px/1.4 Consolas, 'Courier New', ui-monospace, monospace;
  letter-spacing: 0.14em; text-transform: uppercase;
}
html[data-phone="port"] #phone-rotate span { color: #ffd84a; font-size: 11px; letter-spacing: 0.2em; }
html[data-phone="port"] #panel { visibility: hidden; }

html[data-phone="land"],
html[data-phone="land"] body {
  height: 100%;
  height: 100dvh;
}
html[data-phone="land"] body {
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
html[data-phone="land"] #panel {
  width: 100%; max-width: none; height: 100%; max-height: none;
  border: 0; box-shadow: none;
}
html[data-phone="land"] #bar {
  padding: 2px 6px; gap: 6px; min-height: 24px;
}
html[data-phone="land"] #bar .brand-mark { width: 14px; height: 14px; font-size: 8px; }
html[data-phone="land"] #bar .beta-mark { font-size: 6px; }
html[data-phone="land"] #bar .rt-tag,
html[data-phone="land"] #inf-ticker,
html[data-phone="land"] #btn-manual,
html[data-phone="land"] #btn-feedback,
html[data-phone="land"] #btn-support { display: none; }
html[data-phone="land"] #bar .t { font-size: 9px; letter-spacing: 0.12em; }
html[data-phone="land"] #bar .live { font-size: 7px; padding: 1px 5px; }
html[data-phone="land"] #btn-sound { font-size: 7px; padding: 2px 6px 2px 14px; min-height: 24px; letter-spacing: 0.08em; }
html[data-phone="land"] #btn-neural-link { font-size: 7px; padding: 2px 6px; min-height: 24px; letter-spacing: 0.08em; }
html[data-phone="land"] #viewport {
  min-height: 0; flex: 1 1 auto;
}
html[data-phone="land"] #map-crt { display: none; }
html[data-phone="land"] #feed-wrap { display: none; }

html[data-phone="land"] #phone-peeks {
  display: block; position: absolute; inset: 0; z-index: 7; pointer-events: none;
}
html[data-phone="land"] #phone-peeks button {
  pointer-events: auto; position: absolute; top: 50%; transform: translateY(-50%);
  min-height: 48px; padding: 5px 4px; cursor: pointer;
  font: 700 7px/1 Consolas, 'Courier New', ui-monospace, monospace;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: #aefffb; background: rgba(7, 24, 32, 0.92);
  border: 1px solid rgba(0, 255, 245, 0.28);
  writing-mode: vertical-rl;
}
html[data-phone="land"] #phone-sitrep-btn { left: 0; }
html[data-phone="land"] #phone-target-btn { right: 0; color: #ffe9c4; display: none; }
html[data-phone="land"] #viewport:has(#inspect.show) #phone-target-btn { display: block; }

html[data-phone="land"] #hud {
  left: 0; top: 0; bottom: auto;
  width: min(240px, 70vw); max-width: none;
  max-height: 100%; height: 100%;
  padding: 5px 6px; font-size: 9px; line-height: 1.35;
  pointer-events: auto;
  transform: translateX(-105%);
  transition: transform 0.22s ease;
  z-index: 8;
}
html[data-phone="land"].phone-sitrep-open #hud {
  transform: translateX(0);
}
html[data-phone="land"] #hud .sitrep { font-size: 10px; letter-spacing: 0.12em; }
html[data-phone="land"] #hud .hud-head { margin: -5px -6px 5px; padding: 5px 8px 5px 12px; }
html[data-phone="land"] #hud .hsb-label,
html[data-phone="land"] #hud .hud-vital-label { font-size: 7px; }
html[data-phone="land"] #hud .hsb-value { font-size: 10px; }
html[data-phone="land"] #hud .event-card { padding: 5px 7px; gap: 5px; }
html[data-phone="land"] #hud .event-card .ev-title { font-size: 9px; }
html[data-phone="land"] #hud .event-card .ev-goto { font-size: 7px; padding: 2px 5px; min-height: 22px; }
html[data-phone="land"] #inspect-dock {
  top: 0; right: 0; max-height: 100%;
  transform: translateX(105%);
  transition: transform 0.22s ease;
  z-index: 8;
}
html[data-phone="land"].phone-target-open #inspect-dock {
  transform: translateX(0);
}
html[data-phone="land"] #inspect {
  width: min(240px, 70vw); max-height: 100%;
  font-size: 9px; line-height: 1.35;
}
html[data-phone="land"] #inspect .sitrep-title { font-size: 10px; letter-spacing: 0.12em; }
html[data-phone="land"] #inspect .sitrep-subtitle { font-size: 8px; }
html[data-phone="land"] #inspect .sitrep-section { margin: 5px 6px; padding: 5px 7px 6px; }
html[data-phone="land"] #inspect .sitrep-section-title { margin: -5px -7px 5px; padding: 5px 7px 4px 12px; font-size: 8px; }
html[data-phone="land"] #inspect .sitrep-row { font-size: 8px; padding: 2px 0; }
html[data-phone="land"] #inspect .k { font-size: 8px; }
html[data-phone="land"] #inspect .sitrep-hint { font-size: 8px; }
html[data-phone="land"] #inspect .bd-post-lead { font-size: 9px; margin: 6px 0 5px; }
html[data-phone="land"] #inspect .bd-post-split strong { font-size: 10px; }
html[data-phone="land"] #inspect .bd-post-box { min-height: 28px; }
html[data-phone="land"] #inspect .bd-cli { min-height: 28px; font-size: 13px; }
html[data-phone="land"] #inspect .bd-post #btn-backdoor-create { min-height: 28px; font-size: 9px; }

html[data-phone="land"] #toolbar { overflow: visible; font-size: 9px; }
html[data-phone="land"] #toolbar-main {
  flex-direction: row; flex-wrap: nowrap; align-items: stretch;
  padding: 2px 4px; gap: 4px;
}
html[data-phone="land"] #stats {
  flex-direction: row; flex-wrap: nowrap; align-items: center;
  min-width: 0; max-width: none; flex: 0 1 auto;
  margin: 0; padding: 0 2px 0 0; border: 0; gap: 4px;
  overflow-x: auto;
}
html[data-phone="land"] #stats::before,
html[data-phone="land"] #stats::after,
html[data-phone="land"] #st-name,
html[data-phone="land"] #ram-meter-label,
html[data-phone="land"] #ram-meter-hint { display: none; }
html[data-phone="land"] .hud-vital-row { flex: 0 0 auto; min-width: 52px; gap: 4px; }
html[data-phone="land"] .hud-vital-label { font-size: 6px; letter-spacing: 0.08em; }
html[data-phone="land"] .hud-vital-value { font-size: 9px; }
html[data-phone="land"] #ram-meter-wrap,
html[data-phone="land"] #nrg-meter-wrap,
html[data-phone="land"] #heat-meter-wrap,
html[data-phone="land"] .cr-meter-wrap { width: 36px; height: 4px; flex: 0 0 36px; }
html[data-phone="land"] .hud-vital-value { flex: 0 0 auto; }
html[data-phone="land"] #software-zone {
  display: none;
  flex: unset; max-width: none; margin: 0; padding: 5px;
  border: 1px solid rgba(0, 255, 245, 0.28);
  background: rgba(6, 20, 28, 0.96);
  position: absolute; left: 6px; right: 6px; bottom: calc(100% + 4px);
  z-index: 9; max-height: min(48dvh, 200px); overflow: auto;
  font-size: 9px;
}
html[data-phone="land"].phone-prog-open #software-zone { display: block; }
html[data-phone="land"] .sw-panel-title { font-size: 8px; letter-spacing: 0.14em; }
html[data-phone="land"] .sw-panel-mem { font-size: 7px; }
html[data-phone="land"] .sw-mod { min-height: 32px; }
html[data-phone="land"] .sw-mod-icon { width: 22px; }
html[data-phone="land"] .sw-mod-dot { width: 10px; height: 10px; border-width: 1.5px; }
html[data-phone="land"] .sw-mod-name { font-size: 9px; }
html[data-phone="land"] .sw-mod-status { font-size: 6px; padding: 0 3px; }
html[data-phone="land"] .sw-mod-ram { font-size: 7px; }
html[data-phone="land"] .sw-console-line { font-size: 7px; }
html[data-phone="land"] #toolbar { position: relative; }
html[data-phone="land"] #phone-prog-btn {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; min-width: 32px; min-height: 32px; margin: 0;
  font: 700 7px/1 Consolas, 'Courier New', ui-monospace, monospace;
  letter-spacing: 0.1em; color: #8dffc4;
  background: #071820; border: 1px solid rgba(43, 255, 142, 0.4);
}
html[data-phone="land"].phone-prog-open #phone-prog-btn {
  color: #04180f; background: #4dff9f; border-color: #4dff9f;
}
html[data-phone="land"] #toolbar-actions {
  flex: 1 1 auto; flex-wrap: nowrap; justify-content: flex-start;
  overflow-x: auto; -webkit-overflow-scrolling: touch; gap: 4px;
}
html[data-phone="land"] #toolbar-actions .act-group { flex: 0 0 auto; }
html[data-phone="land"] #toolbar-actions .act-row { flex-wrap: nowrap; gap: 3px; }
html[data-phone="land"] #toolbar-actions button {
  min-width: 36px; min-height: 32px; padding: 0;
  font-size: 7px; letter-spacing: 0.06em;
}
html[data-phone="land"] #toolbar-actions .act-btn-inner { min-height: 32px; padding: 2px 4px; }
html[data-phone="land"] #toolbar-actions .act-btn-row { gap: 2px; }
html[data-phone="land"] #toolbar-actions .act-btn-icon { width: 12px; height: 12px; font-size: 8px; }
html[data-phone="land"] #toolbar-actions .act-btn-label { font-size: 7px; letter-spacing: 0.06em; }
html[data-phone="land"] #toolbar-actions .act-btn-meta { display: none; }
html[data-phone="land"] #toolbar-actions .act-group-head { display: none; }
html[data-phone="land"] #toolbar button { touch-action: manipulation; }

html[data-phone="land"] #viewport { --nl-w: min(320px, 82vw); }
html[data-phone="land"] #neural-link { font-size: 10px; }
html[data-phone="land"] #neural-link .nx-btn,
html[data-phone="land"] #neural-link .nl-tab { min-height: 32px; }

/* Map popups / overlays — compact cards, not full short-viewport slabs. */
html[data-phone="land"] #demo-cta-banner {
  top: 6px; max-width: min(280px, 72vw); padding: 6px 10px; gap: 4px;
  font-size: 9px; line-height: 1.3;
}
html[data-phone="land"] #demo-cta-banner.show { gap: 4px; }

html[data-phone="land"] #demo-cta-banner strong { font-size: 9px; letter-spacing: 0.1em; }
html[data-phone="land"] #demo-cta-banner .demo-access-badge { display: none; }
html[data-phone="land"] #demo-cta-banner p { margin: 2px 0 0; font-size: 8px; }
html[data-phone="land"] #demo-cta-btn {
  margin-top: 2px; padding: 5px 10px; font-size: 9px; letter-spacing: 0.08em; min-height: 28px;
}
html[data-phone="land"] #demo-cta-restore, html[data-phone="land"] #demo-cta-intro { font-size: 8px; margin-top: 0; }

html[data-phone="land"] #deploy-banner {
  top: 6px; max-width: min(280px, 72vw); padding: 6px 10px; font-size: 9px; gap: 6px;
}
html[data-phone="land"] #deploy-banner .deploy-icon { font-size: 12px; }
html[data-phone="land"] #deploy-banner strong { font-size: 9px; letter-spacing: 0.1em; }
html[data-phone="land"] #deploy-banner p { margin: 2px 0 0; font-size: 8px; }
html[data-phone="land"] #deploy-banner .deploy-frontier-hint { margin: 3px 0 0; font-size: 7px; }

html[data-phone="land"] #deploy-dialog-box,
html[data-phone="land"] #map-confirm-box {
  width: min(260px, 78vw); padding: 10px 12px 9px; font-size: 9px;
}
html[data-phone="land"] #deploy-dialog-box h3,
html[data-phone="land"] #map-confirm-box h3 { font-size: 10px; margin-bottom: 4px; letter-spacing: 0.1em; }
html[data-phone="land"] #deploy-dialog-box .sector { margin-bottom: 6px; font-size: 8px; }
html[data-phone="land"] #deploy-dialog-box label { font-size: 7px; margin-bottom: 3px; }
html[data-phone="land"] #deploy-core-name { padding: 5px 7px; font-size: 11px; }
html[data-phone="land"] #map-confirm-box p { font-size: 8px; margin-bottom: 6px; }
html[data-phone="land"] #map-confirm-warn { margin: 0 0 8px; padding: 5px 7px; font-size: 7px; }
html[data-phone="land"] #deploy-dialog-actions,
html[data-phone="land"] #map-confirm-actions { gap: 6px; }
html[data-phone="land"] #deploy-dialog-actions button,
html[data-phone="land"] #map-confirm-actions button {
  padding: 5px 10px; font-size: 8px; min-height: 28px;
}

html[data-phone="land"] #loot-reveal-box {
  width: min(280px, 82vw); padding: 10px 12px 9px;
}
html[data-phone="land"] #loot-reveal-title { font-size: 10px; margin-bottom: 2px; }
html[data-phone="land"] #loot-reveal-sub { font-size: 8px; margin-bottom: 8px; }
html[data-phone="land"] #loot-reveal-cards { gap: 6px; margin-bottom: 8px; }
html[data-phone="land"] .loot-chip { min-width: 88px; max-width: 120px; padding: 5px 7px; }
html[data-phone="land"] .loot-chip-name { font-size: 8px; }
html[data-phone="land"] .loot-chip-meta { font-size: 7px; margin-top: 3px; }
html[data-phone="land"] #loot-reveal-actions button { padding: 5px 10px; font-size: 8px; min-height: 28px; }
html[data-phone="land"] #loot-toast-stack {
  bottom: 56px; max-width: min(220px, 70vw);
}
html[data-phone="land"] .loot-toast { padding: 6px 8px; }
html[data-phone="land"] .loot-toast-head { font-size: 7px; margin-bottom: 3px; }
html[data-phone="land"] .loot-toast-foot { font-size: 6px; margin-top: 3px; }

html[data-phone="land"] #enter-defense-cta {
  right: 8px; bottom: 8px; width: min(220px, calc(100vw - 16px));
  padding: 6px 8px; font-size: 9px;
}
html[data-phone="land"] #enter-defense-cta .ed-title { font-size: 9px; }
html[data-phone="land"] #enter-defense-cta .ed-status,
html[data-phone="land"] #enter-defense-cta .ed-timer { font-size: 8px; }
html[data-phone="land"] #enter-defense-cta #ed-enter-btn,
html[data-phone="land"] #enter-defense-cta .ed-dismiss {
  padding: 5px 8px; font-size: 8px; min-height: 28px;
}

html[data-phone="land"] #frontier-chips {
  left: 6px; bottom: 6px; max-width: min(200px, 42vw); gap: 3px;
}
html[data-phone="land"] #deploy-pending,
html[data-phone="land"] #deploy-toast { font-size: 9px; padding: 6px 10px; }

html[data-phone="land"] #support-overlay .sp-panel,
html[data-phone="land"] #feedback-overlay .fb-panel {
  width: min(300px, 86vw); max-height: min(88dvh, 100%); padding: 12px 14px;
}
html[data-phone="land"] #support-overlay .sp-title,
html[data-phone="land"] #feedback-overlay .fb-title { font-size: 14px; }
html[data-phone="land"] #support-overlay .sp-copy,
html[data-phone="land"] #feedback-overlay .fb-copy { font-size: 10px; }
html[data-phone="land"] #manual-overlay .mo-head { padding: 8px 12px; }
html[data-phone="land"] #manual-overlay .mo-title { font-size: 12px; }
html[data-phone="land"] #manual-overlay .mo-body { max-height: calc(100dvh - 48px); }
html[data-phone="land"] #manual-overlay p,
html[data-phone="land"] #manual-overlay td { font-size: 10px; }

html[data-phone="land"] #duel {
  padding: 0;
  align-items: stretch;
  justify-content: stretch;
}
html[data-phone="land"] #duel-box {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  border-radius: 0;
  border-left: 0;
  border-right: 0;
  font-size: 9px;
  --duel-hand-card-w: 72px;
  --duel-hand-gap: 6px;
  --duel-lane-gap: 6px;
  --duel-zone-pad-x: 10px;
  --duel-battle-h: 48px;
  --duel-deck-h: 78px;
  --duel-hand-h: 64px;
  --duel-tip-h: 72px;
  --duel-recap-h: 96px;
}

/* Safehouse on a landscape phone — same layout, tighter chrome. */
html[data-phone="land"] #panel.safehouse-mode { width: 100%; height: 100%; max-height: none; }
html[data-phone="land"] #safehouse { font-size: 11px; }
html[data-phone="land"] #sh-head { padding: 4px 8px; gap: 6px; flex-wrap: nowrap; }
html[data-phone="land"] #sh-head .title { font-size: 12px; letter-spacing: 0.16em; }
html[data-phone="land"] #sh-head-hint,
html[data-phone="land"] #sh-pane-tabs .sh-tab-s { display: none; }
html[data-phone="land"] #sh-pane-tabs { order: 0; flex-basis: 0; min-width: 0; flex-direction: row; }
html[data-phone="land"] #sh-pane-tabs button { padding: 5px 6px; }
html[data-phone="land"] #sh-pane-tabs .sh-tab-l { font-size: 9px; letter-spacing: 0.06em; }
html[data-phone="land"] #sh-pane-tabs svg { display: none; }
html[data-phone="land"] .sh-pill { min-width: 0; padding: 3px 6px; font-size: 10px; }
html[data-phone="land"] #sh-actions button { min-height: 26px; padding: 4px 8px; font-size: 9px; }
html[data-phone="land"] .sh-view { padding: 6px 8px 8px; }
html[data-phone="land"] #sh-inventory-pane { display: block; overflow: auto; }
html[data-phone="land"] #sh-inventory-pane > .sh-panel + .sh-panel { margin-top: 8px; }
html[data-phone="land"] #sh-catalog { overflow: visible; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
html[data-phone="land"] #sh-deck-slots { --cols: 5; gap: 6px; padding: 8px; }
html[data-phone="land"] .sh-short-note { display: none; }
html[data-phone="land"] #sh-kit-mode-hint { min-height: 0; font-size: 11px; }

@media (prefers-reduced-motion: reduce) {
  html[data-phone="land"] #hud,
  html[data-phone="land"] #inspect-dock { transition: none; }
}

/* ---- Hex context radial — SELECT-mode click on a hex pops this instead of
   (in addition to) just the flat SITREP panel: an on-map ring of only the
   actions that are actually legal/relevant for that one hex, so FORTIFY/
   RELEASE/CAPTURE/RAID/SCAN/DEEP SCAN don't all have to live as permanent
   toolbar buttons. Sticky #toolbar-actions modes (SCAN/DEEP SCAN/CAPTURE/
   RAID/FORTIFY/RELEASE) are unchanged and still exist for burst/repeat
   actions across many hexes — this is purely an additive one-shot shortcut.
   Markup is built lazily in JS (ensureHexRadial() in world.js), same
   "dynamic overlay appended to body" pattern glossary.js already uses for
   #duel-gloss-tip — no static markup lives in this file, only the styling.
   Slice border colors intentionally mirror #toolbar-actions
   button[data-act="..."] above so the same verb reads the same color
   everywhere; keep both in sync if a verb's accent color ever changes. */
#hex-radial {
  position: fixed; left: 0; top: 0; width: 0; height: 0; z-index: 32;
  pointer-events: none;
}
#hex-radial .hr-slice {
  position: absolute; width: 54px; height: 54px; margin: -27px 0 0 -27px;
  border-radius: 50%; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px; background: rgba(6,16,22,0.94);
  border: 1px solid rgba(0,255,245,0.35); color: var(--chrome-text);
  font-family: var(--chrome-font); cursor: pointer; opacity: 0; transform: scale(0.4);
  transition: opacity 0.16s ease, transform 0.22s cubic-bezier(0.2,1.4,0.4,1),
              border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
  pointer-events: none;
}
#hex-radial.show .hr-slice { opacity: 1; transform: scale(1); pointer-events: auto; }
/* A panel over the hex: the radial hides until the hex is in view again (hexactions.js). */
#hex-radial.covered { visibility: hidden; }
#hex-radial.covered .hr-slice { pointer-events: none; }
#hex-radial .hr-slice:hover:not(.hr-disabled),
#hex-radial .hr-slice:focus-visible:not(.hr-disabled) {
  background: linear-gradient(160deg, rgba(20,54,68,0.95), rgba(7,22,31,0.95));
  border-color: rgba(69,255,240,0.8); box-shadow: 0 0 14px rgba(0,255,245,0.35);
  outline: none;
}
#hex-radial .hr-icon { font-size: 15px; line-height: 1; }
#hex-radial .hr-label { font-size: 7px; letter-spacing: 0.08em; font-weight: 700; text-align: center; }
#hex-radial .hr-slice.hr-disabled { cursor: help; }
#hex-radial .hr-slice.hr-disabled .hr-icon,
#hex-radial .hr-slice.hr-disabled .hr-label { opacity: 0.38; }
/* per-verb accent — same literal colors as the matching #toolbar-actions rules */
#hex-radial .hr-slice[data-act="scan"] { border-color: rgba(138,127,176,0.55); }
#hex-radial .hr-slice[data-act="deepscan"] { border-color: rgba(55,213,245,0.5); }
#hex-radial .hr-slice[data-act="fortify"] { border-color: rgba(55,245,163,0.5); }
#hex-radial .hr-slice[data-act="release"] { border-color: rgba(245,163,55,0.5); }
#hex-radial .hr-slice[data-act="capture"] { border-color: rgba(255,176,31,0.65); }
#hex-radial .hr-slice[data-act="raid"] { border-color: rgba(255,180,220,0.65); }
/* small marker pinning the ring to the actual hex it targets */
#hex-radial .hr-center {
  position: absolute; width: 8px; height: 8px; margin: -4px 0 0 -4px;
  border-radius: 50%; background: #37d5f5; box-shadow: 0 0 10px rgba(55,213,245,0.85);
  pointer-events: none; opacity: 0; transition: opacity 0.16s ease;
}
#hex-radial.show .hr-center { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  #hex-radial .hr-slice { transition: opacity 0.12s ease; transform: none !important; }
}
@media (max-width: 640px), (pointer: coarse) {
  #hex-radial .hr-slice { width: 46px; height: 46px; margin: -23px 0 0 -23px; }
  #hex-radial .hr-icon { font-size: 13px; }
  #hex-radial .hr-label { font-size: 6px; }
}

/* ---- BULLETIN — cyberpunk terminal readout, docked under the toolbar
   action buttons (see claude/tips-bulletin-design.md). Lives INSIDE
   #toolbar, appended as its last child (ensureBulletin() in world.js) so it
   always sits directly under NAVIGATE/RECON/STRIKE — this strip is
   #bulletin's alone now; #attack-cost-bar (the CAPTURE/RAID cost formula
   that used to live right here, below the buttons) was moved ABOVE
   #toolbar-main instead once the two started visually colliding in the
   same spot. A fixed-position floating banner (the first version of this
   feature) read as disconnected from the game chrome; this reads as one
   more readout on the same console. Separate on purpose from #inf-ticker
   (syndicate influence %, always-on scroll, top bar) and from
   #grid-update-banner/#node-restart-banner (full-width system alerts).
   Rotates through BULLETIN_CANDIDATES on its own (rotateBulletin() in
   world.js) — a terminal "boot line" feel: >> prompt, bracketed category
   tag color-coded per system, monospace text typed out character by
   character with a blinking cursor, a one-shot scan-sweep flash on each
   new line. SNOOZE mutes that one tip for a while without touching the
   others. Background is a deliberately distinct violet-tinted band (the
   same border/glow violet #panel itself uses) rather than the near-black
   #toolbar tone either side of it — #bulletin is appended after
   #toolbar-main (buttons+feed stay glued in #toolbar-ops), and without a
   visibly different fill this strip just disappeared into both. */
#bulletin {
  display: none; align-items: center; gap: 10px;
  padding: 7px 12px; min-height: 17px;
  border-top: 1px solid rgba(0,255,245,0.25);
  border-bottom: 1px solid #2a1a48;
  background:
    repeating-linear-gradient(180deg, rgba(0,255,245,0.035) 0px, rgba(0,255,245,0.035) 1px, transparent 1px, transparent 3px),
    linear-gradient(180deg, rgba(76,42,138,0.28) 0%, rgba(20,10,40,0.9) 100%);
  font-family: var(--chrome-font); font-size: 11px; letter-spacing: 0.03em;
  overflow: hidden; position: relative;
  --bl-accent: #37d5f5; --bl-accent-bg: rgba(55,213,245,0.12);
}
#bulletin.show { display: flex; }
#bulletin::before {
  /* one-shot scan sweep flashed across the bar whenever a new line lands */
  content: ''; position: absolute; inset: 0; pointer-events: none; width: 45%;
  background: linear-gradient(90deg, transparent, var(--bl-accent), transparent);
  opacity: 0.5; transform: translateX(-140%);
}
#bulletin.sweep::before { animation: bl-sweep 0.65s ease-out; }
@keyframes bl-sweep { to { transform: translateX(320%); } }
#bulletin .bl-prompt {
  flex-shrink: 0; color: var(--bl-accent); font-weight: 900;
  text-shadow: 0 0 8px var(--bl-accent);
  animation: bl-blink-prompt 1.1s steps(1) infinite;
}
@keyframes bl-blink-prompt { 50% { opacity: 0.3; } }
#bulletin .bl-tag {
  flex-shrink: 0; font-weight: 900; letter-spacing: 0.16em; font-size: 9px;
  padding: 2px 7px; border: 1px solid var(--bl-accent);
  color: var(--bl-accent); background: var(--bl-accent-bg);
  text-shadow: 0 0 6px var(--bl-accent);
}
#bulletin .bl-text {
  flex: 1 1 auto; min-width: 0; color: var(--chrome-text);
  text-transform: uppercase; letter-spacing: 0.02em; line-height: 1.4;
}
/* Category-expansion round: some tips jump somewhere when clicked
   (cand.action in showBulletin, world.js) — a hex, a HUD tab, the
   software rack. Underline-on-hover + pointer cursor is the only visual
   difference; layout/typing/gloss behavior is unchanged either way. */
#bulletin .bl-text.bl-clickable {
  cursor: pointer; text-decoration-line: underline; text-decoration-style: dotted;
  text-decoration-color: transparent; text-underline-offset: 3px;
  transition: text-decoration-color 0.15s ease;
}
#bulletin .bl-text.bl-clickable:hover,
#bulletin .bl-text.bl-clickable:focus-visible { text-decoration-color: var(--bl-accent); }
#bulletin .bl-text.bl-clickable:focus-visible { outline: 1px solid var(--bl-accent); outline-offset: 2px; }
#bulletin .bl-cursor {
  flex-shrink: 0; margin-left: -6px; color: var(--bl-accent); font-weight: 900;
  text-shadow: 0 0 6px var(--bl-accent);
  animation: bl-blink-cursor 0.85s step-end infinite;
}
@keyframes bl-blink-cursor { 50% { opacity: 0; } }
#bulletin .bl-snooze {
  flex-shrink: 0; margin-left: auto; background: none;
  border: 1px solid rgba(255,255,255,0.16); border-radius: 3px;
  color: var(--chrome-muted); font: inherit; text-transform: uppercase;
  font-size: 9px; letter-spacing: 0.14em; padding: 3px 8px; cursor: pointer;
}
#bulletin .bl-snooze:hover { border-color: var(--bl-accent); color: var(--bl-accent); }
@media (prefers-reduced-motion: reduce) {
  #bulletin .bl-prompt, #bulletin .bl-cursor { animation: none; }
  #bulletin.sweep::before { animation: none; opacity: 0; }
}
@media (max-width: 640px), (pointer: coarse) {
  #bulletin { font-size: 10px; padding: 6px 10px; }
  #bulletin .bl-tag { font-size: 8px; }
}
/* Generic "you were just sent here" pulse — currently only used by the
   PROGRAMS bulletin tip's click action (bulletinRevealSoftwarePanel() in
   world.js), which has no on-map hex to jump to, so it flashes the
   software rack (#software-zone) in place instead. Not #bulletin-specific;
   kept general in case a later click target needs the same nudge. */
@keyframes bl-target-flash {
  0%, 100% { box-shadow: none; }
  15%, 55% { box-shadow: 0 0 0 2px rgba(159,180,199,0.85), 0 0 16px rgba(159,180,199,0.55); }
}
.bl-flash-target { animation: bl-target-flash 1.1s ease-out; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
  .bl-flash-target { animation: none; }
}

/* Full screen on touch devices (world/fullscreen.js, 2026-10-09). */
#fs-btn {
  flex: 0 0 auto; min-width: 26px; min-height: 24px; padding: 0 6px; cursor: pointer;
  font: 700 14px/1 var(--chrome-font, monospace); color: #8ff6ff;
  background: rgba(0, 255, 245, 0.08); border: 1px solid rgba(0, 255, 245, 0.45); border-radius: 3px;
}
#fs-btn.on { color: #05080d; background: #00fff5; }
#phone-rotate .fs-gate-tip { font-style: normal; font-size: 10px; letter-spacing: 0.18em; color: #8ff6ff; opacity: 0.8; }
/* Install card (world/fullscreen.js, 2026-10-17): every visit in the browser until the game runs
   from the home screen. Sized for a landscape phone (~390px tall). */
#a2hs-hint {
  position: fixed; left: 50%; bottom: calc(env(safe-area-inset-bottom) + 12px); transform: translateX(-50%);
  z-index: 9500; width: min(94vw, 680px); padding: 10px 14px 12px; box-sizing: border-box;
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 6px 14px;
  font: 12px/1.35 var(--chrome-font, monospace); letter-spacing: 0.04em; color: #d7f4f6;
  background: rgba(5, 8, 13, 0.96); border: 1px solid rgba(0, 255, 245, 0.55); border-left: 3px solid #00fff5;
  box-shadow: 0 0 24px rgba(0, 255, 245, 0.28); animation: a2hs-in 0.4s cubic-bezier(.2,.8,.2,1) both;
}
#a2hs-hint .a2hs-head { grid-column: 1; grid-row: 1; font: 700 13px/1 'Chakra Petch', var(--chrome-display, sans-serif); letter-spacing: 0.2em; color: #00fff5; }
#a2hs-hint .a2hs-line, #a2hs-hint .a2hs-steps { grid-column: 1 / -1; }
#a2hs-hint .a2hs-line { margin: 0; color: #c4dde4; }
#a2hs-hint .a2hs-steps { margin: 0; padding: 0; list-style: none; display: flex; gap: 10px; flex-wrap: wrap; }
#a2hs-hint .a2hs-steps li { flex: 1 1 0; min-width: 120px; display: flex; align-items: center; gap: 7px; }
#a2hs-hint .a2hs-n { flex: 0 0 auto; font-size: 10px; color: #8a9fb0; }
#a2hs-hint .a2hs-ico { flex: 0 0 auto; display: grid; place-items: center; width: 34px; height: 34px; color: #ffd84a;
  background: rgba(255, 216, 74, 0.1); border: 1px solid rgba(255, 216, 74, 0.45); border-radius: 8px; }
#a2hs-hint .a2hs-ico svg { width: 22px; height: 22px; }
#a2hs-hint .a2hs-t { display: flex; flex-direction: column; min-width: 0; }
#a2hs-hint .a2hs-t b { color: #fff; font-weight: 700; }
#a2hs-hint .a2hs-t small { font-size: 10px; color: #8a9fb0; }
#a2hs-hint .a2hs-acts { grid-column: 2; grid-row: 1; display: flex; gap: 8px; }
#a2hs-hint button { min-height: 34px; padding: 0 14px; cursor: pointer; font: 700 12px/1 var(--chrome-font, monospace); letter-spacing: 0.14em; border-radius: 3px; }
#a2hs-hint .a2hs-go { color: #05080d; background: #00fff5; border: 0; }
#a2hs-hint .a2hs-later { color: #8a9fb0; background: transparent; border: 1px solid rgba(138, 159, 176, 0.5); }
@keyframes a2hs-in { from { opacity: 0; transform: translate(-50%, 16px); } }
@media (prefers-reduced-motion: reduce) { #a2hs-hint { animation: none; } }
/* Phone landscape fixes (2026-10-09): the vitals strip is wider than its slot, and centring it
   pushed RAM off the left edge where the scroll cannot reach — it starts at the left now. The
   drill mission repeats the drill dialog and sat on top of it — hidden while the dialog shows. */
html[data-phone="land"] #stats { justify-content: flex-start; }
html[data-phone="land"] #demo-cta-banner.show ~ #demo-mission { display: none; }

/* NEURAL LINK on a phone in landscape (2026-10-09): the head, the identity block and a 2×2 tab
   grid took the whole screen and left ~47 px for the content. Now the head is one thin line, the
   identity one row (name + chips, no sigil), the four tabs one row (title only) — the content gets
   most of the height. */
html[data-phone="land"] #neural-link .nl-head { padding: 3px 10px; gap: 8px; }
html[data-phone="land"] #neural-link .nl-title { font-size: 11px; letter-spacing: .26em; }
html[data-phone="land"] #neural-link .nx-wave { height: 12px; }
html[data-phone="land"] #neural-link .nl-close { width: 26px; height: 22px; min-height: 0; font-size: 12px; }
html[data-phone="land"] #neural-link .nx-ident { padding: 3px 10px; gap: 8px; align-items: center; }
html[data-phone="land"] #neural-link .nx-sigil { display: none; }
html[data-phone="land"] #neural-link .nx-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
html[data-phone="land"] #neural-link .nx-who-name { font-size: 13px; flex: none; }
html[data-phone="land"] #neural-link .nx-chips { flex-wrap: nowrap; overflow: hidden; gap: 4px; min-width: 0; }
html[data-phone="land"] #neural-link .nx-chip { padding: 1px 5px; font-size: 8px; }
html[data-phone="land"] #neural-link .nl-tabs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
html[data-phone="land"] #neural-link .nl-tab { min-height: 26px; padding: 4px 8px; border-bottom: 0; border-right: 1px solid var(--nx-line); }
html[data-phone="land"] #neural-link .nl-tab:last-child { border-right: 0; }
html[data-phone="land"] #neural-link .nl-tab .nx-ts { display: none; }
html[data-phone="land"] #neural-link .nl-tab .nx-tl { font-size: 10px; }
html[data-phone="land"] #neural-link .nl-new-tag { top: 2px; right: 2px; padding: 0 3px; font-size: 7px; }
html[data-phone="land"] #neural-link .nl-body { padding: 8px 10px 14px; }

/* The vitals strip on a phone (2026-10-09): label and value only, no bars, no hints — RAM, NRG,
   HEAT and CR all show without a hidden scroll (it was 542 px of content in a 299 px slot). */
html[data-phone="land"] #ram-meter-wrap,
html[data-phone="land"] #nrg-meter-wrap,
html[data-phone="land"] #heat-meter-wrap,
html[data-phone="land"] .cr-meter-wrap,
html[data-phone="land"] #st-energy-hint,
html[data-phone="land"] #st-credits-hint { display: none; }
html[data-phone="land"] .hud-vital-row { min-width: 0; gap: 3px; }
html[data-phone="land"] #stats { gap: 8px; }
/* A NEW tag on a narrow phone tile is a dot in the corner, not a word over the label. */
html[data-phone="land"] #toolbar-actions .cl-new-tag { top: 3px; right: 3px; width: 7px; height: 7px; padding: 0; font-size: 0; color: transparent; overflow: hidden; border-radius: 50%; }

/* Sign-up on a phone (2026-10-09): smaller head, tabs and fields, so DEPLOY is on screen without
   scrolling; the recovery channels stay below for whoever scrolls. */
html[data-phone="land"] #node-deploy-overlay .nd-panel { padding: 8px 16px 10px; }
html[data-phone="land"] #node-deploy-overlay .nd-eyebrow { display: none; }
html[data-phone="land"] #node-deploy-overlay .nd-title { font-size: 15px; margin: 0 0 6px; }
html[data-phone="land"] #node-deploy-overlay .nd-tabs { margin-bottom: 6px; }
html[data-phone="land"] #node-deploy-overlay .nd-tab { padding: 6px 8px; min-height: 0; font-size: 9px; }
html[data-phone="land"] #node-deploy-overlay .nd-field { margin-bottom: 6px; }
html[data-phone="land"] #node-deploy-overlay .nd-field label { margin-bottom: 3px; font-size: 9px; }
html[data-phone="land"] #node-deploy-overlay .nd-input-wrap input { padding: 7px 10px; font-size: 13px; }
html[data-phone="land"] #node-deploy-overlay .nd-hint { margin-top: 2px; font-size: 8px; }
html[data-phone="land"] #node-deploy-overlay .nd-deploy { margin-top: 4px; padding: 8px 12px; min-height: 0; }
html[data-phone="land"] #node-deploy-overlay .nd-close { top: 6px; right: 8px; width: 28px; height: 28px; }
html[data-phone="land"] .hud-vital-label, html[data-phone="land"] .hud-vital-value { width: auto; min-width: 0; flex: 0 0 auto; }
html[data-phone="land"] #st-nemesis-chip { display: none !important; } /* in NEURAL LINK; the strip has no room */
html[data-phone="land"] #stats { flex: 0 0 auto; overflow-x: visible; }
/* The tiles fill the rest of the bar (they stopped at ~535 of 740 and RAID read "RAI"). */
html[data-phone="land"] #toolbar-ops { flex: 1 1 auto; min-width: 0; }
html[data-phone="land"] #toolbar-actions .act-group { flex: 1 1 auto; }
html[data-phone="land"] #toolbar-actions .act-row { width: 100%; }
html[data-phone="land"] #toolbar-actions .act-row button { flex: 1 1 0; }
/* Equal tiles: a group's share follows how many tiles it shows (as on desktop, world-10-menus.css). */
html[data-phone="land"] #toolbar-actions .act-group { flex: 1 1 0; min-width: 0; }
html[data-phone="land"] body:not(.mode-demo) #toolbar-actions .act-group[data-group="navigate"]:has(button:not([hidden]):not(.cl-locked) ~ button:not([hidden]):not(.cl-locked)),
html[data-phone="land"] #toolbar-actions .act-group[data-group="strike"]:has(button:not([hidden]):not(.cl-locked) ~ button:not([hidden]):not(.cl-locked)) { flex-grow: 2; }
html[data-phone="land"] #toolbar-actions .act-row > button { flex: 1 1 0 !important; width: auto !important; min-width: 0 !important; max-width: none !important; }

/* OPERATOR and PROGRAMS as drawers on a phone (owner, 2026-10-09: "they can be buttons that open
   a popup — like PRG"). The vitals leave the bar for an OPR button that keeps the energy in sight;
   tapping it opens them, bars and all, above the toolbar. The PRG drawer is as wide as its content
   needs instead of the whole bar (its TRACE bar stretched it). */
html[data-phone="land"] #phone-op-btn {
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  flex: 0 0 auto; min-width: 38px; min-height: 32px; margin: 0; padding: 0 4px;
  font: 700 7px/1 Consolas, 'Courier New', ui-monospace, monospace; letter-spacing: 0.1em; color: #8ff6ff;
  background: #071820; border: 1px solid rgba(0, 255, 245, 0.4);
}
html[data-phone="land"] #phone-op-btn #phone-op-nrg { font-size: 9px; color: #37f5a3; letter-spacing: 0; }
html[data-phone="land"].phone-op-open #phone-op-btn { color: #04110f; background: #00fff5; border-color: #00fff5; }
html[data-phone="land"].phone-op-open #phone-op-btn #phone-op-nrg { color: #04110f; }
html[data-phone="land"] #stats { display: none; }
html[data-phone="land"].phone-op-open #stats {
  display: flex; flex-direction: column; align-items: stretch; gap: 5px;
  position: absolute; left: 6px; bottom: calc(100% + 4px); z-index: 9;
  width: min(280px, 60vw); max-height: min(60dvh, 230px); overflow: auto;
  padding: 8px 10px; box-sizing: border-box;
  background: rgba(6, 20, 28, 0.97); border: 1px solid rgba(0, 255, 245, 0.35);
}
html[data-phone="land"].phone-op-open #st-name { display: block; font-size: 9px; }
html[data-phone="land"].phone-op-open .hud-vital-row { gap: 6px; }
html[data-phone="land"].phone-op-open .hud-vital-label { flex: 0 0 34px; font-size: 7px; }
html[data-phone="land"].phone-op-open #ram-meter-wrap,
html[data-phone="land"].phone-op-open #nrg-meter-wrap,
html[data-phone="land"].phone-op-open #heat-meter-wrap,
html[data-phone="land"].phone-op-open .cr-meter-wrap { display: block; flex: 1 1 auto; width: auto; height: 5px; max-width: none; }
html[data-phone="land"].phone-op-open .hud-vital-value { margin-left: auto; font-size: 9px; }
html[data-phone="land"].phone-op-open #st-energy-hint { display: inline; font-size: 7px; }
html[data-phone="land"].phone-op-open #st-nemesis-chip:not([hidden]) { display: flex !important; }
html[data-phone="land"] #software-zone { right: auto; width: min(300px, 62vw); }
html[data-phone="land"] #software-zone .sw-trace-row .trace-demo-slot { min-width: 0; }
/* Sign-up overlay on a phone: clear of the screen's rounded corners and the island. */
html[data-phone="land"] #node-deploy-overlay {
  padding: max(6px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) max(6px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
}

/* The map on touch screens (2026-10-09): the canvas takes touch itself — one finger pans, two
   pinch-zoom the map (world/mapinput.js), not the page — and + / − buttons sit on its right edge. */
#map-zoom { display: none; }
@media (hover: none), (pointer: coarse) {
  #c, #fx { touch-action: none; }
  #map-zoom {
    display: flex; flex-direction: column; gap: 6px;
    position: absolute; right: max(8px, env(safe-area-inset-right)); top: 44px; z-index: 6; /* above the TARGET tab, which sits at mid-height */
  }
  #map-zoom button {
    width: 34px; height: 34px; padding: 0; cursor: pointer; touch-action: manipulation;
    font: 700 18px/1 var(--chrome-font, monospace); color: #8ff6ff;
    background: rgba(5, 12, 18, 0.85); border: 1px solid rgba(0, 255, 245, 0.45); border-radius: 4px;
    box-shadow: 0 0 10px rgba(0, 255, 245, 0.15);
  }
  #map-zoom button:active { background: rgba(0, 255, 245, 0.25); }
}

/* SITREP, TARGET and NEURAL LINK on a phone, finer (owner, 2026-10-09: "smaller elements so the
   information shows; now they are hard to handle"): tighter boxes and type, one-line heads. */
html[data-phone="land"] #hud .hud-head { margin: -5px -6px 4px; padding: 3px 8px 3px 10px; }
html[data-phone="land"] #hud .hud-head-title { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
html[data-phone="land"] #hud .sitrep-prompt { font-size: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
html[data-phone="land"] #clearance-chip { margin: 0 0 4px; padding: 3px 7px; font-size: 8px; gap: 4px; }
html[data-phone="land"] #hud .hud-stat-grid { gap: 3px; }
html[data-phone="land"] #hud .hud-stat-box { padding: 3px 6px 3px 8px; gap: 0; min-height: 0; }
html[data-phone="land"] #hud .hsb-label { font-size: 6.5px; }
html[data-phone="land"] #hud .hsb-value { font-size: 10px; line-height: 1.2; }
html[data-phone="land"] #hud .hsb-hint { font-size: 7px; line-height: 1.2; }
html[data-phone="land"] #inspect .sitrep-section { margin: 3px 4px; padding: 3px 6px 4px; }
html[data-phone="land"] #inspect .sitrep-section-title { margin: -3px -6px 3px; padding: 3px 6px 3px 10px; font-size: 7.5px; }
html[data-phone="land"] #inspect .sitrep-row { font-size: 7.5px; padding: 1px 0; }
html[data-phone="land"] #inspect .k, html[data-phone="land"] #inspect .sitrep-hint { font-size: 7.5px; }
html[data-phone="land"] #neural-link .nx-card { padding: 7px 10px 8px; gap: 6px; }
html[data-phone="land"] #neural-link .nx-card-h h3 { font-size: 10px; letter-spacing: .18em; }
html[data-phone="land"] #neural-link .nx-meta { font-size: 8px; }
html[data-phone="land"] #neural-link .nx-lead, html[data-phone="land"] #neural-link .nx-kv,
html[data-phone="land"] #neural-link .nx-rule, html[data-phone="land"] #neural-link .nx-hint { font-size: 9px; line-height: 1.4; }
html[data-phone="land"] #neural-link .nx-btn { min-height: 24px; padding: 3px 10px; font-size: 8.5px; }
html[data-phone="land"] #neural-link .nl-pane.active { gap: 8px; }
html[data-phone="land"] #clearance-chip .cl-lvl { font-size: 10px; }
html[data-phone="land"] #clearance-chip .cl-next { font-size: 8px; }
html[data-phone="land"] #neural-link .nx-k { font-size: 7.5px; }
html[data-phone="land"] #neural-link .nx-v { font-size: 10px; }
html[data-phone="land"] #neural-link .nx-kv { gap: 1px; }
html[data-phone="land"] #neural-link .nx-card .nx-btn { min-height: 24px; height: auto; padding: 3px 10px; }
html[data-phone="land"] #demo-cta-register { margin-top: 2px; padding: 5px 10px; font-size: 9px; letter-spacing: 0.08em; min-height: 28px; }
html[data-phone="land"] #guest-landing .gl-tag { left: max(10px, env(safe-area-inset-left)); font-size: 8px; }

/* The top bar's long layout (data-fit — public/i18n.js picks it when the labels do not fit, in any
   language or width): the utility buttons show their icon only; the name stays in the tooltip. */
#bar.fit-long .info-array button:not(#btn-lang) {
  font-size: 0 !important; letter-spacing: 0 !important; gap: 0; justify-content: center;
  min-width: 32px; padding-left: 8px !important; padding-right: 8px !important;
}
#bar.fit-long .info-array button:not(#btn-lang)::before {
  content: attr(data-icon); position: static; transform: none; width: auto; height: auto;
  border: 0; background: none !important; box-shadow: none !important; opacity: 1;
  font: 13px/1 var(--chrome-font); color: var(--chrome-muted);
}
#bar.fit-long #btn-sound.on::before { color: #37f5a3; }
#bar.fit-long #btn-manual::before, #bar.fit-long #btn-feedback::before { color: #f5a337; }
#bar.fit-long #btn-app::before { color: #37d5f5; }

/* The syndicate chips keep one row (never stacked): in the short layout the row takes the width
   it needs, so a crowded bar overflows and #bar gets fit-long (public/i18n.js data-fit). The long
   layout then shows the chips by name only (the % stays in their tooltip) and lets the row clip. */
#inf-ticker { flex: 0 1 auto; min-width: max-content; }
#inf-ticker .inf-ticker-clip, #inf-ticker .inf-ticker-track { flex-wrap: nowrap; }
#bar.fit-long #inf-ticker { min-width: 0; overflow: hidden; }
#bar.fit-long #inf-ticker .fac-chip .fac-pct { display: none; }
#bar.fit-long #build-id { display: none; }
/* The row no longer grows, so the right-hand group (language … LIVE) takes the free room itself and
   stays in the top right corner (owner, 2026-10-16: since the languages it sat right after the chips). */
#bar .bar-right { margin-left: auto; }

/* The SITREP is a solid panel, not a see-through overlay (owner, 2026-10-16: with it open he could still
   click a sector under it, and that sector's radial came up over the panel): while it is open its
   clicks stay on it. Closed, it slides away and lets the map through again (world-02-hud.css). */
html:not([data-phone="land"]):not([data-phone="port"]) #hud:not(.drawer-closed) { pointer-events: auto; }

/* The capture cost formula under the map (CAPTURE 15 + 2×1 + … = 20 NRG · distance H=… · empire tax …) is
   gone (owner, 2026-10-16: it said nothing a player needs); the CAPTURE button shows the cost and why
   a target is out of reach. */
#attack-cost-bar, #attack-cost-bar.show { display: none !important; }

/* Phone: TARGET and NEURAL LINK open full screen (owner, 2026-10-16: in a side drawer they showed
   almost nothing); TARGET waits as a strip on the right edge (like SITREP) that lights up when it has news
   (world.js), and its ✕ closes it. */
html[data-phone="land"] #viewport { --nl-w: 100%; }
html[data-phone="land"] #neural-link { border-left: 0; }
html[data-phone="land"] #inspect-dock { left: 0; right: 0; top: 0; bottom: 0; max-height: none; align-items: stretch; z-index: 46; }
html[data-phone="land"] #inspect { width: 100%; height: 100%; max-height: none; overflow-y: auto; background-color: #070a12; }
/* the TARGET strip: the same vertical strip as SITREP's, on the right edge */
html[data-phone="land"] #phone-peeks #phone-target-btn.has-news { animation: phone-target-news 1.1s ease-in-out infinite; border-color: #ffb01f; color: #ffcf7a; }
html[data-phone="land"] #phone-peeks #phone-target-btn.has-news::after {
  content: ''; position: absolute; top: 4px; left: 50%; width: 6px; height: 6px; margin-left: -3px; border-radius: 50%;
  background: #ffb01f; box-shadow: 0 0 6px #ffb01f;
}
@keyframes phone-target-news { 50% { box-shadow: 0 0 14px rgba(255, 176, 31, 0.7); } }
/* An open panel keeps its strip at its inner edge, to fold it away again (owner, 2026-10-16). */
html[data-phone="land"].phone-target-open #phone-peeks #phone-target-btn { right: 50vw; }
html[data-phone="land"].phone-sitrep-open #phone-peeks #phone-sitrep-btn { left: 50vw; }

/* iOS Safari enlarges text by itself in landscape ("text inflation"), and not evenly — on the owner's
   iPhone some labels came out far bigger than set, others not (2026-10-16). Every size here is meant
   as written. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* Phone, finer (owner, 2026-10-16): the SITREP scrolls to its active operations; the tips strip, the
   map's zoom and style toggles and the action buttons take less room; the top bar sits a little off
   the screen's top edge, where Safari takes the first touch for itself. */
html[data-phone="land"] #hud .hud-body { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; touch-action: pan-y; }
html[data-phone="land"] #hud { touch-action: pan-y; }
html[data-phone="land"] #bulletin { padding: 2px 8px; min-height: 0; gap: 6px; font-size: 8px; }
html[data-phone="land"] #bulletin .bl-tag { font-size: 7px; padding: 1px 4px; letter-spacing: 0.12em; }
html[data-phone="land"] #bulletin .bl-text { line-height: 1.25; }
html[data-phone="land"] #bulletin .bl-snooze { font-size: 7px; padding: 1px 5px; }
:root[data-phone="land"] #map-style .ms-seg button { padding: 3px 6px; font-size: 8px; letter-spacing: 0.08em; }
:root[data-phone="land"] #map-style .ms-layers label { font-size: 8px; }
:root[data-phone="land"] #map-style { gap: 4px; right: 6px; bottom: 6px; }
html[data-phone="land"] #toolbar-actions .act-btn-inner { min-height: 26px; }
/* iOS keeps the top edge of the screen for its own swipe-down gesture: a tap in the first ~20 px is
   held back or dropped (owner, 2026-10-16: the top buttons caught only at their lower part). The bar
   sits clear of that edge and its buttons are taller, so most of each button is where a tap counts. */
html[data-phone="land"] #bar { padding-top: 14px; padding-bottom: 3px; }
html[data-phone="land"] #bar button, html[data-phone="land"] #bar .live { min-height: 30px; touch-action: manipulation; }
/* …and the whole SITREP scrolls as one, instead of the operations list being squeezed into a slot a
   few pixels tall under the stats (it had its own scroll, 27 px high on a phone). */
html[data-phone="land"] #hud .hud-body > * { flex: none; }
html[data-phone="land"] #hud .hud-events { overflow: visible; max-height: none; }
html[data-phone="land"] #hud .event-card .ev-effect,
html[data-phone="land"] #hud .event-card .ev-loc,
html[data-phone="land"] #hud .event-card .hud-clock { font-size: 8px; line-height: 1.35; }
html[data-phone="land"] #hud .event-card .ev-icon { font-size: 10px; }

/* SAFEHOUSE on a phone, finer (owner, 2026-10-16: "much finer, smaller pieces, more on screen"):
   tighter panels, a small mode switch, and the whole 10-card kit in one row of small cards — cost,
   name and stats; the full text stays a long press away and in the catalogue below. */
html[data-phone="land"] .sh-panel { padding: 8px 10px 10px; }
html[data-phone="land"] #sh-loadout-label { font-size: 11px; letter-spacing: 0.14em; }
html[data-phone="land"] #sh-loadout-sub { font-size: 9px; }
html[data-phone="land"] #sh-kit-mode { padding: 2px; }
html[data-phone="land"] #sh-kit-mode button { padding: 3px 8px; min-height: 0; font-size: 9px; line-height: 1.25; }
html[data-phone="land"] #sh-kit-mode button * { font-size: inherit; }
html[data-phone="land"] #sh-kit-mode-hint { font-size: 9px; line-height: 1.35; }
html[data-phone="land"] #sh-deck-slots { --cols: 10; gap: 4px; padding: 6px; }
html[data-phone="land"] #sh-deck-slots .sh-bay { gap: 2px; }
html[data-phone="land"] #sh-deck-slots .sh-socket { min-height: 0; aspect-ratio: 5 / 7; }
html[data-phone="land"] #sh-deck-slots .sh-pc { padding: 4px 4px 3px; gap: 2px; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pd { display: none; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pk { font-size: 6px; letter-spacing: 0.06em; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pt { font-size: 6px; padding: 0 2px; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pn { font-size: 8px; line-height: 1.15; min-height: 2.3em; }
html[data-phone="land"] #sh-deck-slots .sh-pc .ps, html[data-phone="land"] #sh-deck-slots .sh-pc .ps * { font-size: 9px; }
html[data-phone="land"] #sh-deck-slots .sh-bay-lbl { font-size: 6px; }
html[data-phone="land"] #sh-catalog { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 6px; }
html[data-phone="land"] #sh-kit-status { font-size: 9px; }
html[data-phone="land"] #sh-deck-stats, html[data-phone="land"] #sh-deck-stats * { font-size: 8px; }
html[data-phone="land"] #sh-avg-thr { font-size: 11px; }
html[data-phone="land"] #safehouse .sh-panel button:not(.sh-socket):not(.sh-pc) { padding: 3px 8px; min-height: 0; font-size: 8px; letter-spacing: 0.08em; }
html[data-phone="land"] #safehouse input[type="search"], html[data-phone="land"] #safehouse input[type="text"] { padding: 4px 8px; font-size: 10px; min-height: 0; }
html[data-phone="land"] #sh-catalog .sh-deck-card-wrap { min-height: 0; }
html[data-phone="land"] #sh-catalog .sh-deck-card-wrap * { font-size: 8px; line-height: 1.3; }
html[data-phone="land"] #sh-catalog .sh-deck-card-wrap .sh-stat { font-size: 9px; }
html[data-phone="land"] #sh-catalog .sh-deck-card-wrap > * { padding: 5px 6px; }
html[data-phone="land"] #sh-catalog { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); }
html[data-phone="land"] #sh-catalog .sh-deck-card-wrap > *, html[data-phone="land"] #sh-catalog .sh-deck-card-wrap > * > * { min-height: 0; height: auto; }

/* Phone, round 2 (owner, 2026-10-16) ----------------------------------------------------------- */
/* 1. SOUND is an icon (its name stays in the long-press tip). */
html[data-phone="land"] #btn-sound { font-size: 0 !important; letter-spacing: 0; gap: 0; padding: 2px 8px; min-width: 28px; justify-content: center; }
html[data-phone="land"] #btn-sound::before {
  content: ''; width: 15px; height: 15px; box-shadow: none !important; background: var(--chrome-muted) !important;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round'><path d='M2 6h3l4-3v10l-4-3H2z' fill='black'/><path d='M11 6l4 4M15 6l-4 4'/></svg>") center / contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round'><path d='M2 6h3l4-3v10l-4-3H2z' fill='black'/><path d='M11 6l4 4M15 6l-4 4'/></svg>") center / contain no-repeat;
}
html[data-phone="land"] #btn-sound.on::before {
  background: #37f5a3 !important;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round'><path d='M2 6h3l4-3v10l-4-3H2z' fill='black'/><path d='M11 5.5a3.5 3.5 0 0 1 0 5M12.8 3.6a6.2 6.2 0 0 1 0 8.8'/></svg>") center / contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round'><path d='M2 6h3l4-3v10l-4-3H2z' fill='black'/><path d='M11 5.5a3.5 3.5 0 0 1 0 5M12.8 3.6a6.2 6.2 0 0 1 0 8.8'/></svg>") center / contain no-repeat;
}
/* 2. SITREP and TARGET open to half the screen from their edge strips, not full screen; SITREP's
   operations finer, their head wrapping instead of overlapping. */
html[data-phone="land"] #hud { width: 50vw; }
html[data-phone="land"] #inspect-dock { left: auto; right: 0; width: 50vw; }
html[data-phone="land"] #hud .event-card { font-size: 8px; }
html[data-phone="land"] #hud .event-card .ev-title { font-size: 8px; letter-spacing: 0.08em; line-height: 1.25; }
html[data-phone="land"] #hud .event-card .hud-clock { font-size: 7px; padding: 1px 4px; white-space: nowrap; }
html[data-phone="land"] #hud .event-card > :first-child { flex-wrap: wrap; row-gap: 2px; }
/* 3. No + / − on a phone: pinch zooms the map. */
html[data-phone="land"] #map-zoom { display: none !important; }
/* 4. SAFEHOUSE: the kit on two rows of five, roomy enough for each card's text; the head's tabs as
   icons (the open one keeps its name) and its actions as icons. */
html[data-phone="land"] #sh-deck-slots { --cols: 5; gap: 5px; }
html[data-phone="land"] #sh-deck-slots .sh-socket { aspect-ratio: 6 / 5; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pd { display: block; font-size: 7px; line-height: 1.3; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pn { font-size: 9px; min-height: 0; }
html[data-phone="land"] #sh-deck-slots .sh-pc .pk, html[data-phone="land"] #sh-deck-slots .sh-pc .pt { font-size: 7px; }
html[data-phone="land"] #sh-pane-tabs svg { display: inline-block; width: 14px; height: 14px; }
html[data-phone="land"] #sh-actions button { font-size: 0 !important; min-width: 30px; padding: 4px 8px; }
/* drawn icons with some body (owner: a thin glyph read weak): a floppy saves, a folded map goes back */
html[data-phone="land"] #sh-actions button { display: inline-flex; align-items: center; justify-content: center; gap: 3px; }
html[data-phone="land"] #sh-save::before, html[data-phone="land"] #sh-save-return::before, html[data-phone="land"] #sh-back-map::before,
html[data-phone="land"] #sh-save-return::after {
  content: ''; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: var(--ico) center / contain no-repeat; mask: var(--ico) center / contain no-repeat;
}
html[data-phone="land"] #sh-save::before, html[data-phone="land"] #sh-save-return::before { --ico: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round'><path d='M2.5 2.5h8.5l2.5 2.5v8.5h-11z' fill='black' fill-opacity='.25'/><path d='M5 2.5v3.5h5.5V2.5'/><rect x='4.5' y='9' width='7' height='4.5'/></svg>"); }
html[data-phone="land"] #sh-save-return::after, html[data-phone="land"] #sh-back-map::before { --ico: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round'><path d='M1.5 3.5l4-1.5 5 1.5 4-1.5v10.5l-4 1.5-5-1.5-4 1.5z' fill='black' fill-opacity='.25'/><path d='M5.5 2v10.5M10.5 3.5V14'/></svg>"); }
/* 5. A tighter radial with smaller slices. */
html[data-phone="land"] #hex-radial .hr-slice { width: 38px; height: 38px; margin: -19px 0 0 -19px; }
html[data-phone="land"] #hex-radial .hr-icon { font-size: 11px; }
html[data-phone="land"] #hex-radial .hr-label { font-size: 5px; }
html[data-phone="land"] #hud .event-card .ev-timer, html[data-phone="land"] #hud .event-card .ev-timer * { font-size: 7px; padding: 1px 4px; letter-spacing: 0.06em; }
/* The SAFEHOUSE body never grows past the screen (owner, 2026-10-16: opened on DEFENSE from the
   OPERATOR/SITREP links, a wide piece pushed its column to ~960 px — cut-off cards, a sideways scroll). */
html[data-phone="land"] #sh-main { grid-template-columns: minmax(0, 1fr); min-width: 0; }
html[data-phone="land"] #sh-main > * { min-width: 0; }

/* The version chip is for the host, not the players (owner, 2026-10-16): shown only with ?build in the address. */
html:not(.show-build) #build-id { display: none !important; }

/* Touch: a double tap must not zoom the page (owner, 2026-10-16: missed taps on RELOAD zoomed
   the whole site, and the zoom stayed after the reload). Pinch is stopped in world/fullscreen.js. */
@media (hover: none), (pointer: coarse) {
  html, body { touch-action: manipulation; }
}
/* The reload banner on a phone: below iOS's top-edge gesture zone, and the whole strip is a button. */
html[data-phone="land"] #grid-update-banner { padding: 16px 16px 8px; cursor: pointer; touch-action: manipulation; }
html[data-phone="land"] #grid-update-reload { min-height: 34px; padding: 6px 22px; }

/* ?lite — less-text preview (owner, 2026-10-16). ACTIVE OPS: a quiet list, one row per event
   (events.js liteEventCardsHtml) — no per-row gradient or cut corners, the event's colour only on its
   left edge and icon; the description is the tooltip, the HP bar a thin line under the row. */
html.lite #hud .event-card.lite-ev {
  margin-top: 0; padding: 7px 8px 7px 10px; clip-path: none; cursor: pointer; text-decoration: none;
  background: transparent; border: 0; border-left: 2px solid var(--ev-color, #3a2170);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
html.lite #hud .event-card.lite-ev:first-child { border-top: 1px solid rgba(255, 255, 255, 0.06); }
html.lite #hud .event-card.lite-ev:hover { background: color-mix(in srgb, var(--ev-color, #37d5f5) 12%, transparent); border-color: rgba(255, 255, 255, 0.06); border-left-color: var(--ev-color, #37d5f5); }
html.lite #hud .event-card.lite-ev .ev-head { align-items: center; gap: 9px; }
html.lite #hud .event-card.lite-ev .ev-icon { width: 18px; height: 18px; font-size: 10px; }
html.lite #hud .event-card.lite-ev .ev-title { flex: 1 1 auto; min-width: 0; font-size: 11px; line-height: 1.2; letter-spacing: 0.1em;
  color: #e3ecf3 !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.lite #hud .event-card.lite-ev .ev-count { color: var(--ev-color, #8aa0b0); font-size: 10px; margin-left: 5px; }
html.lite #hud .event-card.lite-ev .ev-timer { padding: 0; border: 0; background: none; font-size: 10px; letter-spacing: 0.06em;
  color: #8fa3b3; flex-shrink: 0; }
html.lite #hud .event-card.lite-ev .ev-go { flex-shrink: 0; width: 10px; text-align: center; color: var(--ev-color, var(--chrome-cyan));
  font-size: 15px; line-height: 1; opacity: 0.55; }
html.lite #hud .event-card.lite-ev:hover .ev-go { opacity: 1; }
html.lite #hud .event-card.lite-ev .ev-hp-track { height: 2px; margin: 6px 0 0 27px; border: 0; background: rgba(255, 255, 255, 0.08); }
html.lite #hud .event-card.lite-ev .ev-hp-label, html.lite #hud .event-card.lite-ev .ev-hp-label-row { display: none; }
/* TARGET in ?lite: the duel as three numbers, DETAILS folded under a clickable divider. */
html.lite #inspect-dock .lite-goals { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
html.lite #inspect-dock .lite-goals b { font-size: 15px; }
html.lite #inspect-dock details.sitrep-ref-fold > summary { cursor: pointer; list-style: none; }
html.lite #inspect-dock details.sitrep-ref-fold > summary::-webkit-details-marker { display: none; }
html.lite #inspect-dock details.sitrep-ref-fold > summary::after { content: ' ▸'; }
html.lite #inspect-dock details.sitrep-ref-fold[open] > summary::after { content: ' ▾'; }
/* TARGET in ?lite: the capture is a button that says what it costs; what is special about the hex
   (shields, fort, district…) sits in the brief as plain rows. */
html.lite #inspect-dock .lite-cta { display: flex; width: 100%; align-items: baseline; justify-content: space-between; gap: 10px;
  margin: 2px 0 4px; padding: 10px 12px; cursor: pointer; font: 700 13px/1.1 'Chakra Petch', var(--chrome-display);
  letter-spacing: 0.12em; color: #0b0d12; background: #f5c842; border: 0; }
html.lite #inspect-dock .lite-cta span { font: 600 11px/1 var(--chrome-font); letter-spacing: 0.04em; opacity: 0.8; }
html.lite #inspect-dock .lite-cta:hover { filter: brightness(1.12); }
html.lite #inspect-dock .sitrep-brief-rows { margin-top: 6px; }
/* SITREP tiles in ?lite: a tile without a second line is shorter; the grid stays 3 × 2. */
html.lite #hud .hud-stat-box { padding-top: 8px; padding-bottom: 8px; justify-content: flex-start; }
html.lite #hud .hsb-value { font-size: 17px; }
/* ACTIVE OPS in ?lite, two lines (owner: SITREP has room now): a bigger icon beside the name and
   timer, with where it is (or the boss's HP) underneath. */
html.lite #hud .event-card.lite-ev { padding: 10px 10px 10px 12px; }
html.lite #hud .event-card.lite-ev .ev-head { align-items: center; gap: 11px; }
html.lite #hud .event-card.lite-ev .ev-icon { width: 30px; height: 30px; font-size: 15px; }
html.lite #hud .event-card.lite-ev .ev-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
html.lite #hud .event-card.lite-ev .ev-line1 { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
html.lite #hud .event-card.lite-ev .ev-title { font-size: 12px; }
html.lite #hud .event-card.lite-ev .ev-where { font-size: 10px; letter-spacing: 0.04em; color: #7f95a6;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.lite #hud .event-card.lite-ev .ev-where .hexref, html.lite #hud .event-card.lite-ev .ev-where a { color: #8fd6ff; }
html.lite #hud .event-card.lite-ev .ev-hp-track { margin: 2px 0 0; height: 3px; }
html.lite #hud .event-card.lite-ev .ev-go { font-size: 18px; }
/* ?lite: the bounty-on-you and blueprints rows are information, not a jump. */
html.lite #hud .event-card.lite-ev.lite-static { cursor: default; pointer-events: auto; }
html.lite #hud .event-card.lite-ev.lite-static:hover { background: transparent; }
/* ?lite ACTIVE OPS — hacker motion (owner, 2026-10-17: "too static, as if from another game"). Same
   colours; terminal type, a scan line running down the list, flowing HP, new rows decrypt in
   (ops-fx.js), a blinking LIVE dot. Loops share one clock across re-renders (ops-fx.js). */
html.lite #hud .hud-ops-rule {
  background: repeating-linear-gradient(90deg, rgba(0,255,245,0.55) 0 6px, transparent 6px 10px);
  -webkit-mask: linear-gradient(90deg, #000, transparent); mask: linear-gradient(90deg, #000, transparent);
  background-size: 20px 1px; animation: ops-flow 1.2s linear infinite;
}
html.lite #hud .hud-ops-count::before { content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 6px;
  border-radius: 50%; background: #f55858; box-shadow: 0 0 6px #f55858; vertical-align: 1px; animation: ops-blink 1.6s steps(1) infinite; }
html.lite #hud .hud-events { background-image: repeating-linear-gradient(0deg, rgba(0,255,245,0.025) 0 1px, transparent 1px 3px); }
html.lite #hud .event-card.lite-ev { position: relative; overflow: hidden; }
html.lite #hud .event-card.lite-ev::after { content: ''; position: absolute; inset: 0 auto 0 0; width: 45%; pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ev-color, #37d5f5) 24%, transparent), transparent);
  transform: translateX(-110%); animation: ops-scan 7s linear infinite; animation-delay: calc(var(--i, 0) * 0.14s); }
html.lite #hud .event-card.lite-ev .ev-title { font: 400 13px/1.2 var(--chrome-font); letter-spacing: 0.14em;
  text-shadow: 0 0 8px color-mix(in srgb, var(--ev-color, #37d5f5) 45%, transparent); }
html.lite #hud .event-card.lite-ev .ev-timer { font-family: var(--chrome-font); font-size: 11px; color: color-mix(in srgb, var(--ev-color, #8fa3b3) 55%, #c8d6e0); }
html.lite #hud .event-card.lite-ev .ev-timer::before { content: '['; opacity: 0.45; margin-right: 2px; }
html.lite #hud .event-card.lite-ev .ev-timer::after { content: ']'; opacity: 0.45; margin-left: 2px; }
html.lite #hud .event-card.lite-ev .ev-timer:has(.hud-clock:empty) { display: none; }
html.lite #hud .event-card.lite-ev .ev-where::before { content: '└ '; color: color-mix(in srgb, var(--ev-color, #7f95a6) 60%, transparent); }
html.lite #hud .event-card.lite-ev .ev-where:has(+ .ev-where)::before { content: '├ '; }
html.lite #hud .event-card.lite-ev.backdoor .ev-where:last-child span::after { content: '▌'; margin-left: 3px; animation: ops-blink 1s steps(1) infinite; }
/* the icon: a sheen crosses the hex now and then */
html.lite #hud .event-card.lite-ev .ev-icon { position: relative; overflow: hidden; }
html.lite #hud .event-card.lite-ev .ev-icon::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 35%, rgba(255,255,255,0.55) 50%, transparent 65%);
  transform: translateX(-120%); animation: ops-sheen 7s ease-in-out infinite; animation-delay: calc(var(--i, 0) * 0.14s + 0.3s); }
/* HP: segmented, with data flowing through it */
html.lite #hud .event-card.lite-ev .ev-hp-track { height: 4px; background: repeating-linear-gradient(90deg, rgba(255,255,255,0.09) 0 5px, transparent 5px 7px); }
html.lite #hud .event-card.lite-ev .ev-hp-fill { position: relative; overflow: hidden; box-shadow: 0 0 8px color-mix(in srgb, var(--ev-color, #a35cff) 60%, transparent);
  background: repeating-linear-gradient(90deg, var(--ev-color, #a35cff) 0 5px, transparent 5px 7px); }
html.lite #hud .event-card.lite-ev .ev-hp-fill::after { content: ''; position: absolute; inset: 0; width: 30%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.7), transparent); animation: ops-hp 2.4s linear infinite; }
/* hover: the name glitches, the arrow runs */
html.lite #hud .event-card.lite-ev:hover .ev-title,
html.lite #hud .event-card.lite-ev.ev-glitch .ev-title { animation: ops-glitch 0.32s steps(2) 1; }
html.lite #hud .event-card.lite-ev:hover .ev-go { animation: ops-go 0.7s ease-in-out infinite; }
/* under five minutes: the timer goes red and blinks */
html.lite #hud .event-card.lite-ev.ev-urgent .ev-timer { color: #ff5a6e; text-shadow: 0 0 8px rgba(255,90,110,0.7); animation: ops-blink 1s steps(1) infinite; }
/* a row that just appeared: wipes in, its name decrypts (ops-fx.js) */
html.lite #hud .event-card.lite-ev.ev-in { animation: ops-in 0.45s cubic-bezier(.2,.8,.2,1) both; animation-delay: var(--in-d, 0s); }
@keyframes ops-flow { to { background-position: 20px 0; } }
@keyframes ops-blink { 50% { opacity: 0.2; } }
@keyframes ops-scan { 0% { transform: translateX(-110%); } 14%, 100% { transform: translateX(330%); } }
@keyframes ops-sheen { 0% { transform: translateX(-120%); } 10%, 100% { transform: translateX(120%); } }
@keyframes ops-hp { from { transform: translateX(-100%); } to { transform: translateX(340%); } }
@keyframes ops-go { 50% { transform: translateX(3px); } }
@keyframes ops-in { from { opacity: 0; transform: translateX(-12px); clip-path: inset(0 100% 0 0); } to { opacity: 1; transform: none; clip-path: inset(0 0 0 0); } }
@keyframes ops-glitch {
  0% { transform: translateX(-2px); text-shadow: 2px 0 rgba(255,0,90,0.8), -2px 0 rgba(0,255,245,0.8); }
  50% { transform: translateX(2px); text-shadow: -2px 0 rgba(255,0,90,0.8), 2px 0 rgba(0,255,245,0.8); }
  100% { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  html.lite #hud .hud-ops-rule, html.lite #hud .hud-ops-count::before, html.lite #hud .event-card.lite-ev,
  html.lite #hud .event-card.lite-ev *, html.lite #hud .event-card.lite-ev::after, html.lite #hud .event-card.lite-ev *::after { animation: none !important; }
}
/* the phone rules shrink every event clock to 7px for the old wordy cards; a lite row keeps its own size */
html.lite #hud .event-card.lite-ev .ev-timer .hud-clock { font-size: inherit; padding: 0; letter-spacing: inherit; }
/* Phone: the head's glow tab sat at 16px over a title that starts at 10px and covered "SI" of
   SITREP — a narrower tab at the edge, the title after it. */
html[data-phone="land"] #hud .hud-head { padding-left: 20px; }
html[data-phone="land"] #hud .hud-head::before { left: 8px; width: 5px; top: 5px; bottom: 5px; box-shadow: 0 0 8px var(--chrome-cyan); }
/* SITREP's CR tile (lite, 2026-10-17): in BREACH's place; a click opens the LEDGER. */
#hud .hud-stat-box.hsb-cr { cursor: pointer; text-decoration: none; }
#hud .hud-stat-box.hsb-cr:hover { background: rgba(255, 211, 106, 0.08); border-color: rgba(255, 211, 106, 0.45); }
#hud .hud-stat-box.hsb-cr .cr-ledger-ico { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: grid; place-items: center;
  width: 22px; height: 22px; color: #ffd36a; opacity: 0.7; }
#hud .hud-stat-box.hsb-cr .cr-ledger-ico svg { width: 18px; height: 18px; }
#hud .hud-stat-box.hsb-cr:hover .cr-ledger-ico { opacity: 1; }
#hud .hud-stat-box.hsb-cr .hsb-value { padding-right: 24px; }
