/* ═══════════════════════════════════════════════════════════════════════
   TRUMP WARS · battlefield intel sheet (package U3 of the "Fleet Command Console")
   The wave panel (#waveBox), tactical minimap (#miniBox > #mini), selected tower (#sel), screen-level boss bar (#boss)
   and the banner (#banner). Markup is filled by js/ui/intel.js; the canvases by js/ui/overlay.js.
   Ported from ui-lab/final/final.css 'U3 · WAVE PANEL', 'U3 · MINIMAP', 'U3 · SELECTED TOWER', 'U3 · BOSS BAR',
   'U3 · BANNER', with the review fixes: build rows wrap their trait tags under the name and keep the count column
   fixed; the wave panel compacts itself (.f1-.f5, intel.js fitWave) so it never runs into #sel; the Sell button and
   #sel carry a hold-X fill; no glyph outside the two fonts (diamond, triangle, infinity and close are drawn shapes);
   text floor max(9px, Xrem).
   ═══════════════════════════════════════════════════════════════════════ */

/* drawn triangle marker (the ▸ glyph is not in either font) */
.tri { display: inline-block; width: 0; height: 0; border-top: .3em solid transparent; border-bottom: .3em solid transparent; border-left: .45em solid currentColor; margin: 0 .25em 0 .3em; vertical-align: .04em; }
svg.inf { display: inline-block; width: 1.5em; height: .75em; vertical-align: -.02em; }

/* ═══ U3 · WAVE PANEL (#waveBox) ══════════════════════════════════════════
   #s-wave and #w-name are setT leaves the game overwrites ('8 / 20', '9 left'): hidden .leaf spans.
   The big number is .wv-n: the CURRENT wave in combat, the NEXT wave in the build phase (the label says which).
   State classes (intel.js): .combat / .build; .bld and .cbt children show in one state only.           */
#waveBox { position: absolute; right: var(--gap); top: 5rem; width: 26rem; padding: .9rem 1rem 1rem; }
#waveBox.combat .bld, #waveBox.build .cbt { display: none !important; }
.wv-h { display: flex; align-items: flex-end; gap: .8rem; }
.wv-h .lbl { margin-bottom: .45rem; white-space: nowrap; }
.wv-h .val { font-size: 3.5rem; color: var(--yel); white-space: nowrap; }
.wv-h .val small { font-size: .34em; }
.wv-h .sp { flex: 1; }
.wv-h .kl { text-align: right; margin-right: .6rem; margin-bottom: .3rem; }
.wv-h .kl .lbl { font-size: max(9px, .9rem); margin-bottom: 0; }
.wv-h .kv { font: 400 1.6rem/1 var(--f-num); color: var(--txt-2); margin-top: .25rem; }
#wChip { margin-bottom: .35rem; }
#wChip .dia { width: .5em; height: .5em; margin: 0 .45em 0 0; }
/* wave pips (FINAL_WAVE of them); boss waves are diamonds */
.pips { display: grid; grid-template-columns: repeat(var(--n, 20), 1fr); gap: .22rem; margin: .7rem 0 0; align-items: center; height: 1rem; }
.pips i { height: .7rem; background: rgba(255, 255, 255, .1); }
.pips i.d { background: var(--amb); opacity: .75; }
.pips i.c { background: var(--yel); box-shadow: 0 0 0 1px var(--k0), 0 0 .5rem rgba(255, 232, 31, .6); animation: blink 1s steps(2, jump-none) infinite; }
.pips i.b { height: .9rem; width: .9rem; justify-self: center; transform: rotate(45deg); background: none; box-shadow: inset 0 0 0 1.5px var(--hos); }
.pips i.b.d { background: var(--hos); opacity: 1; }
.pips i.b.c { background: var(--hos); box-shadow: 0 0 0 1px var(--k0), 0 0 .6rem rgba(255, 74, 58, .8); }
#waveBox.endless .pips, #waveBox.endless .pipl { display: none !important; }
.pipl { display: flex; justify-content: space-between; margin-top: .45rem; font: 400 max(9px, .95rem)/1 var(--f-num); color: var(--txt-3); letter-spacing: .1em; white-space: nowrap; }
.pipl b { color: var(--hos); font-weight: 400; }
.pipl .dia { width: .55em; height: .55em; }
/* wave progress: destroyed / leaked / active / inbound (sums to the total captured at launch). A leak is a loss, never progress:
   its own dark-red segment with a red edge (ACTIVE is solid red, INBOUND hatched red, DOWN amber) */
.prog { margin: .7rem 0 .45rem; height: 1rem; display: flex; gap: 2px; background: rgba(255, 255, 255, .06); padding: 2px; }
.prog > span { display: block; height: 100%; flex: 0 1 0; min-width: 0; }
.prog .dn { background: var(--amb); opacity: .8; }
.prog .lk { background: #4a0a0d; box-shadow: inset 0 0 0 1px var(--hos); }
.prog .ac { background: var(--hos); }
.prog .ib2 { background: repeating-linear-gradient(135deg, rgba(255, 74, 58, .45) 0 .25rem, transparent .25rem .5rem); }
/* the legend wraps (T+ first, then INBOUND) rather than cut a count; fitWave re-runs when LEAKED appears */
.progl { display: flex; flex-wrap: wrap; gap: .4rem .9rem; font: 400 max(9px, 1.02rem)/1 var(--f-num); letter-spacing: .06em; color: var(--txt-2); white-space: nowrap; }
.progl .wt { margin-left: auto; color: var(--txt-3); }
.progl .wt b { color: var(--txt-2); }
.progl i { display: inline-block; width: .7rem; height: .7rem; margin-right: .3rem; vertical-align: -.05rem; }
.progl i.dn { background: var(--amb); } .progl i.ac { background: var(--hos); } .progl i.ib2 { box-shadow: inset 0 0 0 1px var(--hos); }
.progl i.lk { background: #4a0a0d; box-shadow: inset 0 0 0 1px var(--hos); }
.progl span.lk, .progl span.lk b { color: #ff7a70; }
.progl b { color: var(--txt); font-weight: 400; }
/* composition rows */
.comp { margin-top: .8rem; display: flex; flex-direction: column; gap: .25rem; }
.comp:empty { display: none; }
#waveBox .inc-h { margin-top: .9rem; }
/* build preview: icon / name with its trait tags wrapped underneath / count (fixed column, never pushed out) */
.en { display: grid; grid-template-columns: 2.2rem minmax(0, 1fr) auto; align-items: center; gap: .6rem; padding: .25rem .4rem .25rem .3rem; background: linear-gradient(90deg, rgba(255, 59, 48, .12), rgba(255, 59, 48, 0) 70%); box-shadow: inset 2px 0 0 var(--hos); }
.en > .ic { width: 2.2rem; height: 2.2rem; color: var(--hos); }
.en > .ic svg { display: block; width: 100%; height: 100%; }
.en .nm { min-width: 0; font: 600 1.3rem/1 var(--f-txt); letter-spacing: .04em; text-transform: uppercase; display: flex; flex-direction: column; gap: .25rem; }
.en .nm > span:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.en .tr { display: flex; flex-wrap: wrap; gap: .2rem; }
.en .tr .tag { height: 1.3rem; font-size: max(9px, .9rem); padding: 0 .25rem; letter-spacing: .04em; }
.en .ct { min-width: 1.8rem; font: 400 1.9rem/1 var(--f-num); color: var(--txt); text-align: right; white-space: nowrap; }
.en.air { box-shadow: inset 2px 0 0 var(--hos-air); background: linear-gradient(90deg, rgba(255, 95, 210, .12), rgba(255, 95, 210, 0) 70%); }
.en.air > .ic { color: var(--hos-air); }
.en.boss { box-shadow: inset 2px 0 0 var(--yel); background: linear-gradient(90deg, rgba(255, 232, 31, .16), rgba(255, 232, 31, 0) 75%); }
.en.boss > .ic, .en.boss .nm > span:first-child { color: var(--yel); }
.comp .more { font: 400 max(9px, .95rem)/1 var(--f-num); letter-spacing: .1em; color: var(--txt-3); padding: .3rem .4rem 0; }
/* combat composition: one compact row per enemy type, the 1-2 traits that change play as text chips and the live count
   ('4' alive, '+2' still inbound). Cleared types drop out. */
.comp.cmp { gap: .2rem; margin-top: .65rem; }
.cmp .ch { display: grid; grid-template-columns: 2rem minmax(0, 1fr) auto minmax(2.2rem, auto); align-items: center; gap: .55rem; height: 2.3rem; padding: 0 .45rem 0 .35rem; background: linear-gradient(90deg, rgba(255, 59, 48, .14), rgba(255, 59, 48, .03) 80%); box-shadow: inset 2px 0 0 var(--hos); }
.cmp .ch > .ic svg { width: 1.9rem; height: 1.9rem; color: var(--hos); display: block; }
.cmp .ch .nm { font: 700 1.25rem/1 var(--f-txt); letter-spacing: .03em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmp .ch .tr { display: flex; gap: .2rem; }
.cmp .ch .tr .tag { height: 1.45rem; font-size: max(9px, .92rem); padding: 0 .28rem; letter-spacing: .04em; }
.cmp .ch.x1 .tr .tag.lo { display: none; } /* E5: a name that would be cut drops the lower-priority chip first (intel.js fitRows) */
.cmp .ch .ct { text-align: right; white-space: nowrap; font: 700 1.7rem/1 var(--f-txt); font-variant-numeric: tabular-nums; color: var(--txt); }
.cmp .ch .ct small { font: 400 max(9px, .92rem)/1 var(--f-num); color: var(--txt-3); margin-left: .2rem; }
.cmp .ch .ct small:empty { display: none; }
.cmp .ch.air { background: linear-gradient(90deg, rgba(255, 95, 210, .14), rgba(255, 95, 210, .03) 80%); box-shadow: inset 2px 0 0 var(--hos-air); }
.cmp .ch.air > .ic svg { color: var(--hos-air); }
.cmp .ch.boss { background: linear-gradient(90deg, rgba(255, 232, 31, .16), rgba(255, 232, 31, .03) 80%); box-shadow: inset 2px 0 0 var(--yel); }
.cmp .ch.boss > .ic svg, .cmp .ch.boss .nm { color: var(--yel); }
.nxt { white-space: nowrap; margin-top: .6rem; padding-top: .55rem; border-top: 1px dashed var(--ln-2); display: flex; align-items: center; gap: .6rem; font: 400 max(9px, 1.02rem)/1 var(--f-num); color: var(--txt-2); letter-spacing: .08em; }
.nxt > span:first-child b { color: var(--txt); font-weight: 400; }
/* the counts never give way (intel.js caps the list at 3-4 types + '+n'); the filler text is the part that yields */
.nxt .ics { display: flex; gap: .5rem; flex: none; }
.nxt .ics span { display: inline-flex; align-items: center; gap: .15rem; color: var(--txt); }
.nxt .ics svg { width: 1.6rem; height: 1.6rem; color: var(--hos); }
.nxt .ics span.air svg { color: var(--hos-air); }
.nxt .ics span.boss svg { color: var(--yel); }
.nxt .ics span.more { color: var(--txt-3); }
.nxt .x { color: var(--txt-3); white-space: nowrap; margin-left: auto; }
.nxt .x:not(.bs) { flex: 0 1 auto; min-width: 0; overflow: hidden; }
.nxt .x.bs { color: var(--yel); }
.nxt .x .dia { width: .55em; height: .55em; }
/* build-phase counter hint: the trait that dominates the next wave and the real answer to it */
.counter { display: flex; align-items: center; gap: .6rem; margin-top: .7rem; padding: .5rem .6rem; font: 500 1.2rem/1.2 var(--f-txt); color: var(--txt); background: rgba(255, 255, 255, .04); box-shadow: inset 2px 0 0 var(--txt-2); }
.counter:empty { display: none; }
.counter .tag { flex: none; }
.counter b { color: var(--yel); font-weight: 600; }
/* build-phase launch block */
.launch { margin-top: 1rem; }
.btn-launch { width: 100%; height: 4.6rem; display: flex; align-items: center; justify-content: center; gap: 1.2rem; position: relative; color: var(--k0); background: var(--yel);
  clip-path: polygon(1rem 0, 100% 0, 100% calc(100% - 1rem), calc(100% - 1rem) 100%, 0 100%, 0 1rem);
  font: 700 1.75rem/1 var(--f-txt); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
.btn-launch::before { content: ''; position: absolute; inset: 3px; border: 1px solid rgba(0, 0, 0, .35); clip-path: inherit; pointer-events: none; }
.btn-launch .key { background: var(--k0); color: var(--yel); font-size: max(9px, 1rem); height: 1.8rem; padding: 0 .5rem; letter-spacing: .1em; }
.btn-launch:hover { background: #fff36b; }
.btn-launch:disabled { display: none; }
#waveBox .auto { display: flex; align-items: center; gap: .8rem; margin-top: .9rem; cursor: pointer; }
/* the real input#c-auto stays in the label (the game reads .checked), visually replaced by the switch */
#waveBox .auto input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.auto .sw { width: 3.4rem; height: 1.6rem; position: relative; background: rgba(255, 255, 255, .08); box-shadow: inset 0 0 0 1px var(--ln); flex: none; }
.auto .sw::after { content: ''; position: absolute; top: .3rem; left: .3rem; width: 1rem; height: 1rem; background: var(--txt-3); transition: transform .15s; }
.auto input:checked + .sw { background: rgba(82, 216, 255, .18); box-shadow: inset 0 0 0 1px var(--fr); }
.auto input:checked + .sw::after { transform: translateX(1.8rem); background: var(--fr); }
.auto:hover .sw { box-shadow: inset 0 0 0 1px var(--yel); }
.auto .tx { font: 600 1.3rem/1 var(--f-txt); letter-spacing: .1em; text-transform: uppercase; color: var(--txt-2); flex: 1; white-space: nowrap; }
.auto .cd { font: 400 max(9px, 1.05rem)/1 var(--f-num); color: var(--fr); letter-spacing: .08em; white-space: nowrap; }
.auto .cd.off { color: var(--txt-3); }
.cdbar { height: 3px; margin-top: .6rem; background: rgba(82, 216, 255, .15); }
.cdbar i { display: block; height: 100%; background: var(--fr); transform-origin: left center; transform: scaleX(0); }
.cdh { margin-top: .45rem; font: 400 max(9px, .92rem)/1 var(--f-num); letter-spacing: .1em; color: var(--txt-3); text-align: right; white-space: nowrap; }
/* fit levels (intel.js fitWave): the panel gives way to #sel step by step instead of running under it */
#waveBox.f1 .counter { display: none; }
#waveBox.f2 .en { padding: .15rem .4rem .15rem .3rem; }
#waveBox.f2 .en > .ic { width: 1.9rem; height: 1.9rem; }
#waveBox.f2 .en .nm { flex-direction: row; align-items: center; gap: .5rem; }
#waveBox.f2 .en .nm > span:first-child { flex: 0 1 auto; }
/* the name wins over the chips: the chip strip gives way first (flex-shrink 1000) down to its widest chip; chips that no longer fit
   wrap onto a second line that is clipped, so a chip drops whole and is never cut, and only then does the name take an ellipsis */
#waveBox.f2 .en .tr { flex: 0 1000 auto; min-width: min-content; flex-wrap: wrap; align-content: flex-start; max-height: 1.3rem; overflow: hidden; }
#waveBox.f2 .en .tr .tag:not(.p), #waveBox.f2 .en .tr .tag.p ~ .tag.p ~ .tag.p { display: none; }
#waveBox.f2 .en .ct { font-size: 1.6rem; }
#waveBox.f3 .pipl, #waveBox.f3 .inc-h { display: none; }
#waveBox.f3 .comp { margin-top: .6rem; }
#waveBox.f4 .cdh, #waveBox.f4 .cdbar { display: none; }
#waveBox.f4 .launch { margin-top: .6rem; }
#waveBox.f4 .btn-launch { height: 3.8rem; }
#waveBox.f4 .auto { margin-top: .6rem; }
#waveBox.f5 .nxt { display: none; }
#waveBox .comp > .xr { display: none; }
/* E3 · wave doctrine chip (#wDoc): glyph, name and satirical subtitle above the rows (build); compact with the next-group timer
   (combat). Hostile red edge (magenta for an air raid, yellow for a State Visit); the corner chamfer is the panel language */
#wDoc { display: grid; grid-template-columns: 2.6rem minmax(0, 1fr) auto; align-items: center; gap: .65rem; margin-top: .6rem; padding: .45rem .6rem .45rem .45rem;
  background: linear-gradient(90deg, rgba(255, 59, 48, .17), rgba(255, 59, 48, .02) 85%); box-shadow: inset 2px 0 0 var(--hos), inset 0 1px 0 rgba(255, 59, 48, .22);
  clip-path: polygon(0 0, calc(100% - .6rem) 0, 100% .6rem, 100% 100%, 0 100%); }
#wDoc.hidden { display: none; }
#wDoc .gl { width: 2.6rem; height: 2.6rem; color: var(--hos); }
#wDoc .gl svg { display: block; width: 100%; height: 100%; }
#wDoc .dt { min-width: 0; display: flex; flex-direction: column; gap: .3rem; }
#wDoc .dt b { font: 700 1.5rem/1 var(--f-txt); letter-spacing: .1em; text-transform: uppercase; color: var(--txt); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#wDoc .dt small { font: 400 max(9px, .95rem)/1.18 var(--f-num); letter-spacing: .03em; color: var(--txt-2); }
#wDoc.air { background: linear-gradient(90deg, rgba(255, 95, 210, .17), rgba(255, 95, 210, .02) 85%); box-shadow: inset 2px 0 0 var(--hos-air), inset 0 1px 0 rgba(255, 95, 210, .22); }
#wDoc.air .gl { color: var(--hos-air); }
#wDoc.boss { background: linear-gradient(90deg, rgba(255, 232, 31, .16), rgba(255, 232, 31, .02) 85%); box-shadow: inset 2px 0 0 var(--yel), inset 0 1px 0 rgba(255, 232, 31, .28); }
#wDoc.boss .gl, #wDoc.boss .dt b { color: var(--yel); }
#wDoc.cmp { grid-template-columns: 1.9rem minmax(0, 1fr) auto; padding: .3rem .55rem .3rem .4rem; }
#wDoc.cmp .gl { width: 1.9rem; height: 1.9rem; }
#wDoc.cmp .dt b { font-size: 1.3rem; }
#wDoc .st { font: 400 max(9px, .95rem)/1 var(--f-num); letter-spacing: .1em; color: var(--amb); white-space: nowrap; }
#wDoc .st:empty { display: none; }
/* NEW (amber = command intel): a type on its intro wave, a doctrine on its first scripted wave */
.tag.new { color: var(--k0); background: var(--amb); border-color: var(--amb); }
/* the source chip ('GND · LZ 1' / 'AIR · CORRIDOR 2') and each row's counter hint (ENEMIES[k].hint) */
.en .tr .tag.src { letter-spacing: .02em; }
/* a compact row shows the source's short form ('AIR C2' / 'LZ 1+2'; the full text is the chip's tooltip) */
.en .tag .sh, #waveBox.f2 .en .tag .lg { display: none; } /* any chip with a short form (E3 source chips, E4b BREACHES WALLS) */
#waveBox.f2 .en .tag .sh { display: inline; }
.en .hn { font: 400 max(9px, .9rem)/1.15 var(--f-num); letter-spacing: .04em; color: var(--txt-3); white-space: normal; }
/* the 3 pips after the shown wave carry their doctrine's glyph */
.pips { height: 1.3rem; }
.pips i.g { height: 1.3rem; width: 1.3rem; justify-self: center; background: none; color: var(--hos); }
.pips i.g svg { display: block; width: 100%; height: 100%; }
.pips i.g.air { color: var(--hos-air); }
/* the NEXT line's doctrine glyph */
.nxt .dg { display: inline-flex; flex: none; width: 1.6rem; height: 1.6rem; color: var(--hos); }
.nxt .dg svg { width: 100%; height: 100%; }
.nxt .dg.air { color: var(--hos-air); }
#waveBox.f1 .en .hn { display: none; }
#waveBox.f3 #wDoc .dt small { display: none; }
#waveBox.f3 #wDoc { padding-top: .3rem; padding-bottom: .3rem; }

/* ═══ U3 · MINIMAP (#miniBox > #mini) ═════════════════════════════════════════
   Colour = allegiance (cyan friendly / red hostile / magenta hostile air / yellow Capitol), shape = domain.
   Drawn by overlay.js every frame from a cached static layer; the panel swallows clicks (no shots through it). */
#miniBox { position: absolute; left: var(--gap); bottom: var(--gap); padding: .7rem .75rem .65rem; width: 18.7rem; }
#miniBox .hd { margin-bottom: .55rem; }
#miniBox .hd .r { overflow: hidden; text-overflow: ellipsis; }
#mini { display: block; width: 17.2rem; height: 11.73rem; background: #050608; box-shadow: 0 0 0 1px var(--ln-2); }
#miniBox .legend { display: flex; justify-content: space-between; gap: .35rem; margin-top: .5rem; font: 400 max(9px, .9rem)/1 var(--f-num); letter-spacing: -.02em; color: var(--txt-2); text-transform: uppercase; white-space: nowrap; }
#miniBox .legend span { display: inline-flex; align-items: center; gap: .22rem; }
#miniBox .legend i { width: .62rem; height: .62rem; display: inline-block; flex: none; }
.lg-tw { background: var(--fr); box-shadow: 0 0 0 1px #000; }
.lg-gn { background: var(--hos); border-radius: 50%; }
.lg-ai { width: 0 !important; height: 0 !important; border-left: .38rem solid transparent; border-right: .38rem solid transparent; border-bottom: .66rem solid var(--hos-air); }
.lg-hq { background: var(--yel); transform: rotate(45deg) scale(.85); }
.lg-vw { box-shadow: inset 0 0 0 1px var(--txt); }

/* ═══ U3 · SELECTED TOWER (#sel) ══════════════════════════════════════════
   Own bottom-right column (23rem, reserved by bar.js even while closed), never under #bar. Closes on Esc, the close button,
   picking a tower (card or key) or selling; LMB on the ground only fires, RMB keeps firing torpedoes. .hidden keeps the class contract but slides instead of popping.  */
#sel { position: absolute; right: var(--gap); bottom: var(--gap); width: 23rem; padding: 1rem 1.1rem 1.1rem; transition: opacity .16s, transform .16s; --hold: 0; }
#sel.hidden { display: block !important; opacity: 0; transform: translateX(2rem); pointer-events: none; visibility: hidden; }
.sl-des { font: 400 max(9px, .95rem)/1 var(--f-num); letter-spacing: .18em; color: var(--amb); text-transform: uppercase; margin-bottom: .6rem; display: flex; gap: .7rem; align-items: center; white-space: nowrap; }
.sl-des::after { content: ''; flex: 1; height: 1px; background: linear-gradient(90deg, var(--ln-2), transparent); }
.sl-h { display: grid; grid-template-columns: 3.6rem minmax(0, 1fr) auto; gap: .8rem; align-items: center; }
.sl-h .ico { width: 3.6rem; height: 3.6rem; color: var(--tc); padding: .3rem; background: rgba(255, 255, 255, .04); box-shadow: inset 0 0 0 1px var(--ln-2); }
.sl-h .ico svg { display: block; width: 100%; height: 100%; }
.sl-h .nm { font: 700 1.8rem/1 var(--f-txt); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sl-h .lv { display: flex; align-items: center; gap: .5rem; margin-top: .35rem; white-space: nowrap; }
.lvp { display: flex; gap: .2rem; }
.lvp i { width: 1.1rem; height: .55rem; background: rgba(255, 255, 255, .12); transform: skewX(-24deg); }
.lvp i.on { background: var(--yel); }
.lvp i.nx { background: none; box-shadow: inset 0 0 0 1px var(--yel); animation: blink 1s steps(2, jump-none) infinite; }
.sl-h .lv .mono { font-size: 1rem; color: var(--txt-2); letter-spacing: .1em; }
/* capability tags: neutral with the domain glyph (same as the tower cards; colour = allegiance) */
.sl-h .tag { height: 1.4rem; font-size: max(9px, .95rem); padding: 0 .28rem; letter-spacing: .04em; gap: .22rem; color: var(--txt-2); border-color: rgba(205, 198, 171, .42); }
.sl-h .tag.gnd::before { content: ''; flex: none; width: .44rem; height: .44rem; border-radius: 50%; background: currentColor; }
.sl-h .tag.air::before { content: ''; flex: none; width: .56rem; height: .48rem; background: currentColor; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.sl-h .tag.slow { color: var(--yel); border-color: rgba(255, 232, 31, .5); }
/* E4: a wall node (Barrier Post): its level name as the tag, amber link bars, LINK PENDING while one of its links waits for its check */
.sl-h .tag.wall { color: var(--amb); border-color: rgba(255, 184, 48, .5); letter-spacing: .08em; }
#sel .sr .bar i.wl-n, #sel .sr .bar i.wl-k { background: var(--amb); }
#sel .sr .bar i.wl-s { background: var(--yel); }
.sl-st .lpend { color: var(--k0); background: var(--amb); padding: .2rem .35rem; letter-spacing: .12em; }
/* E4b: one of the node's walls is breached (Loophole Sappers): the seconds until it closes, hostile red; the status text yields its room */
.sl-st .brch { color: #fff; background: var(--hos); padding: .2rem .35rem; letter-spacing: .12em; flex: none; }
.sl-st .stx { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sl-st .brch:not(.hidden) ~ .stx { display: none; }
/* E5 Rules of Engagement: the TARGET block of a weapon tower: label + key chip + APPLY TO ALL (×n = towers it would retask; off while
   none), then one chamfered chip per mode the tower offers in a 3-column grid (glyph + name, never cut), the active one command yellow */
.sl-roe { margin-top: .8rem; padding-top: .65rem; border-top: 1px solid var(--ln-2); }
.roe-h { display: flex; align-items: center; gap: .5rem; height: 1.8rem; }
.roe-h .lbl { font-size: max(9px, .98rem); }
.roe-h .key { min-width: 1.5rem; height: 1.5rem; font-size: max(9px, 1rem); }
.roe-h .sp { flex: 1; }
.roe-all { display: inline-flex; align-items: center; gap: .35rem; height: 1.8rem; padding: 0 .55rem; font: 400 max(9px, .9rem)/1 var(--f-num); letter-spacing: .12em; text-transform: uppercase; white-space: nowrap; color: var(--amb); box-shadow: inset 0 0 0 1px rgba(255, 184, 48, .55); background: rgba(255, 184, 48, .07); clip-path: polygon(.4rem 0, 100% 0, 100% calc(100% - .4rem), calc(100% - .4rem) 100%, 0 100%, 0 .4rem); }
.roe-all b { font-weight: 400; color: var(--yel); }
.roe-all b:empty { display: none; }
.roe-all:hover { color: var(--k0); background: var(--amb); }
.roe-all:hover b { color: var(--k0); }
.roe-all:disabled { color: var(--txt-3); box-shadow: inset 0 0 0 1px var(--ln-2); background: none; cursor: default; }
.roe-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .35rem; margin-top: .45rem; }
.roe-m { display: flex; align-items: center; gap: .4rem; height: 2.3rem; padding: 0 .5rem; color: var(--txt-2); background: rgba(255, 255, 255, .04); box-shadow: inset 0 0 0 1px var(--ln-2); clip-path: polygon(.45rem 0, 100% 0, 100% calc(100% - .45rem), calc(100% - .45rem) 100%, 0 100%, 0 .45rem); min-width: 0; }
.roe-m svg { flex: none; width: 1.25rem; height: 1.25rem; display: block; }
.roe-m span { font: 600 max(9px, 1.15rem)/1 var(--f-txt); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }
.roe-m:hover { color: var(--yel); box-shadow: inset 0 0 0 1px var(--yel); }
.roe-m.on { color: var(--k0); background: var(--yel); box-shadow: none; }
.x-btn { width: 2.2rem; height: 2.2rem; display: grid; place-items: center; color: var(--txt-3); box-shadow: inset 0 0 0 1px var(--ln-2); align-self: start; }
.x-btn:hover { color: var(--yel); box-shadow: inset 0 0 0 1px var(--yel); }
.x-btn svg { width: 1rem; height: 1rem; display: block; }
#sel .sts { display: flex; flex-direction: column; gap: .5rem; margin-top: .9rem; }
#sel .sr { display: grid; grid-template-columns: 5rem minmax(0, 1fr) 6.8rem; gap: .6rem; align-items: center; }
#sel .sr .lbl { font-size: max(9px, .98rem); }
#sel .sr .bar { height: .7rem; background: rgba(255, 255, 255, .07); position: relative; overflow: hidden; }
#sel .sr .bar i { position: absolute; left: 0; top: 0; bottom: 0; width: 100%; background: var(--txt-2); transform-origin: left center; }
#sel .sr .bar i.up { background: repeating-linear-gradient(135deg, var(--yel) 0 .2rem, rgba(255, 232, 31, .35) .2rem .4rem); }
#sel .sr .bar i.hp { background: var(--fr); }
#sel .sr .bar.low i.hp { background: var(--warn); }
#sel .sr .bar.none { height: 1px; background: none; border-bottom: 1px dotted var(--ln-2); }
#sel .sr .v { font: 400 1.2rem/1 var(--f-num); text-align: right; white-space: nowrap; }
#sel .sr .v em { font-style: normal; color: var(--yel); }
#sel .sr .v em .tri { margin: 0 .1em 0 .3em; }
#sel .sr .v s { text-decoration: none; color: var(--txt-3); }
#sel .sr .v .mod { font-size: max(9px, .95rem); letter-spacing: .1em; color: var(--k0); background: var(--fr); padding: .12rem .3rem; margin-right: .5rem; vertical-align: .1rem; }
.sl-st { display: flex; align-items: center; gap: .5rem; margin-top: .65rem; height: 1.6rem; font: 400 max(9px, .98rem)/1 var(--f-num); letter-spacing: .1em; color: var(--txt-2); white-space: nowrap; }
.sl-st .uf { color: #fff; background: var(--hos); padding: .2rem .35rem; letter-spacing: .12em; animation: ufBlink 1.2s steps(2, jump-none) infinite; }
.sl-st .ok { color: var(--txt-3); }
@keyframes ufBlink { 50% { background: rgba(255, 59, 48, .45); } }
.sl-btns { display: grid; grid-template-columns: 1.35fr 1fr; gap: .5rem; margin-top: .8rem; }
.sb { height: 3.6rem; display: flex; align-items: center; justify-content: space-between; gap: .4rem; padding: 0 .7rem; position: relative; isolation: isolate; clip-path: polygon(.6rem 0, 100% 0, 100% calc(100% - .6rem), calc(100% - .6rem) 100%, 0 100%, 0 .6rem); }
.sb .t { font: 700 1.35rem/1 var(--f-txt); letter-spacing: .12em; text-transform: uppercase; display: flex; flex-direction: column; gap: .2rem; text-align: left; }
.sb .t small { font: 400 max(9px, .9rem)/1 var(--f-num); letter-spacing: .08em; opacity: .8; }
.sb .p { font: 400 1.45rem/1 var(--f-num); display: inline-flex; align-items: center; }
.sb .p .cu { font-size: .6em; margin-right: .4em; }
.sb.up { background: var(--yel); color: var(--k0); }
.sb.up .key { background: var(--k0); color: var(--yel); }
.sb.up:hover { background: #fff36b; }
.sb.up.cant { background: rgba(255, 255, 255, .06); color: var(--txt-3); box-shadow: inset 0 0 0 1px var(--ln-2); }
.sb.up.cant .t small { color: var(--warn); opacity: 1; }
.sb.up.cant .key { background: var(--txt-3); color: var(--k0); }
.sb.up:disabled { background: rgba(255, 255, 255, .05); color: var(--txt-3); box-shadow: inset 0 0 0 1px var(--ln-3); cursor: default; }
.sb.sell { color: var(--txt); box-shadow: inset 0 0 0 1px rgba(255, 74, 58, .55); background: rgba(255, 74, 58, .07); }
.sb.sell:hover { background: rgba(255, 74, 58, .16); }
/* hold-X fill: a red sweep across the button and along the panel's bottom edge (UI.sellHold sets --hold 0..1) */
.sb.sell .hf { position: absolute; inset: 0; z-index: -1; background: rgba(255, 59, 48, .55); transform-origin: left center; transform: scaleX(var(--hold)); }
#sel .sl-hold { position: absolute; left: 1px; right: 1px; bottom: 1px; height: 3px; background: var(--hos); transform-origin: left center; transform: scaleX(var(--hold)); pointer-events: none; }
#sel.holding { --ln: rgba(255, 59, 48, .7); }
.sl-f { margin-top: .6rem; font: 400 max(9px, .95rem)/1.35 var(--f-num); color: var(--txt-3); letter-spacing: .04em; }
.sl-f .cu { font-size: .7em; margin-right: .3em; }

/* ═══ U3 · BOSS BAR (screen level) ═════════════════════════════════════════════
   Shown while a boss (CC.isBoss: def.boss or the Dreadnought) is alive; width / text written at 8 Hz, never re-rendered. */
#boss { position: absolute; left: 50%; top: var(--gap); transform: translateX(-50%); width: 30rem; padding: .7rem 1rem .8rem; --cut: .7rem; }
#boss .bh { display: flex; align-items: center; gap: .6rem; }
#boss .bh .ic { width: 2rem; height: 2rem; color: var(--yel); flex: none; }
#boss .bh .ic svg { display: block; width: 100%; height: 100%; }
#boss .bh .nm { font: 700 1.5rem/1 var(--f-txt); letter-spacing: .22em; color: var(--yel); text-transform: uppercase; white-space: nowrap; }
#boss .bh .nn { font: 400 1.1rem/1 var(--f-num); color: var(--yel); }
#boss .bh .sp { flex: 1; }
#boss .bh .mono { font-size: 1.1rem; color: var(--txt); white-space: nowrap; }
#boss .bb { position: relative; height: 1.2rem; margin-top: .55rem; background: rgba(255, 255, 255, .08); box-shadow: 0 0 0 1px rgba(0, 0, 0, .9); overflow: hidden; }
#boss .bb i { position: absolute; left: 0; top: 0; bottom: 0; width: 100%; transform-origin: left center; background: linear-gradient(180deg, #ffef6a, var(--yel) 45%, #d9a400); }
#boss .bb i.lag { background: #fff; opacity: .5; }
#boss .bb::after { content: ''; position: absolute; inset: 0; background: repeating-linear-gradient(90deg, transparent 0 calc(10% - 1px), rgba(0, 0, 0, .65) calc(10% - 1px) 10%); }
#boss .bt { display: flex; gap: .3rem; margin-top: .5rem; white-space: nowrap; }
#boss .bt .sp { flex: 1; }

/* ═══ U3 · BANNER ══════════════════════════════════════════════════════════════
   Backed band, priority label, composition with icons, the QUEUED chip. At most 2.5 s on screen (1.5 s when another
   waits), never captures input. Low-priority events (abilities, BUILDING DOWN, PAUSED) go to the comms log instead. */
#banner { position: absolute; left: 50%; top: 15%; transform: translateX(-50%); width: 64rem; text-align: center; pointer-events: none; transition: opacity .25s; }
#banner.out { opacity: 0; }
#banner .band { position: relative; overflow: hidden; padding: 1.3rem 3rem 1.4rem; background: linear-gradient(90deg, rgba(5, 8, 12, 0), rgba(5, 8, 12, .86) 14%, rgba(5, 8, 12, .86) 86%, rgba(5, 8, 12, 0)); animation: bandIn .28s cubic-bezier(.2, .8, .3, 1) both; }
#banner .band::before, #banner .band::after { content: ''; position: absolute; left: 6%; right: 6%; height: 1px; background: linear-gradient(90deg, transparent, var(--amb) 20%, var(--amb) 80%, transparent); }
#banner .band::before { top: 0; } #banner .band::after { bottom: 0; }
@keyframes bandIn { from { transform: scaleY(.15); opacity: 0; } }
#banner .pri { display: inline-flex; align-items: center; gap: .8rem; font: 400 1.1rem/1 var(--f-num); letter-spacing: .3em; color: var(--hos); white-space: nowrap; }
#banner .pri::before, #banner .pri::after { content: ''; width: .6rem; height: .6rem; background: var(--hos); transform: rotate(45deg); }
#banner h2 { margin: .7rem 0 .5rem; font: 700 5.6rem/.95 var(--f-txt); letter-spacing: .14em; color: var(--yel); text-shadow: 0 0 2.4rem rgba(255, 232, 31, .28); white-space: nowrap; }
#banner h2 .sl { color: var(--txt-3); font-weight: 500; margin: 0 .3em; }
#banner h2 .ic { color: var(--txt); }
#banner .sub { display: inline-flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.4rem; align-items: center; max-width: 60rem; font: 400 1.25rem/1 var(--f-num); letter-spacing: .1em; color: var(--txt); text-transform: uppercase; }
#banner .sub span { display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap; }
#banner .sub svg { width: 2rem; height: 2rem; color: var(--hos); }
#banner .sub .air svg { color: var(--hos-air); }
#banner .sub .bs { color: var(--yel); }
#banner .sub .bs .dia { width: .6em; height: .6em; margin: 0 .2em 0 0; }
#banner .sub b { font-weight: 400; color: #fff; background: var(--hos); padding: .15rem .35rem; }
#banner .q { margin-top: .8rem; display: flex; justify-content: center; gap: .4rem; }
#banner .q:empty { display: none; }
#banner .q span { font: 400 max(9px, .95rem)/1 var(--f-num); letter-spacing: .12em; padding: .3rem .55rem; color: var(--txt-2); box-shadow: inset 0 0 0 1px var(--ln-2); background: var(--plate); white-space: nowrap; }
/* light sweep: transform only (no layout per frame), one pass per banner */
#banner .sweep { position: absolute; top: 0; bottom: 0; left: 0; width: 18%; background: linear-gradient(90deg, transparent, rgba(255, 232, 31, .12), transparent); transform: translateX(-110%); animation: sweep 1.6s .15s ease-out both; }
@keyframes sweep { to { transform: translateX(560%); } }
/* E3 doctrine banner: WAVE nn · <DOCTRINE> (a wider band, a smaller title so the longest name fits), the subtitle with its glyph,
   NEW chips in amber; a State Visit takes the boss colours. The band never reaches the wave panel (26rem + the 1.2rem gutter on the
   right, one more gutter of air): on 16:9 it is 71.2rem, so the title scales with the band (6.4cqi: the longest title,
   'WAVE 104 · FACT-FINDING MISSION', is 15 times its font size wide) and stays 4.6rem wherever the band has room */
#banner.dctr { width: min(86rem, calc(100vw - 2 * 28.4rem)); }
#banner.dctr .band { container-type: inline-size; }
#banner.dctr h2 { font-size: min(4.6rem, 6.4cqi); letter-spacing: .1em; }
#banner .sub .ds { color: var(--txt-2); }
#banner .sub .ds svg { width: 1.8rem; height: 1.8rem; color: var(--hos); }
#banner .sub .ds.air svg { color: var(--hos-air); }
#banner .sub .nw { color: var(--k0); background: var(--amb); padding: .15rem .4rem; }
#banner.boss .pri { color: var(--yel); } #banner.boss .pri::before, #banner.boss .pri::after { background: var(--yel); }
#banner.boss .sub .ds svg { color: var(--yel); }
#banner.ok .pri { color: var(--ok); } #banner.ok .pri::before, #banner.ok .pri::after { background: var(--ok); }
#banner.ok h2 { color: var(--txt); text-shadow: 0 0 2.4rem rgba(141, 255, 138, .18); }
#banner.ok h2 .ic { color: var(--ok); }
