/* ══════════════════════════════════════════════════════════════════════════
   Shell (index.php)
   ══════════════════════════════════════════════════════════════════════════ */
/* Greyscale text uniformly at 80% the brightness of white (#cccccc) */
body            { background-color: #0d1117; color: #cccccc; }
.auth-card      { max-width: 440px; }
.brand-title    { letter-spacing: .1em; }
.form-label     { color: #ffffff; font-weight: 700; }
.form-check-label { color: #ffffff; }
.form-control, .form-select {
    background-color: #161b22;
    color: #cccccc;
    border-color: #30363d;
}
.form-control:focus, .form-select:focus {
    background-color: #161b22;
    color: #cccccc;
    border-color: #f0a500;
    box-shadow: 0 0 0 .2rem rgba(240,165,0,.2);
}
/* Bootstrap greyscale utilities → 80% white */
.text-secondary, .text-muted { color: #cccccc !important; }
.form-control:disabled, .form-select:disabled { opacity: .6; }
.card           { background-color: #161b22; border-color: #30363d; }
.card-title     { color: #f0a500; }
.nav-tabs-wrap  { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.nav-tabs       { border-color: #30363d; flex-wrap: nowrap; min-width: max-content; }
.nav-tabs .nav-link          { color: #cccccc; border-color: transparent; white-space: nowrap; }
.nav-tabs .nav-link:hover    { color: #f0a500; border-color: transparent; }
.nav-tabs .nav-link.active   { background-color: #161b22; color: #f0a500; border-color: #30363d #30363d #161b22; }
.usp-display    { font-family: monospace; font-size: 1.1rem; letter-spacing: .05em; color: #f0a500; word-break: break-all; }
.calc-field     { color: #58a6ff; }
#auth-view      { display: flex; }
#app-view       { display: none; }
.section-heading { color: #f0a500; padding-bottom: .3rem; font-size: .85rem; text-transform: uppercase; letter-spacing: .08em; font-weight: 500;}
.nav-nickname-text { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle; }
.armour-inherent-block { display: none; }
.usp-badge { font-size: .65rem; padding: 1px 5px; vertical-align: middle; }
.craft-col-head { font-size: .7rem; color: #cccccc; padding-bottom: 2px; }
/* Craft cost/USP are catalog- or link-derived, never typed — rendered as
   <output>s (whose .value reads/writes text content, so JS read sites are
   unchanged). calc-field blue marks them as computed. On phones the value
   carries its own d-sm-none label; on ≥576px the column headers name it. */
.craft-out-wrap { display: flex; align-items: center; gap: .35rem; min-width: 0; }
.craft-out-wrap .craft-col-head { padding-bottom: 0; flex: 0 0 auto; }
.craft-output   { color: #58a6ff; font-size: .875rem; min-width: 0;
                  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.craft-output:empty::before { content: '—'; opacity: .4; }
.sd-action-bar  { position: sticky; bottom: 0; z-index: 100;
                  background-color: #0d1117; border-top: 1px solid #30363d;
                  padding: .6rem 0; margin-top: .5rem; }

/* Add/remove buttons — touch-friendly, with press feedback (no hover on mobile) */
.btn-add { font-weight: 600; width: 180px; display: block; margin-left: auto; }
.btn-add i { vertical-align: -.1em; }
.btn-add:active,
.btn-row-remove:active { transform: scale(.96); }
.btn-row-remove {
    min-width: 38px; min-height: 38px;
    display: inline-flex; align-items: center; justify-content: center;
}
/* Placeholder text → 80% white (beats Bootstrap's .form-control::placeholder) */
.form-control::placeholder,
.form-select::placeholder { color: var(--bs-border-color); opacity: .5; }

/* ── Mobile tweaks ──────────────────────────────────────────── */
@media (max-width: 575.98px) {
    .brand-title        { font-size: .9rem; letter-spacing: .05em; }
    .section-heading    { font-size: .75rem; }
    .usp-display        { font-size: .85rem; }
    .nav-tabs .nav-link { font-size: .8rem; padding: .4rem .55rem; white-space: normal; text-align: center; }
    .nav-tabs-wrap      { overflow-x: visible; }
    .nav-tabs           { flex-wrap: nowrap; min-width: 0; }
    .nav-tabs .nav-item { flex: 1 1 0; min-width: 0; }
    .nav-tabs .nav-word { display: block; }
    .card.form-card     { padding: .75rem !important; }
    .row .form-label {
        height: 2.8rem;
        display: flex;
        align-items: flex-end;
        margin-bottom: .25rem;
    }
    /* Big, obvious tap targets on phones (no hover affordance available) */
    .btn-add        { width: 100%; min-height: 44px; }
    .btn-row-remove { min-width: 44px; min-height: 44px; }
    /* iOS Safari auto-zooms the page when focusing any control under 16px
       (1rem) and doesn't reliably zoom back out. Bootstrap's -sm controls
       are .875rem, so every dynamic turret/bay/craft row input triggered
       the zoom. Bumping only on phones keeps the compact desktop rows. */
    .form-control-sm, .form-select-sm { font-size: 1rem; }

    /* Ship Designer inline steppers — [-10][-1][input][+1][+10] (tonnage and
       fuel add [-25%]/[+25%] outside). Buttons exist in the DOM at every
       viewport but only display on phones; padding is deliberately tight so
       the 7-element tonnage/fuel groups still fit a 375px viewport on one
       line. The input's font stays 1rem (iOS zoom threshold) and the 44px
       button height matches the tap-target sizing above. */
    .sd-stepper > .sd-stepper-btn {
        display: inline-flex; align-items: center; justify-content: center;
        min-height: 44px; padding: .25rem .35rem;
        /* min-width ≥ the natural width of the widest unit button (±10), so
           ±1 renders the same size as ±10 instead of shrinking to its text.
           The ±25% buttons are naturally wider and are unaffected. */
        min-width: 2.5rem;
        font-size: .78rem; font-weight: 600;
        color: #cccccc; background-color: #0d1117; border-color: #30363d;
    }
    .sd-stepper > .sd-stepper-btn:active { background-color: #30363d; color: #f0a500; }
    .sd-stepper > .form-control {
        text-align: center; min-width: 3rem;
        padding-left: .2rem; padding-right: .2rem;
    }
}
/* Desktop (≥576px): steppers hidden, plain input restored. The buttons are
   still the input's siblings inside .input-group, so Bootstrap's
   :not(:first-child)/:not(:last-child) rules would square the input's
   corners and pull it -1px left — undo both. !important is required: each
   :not(.class) in Bootstrap's chain adds a class worth of specificity, so
   its rule weighs ~6 classes and a plain 2-class override loses. */
@media (min-width: 576px) {
    .sd-stepper > .sd-stepper-btn { display: none; }
    .sd-stepper > .form-control {
        border-radius: var(--bs-border-radius) !important;
        margin-left: 0 !important;
    }
}
/* Combo box (troops) */
.combo-wrap { position: relative; }
.combo-list {
    position: absolute; z-index: 1000; width: 100%; margin: 0; padding: 0;
    bottom: 100%;
    list-style: none;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    max-height: 16rem; overflow-y: auto;
}
.combo-list li {
    padding: .35rem .75rem; cursor: pointer; font-size: .9rem;
}
.combo-list li:hover,
.combo-list li.combo-active { background: var(--bs-primary); color: #fff; }
/* Help popup */
/* inline-block, not the default inline: the popup is position:absolute and
   resolves its percentage width against this wrap, and an inline element's
   containing block is the union of its line boxes — well-defined only for
   an inline-block. */
.help-wrap { position: relative; display: inline-block; }
.help-popup {
    position: absolute; z-index: 1001; width: 100%; margin: 2px 0;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: .5rem .75rem;
    font-size: .8rem; color: var(--bs-secondary-color);
    white-space: pre-wrap;
}
.help-popup-above { bottom: 100%; top: auto; margin: 0 0 4px 0; }
/* Bay carried-craft popups (the qty data-help and the capacity flash) anchor
   to a narrow qty input, and the default width:100% resolves against that
   input's wrap — an unreadable ~100px column. Same cure as the repair-result
   popup below: size from content, cap at a readable width. HelpPopup's
   clampHorizontal() caps against the viewport and shifts the popup on
   screen, so being wider than the wrap is already handled. Launch Tubes
   needs no rule only because its wrap spans a full col-sm-4 input. */
.bay-contents-wrap .help-popup {
    width: max-content;
    max-width: min(340px, calc(100vw - 16px));
}
/* Repair-result popup (Combat Arena Step 9) — the trigger is a small
   "Attempt" button but the message is a full sentence, plus a success/failure
   background matching this app's existing green/red conventions
   (.bt-range-badge / .bt-section-destroyed).

   Sized from its own content, NOT from the trigger. This was width:300%,
   which resolves against .help-wrap and so made the popup's width an accident
   of how wide the word "Attempt" happens to render (~184px). On mobile the
   Attempt button is right-aligned in a card that is itself max-width:50%, so
   the popup was wider than its own card and ran off the right edge; a longer
   message never got wider, only taller. max-width keeps it inside the
   viewport no matter where the trigger sits. */
.bt-repair-popup         { width: max-content; min-width: 180px;
                           max-width: min(320px, calc(100vw - 16px)); }
.bt-repair-popup-success { background: #132d1a; color: #90ee90; border-color: #90ee90; }
.bt-repair-popup-danger  { background: #2d1214; color: #f85149; border-color: #f85149; }

/* ══════════════════════════════════════════════════════════════════════════
   Shared chat bubbles (ChannelChat module — used by Meeting Room and
   Combat Arena's channel drawer)
   ══════════════════════════════════════════════════════════════════════════ */
.msg-bubble        { max-width:72%;padding:.4rem .75rem;border-radius:.5rem;font-size:.875rem;word-break:break-word;line-height:1.4 }
.msg-bubble-me     { background:#1f6feb;color:#fff }
.msg-bubble-them   { background:#2d333b;color:#cccccc }
.msg-bubble-system { background:#fff;color:#1a1a1a }
.msg-nick          { font-size:.7rem;opacity:.65;margin-bottom:.2rem }

/* ══════════════════════════════════════════════════════════════════════════
   Meeting Room (views/meeting_room.html)
   ══════════════════════════════════════════════════════════════════════════ */
/* ── Text utilities ──────────────────────────────────────────────── */
.mr-small-text { font-size:.85rem }
.mr-label-xs { font-size:.75rem;color:#cccccc }
.mr-contact-label { text-transform:uppercase;letter-spacing:.06em }
.mr-incoming-label { text-transform:uppercase;letter-spacing:.08em;margin-bottom:.4rem }
.mr-nick-gold { color:#f0a500;font-weight:600 }

/* ── Visibility / layout ─────────────────────────────────────────── */
.mr-fixed-cover { position:fixed;inset:0 }

/* ── Pending notice ──────────────────────────────────────────────── */
.mr-pending-notice { position:relative;background:#3d1010;border:1px solid #c0392b;border-radius:.375rem;padding:.65rem 2.5rem .65rem 1rem;margin-bottom:.75rem;color:#f5c6c6;font-size:.85rem;line-height:1.4 }
.mr-pending-notice-dismiss { position:absolute;top:.3rem;right:.5rem;background:none;border:none;color:#f5c6c6;font-size:1rem;line-height:1;cursor:pointer;padding:0 }

/* ── Online players ──────────────────────────────────────────────── */
.mr-user { cursor:pointer;transition:background .15s }
.mr-user:hover { background:#1c2128 }
.mr-user-icon-ai { color:#58a6ff }
.mr-user-icon-human { color:#f0a500 }
.mr-user-nick { font-size:.9rem;color:#cccccc }
.mr-ai-badge { font-size:.6rem;background:#1f6feb;vertical-align:middle }

/* ── Backdrop ────────────────────────────────────────────────────── */
.mr-backdrop { background:rgba(0,0,0,.55);z-index:1040 }

/* ── Contact popup ───────────────────────────────────────────────── */
.mr-contact-popup { position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1050;background:#161b22;border:1px solid #30363d;border-radius:.6rem;padding:1.75rem 2rem;min-width:240px;text-align:center }
.mr-contact-name { font-size:1.25rem;color:#f0a500;font-weight:700 }
.mr-contact-btn { width:60px;height:60px;font-size:1.5rem }

/* ── Incoming overlay ────────────────────────────────────────────── */
.mr-incoming-overlay { display:flex;align-items:center;justify-content:center;flex-direction:column;background:rgba(13,17,23,.93);z-index:1060 }
.mr-incoming-nick { font-size:2.2rem;color:#f0a500;font-weight:700;margin-bottom:2.2rem }
.mr-incoming-btn { width:76px;height:76px;font-size:2rem }
.mr-incoming-btn-label { margin-top:.4rem }

/* ── Channel card ────────────────────────────────────────────────── */
.mr-channel-card { border-color:#30363d }
.mr-card-header { background:#1c2128;border-bottom:1px solid #30363d;border-radius:.375rem .375rem 0 0 }
.mr-card-nick { font-size:.9rem }
.mr-chat-area { height:260px;overflow-y:auto;background:#0d1117 }
.mr-card-footer { background:#161b22;border-top:1px solid #30363d }

/* ── Arena button states ─────────────────────────────────────────── */
/* Bootstrap variant classes (btn-warning/btn-outline-success/btn-success)
   now own all hover/focus/disabled states — no custom color CSS needed. */
.mr-arena-btn { min-width:130px;font-weight:600 }

/* ── mr-hidden last so display:none wins over any display:X above ── */
.mr-hidden { display:none }

/* ══════════════════════════════════════════════════════════════════════════
   Combat Arena (views/combat_arena.html)
   ══════════════════════════════════════════════════════════════════════════ */
/* Reserves vertical space for whichever step's controls are about to render
   (a button, a status message, a whole decisions form) so switching between
   them doesn't shift the rest of the page up/down every render. Same
   border/background treatment as .bt-step-bar so the two read as one
   continuous panel. */
#bt-action-panel { min-height:32px;background:#1c2128;border:1px solid #30363d;border-radius:5px;padding:8px 14px }

/* ── Channel card (pre-battle) ──────────────────────────────────────────── */
.ca-channel-card   { border-color:#30363d }
.ca-card-header    { background:#1c2128;border-bottom:1px solid #30363d;border-radius:.375rem .375rem 0 0 }
.ca-nick           { font-size:.9rem;color:#f0a500;font-weight:600 }
.ca-state-badge    { font-size:.65rem;background:#1f3a1f;color:#90ee90;letter-spacing:.04em }
.ca-chat-area      { height:220px;overflow-y:auto;background:#0d1117 }
.ca-input-wrap     { background:#161b22;border-top:1px solid #30363d }

/* Mobile: Enter Arena/Cancel drop to their own line below the selected-
   arena name instead of crowding onto the same line. Desktop keeps them
   inline since there's room. */
@media (max-width: 576px) {
    .ca-pending-resume-actions { flex-basis: 100%; margin-top: .5rem; }
    /* bt-action-row (actionRowHtml() in ship_combat.js) pairs a step's
       primary controls with the persistent Save Arena button in a flex row.
       Only wrap when the content genuinely doesn't fit (e.g. Range's two
       buttons alongside Save Arena) — a plain single button (e.g. "End
       Turn") + Save Arena should stay on one row on mobile. */
    .bt-action-row { flex-wrap: wrap; }
}
.ca-config-label   { font-size:.8rem;color:#cccccc;white-space:nowrap }
.ca-select-budget  { width:140px;background:#0d1117;color:#cccccc;border-color:#30363d }
.ca-select-tl      { width:80px;background:#0d1117;color:#cccccc;border-color:#30363d }
.ca-value-highlight{ font-size:.85rem;font-weight:600;color:#f0a500 }
.ca-enter-hint     { font-size:.75rem;color:#6e7681;font-style:italic }
.ca-enter-btn      { min-width:140px;font-weight:600 }
.ca-hangup-btn     { font-weight:600 }
.ca-waiting-title  { font-size:1.1rem }
.ca-fleet-heading  { font-size:1rem;color:#f0a500 }
.ca-fleet-card     { border-color:#30363d;background:#0d1117 }
.ca-fleet-nick     { font-size:.9rem;color:#f0a500;font-weight:600 }
.ca-budget-label   { font-size:.8rem;color:#cccccc }
.ca-budget-value   { font-size:.85rem;font-weight:600;color:#90ee90 }
.ca-ship-select    { background:#161b22;color:#cccccc;border-color:#30363d }
.ca-pick-label     { font-size:.75rem;color:#6e7681 }
.ca-pick-usp       { width:200px;font-family:monospace;font-size:.78rem;background:#0d1117;color:#e6edf3;border-color:#30363d }
.ca-pick-mcr       { width:90px;background:#0d1117;color:#e6edf3;border-color:#30363d }
.ca-pick-qty       { width:65px;background:#161b22;color:#e6edf3;border-color:#30363d }
.ca-pick-total     { width:100px;background:#0d1117;color:#90ee90;border-color:#30363d }
.ca-fleet-list     { min-height:60px;border:1px solid #30363d;border-radius:.375rem;padding:.5rem;background:#161b22 }
.ca-fleet-empty    { font-size:.8rem }
.bt-groups-empty   { font-size:.78rem;padding:4px }
.ca-ready-btn      { min-width:100px;font-weight:600 }
.ca-fleet-hidden   { font-size:.85rem;font-style:italic;border:1px solid #30363d;border-radius:.375rem;background:#161b22 }
.ca-ready-notice   { font-size:.85rem;color:#90ee90;font-weight:600 }

/* ── Battle UI ─────────────────────────────────────────────────────────── */
.bt-section-label  { font-size:.65rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;padding:2px 8px;border-radius:3px;margin-bottom:6px;display:inline-block;cursor:pointer;list-style:none }
.bt-section-label::-webkit-details-marker { display:none }
.bt-section-line   { background:#1f2a3f;color:#58a6ff;border:1px solid #58a6ff }
.bt-section-res    { background:#21262d;color:#8b949e;border:1px solid #444 }
.bt-section-destroyed { background:#2d1214;color:#f85149;border:1px solid #f85149 }
.bt-section-brokenoff { background:#1f3a1f;color:#90ee90;border:1px solid #90ee90 }
.bt-section-details:not(:last-child) { border-bottom:2px solid #21262d;padding-bottom:12px }
/* bi-play-fill is a right-pointing triangle by default (matches its use
   elsewhere in this app, e.g. launch/formation-move buttons) — rotated 90°
   when open so it points down, same trick as the mirrored recover icon
   (transform:scaleX(-1)). Pure CSS toggle via the [open] attribute — no JS
   needed since <details> already handles the click/open-state natively. */
.bt-section-toggle-icon { display:inline-block;transition:transform .15s }
.bt-section-details[open] > summary .bt-section-toggle-icon { transform:rotate(90deg) }
.bt-attacker-badge { font-size:.65rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
                      padding:2px 8px;border-radius:3px;margin-bottom:6px;margin-left:6px;
                      display:inline-block;background:#2d1414;color:#ff7b7b;border:1px solid #ff7b7b }
/* The nested .bt-owner-me/.bt-owner-opp span (used at .72rem elsewhere, on
   group cards) would otherwise stretch this badge's line-box taller than
   .bt-section-label's — force it back down to the badge's own size. */
.bt-attacker-badge .bt-owner-me,
.bt-attacker-badge .bt-owner-opp { font-size:inherit;font-weight:inherit }
.bt-range-badge    { font-size:.65rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
                      padding:2px 8px;border-radius:3px;margin-bottom:6px;margin-left:6px;
                      display:inline-block;background:#132d1a;color:#90ee90;border:1px solid #90ee90 }
.bt-group-list     { display:flex;flex-wrap:wrap;gap:6px }
.bt-row-break      { flex-basis:100%;height:0;margin:0;padding:0 }
.bt-group-card     { flex:1 1 240px;min-width:240px;background:#161b22;border:1px solid #30363d;border-radius:5px;padding:8px }
@media (min-width:576px) {
    .bt-group-card { max-width:50% }
}
/* The Stage B fire-allocation modal shows ONE cloned card in a plain block
   container (#bt-fire-alloc-target-clone), not the two-up .bt-group-list
   flex row the 50% cap above exists for — without this it renders at half
   the modal's width for no reason. Same media query as the rule it
   counteracts, since that's the only width where the cap applies. */
@media (min-width:576px) {
    #bt-fire-alloc-target-clone .bt-group-card { max-width:100% }
}
.bt-group-card-me  { border-color:#58a6ff }
.bt-group-card-opp { border-color:#f0a500 }
/* Fire controls card, injected right after the currently-targeted group card
   (see renderSection()) — a left accent (same red as .bt-badge-targeted)
   distinguishes it from an actual ship card without otherwise disrupting the
   shared .bt-group-card flex/wrap sizing. */
.bt-fire-card      { border-color: #da3633; border-left:10px solid #da3633 }
.bt-group-header   { display:flex;align-items:center;justify-content:space-between;margin:-8px -8px 3px -8px;
                      padding:4px 6px;border-radius:4px 4px 0 0 }
.bt-group-card-me  .bt-group-header { background:rgba(88,166,255,.15) }
.bt-group-card-opp .bt-group-header { background:rgba(240,165,0,.15) }
.bt-group-header-left { display:flex;align-items:center;gap:6px }
.bt-owner-me, .bt-owner-opp { font-size:.72rem;font-weight:600;padding:1px 7px;border-radius:3px;
                              display:inline-block;cursor:pointer;white-space:nowrap }
.bt-owner-me       { color:#58a6ff;border:1px solid #58a6ff }
.bt-owner-opp      { color:#f0a500;border:1px solid #f0a500 }
/* A long nickname (>~21 chars) would otherwise word-wrap the owner badge
   onto two lines — bound it to one line with an ellipsis instead. Scoped to
   just the nick text (not the whole badge, which also carries " · N× ship"
   or a tactics score) via this inner wrapper, so the badge's border/click
   target and the surrounding text stay intact. */
.bt-owner-nick     { display:inline-block;max-width:100px;overflow:hidden;
                      text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom }
.bt-owner-popup    { margin:2px 0 6px;padding:6px 8px;background:#161b22;border-radius:5px;font-size:.72rem;color:#e6edf3 }
.bt-owner-me-popup { border:1px solid #58a6ff }
.bt-owner-opp-popup{ border:1px solid #f0a500 }
.bt-owner-line     { padding:1px 0 }
.bt-formation-label{ font-size:.68rem;color:#c9d1d9 }
/* Card identity row — sits directly above the USP line. The ship's own name
   carries the contrast; class and tonnage are supporting detail, dimmed so
   the eye lands on the name first. */
.bt-ship-identity  { font-size:.72rem;color:#e6edf3;font-style:italic;margin:0 0 1px }
.bt-ship-class     { color:#c9d1d9 }
.bt-ship-tons      { color:#8b949e;font-style:normal }
/* "#2 of 5" — stays in the header beside the quantity badge. Inherits what
   .bt-ship-name used to style, since it is what remains of that span. */
.bt-ship-index     { font-size:.68rem;color:#e6edf3;font-style:italic }
.bt-fire-target-name { color:#f0a500 }
.bt-usp            { font-family:monospace;font-size:.75rem;color:#90ee90;margin:0 0 5px }
.bt-usp-changed    { color:#ff7b7b;font-weight:700 }
.bt-step-bar       { background:#1c2128;border:1px solid #30363d;border-radius:5px;padding:8px 14px;margin-bottom:10px;display:flex;align-items:center;gap:12px;flex-wrap:wrap }
.bt-step-bar-offset{ padding-right:52px }
.bt-step-tile      { display:flex;flex-direction:column;align-items:center;line-height:1.1 }
.bt-step-tile-label{ font-size:.62rem;color:#8b949e;text-transform:uppercase;letter-spacing:.05em }
.bt-step-tile-value{ font-size:1.3rem;font-weight:700;color:#f0a500;min-width:28px;text-align:center }
.bt-step-name      { font-weight:600;color:#e6edf3;font-size:.9rem }
.bt-step-hint      { font-size:.8rem;color:#8b949e;flex:1 }
.bt-range-hint-value { color:#58a6ff;font-weight:700 }
.bt-skirmish-row   { background:#1c2128;border:1px solid #30363d;border-radius:5px;margin-bottom:10px }
.bt-skirmish-summary{ padding:8px 14px;font-weight:600;color:#e6edf3;font-size:.9rem;cursor:pointer;list-style:none }
.bt-skirmish-summary::-webkit-details-marker{ display:none }
.bt-skirmish-body  { padding:0 14px 12px }
.bt-log-label      { font-size:.7rem;color:#8b949e;font-weight:600;text-transform:uppercase;letter-spacing:.06em;margin-bottom:4px }
.bt-action-btn     { padding:3px 10px;font-size:.82rem;font-weight:600;border-radius:4px;cursor:pointer }
.bt-btn-pass       { background:#30363d;color:#adbac7 }
.bt-btn-line       { background:#1f2a3f;color:#58a6ff;border:1px solid #58a6ff }
.bt-btn-reserve    { background:#21262d;color:#58a6ff;border:1px solid #58a6ff }
.bt-btn-split      { background:#2d2210;color:#f0a500;border:1px solid #f0a500;margin-left:4px }
.bt-action-btn + .bt-recover-toggle-btn { margin-left:4px }
.bt-craft-row      { display:flex;align-items:center;gap:6px;margin-top:6px;flex-wrap:wrap }
.bt-craft-badge    { font-size:.7rem;font-weight:600;background:#21262d;color:#8b949e;border:1px solid #30363d;cursor:pointer }
/* Compact click-triggered help popup for the craft badge (Ship Designer's
   .help-wrap/.help-popup are sized for full-width inputs, not inline badges) */
.bt-help-wrap      { position:relative;display:inline-block }
.bt-help-popup     { position:absolute;z-index:30;width:220px;margin:2px 0;
                      background:#1c2128;border:1px solid #30363d;border-radius:4px;
                      padding:.5rem .65rem;font-size:.72rem;color:#cccccc;white-space:pre-wrap }
/* Shortfall flash messages (launch/recover rate or capacity capped) trigger
   off tiny icon-only buttons — a width matching the trigger (the shared
   .help-popup default) would be unreadably narrow, so this gets a fixed,
   viewport-capped width instead. Horizontal on-screen clamping is handled
   in help_popup.js's flash()/position(). */
.bt-flash-popup    { position:absolute;z-index:30;width:240px;max-width:80vw;margin:2px 0;
                      background:#1c2128;border:1px solid #30363d;border-radius:4px;
                      padding:.5rem .65rem;font-size:.72rem;color:#cccccc;white-space:pre-wrap }
.bt-craft-count    { display:inline-block;min-width:50px;text-align:center;background:#0d1117;color:#e6edf3;border:1px solid #30363d;border-radius:3px;font-size:.85rem;padding:4px 6px }
.bt-recover-popup  { margin-top:6px;padding:8px;background:#161b22;border:1px solid #30363d;border-radius:5px }
.bt-recover-row    { display:flex;flex-direction:column;gap:6px;margin-bottom:10px }
.bt-recover-row:last-of-type { margin-bottom:0 }
.bt-recover-label-row { font-size:.7rem;color:#8b949e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap }
.bt-recover-qty-row { display:flex;align-items:center;gap:6px }
.bt-recover-count  { display:inline-block;min-width:50px;flex:0 0 auto;text-align:center;background:#0d1117;color:#e6edf3;border:1px solid #30363d;border-radius:3px;font-size:.85rem;padding:4px 6px }
.bt-recover-step,
.bt-recover-pct    { background:#30363d;color:#adbac7;border:none;border-radius:3px;font-size:.72rem;padding:3px 6px;flex:1 1 0;min-width:0;text-align:center }
.bt-recover-action-row { display:flex }
.bt-btn-launch      { background:#1f3a1f;color:#90ee90;border:1px solid #90ee90 }
.bt-btn-launch-all  { background:#1f3a1f;color:#90ee90;border:1px solid #90ee90 }
.bt-status-msg     { font-size:.82rem }
.bt-panel-hint     { font-size:.8rem;color:#e6edf3;margin-bottom:6px }
.bt-help-section   { margin-bottom:8px;font-size:.78rem }
.bt-help-section > summary { color:#fff;cursor:pointer;font-weight:600;padding:2px 0;list-style:revert }
.bt-help-content   { margin-top:4px;padding:8px;background:#161b22;border:1px solid #30363d;border-radius:4px;color:#cccccc }
.bt-help-content p { margin:0 0 6px }
.bt-help-content p:last-child { margin-bottom:0 }
/* Badge-style "How do these controls work?" summary — rectangle badge in
   light red, with a matching light-red bottom border running continuously
   under both the badge and the label text (one shared border on the
   wrapper, not two separate underlines, so it reads as a single accent). */
.bt-help-badge-b-wrap { display:inline-flex;align-items:center;gap:6px;border-bottom:2px solid #f5b7bb }
.bt-help-badge-b   { display:inline-block;background:#f5b7bb;color:#3a0d10;font-weight:700;font-size:.72rem;
                      padding:1px 7px;border-radius:2px;line-height:1.3 }
.bt-panel-title    { font-size:.82rem;color:#e6edf3;font-weight:600;margin-bottom:4px }
.bt-targeted-msg   { font-size:.82rem;color:#ff7b7b;font-weight:600;margin-bottom:4px }
/* Same blue as .bt-owner-me's "You" label in group cards. */
.bt-fire-result-line { color:#58a6ff }
.bt-dec-row        { border-bottom:1px solid #21262d;padding:5px 0;font-size:.8rem;display:flex;flex-direction:column;gap:4px }
.bt-dec-line       { display:flex;flex-wrap:wrap;gap:10px;align-items:center }
.bt-dec-label      { color:#cccccc;white-space:nowrap;display:flex;align-items:center;gap:4px }
.dec-qty           { width:80px }
/* .dec-bo-select and .dec-bg used to style two <select> elements here. Both
   are .bt-opt-picker button groups now and take their look from .bt-opt-btn,
   so the rule is gone rather than left to style nothing.

   With that select gone and the three quantity fields converted from
   <input type="number"> to <output>, the battle view has NO focusable form
   control left on a group card. Nothing for iOS Safari to auto-zoom on focus,
   nothing to raise the keyboard over the card being decided on, and nothing
   for a stray desktop scroll wheel to silently re-value. The quantities are
   set entirely by the buttons around them, which is how they were always
   actually used. Bounds now live in data-min/data-max — see clampQty(). */
/* Read-only badges reflecting a card's current pre-combat decision state —
   shown on any card, any step, once the underlying ship flags are set. */
.bt-decision-badges{ display:flex;flex-wrap:wrap;gap:4px;margin:2px 0 4px }
/* The ACTIONABLE strip, beneath the passive .bt-decision-badges one. Every
   badge here opens a .bt-card-panel of controls (or, for SURRENDER, acts
   directly), so it is visually separated from the state readouts above. */
.bt-action-badges  { display:flex;flex-wrap:wrap;gap:4px;margin:0 0 4px;padding-top:4px;border-top:1px dashed #21262d }
.bt-badge-action   { background:#30363d;color:#adbac7;border:1px solid #444c56;cursor:pointer }
.bt-badge-action[aria-expanded="true"] { background:#444c56;color:#e6edf3 }
.bt-card-panel     { margin:4px 0 6px;padding:8px;background:#161b22;border:1px solid #30363d;border-radius:5px }
/* Option picker — a <select> replacement built from the same black buttons as
   the [-10][-1][+1][+10] qty stepper. Scrolls rather than stretching the card
   when a list is long (Crew Transfer can offer every ship you own). */
.bt-opt-picker     { display:flex;flex-wrap:wrap;gap:4px;margin:4px 0;max-height:8.5rem;overflow-y:auto }
.bt-opt-btn        { font-size:.72rem;padding:3px 10px }
.bt-opt-btn.selected { background:#347d39;color:#fff }
.bt-opt-group      { flex-basis:100%;font-size:.62rem;font-weight:700;letter-spacing:.06em;
                      text-transform:uppercase;color:#768390;margin:2px 0 0 }
.bt-decision-badge { font-size:.65rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
                      padding:1px 7px;border-radius:3px;display:inline-block }
button.bt-decision-badge { font-family:inherit;line-height:normal }
.bt-badge-ea       { background:#3a1414;color:#ff7b7b;border:1px solid #ff7b7b }
.bt-badge-bo       { background:#1f2a3f;color:#58a6ff;border:1px solid #58a6ff }
.bt-badge-desig    { background:#2d2210;color:#f0a500;border:1px solid #f0a500 }
.bt-badge-flicker  { background:#21262d;color:#8b949e;border:1px solid #444 }
.bt-badge-disabled  { background:#21262d;color:#8b949e;border:1px solid #8b949e }
.bt-badge-boardable { background:#3a1414;color:#ff4d4d;border:1px solid #ff4d4d }
/* A toggle now, like [DMG]/[BTTY] — a card can hold captors and prizes at
   once, so the per-ship breakdown is where the detail lives. */
.bt-badge-captured  { background:#0d2b1f;color:#3fb950;border:1px solid #3fb950;cursor:pointer }
/* [NO EP] — a hull producing no energy points, so every powered system is
   dead. A toggle, like [CAPTURED]/[DMG]: current fuel and fuel_shattered are
   both outside groupKey(), so a card holds a mix and the per-ship breakdown
   is where the cause lives. Amber while the plant is merely damaged (a Step 9
   repair can bring it back), red once any cause is permanent — a shattered
   tank, or a Power Plant Disabled critical, neither of which is repairable.
   Distinct from .bt-badge-flicker's "EP n/m", which is capacitor CHARGE. */
.bt-badge-noep      { background:#2d2210;color:#f0a500;border:1px solid #f0a500;cursor:pointer }
.bt-badge-noep-permanent { background:#3a1414;color:#ff4d4d;border-color:#ff4d4d }
/* A Frozen Watch already in flight to this card — informational, so it reads
   as a pending good rather than damage. */
.bt-badge-watch     { background:#0d2233;color:#58a6ff;border:1px solid #58a6ff }
.bt-badge-surrender { background:#21262d;color:#fff;border:1px solid #fff }
button.bt-badge-surrender { cursor:pointer }
/* Step 4 [Break Off?] toggle — reuses .bt-badge-bo's blue (#58a6ff, the same
   token as .bt-owner-me "You" and .bt-group-card-me) and just adds the
   affordance, same as button.bt-badge-surrender above. */
button.bt-dec-toggle-btn { cursor:pointer }
button.bt-dec-toggle-btn[aria-expanded="true"] { background:#58a6ff;color:#0d1117 }
.bt-badge-targeted { background:#da3633;color:#fff;border:1px solid #da3633 }
.bt-badge-dmg      { background:#da3633;color:#fff;border:1px solid #da3633;cursor:pointer }
.bt-dmg-popup      { margin:2px 0 6px;padding:6px 8px;background:#161b22;border:1px solid #da3633;border-radius:5px;font-size:.72rem;color:#e6edf3 }
.bt-dmg-line       { padding:1px 0 }
.bt-dmg-ship-block { margin-bottom:6px }
.bt-dmg-ship-block:last-child { margin-bottom:0 }
.bt-dmg-ship-name  { font-size:.68rem;color:#e6edf3;font-style:italic;margin:0 -8px 1px;padding:2px 8px }
.bt-badge-btty     { background:#0d1117;color:#90ee90;border:1px solid #90ee90;cursor:pointer }
.bt-btty-popup     { margin:2px 0 6px;padding:6px 8px;background:#161b22;border:1px solid #90ee90;border-radius:5px;font-size:.72rem;color:#e6edf3 }
.bt-btty-line      { padding:1px 0 }
.bt-btty-line-divider { padding-bottom:4px;margin-bottom:3px;border-bottom:1px solid #30363d }
.bt-btty-footer-row { display:flex }
.bt-btty-footer-col { width:50%;text-align:left }
.bt-btty-ship-block { margin-bottom:6px }
.bt-btty-ship-block:last-child { margin-bottom:0 }
.bt-btty-ship-name  { font-size:.68rem;color:#e6edf3;font-style:italic;margin:0 -8px 1px;padding:2px 8px }
.bt-group-card-me  .bt-dmg-ship-name, .bt-group-card-me  .bt-btty-ship-name { background:rgba(88,166,255,.15) }
.bt-group-card-opp .bt-dmg-ship-name, .bt-group-card-opp .bt-btty-ship-name { background:rgba(240,165,0,.15) }
.bt-log            { background:#0d1117;border:1px solid #21262d;border-radius:4px;padding:6px 10px;min-height:600px;overflow-y:auto;font-family:monospace;font-size:.72rem;color:#8b949e }
.bt-log-turn       { margin-bottom:4px }
.bt-log-step       { margin:2px 0 2px 14px }
.bt-log-group      { margin:2px 0 2px 14px }
/* Parent (collapsible) rows are color-coded by indentation depth — every
   node at the same depth shares one color, regardless of turn/step/group type. */
.bt-log-turn > summary { font-weight:700;color:#f0a500;cursor:pointer;padding:2px 0;list-style:revert }
.bt-log-turn > .bt-log-step > summary,
.bt-log-turn > .bt-log-group > summary { font-weight:600;color:#58a6ff;cursor:pointer;padding:2px 0;list-style:revert }
.bt-log-turn > .bt-log-group > .bt-log-group > summary { font-weight:600;color:#90ee90;cursor:pointer;padding:2px 0;list-style:revert }
/* Leaf (non-collapsible) rows are always white */
.bt-log-entry      { padding:2px 0 2px 14px;color:#fff }
.bt-log-entry:last-child { border:none }
.bt-log-roll-hit   { color:#90ee90;font-weight:600 }
.bt-log-roll-miss  { color:#ff7b7b;font-weight:600 }
/* Matches .bt-owner-me/.bt-owner-opp's colors (group-card "You"/opponent
   labels) so a nick reads the same color everywhere it appears. */
.bt-log-nick-me    { color:#58a6ff;font-weight:600 }
.bt-log-nick-opp   { color:#f0a500;font-weight:600 }
/* Stage A (Fire Allocation): tappable toggle buttons, one per (weapon_type,
   factor) option grouped/summed across the whole battle line — btn-light
   (unselected) / btn-success (selected), toggled on click; mobile has no
   hover state so no hover rule is needed. */
.bt-fire-options-scroll { max-height:180px;overflow-y:auto;display:flex;flex-wrap:wrap;gap:8px;padding:4px 0;margin-bottom:4px }
.bt-fire-opt-btn   { font-size:.8rem;font-weight:600 }
/* Stage B (Battery Allocation): scrollable list of per-ship slider blocks. */
.bt-alloc-scroll   { max-height:220px;overflow-y:auto;border:1px solid #21262d;border-radius:4px;padding:4px 8px }
.bt-alloc-row      { display:flex;align-items:center;gap:6px;padding:2px 6px;margin:0 -6px;border-radius:4px;font-size:.8rem }
.bt-alloc-row:nth-child(even) { background:rgba(255,255,255,.06) }
.bt-alloc-row .bt-dec-label { width:130px;color:#e6edf3;font-weight:600 }
.bt-alloc-he-label { font-size:.75rem;color:#e6edf3;white-space:nowrap }
/* Stage B fleet-wide fire-allocation modal — one card-style row per
   (weapon type, factor), not the single-line flex layout .bt-alloc-row
   uses for Active Defense's per-hit rows. */
.bt-fire-alloc-row { background:#161b22;border:1px solid #21262d;border-radius:6px;padding:10px 12px;margin-bottom:10px }
.bt-fire-alloc-row .bt-dec-label { width:auto;color:#e6edf3;font-weight:600;white-space:normal;margin-bottom:8px }
.bt-alloc-count-row { display:flex;align-items:center;gap:8px;margin-bottom:8px }
.bt-alloc-count    { display:inline-block;min-width:80px;text-align:center;background:#0d1117;color:#e6edf3;border:1px solid #30363d;border-radius:3px;font-size:.9rem;padding:4px 6px }
.bt-alloc-step     { flex:0 0 auto }
.bt-alloc-pct-row  { display:flex;gap:6px;flex-wrap:wrap }
.bt-alloc-pct,
.bt-qty-pct        { flex:1 1 0;min-width:0;text-align:center }
/* Shared qty control (qtyStepperHtml): the stepper row plus the
   None/25%/50%/All row, used by Step 4 break-off, Step 8 pursuit, Step 9
   boarding and the fire-allocation modal. */
.bt-qty-control    { margin-bottom:6px }
/* On a group card the control shares a cramped .bt-dec-line / .bt-board-row
   with a label (and Board's 50%-width column), so the input takes a
   proportional width instead of .bt-alloc-count's fixed 80px. Two classes
   beats that rule's single class, so source order doesn't matter. The
   fire-allocation modal keeps 80px — it has the room. */
.bt-alloc-count.dec-qty,
.bt-alloc-count.dec-pursuit-qty,
.bt-alloc-count.dec-board-qty,
.bt-alloc-count.dec-fw-qty { width:50% }
.bt-defense-badges { display:flex;gap:6px;flex-wrap:wrap }
.bt-defense-badge  { font-size:.7rem;font-weight:600;background:#21262d;border:1px solid #30363d;border-radius:3px;padding:2px 8px;cursor:pointer;user-select:none }
.bt-defense-badge:hover { filter:brightness(1.3) }
.bt-defense-legend { display:flex;gap:8px;flex-wrap:wrap;padding:6px 0;border-top:1px solid #21262d;margin-top:4px }
.bt-legend-badge   { font-size:.7rem;font-weight:600;background:transparent;border:1px solid;border-radius:3px;padding:2px 8px;cursor:pointer;user-select:none }
/* Selectable legend (Allocate Active Defenses modal) — toggles which
   defense type(s) [Water-fill Defenses] applies to; unselected types dim
   instead of disappearing so the pool count stays visible/comparable. */
.bt-legend-badge:not(.bt-legend-badge-selected) { opacity:.4 }
.bt-legend-badge-selected { background:rgba(255,255,255,.1) }
.bt-legend-qty     { color:#90ee90 }
/* Allocate Active Defenses modal — one card-style block per incoming hit
   (same visual weight as .bt-fire-alloc-row), each with a bordered sub-row
   per applicable defense type using a step-button count instead of an
   editable input (defense allocation has no "% of pool" concept per hit).
   modal-body is a flex column with fixed help/legend/water-fill-button
   sections so #bt-defense-alloc-rows can grow to fill all remaining
   height and scroll internally, instead of the whole body scrolling. */
.bt-defense-alloc-dialog { height:75vh;max-width:600px }
.bt-defense-alloc-dialog .modal-content { height:100%;max-height:100% }
.bt-defense-alloc-dialog .modal-body { display:flex;flex-direction:column;overflow:hidden;min-height:0 }
.bt-defense-alloc-dialog #bt-defense-alloc-rows { flex:1 1 auto;min-height:0;max-height:none;overflow-y:auto }
.bt-defense-alloc-row    { background:#161b22;border:1px solid #21262d;border-radius:6px;padding:10px 12px;margin-bottom:10px }
.bt-defense-alloc-title  { color:#e6edf3;font-weight:600;margin-bottom:8px }
/* Summary strip at the top of the list — one badge per distinct weapon+factor
   being allocated against, so a long list can be read without scrolling it.
   Shares .bt-defense-alloc-row's card styling; the badge deliberately does
   NOT reuse .bt-legend-badge, whose cursor:pointer would advertise a toggle
   these don't have. */
.bt-defense-hit-summary  { display:flex;flex-wrap:wrap;gap:6px }
.bt-defense-hit-badge    { font-size:.7rem;font-weight:600;color:#e6edf3;background:#21262d;
                           border:1px solid #30363d;border-radius:3px;padding:2px 8px }
/* Count picked out in the same green .bt-legend-qty uses for its remaining
   pool, so a quantity reads as a quantity throughout the modal. */
.bt-defense-hit-count    { color:#90ee90;margin-left:3px }
.bt-defense-alloc-subrow { display:flex;align-items:center;gap:8px;border:1px solid;border-radius:4px;padding:4px 8px;margin-bottom:6px }
.bt-defense-alloc-subrow:last-child { margin-bottom:0 }
.bt-defense-alloc-subrow .bt-dec-label { width:80px }
.bt-defense-alloc-count  { width:24px;text-align:center;color:#90ee90;font-weight:600 }
/* Task #31: "Assign Damage" card — one pool block per Weapon-n/Screen-n
   requirement, badges click-to-hit with a live water-fill preview. */
.bt-assign-pool    { margin-bottom:8px }
.bt-assign-pool-label { font-size:.75rem;color:#8b949e;margin-bottom:4px }
/* Opposing-player gold (matches .bt-owner-opp) — the screen being disabled is
   the ENEMY's, unlike the Weapon/Screen pools above it, so it reads in their
   colour rather than the neutral grey. */
.bt-assign-disable-label { color:#f0a500 }
/* Reusable click-confirmation fade for .bt-btn-confirm-style submit buttons
   (see withSubmitFade() in ship_combat.js) — the button would otherwise be
   torn out by the next re-render before a click ever got visible feedback. */
.bt-btn-fade-out { transition:opacity 1s ease;opacity:0;pointer-events:none }
.bt-assign-badges  { display:flex;gap:10px;flex-wrap:wrap }
.bt-assign-badge   { font-size:.7rem;font-weight:600;background:#21262d;border:1px solid #30363d;border-radius:3px;padding:6px 12px;cursor:pointer;user-select:none }
.bt-assign-badge:hover { filter:brightness(1.3) }
.bt-assign-badge-disabled { opacity:.4;cursor:not-allowed;pointer-events:none }
.bt-weapon-row     { display:flex;align-items:center;gap:6px;padding:3px 0;border-bottom:1px solid #21262d;font-size:.8rem }
.bt-weapon-row:last-child { border:none }
.bt-weapon-name    { width:130px;color:#e6edf3;font-weight:600 }
.bt-weapon-factor  { width:40px;color:#58a6ff;text-align:center }
.bt-weapon-slider  { width:100px }
.bt-weapon-val     { width:30px;text-align:center;font-size:.8rem }
.bt-weapon-max     { font-size:.7rem;color:#6e7681 }
.bt-nuke-label     { font-size:.7rem;color:#cccccc;white-space:nowrap }
.bt-range-btn      { padding:4px 16px;font-size:.85rem;font-weight:700;border-radius:4px;border:2px solid;cursor:pointer }
.bt-range-long     { background:#1f2a3f;border-color:#58a6ff;color:#58a6ff }
.bt-range-short    { background:#1a2a1a;border-color:#90ee90;color:#90ee90 }
.bt-range-btn.selected     { opacity:1 }
.bt-range-btn:not(.selected) { opacity:.45 }
.bt-victory-banner { text-align:center;padding:24px 0 }
.bt-victory-label  { font-size:2.5rem;font-weight:700;letter-spacing:.04em }
.bt-victory-win    { color:#90ee90 }
.bt-victory-loss   { color:#ff7b7b }
.bt-victory-draw   { color:#f0a500 }
.bt-turn-label     { font-size:.9rem }

/* Per-bout run-down under the victory headline. The banner is centred, so
   the table is centred as a block while its own cells stay left-aligned —
   ragged outcome/turn columns are much harder to scan than a ragged edge. */
.bt-bout-summary                          { margin:0 auto;border-collapse:collapse;font-size:.85rem }
.bt-bout-summary td                       { padding:2px 10px;vertical-align:top;text-align:left }
td.bt-bout-outcome                        { font-weight:700 }
/* The fleet action is the row that decided the headline — every other row is
   a trailing skirmish worth a quarter as much. Marking it is what explains a
   banner that disagrees with the LAST row of its own summary.
   Scoped to the NAME cell only, and to td.* so it cannot outrank
   .bt-bout-outcome. A blanket `.bt-bout-row-primary td { font-weight:600 }`
   is more specific than a bare `.bt-bout-outcome` and quietly made the row it
   was meant to emphasise the only one with a LIGHTER outcome than the rest. */
tr.bt-bout-row-primary td.bt-bout-name    { font-weight:600 }
tr.bt-bout-row-primary td:first-child     { border-left:2px solid currentColor }
/* Numbers align on their own edge — 1.0 over 0.25 only reads as one scale
   when the decimal points line up, which left-aligning breaks. */
td.bt-bout-points                         { text-align:right;font-variant-numeric:tabular-nums }
.bt-bout-note                             { font-size:.78rem;opacity:.75 }

/* ── Channel drawer ─────────────────────────────────────────────────────── */
#ca-chat-drawer {
    position:absolute;top:0;right:0;width:340px;height:100%;
    transform:translateX(100%);transition:transform 250ms ease;
    z-index:20;display:flex;flex-direction:column;
    background:#0d1117;border-left:1px solid #30363d;
    box-shadow:-4px 0 18px rgba(0,0,0,.55)
}
#ca-chat-drawer.open { transform:translateX(0) }
#ca-chat-toggle {
    position:absolute;top:10px;right:10px;z-index:21;
    width:36px;height:36px;border-radius:50%;border:1px solid #90ee90;
    background:#1c2128;color:#adbac7;cursor:pointer;
    display:flex;align-items:center;justify-content:center;font-size:1.1rem
}
#ca-chat-toggle:hover { background:#2d333b }
/* Green echoes the meeting room's "Accept" open-channel button, signaling
   this channel persists into the arena — using the app's existing bright
   dark-mode green (.bt-usp/.bt-badge-btty/.bt-range-badge) rather than
   Bootstrap's --bs-success, which is tuned for light backgrounds and reads
   muted against this dark button. */
#ca-chat-toggle .bi-chat-text { color:#90ee90 }
.ca-unread-badge {
    position:absolute;top:-4px;right:-4px;min-width:18px;height:18px;
    border-radius:9px;background:#da3633;color:#fff;
    font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;
    padding:0 4px;pointer-events:none
}

/* ══════════════════════════════════════════════════════════════════════════
   Pending notice — a message carried across a page load (app.js's
   consumePendingNotice). Overlays whatever view the user landed on, since it
   may concern a tab they aren't currently looking at.
   ══════════════════════════════════════════════════════════════════════════ */
.hgr-pending-notice{
    /* Deliberately NOT position:fixed. Every fixed variant tried (left:50% +
       translate, then symmetric insets) put this partly off screen on a real
       phone, because both resolve against a layout viewport that measures
       wider than the visible area on this app's mobile view -- the same
       mismatch that put the repair popup off screen. No amount of viewport
       arithmetic is reliable when the viewport itself is the thing lying.

       Sticky in normal flow sidesteps it entirely: width comes from the flow,
       exactly like .mr-pending-notice above (which has never had this
       problem), and top:0 keeps it visible while scrolling. No left/right, no
       transform, no vw. */
    position:sticky;top:0;
    z-index:1090;                       /* above Bootstrap modals (1055) */
    margin:0 0 8px;border-radius:0;
    box-shadow:0 4px 16px rgba(0,0,0,.45)
}

/* A chosen "One Screen Disabled" target — a selection, not a spent hit, so it
   reads as active (amber, like other confirmed decisions) rather than dimmed
   the way .bt-assign-badge-disabled does. */
.bt-assign-badge-picked { background:#4a3a12;border-color:#d29922;color:#f0c674 }

/* [Assign All] sits at the end of the badge row and is meant to read as one
   more thing to click there, so it takes the badge's own metrics rather than
   .bt-action-btn's larger ones. Bootstrap's .btn supplies the green. */
.bt-assign-all-btn { font-size:.7rem;font-weight:600;border-radius:3px;padding:6px 12px;
                     line-height:normal;border:1px solid transparent }

/* Repair budget "{used} of {max}" — sits between the system select and
   [Attempt]. Both numbers come from the server (poll.php), never from
   counting clicks. */
/* The "N of M" / "(N available)" readout on an action panel's title line.
   Shared by REPAIR and WATCH, which render the same three bands: title +
   count, option picker, then Qty and the confirm button. */
.bt-panel-count, .bt-repair-count { font-size:.72rem;color:#cccccc;white-space:nowrap;padding:0 8px }
