/* NETWAR — world.html styles, part 7 of 9: Training banner, demo chrome, clearance HUD, blocking popups, abandon dialog.
   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. */
/* Demo-first onboarding — see claude/demo-onboarding-design.md. Shown instead of
   #deploy-banner for a coreless GUEST only (updateDeployUi() in world.js) — a
   real coreless operator still sees the normal green DEPLOY banner above. Cyan,
   not green, so the two are never visually confused. */
#demo-cta-banner { display: none; position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  z-index: 25; max-width: min(420px, 92%); padding: 14px 20px; background: rgba(8,14,20,0.94);
  border: 1px solid #37d5f5; box-shadow: 0 0 24px rgba(55,213,245,0.25);
  font-size: 11px; line-height: 1.5; text-align: center; overflow: hidden; }
/* Visual polish round 2 — same cyan boot-in + border-pulse + scanline sweep
   used on the 5 blocking popups (see popup-boot-in / popup-border-pulse-cyan
   / popup-scan-sweep above), applied here too so this banner (shown across
   all three demo training rounds) reads consistently with them. No .breaching
   full-screen flicker here on purpose — this is a persistent HUD banner, not
   a one-shot blocking modal, so only the calmer "blue style" applies. */
#demo-cta-banner.show {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  /* Only the continuous glow here, not the one-shot entrance — .show gets
     added while the banner is still hidden behind the boot-chrome
     cinematic (see the boot-chrome rules above), so an entrance keyed off
     .show alone would play out fully, invisibly, before the boot sequence
     ever reveals it. The entrance lives on .fx-boot-in instead, added by
     triggerBannerBootIn() in world.js at the exact moment the banner
     actually becomes visible. The pulse doesn't have this problem — it's
     an infinite loop, so it doesn't matter when it started. */
  animation: popup-border-pulse-cyan 2.6s ease-in-out infinite 0.5s;
}
#demo-cta-banner.show.fx-boot-in {
  /* NOT popup-boot-in — this banner centers itself via left:50% +
     transform:translateX(-50%) (the other 4 popups center via a flex
     parent instead), and popup-boot-in's own transform keyframes would
     overwrite that translateX(-50%), shoving the banner off to the right.
     popup-boot-in-centered bakes translateX(-50%) into every keyframe so
     the entrance lift/scale composes with the centering instead of
     replacing it. */
  animation: popup-boot-in-centered 0.5s cubic-bezier(0.2,0.9,0.25,1) both,
             popup-border-pulse-cyan 2.6s ease-in-out infinite 0.5s;
}
#demo-cta-banner.show::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 40%;
  background: linear-gradient(180deg, rgba(55,213,245,0.07), rgba(55,213,245,0));
  animation: popup-scan-sweep 3.2s linear infinite; pointer-events: none;
}
#demo-cta-banner.show::after {
  content: ''; position: absolute; inset: 0;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,0) 0px, rgba(0,0,0,0) 2px, rgba(0,0,0,0.16) 3px);
  pointer-events: none; opacity: 0.5;
}
#demo-cta-banner.show > * { position: relative; z-index: 1; }
@media (prefers-reduced-motion: reduce) {
  #demo-cta-banner.show,
  #demo-cta-banner.show.fx-boot-in,
  #demo-cta-banner.show::before {
    animation: none;
  }
}

#demo-cta-banner .demo-access-badge {
  display: block; font-size: 9px; letter-spacing: 0.1em; color: #f5a337;
  margin-bottom: 4px; text-transform: uppercase;
}
#demo-cta-banner strong { color: #37d5f5; letter-spacing: 1.5px; display: block; font-size: 12px; }
#demo-cta-banner p { margin: 3px 0 0; color: #8a9fb0; }
#demo-cta-btn {
  margin-top: 4px; padding: 10px 22px; background: rgba(55,213,245,0.14);
  border: 1px solid #37d5f5; color: #cdf6ff; font: inherit; font-size: 12px;
  letter-spacing: 1.5px; font-weight: 700; cursor: pointer; pointer-events: auto;
  transition: background 0.15s ease, box-shadow 0.15s ease;
}
#demo-cta-btn:hover, #demo-cta-btn:focus-visible {
  background: rgba(55,213,245,0.28); box-shadow: 0 0 18px rgba(55,213,245,0.35);
}
#demo-cta-banner .demo-cta-links { display: flex; justify-content: center; flex-wrap: wrap; gap: 4px 16px; }
#demo-cta-intro[hidden] { display: none; }
#demo-cta-restore, #demo-cta-intro {
  margin-top: 2px; background: none; border: none; padding: 0; cursor: pointer;
  pointer-events: auto; color: #6a8a98; font: inherit; font-size: 10px;
  letter-spacing: 0.4px; text-decoration: underline; text-underline-offset: 2px;
}
#demo-cta-restore:hover, #demo-cta-restore:focus-visible, #demo-cta-intro:hover, #demo-cta-intro:focus-visible { color: #37d5f5; }
/* Phase A — demo chrome strip (mission line under CTA) */
#demo-mission {
  display: none; position: absolute; top: 118px; left: 50%; transform: translateX(-50%);
  z-index: 24; max-width: min(440px, 94%); padding: 8px 14px;
  background: rgba(6,12,18,0.88); border: 1px solid rgba(55,213,245,0.35);
  font-size: 10px; letter-spacing: 0.08em; color: #8ec8d8; text-align: center;
  pointer-events: none;
}
body.mode-demo #demo-mission.show { display: block; }
/* Phase B — conversion overlay after 3 training rounds */
#demo-conversion {
  display: none; position: absolute; inset: 0; z-index: 80;
  align-items: center; justify-content: center;
  background: rgba(4,8,14,0.82); pointer-events: auto;
}
#demo-conversion.show { display: flex; }
#demo-conversion-box {
  max-width: min(420px, 92%); padding: 22px 24px; text-align: center;
  background: rgba(8,14,20,0.96); border: 1px solid #37d5f5;
  box-shadow: 0 0 28px rgba(55,213,245,0.28);
  font-family: var(--chrome-font);
}
#demo-conversion-box h3 {
  margin: 0 0 10px; font-family: var(--chrome-display); font-size: 13px;
  letter-spacing: 0.16em; color: #37d5f5;
}
#demo-conversion-box p { margin: 0 0 16px; font-size: 11px; line-height: 1.55; color: #8a9fb0; }
#demo-conversion-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
#demo-conversion-register, #demo-conversion-restore {
  padding: 10px 18px; font: inherit; font-size: 11px; letter-spacing: 0.14em;
  font-weight: 700; cursor: pointer; border: 1px solid #37d5f5;
}
#demo-conversion-register {
  background: rgba(55,213,245,0.18); color: #cdf6ff;
}
#demo-conversion-register:hover { background: rgba(55,213,245,0.32); }
#demo-conversion-restore {
  background: transparent; color: #8a9fb0;
}
#demo-conversion-restore:hover { color: #37d5f5; }
/* Phase A — mode-demo: strip live chrome; keep map / minimal bar / duel / demo banners */
body.mode-demo #neural-link,
body.mode-demo #btn-neural-link,
body.mode-demo #feed-wrap,
body.mode-demo #btn-safehouse,
body.mode-demo #st-heat-chip,
body.mode-demo #inf-ticker,
body.mode-demo #hud .hud-events,
body.mode-demo #hud .hud-season,
body.mode-demo #hud .hud-ops-title,
body.mode-demo #inspect-dock,
body.mode-demo #phone-peeks,
body.mode-demo #clearance-chip {
  display: none !important;
}
body.mode-demo #hud .hud-stat-box:nth-child(n+3) { display: none; }
body.mode-demo #software-zone .sw-trace-row,
body.mode-demo #software-preview { opacity: 0.35; pointer-events: none; }
/* D-UI — clearance HUD chip + NL roadmap + softlock / beat / holding teach */
#clearance-chip {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 6px 0 4px; padding: 6px 10px; width: 100%; box-sizing: border-box;
  background: rgba(8,22,36,0.55); border: 1px solid rgba(55,213,245,0.4);
  color: var(--chrome-cyan); font: inherit; font-size: 10px; letter-spacing: 0.12em;
  cursor: pointer; text-align: left; pointer-events: auto;
}
#clearance-chip:hover { border-color: var(--chrome-cyan); background: rgba(55,213,245,0.12); }
#clearance-chip .cl-lvl {
  font-family: var(--chrome-display); font-weight: 700; font-size: 11px; flex-shrink: 0;
}
#clearance-chip .cl-next {
  color: #8a9fb0; font-size: 9px; letter-spacing: 0.06em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* D-I5 (ACTION_PLAN_FIRST_LOOP.md §9.6) — ONE frozen next-step control, not a
   toolbar-wide grey-out (still forbidden — see §0 / non-goal #11). Reuses the
   existing clearance-chip and its live nextStepProgress() label; no second
   source of truth for "what's next". */
#clearance-chip.cl-frozen {
  filter: grayscale(0.85) brightness(0.72);
  position: relative;
}
#clearance-chip.cl-frozen::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(115deg, rgba(160,210,230,0.10) 0 2px, transparent 2px 7px);
  mix-blend-mode: overlay;
}
#clearance-chip.cl-thaw { filter: none; transition: filter 0.6s ease-out; }
@media (prefers-reduced-motion: reduce) {
  #clearance-chip.cl-thaw { transition: none; }
}
#clearance-beat, #holding-teach, #softlock-modal, #ram-release-teach {
  display: none; position: fixed; inset: 0; z-index: 90;
  align-items: center; justify-content: center;
  background: rgba(4,8,14,0.86); pointer-events: auto;
}
#clearance-beat.show, #holding-teach.show, #softlock-modal.show, #ram-release-teach.show { display: flex; }
#clearance-beat-box, #holding-teach-box, #softlock-box, #ram-release-teach-box {
  max-width: min(440px, 92%); padding: 22px 24px; text-align: center;
  background: rgba(8,14,20,0.96); border: 1px solid var(--chrome-cyan);
  box-shadow: 0 0 32px rgba(55,213,245,0.3); font-family: var(--chrome-font);
}
#clearance-beat-box h3, #holding-teach-box h3, #softlock-box h3, #ram-release-teach-box h3 {
  margin: 0 0 10px; font-family: var(--chrome-display); font-size: 14px;
  letter-spacing: 0.14em; color: var(--chrome-cyan);
}
#clearance-beat-box p, #holding-teach-box p, #softlock-box p, #ram-release-teach-box p {
  margin: 0 0 16px; font-size: 11px; line-height: 1.55; color: #8a9fb0;
}
#clearance-beat-dismiss, #clearance-beat-gotit, #holding-teach-dismiss, #softlock-relocate, #softlock-cancel,
#ram-release-teach-show, #ram-release-teach-gotit {
  padding: 10px 18px; font: inherit; font-size: 11px; letter-spacing: 0.12em;
  font-weight: 700; cursor: pointer; border: 1px solid var(--chrome-cyan);
  background: rgba(55,213,245,0.16); color: #cdf6ff; margin: 0 4px;
}
#softlock-cancel, #clearance-beat-gotit, #ram-release-teach-gotit { background: transparent; color: #8a9fb0; }
#duel-protocol {
  font-family: var(--chrome-display, Orbitron, sans-serif);
  font-size: 9px; letter-spacing: 0.18em; color: #8ec8d8;
  text-align: center; margin: 2px 0 0;
}
#duel-seat-goal {
  font-size: 9px; letter-spacing: 0.06em; color: #6a8090;
  text-align: center; margin: 2px 0 4px;
}
#holding-teach-box .ht-anim {
  height: 48px; margin: 0 auto 12px; max-width: 220px;
  border: 1px dashed rgba(55,213,245,0.35);
  background: linear-gradient(90deg, rgba(55,245,163,0.08), rgba(245,163,55,0.12), rgba(55,245,163,0.08));
  background-size: 200% 100%;
  animation: ht-sweep 2.4s linear infinite;
}
@keyframes ht-sweep {
  0% { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  #holding-teach-box .ht-anim { animation: none; }
}
/* D-J14 (ACTION_PLAN_FIRST_LOOP.md §10.20), upgraded D-J17 (§10.25) — one
   shared cyberpunk reveal for every blocking popup: a brief red glitch-blink
   on the title (plays once, ~2 blinks, then settles back to the element's
   normal color) plus a JS "decrypt" glitch-scramble reveal on body text
   (see glitchScrambleInto()/playHackerReveal() in world.js). Never a
   continuous/looping blink — that reads as an error state and risks being
   an annoyance, not a cyberpunk flourish. */
/* RGB-split glitch-lock burst, fired the instant playHackerReveal() adds
   .hacker-blink — runs alongside hacker-blink-red (combined animation
   shorthand below), not instead of it. */
@keyframes popup-title-glitch {
  0%, 100% { transform: translate(0,0); }
  10% { transform: translate(-2px, 1px); text-shadow: 2px 0 #ff3b3b, -2px 0 #37d5f5; }
  20% { transform: translate(2px, -1px); text-shadow: -2px 0 #ff3b3b, 2px 0 #37d5f5; }
  30% { transform: translate(-1px, 1px); }
  40% { transform: translate(1px, -1px); text-shadow: 2px 0 #ff3b3b, -2px 0 #37d5f5; }
  60% { transform: translate(1px, 1px); text-shadow: -2px 0 #ff3b3b, 2px 0 #37d5f5; }
  75%, 100% { transform: translate(0,0); text-shadow: none; }
}
@keyframes hacker-blink-red {
  0%, 100% { color: inherit; text-shadow: none; }
  20%, 60% { color: #ff3b3b; text-shadow: 0 0 8px rgba(255,59,59,0.7); }
  40%, 80% { color: inherit; text-shadow: none; }
}
.hacker-blink { animation: hacker-blink-red 1.2s steps(1, end) 1, popup-title-glitch 0.35s steps(2, end) 2; }
@media (prefers-reduced-motion: reduce) {
  .hacker-blink { animation: none; }
}
/* Visual polish, round 2 (2026-09-16) — round 1 gave every popup box shell a
   single flash-in keyframe (cyberbox-in) but nothing after that; the shell
   went completely static once visible, which still read as flat next to a
   reference cyberpunk UI the user pointed to. This round replaces that one
   keyframe with four layered, reusable pieces applied via the SAME shared
   selector groups (still zero per-popup bespoke code):
     1. popup-boot-in    — richer entrance (adds a translateY lift to the
                           old scale+brightness flash).
     2. popup-border-pulse-* — a slow glow pulse that keeps breathing for as
                           long as the popup stays open, not just on entry.
     3. popup-scan-sweep — a moving highlight band across the top of the
                           box, like a terminal re-scanning its own panel.
     4. popup-bg-flicker-* — a brief full-screen breach flicker on the
                           overlay backdrop itself, fired from JS
                           (playHackerReveal() in world.js) via a .breaching
                           class at the exact instant the title's decrypt
                           lands and starts its glitch-lock burst.
   Two color groups, matching each popup's existing accent (never inventing
   a new palette): cyan for the four chrome-cyan popups, amber/red for
   #defense-brief (which already uses that pairing for its own title/sub). */
@keyframes popup-boot-in {
  0%   { opacity: 0; transform: translateY(10px) scale(0.97); filter: brightness(2.2) saturate(1.4); }
  55%  { opacity: 1; filter: brightness(1.15) saturate(1.1); }
  100% { opacity: 1; transform: translateY(0) scale(1); filter: brightness(1) saturate(1); }
}
/* Same entrance as popup-boot-in, but with translateX(-50%) baked into
   every step — for #demo-cta-banner, which centers itself via its own
   transform instead of a flex parent (see the comment on
   #demo-cta-banner.show above). */
@keyframes popup-boot-in-centered {
  0%   { opacity: 0; transform: translateX(-50%) translateY(10px) scale(0.97); filter: brightness(2.2) saturate(1.4); }
  55%  { opacity: 1; filter: brightness(1.15) saturate(1.1); }
  100% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); filter: brightness(1) saturate(1); }
}
@keyframes popup-border-pulse-cyan {
  0%, 100% { box-shadow: 0 0 10px rgba(55,213,245,0.25), inset 0 0 22px rgba(55,213,245,0.05); }
  50%      { box-shadow: 0 0 22px rgba(55,213,245,0.55), inset 0 0 30px rgba(55,213,245,0.10); }
}
@keyframes popup-border-pulse-amber {
  0%, 100% { box-shadow: 0 0 10px rgba(245,163,55,0.28), inset 0 0 22px rgba(245,163,55,0.05); }
  50%      { box-shadow: 0 0 22px rgba(245,163,55,0.58), inset 0 0 30px rgba(245,163,55,0.10); }
}
@keyframes popup-scan-sweep {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(320%); }
}
@keyframes popup-bg-flicker-cyan {
  0%, 100% { background-color: rgba(4,8,14,0.85); }
  20%  { background-color: rgba(55,213,245,0.30); }
  40%  { background-color: rgba(4,8,14,0.85); }
  60%  { background-color: rgba(55,213,245,0.20); }
  80%  { background-color: rgba(4,8,14,0.85); }
}
@keyframes popup-bg-flicker-amber {
  0%, 100% { background-color: rgba(4,2,10,0.72); }
  20%  { background-color: rgba(245,163,55,0.28); }
  40%  { background-color: rgba(4,2,10,0.72); }
  60%  { background-color: rgba(245,88,88,0.22); }
  80%  { background-color: rgba(4,2,10,0.72); }
}
#demo-conversion.show #demo-conversion-box,
#clearance-beat.show #clearance-beat-box,
#holding-teach.show #holding-teach-box,
#softlock-modal.show #softlock-box,
#ram-release-teach.show #ram-release-teach-box {
  position: relative; overflow: hidden;
  animation: popup-boot-in 0.5s cubic-bezier(0.2,0.9,0.25,1) both,
             popup-border-pulse-cyan 2.6s ease-in-out infinite 0.5s;
}
#defense-brief .db-box {
  position: relative; overflow: hidden;
  animation: popup-boot-in 0.5s cubic-bezier(0.2,0.9,0.25,1) both,
             popup-border-pulse-amber 2.6s ease-in-out infinite 0.5s;
}
#demo-conversion.show #demo-conversion-box::before,
#clearance-beat.show #clearance-beat-box::before,
#holding-teach.show #holding-teach-box::before,
#softlock-modal.show #softlock-box::before,
#ram-release-teach.show #ram-release-teach-box::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 40%;
  background: linear-gradient(180deg, rgba(55,213,245,0.07), rgba(55,213,245,0));
  animation: popup-scan-sweep 3.2s linear infinite; pointer-events: none;
}
#defense-brief .db-box::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 40%;
  background: linear-gradient(180deg, rgba(245,163,55,0.08), rgba(245,163,55,0));
  animation: popup-scan-sweep 3.2s linear infinite; pointer-events: none;
}
#demo-conversion.show #demo-conversion-box::after,
#clearance-beat.show #clearance-beat-box::after,
#holding-teach.show #holding-teach-box::after,
#softlock-modal.show #softlock-box::after,
#ram-release-teach.show #ram-release-teach-box::after,
#defense-brief .db-box::after {
  content: ''; position: absolute; inset: 0;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,0) 0px, rgba(0,0,0,0) 2px, rgba(0,0,0,0.16) 3px);
  pointer-events: none; opacity: 0.5;
}
#demo-conversion.show #demo-conversion-box > *,
#clearance-beat.show #clearance-beat-box > *,
#holding-teach.show #holding-teach-box > *,
#softlock-modal.show #softlock-box > *,
#ram-release-teach.show #ram-release-teach-box > *,
#defense-brief .db-box > * {
  position: relative; z-index: 1;
}
#demo-conversion.breaching, #clearance-beat.breaching,
#holding-teach.breaching, #softlock-modal.breaching, #ram-release-teach.breaching {
  animation: popup-bg-flicker-cyan 0.6s steps(1, end) 1;
}
#defense-brief.breaching {
  animation: popup-bg-flicker-amber 0.6s steps(1, end) 1;
}
@media (prefers-reduced-motion: reduce) {
  #demo-conversion.show #demo-conversion-box,
  #clearance-beat.show #clearance-beat-box,
  #holding-teach.show #holding-teach-box,
  #softlock-modal.show #softlock-box,
  #ram-release-teach.show #ram-release-teach-box,
  #defense-brief .db-box,
  #demo-conversion.show #demo-conversion-box::before,
  #clearance-beat.show #clearance-beat-box::before,
  #holding-teach.show #holding-teach-box::before,
  #softlock-modal.show #softlock-box::before,
  #ram-release-teach.show #ram-release-teach-box::before,
  #defense-brief .db-box::before,
  #demo-conversion.breaching, #clearance-beat.breaching,
  #holding-teach.breaching, #softlock-modal.breaching, #ram-release-teach.breaching,
  #defense-brief.breaching {
    animation: none;
  }
}
#frontier-chips {
  display: none; position: absolute; left: 12px; bottom: 12px; z-index: 6;
  max-width: min(340px, 46vw); flex-direction: column; gap: 6px; pointer-events: none;
}
#frontier-chips.show { display: flex; }
#frontier-chips .sitrep {
  background: rgba(6, 10, 18, 0.88); border: 1px solid rgba(55, 213, 245, 0.45);
  color: #9adff0; font: 9px/1.35 Consolas, monospace; letter-spacing: 0.4px;
  padding: 6px 8px; box-shadow: 0 0 12px rgba(55, 213, 245, 0.12);
}
#frontier-chips .sitrep b { color: #37d5f5; font-weight: 700; }
@keyframes deploy-banner-pulse {
  0%, 100% { box-shadow: 0 0 16px rgba(55,245,163,0.2); border-color: #37f5a3; }
  50% { box-shadow: 0 0 28px rgba(55,245,163,0.45); border-color: #8affc8; }
}
#deploy-pending { display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 40; padding: 14px 22px; background: rgba(20,12,30,0.96); border: 1px solid #f5a337;
  color: #f5a337; font-size: 13px; letter-spacing: 1.4px; font-weight: 700;
  pointer-events: none; box-shadow: 0 0 28px rgba(245,163,55,0.35);
  text-align: center; max-width: min(420px, 90vw); }
#deploy-pending.show { display: block; animation: deploy-pending-blink 0.8s ease-in-out infinite; }
#viewport.deploy-busy #tier-map {
  pointer-events: none; filter: brightness(0.55) saturate(0.7);
}
#viewport.deploy-busy::after {
  content: ''; position: absolute; inset: 0; z-index: 35;
  background: rgba(4, 6, 14, 0.35); pointer-events: none;
}
@keyframes deploy-pending-blink { 0%,100% { opacity: 1; } 50% { opacity: 0.55; } }
#deploy-toast { display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.92);
  z-index: 30; padding: 18px 28px; background: rgba(6,20,12,0.96); border: 2px solid #37f5a3;
  box-shadow: 0 0 40px rgba(55,245,163,0.35); text-align: center; pointer-events: none;
  font-size: 13px; letter-spacing: 1px; color: #37f5a3; }
#deploy-toast.show { display: block; animation: deploy-toast-in 0.35s ease-out forwards; }
#deploy-toast .sub { display: block; margin-top: 6px; font-size: 10px; color: #8a7fb0; letter-spacing: 0.5px; }
@keyframes deploy-toast-in {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
#tier-map.awaiting-core { cursor: crosshair; }
#tier-map.awaiting-core.invalid-hover { cursor: not-allowed; }

#deploy-dialog { display: none; position: absolute; inset: 0; z-index: 35;
  background: rgba(4, 6, 14, 0.72); align-items: center; justify-content: center; }
#deploy-dialog.show { display: flex; }
#deploy-dialog-box { width: min(340px, 92vw); padding: 16px 18px 14px;
  background: #0c081a; border: 1px solid #37f5a3; box-shadow: 0 0 32px rgba(55,245,163,0.2);
  font-size: 11px; line-height: 1.45; }
#deploy-dialog-box h3 { margin: 0 0 6px; color: #37f5a3; letter-spacing: 1.5px; font-size: 13px; }
#deploy-dialog-box .sector { color: #8a7fb0; margin-bottom: 10px; }
#deploy-dialog-box label { display: block; color: #6a5f8f; font-size: 9px; letter-spacing: 0.8px; margin-bottom: 4px; }
#deploy-core-name { width: 100%; box-sizing: border-box; padding: 8px 10px; margin-bottom: 12px;
  background: #080511; border: 1px solid #2c1a55; color: #e8e0f8; font: inherit; }
#deploy-core-name:focus { outline: none; border-color: #37d5f5; }
#deploy-dialog-actions { display: flex; gap: 8px; justify-content: flex-end; }
#deploy-dialog-actions button { font: inherit; padding: 6px 14px; cursor: pointer; letter-spacing: 0.8px;
  border: 1px solid #2c1a55; background: #130c26; color: #8a7fb0; }
#deploy-confirm { color: #37f5a3 !important; border-color: #1e5a44 !important; }
#deploy-cancel:hover { border-color: #6a5f8f; color: #cfc7e8; }
#deploy-confirm:hover { background: #1a2e24; }

/* --- Nomadic Frontier — map-scoped ABANDON confirmation dialog -----------
   Mirrors #deploy-dialog's structure (map-root modal, not nested inside
   #safehouse like #sh-confirm-dialog — that one's DOM lives in a different
   screen and isn't reachable from here) with #sh-confirm-box's richer
   title/body/warning-list layout. */
#map-confirm-dialog { display: none; position: absolute; inset: 0; z-index: 35;
  background: rgba(4, 6, 14, 0.72); align-items: center; justify-content: center; }
#map-confirm-dialog.show { display: flex; }
#map-confirm-box { width: min(380px, 92vw); padding: 16px 18px 14px;
  background: #0c081a; border: 1px solid #f5a337; box-shadow: 0 0 32px rgba(245,163,55,0.2);
  font-size: 11px; line-height: 1.45; }
#map-confirm-box h3 { margin: 0 0 8px; color: #f5a337; letter-spacing: 1.5px; font-size: 13px; }
#map-confirm-box p { margin: 0 0 10px; font-size: 10px; color: #8a7eb0; line-height: 1.45; }
#map-confirm-warn { display: none; margin: 0 0 12px; padding: 8px 10px; font-size: 9px;
  color: #f5a337; background: rgba(245,163,55,0.08); border: 1px solid #6a4820; line-height: 1.5; }
#map-confirm-warn.show { display: block; }
#map-confirm-warn strong { display: block; margin-bottom: 4px; letter-spacing: 0.6px; }
#map-confirm-actions { display: flex; gap: 8px; justify-content: flex-end; }
#map-confirm-actions button { font: inherit; padding: 6px 14px; cursor: pointer; letter-spacing: 0.8px;
  border: 1px solid #2c1a55; background: #130c26; color: #8a7fb0; }
#map-confirm-apply { color: #f5a337 !important; border-color: #6a4820 !important; }
#map-confirm-apply:disabled { opacity: 0.4; cursor: not-allowed; }
#map-confirm-cancel:hover { border-color: #6a5f8f; color: #cfc7e8; }
#map-confirm-apply:hover:not(:disabled) { background: #261808; }


/* The guest landing (docs/TRAILER_PLAN.md stage 4, world/training.js): the trailer muted behind
   the first choice, dimmed so the buttons read; without the file the live map shows through the
   same frame — letterbox bars and the "INTERCEPTED FEED // REPLAY" tag (it is a replay, not live). */
#guest-landing { display: none; position: absolute; inset: 0; z-index: 4; pointer-events: none; overflow: hidden; }
body.guest-landing-on #guest-landing { display: block; }
#landing-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; filter: brightness(0.6) saturate(1.1); transition: opacity 0.9s ease; }
#guest-landing.has-video #landing-video { opacity: 1; }
#guest-landing .gl-frame { position: absolute; inset: 0; }
/* No letterbox bars (owner, 2026-10-10): the map frame is wide and low already — the trailer
   gets its full height. */
#guest-landing .gl-tag { position: absolute; left: 18px; bottom: 14px; z-index: 1; display: inline-flex; align-items: center; gap: 8px;
  font: 11px 'Share Tech Mono', monospace; letter-spacing: 0.22em; color: rgba(215, 244, 246, 0.8); }
#guest-landing .gl-tag i { width: 8px; height: 8px; border-radius: 50%; background: #ff3b5c; box-shadow: 0 0 8px #ff3b5c; animation: gl-rec 1.2s steps(2) infinite; }
@keyframes gl-rec { 50% { opacity: 0.2; } }
/* The bottom dock hides while the intro plays (owner, 2026-10-10; the ?landingfull preview made the
   default), so the map frame — and the 16:9 trailer in it — fills the window under the top bar. */
body.guest-landing-on #toolbar { display: none !important; }
/* The first choice: PLAY TRAINING and REGISTER side by side; the "restricted" badge is for a drill in play. */
#demo-cta-banner .demo-cta-row { display: flex; gap: 8px; width: 100%; }
#demo-cta-banner .demo-cta-row > button { flex: 1 1 0; }
#demo-cta-register {
  padding: 10px 14px; cursor: pointer; font: 700 12px var(--chrome-font, monospace); letter-spacing: 0.14em;
  color: #04110f; background: #00fff5; border: 1px solid #00fff5; box-shadow: 0 0 16px rgba(0, 255, 245, 0.35);
}
#demo-cta-register:hover { box-shadow: 0 0 24px rgba(0, 255, 245, 0.6); }
body.guest-landing-on #demo-cta-banner .demo-access-badge { display: none; }
#demo-conversion-more { margin-top: 10px; background: transparent; border: 0; color: #8a9fb0; cursor: pointer;
  font: 11px var(--chrome-font, monospace); letter-spacing: 0.12em; text-decoration: underline; }
#demo-conversion-more[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { #guest-landing .gl-tag i { animation: none; } }
/* The first choice is the whole screen: the guest's SITREP (0/64, no core) waits until a drill starts. */
body.guest-landing-on #hud, body.guest-landing-on #hud-tab, body.guest-landing-on #phone-peeks { display: none !important; }
/* A word from the developer under the landing's buttons (2026-10-17): small and quiet, below a
   thin rule, so the banner grows by about a line and the buttons stay the first thing seen. */
#demo-cta-banner .demo-cta-note { margin: 2px 0 0; padding-top: 8px; border-top: 1px solid rgba(55, 213, 245, 0.18);
  font: 10.5px/1.5 var(--chrome-font, monospace); letter-spacing: 0.02em; color: #8fa8b8; text-align: left; }
#demo-cta-banner .demo-note-link { padding: 0; border: 0; background: none; cursor: pointer; font: inherit; letter-spacing: inherit;
  color: #6ee7ff; text-decoration: underline; text-underline-offset: 2px; }
#demo-cta-banner .demo-note-link:hover { color: #b8f6ff; }
#demo-cta-banner .demo-note-sig { float: right; margin-left: 8px; color: #37d5f5; font-style: italic; }
/* Demo first (2026-10-17): the bright, filled button is PLAY TRAINING — the eye goes to it, and a
   stranger is not asked for an account first. REGISTER keeps the outline; whoever wants it finds it. */
#demo-cta-banner .demo-cta-row #demo-cta-btn {
  color: #04110f; background: #00fff5; border: 1px solid #00fff5; box-shadow: 0 0 16px rgba(0, 255, 245, 0.35); }
#demo-cta-banner .demo-cta-row #demo-cta-btn:hover, #demo-cta-banner .demo-cta-row #demo-cta-btn:focus-visible {
  background: #00fff5; box-shadow: 0 0 24px rgba(0, 255, 245, 0.6); }
#demo-cta-banner .demo-cta-row #demo-cta-register {
  color: #cdf6ff; background: rgba(55, 213, 245, 0.14); border: 1px solid #37d5f5; box-shadow: none; }
#demo-cta-banner .demo-cta-row #demo-cta-register:hover {
  background: rgba(55, 213, 245, 0.28); box-shadow: 0 0 18px rgba(55, 213, 245, 0.35); }
