/* ═══════════════════════════════════════════════════════════
   SUPERNOVA — Outpost Defense · HUD stylesheet
   ═══════════════════════════════════════════════════════════ */

:root{
  --bg:#0a0705;
  --ink:#f3e9dd;
  --dim:#a89684;
  --cyan:#6cf3ff;
  --cyan-d:#1b8fa8;
  --amber:#ffbe4d;
  --lime:#c8f24a;
  --red:#ff5a49;
  --violet:#b06bff;
  --glass:rgba(14,11,9,.62);
  --stroke:rgba(255,210,160,.16);
  --stroke-hot:rgba(120,240,255,.45);
  --font:"Inter","SF Pro Display",system-ui,-apple-system,"Segoe UI","Noto Sans Thai",sans-serif;
  --mono:"SFMono-Regular",ui-monospace,Menlo,Consolas,monospace;
  --sh:0 6px 26px rgba(0,0,0,.55);
}

*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden;background:var(--bg);color:var(--ink);font-family:var(--font)}
body{-webkit-user-select:none;user-select:none;touch-action:none;overscroll-behavior:none}

#app{position:fixed;inset:0}
#game{position:absolute;inset:0;width:100%;height:100%;display:block;cursor:crosshair}

.hidden{display:none !important}

/* ── HUD shell ─────────────────────────────────────────── */
.hud{position:absolute;inset:0;pointer-events:none;z-index:5}
.hud > *{pointer-events:auto}

/* ── top bar ───────────────────────────────────────────── */
.topbar{
  position:absolute;top:0;left:0;right:0;
  display:flex;align-items:center;gap:14px;
  padding:calc(8px + env(safe-area-inset-top)) 14px 10px;
  background:linear-gradient(180deg,rgba(8,6,5,.86) 0%,rgba(8,6,5,.52) 62%,transparent 100%);
}

.cmd{display:flex;align-items:center;gap:9px;flex:0 0 auto}
.cmd-portrait{
  position:relative;width:42px;height:42px;display:grid;place-items:center;
  background:linear-gradient(150deg,#1d3a4a,#0d1620);
  border:1px solid var(--stroke-hot);border-radius:9px;
  box-shadow:inset 0 0 18px rgba(108,243,255,.22),var(--sh);
}
.cmd-portrait span{font:700 13px/1 var(--mono);letter-spacing:.06em;color:var(--cyan)}
.cmd-rank{
  position:absolute;right:-6px;bottom:-6px;min-width:18px;height:18px;padding:0 4px;
  display:grid;place-items:center;font:700 11px/1 var(--mono);font-style:normal;
  background:linear-gradient(160deg,#ffd479,#e08b1c);color:#251500;
  border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,.6);
}
.cmd-meta{display:flex;flex-direction:column;gap:5px}
.cmd-meta b{font:600 11px/1 var(--font);letter-spacing:.16em;color:var(--dim)}
.xpbar{width:74px;height:4px;border-radius:99px;background:rgba(255,255,255,.1);overflow:hidden}
.xpbar i{display:block;height:100%;width:0%;border-radius:99px;
  background:linear-gradient(90deg,#7ef9ff,#4aa8ff);transition:width .45s cubic-bezier(.2,.8,.2,1)}

.stats{display:flex;align-items:center;gap:10px;flex:1 1 auto;min-width:0;overflow:hidden}
.stat{
  display:flex;align-items:center;gap:7px;padding:6px 11px 6px 8px;
  background:var(--glass);border:1px solid var(--stroke);border-radius:8px;
  backdrop-filter:blur(9px);-webkit-backdrop-filter:blur(9px);box-shadow:var(--sh);
  white-space:nowrap;
}
.stat b{font:600 14px/1 var(--mono);letter-spacing:.02em}
.stat b em{font-style:normal;font-size:11px;color:var(--dim)}
.sep{width:1px;height:22px;background:var(--stroke)}

.ico{width:16px;height:16px;border-radius:4px;flex:0 0 auto;
  background-repeat:no-repeat;background-size:contain;background-position:center}
.ico-credit{background:radial-gradient(circle at 34% 30%,#ffe9a8,#f0a91e 58%,#8a5a06);
  border-radius:50%;box-shadow:0 0 9px rgba(255,190,77,.55)}
.ico-alloy{background:linear-gradient(150deg,#cfeaff,#5f9ecf 55%,#25455f);
  clip-path:polygon(50% 0,100% 28%,100% 72%,50% 100%,0 72%,0 28%);box-shadow:0 0 9px rgba(120,190,255,.4)}
.ico-swarm{background:radial-gradient(circle at 50% 34%,#e5b0ff,#7a3fa8 58%,#2a1236);
  border-radius:50% 50% 40% 40%;box-shadow:0 0 9px rgba(190,120,255,.45)}
.ico-turret{background:linear-gradient(160deg,#bfe9f6,#4a8fa8 60%,#1d3c49);
  clip-path:polygon(50% 0,100% 34%,82% 100%,18% 100%,0 34%)}

.right-cluster{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.wavechip{
  display:flex;align-items:center;gap:7px;padding:6px 12px;border-radius:8px;
  background:linear-gradient(150deg,rgba(176,107,255,.22),rgba(20,10,30,.7));
  border:1px solid rgba(176,107,255,.4);box-shadow:var(--sh),inset 0 0 18px rgba(176,107,255,.15);
}
.wavechip span{font:700 9px/1 var(--font);letter-spacing:.22em;color:#d9bcff}
.wavechip b{font:700 16px/1 var(--mono);color:#fff;text-shadow:0 0 12px rgba(176,107,255,.8)}
.coords{font:500 11px/1 var(--mono);color:var(--dim);letter-spacing:.04em;opacity:.8}

/* ── next wave timer ───────────────────────────────────── */
.wavetimer{
  position:absolute;top:64px;left:50%;transform:translateX(-50%);
  display:flex;align-items:center;gap:10px;padding:7px 8px 7px 14px;border-radius:999px;
  background:var(--glass);border:1px solid var(--stroke);backdrop-filter:blur(10px);box-shadow:var(--sh);
}
.wavetimer span{font:700 9px/1 var(--font);letter-spacing:.2em;color:var(--dim)}
.wavetimer b{font:700 17px/1 var(--mono);color:var(--amber);min-width:26px;text-align:center}
.mini{
  font:600 11px/1 var(--font);color:#0c1a1e;letter-spacing:.02em;
  padding:7px 12px;border:0;border-radius:999px;cursor:pointer;
  background:linear-gradient(160deg,#8ff6ff,#37b6d4);
  box-shadow:0 3px 12px rgba(108,243,255,.35);transition:transform .12s,filter .12s;
}
.mini i{font-style:normal;font-weight:800}
.mini:hover{transform:translateY(-1px);filter:brightness(1.1)}
.mini:active{transform:translateY(0)}

/* ── centre banner ─────────────────────────────────────── */
.banner{
  position:absolute;top:22%;left:50%;transform:translate(-50%,-6px);
  text-align:center;opacity:0;pointer-events:none;
  transition:opacity .3s,transform .3s;
}
.banner.show{opacity:1;transform:translate(-50%,0)}
.banner b{
  display:block;font:800 44px/1 var(--font);letter-spacing:.1em;
  color:#fff;text-shadow:0 0 30px rgba(255,120,60,.7),0 4px 22px rgba(0,0,0,.8);
}
.banner span{display:block;margin-top:6px;font:600 12px/1 var(--font);
  letter-spacing:.34em;color:var(--amber);text-shadow:0 2px 10px rgba(0,0,0,.9)}

/* ── build panel ───────────────────────────────────────── */
.buildpanel{
  position:absolute;left:50%;bottom:calc(14px + env(safe-area-inset-bottom));
  transform:translateX(-50%);width:min(760px,calc(100vw - 24px));
  background:var(--glass);border:1px solid var(--stroke);border-radius:14px;
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);box-shadow:var(--sh);
  overflow:hidden;animation:rise .22s cubic-bezier(.2,.9,.25,1);
}
/* Deliberately does NOT animate opacity: if the first frame after opening is
   slow (heavy scene, cold shader cache) an opacity-from-0 keyframe leaves the
   panel invisible but still clickable. Slide only. */
@keyframes rise{from{transform:translate(-50%,14px)}to{transform:translate(-50%,0)}}
.buildpanel header{
  display:flex;align-items:center;justify-content:space-between;
  padding:9px 12px;border-bottom:1px solid var(--stroke);
  background:linear-gradient(180deg,rgba(108,243,255,.08),transparent);
}
.buildpanel header b{font:700 11px/1 var(--font);letter-spacing:.2em;color:var(--cyan)}
.x{background:none;border:0;color:var(--dim);font-size:14px;cursor:pointer;padding:2px 6px;border-radius:6px}
.x:hover{color:#fff;background:rgba(255,255,255,.08)}

.cards{display:flex;gap:8px;padding:10px;overflow-x:auto;scrollbar-width:thin}
.cards::-webkit-scrollbar{height:5px}
.cards::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16);border-radius:9px}

.card{
  position:relative;flex:1 0 132px;min-width:132px;text-align:left;cursor:pointer;
  padding:10px;border-radius:11px;color:var(--ink);
  background:linear-gradient(165deg,rgba(255,255,255,.07),rgba(255,255,255,.02));
  border:1px solid rgba(255,255,255,.09);
  transition:transform .13s,border-color .13s,background .13s;
}
.card:hover{transform:translateY(-3px);border-color:var(--stroke-hot);
  background:linear-gradient(165deg,rgba(108,243,255,.14),rgba(255,255,255,.03))}
.card:disabled,.card.locked{opacity:.42;cursor:not-allowed;transform:none}
.card .glyph{width:34px;height:34px;border-radius:9px;margin-bottom:7px;
  display:grid;place-items:center;font-size:19px;
  background:rgba(0,0,0,.32);border:1px solid rgba(255,255,255,.1)}
.card h4{font:700 12px/1.2 var(--font);letter-spacing:.03em;margin-bottom:3px}
.card p{font:400 10px/1.35 var(--font);color:var(--dim);min-height:26px}
.card .cost{display:flex;align-items:center;gap:5px;margin-top:7px;
  font:600 12px/1 var(--mono)}
.card .cost.no{color:var(--red)}
.card .tag{position:absolute;top:8px;right:8px;font:700 8px/1 var(--font);
  letter-spacing:.14em;padding:3px 5px;border-radius:4px;
  background:rgba(200,242,74,.16);color:var(--lime);border:1px solid rgba(200,242,74,.3)}
.card .stats-line{display:flex;gap:8px;margin-top:6px;font:500 9px/1 var(--mono);color:var(--dim)}

/* ── ability bar ───────────────────────────────────────── */
.abilitybar{
  position:absolute;right:14px;bottom:calc(16px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;gap:9px;
}
.ab{
  position:relative;width:56px;height:56px;border-radius:14px;cursor:pointer;
  border:1px solid var(--stroke);background:var(--glass);color:var(--ink);
  backdrop-filter:blur(10px);box-shadow:var(--sh);overflow:hidden;
  display:grid;place-items:center;transition:transform .12s,border-color .12s;
}
.ab:hover{transform:translateY(-2px);border-color:var(--stroke-hot)}
.ab .ab-ico{font-size:22px;line-height:1;filter:drop-shadow(0 2px 6px rgba(0,0,0,.7))}
.ab .ab-key{position:absolute;top:3px;left:5px;font:700 9px/1 var(--mono);color:var(--dim)}
.ab .ab-cd{position:absolute;inset:0;background:rgba(4,8,12,.78);
  display:grid;place-items:center;font:700 15px/1 var(--mono);color:#fff;
  clip-path:inset(0 0 0 0)}
.ab.ready{border-color:rgba(108,243,255,.5);box-shadow:var(--sh),0 0 20px rgba(108,243,255,.2)}
.ab.armed{border-color:var(--amber);box-shadow:0 0 0 2px rgba(255,190,77,.4),0 0 24px rgba(255,190,77,.4)}
.ab.armed .ab-ico{animation:pulse .8s infinite}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.16)}}

/* ── event log ─────────────────────────────────────────── */
.log{
  position:absolute;left:14px;bottom:calc(16px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column-reverse;gap:5px;max-width:300px;pointer-events:none;
}
.log div{
  font:500 11px/1.35 var(--font);padding:5px 10px;border-radius:7px;
  background:rgba(10,8,6,.62);border-left:2px solid var(--cyan);
  backdrop-filter:blur(6px);animation:logIn .3s ease-out;
}
.log div.warn{border-left-color:var(--amber)}
.log div.bad{border-left-color:var(--red)}
.log div.good{border-left-color:var(--lime)}
@keyframes logIn{from{opacity:0;transform:translateX(-14px)}to{opacity:1;transform:none}}

/* ── full screens ──────────────────────────────────────── */
.screen{
  /* Scrollable, not just centred: the command post made the start panel tall
     enough that on a short window the launch button fell off the bottom with
     no way to reach it. */
  position:absolute;inset:0;z-index:20;padding:20px;
  display:grid;place-items:center;
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
  background:radial-gradient(ellipse at 50% 34%,rgba(48,20,9,.44) 0%,rgba(12,7,5,.76) 52%,rgba(4,3,3,.9) 100%);
  backdrop-filter:blur(5px) saturate(.85);-webkit-backdrop-filter:blur(5px) saturate(.85);
  animation:screenIn .4s ease-out;
}
/* Same reason as `rise`: never animate opacity from 0 on something the player
   has to click. A stalled first frame would leave the menu invisible. */
@keyframes screenIn{from{transform:scale(1.012)}to{transform:none}}
.stars{position:absolute;inset:0;opacity:.5;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 22%,#fff,transparent),
    radial-gradient(1.2px 1.2px at 78% 14%,#cfe9ff,transparent),
    radial-gradient(1px 1px at 44% 68%,#fff,transparent),
    radial-gradient(1.6px 1.6px at 66% 80%,#ffd9a8,transparent),
    radial-gradient(1px 1px at 88% 52%,#fff,transparent),
    radial-gradient(1.2px 1.2px at 26% 88%,#bfe0ff,transparent),
    radial-gradient(1px 1px at 6% 60%,#fff,transparent),
    radial-gradient(1.3px 1.3px at 56% 34%,#fff,transparent);
  animation:twinkle 6s ease-in-out infinite alternate}
@keyframes twinkle{from{opacity:.32}to{opacity:.62}}

.panelbox{
  position:relative;width:min(620px,100%);padding:34px 32px 26px;text-align:center;
  margin:auto 0;
  background:linear-gradient(170deg,rgba(24,18,14,.9),rgba(10,8,6,.94));
  border:1px solid var(--stroke);border-radius:20px;box-shadow:0 30px 80px rgba(0,0,0,.7);
  backdrop-filter:blur(12px);
}
.panelbox.slim{width:min(460px,100%);padding:30px 28px 24px}
.logomark{width:60px;height:60px;margin-bottom:8px;filter:drop-shadow(0 0 18px rgba(108,243,255,.5))}
.panelbox h1{font:800 42px/1 var(--font);letter-spacing:.14em;
  background:linear-gradient(180deg,#fff,#ffc98a);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent}
.panelbox h1 em{font-style:normal;
  background:linear-gradient(180deg,#9ef7ff,#4a7dff);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent}
.tag{margin-top:8px;font:600 10px/1 var(--font);letter-spacing:.36em;color:var(--dim)}
.brief{margin:22px auto 20px;max-width:440px;font:400 13px/1.75 var(--font);color:#d5c4b2}
.brief b{color:var(--amber);font-weight:700}

.difficulty{display:flex;gap:8px;justify-content:center;margin-bottom:20px;flex-wrap:wrap}
.difficulty button{
  flex:1 1 120px;padding:11px 8px;border-radius:11px;cursor:pointer;color:var(--dim);
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.09);
  transition:.14s;font-family:var(--font);
}
.difficulty button b{display:block;font-size:13px;font-weight:700;color:var(--ink);margin-bottom:2px}
.difficulty button span{font-size:10px;letter-spacing:.06em}
.difficulty button:hover{border-color:var(--stroke-hot)}
.difficulty button.on{
  border-color:var(--cyan);background:linear-gradient(165deg,rgba(108,243,255,.2),rgba(108,243,255,.05));
  box-shadow:0 0 22px rgba(108,243,255,.18)}
.difficulty button.on b{color:#fff}

.cta{
  width:100%;padding:15px;border:0;border-radius:13px;cursor:pointer;
  font:800 15px/1 var(--font);letter-spacing:.14em;color:#0a1418;
  background:linear-gradient(160deg,#a6f9ff,#3fb3d8 55%,#2f8fd0);
  box-shadow:0 10px 30px rgba(80,200,255,.32),inset 0 1px 0 rgba(255,255,255,.6);
  transition:transform .13s,filter .13s;
}
.cta:hover{transform:translateY(-2px);filter:brightness(1.08)}
.cta:active{transform:translateY(0)}

.keys{display:flex;flex-wrap:wrap;gap:8px 16px;justify-content:center;margin-top:18px}
.keys span{font:400 10px/1 var(--font);color:var(--dim);display:flex;align-items:center;gap:5px}
kbd{font:600 10px/1 var(--mono);padding:4px 6px;border-radius:5px;color:var(--ink);
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.13);
  box-shadow:0 2px 0 rgba(0,0,0,.4)}

.dead{font:800 30px/1 var(--font);letter-spacing:.1em;color:var(--red);
  text-shadow:0 0 34px rgba(255,90,73,.5);margin-bottom:22px}
.scoregrid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:16px}
.scoregrid div{padding:13px 8px;border-radius:11px;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08)}
.scoregrid b{display:block;font:700 24px/1 var(--mono);color:var(--amber)}
.scoregrid span{display:block;margin-top:5px;font:500 10px/1 var(--font);
  letter-spacing:.1em;color:var(--dim)}
.best{font:500 11px/1 var(--font);color:var(--dim);margin-bottom:18px}
.best b{color:var(--cyan);font-family:var(--mono)}

/* ── loading ───────────────────────────────────────────── */
.loading{position:absolute;inset:0;z-index:40;display:grid;place-items:center;
  gap:14px;background:#0a0705;grid-auto-flow:row}
.loading i{width:42px;height:42px;border-radius:50%;
  border:2px solid rgba(108,243,255,.18);border-top-color:var(--cyan);
  animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.loading span{font:600 11px/1 var(--font);letter-spacing:.24em;color:var(--dim)}

/* ── responsive ────────────────────────────────────────── */
@media (max-width:820px){
  .cmd-meta,.coords{display:none}
  .panelbox h1{font-size:32px}
  .banner b{font-size:32px}
  .stat{padding:5px 9px 5px 7px}
  .stat b{font-size:13px}
}
@media (max-width:560px){
  .stats{gap:6px}
  .sep{display:none}

  /* abilities become a horizontal strip so they never sit on top of the
     build panel, which needs the full width on a phone */
  .abilitybar{
    flex-direction:row;right:10px;left:auto;
    bottom:calc(10px + env(safe-area-inset-bottom));
  }
  .ab{width:46px;height:46px;border-radius:12px}
  .ab .ab-ico{font-size:19px}

  .buildpanel{
    width:calc(100vw - 16px);
    bottom:calc(66px + env(safe-area-inset-bottom));
  }
  .card{flex:1 0 106px;min-width:106px;padding:8px}
  .card p{font-size:9px;min-height:24px}
  .card .glyph{width:28px;height:28px;font-size:16px;margin-bottom:5px}

  /* log moves out of the way of the panel */
  .log{
    top:calc(52px + env(safe-area-inset-top));bottom:auto;left:8px;
    max-width:56vw;flex-direction:column;
  }
  .log div{font-size:10px;padding:4px 8px}

  .wavetimer{top:56px;padding:5px 6px 5px 11px}
  .scoregrid b{font-size:20px}
}

@media (max-width:430px){
  .stat b em{display:none}
  .topbar{gap:8px;padding-left:8px;padding-right:8px}
  .panelbox{padding:26px 18px 20px}
  .panelbox h1{font-size:27px;letter-spacing:.1em}
  .brief{font-size:12px;margin:16px auto 16px}
}

/* ── 3D: HUD overlay canvas + full-screen flash ─────────── */
#overlay{
  position:absolute;inset:0;width:100%;height:100%;
  display:block;pointer-events:none;z-index:2;
}
#flash{
  position:absolute;inset:0;pointer-events:none;z-index:3;
  opacity:0;mix-blend-mode:screen;transition:opacity .08s linear;
}

/* ── stage run: crawler progress ─────────────────────────── */
.ico-power{background:radial-gradient(circle at 40% 32%,#ffd0d0,#ff5a5a 58%,#8a1414);
  border-radius:3px;box-shadow:0 0 9px rgba(255,90,90,.55)}

.crossing{
  position:absolute;top:58px;left:50%;transform:translateX(-50%);
  display:flex;align-items:center;gap:10px;padding:6px 12px;border-radius:999px;
  background:var(--glass);border:1px solid var(--stroke);
  backdrop-filter:blur(10px);box-shadow:var(--sh);
}
.crossing span{font:700 9px/1 var(--font);letter-spacing:.2em;color:var(--dim)}
.crossing b{font:700 12px/1 var(--mono);color:var(--amber);min-width:34px;text-align:right}
.crossbar{position:relative;width:min(38vw,300px);height:6px;border-radius:99px;
  background:rgba(255,255,255,.1);overflow:hidden}
.crossbar i{position:absolute;inset:0 auto 0 0;width:0%;border-radius:99px;
  background:linear-gradient(90deg,#7ef9ff,#4aa8ff);transition:width .25s linear}
.crossbar u{position:absolute;top:-3px;width:2px;height:12px;background:var(--red);
  box-shadow:0 0 7px rgba(255,90,73,.9);text-decoration:none}
.crossing.guardian b{color:var(--red)}
.crossing.guardian .crossbar i{background:linear-gradient(90deg,#ff8a72,#c22a1c)}

/* ── intermission ───────────────────────────────────────── */
.panelbox.wide{width:min(880px,100%);padding:26px 26px 22px;text-align:left;
  max-height:92vh;overflow-y:auto}
.cleared{font:800 24px/1 var(--font);letter-spacing:.06em;color:var(--cyan);
  text-shadow:0 0 26px rgba(108,243,255,.35);text-align:center}
.itsub{margin-top:6px;text-align:center;font:500 12px/1 var(--font);color:var(--dim)}
.itsub b{color:var(--amber);font-family:var(--mono)}

.purse{display:flex;gap:10px;justify-content:center;margin:16px 0 6px}
.purse div{display:flex;align-items:center;gap:7px;padding:7px 14px;border-radius:9px;
  background:rgba(255,255,255,.05);border:1px solid var(--stroke)}
.purse b{font:700 16px/1 var(--mono)}

.itsec{margin-top:16px}
.itsec h3{font:700 10px/1 var(--font);letter-spacing:.22em;color:var(--dim);
  margin-bottom:8px;padding-left:2px}
.cards.tight{padding:0;gap:7px;flex-wrap:wrap;overflow:visible}
.cards.tight .card{flex:0 1 132px;min-width:132px;padding:9px}
.cards.tight .card p{min-height:0;margin-bottom:2px}

.routes{display:flex;gap:9px;flex-wrap:wrap}
.routes button{
  flex:1 1 200px;min-width:190px;text-align:left;cursor:pointer;padding:13px;
  border-radius:12px;color:var(--ink);
  background:linear-gradient(165deg,rgba(255,255,255,.07),rgba(255,255,255,.02));
  border:1px solid rgba(255,255,255,.1);transition:transform .13s,border-color .13s;
  font-family:var(--font);
}
.routes button:hover{transform:translateY(-3px);border-color:var(--stroke-hot);
  background:linear-gradient(165deg,rgba(108,243,255,.14),rgba(255,255,255,.03))}
.routes .rglyph{font-size:22px;line-height:1;margin-bottom:6px;display:block}
.routes h4{font:700 13px/1.2 var(--font);margin-bottom:4px}
.routes p{font:400 10px/1.4 var(--font);color:var(--dim)}
.routes .rtag{display:inline-block;margin-top:7px;font:600 9px/1 var(--mono);
  letter-spacing:.06em;padding:4px 7px;border-radius:5px;
  background:rgba(255,190,77,.14);color:var(--amber)}

@media (max-width:560px){
  .crossing{top:52px;padding:5px 10px;gap:7px}
  .crossbar{width:42vw}
  .panelbox.wide{padding:18px 14px 16px}
  .cards.tight .card{flex:1 1 106px;min-width:106px}
  .routes button{flex:1 1 100%;min-width:0}
}

/* ── weather chip ─────────────────────────────────────────
   Left edge, mid height: out of the way of the top bar's numbers and of the
   build panel, and on the side the compass is not. Its accent colour is set
   from the storm def so the three read as three things at a glance. */
#stormChip{
  position:absolute;left:14px;top:50%;transform:translateY(-50%);
  z-index:6;display:flex;align-items:center;gap:9px;
  padding:8px 13px 8px 10px;border-radius:11px;
  background:linear-gradient(150deg,rgba(var(--st,224,176,112),.18),rgba(10,8,6,.74));
  border:1px solid rgba(var(--st,224,176,112),.42);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  box-shadow:var(--sh),inset 0 0 22px rgba(var(--st,224,176,112),.12);
  animation:rise .22s cubic-bezier(.2,.9,.25,1);
}
#stormChip i{font-style:normal;font-size:19px;line-height:1;
  filter:drop-shadow(0 0 8px rgba(var(--st,224,176,112),.8))}
#stormChip.warn i{animation:stormPulse .9s ease-in-out infinite}
@keyframes stormPulse{0%,100%{opacity:1}50%{opacity:.35}}
.storm-meta{display:flex;flex-direction:column;gap:3px;width:min(232px,34vw)}
.storm-meta b{font:700 11px/1 var(--font);letter-spacing:.06em;color:rgb(var(--st,224,176,112))}
.storm-meta em{font:500 10px/1.25 var(--font);font-style:normal;color:var(--dim)}
.storm-track{width:5px;height:38px;flex:0 0 auto;border-radius:99px;background:rgba(255,255,255,.1);
  overflow:hidden;display:flex;align-items:flex-end}
.storm-track s{display:block;width:100%;height:0%;text-decoration:none;
  background:linear-gradient(0deg,rgb(var(--st,224,176,112)),rgba(255,255,255,.9))}

/* ── charge lance & beam clash ───────────────────────────── */
/* The frame around the picture is part of the weather. Its colours are CSS
   variables so the renderer can drive them from the same blended biome
   descriptor that sets the fog — a salt pan closes in pale, a night bloom
   closes in cold — without a second full-screen pass to pay for it. The
   defaults are the rust values it always had, so a frame drawn before the
   world exists still looks right. */
#vignette{
  --vig-mid:26,8,2;
  --vig-edge:14,4,1;
  --vig-top:255,180,110;
  position:absolute;inset:0;pointer-events:none;z-index:2;
  background:
    radial-gradient(ellipse at 50% 46%,rgba(0,0,0,0) 48%,rgba(var(--vig-mid),.30) 78%,rgba(var(--vig-edge),.62) 100%),
    linear-gradient(180deg,rgba(var(--vig-top),.05),transparent 30%);
}

.clash{
  position:absolute;top:12%;left:50%;transform:translateX(-50%);
  width:min(560px,86vw);padding:11px 14px 9px;border-radius:14px;
  background:rgba(12,7,4,.72);border:1px solid rgba(255,200,120,.4);
  backdrop-filter:blur(10px);box-shadow:0 10px 40px rgba(0,0,0,.6),0 0 40px rgba(255,180,80,.25);
  animation:clashIn .18s ease-out;
}
@keyframes clashIn{from{transform:translate(-50%,-8px) scale(.97)}to{transform:translate(-50%,0) scale(1)}}
.clash-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:7px}
.clash-head span{font:800 12px/1 var(--font);letter-spacing:.26em;color:#ffe9a8;
  text-shadow:0 0 16px rgba(255,200,110,.7)}
.clash-head b{font:700 11px/1 var(--font);letter-spacing:.08em;color:var(--amber);
  animation:mashPulse .35s infinite alternate}
@keyframes mashPulse{from{opacity:.55}to{opacity:1}}

.clash-track{position:relative;height:16px;border-radius:9px;overflow:hidden;
  background:linear-gradient(90deg,rgba(255,90,60,.28),rgba(0,0,0,.5) 45%,rgba(120,240,255,.22))}
.clash-track i{position:absolute;inset:0 auto 0 0;width:50%;
  background:linear-gradient(90deg,rgba(255,240,190,.25),rgba(255,220,140,.85));
  transition:width .05s linear}
.clash-track u{position:absolute;top:-4px;width:6px;height:24px;border-radius:3px;
  background:#fff;box-shadow:0 0 16px rgba(255,240,180,1),0 0 34px rgba(255,190,90,.8);
  transform:translateX(-3px);text-decoration:none;transition:left .05s linear}
.clash-track s{position:absolute;top:0;bottom:0;left:94%;width:2px;
  background:rgba(140,255,180,.9);text-decoration:none}
.clash-ends{display:flex;justify-content:space-between;margin-top:5px}
.clash-ends em{font:600 9px/1 var(--font);font-style:normal;letter-spacing:.18em;color:var(--dim)}

@media (max-width:560px){
  .clash{top:14%;padding:8px 10px 7px}
  .clash-head span{font-size:10px;letter-spacing:.18em}
}

.routes button .rbio{display:block;margin:8px 0 2px;font-size:12px;letter-spacing:.04em;
  color:#ffd9a0;opacity:.92}

/* doctrine picker — wider than the weapon row because each one is a trade that
   has to be read, not an icon to recognise */
.doctrine-pick{display:grid;gap:6px;margin:10px 0 4px}
.dpick{--wc:#8fffd0;display:grid;grid-template-columns:26px 1fr;gap:2px 9px;
  align-items:center;padding:8px 11px;text-align:left;border-radius:10px;
  border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.03);
  color:#e8e8ee;cursor:pointer;transition:border-color .15s,background .15s}
.dpick i{grid-row:1/3;font-size:19px;font-style:normal;color:var(--wc);text-align:center}
.dpick b{font-size:13px;font-weight:700}
.dpick span{font-size:11px;line-height:1.4;opacity:.7}
.dpick:hover{border-color:rgba(255,255,255,.2);background:rgba(255,255,255,.06)}
.dpick.on{border-color:var(--wc);background:rgba(255,255,255,.07);
  box-shadow:0 0 0 1px var(--wc) inset,0 0 18px -6px var(--wc)}
.dpick.locked{opacity:.4;cursor:default;grid-template-columns:26px 1fr}
.dpick.locked:hover{border-color:rgba(255,255,255,.10);background:rgba(255,255,255,.03)}

/* the extraction offer — a win reads green where a loss reads red */
h2.won{color:#8fffd0;text-shadow:0 0 22px rgba(120,255,200,.35)}
.vsub{margin:-4px 0 14px;font-size:13px;opacity:.75;text-align:center}
.vchoice{display:grid;gap:9px;margin-top:4px}
.cta.ghost{background:transparent;border:1px solid rgba(255,255,255,.22);
  color:#ffd0a0;box-shadow:none;font-size:13px}
.cta.ghost:hover{border-color:rgba(255,190,120,.5);background:rgba(255,170,90,.08)}

/* which species the strip fields — the reason to read the card rather than
   compare its multipliers */
.routes button .rswarm{display:block;margin:3px 0 1px;font:500 10px/1.45 var(--mono);
  color:#d0b0ff;opacity:.82}

/* current primary weapon */
.weaponchip{--wcol:#ffe27a;gap:7px}
.weaponchip .wglyph{display:grid;place-items:center;width:19px;height:19px;flex:0 0 auto;
  border-radius:6px;font-size:13px;line-height:1;color:#12100c;background:var(--wcol);
  box-shadow:0 0 10px color-mix(in srgb,var(--wcol) 60%,transparent)}
.weaponchip b{color:var(--wcol);font-size:12.5px;letter-spacing:.02em}
@media (max-width:760px){.weaponchip b{display:none}}

/* ══════════ touch controls ══════════
   Hidden until a coarse pointer or a real touch shows up, so a desktop
   player never sees a thumbstick. */
.touchui{display:none}
#app.touch .touchui{display:block}
.touchui .stick{
  position:absolute;width:132px;height:132px;border-radius:50%;
  border:1px solid rgba(255,255,255,.16);background:rgba(12,10,8,.28);
  backdrop-filter:blur(3px);pointer-events:none;opacity:0;
  transform:translate(-50%,-50%);transition:opacity .14s;
}
.touchui .stick.on{opacity:1}
.touchui .stick i{
  position:absolute;left:50%;top:50%;width:56px;height:56px;border-radius:50%;
  background:radial-gradient(circle at 40% 34%,rgba(255,226,140,.95),rgba(255,150,60,.7));
  box-shadow:0 0 18px rgba(255,170,80,.5);transform:translate(-50%,-50%);
}
.touchui .tbtns{
  position:absolute;right:82px;bottom:calc(18px + env(safe-area-inset-bottom));
  display:flex;gap:12px;align-items:flex-end;
}
.tbtn{
  width:76px;height:76px;border-radius:50%;border:1px solid var(--stroke);
  background:var(--glass);backdrop-filter:blur(10px);color:var(--ink);
  display:grid;place-items:center;gap:1px;line-height:1;
  box-shadow:var(--sh);touch-action:none;user-select:none;
}
.tbtn b{font-size:24px}
.tbtn span{font-size:10px;opacity:.72}
.tbtn.charge{width:92px;height:92px;border-color:rgba(255,200,110,.5)}
.tbtn.charge b{color:#ffd884;font-size:29px}
.tbtn:active{transform:scale(.94);border-color:#ffce7a}
@media (max-width:760px){
  /* the ability bar turns into a row along the bottom here, so the thumb
     buttons stack above it instead of landing on top of it */
  .touchui .tbtns{right:10px;bottom:calc(84px + env(safe-area-inset-bottom));gap:10px}
  .tbtn{width:64px;height:64px}
  .tbtn.charge{width:78px;height:78px}
}

/* ══════════ command post: what survives a dead crawler ══════════ */
.ico-data{background:conic-gradient(from 210deg,#7ef9ff,#b06bff 55%,#2b6cff);
  clip-path:polygon(50% 0,100% 28%,100% 72%,50% 100%,0 72%,0 28%);
  box-shadow:0 0 10px rgba(140,190,255,.5)}
.post{margin:16px 0 4px;padding:14px 14px 12px;border-radius:16px;
  border:1px solid var(--stroke);background:rgba(12,10,14,.42)}
.post-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.post-head h3{margin:0;font-size:13px;letter-spacing:.16em;text-transform:uppercase;opacity:.72}
.databal,.datagain{display:flex;align-items:center;gap:7px}
.databal b,.datagain b{font-size:17px;color:#a9d8ff}
.databal em,.datagain em{font-style:normal;font-size:11px;opacity:.6}
.datagain{justify-content:center;margin:6px 0 14px}
.datagain b{font-size:22px}

.weapon-pick{display:flex;gap:8px;margin-bottom:11px;flex-wrap:wrap}
.wpick{--wc:#ffe27a;display:flex;align-items:center;gap:7px;padding:7px 11px;border-radius:11px;
  border:1px solid var(--stroke);background:var(--glass);color:var(--ink);font-size:12px;
  cursor:pointer;transition:border-color .12s,transform .12s}
.wpick i{font-style:normal;font-size:15px;color:var(--wc)}
.wpick.on{border-color:var(--wc);box-shadow:0 0 0 1px color-mix(in srgb,var(--wc) 40%,transparent) inset}
.wpick.locked{opacity:.34;cursor:not-allowed}
.wpick:not(.locked):hover{transform:translateY(-1px)}

.mcard{--mc:#ffd27a;position:relative;display:flex;flex-direction:column;gap:3px;
  padding:9px 10px;border-radius:12px;border:1px solid var(--stroke);
  background:var(--glass);color:var(--ink);text-align:left;cursor:pointer;
  transition:border-color .12s,transform .12s}
.mcard:not(.maxed):not(.poor):hover{transform:translateY(-2px);border-color:var(--mc)}
.mcard .mtop{display:flex;align-items:center;gap:7px}
.mcard .mg{font-size:15px;color:var(--mc)}
.mcard .mn{font-size:12.5px;font-weight:700}
.mcard .mpips{margin-left:auto;display:flex;gap:3px}
.mcard .mpips u{width:6px;height:6px;border-radius:2px;background:rgba(255,255,255,.16)}
.mcard .mpips u.on{background:var(--mc)}
.mcard .md{font-size:10.5px;opacity:.66;line-height:1.35}
.mcard .mc{font-size:11px;color:#a9d8ff}
.mcard.maxed{opacity:.6;cursor:default}
.mcard.maxed .mc{color:#8fe06a}
.mcard.poor{cursor:not-allowed}
.mcard.poor .mc{color:#ff8a8a}

/* ══════════ the wilds compass ══════════ */
.compass{display:flex;align-items:center;gap:7px;margin-left:10px;
  padding-left:10px;border-left:1px solid rgba(255,255,255,.12)}
.compass i{font-style:normal;font-size:13px;line-height:1;color:var(--amber);
  transition:transform .1s linear,opacity .2s}
.compass b{font:700 12px/1 var(--mono);color:var(--amber)}
.compass em{font:600 10px/1 var(--font);font-style:normal;color:var(--dim)}
/* the outpost is off screen from out here, so the distance home has to be the
   thing that warns you instead of its health bar */
.compass em.far{color:var(--red)}

/* ══════════ attributes ══════════
   Wider than an upgrade card on purpose. An upgrade card is a price and a line
   of flavour; an attribute card has to show a rank, a cost curve and two
   keystones with their conditions, and squeezing that into the same 150 px
   would mean truncating the part the decision rests on. */
.attrs{display:grid;gap:9px;grid-template-columns:repeat(auto-fit,minmax(228px,1fr))}
.attr{--ac:#ffd27a;display:flex;flex-direction:column;gap:6px;
  padding:11px 12px;border-radius:12px;border:1px solid var(--stroke);
  background:var(--glass);text-align:left}
.attr.maxed{opacity:.72}
.attr .atop{display:flex;align-items:center;gap:8px}
.attr .ag{font-size:17px;color:var(--ac);line-height:1}
.attr .an{font:700 13px/1 var(--font)}
.attr .ar{margin-left:auto;font:700 13px/1 var(--mono);color:var(--ac)}
.attr .ar em{font-style:normal;font-size:10px;opacity:.5}
.attr .apips{display:flex;gap:4px}
/* the last three pips read heavier because they cost double — the price curve
   should be visible before it is paid, not discovered at rank four */
.attr .apips u{flex:1;height:5px;border-radius:2px;background:rgba(255,255,255,.13)}
.attr .apips u.dear{background:rgba(255,255,255,.07);
  border:1px solid rgba(255,255,255,.14);height:5px}
.attr .apips u.on{background:var(--ac);border-color:var(--ac)}
.attr .aper{font:500 10.5px/1.4 var(--font);color:var(--ink);opacity:.8}
/* nowrap so it never breaks between "ต่อ" and "ระดับ", which left an orphan
   line and made every card in a row a different height */
.attr .aper em{font-style:normal;opacity:.5;white-space:nowrap}
.attr .aperks{display:flex;flex-direction:column;gap:4px;margin-top:1px}
.attr .perk{display:flex;gap:6px;font:400 10px/1.35 var(--font);color:var(--dim);opacity:.62}
.attr .perk i{font-style:normal;font-size:9px;line-height:1.5;color:rgba(255,255,255,.3)}
.attr .perk b{display:block;font-weight:700;color:var(--dim)}
.attr .perk.on{opacity:1}
.attr .perk.on i{color:var(--ac)}
.attr .perk.on b{color:var(--ac)}
.attr .abuy{
  margin-top:auto;padding:7px 10px;border-radius:8px;cursor:pointer;
  border:1px solid color-mix(in srgb,var(--ac) 40%,transparent);
  background:color-mix(in srgb,var(--ac) 12%,transparent);
  color:var(--ink);font:700 10.5px/1 var(--font);letter-spacing:.04em;
  transition:background .12s,border-color .12s}
.attr .abuy:not(:disabled):hover{background:color-mix(in srgb,var(--ac) 24%,transparent);
  border-color:var(--ac)}
.attr .abuy:disabled{opacity:.4;cursor:not-allowed}

/* unspent points, on the rank chip — the sheet is behind a keypress, so the
   only thing that can say "there is something to do in there" is the HUD */
.cmd-pts{
  position:absolute;left:-6px;top:-6px;min-width:17px;height:17px;padding:0 4px;
  display:grid;place-items:center;font:700 10px/1 var(--mono);
  background:linear-gradient(160deg,#c8f24a,#7aa81c);color:#1a2000;
  border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,.6);
  animation:ptsPulse 1.5s ease-in-out infinite}
.cmd-portrait{cursor:pointer}
@keyframes ptsPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.14)}}

/* the derived stat sheet */
.sheet{display:grid;gap:5px;grid-template-columns:repeat(auto-fit,minmax(232px,1fr))}
.sheet div{display:flex;align-items:baseline;gap:8px;padding:6px 10px;border-radius:8px;
  background:rgba(255,255,255,.032)}
.sheet span{font:500 10.5px/1.3 var(--font);color:var(--dim)}
.sheet b{margin-left:auto;font:700 11px/1.3 var(--mono);color:var(--ink);text-align:right}

/* turret module slot */
.card.modslot{border-color:color-mix(in srgb,var(--mc,#8a8) 46%,transparent)}
.card.modslot.empty{opacity:.6;border-style:dashed}
.card[data-act="module"]{border-color:color-mix(in srgb,var(--mc) 34%,transparent)}
.card[data-act="module"]:hover{border-color:var(--mc)}

/* ══════════ coaching line ══════════ */
.coach{
  position:absolute;left:50%;top:calc(96px + env(safe-area-inset-top));transform:translateX(-50%);
  display:flex;align-items:center;gap:9px;max-width:min(560px,92vw);
  padding:9px 15px 9px 10px;border-radius:999px;
  border:1px solid rgba(255,206,122,.34);background:rgba(24,17,10,.82);
  backdrop-filter:blur(9px);box-shadow:0 10px 30px rgba(0,0,0,.5);
  font:600 13px/1.4 var(--font);color:#ffe9c8;z-index:8;
  animation:coachIn .3s cubic-bezier(.2,.9,.25,1);
}
@keyframes coachIn{from{transform:translate(-50%,-8px)}to{transform:translate(-50%,0)}}
.coach b{display:grid;place-items:center;flex:0 0 auto;width:21px;height:21px;border-radius:50%;
  background:linear-gradient(160deg,#ffd27a,#ff9d3d);color:#20150a;font-size:11px}
.coach.done{border-color:rgba(150,230,120,.5);color:#d6f5c4}
.coach.done b{background:linear-gradient(160deg,#a9f08a,#5fc25a)}

/* ══════════ pause / settings ══════════ */
.paused{margin:0 0 4px;font:800 22px/1.2 var(--font);letter-spacing:.06em;color:#ffd9a2}
.opts{display:flex;flex-direction:column;gap:11px;margin:18px 0 20px;text-align:left}
.opt{display:flex;align-items:center;gap:12px;font-size:12.5px;color:#d9cbba}
.opt > span{flex:0 0 118px}
.opt input[type=range]{flex:1;accent-color:#ffc46b;height:3px}
.opt b{flex:0 0 42px;text-align:right;font-size:12px;color:#ffcf8d}
.toggle{position:relative;width:44px;height:24px;border-radius:999px;flex:0 0 auto;
  border:1px solid var(--stroke);background:rgba(255,255,255,.06);cursor:pointer;transition:background .15s}
.toggle i{position:absolute;left:3px;top:2.5px;width:17px;height:17px;border-radius:50%;
  background:#9a9186;transition:transform .16s,background .16s}
.toggle[aria-pressed="true"]{background:rgba(255,196,107,.26);border-color:rgba(255,196,107,.5)}
.toggle[aria-pressed="true"] i{transform:translateX(20px);background:#ffc46b}
.seg{display:flex;gap:4px;flex:1}
.seg button{flex:1;padding:6px 4px;border-radius:8px;font-size:11px;color:var(--dim);
  border:1px solid var(--stroke);background:rgba(255,255,255,.04);cursor:pointer}
.seg button.on{color:#20150a;background:linear-gradient(160deg,#ffd27a,#ff9d3d);border-color:transparent}
.pausebtns{display:flex;flex-direction:column;gap:9px}
.ghost{padding:11px;border-radius:11px;font:600 13px var(--font);color:var(--dim);
  border:1px solid var(--stroke);background:transparent;cursor:pointer}
.ghost:hover{color:var(--ink);border-color:rgba(255,255,255,.24)}
.hintline{margin:14px 0 0;font-size:11px;color:var(--dim)}
.hintline kbd{font-size:10px}

/* combo meter: four pips and the finisher they will fire */
.combochip{--cc:#ffe27a;gap:7px}
.combochip .cpips{display:flex;gap:3px;flex:0 0 auto}
.combochip .cpips u{width:5px;height:13px;border-radius:2px;background:rgba(255,255,255,.15);
  transition:background .1s,box-shadow .1s}
.combochip .cpips u.on{background:var(--cc);box-shadow:0 0 7px color-mix(in srgb,var(--cc) 70%,transparent)}
.combochip b{color:var(--cc);font-size:12px;letter-spacing:.02em}
@media (max-width:860px){.combochip b{display:none}}

/* spare gunships — wilds only. Pips because the number is small and the answer
   wanted mid-fight is "how many left", which is a shape, not a digit. The count
   stays next to them for the width the chip is squeezed down to on a phone. */
.lifechip{--lc:#ffe98c;gap:7px}
.lifechip .lpips{display:flex;gap:3px;flex:0 0 auto}
.lifechip .lpips u{width:7px;height:13px;flex:0 0 auto;background:rgba(255,255,255,.14);
  clip-path:polygon(50% 0,100% 38%,50% 100%,0 38%);transition:background .12s,box-shadow .12s}
.lifechip .lpips u.on{background:var(--lc);box-shadow:0 0 8px color-mix(in srgb,var(--lc) 70%,transparent)}
.lifechip b{color:var(--lc);font:600 13px/1 var(--mono)}
/* one left is the thing the player must not miss, so the chip says it twice */
.lifechip.last{animation:lifelow 1.1s ease-in-out infinite}
.lifechip.last{--lc:#ff8f6a}
@keyframes lifelow{0%,100%{opacity:1}50%{opacity:.45}}
