/*
  Light "engraved plates" theme (spec 2026-09-20). Every colour in the
  site reads from these tokens. Text tokens are contrast-checked by
  tests/test_theme_tokens.py: orange as TEXT must be --accent-ink; a label
  on an --accent fill must be --on-accent (white fails AA on #d9691f).
  Served static since 2026-09-02 so all pages share one sheet. CSP allows
  a same-origin stylesheet.
*/
:root{
  --bg:#dddbd6; --surface:#f1efeb; --surface2:#e8e6e1; --border:#a7a399;
  --ink:#1c1b19; --text:#1c1b19; --text2:#5d5a52; --text3:#5d5a52;
  --accent:#d9691f; --accent-hover:#e8833f; --accent-ink:#9e430a; --accent-soft:#f6dcc8; --on-accent:#1c1b19;
  --moss:#446022; --moss-soft:#dfe6d3;
  --amber:#7a5200; --amber-soft:#efe1c2;
  --danger:#a3321f; --danger-soft:#f0d9d4; --on-danger:#f1efeb;
  --inactive-bg:#e2e0db;
  --mono:'Spline Sans Mono',ui-monospace,Consolas,monospace;
  --sans:'IBM Plex Sans',-apple-system,sans-serif;
  --disp:'Bodoni Moda','Times New Roman',serif;
}
*{box-sizing:border-box;}
html,body{margin:0;}
body{background:var(--bg);color:var(--text);font-family:var(--sans);}
a{color:var(--accent-ink);}
.wrap{max-width:1040px;margin:0 auto;padding:44px 24px 80px;display:flex;flex-direction:column;gap:32px;}
.panel{background:var(--surface);border:1px solid var(--border);padding:32px;display:flex;flex-direction:column;gap:22px;}
.eyebrow{font-family:var(--mono);font-size:12.5px;letter-spacing:.14em;color:var(--text2);text-transform:uppercase;}
h1{font-family:var(--sans);font-size:28px;font-weight:700;color:var(--text);margin:0;line-height:1.18;text-wrap:balance;}
.sub{font-size:15px;color:var(--text2);margin:0;line-height:1.55;max-width:56ch;}
form.field-row{display:flex;gap:10px;align-items:stretch;flex-wrap:wrap;}
.input{flex-grow:1;min-width:220px;background:var(--bg);border:1px solid var(--border);color:var(--text);font-family:var(--mono);font-size:14px;padding:13px 15px;}
.btn{font-family:var(--mono);font-size:13.5px;letter-spacing:.1em;font-weight:600;color:var(--on-accent);background:var(--accent);border:1px solid var(--accent);padding:13px 20px;white-space:nowrap;cursor:pointer;}
.card .btn{white-space:normal;}   /* a long tile-button label wraps rather than clipping at the card edge */
.btn.secondary{background:transparent;color:var(--text2);border-color:var(--border);}
.btn.danger{background:var(--danger);border-color:var(--danger);color:var(--on-danger);}   /* destructive action: on-accent ink fails AA on danger */
a.btn{text-decoration:none;}
.hint{font-family:var(--mono);font-size:12.5px;color:var(--text3);}
.error{font-family:var(--mono);font-size:13.5px;color:var(--danger);background:var(--danger-soft);border:1px solid var(--danger);padding:10px 14px;}
.tos-head{display:flex;justify-content:space-between;align-items:baseline;flex-wrap:wrap;gap:8px;}
.tos-title{font-size:16px;font-weight:600;color:var(--text);margin:0;}
.tos-note{font-family:var(--mono);font-size:11.5px;color:var(--text3);letter-spacing:.06em;}
table{width:100%;border-collapse:collapse;}
th{font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);text-align:left;padding:0 12px 10px 0;font-weight:500;border-bottom:1px solid var(--border);}
td{font-size:13px;color:var(--text2);padding:10px 12px 10px 0;vertical-align:top;line-height:1.4;}
.divider{display:flex;align-items:center;gap:14px;}
.divider .line{flex-grow:1;height:1px;background:var(--border);}
.divider .label{font-family:var(--mono);font-size:11.5px;letter-spacing:.16em;color:var(--text3);text-transform:uppercase;}
.soon{font-size:10.5px;letter-spacing:.04em;color:var(--text3);border:1px solid var(--border);padding:1px 5px;text-transform:uppercase;}
.avatar{width:22px;height:22px;background:var(--moss-soft);border:1px solid var(--moss);display:flex;align-items:center;justify-content:center;font-size:11.5px;color:var(--moss);font-weight:600;}
.idstrip{font-size:14px;color:var(--text2);}
.idstrip b{color:var(--text);font-weight:600;}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;}
.card{background:var(--surface);border:1px solid var(--border);padding:20px;display:flex;flex-direction:column;gap:10px;min-height:118px;}
.card-eyebrow{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--text3);}
.card-title{font-size:17px;font-weight:700;color:var(--text);margin:0;}
.card-line{font-size:13.5px;color:var(--text2);margin:0;line-height:1.5;}
.card-line .warpay-amt{color:var(--moss);font-family:var(--mono);font-weight:700;}
.card-line code, .spy-hint code, .sub code{font-family:var(--mono);font-size:12.5px;background:var(--surface2);border:1px solid var(--border);padding:1px 5px;color:var(--text);}
.badge{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:12px;letter-spacing:.04em;padding:4px 9px 4px 7px;width:fit-content;}
.badge .dot{width:6px;height:6px;flex:none;}
.badge.trend-move{padding:4px 9px;}   /* arrow + places: no dot, so no left-heavy padding (CR-023) */
.badge.active{color:var(--moss);background:var(--moss-soft);}
.badge.active .dot{background:var(--moss);}
.badge.inactive{color:var(--text3);background:var(--inactive-bg);}
.badge.inactive .dot{background:var(--text3);}
.badge.unknown{color:var(--amber);background:var(--amber-soft);}
.badge.unknown .dot{background:var(--amber);}
.badge.restricted{color:var(--accent-ink);background:var(--accent-soft);}
.badge.restricted .dot{background:var(--accent);}
.card form{margin-top:2px;}
/* Command Centre overview tile — the one restricted card, marked out by the accent. */
.card.card-cc{border-color:var(--accent);background:var(--surface2);}
.card-cc .card-eyebrow{display:inline-flex;align-items:center;gap:6px;color:var(--accent-ink);background:var(--accent-soft);padding:4px 8px;width:fit-content;font-size:11px;letter-spacing:.16em;}
.cc-lock{flex:none;}
.ghost{border:1px dashed var(--border);display:flex;align-items:center;justify-content:center;color:var(--text3);font-family:var(--mono);font-size:12.5px;letter-spacing:.06em;min-height:118px;}

/* ---- War Dashboard (2026-09-02) ---- */
.warhead h1{font-size:24px;}
.warhead .whenline{font-family:var(--mono);font-size:13.5px;color:var(--text2);letter-spacing:.02em;margin:0;}
.warhead .whenline b{color:var(--text);font-weight:600;}
.warhead .hint{margin:0;}
.muted-panel h1{color:var(--text2);font-weight:600;font-size:21px;}
.statusrow{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;}
.spy-hint{font-size:13.5px;color:var(--text2);margin:0;line-height:1.5;}
.spylist th:first-child, .spylist td:first-child{width:26px;color:var(--text3);font-family:var(--mono);}
.spylist td.spy-name{overflow-wrap:anywhere;}
.spylist td.spy-name a{color:var(--text);text-decoration:none;font-weight:600;}
.spylist td.spy-level{font-family:var(--mono);color:var(--text3);}
/* wrap, don't nowrap: a long estimate range would otherwise widen the
   Spies table past a phone viewport (same class of bug as the stalk
   tables' status cell — see the containment block lower down). */
.spylist td.spy-bs{font-family:var(--mono);color:var(--text);text-align:left;white-space:normal;overflow-wrap:anywhere;}
.spylist td.spy-bs.unknown{color:var(--text3);}
.spy-star{color:var(--amber);font-weight:700;cursor:help;}

/* ---- War Dashboard: collapsible + reorderable feature sections (2026-09-02) ---- */
.features{display:flex;flex-direction:column;gap:16px;}
.feature{background:var(--surface);border:1px solid var(--border);}
.feature-head{list-style:none;cursor:pointer;display:flex;align-items:center;gap:12px;padding:20px 24px;user-select:none;}
.feature-head::-webkit-details-marker{display:none;}
.feature-head::before{content:"\25B8";font-family:var(--mono);font-size:12.5px;color:var(--text3);flex:none;transition:transform .15s ease;}
.feature[open] .feature-head::before{transform:rotate(90deg);}
.feature-title{font-size:16px;font-weight:600;color:var(--text);flex-grow:1;}
.feature-grip{font-family:var(--mono);font-size:14px;letter-spacing:-2px;color:var(--text3);cursor:grab;flex:none;padding:0 2px;}
.feature-grip:active{cursor:grabbing;}
.feature-move{display:flex;gap:4px;flex:none;}
.movebtn{font-family:var(--mono);font-size:13.5px;line-height:1;color:var(--text3);background:transparent;border:1px solid var(--border);padding:4px 7px;cursor:pointer;}
.feature.dragging{opacity:.45;}
.feature-body{padding:2px 24px 24px;display:flex;flex-direction:column;gap:22px;}
.warhead-live{border-color:var(--danger);}
.warhead-done{opacity:.82;}
/* "Pop out" — open this one panel in its own window (app.js: Document
   Picture-in-Picture where supported, else a popup at /dashboard/panel/<key>). */
.feature-popout{display:flex;flex:none;}
.popoutbtn{font-family:var(--mono);font-size:14px;line-height:1;color:var(--text3);background:transparent;border:1px solid var(--border);padding:4px 8px;cursor:pointer;}

/* ---- Pop-out standalone page (templates/panel_popout.html) — no nav,
   fills its window; the feature panel markup + app.js are shared with the
   Dashboard. ---- */
.wrap-popout{max-width:none;padding:14px 16px 40px;gap:16px;}
.popout-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
  padding:12px 16px;border-bottom:1px solid var(--border);background:var(--surface);}
.popout-title{font-family:var(--sans);font-weight:700;font-size:15px;color:var(--text);}
.popout-enemy{font-family:var(--mono);font-size:12px;color:var(--text3);}
.popout-back{margin-left:auto;font-family:var(--mono);font-size:12px;color:var(--text2);text-decoration:none;}

/* ---- nav "live" dot + Overview Dashboard card ---- */
.live-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--danger);vertical-align:middle;margin-left:5px;animation:live-pulse 2s ease-out infinite;}
@keyframes live-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--danger) 55%,transparent);}70%{box-shadow:0 0 0 6px color-mix(in srgb,var(--danger) 0%,transparent);}100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--danger) 0%,transparent);}}
@media (prefers-reduced-motion: reduce){.live-dot{animation:none;}}
a.cardlink{text-decoration:none;color:inherit;}
.feature-strip{display:flex;flex-wrap:wrap;gap:6px;margin-top:auto;padding-top:4px;}
.chip{font-family:var(--mono);font-size:10.5px;letter-spacing:.03em;padding:2px 6px;border:1px solid var(--border);color:var(--text3);white-space:nowrap;}
.chip.active{color:var(--moss);border-color:var(--moss);}
.chip.unknown{color:var(--amber);border-color:var(--amber);}

/* ---- hospital / travel stalk tables ---- */
.stalklist td.stalk-dot, .stalklist th:first-child{width:18px;padding-right:8px;}
.stalklist td.stalk-status{font-family:var(--mono);color:var(--text2);white-space:nowrap;}
.stalklist td.stalk-status.okay{color:var(--moss);}
.stalklist td.stalk-status.landing{color:var(--amber);}
[data-traveller-tables]{display:block;}
/* Group subheading — a full-width <td> row inside the single traveller
   table (one table, not one per group, so every section shares the same
   column geometry). Extra top space separates a group from the one
   above; the first group sits right under the header row. */
.traveller-group td.tg-head{font-family:var(--mono);font-size:12.5px;letter-spacing:.08em;color:var(--text2);text-transform:none;border-bottom:none;padding:4px 0 2px;}
.traveller-group tbody + tbody td.tg-head{padding-top:20px;}

/*
  Keep stalk-table content within bounds on a narrow screen (2026-09-02).
  `white-space:nowrap` on the status cell (and on `.spy-bs` near the top
  of this file) made those columns un-shrinkable, so a line like
  "In flight — ETA unknown" or "Landing in 12:34" pushed the whole table
  past a ~375px viewport and clipped the last column off-screen. Fix: let
  those cells wrap, stop a single long token (a spaceless username) from
  widening the table, and hard-clip the feature body so nothing can bleed
  the page sideways. Auto table layout is kept on purpose — app.js
  rebuilds the travel tables wholesale (thead included) on every /feed
  poll, so a <colgroup> or first-row width hint wouldn't survive.
  `tbody` in the selectors is only to win specificity over the nowrap
  rules earlier in the file without depending on source order.
*/
.stalklist tbody td.stalk-status{white-space:normal;overflow-wrap:anywhere;}
.stalklist tbody td.spy-bs{white-space:normal;overflow-wrap:anywhere;}
.stalklist tbody td.spy-name{overflow-wrap:anywhere;}
.feature-body{overflow-x:hidden;overflow-x:clip;}

@media (max-width:560px){
  /* Bodoni titles are wider than the old sans, so a one-row head squeezed the title to two lines. Phones: title on
     row 1 (after the chevron/grip), status badge left + move/pop-out buttons right on row 2, same for every panel. */
  .feature-head{flex-wrap:wrap;row-gap:10px;}
  .feature-title{flex:1 1 calc(100% - 60px);}
  .feature-head .badge{white-space:nowrap;margin-right:auto;}
  .wrap{padding-left:14px;padding-right:14px;}
  .panel{padding:24px 18px;}
  .feature-head{padding-left:16px;padding-right:16px;}
  .feature-body{padding-left:14px;padding-right:14px;}
  .stalklist th,.stalklist td{padding-right:8px;}
}

/*
  Indicators column (2026-09-02) — a small run of emoji: abroad-country
  flag, 🩸 self-hosp, 🎯 bounty, and dib markers later. `nowrap` is fine
  here (it's glyphs, not free text); `width:1%` shrinks it to content so
  it can't steal width from Player / Status under auto layout.
*/
.stalklist td.stalk-ind{white-space:nowrap;line-height:1;width:1%;}
.stalklist td.stalk-ind .ind{margin-right:4px;}
.stalklist td.stalk-ind .ind:last-child{margin-right:0;}
.stalklist th.col-ind{width:1%;white-space:nowrap;}

/*
  Column density (2026-09-02, per-panel since 2026-09-05). "simple" drops
  the non-essential columns (Lvl, Est. stats) so a phone never scrolls a
  stalk table sideways; essential = status dot, Player, Indicators,
  Status. The server always renders data-density="simple" on each
  .feature panel that has one (mobile-first, and the no-JS fallback);
  app.js bumps a wide screen to "full" on load per panel and persists
  each panel's own choice to localStorage independently, so choosing
  "full" on Hospital doesn't affect Travel. The Spies table is
  deliberately untagged, so it keeps every column in both modes.
*/
.feature[data-density="simple"] .col-extra{display:none;}
.features-bar{display:flex;justify-content:flex-end;}
.densitybtn{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--text3);background:transparent;border:1px solid var(--border);padding:5px 10px;cursor:pointer;}
.densitybtn[aria-pressed="true"]{color:var(--moss);border-color:var(--moss);}

/*
  Highlight (2026-09-04). A personal watch marker on enemy rows —
  localStorage only, per browser + per viewer (app.js, keyed by
  data-viewer-id). Whole matching row gets the accent tint, mirroring
  the War Pay "row-you" treatment but in orange so it doesn't read as
  "you". The star sits in the Player cell; no server state.
*/
.hl-star{background:transparent;border:0;color:var(--text3);font-size:15px;line-height:1;padding:4px 8px 4px 0;margin:0;cursor:pointer;vertical-align:middle;}
.hl-star[aria-pressed="true"]{color:var(--accent-ink);}
.hl-star.hl-star-full-warn{color:var(--danger);}
.stalklist tr.is-highlighted td,
.spylist tr.is-highlighted td{background:var(--accent-soft);}
.stalklist tr.is-highlighted td.spy-name a,
.spylist tr.is-highlighted td.spy-name a{color:var(--accent-ink);}
.spy-hl-bar{display:flex;justify-content:flex-end;margin:0 0 10px;}
.spy-hl-filtered tr[data-torn-id]:not(.is-highlighted){display:none;}

/* ---- War Pay page (2026-09-03) ---- */
.warpay-hidden{font-family:var(--mono);font-size:12.5px;color:var(--text3);margin:-8px 0 0;}
.paylist{display:flex;flex-direction:column;gap:14px;}
.paycard{background:var(--surface);border:1px solid var(--border);}
.paycard-head{list-style:none;cursor:pointer;display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;padding:18px 22px;user-select:none;}
.paycard-head::-webkit-details-marker{display:none;}
.paycard-head::before{content:"\25B8";font-family:var(--mono);font-size:12.5px;color:var(--text3);flex:none;align-self:center;transition:transform .15s ease;}
.paycard[open] .paycard-head::before{transform:rotate(90deg);}
.paycard-enemy{font-size:16px;font-weight:700;color:var(--text);}
.paycard-when{font-family:var(--mono);font-size:12.5px;color:var(--text3);}
.paycard-mine{font-family:var(--mono);font-size:13.5px;color:var(--text2);margin-left:auto;}
.paycard-mine b{color:var(--moss);}
.paycard-body{padding:2px 22px 22px;display:flex;flex-direction:column;gap:20px;overflow-x:hidden;overflow-x:clip;}

/* Column density toggle — one control for every war's table. Simple =
   Member / Share / Pay only (server default, mobile-first); app.js
   reveals the button and bumps a wide screen to "full". */
.warpay-bar{display:flex;justify-content:flex-end;margin-bottom:12px;}   /* was -4px: the button sat on the plate's top edge */
#warpay-list[data-density="simple"] .paytable .col-extra{display:none;}
/* simple view is only 3 columns — let a long name wrap so it fits a
   phone without the Pay column scrolling out of sight. Full view keeps
   names on one line and the table scrolls (it's meant to be dense). */
#warpay-list[data-density="simple"] .paytable td.pay-name{white-space:normal;overflow-wrap:anywhere;}

.mywar{background:var(--surface2);border:1px solid var(--border);padding:16px 18px;display:flex;flex-direction:column;gap:12px;}
.mywar-eyebrow,.totals-eyebrow{font-family:var(--mono);font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--text2);}
.mywar-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:12px;}
.mywar-grid .k,.mywar-pay .k{display:block;font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);}
.mywar-grid .v{display:block;font-size:17px;font-weight:700;color:var(--text);font-family:var(--mono);margin-top:3px;}
.mywar-pay{border-top:1px solid var(--border);padding-top:10px;}
.mywar-pay .v.big{display:block;font-size:22px;font-weight:700;color:var(--moss);font-family:var(--mono);margin-top:2px;}
.mywar-pay .split{display:block;font-family:var(--mono);font-size:12.5px;color:var(--text3);margin-top:3px;}

.totals-table{width:100%;border-collapse:collapse;max-width:360px;}
.totals-table td{font-family:var(--mono);font-size:13px;color:var(--text2);padding:4px 0;border:none;}
.totals-table td:last-child{text-align:right;color:var(--text);}
.totals-table tr.totals-strong td{color:var(--text);font-weight:700;border-top:1px solid var(--border);padding-top:7px;}

.paycard-warnings{margin:0;padding:10px 14px 10px 30px;background:var(--amber-soft);border:1px solid var(--amber-soft);}
.paycard-warnings li{font-family:var(--mono);font-size:12.5px;color:var(--amber);line-height:1.5;}

.paytable-wrap{overflow-x:auto;}
.paytable{width:100%;border-collapse:collapse;}
.paytable th{font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);text-align:left;padding:0 10px 8px 0;font-weight:500;border-bottom:1px solid var(--border);}
.paytable td{font-size:13px;color:var(--text2);padding:7px 10px 7px 0;border-bottom:1px solid var(--border);white-space:nowrap;}
.paytable td.num,.paytable th.num{text-align:right;font-family:var(--mono);}
.paytable td.muted{color:var(--text3);}
/* names stay on one line — the .paytable-wrap scrolls horizontally, so a
   long username should push the scroll width, not wrap to a column of
   single letters. */
.paytable td.pay-name{color:var(--text);font-weight:600;}
.paytable td.pay-amount{color:var(--text);}
.paytable tr.row-absent td{color:var(--text3);}
.paytable tr.row-absent td.pay-name{color:var(--text3);font-weight:400;}
.paytable tr.row-you td{background:var(--moss-soft);}
.paytable tr.row-you td.pay-name,.paytable tr.row-you td.pay-amount{color:var(--moss);}
.you-tag{font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--moss);border:1px solid var(--moss);padding:1px 4px;margin-left:5px;vertical-align:middle;}
.paycard-sheet{margin:0;font-family:var(--mono);font-size:12.5px;}

@media (max-width:560px){
  .paytable th,.paytable td{padding-right:6px;}   /* phones: tighter gutters so names wrap later (Topdo/g) */
  .paycard-head{padding-left:16px;padding-right:16px;}
  .paycard-body{padding-left:16px;padding-right:16px;}
  .paycard-mine{margin-left:0;width:100%;}
}

/* Forecast tile (CR-019 Command Centre) */
.forecast-panel{gap:14px;}
.forecast-stage{position:relative;width:100%;aspect-ratio:16/7;min-height:200px;background:var(--surface2);border:1px solid var(--border);}
#forecast-canvas{display:block;width:100%;height:100%;}
.forecast-msg{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:0 24px;margin:0;font-family:var(--mono);font-size:13px;color:var(--text2);pointer-events:none;}
.forecast-msg:empty{display:none;}
.forecast-instruments{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--border);}
.forecast-instruments>div{padding:10px 12px;border-right:1px solid var(--border);display:flex;flex-direction:column;gap:3px;}
.forecast-instruments>div:last-child{border-right:0;}
.forecast-k{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--text3);}
.forecast-v{font-family:var(--mono);font-size:14px;color:var(--text);font-variant-numeric:tabular-nums;}
.forecast-v.forecast-sub{font-size:11px;color:var(--text2);}
.forecast-note{margin:0;}
@media (max-width:560px){
  .forecast-instruments{grid-template-columns:1fr 1fr;}
  .forecast-instruments>div:nth-child(2){border-right:0;}
  .forecast-instruments>div:nth-child(1),.forecast-instruments>div:nth-child(2){border-bottom:1px solid var(--border);}
}

/* Natural-decay calculator — collapsible, below the instruments */
.forecast-decay{border:1px solid var(--border);border-top:0;}
.forecast-decay[hidden]{display:none;}
.forecast-decay>summary{cursor:pointer;padding:10px 12px;font-family:var(--mono);font-size:10px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text3);list-style:none;
  display:flex;gap:6px;align-items:baseline;flex-wrap:wrap;}
.forecast-decay>summary::-webkit-details-marker{display:none;}
.forecast-decay>summary::before{content:"\25b8";color:var(--text3);}
.forecast-decay[open]>summary::before{content:"\25be";}
.forecast-decay-when{color:var(--text);text-transform:none;letter-spacing:0;font-size:12px;
  font-variant-numeric:tabular-nums;}
.forecast-decay-body{padding:2px 12px 12px;display:flex;flex-direction:column;gap:10px;}
.forecast-decay-head{margin:0;font-family:var(--mono);font-size:13px;color:var(--text);line-height:1.6;
  font-variant-numeric:tabular-nums;}
.forecast-decay-head .k{color:var(--text3);}
.forecast-decay-tablewrap{max-height:320px;overflow:auto;border:1px solid var(--border);}
.forecast-decay-table{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12px;
  font-variant-numeric:tabular-nums;}
.forecast-decay-table th{position:sticky;top:0;background:var(--surface2);color:var(--text3);
  font-weight:500;font-size:10px;letter-spacing:.06em;text-transform:uppercase;text-align:left;
  padding:6px 10px;border-bottom:1px solid var(--border);}
.forecast-decay-table td{padding:5px 10px;color:var(--text2);border-bottom:1px solid var(--border);white-space:nowrap;}
.forecast-decay-table td.num,.forecast-decay-table th.num{text-align:right;}
.forecast-decay-table tr:last-child td{border-bottom:0;}
.forecast-decay-table tr.is-end td{background:var(--moss-soft);color:var(--moss);font-weight:700;}
.forecast-decay-table tr.is-cap td{color:var(--text3);}

/* CR-024 Forecast — Goal + Bleed tables (below the chart). Reuse .paytable. */
.visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
.fx-warbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 16px;}
.fx-picker{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0;min-width:0;}
.fx-picker label{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text3);}
.fx-picker select{font-family:var(--mono);font-size:13px;color:var(--text);background:var(--surface);border:1px solid var(--border);padding:7px 10px;max-width:100%;min-width:0;}
.fx-show{padding:7px 12px;}
.fx-keep{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.fx-keep form{margin:0;}
.fx-keep .btn{padding:8px 14px;font-size:12px;}
.fx-unkeep{font-family:var(--mono);font-size:11.5px;color:var(--danger);text-decoration:underline;text-underline-offset:2px;}
.fx-retention{margin:-8px 0 0;}
.fx-panel{gap:14px;}
.fx-lede{margin:-6px 0 0;max-width:72ch;line-height:1.5;}
.fx-goalform{display:flex;flex-direction:column;gap:6px;margin:0;padding:14px;border:1px solid var(--border);background:var(--surface2);}
.fx-goalform>label{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text2);}
.fx-sublabel{text-transform:none;letter-spacing:0;color:var(--text3);margin-left:6px;}
.fx-goalrow{display:flex;gap:8px;flex-wrap:wrap;}
.fx-goalrow input{font-family:var(--mono);font-size:15px;color:var(--text);background:var(--surface);border:1px solid var(--border);padding:10px 12px;min-width:0;flex:1 1 10ch;max-width:18ch;}
.fx-goalrow .btn{padding:10px 16px;}
.fx-goalform .hint{margin:2px 0 0;}
.fx-body{display:flex;flex-direction:column;gap:10px;}
.fx-status{margin:0;font-size:15px;color:var(--text2);line-height:1.6;}
.fx-status b{color:var(--text);}
.fx-status.muted{color:var(--text3);}
.fx-when{font-family:var(--mono);}
.fx-by{font-size:13px;color:var(--text2);}
.fx-approx{font-family:var(--mono);font-size:11px;color:var(--amber);background:var(--amber-soft);padding:1px 6px;cursor:help;white-space:nowrap;}
.fx-sum{margin:0;font-family:var(--mono);font-size:12px;color:var(--text3);line-height:1.5;}
.fx-note{margin:0;font-family:var(--mono);font-size:12.5px;color:var(--text2);background:var(--surface2);border:1px solid var(--border);padding:8px 12px;line-height:1.5;}
.fx-note-warn{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-soft);}
.fx-table th.fx-total,.fx-table td.fx-total{border-left:1px solid var(--border);padding-left:10px;}
.fx-table td.fx-total{color:var(--text);font-weight:600;}
.fx-expand{font:inherit;font-weight:600;color:var(--text);background:none;border:0;padding:0;cursor:pointer;text-align:left;display:inline-flex;gap:6px;align-items:baseline;}
.fx-expand::before{content:"\25b8";color:var(--text3);font-size:11px;}
.fx-expand[aria-expanded="true"]::before{content:"\25be";}
.fx-member .fx-tl-row>td{padding:0 0 10px 14px;white-space:normal;background:var(--surface2);}
.fx-tl{width:100%;table-layout:fixed;border-collapse:collapse;font-family:var(--mono);font-size:12px;}
.fx-tl th{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);text-align:left;padding:8px 10px 4px 0;font-weight:500;border-bottom:1px solid var(--border);}
.fx-tl td{padding:4px 10px 4px 0;color:var(--text2);border-bottom:1px solid var(--border);white-space:normal;overflow-wrap:break-word;}
.fx-tl tr:last-child td{border-bottom:0;}
.fx-tl td.fx-target{white-space:normal;overflow-wrap:anywhere;color:var(--text);}
.fx-tl td.fx-type{white-space:normal;}
.fx-tl .fx-date{color:var(--text3);font-size:10.5px;}
.fx-tl tr.fx-crossing td{color:var(--text);font-weight:600;}
.fx-goaltag{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--moss);border:1px solid var(--moss);padding:0 4px;margin-left:4px;white-space:nowrap;}
@media (max-width:560px){
  .fx-table th,.fx-table td{padding-right:6px;font-size:12px;}
  .fx-table th{font-size:10px;letter-spacing:.02em;}
  .fx-table th.fx-total,.fx-table td.fx-total{padding-left:6px;}
  .fx-table td.pay-name{white-space:normal;overflow-wrap:anywhere;}
  .fx-member .fx-tl-row>td{padding-left:4px;}
  .fx-tl th,.fx-tl td{padding-right:6px;font-size:11px;}
  .fx-warbar{flex-direction:column;align-items:stretch;}
  .fx-picker{flex-wrap:nowrap;}
  .fx-picker select{flex:1 1 0;width:0;}   /* a long war label must not widen the page */
}

/* War Pay publishing control (CR-019 Command Centre) */
.warpay-pub-list{display:flex;flex-direction:column;gap:10px;margin-top:16px;}
.warpay-pub-row{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--border);padding:14px 16px;}
.warpay-pub-enemy{font-size:15px;font-weight:600;color:var(--text);}
.warpay-pub-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:5px;}
.warpay-pub-when{font-family:var(--mono);font-size:11.5px;color:var(--text3);}
.warpay-pub-action{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.warpay-pub-links{font-family:var(--mono);font-size:11.5px;color:var(--text3);margin:6px 0 0;}
.warpay-pub-links a{color:var(--text2);text-decoration:underline;text-underline-offset:2px;}
.warpay-pub-links a.danger-link{color:var(--danger);}
.notice{font-family:var(--mono);font-size:13.5px;color:var(--moss);background:var(--moss-soft);border:1px solid var(--moss);padding:10px 14px;}

/* Member Performance tile (CR-020 Command Centre) */
.badge.danger{color:var(--danger);background:var(--danger-soft);}
.badge.danger .dot{background:var(--danger);}
.badge.warn{color:var(--accent-ink);background:var(--accent-soft);}
.badge.warn .dot{background:var(--accent);}
.perf-summary{margin:8px 0 0;font-size:15px;color:var(--text2);line-height:1.6;}
.perf-summary b{color:var(--text);}
.perf-star{color:var(--amber);font-weight:700;}
.perf-warlist{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:6px;}
.perf-warlist li{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:13px;color:var(--text2);}
.perf-war-enemy{font-weight:600;color:var(--text);}
.perf-war-when{font-family:var(--mono);font-size:11.5px;color:var(--text3);}
.perf-foot{margin:12px 0 0;}
.perf-foot p{margin:0 0 9px;}
.perf-foot p:last-child{margin-bottom:0;}
.perf-table td.perf-pos{font-family:var(--mono);color:var(--text3);}
.perf-table td.perf-armoury{white-space:nowrap;font-family:var(--mono);}
.perf-table td.perf-armoury.good{color:var(--moss);}
.perf-table td.perf-armoury.warn{color:var(--amber);}
.perf-table td.perf-armoury.bad{color:var(--danger);}
.perf-table th.perf-warcol,.perf-table td.perf-warcol{color:var(--text2);}
.perf-table th.perf-total,.perf-table td.perf-total{border-left:1px solid var(--border);padding-left:12px;}
.perf-table td.perf-total{color:var(--text);font-weight:600;}
.perf-toolbar{display:flex;flex-direction:column;gap:8px;margin-bottom:8px;}
.perf-bar{display:flex;justify-content:flex-end;align-items:center;gap:14px;}
.perf-png-link{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--text2);text-decoration:underline;text-underline-offset:3px;}
.perf-filter{display:flex;flex-wrap:wrap;align-items:center;gap:6px;}
.perf-filter-label{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text3);}
.perf-role-chip{font-family:var(--mono);font-size:11.5px;color:var(--text3);background:transparent;border:1px solid var(--border);padding:4px 9px;cursor:pointer;}
.perf-role-chip[aria-pressed="true"]{color:var(--moss);border-color:var(--moss);}
.perf-role-chip[aria-pressed="false"]{opacity:.55;text-decoration:line-through;}
.perf-filter-count{font-family:var(--mono);font-size:11px;color:var(--amber);}
#perf-list[data-density="simple"] .paytable .col-extra{display:none;}
#perf-list[data-density="simple"] .paytable .badge{white-space:normal;}
/* Names stay on one line in the fewer-columns view too — on desktop
   there's width to spare, and mid-word wrapping ("Metal / militia / 314")
   just looks broken. Only wrap on a genuinely narrow viewport, same as
   the Armoury tables below. */
@media (max-width:720px){
  #perf-list[data-density="simple"] .paytable td.pay-name{white-space:normal;overflow-wrap:anywhere;}
}

/* My Performance: keep the trend badge on one line (the shared simple-view
   rule above lets badges wrap). */
#perf-list.my-perf .paytable .badge{white-space:nowrap;}

/* Personal highlight markers on the Performance / Armoury Member rosters
   (localStorage only, shared "acorn.cc.highlights.<viewer>" key). Reuses
   the .hl-star / .is-highlighted / .hl-star-full-warn styles from the War
   dashboard. */
.perf-table tr.is-highlighted td{background:var(--accent-soft);}
.perf-table tr.is-highlighted td.pay-name .pay-name-text{color:var(--accent-ink);}
.perf-table.perf-hl-filtered tbody tr[data-torn-id]:not(.is-highlighted){display:none;}
.perf-hl-filter[aria-pressed="true"]{color:var(--accent-ink);border-color:var(--accent);}

/* Date-range switcher above the two Armoury panels — a plain pill row of
   links (?window=); the active one carries the accent. */
.cc-range{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 14px;}
.cc-range-label{font-family:var(--mono);font-size:11px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text3);margin-right:2px;}
.cc-range-opt{font-size:12px;padding:4px 10px;border:1px solid var(--border);border-radius:999px;
  color:var(--text2);text-decoration:none;white-space:nowrap;}
.cc-range-opt.is-active{border-color:var(--accent);color:var(--accent-ink);font-weight:600;}

/* A trailing filler column: an empty last cell that grabs all the slack,
   so the real columns pack against the left (numbers stay next to names)
   while the table still spans its container — at any width, any column
   count. This is what a star-filtered Armoury Member table needs (2-3
   visible columns in a wide panel would otherwise spread out or drift
   right); it collapses to nothing once the real columns fill the width. */
.paytable .col-fill{width:100%;padding:0;min-width:0;}

/* Command Centre Armoury — the two-table panel reuses .paytable /
   .perf-* wholesale; these are the only armoury-specific rules.
   Tighter cell gutters (9px vs 10px), and the Value column sits flush
   against the filler. Starring an item in the Faction table adds
   .is-highlighted (accent tint, via the rule above). */
#armoury-faction .paytable th,
#armoury-faction .paytable td,
#armoury-members .paytable th,
#armoury-members .paytable td{padding-right:9px;}
#armoury-faction .paytable .perf-total,
#armoury-members .paytable .perf-total{padding-right:0;}

/* Mobile only: let names + item headers wrap so 15 item columns are less
   of a scroll. On desktop there's width to spare — keep names on one line
   (mid-word wrapping there just looks broken). */
@media (max-width:720px){
  #armoury-faction .paytable td.pay-name,
  #armoury-members .paytable td.pay-name{white-space:normal;overflow-wrap:anywhere;}
  #armoury-members .perf-table th[data-item-col]{white-space:normal;line-height:1.15;
    min-width:0;max-width:6em;vertical-align:bottom;}
  #armoury-members .perf-table td[data-item-col]{min-width:0;}
}
#armoury-faction .hl-star[aria-pressed="true"],
#armoury-faction tr.is-highlighted td.pay-name .pay-name-text{color:var(--accent-ink);}
#armoury-faction .densitybtn[aria-pressed="false"]{color:var(--accent-ink);border-color:var(--accent);}

/* ---- Plates (spec §3.3) + display type (spec §3.2) ----
   Appended last on purpose: same-specificity rules above lose to these.
   Existing card-like classes are styled here; templates keep their class
   names (tests and app.js key off them). */
.plate,.card,.panel,.feature,.paycard{position:relative;background:var(--surface);border:1px solid var(--ink);}
.plate::before,.card::before,.panel::before,.feature::before,.paycard::before,
.plate::after,.card::after,.panel::after,.feature::after,.paycard::after{
  content:"+";position:absolute;z-index:1;pointer-events:none;
  font:10px/1 var(--mono);color:var(--ink);background:var(--bg);padding:0 2px;}
.plate::before,.card::before,.panel::before,.feature::before,.paycard::before{left:-6px;top:-6px;}
.plate::after,.card::after,.panel::after,.feature::after,.paycard::after{right:-6px;bottom:-6px;}
.plate.live,.card-live,.warhead-live{border-color:var(--accent);}
.card-live .badge.active{background:var(--accent);color:var(--on-accent);}
.card-live .badge.active .dot{background:var(--on-accent);}
@media (min-width:900px){.card-live{grid-column:span 2;}.grid{grid-auto-flow:dense;}}   /* dense: a 2-wide live tile must not leave a hole in the row above it */
.warpay-pub-row{border-color:var(--ink);}
.mywar{border-color:var(--ink);}

h1,.card-title,.paycard-enemy,.feature-title,.tos-title,.popout-title{font-family:var(--disp);}
h1{font-weight:700;}
.card-title,.paycard-enemy,.feature-title{font-weight:700;}
.mywar-grid .v,.mywar-pay .v.big,.card-line .warpay-amt,.perf-summary b,.totals-table td:last-child{
  font-family:var(--disp);font-variant-numeric:lining-nums tabular-nums;}
.paytable td.num,.perf-table td.num{font-variant-numeric:lining-nums tabular-nums;}

/* ---- Site header (spec §3.5, §9b) ---- */
.sitehead{display:flex;align-items:center;flex-wrap:wrap;column-gap:26px;row-gap:12px;padding:0 0 14px;border-bottom:1px solid var(--border);
  /* Content row = the 32px user chip (+14 padding +1 border). The logged-out header has no chip, so without
     this floor its wordmark sat 3px higher than on home and the login rosette->header handoff jumped. */
  min-height:47px;}
.brand{display:inline-flex;align-items:center;gap:9px;flex:none;color:var(--text);text-decoration:none;}
.brand .mk{display:inline-block;width:26px;height:26px;flex:none;}
.brand .word{font-family:var(--mono);font-size:12px;font-weight:500;letter-spacing:.16em;position:relative;}
.mark{display:block;width:26px;height:26px;}
.mark-r1{stroke:var(--accent);stroke-width:.55;transform-origin:12px 12px;animation:mark-spin 40s linear infinite;}
.mark-r2{stroke:var(--ink);stroke-width:.4;opacity:.45;transform-origin:12px 12px;animation:mark-spin 30s linear infinite reverse;}
.mark-acorn{fill:var(--surface);stroke:var(--ink);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}
@keyframes mark-spin{to{transform:rotate(360deg);}}
/* flex-basis:auto (max-content), not 0: when brand + links + chip cannot share one row the whole nav drops to its own row under the brand
   (links left, chip right) instead of the chip wrapping under the links beside a vertically-centred brand. */
.sitenav{display:flex;align-items:center;justify-content:space-between;gap:22px;flex:1 1 auto;min-width:0;flex-wrap:wrap;}
.navlinks{display:flex;align-items:center;gap:22px;flex-wrap:wrap;}
.navlink{position:relative;font-family:var(--mono);font-size:12px;letter-spacing:.12em;color:var(--text2);display:inline-flex;align-items:center;gap:6px;text-decoration:none;}
.navlink.active{color:var(--text);}
.userchip{display:flex;align-items:center;gap:10px;margin-left:auto;font-family:var(--mono);font-size:12px;color:var(--text2);}
.userchip-text{min-width:0;overflow-wrap:anywhere;}
.logout-form{display:inline;margin:0;}
.logout-btn{background:none;border:none;color:var(--text2);font-family:var(--mono);font-size:12px;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:2px;}
.menubtn{display:none;flex:none;width:34px;height:34px;padding:0;border:1px solid var(--ink);background:var(--surface);cursor:pointer;
  flex-direction:column;align-items:center;justify-content:center;gap:4px;}
.menubtn i{display:block;width:14px;height:1.5px;background:var(--ink);transition:transform .2s ease,opacity .2s ease;}
.menubtn[aria-expanded="true"] i:nth-child(1){transform:translateY(5.5px) rotate(45deg);}
.menubtn[aria-expanded="true"] i:nth-child(2){opacity:0;}
.menubtn[aria-expanded="true"] i:nth-child(3){transform:translateY(-5.5px) rotate(-45deg);}
@media (max-width:720px){
  .sitehead{flex-wrap:wrap;gap:12px;}
  .brand .mk,.mark{width:24px;height:24px;}
  .js .menubtn{display:flex;margin-left:auto;}
  .sitenav{flex-basis:100%;flex-direction:column;align-items:stretch;gap:14px;}
  .js .sitenav{display:none;}
  .js .sitenav.is-open{display:flex;}
  .navlinks{flex-direction:column;align-items:stretch;gap:0;}
  .navlink{min-height:44px;border-bottom:1px solid var(--border);padding:0 2px;font-size:12.5px;justify-content:space-between;}
  .navlink.active{box-shadow:inset 3px 0 0 var(--accent);padding-left:10px;font-weight:500;}
  .userchip{flex-wrap:wrap;margin-left:0;}   /* desktop margin-left:auto would inset the chip inside the stretched sheet column */
  .logout-form{flex-basis:100%;}
  .logout-btn{width:100%;min-height:44px;border:1px solid var(--ink);text-decoration:none;}
}
@media (prefers-reduced-motion:reduce){.mark-r1,.mark-r2{animation:none;}.menubtn i{transition:none;}}
/* ---- Home header (spec §6) ---- */
.homehead{display:flex;flex-direction:column;gap:6px;}
.greet{font:italic 500 clamp(24px,4vw,32px)/1.15 var(--disp);margin:0;}
.greet-name{color:var(--accent-ink);font-style:italic;}
[data-greeting]{visibility:hidden;}
[data-greeting].is-set{visibility:visible;}
.idline{margin:0;font:400 12px var(--mono);letter-spacing:.08em;color:var(--text2);}
/* == INTERACTION STATES == */
/* Spec §7. Hover only where a real pointer exists; every :hover selector has a
   :focus-visible twin (tests/test_theme_tokens.py enforces this); touch gets :active.
   Nothing shifts layout; colour is never the only cue. */
:focus-visible{outline:2px solid var(--accent-ink);outline-offset:2px;}
input:focus{outline:2px solid var(--accent-ink);outline-offset:2px;}
a,button,summary{-webkit-tap-highlight-color:transparent;}

/* A. nav links: orange underline draws in from the left */
.navlink::after,.brand .word::after{content:"";position:absolute;left:0;right:0;bottom:-6px;height:2px;background:var(--accent);
  transform:scaleX(0);transform-origin:left;transition:transform .22s ease;}
.navlink.active::after{transform:scaleX(1);}
a.navlink:focus-visible,.brand:focus-visible{color:var(--text);}
a.navlink:focus-visible::after,.brand:focus-visible .word::after{transform:scaleX(1);}
.brand:focus-visible .mark-r1,.brand:focus-visible .mark-r2{animation-duration:6s;}
@media (hover:hover){
  a.navlink:hover,.brand:hover{color:var(--text);}
  a.navlink:hover::after,.brand:hover .word::after{transform:scaleX(1);}
  .brand:hover .mark-r1,.brand:hover .mark-r2{animation-duration:6s;}
}

/* B. plates that are links: printed-plate lift, crosses turn orange */
a.cardlink{text-decoration:none;color:inherit;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease;}
a.cardlink:focus-visible{border-color:var(--accent);transform:translate(-2px,-2px);box-shadow:3px 3px 0 var(--ink);}
a.cardlink::before,a.cardlink::after{transition:color .18s ease,transform .18s ease;}
.cc-lock{transition:transform .18s ease;}
a.cardlink:focus-visible::before,a.cardlink:focus-visible::after{color:var(--accent-ink);transform:rotate(45deg);}
a.cardlink:focus-visible .cc-lock{transform:rotate(-14deg);}
a.cardlink:active{transform:translate(0,0);box-shadow:none;border-color:var(--accent);}
@media (hover:hover){
  a.cardlink:hover{border-color:var(--accent);transform:translate(-2px,-2px);box-shadow:3px 3px 0 var(--ink);}
  a.cardlink:hover::before,a.cardlink:hover::after{color:var(--accent-ink);transform:rotate(45deg);}
  a.cardlink:hover .cc-lock{transform:rotate(-14deg);}
}

/* C. primary button */
.btn{transition:background .15s ease;}
.btn:focus-visible{background:var(--accent-hover);}
.btn:active{background:var(--accent-hover);transform:translateY(1px);}
.btn.danger:focus-visible,.btn.danger:active{background:var(--ink);border-color:var(--ink);color:var(--on-danger);}
.btn .arr{display:inline-block;transition:transform .15s ease;}
.btn:focus-visible .arr{transform:translateX(3px);}
@media (hover:hover){
  .btn:hover{background:var(--accent-hover);}
  .btn.danger:hover{background:var(--ink);border-color:var(--ink);color:var(--on-danger);}
  .btn:hover .arr{transform:translateX(3px);}
}

/* D. utility buttons and chips: border to ink.
   Pressed/active toggles are excluded from the generic colour+border change so their own
   cue (moss / accent / danger) always survives hover and focus; they get a surface fill instead. */
.popout-back{border:1px solid var(--border);padding:4px 10px;}
.btn.secondary:not([aria-pressed="true"]):not(.is-active):focus-visible,
.movebtn:not([aria-pressed="true"]):not(.is-active):focus-visible,
.popoutbtn:not([aria-pressed="true"]):not(.is-active):focus-visible,
.densitybtn:not([aria-pressed="true"]):not(.is-active):focus-visible,
.perf-role-chip:not([aria-pressed="true"]):not(.is-active):focus-visible,
.cc-range-opt:not([aria-pressed="true"]):not(.is-active):focus-visible,
.popout-back:focus-visible{color:var(--text);border-color:var(--ink);background:var(--surface);}
.densitybtn[aria-pressed="true"]:focus-visible,.perf-role-chip[aria-pressed="true"]:focus-visible,
.cc-range-opt.is-active:focus-visible{background:var(--surface2);}
#armoury-faction .densitybtn[aria-pressed="false"]:focus-visible{background:var(--surface2);}
.btn.secondary:active,.movebtn:active,.popoutbtn:active,.densitybtn:active,.perf-role-chip:active,.cc-range-opt:active,
.popout-back:active{background:var(--surface2);}
@media (hover:hover){
  .btn.secondary:not([aria-pressed="true"]):not(.is-active):hover,
  .movebtn:not([aria-pressed="true"]):not(.is-active):hover,
  .popoutbtn:not([aria-pressed="true"]):not(.is-active):hover,
  .densitybtn:not([aria-pressed="true"]):not(.is-active):hover,
  .perf-role-chip:not([aria-pressed="true"]):not(.is-active):hover,
  .cc-range-opt:not([aria-pressed="true"]):not(.is-active):hover,
  .popout-back:hover{color:var(--text);border-color:var(--ink);background:var(--surface);}
  .densitybtn[aria-pressed="true"]:hover,.perf-role-chip[aria-pressed="true"]:hover,
  .cc-range-opt.is-active:hover{background:var(--surface2);}
  #armoury-faction .densitybtn[aria-pressed="false"]:hover{background:var(--surface2);}
}

/* E. text links and small controls */
/* table row links (spy names etc.): orange-ink with a dotted underline */
.spylist td.spy-name a:focus-visible{color:var(--accent-ink);text-decoration:underline dotted;text-underline-offset:3px;}
.perf-png-link:focus-visible,.warpay-pub-links a:focus-visible,
.paycard-sheet a:focus-visible,.spy-hint a:focus-visible{color:var(--text);text-decoration:underline;text-underline-offset:3px;}
.warpay-pub-links a.danger-link:focus-visible{color:var(--danger);}
/* stars sit flush against scroll/clip containers (.paytable-wrap, .feature-body): draw the ring inside so it is not cut off */
.hl-star:focus-visible{outline-offset:-2px;}
/* the "full" warning star keeps its danger colour */
.hl-star:not(.hl-star-full-warn):focus-visible{color:var(--accent-ink);}
/* Log out: resting hairline, a 2px orange-ink underline slides in from the left */
.logout-btn{text-decoration:none;padding-bottom:2px;
  background:linear-gradient(var(--accent-ink),var(--accent-ink)) 0 100%/0 2px no-repeat,
             linear-gradient(var(--text3),var(--text3)) 0 100%/100% 1px no-repeat;
  transition:background-size .22s ease,color .15s ease;}
.logout-btn:focus-visible{color:var(--accent-ink);background-size:100% 2px,100% 1px;}
/* user chip: border to ink (transparent at rest so nothing shifts) */
.userchip{border:1px solid transparent;padding:4px 10px;transition:border-color .15s ease;}
.userchip:focus-visible,.userchip:focus-within{border-color:var(--ink);}
@media (hover:hover){
  .spylist td.spy-name a:hover{color:var(--accent-ink);text-decoration:underline dotted;text-underline-offset:3px;}
  .perf-png-link:hover,.warpay-pub-links a:hover,
  .paycard-sheet a:hover,.spy-hint a:hover{color:var(--text);text-decoration:underline;text-underline-offset:3px;}
  .warpay-pub-links a.danger-link:hover{color:var(--danger);}
  .hl-star:not(.hl-star-full-warn):hover{color:var(--accent-ink);}
  .logout-btn:hover{color:var(--accent-ink);background-size:100% 2px,100% 1px;}
  .userchip:hover{border-color:var(--ink);}
}

/* F. collapsible headers: faint fill */
.feature-head:focus-visible,.paycard-head:focus-visible,.forecast-decay>summary:focus-visible{background:var(--surface2);}
@media (hover:hover){
  .feature-head:hover,.paycard-head:hover,.forecast-decay>summary:hover{background:var(--surface2);}
}

/* G. menu button (mobile) — added in Task 4: the brief's block did not cover it */
.menubtn:focus-visible{background:var(--surface2);}
.menubtn:active{background:var(--accent-soft);}
@media (hover:hover){.menubtn:hover{background:var(--surface2);}}

/* H. touch: pressed feedback for the stacked mobile nav; its active cue is the inset bar,
   so the desktop underline is switched off there */
@media (max-width:720px){
  .navlink::after{display:none;}
  .userchip{padding:0;border:0;}
  .logout-btn{background:none;padding-bottom:0;}
  .navlink:active,.spylist td.spy-name a:active{background:var(--surface2);}
  .logout-btn:active{background:var(--surface2);}
  .logout-btn:focus-visible{border-color:var(--accent-ink);}   /* the stacked button has a border, so colour is not the only cue */
}
@media (max-width:720px) and (hover:hover){.logout-btn:hover{border-color:var(--accent-ink);}}

@media (prefers-reduced-motion:reduce){
  .navlink::after,.brand .word::after{transition:none;}
  a.cardlink,a.cardlink:hover,a.cardlink:focus-visible,a.cardlink:active{transform:none;box-shadow:none;transition:none;}
  .btn,.btn:active{transform:none;transition:none;}
  a.cardlink::before,a.cardlink::after,a.cardlink:hover::before,a.cardlink:hover::after,
  a.cardlink:focus-visible::before,a.cardlink:focus-visible::after{transform:none;transition:none;}
  .cc-lock,a.cardlink:hover .cc-lock,a.cardlink:focus-visible .cc-lock{transform:none;transition:none;}
  .btn .arr,.btn:hover .arr,.btn:focus-visible .arr{transform:none;transition:none;}
  .logout-btn,.userchip{transition:none;}
}

/* CR-024 Forecast timeline toggle */
.fx-expand:focus-visible{color:var(--accent-ink);}
@media (hover:hover){
  .fx-expand:hover{color:var(--accent-ink);}
}
