/* ReGenesis front-end — no external assets, works from a single stylesheet. */

:root {
  --bg: #14100c;
  --panel: #1f1913;
  --panel-2: #28211a;
  --border: #3d3226;
  --text: #d8cbb4;
  --muted: #8a7c66;
  --accent: #c9a44c;
  --accent-2: #8fb04e;
  --danger: #c05b4d;
  --link: #d8b86a;
  --font: Georgia, "Times New Roman", serif;
  /* The body text size, themable (Willow reads larger). Body copy and every
     font:inherit control ride it; the chrome bars are rem-sized so they cannot. */
  --font-size: 15px;
  /* Pass 67: shared status colors — every theme gets correct throne colors; themes may
     override. --pa = the per-acre accent; --warn-subdued flags suppressed thief/wizard
     figures; --fx-op / --fx-atk color operation and attack-debuff effects. */
  --good: #90ee90;
  --bad: #ec7566;
  /* 67.h.12: solid result-box fills — dark enough for white text in every theme
     (the --good/--bad text colors are too light to sit under white). */
  --result-good: #2e7d32;
  --result-bad: #b3261e;
  --pa: #5b9bd5;
  --warn-subdued: #e06c6c;
  --advice: #ffe9a8;
  --fx-op: #b58ae0;
  --fx-atk: #e0904a;
  /* Pass 72: the chart facelift — legacy STRUCTURE (an alpha zebra wash on alternate
     rows + a styled header bar), palette per theme. Legacy used the same
     rgba(48,48,48,.6) wash in every skin; here each theme tunes its own. */
  --row-alt: rgba(0, 0, 0, 0.25);
  --th-bg: radial-gradient(ellipse at center, #3a3325 0%, #241e15 100%);
  --th-fg: var(--accent);
  --th-shadow: -1px 1px 2px #000;
  /* Pass 65: theme-INVARIANT chrome. The nav rail/strip, ticker, resource bar, and
     advisor chips use ONLY these — no theme may override them (the legacy rule: the bar
     chrome stays dark/gold in every skin; only the content area re-dresses). */
  --chrome-bg: #14141f;
  --chrome-panel: #1c1c2a;
  --chrome-border: #3a3a52;
  --chrome-text: #cfc8dd;
  --chrome-muted: #8a84a0;
  --chrome-gold-1: #ffe9a8;
  --chrome-gold-2: #ffc300;
  --ticker-h: 34px;
  --resbar-h: 86px;
  --navstrip-h: 52px;
}

* { box-sizing: border-box; }

/* Plain links read on every theme (ticket-0022, 2026-10-03): the default theme never coloured
   them, so logged-out visitors got the browser's blue/purple on the dark background. The
   themed `:root[data-theme] a` rules still win where a theme sets its own. */
/* :where() keeps these at zero specificity, so any classed link (buttons, chips, cards) keeps
   its own colour. */
:where(a, a:visited) { color: var(--link); }
:where(a:hover) { color: var(--accent); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--font-size)/1.45 var(--font);
}

#topbar {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.6rem 1.2rem;
  background: var(--panel);
  border-bottom: 2px solid var(--border);
  flex-wrap: wrap;
}

#brand {
  display: grid;
  gap: 0.2rem;
  flex: 0 0 auto;
}
#brand .brand-word { display: block; color: #d8dfef; font-family: Georgia, serif; font-size: clamp(1.7rem, 3vw, 2.25rem); font-weight: 800; letter-spacing: 0.045em; line-height: .95; text-shadow: 0 1px 0 #0a0c12, 0 2px 0 #0a0c12, 0 4px 8px rgba(0,0,0,.65); white-space: nowrap; }
#brand .brand-word span { color: var(--accent); text-shadow: 0 1px 0 #7d5600, 0 2px 0 #4c3300, 0 4px 8px rgba(0,0,0,.7); }
#brand .brand-badges { display: flex; gap: .35rem; }
#brand #btn-staff-command, #brand #btn-council-lobby { width: fit-content; padding: 0.12rem 0.48rem; border: 1px solid var(--chrome-gold-2); border-radius: 999px; color: var(--chrome-gold-1); background: #172845; font-size: 0.65rem; font-weight: bold; letter-spacing: 0.08em; text-transform: uppercase; }
#brand #btn-staff-command:hover, #brand #btn-council-lobby:hover { color: #1a1408; background: var(--chrome-gold-2); }

#worldbar { flex: 1; color: var(--muted); }
#worldbar b { color: var(--text); }
#worldbar:empty { display: none; }

/* The signed-in header prioritizes identity and logout. Secondary destinations live
   in a closed-by-default menu so the row remains useful on mobile. */
#session { display: flex; flex: 1 1 auto; align-items: center; justify-content: flex-end; gap: .45rem; min-width: 0; }
#session button, #session a.btnlink { margin: 0; border-radius: 999px; }
#session .site-menu { position: relative; }
#session .menu-toggle { display: grid; gap: .2rem; width: 2.45rem; min-height: 2.3rem; padding: .5rem .6rem; place-content: center; }
#session .menu-toggle span { display: block; width: 1.05rem; height: 2px; border-radius: 2px; background: currentColor; }
#session .site-menu-links { position: absolute; z-index: 20; top: calc(100% + .45rem); right: 0; display: grid; min-width: 12.5rem; padding: .45rem; border: 1px solid var(--border); border-radius: .65rem; background: var(--panel); box-shadow: 0 .7rem 1.5rem rgba(0,0,0,.4); }
#session .site-menu-links[hidden] { display: none; }
/* ticket-0073 (2026-10-05): while the ☰ menu is open the top bar rises above the frozen game
   header (Legacy .legacy-head, z 2600), which hid the first menu items; it stays under the
   drawers and dialogs (2800+). Only while open, so the toast at the top is never covered. */
#topbar:has(.site-menu-links:not([hidden])) { position: relative; z-index: 2700; }
#session .site-menu-links button, #session .site-menu-links a.btnlink { width: 100%; padding: .55rem .7rem; text-align: left; }
#session .account-identity { display: inline-flex; align-items: center; gap: .45rem; min-width: 0; min-height: 2.3rem; padding-inline: .7rem .55rem; }
#session .account-name { overflow: hidden; max-width: 11rem; text-overflow: ellipsis; white-space: nowrap; }
#session .account-icon { position: relative; width: 1rem; height: 1rem; flex: 0 0 1rem; border: 1px solid currentColor; border-radius: 50%; }
#session .account-icon::before { content: ""; position: absolute; top: .16rem; left: .28rem; width: .3rem; height: .3rem; border-radius: 50%; background: currentColor; }
#session .account-icon::after { content: ""; position: absolute; bottom: .12rem; left: .16rem; width: .56rem; height: .28rem; border-radius: .4rem .4rem .15rem .15rem; background: currentColor; }
@media (max-width: 760px) { #topbar { align-items: flex-start; gap: .8rem; padding: .7rem .8rem; } #session { justify-content: flex-end; } #session button { min-height: 2.5rem; } }
@media (max-width: 420px) { #topbar { display: grid; grid-template-columns: 1fr; } #session { justify-self: end; } #session .account-name { max-width: 8.5rem; } #session #btn-logout { padding-inline: .65rem; } }

main {
  max-width: 1080px;
  margin: 1rem auto;
  padding: 0 1rem 3rem;
}

/* The lobby is a single-column stack (The Age, server chooser, calendar,
   invitations) — scope it well in from the full 1080px so it reads as a
   centred card column instead of stretching the panels edge to edge. */
body.view-lobby main { max-width: 640px; }

/* Codes & Guidelines (Pass 93.x): the reference renders as codex.html embedded in the
   site frame. The page becomes a flex column so the age bar / Lobby nav / admin strip
   keep their natural height on top and the frame fills the rest, scrolling inside itself
   (its own sticky ToC + search stay pinned) rather than scrolling the whole page. */
body.view-codex { display: flex; flex-direction: column; min-height: 100vh; }
body.view-codex > #topbar,
body.view-codex > #adminnav,
body.view-codex > footer { flex: 0 0 auto; }
body.view-codex > main { flex: 1 1 auto; min-height: 0;
  max-width: none; margin: 0; padding: 0; display: flex; }
#codexframe { flex: 1 1 auto; width: 100%; min-height: 0; border: 0; display: block; }
/* ticket-0099 (2026-10-12): iPad Safari grows the embedded guide to its full height, so the
   whole page scrolls and the top bar (Lobby, menu, account) went off the top with no way
   back. Pin it while a guide or rules page is open. */
body.view-codex > #topbar { position: sticky; top: 0; z-index: 40; }

/* Page-flip smoothness (Alpha-Ticket-0012): flipping between in-game pages refetches
   and re-renders, and an async page briefly shows a short "loading" body — which let
   the site footer's "ReGenesis — a browser strategy game…" tagline flash up into view
   before the content filled in. Make the in-game frame a full-height flex column (same
   sticky-footer shape as view-codex) so #app always fills the viewport and the footer
   stays pinned at the bottom; a min-height on the view reserves the content area so the
   in-frame © line doesn't jump either. */
body.game { display: flex; flex-direction: column; min-height: 100vh; }
body.game > #topbar, body.game > #adminnav, body.game > footer { flex: 0 0 auto; }
body.game > main#app { flex: 1 0 auto; }
body.game #view { min-height: 60vh; }

footer {
  padding: 1rem 1.2rem 2rem;
  text-align: center;
}

.muted { color: var(--muted); }
.good { color: var(--accent-2); }
.bad { color: var(--danger); }
.advice { color: var(--advice); }
.pa { color: var(--pa); font-size: 0.82em; }
.pa.subdued { color: var(--warn-subdued); }
.fx-good { color: var(--good); }
.fx-bad { color: var(--bad); }
.fx-op { color: var(--fx-op); }
.fx-atk { color: var(--fx-atk); }

nav.tabs {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
nav.tabs button {
  background: none;
  border: 1px solid transparent;
  border-bottom: none;
  color: var(--muted);
  font: inherit;
  padding: 0.45rem 1rem;
  min-height: 2.75rem;     /* phone tap target (small-phone pass, 2026-09-28) */
  cursor: pointer;
}
/* Sub-page pills (Rankings / Archive / Directory, Vote / War / NAP …) are links styled as
   chips; on a phone they need the same 2.75rem tap height as every other control. */
nav.tabs .chip { display: inline-flex; align-items: center; min-height: 2.75rem; }
nav.tabs button.active {
  background: var(--panel);
  border-color: var(--border);
  color: var(--accent);
  border-radius: 4px 4px 0 0;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1rem 1.2rem;
  margin-bottom: 1rem;
}
.panel h2 {
  margin: 0 0 0.7rem;
  font-size: 1.1rem;
  color: var(--accent);
  letter-spacing: 0.04em;
}
.panel h3 { margin: 1rem 0 0.4rem; font-size: 1rem; color: var(--text); }

/* Honor & Nobility box (State page) — the province's title + next-rank progress bar. */
.honor-title { font-size: 1.3rem; font-weight: bold; color: var(--accent); margin: 0.2rem 0 0.5rem; }
.honor-bar { height: 0.55rem; border-radius: 0.3rem; background: var(--border);
  overflow: hidden; margin: 0.2rem 0 0.5rem; }
.honor-bar-fill { height: 100%; background: var(--accent); border-radius: 0.3rem;
  transition: width 0.4s ease; }
.honor-progress { border-top: 1px solid var(--border); padding-top: 0.5rem; line-height: 1.5; }
/* ticket-0083: the monarch's rank beside the crown title, the rank's bonus line, the Codex link
   (a full-width thumb target on a phone) and the Throne's rank tap-through. */
.honor-rank-sub { font-size: 0.72em; font-weight: normal; color: var(--muted); }
.honor-effects { font-size: 0.9em; line-height: 1.4; margin: -0.2rem 0 0.6rem; }
.honor-link a { display: block; min-height: 2.75rem; line-height: 2.75rem; margin-top: 0.3rem;
  color: var(--link); text-decoration: none; }
a.honor-rank { color: inherit; text-decoration: underline dotted; text-underline-offset: 0.15em; }

/* State page: a strict two-column grid (Population | Economy / Highlights | Honor). */
.state-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.state-grid > .panel { margin-bottom: 0; }
@media (max-width: 640px) { .state-grid { grid-template-columns: 1fr; } }

.cols { display: flex; gap: 1rem; flex-wrap: wrap; }
.cols > .panel { flex: 1 1 280px; margin-bottom: 0; }
.cols { margin-bottom: 1rem; }

table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 0.25rem 0.7rem 0.25rem 0; }
th { color: var(--muted); font-weight: normal; border-bottom: 1px solid var(--border); }
td.num, th.num { text-align: right; }
tr.me td { color: var(--accent); }

/* .fields = the same field stack inside a box of a multi-panel form (Pass 81: the Found
   page's one form spans three panels, so the form itself can't be the stack). */
form.stack, .fields { display: flex; flex-direction: column; gap: 0.55rem; }
form.stack { max-width: 26rem; }
form.stack label, .fields label { display: flex; flex-direction: column; gap: 0.15rem; color: var(--muted); }
form.stack .row, .fields .row { display: flex; gap: 0.6rem; align-items: center; }
form.stack .gender-row, .fields .gender-row { color: var(--muted); }
form.stack label.inline, .fields label.inline { flex-direction: row; align-items: center; gap: 0.3rem; }
.fields div.stack { display: flex; flex-direction: column; gap: 0.55rem; }

/* The creator's bonus window (Pass 56) — re-renders as the race/personality picks change. */
.bonus-panel {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.5rem 0.8rem;
  /* Pass 81: no height cap — the pairs own a full-width box now, and the merged
     list + unique cards must read whole (the 16rem scroll cut hid the uniques). */
}
.bonus-panel h4 { margin: 0.4rem 0 0.15rem; color: var(--accent); font-weight: normal; }
.bonus-panel h5.bonus-group { margin: 0.45rem 0 0.1rem; color: var(--muted);
  font-weight: normal; font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.08em; }
.bonus-panel ul.bonuses { margin: 0 0 0.3rem; padding-left: 1.2rem; }
.bonus-panel li { list-style: "\2726  "; }

input, select, textarea {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  font: inherit;           /* 16px on phones — a 13px browser-default textarea makes iOS zoom the page */
  padding: 0.35rem 0.5rem;
  border-radius: 3px;
}
input:focus, select:focus, textarea:focus { outline: 1px solid var(--accent); }
/* A select never sets its box's width (ticket-0045, 2026-10-03): its widest option ("Claim an
   abandoned province (invitation code)", a long kingdom name) used to become the panel's
   minimum width, pushing the Found Province kingdom box — and on Firefox for Android the
   whole page — past the phone's edge. The panels in a .cols row may shrink to the screen. */
select { max-width: 100%; }
#f-found .cols > .panel { min-width: 0; }
/* Every text field at least 16px (phone-first base rule, 2026-09-28): below that iOS zooms
   the whole page on focus, and the realm's 15px body font would otherwise carry into number
   fields and textareas. Checkboxes and radios are untouched. */
input:not([type="checkbox"]):not([type="radio"]), select, textarea { font-size: max(1em, 16px); }

button, .btn {
  background: var(--panel-2);
  border: 1px solid var(--accent);
  color: var(--accent);
  font: inherit;
  padding: 0.35rem 1rem;
  border-radius: 3px;
  cursor: pointer;
}
button:hover { background: var(--accent); color: var(--bg); }
button.quiet { border-color: var(--border); color: var(--muted); }
button.quiet:hover { background: var(--panel-2); color: var(--text); }
/* the top bar's link-buttons (Rules, Rankings) dress EXACTLY like the quiet
   buttons beside them — same padding/radius/font (owner 2026-07-21) */
a.btnlink { display: inline-block; padding: 0.35rem 1rem; border: 1px solid var(--border);
  border-radius: 3px; color: var(--muted); text-decoration: none; font: inherit;
  background: var(--panel-2); }
a.btnlink:hover { background: var(--panel-2); color: var(--text); }
button:disabled { opacity: 0.45; cursor: default; }

/* News/log feed lists (was #chronicle until Pass 67.h.3 removed the Chronicle box).
   Pass 67.h.5 dropped the inner scroll box — the month's entries run to the bottom
   of the page. */
.feedlog {
  font-size: 0.9rem;
}
/* Locked two-column rows: a fixed date gutter and a text column that wraps within
   itself — a long entry's wrapped lines stay under the entry, never running back
   under the Date. align-items:start keeps the date on the first line; the date
   column is wide enough for the longest "24th of Blossomtide" and wraps within
   its own gutter (never into the message) on very wide themes. */
.feedlog .entry {
  display: grid;
  grid-template-columns: 11em 1fr;
  column-gap: 0.6rem;
  align-items: start;
  padding: 0.2rem 0;
  border-bottom: 1px dotted var(--border);
}
.feedlog .entry .t { color: var(--muted); text-align: right; }
.feedlog .entry .msg { min-width: 0; }  /* let the text column shrink so it wraps */

/* Pass 67.h.10: the State advisor's Trends math table — each resource group closes
   with a ruled, bold Net Change sub-total, legacy style. */
.trends th { text-align: left; font-weight: normal; }
.trends tr:first-child th { font-weight: bold; }
.trends tr.subtotal th, .trends tr.subtotal td {
  border-top: 1px solid var(--border);
  font-weight: bold;
}

/* Pass 67.h.9: the throne's Recent News — each report is a two-row block, its game
   date on the line above and the report beneath it. */
#throne-news .entry { padding: 0.35rem 0; border-bottom: 1px dotted var(--border); }
#throne-news .entry:last-child { border-bottom: 0; }
#throne-news .entry .t { display: block; font-size: 0.85rem; }
#throne-news .entry .report { margin-top: 0.1rem; }

/* Pass 67.h.5: the feeds' month pager — ◀ earlier | month name | later ▶. */
.feedpager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.25rem 0 0.5rem;
}
.feedpager h3 { margin: 0; }

/* Pass 67.h.3: the one-line action note that replaced the Chronicle box — the latest
   result or error, above the view; empty (and hidden) until something happens. */
#actionnote {
  margin: 0 0 0.6rem;
  padding: 0.3rem 0.7rem;
  font-size: 0.9rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
}
#actionnote:empty { display: none; }

.statgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.4rem 1.2rem;
}
.statgrid div b { display: block; color: var(--muted); font-weight: normal; font-size: 0.85rem; }
/* Aid page "Kingdom resources available": big totals need air — two columns on a phone,
   all five across once there is room (owner 2026-09-30). */
.statgrid.aid-totals { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem 1.5rem; }
.statgrid.aid-totals div { overflow-wrap: anywhere; }
@media (min-width: 600px) {
  .statgrid.aid-totals { grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); }
}

.notice { color: var(--accent-2); }
.error { color: var(--danger); }

.bar { height: 10px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 5px; overflow: hidden; }
.bar div { height: 100%; background: var(--accent); }
.bar.full div { background: var(--accent-2); }

/* Pass 61: the main navigation bar */
#mainnav {
  display: flex; flex-wrap: wrap; gap: 0.2rem 1.1rem; align-items: baseline;
  padding: 0.35rem 1.2rem; background: var(--panel-2);
  border-bottom: 1px solid var(--border); font-size: 0.92rem;
}
#mainnav a { color: var(--link); text-decoration: none; }
#mainnav a:hover { color: var(--accent); }
#mainnav a.active { color: var(--accent); border-bottom: 1px solid var(--accent); }
.admin-table td, .admin-table th { padding: 0.25rem 0.55rem; border: 1px solid var(--border);
  text-align: left; vertical-align: top; }
.admin-table th { color: var(--muted); }

/* Admin → Users: a card per matched account — readable identity, a labelled field grid,
   and grouped controls, in place of the wide overflow table (kept for the bulk anti-cheat
   lists). Themed entirely through the shared tokens so every skin inherits it. */
.user-cards { display: grid; gap: 0.9rem; }
.result-count { margin: 0 0 0.6rem; }
.user-card { border: 1px solid var(--border); border-radius: 6px; background: var(--panel-2);
  padding: 0.75rem 1rem 0.85rem; }
.user-card-head { display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 0.4rem 0.75rem;
  border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; margin-bottom: 0.65rem; }
.user-card .user-name { font-size: 1.15rem; font-weight: bold; color: var(--accent); }
.user-card .user-sub { margin-left: 0.5rem; font-size: 0.82rem; color: var(--muted); }
.user-flags { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.flag-chip { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;
  padding: 0.1rem 0.5rem; border-radius: 999px; border: 1px solid var(--border);
  color: var(--muted); white-space: nowrap; }
.flag-chip.is-admin { border-color: var(--accent); color: var(--accent); }
.flag-chip.is-ok { border-color: var(--good); color: var(--good); }
.flag-chip.is-warn { border-color: var(--warn-subdued); color: var(--warn-subdued); }
.flag-chip.is-danger { border-color: var(--danger); color: var(--danger); }
.user-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.55rem 1.3rem; margin: 0; }
.user-fields dt { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); margin-bottom: 0.1rem; }
.user-fields dd { margin: 0; word-break: break-word; }
.user-fields .ok-tick { color: var(--good); }

/* The card body split into columns: Account | Provinces | Recent sign-ins. Reflows to
   two then one column as the frame narrows; a rule between columns keeps them distinct. */
.user-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0.4rem 1.4rem; }
.user-col { min-width: 0; }
.user-col + .user-col { padding-left: 1.4rem; border-left: 1px solid var(--border); }
.user-col h4 { margin: 0 0 0.5rem; font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted); font-weight: bold;
  border-bottom: 1px solid var(--border); padding-bottom: 0.25rem; }
@media (max-width: 700px) {
  .user-col + .user-col { padding-left: 0; border-left: 0; padding-top: 0.4rem; }
}
.user-fields-stacked { grid-template-columns: 1fr; gap: 0.45rem; }

.prov-row { margin-bottom: 0.5rem; }
.prov-row:last-child { margin-bottom: 0; }
.prov-name { display: block; }
.prov-meta { display: block; font-size: 0.8rem; color: var(--muted); }
/* one block per server on the admin user card (ticket-0058) */
.prov-server + .prov-server { margin-top: 0.6rem; padding-top: 0.5rem; border-top: 1px solid var(--border); }
.prov-server > b { display: block; margin-bottom: 0.25rem; font-size: 0.85rem; color: var(--accent); }

.signin-list { list-style: none; margin: 0; padding: 0; }
.signin-list li { padding: 0.3rem 0; border-bottom: 1px dotted var(--border); }
.signin-list li:last-child { border-bottom: 0; }
.si-time { display: block; font-size: 0.82rem; }
.si-ip { font-variant-numeric: tabular-nums; }
.si-ip.ip-shared { color: #e08a3c; font-weight: 600; cursor: help; }

/* Shared-browser (ID cookie) warning banner atop the Users results. */
.cookie-alert { border: 1px solid #e08a3c; border-left-width: 4px; border-radius: 4px;
  background: rgba(224, 138, 60, 0.1); padding: 0.6rem 0.9rem; margin: 0 0 1rem;
  color: var(--text); }
.cookie-alert ul { margin: 0.4rem 0 0; padding-left: 1.2rem; }
.cookie-alert li { margin: 0.15rem 0; }

.user-suspensions { margin: 0.6rem 0 0; font-size: 0.9rem; }
.user-suspensions summary { cursor: pointer; color: var(--danger); }
.user-suspensions ul { margin: 0.4rem 0 0; padding-left: 1.2rem; }
.user-suspensions li { margin: 0.15rem 0; }

.user-locations { margin: 0.6rem 0 0; font-size: 0.9rem; }
.user-locations summary { cursor: pointer; color: var(--link); }
.loc-list { list-style: none; margin: 0.4rem 0 0; padding: 0; columns: 2; }
.loc-list li { margin: 0.15rem 0; break-inside: avoid; }
@media (max-width: 560px) { .loc-list { columns: 1; } }

details.pe-recent > summary { cursor: pointer; font-size: 1rem; font-weight: 600;
  color: var(--text); }
details.pe-recent[open] > summary { margin-bottom: 0.6rem; }
/* Province editor Change column: a thumb-sized +/− switch beside each box (phone number
   pads have no minus key), red on a subtract row, with the "→ new amount" line beneath.
   The long hover selectors outrank the themes' button:hover fill, which sticks after a tap. */
.pe-change-row { display: flex; align-items: center; gap: 0.25rem; }
.pe-sign { flex: 0 0 auto; min-width: 2.75rem; min-height: 2.75rem; padding: 0;
  font-size: 1.3rem; font-weight: 700; line-height: 1; color: var(--good);
  border-color: var(--good); background: transparent; }
.pe-change .pe-delta { flex: 1 1 auto; width: 4.75em; min-width: 0; max-width: 11em;
  min-height: 2.75rem; }
@media (min-width: 760px) { .pe-change .pe-delta { width: 9em; } }
.pe-minus .pe-sign { color: #fff; background: var(--danger); border-color: var(--danger); }
:root .pe-change .pe-change-row button.pe-sign:hover { color: var(--good);
  background: transparent; }
:root .pe-minus .pe-change-row button.pe-sign:hover { color: #fff;
  background: var(--danger); }
.pe-minus .pe-delta, .pe-minus .pe-delta:focus { outline: 2px solid var(--danger); }
.pe-preview { display: block; margin-top: 0.2rem; font-size: 0.85rem; color: var(--muted);
  overflow-wrap: anywhere; }
.pe-preview:empty { display: none; }
.pe-minus .pe-preview, .pe-preview.pe-bad { color: var(--danger); }
.pe-preview.pe-bad { font-weight: 700; }
/* Province editor picker: a short kingdom:island box and the read-only kingdom name
   share a phone line, the province dropdown takes the next; one line from tablet up. */
.pe-picker { display: flex; flex-wrap: wrap; align-items: stretch; gap: 0.5rem; }
.pe-picker > * { min-height: 2.75rem; }
.pe-coord { flex: 0 0 6em; width: 6em; min-width: 0; }
.pe-kdname { flex: 1 1 8em; min-width: 0; display: block; padding: 0 0.5rem;
  line-height: calc(2.75rem - 2px);
  border: 1px dashed var(--border); border-radius: 3px; font-size: max(1em, 16px);
  cursor: default; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.pe-kdname:empty::before { content: "kingdom name"; color: var(--muted); font-style: italic; }
.pe-pick-province { flex: 1 1 100%; }
@media (min-width: 760px) { .pe-kdname { flex: 0 1 18em; } .pe-pick-province { flex: 0 1 auto; } }

/* Users page: pinned Suspects + Favorites lists. */
.user-marks { display: flex; flex-direction: column; gap: 0.4rem; margin: 0 0 0.9rem;
  padding: 0.6rem 0.8rem; border: 1px solid var(--border); border-radius: 4px;
  background: var(--panel-2); }
.user-marks .mark-suspect { color: var(--danger); margin-right: 0.4rem; }
.user-marks .mark-fav { color: var(--accent); margin-right: 0.4rem; }
.mark-chip { display: inline-block; padding: 0 0.45rem; margin: 0.1rem 0.15rem;
  border: 1px solid var(--border); border-radius: 999px; text-decoration: none;
  color: var(--link); }
.mark-chip:hover { border-color: var(--accent); }

/* Admin announcements: older ones tuck under a collapsed disclosure. */
details.older-ann { margin-top: 0.8rem; border-top: 1px solid var(--border); padding-top: 0.6rem; }
details.older-ann > summary { cursor: pointer; color: var(--muted); font-weight: 600; }
details.older-ann[open] > summary { margin-bottom: 0.6rem; }

/* Announcement editor: format toolbar + live preview. */
.ann-toolbar { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.ann-toolbar button { min-width: 2.2em; padding: 0.15rem 0.5rem; font-size: 0.95rem; }
.ann-hint { margin: 0.2rem 0 0.2rem; font-size: 0.85rem; }
.ann-preview { min-height: 2.5rem; }
.announcement a { color: var(--link); }
.admin-table a.ac-user { color: var(--link); }
.ac-desc { display: block; font-size: 0.82rem; color: var(--muted); margin-top: 0.15rem;
  max-width: 46ch; }

/* Age editor: the creation roster on the Edit races / Edit personalities pages sits
   above the per-tag tables, set off with a little breathing room. */
.edroster { margin: 0.2rem 0 1.1rem; }

/* Anti-cheat tab bar: labelled segments (Overview / Signals / Behavior / Casework /
   Config) in one row, separated by thin dividers. Each group is a column: a small muted
   label over its buttons. Wraps gracefully on narrow widths. */
.ac-tabbar { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.4rem 0.55rem;
  margin-bottom: 1rem; }
.ac-tabgroup { display: flex; flex-direction: column; gap: 0.3rem; }
.ac-tabgroup-label { font-size: 0.66rem; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); padding-left: 0.2rem; }
.ac-tabgroup-tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.ac-tabdiv { align-self: stretch; width: 1px; background: var(--border); margin: 0 0.15rem; }
/* The Users cross-link reads as a jump out of anti-cheat, not an in-page tab. */
.ac-xlink { font-style: italic; }

/* Anti-cheat network map: one expandable block per /24. */
.ac-net { border: 1px solid var(--border); border-radius: 4px; margin-bottom: 0.5rem;
  padding: 0.5rem 0.75rem; }
.ac-net > summary { cursor: pointer; }
.ac-net-multi { border-color: var(--danger); background: rgba(192, 91, 77, 0.06); }
.ac-net-body { margin-top: 0.6rem; }
.ac-reason { font-size: 0.88rem; }

/* Anti-cheat world map (choropleth) + country table. */
.worldmap-wrap { width: 100%; overflow: hidden; margin: 0 0 0.8rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: 4px; }
.worldmap { display: block; width: 100%; height: auto; }
.worldmap path { stroke: var(--bg); stroke-width: 0.4; transition: fill 0.3s ease; }
.worldmap path[data-cc]:hover { stroke: var(--accent); stroke-width: 0.8; cursor: help; }
.geo-table { max-width: 30rem; }
.si-dev { display: block; font-size: 0.8rem; color: var(--muted); cursor: help; }

.user-nick { color: var(--text); font-style: italic; margin-left: 0.35rem; }

/* Admin kingdom page: the summary stat strip above the province roster. */
.kd-stat-row { display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; align-items: center;
  margin: 0.2rem 0 1rem; }
.kd-stat-row > span { white-space: nowrap; }
.admin-table td.ipcell { font-variant-numeric: tabular-nums; font-size: 0.85em; }

/* Server page host-metric bars. */
.meter { margin: 0 0 0.8rem; }
.meter-head { display: flex; justify-content: space-between; gap: 1rem; margin-bottom: 0.2rem; }
.meter-track { height: 0.6rem; background: var(--border); border-radius: 0.3rem; overflow: hidden; }
.meter-fill { height: 100%; border-radius: 0.3rem; transition: width 0.4s ease; }
.meter-fill.meter-ok { background: var(--good); }
.meter-fill.meter-warn { background: var(--accent); }
.meter-fill.meter-bad { background: var(--danger); }

.admin-table tr.row-unread td { background: rgba(192, 91, 77, 0.12);
  background: color-mix(in srgb, var(--danger) 12%, transparent); }

/* Staff-editable contact fields (nickname, Discord ID) — an inline row under the columns. */
.user-edit { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem 0.9rem;
  margin-top: 0.8rem; padding-top: 0.7rem; border-top: 1px solid var(--border); }
.ue-field { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.ue-field input { min-width: 12rem; text-transform: none; letter-spacing: normal;
  font-size: 0.9rem; color: var(--text); }
.user-edit button { align-self: flex-end; }
.ue-flash { font-size: 0.82rem; color: var(--muted); align-self: center; }
.user-note { margin: 0.65rem 0 0; padding: 0.4rem 0.65rem; border-left: 2px solid var(--accent);
  background: var(--bg); color: var(--muted); font-size: 0.9rem; }
.user-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.75rem;
  padding-top: 0.6rem; border-top: 1px solid var(--border); }
.user-actions button { font-size: 0.82rem; }
/* Admin → Live Health (2026-09-25). Phone first (owner rule 2026-09-25: most players are on
   phones): the base rules are the phone layout — one card at a time behind the server tabs,
   a stacked checks list, wrapped tracebacks, full-width form controls, thumb-sized buttons —
   and the min-width queries below widen it to two cards (tablet) and three (desktop). */
.health-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.8rem; }
.health-head h2 { flex: 1 1 auto; margin: 0; }
.health-head p { flex-basis: 100%; margin: 0.4rem 0 0; }
.health-checked { flex-basis: 100%; font-size: 0.82rem; }
.health-tabs { flex-basis: 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.4rem; margin-top: 0.3rem; }
.health-tabs button { min-height: 2.75rem; padding: 0.4rem 0.3rem; border-radius: 999px; font-size: 0.92rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.health-tabs button[aria-selected="true"] { border-color: var(--accent); color: var(--text); background: var(--panel-2); }
.health-grid { display: grid; grid-template-columns: 1fr; gap: 0.8rem; }
.health-card { min-width: 0; }
.health-card-off { display: none; }
.health-card h2 .muted { display: block; font-size: 0.8rem; font-weight: normal; }
.health-card h3 { margin: 1rem 0 0.4rem; font-size: 0.95rem; }
.health-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.45rem 0.8rem; }
.health-facts div { min-width: 0; overflow-wrap: anywhere; }
.health-facts div span { display: block; color: var(--muted); font-size: 0.8rem; }
.health-checks { list-style: none; margin: 0; padding: 0; }
.health-checks li { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.45rem 0.6rem;
  border: 1px solid var(--border); border-top: 0; }
.health-checks li:first-child { border-top: 1px solid var(--border); border-radius: 3px 3px 0 0; }
.health-checks li:last-child { border-radius: 0 0 3px 3px; }
.health-checks .hc-name { font-weight: bold; }
.health-checks .hc-detail { color: var(--muted); font-size: 0.9rem; overflow-wrap: anywhere; }
.health-error { padding: 0.6rem 0.8rem; margin: 0.5rem 0; overflow-wrap: anywhere; }
.health-error-meta { display: flex; flex-wrap: wrap; gap: 0.15rem 0.9rem; font-size: 0.88rem; }
.health-error-actions { margin: 0.5rem 0 0; }
.health-card button, .health-head button { min-height: 2.75rem; }
.health-card details.trace summary { min-height: 2.4rem; display: flex; align-items: center; }
.health-card details.trace pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 45vh; margin: 0.4rem 0 0; }
.journal-entry { border-left: 3px solid var(--border); padding: 0.2rem 0.6rem; margin: 0.4rem 0; overflow-wrap: anywhere; }
.journal-entry p { margin: 0.2rem 0; }
.journal-entry [data-hj-del] { float: right; min-width: 2.5rem; padding: 0 0.45rem; margin-left: 0.4rem; }
.journal-entry.pill-open { border-left-color: var(--danger); }
.journal-entry.pill-watching { border-left-color: var(--warn-subdued, var(--accent)); }
.journal-entry.pill-fixed { border-left-color: var(--good); }
.journal-form summary { cursor: pointer; color: var(--link); min-height: 2.4rem; display: flex; align-items: center; }
.journal-form label { display: block; margin: 0.5rem 0 0; color: var(--muted); font-size: 0.85rem; }
.journal-form textarea, .journal-form select { display: block; width: 100%; box-sizing: border-box;
  font-size: max(1rem, 16px); }   /* 16px+ keeps phones from zooming into the field */
.journal-form textarea { min-height: 4.4rem; margin-top: 0.15rem; padding: 0.45rem 0.55rem; resize: vertical;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 3px; color: var(--text); font-family: inherit; }
.journal-form textarea:focus { outline: 1px solid var(--accent); }
.journal-status { margin: 0.4rem 0 0; }
.journal-save { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0.6rem 0 0; }
.journal-save button { flex: 1 1 100%; }
/* Tablet: two cards side by side, every card visible, the tabs scroll to a card. */
@media (min-width: 760px) {
  .health-checked { flex-basis: auto; }
  .health-tabs { flex-basis: auto; display: flex; margin-top: 0; }
  .health-tabs button { min-height: 2.4rem; padding-inline: 0.8rem; }
  .health-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .health-card-off { display: block; }
  .health-card h2 .muted { display: inline; margin-left: 0.4rem; }
  .health-checks li { flex-direction: row; flex-wrap: wrap; gap: 0.2rem 0.8rem; }
  .health-checks .hc-name { flex: 1 0 8rem; }
  .health-checks .hc-detail { flex: 3 1 11rem; }
  .health-card button, .health-head button { min-height: 2.4rem; }
  .journal-save button { flex: 0 0 auto; }
  .journal-form select { display: inline-block; width: auto; }
}
/* Desktop: all three servers side by side. */
@media (min-width: 1100px) {
  .health-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Admin → Backups (2026-09-26), phone first like Live Health: the summary is a stacked list
   of server rows (name on top, facts beneath) that becomes a seven-column table from tablet
   width; the cards reuse the health-card rules. Receipts are a two-line list on a phone. */
.bk-summary { list-style: none; margin: 0 0 0.8rem; padding: 0; }
.bk-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.25rem 0.8rem;
  padding: 0.55rem 0.7rem; border: 1px solid var(--border); border-top: 0; background: var(--panel); }
.bk-row:first-child { border-top: 1px solid var(--border); border-radius: 3px 3px 0 0; }
.bk-row:last-child { border-radius: 0 0 3px 3px; }
.bk-row .bk-name { grid-column: 1 / -1; font-weight: bold; }
.bk-row span i { display: block; font-style: normal; color: var(--muted); font-size: 0.78rem; }
.bk-row.bk-down { border-left: 3px solid var(--danger); }
.bk-row.bk-warn { border-left: 3px solid var(--warn-subdued, var(--accent)); }
.bk-row.bk-ok { border-left: 3px solid var(--good); }
.bk-receipts { list-style: none; margin: 0; padding: 0; }
.bk-receipt { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.4rem 0.6rem;
  border-left: 3px solid var(--border); margin: 0.3rem 0; overflow-wrap: anywhere; }
.bk-receipt.bk-ok { border-left-color: var(--good); }
.bk-receipt.bk-down { border-left-color: var(--danger); }
.bk-receipt > span:last-child { color: var(--muted); font-size: 0.9rem; }
@media (min-width: 760px) {
  .bk-summary { display: table; width: 100%; border-collapse: collapse; }
  .bk-row { display: table-row; border: 0; }
  .bk-row:first-child, .bk-row:last-child { border-radius: 0; }
  .bk-row > span { display: table-cell; padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--border); vertical-align: top; }
  .bk-row .bk-name { white-space: nowrap; }
  .bk-receipt { flex-direction: row; gap: 0.8rem; }
  .bk-receipt > span:first-child { flex: 0 0 11rem; }
}
/* end Admin → Backups */
/* Age Manager → Province Setup (2026-09-26), phone first: one card per founding knob with
   the name on top and the Starting / Default columns beneath; from tablet width the cards
   become rows of a three-column table under a header row. */
.age-knobs { list-style: none; margin: 0.6rem 0 0; padding: 0; display: grid; gap: 0.5rem; }
.age-knob { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.3rem 0.8rem;
  padding: 0.6rem 0.7rem; border: 1px solid var(--border); border-radius: 0.4rem; background: var(--panel-2); }
.age-knob-head { display: none; }
.age-knob-name { grid-column: 1 / -1; font-weight: bold; }
.age-knob label { display: grid; gap: 0.25rem; color: var(--muted); font-size: 0.82rem; }
.age-knob input[type="number"] { width: 100%; box-sizing: border-box; min-height: 2.75rem; font-size: max(1rem, 16px); }
.age-knob input[type="number"]:disabled { opacity: 0.55; }
.age-knob-default b { color: var(--text); font-size: 1.05rem; line-height: 2.75rem; }
.age-knob-use { display: flex; align-items: center; gap: 0.4rem; min-height: 2.4rem; color: var(--text); font-size: 0.9rem; }
.age-knob-use input[type="checkbox"] { width: 1.5rem; height: 1.5rem; margin: 0; }
.age-knob-own { border-color: var(--accent); }
.age-knob-own .age-knob-start > span { color: var(--accent); }
.age-knobs-form .row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-top: 0.8rem; }
.age-province { margin-bottom: 1.4rem; }
/* Age Manager → Ages on deck (2026-09-26), phone first: the template roster is a list of
   cards (identity, three schedule facts, thumb-sized lifecycle buttons that fill two per
   row); from tablet width a card becomes one row: identity | facts | buttons. The new-age
   and re-time forms stack on a phone and sit inline from tablet width. No sideways scroll. */
.age-deck { list-style: none; margin: 0.8rem 0 0; padding: 0; display: grid; gap: 0.6rem; }
.age-deck-card { display: grid; gap: 0.55rem; padding: 0.7rem 0.8rem; border: 1px solid var(--border);
  border-radius: 0.45rem; background: var(--panel-2); min-width: 0; }
.age-deck-card.active { border-color: var(--accent); }
.age-deck-live { border-left: 3px solid var(--good); }
.age-deck-armed { border-left: 3px solid var(--accent); }
.age-deck-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.6rem; min-width: 0; }
.age-deck-id { color: var(--muted); font-size: 0.85rem; }
.age-deck-name { flex: 1 1 auto; font-size: 1.05rem; overflow-wrap: anywhere; }
.age-deck-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.3rem 0.6rem; }
.age-deck-facts span i { display: block; font-style: normal; color: var(--muted); font-size: 0.78rem; }
.age-deck-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.age-deck-actions button { min-height: 2.75rem; flex: 1 1 calc(50% - 0.4rem); }
.age-deck-trash { margin-top: 0.8rem; }
.age-new { display: grid; gap: 0.5rem; margin: 0.6rem 0 0; }
.age-new input { width: 100%; box-sizing: border-box; min-height: 2.75rem; font-size: max(1rem, 16px); }
.age-new button { min-height: 2.75rem; }
/* The live card's folded re-time control (owner, 2026-10-02): one tappable line closed. */
.age-retime-fold { border-top: 1px solid var(--border); padding-top: 0.3rem; }
.age-retime-fold > summary { min-height: 2.75rem; display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem;
  cursor: pointer; color: var(--accent); }
.age-retime-fold > summary::-webkit-details-marker { display: none; }
.age-retime-fold > summary::before { content: "\25B8"; color: var(--muted); }
.age-retime-fold[open] > summary::before { content: "\25BE"; }
.age-retime-fold > p { margin: 0.2rem 0 0.5rem; font-size: 0.9rem; }
.age-retime { display: grid; gap: 0.5rem; }
.age-retime label { display: grid; gap: 0.25rem; color: var(--muted); font-size: 0.85rem; }
.age-retime input { width: 100%; box-sizing: border-box; min-height: 2.75rem; font-size: max(1rem, 16px); }
.age-retime button { min-height: 2.75rem; }
@media (min-width: 760px) {
  .age-deck-card { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; align-items: center; gap: 0.8rem; }
  .age-deck-actions { justify-content: flex-end; }
  .age-deck-actions button { flex: 0 0 auto; min-height: 2.4rem; }
  .age-new { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .age-new input, .age-new button { min-height: 2.4rem; }
  .age-deck-card .age-retime-fold { grid-column: 1 / -1; }
  .age-retime { grid-template-columns: 12rem auto; align-items: end; }
  .age-retime-fold > summary { min-height: 2.4rem; }
  .age-retime input, .age-retime button { min-height: 2.4rem; }
}
/* end Age Manager */
/* Age Manager → Races tab (2026-09-26; the Personalities tab shares it), phone first: the pills are a two-column grid,
   the roster is a card per race, each active race is a folding section, unit stats are
   cards with the three numbers side by side, mods stack name / value / preview, every
   control is thumb-sized and 16px+. From tablet width the pills line up, the roster rows
   and unit cards become table rows, and the mod rows go single-line. */
.ed-subtabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.4rem; margin: 0.2rem 0 0.9rem; }
.ed-subtabs button { min-height: 2.75rem; padding: 0.4rem 0.3rem; font-size: 0.9rem; border-radius: 999px; }
/* The chosen top tab wears a clear yellow outline (owner 2026-09-26: easier to spot on a phone). */
.ed-subtabs button.active, .tm-age-tabs button.active { border: 3px solid #ffe600; box-shadow: 0 0 0 2px rgba(255, 230, 0, 0.45), 0 0 10px rgba(255, 230, 0, 0.5);
  color: #ffe600; background: #2a2410; font-weight: 800; letter-spacing: 0.01em; }
.ed-sub h4 { margin: 0.4rem 0 0.3rem; }
.ed-roster { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.ed-roster-row { display: grid; gap: 0.45rem; padding: 0.6rem 0.7rem; border: 1px solid var(--border);
  border-radius: 0.4rem; background: var(--panel-2); }
.ed-roster-row.on { border-color: var(--good); }
.ed-roster-pick { display: flex; align-items: center; gap: 0.6rem; min-height: 2.4rem; cursor: pointer; }
.ed-roster-pick input { width: 1.5rem; height: 1.5rem; margin: 0; flex: 0 0 auto; }
.ed-roster-name { display: grid; gap: 0.2rem; color: var(--muted); font-size: 0.8rem; }
.ed-roster-name input, .ed-race-body input[type="number"], .ed-race-body input[type="text"],
.ed-race-body input[list], .ed-race-body select { width: 100%; box-sizing: border-box; min-height: 2.75rem;
  font-size: max(1rem, 16px); }
.ed-race { border: 1px solid var(--border); border-radius: 0.45rem; background: var(--panel-2); margin: 0.5rem 0; }
.ed-race > summary { cursor: pointer; padding: 0.7rem 0.8rem; font-weight: bold; color: var(--accent);
  min-height: 2.75rem; box-sizing: border-box; }
.ed-race > summary .muted { font-weight: normal; font-size: 0.85rem; }
.ed-race-body { padding: 0 0.8rem 0.8rem; }
.ed-units { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.ed-unit { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.3rem 0.5rem;
  padding: 0.5rem 0.6rem; border: 1px solid var(--border); border-radius: 0.4rem; }
.ed-unit-name { grid-column: 1 / -1; font-weight: bold; }
.ed-unit-head { display: none; }
.ed-unit label, .ed-field, .ed-slot { display: grid; gap: 0.2rem; color: var(--muted); font-size: 0.8rem; }
.ed-unit-na { min-height: 2.75rem; display: flex; align-items: center; }
.ed-field { margin: 0.7rem 0 0.2rem; }
.ed-field .elitecalc { font-style: italic; margin-left: 0.4rem; }
.ed-slot { margin: 0.5rem 0 0.2rem; }
.ed-mods { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.ed-mod { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.25rem 0.5rem; align-items: center;
  padding: 0.5rem 0.6rem; border: 1px solid var(--border); border-radius: 0.4rem; }
.ed-mod-key { grid-column: 1 / -1; font-weight: bold; overflow-wrap: anywhere; font-size: 0.92rem; }
.ed-mod-key small { font-weight: normal; }
.ed-mod .modshown { grid-column: 1 / -1; order: 3; color: var(--muted); font-style: italic; overflow-wrap: anywhere; }
.ed-mod .dockill { order: 2; }
.ed-mod .dockill, .ed-chip .dockill { min-width: 2.75rem; min-height: 2.75rem; }
.ed-add { display: grid; gap: 0.4rem; margin-top: 0.6rem; }
.ed-add button { min-height: 2.75rem; }
.ed-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.ed-chip { display: inline-flex; align-items: center; gap: 0.3rem; border: 1px solid var(--border);
  border-radius: 999px; padding: 0 0.2rem 0 0.75rem; min-height: 2.4rem; }
.ed-races .edgrid { max-height: none; grid-template-columns: 1fr; gap: 0.2rem; }
.ed-races .edgrid label.inline { min-height: 2.4rem; display: flex; align-items: center; gap: 0.5rem; }
.ed-races .edgrid input[type="checkbox"] { width: 1.4rem; height: 1.4rem; margin: 0; flex: 0 0 auto; }
.ed-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.8rem; align-items: center; }
.ed-actions button { min-height: 2.75rem; flex: 1 1 calc(50% - 0.5rem); }
@media (min-width: 760px) {
  .ed-subtabs { display: flex; flex-wrap: wrap; }
  .ed-subtabs button { min-height: 2.4rem; padding-inline: 0.9rem; }
  .ed-roster-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; }
  .ed-roster-name input, .ed-race-body input[type="number"], .ed-race-body input[type="text"],
  .ed-race-body input[list], .ed-race-body select { min-height: 2.4rem; font-size: 1rem; }
  .ed-unit { grid-template-columns: 10rem repeat(3, minmax(0, 1fr)); align-items: center; }
  .ed-unit-name { grid-column: auto; }
  .ed-unit label > span { display: none; }
  .ed-unit-head { display: grid; color: var(--muted); font-size: 0.8rem; font-weight: bold; border: 0; padding-bottom: 0; }
  .ed-mod .modshown, .ed-mod .dockill { order: 0; }
  .ed-unit-na { min-height: 2.4rem; }
  .ed-mod { grid-template-columns: minmax(0, 1.4fr) 8rem minmax(0, 1fr) auto; }
  .ed-mod-key, .ed-mod .modshown { grid-column: auto; }
  .ed-mod .dockill, .ed-chip .dockill { min-width: 2.4rem; min-height: 2.4rem; }
  .ed-add { grid-template-columns: minmax(0, 1fr) 8rem auto; }
  .ed-add.ed-add-quirk { grid-template-columns: minmax(0, 1fr) auto; }
  .ed-add button { min-height: 2.4rem; }
  .ed-races .edgrid { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
  .ed-actions button { flex: 0 0 auto; min-height: 2.4rem; }
}
/* The Spells tab (2026-09-26) rides the same block: a card per spell, switch rows full width
   on a phone and three-across from tablet width, a full-width search, wrapping filter pills. */
.ed-spells { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.ed-spell { display: grid; gap: 0.35rem; padding: 0.7rem 0.8rem; border: 1px solid var(--border);
  border-radius: 0.45rem; background: var(--panel-2); }
.ed-spell.is-off { opacity: 0.6; }
.ed-spell-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem; }
.ed-spell-head > b { font-size: 1.05rem; color: var(--accent); }
.ed-badges { display: inline-flex; flex-wrap: wrap; gap: 0.3rem; }
.ed-badge { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; border-radius: 999px;
  padding: 0.1rem 0.5rem; border: 1px solid var(--border); color: var(--muted); }
.ed-badge-support { border-color: var(--good); color: var(--good); }
.ed-badge-uni { border-color: var(--accent); color: var(--accent); }
.ed-badge-dis { border-color: var(--bad); color: var(--bad); }
.ed-spell-desc { margin: 0; }
.ed-spell-facts, .ed-spell-chips { margin: 0; font-size: 0.85rem; }
.ed-spell-switches { display: grid; gap: 0.3rem; margin-top: 0.3rem; }
.ed-switch { display: flex; align-items: center; gap: 0.7rem; min-height: 2.75rem; padding: 0 0.5rem;
  border: 1px solid var(--border); border-radius: 0.4rem; cursor: pointer; }
.ed-switch input { width: 1.5rem; height: 1.5rem; margin: 0; flex: 0 0 auto; }
.ed-switch small { display: block; }
.ed-spell-search { width: 100%; box-sizing: border-box; min-height: 2.75rem; font-size: max(1rem, 16px);
  margin-bottom: 0.5rem; position: sticky; top: 0.3rem; z-index: 2; }
.ed-spell-filters { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.7rem; }
.ed-spell-filters button { min-height: 2.4rem; padding-inline: 0.8rem; border-radius: 999px; }
.ed-spell-filters button.active { border: 2px solid var(--accent); color: var(--accent); font-weight: bold; }
/* Who holds a spell (2026-10-02): warning lines, and while Universal is off the race and
   personality chips, thumb-sized and wrapping on a phone. */
.ed-spell-notes { margin: 0; display: grid; gap: 0.25rem; font-size: 0.9rem; }
.ed-spell-notes:empty { display: none; }
.ed-spell-note { border-left: 3px solid var(--accent); padding: 0.2rem 0.5rem; }
.ed-spell-note.bad { border-color: var(--bad); color: var(--bad); }
.ed-holders { margin-top: 0.3rem; padding: 0 0.5rem; border: 1px dashed var(--border);
  border-radius: 0.4rem; }
.ed-holders[hidden] { display: none; }
.ed-holders > p { margin: 0; font-size: 0.85rem; }
.ed-holders > summary { min-height: 2.75rem; display: flex; align-items: center; cursor: pointer; color: var(--accent); }
.ed-holders-group { display: grid; gap: 0.3rem; margin: 0.5rem 0; }
.ed-holders-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.ed-chip { display: inline-flex; align-items: center; gap: 0.45rem; min-height: 2.75rem; padding: 0 0.7rem;
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer; }
.ed-chip input { width: 1.3rem; height: 1.3rem; margin: 0; }
.ed-chip:has(input:checked) { border-color: var(--accent); color: var(--accent); }
@media (min-width: 760px) {
  .ed-chip { min-height: 2.4rem; }
  .ed-spell-switches { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ed-switch { min-height: 2.4rem; }
  .ed-switch small { display: inline; }
  .ed-spell-search { min-height: 2.4rem; font-size: 1rem; }
}
/* Dragons / Rituals tabs (2026-09-26) ride the spell-card shape: a numbers fold per card
   and a knob fold above the list; knob rows one per line on a phone, two across from tablet. */
.ed-numbers { margin: 0.4rem 0 0; }
.ed-numbers > summary { font-size: 0.95rem; }
.ed-numbers h5 { margin: 0.8rem 0 0.3rem; }
.ed-race-body textarea { width: 100%; box-sizing: border-box; font-size: max(1rem, 16px); min-height: 4.5rem; }
.ed-knobfold { margin-bottom: 0.7rem; }
.ed-knobs-grid { display: grid; gap: 0.5rem; }
.ed-knob > span small { display: block; font-size: 0.72rem; }
.ed-mod-key .good { color: var(--good); font-weight: normal; }
@media (min-width: 760px) {
  .ed-knobs-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 1rem; }
  .ed-race-body textarea { font-size: 1rem; }
}
/* end Races tab */
.age-knobs-form .row button { min-height: 2.75rem; flex: 1 1 100%; }
@media (min-width: 760px) {
  .age-knobs { gap: 0; }
  .age-knob { grid-template-columns: 1.3fr 1fr 1.2fr; align-items: center; gap: 0.8rem;
    border-radius: 0; border-top: 0; }
  .age-knob:first-child { border-top: 1px solid var(--border); border-radius: 0.4rem 0.4rem 0 0; }
  .age-knob:last-child { border-radius: 0 0 0.4rem 0.4rem; }
  .age-knob-head { display: grid; color: var(--muted); font-size: 0.82rem; font-weight: bold; background: var(--panel); }
  .age-knob-name { grid-column: auto; }
  .age-knob label > span:first-child { display: none; }
  .age-knob-default { grid-template-columns: auto 1fr; align-items: center; gap: 0.8rem; }
  .age-knob-default b { line-height: 1.4; }
  .age-knobs-form .row button { flex: 0 0 auto; }
}
details.trace summary { cursor: pointer; color: var(--link); }
details.trace pre { white-space: pre; font-size: 0.8rem; color: var(--muted);
  background: var(--bg); padding: 0.5rem; overflow-x: auto; }
.chat { display: flex; flex-direction: column; gap: 0.45rem; }
.chat .msg { max-width: 85%; padding: 0.45rem 0.7rem; border: 1px solid var(--border);
  border-radius: 0.5rem; background: var(--panel-2); white-space: pre-wrap; }
.chat .msg.admin { align-self: flex-start; border-color: var(--accent); }
.chat .msg.player { align-self: flex-end; }
.chat .who { display: block; font-size: 0.78rem; color: var(--muted); }

/* Pass 64: the public landing page — intro/logo on the left, sign-in / sign-up /
   who's-online / announcements stacked on the right. */
.landing { display: grid; grid-template-columns: 3fr 2fr; gap: 1rem; align-items: start; }
@media (max-width: 760px) { .landing { grid-template-columns: 1fr; } }
.landing-intro { margin-bottom: 0; }
.landing-side { display: flex; flex-direction: column; gap: 1rem; }
.landing-side .panel { margin-bottom: 0; }
.landing-logo { text-align: center; padding: 1.2rem 0 0.8rem; }
.landing-logo .crest { width: 72px; height: 72px; color: var(--accent); }
.landing-logo .wordmark { font-size: 2.6rem; letter-spacing: 0.08em; color: var(--muted); }
.landing-logo .wordmark span { color: var(--accent); }
.landing-logo .tagline { margin: 0.1rem 0 0; color: var(--muted); font-style: italic; }
.online-tally { font-size: 1.4rem; color: var(--accent-2); }
.announcement { padding: 0.45rem 0; border-top: 1px dotted var(--border); }
.announcement:first-of-type { border-top: none; }
.announcement p { margin: 0.25rem 0 0; white-space: pre-wrap; }

/* Pass 64: the lobby's server chooser. */
#lobby-servers { display: grid; gap: 0.7rem; }
.server-card {
  display: flex; gap: 1rem; align-items: center; justify-content: space-between;
  flex-wrap: wrap; background: var(--panel-2); border: 1px solid var(--accent);
  border-radius: 4px; padding: 0.7rem 1rem;
}
.server-card .server-name { font-size: 1.15rem; color: var(--accent); }

.server-card-select { width: 100%; text-align: left; cursor: pointer; }
.server-card-link { display: inline-flex; align-items: center; min-height: 2.75rem; margin-top: .15rem; color: var(--accent); text-decoration: underline; font-size: .95rem; }
.server-card-select > span:first-child { display: grid; gap: 0.25rem; }
.server-card-active { border: 4px solid var(--accent); padding: calc(0.7rem - 3px) calc(1rem - 3px);
  box-shadow: 0 0 0 1px var(--accent), 0 0 14px color-mix(in srgb, var(--accent) 45%, transparent); }

/* The lobby's "The Age" summary — a compact label/value table. */
.age-summary { border-collapse: collapse; }
.age-summary th {
  text-align: left; font-weight: normal; color: var(--muted);
  padding: 0.15rem 0.9rem 0.15rem 0; vertical-align: top; white-space: nowrap;
}
.age-summary td { padding: 0.15rem 0; }
.age-summary .age-countdown { font-variant-numeric: tabular-nums; }

/* ==================== Pass 65: the in-game chrome ====================
   Rail + ticker + resource bar + advisor bar. CHROME RULE: these selectors use only the
   --chrome-* variables (plus .good/.bad for the delta row) so every theme leaves the
   bars dark/gold — the legacy behaviour, true by construction. */

/* The game frame is LOCKED, not fluid (owner direction 2026-07-16): a fixed
   centered width so the top bar, the advisor bar and every page column share
   one edge on any monitor. 1020px total = 170px rail + 1rem gap + ~800px game
   column — the middle ground between the old full-stretch resource bar
   (~1090px) and the content-hugging one (~520px). max-width still yields on
   windows narrower than the frame. */
body.game main { width: 1020px; max-width: 100%; }

.realm-gamewrap { display: grid; grid-template-columns: 1fr; gap: 1rem; align-items: start; }
#gamecol { min-width: 0; }

.chip {
  display: block; color: var(--chrome-text); text-decoration: none;
  background: var(--chrome-panel); border: 1px solid var(--chrome-border);
  border-radius: 999px; padding: 0.22rem 0.7rem; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.chip:hover { border-color: var(--chrome-gold-2); color: var(--chrome-gold-1); }
.chip.active {
  background: linear-gradient(var(--chrome-gold-1), var(--chrome-gold-2));
  color: #1a1408; border-color: var(--chrome-gold-2); font-weight: bold;
}
.chip-badge { color: var(--chrome-gold-2); font-size: 0.85em; }
.chip.active .chip-badge { color: #1a1408; }
#ticker b { color: var(--chrome-gold-1); }
#ticker { display: none; }               /* the mobile clone; shown ≤900px */

/* -- the resource bar (7 columns × projected / delta / current) --
   The bar spans the locked game column — the same edge as the advisor bar and
   every page below it (owner direction 2026-07-16: one framed width, a middle
   ground between full-stretch and content-hugging). overflow keeps it
   scrollable when the window is narrower than the numbers. */
#resourcebar {
  background: var(--chrome-bg); border: 1px solid var(--chrome-border); border-radius: 6px;
  padding: 0.3rem 0.6rem; margin-bottom: 0.6rem; overflow-x: auto;
}
#resourcebar table { border-collapse: collapse; width: 100%; min-width: 640px; }
#resourcebar th {
  color: var(--chrome-muted); font-weight: normal; font-size: 0.78rem;
  border-bottom: 1px solid var(--chrome-border); padding: 0.1rem 0.7rem;
}
#resourcebar td { color: var(--chrome-text); padding: 0.06rem 0.7rem; white-space: nowrap; }
#resourcebar .rb-label { color: var(--chrome-muted); font-size: 0.75rem; font-style: italic; }
#resourcebar .rb-proj td { color: var(--chrome-muted); }
#resourcebar .rb-delta td { font-size: 0.8rem; }
/* Pass 67.h.2 addendum: the ± row's colors. The .good/.bad classes were losing the
   specificity fight against `#resourcebar td` above, so the deltas rendered plain —
   these win it. --good/--bad are :root-only (no theme overrides): chrome-invariant. */
#resourcebar td.good { color: var(--good); }
#resourcebar td.bad { color: var(--bad); }
#resourcebar td.muted { color: var(--chrome-muted); }
#resourcebar .rb-cur td { font-weight: bold; }
#resourcebar .rb-cur td.rb-label { font-weight: normal; }

/* -- the staff strip: full browser width under the topbar, on EVERY logged-in
   page (out-of-game since 2026-07-15; in-game too since 2026-07-16 — the old
   in-frame #adminbar stopped fitting the locked 1020px frame and scrolled).
   The pills match the top bar's site-nav pills in size (owner 2026-09-17: the
   old 0.78rem chips were hard to read), so the strip wraps to a second row on
   narrower screens instead of clipping. -- */
#adminnav {
  display: flex; gap: 0.3rem; align-items: center; flex-wrap: wrap;
  background: var(--chrome-bg); border-bottom: 1px solid var(--chrome-gold-2);
  padding: 0.3rem 0.55rem;
}
#adminnav .chip { flex: 0 0 auto; padding: 0.35rem 1rem; font-size: 1rem; }
/* The staff bar over Admin / Council tool pages (2026-09-27), phone first: the tool's name on
   its own line, two thumb-height buttons beneath; one row from tablet width. Sticky so the
   way back is always in reach on a long tool page. */
#staffbar { position: sticky; top: 0; z-index: 60; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.4rem; padding: 0.45rem 0.6rem; background: var(--chrome-bg); border-bottom: 1px solid var(--chrome-gold-2); }
#staffbar[hidden] { display: none; }
#staffbar .staff-title { grid-column: 1 / -1; color: var(--chrome-gold-2); font-size: 0.95rem; overflow-wrap: anywhere; }
#staffbar button { min-height: 2.75rem; font-size: 0.95rem; }
@media (min-width: 760px) {
  #staffbar { grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; }
  #staffbar .staff-title { grid-column: 2; order: 2; text-align: center; }
  #staffbar [data-staff-back] { order: 1; }
  #staffbar [data-staff-game] { order: 3; }
  #staffbar button { min-height: 2.4rem; }
}

/* -- the announcement bar -- */
#announcebar {
  background: var(--chrome-panel); border: 1px solid var(--chrome-gold-2);
  border-radius: 4px; color: var(--chrome-text); padding: 0.35rem 0.8rem;
  margin-bottom: 0.6rem; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#announcebar b { color: var(--chrome-gold-1); }
#announcebar.open { white-space: pre-wrap; }

/* Pass 66: the lobby's call to arms */
button.resume {
  background: linear-gradient(var(--chrome-gold-1), var(--chrome-gold-2));
  color: #1a1408; border-color: var(--chrome-gold-2); font-weight: bold;
  font-size: 1.05rem; padding: 0.45rem 1.2rem;
}
button.resume:hover { background: var(--chrome-gold-1); color: #1a1408; }

/* Pass 66: the A/B creator's pair slots + the age-details reference page */
.pair-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 0.5rem 0; }
@media (max-width: 900px) { .pair-cols { grid-template-columns: 1fr; } }
.pair {
  border: 1px solid var(--border); border-radius: 4px; padding: 0.6rem 0.8rem;
  display: flex; flex-direction: column; gap: 0.5rem; background: var(--panel-2);
}
.pair.chosen { border: 2px solid var(--accent-2); }
.pair-head { color: var(--muted); text-transform: uppercase; font-size: 0.75rem;
  letter-spacing: 0.08em; }
.pair.chosen .pair-head::after { content: " — chosen"; color: var(--accent-2); }
.pair-units table { font-size: 0.85rem; }
/* Owner 2026-09-28: the founding table folds the personality — shifted cells carry the
   signed delta, and the whole-army / warmaster lines sit under the table. */
.pair-units .unit-shift { font-size: 0.8em; white-space: nowrap; }
.pair-units .unit-strength { margin: 0.3rem 0 0; padding-left: 1.1rem; font-size: 0.85rem;
  display: grid; gap: 0.2rem; }
/* Owner 2026-10-02: the founding column follows the age-changes sheet — a Military heading
   over the units table, then the spell and op books as thumb-sized folds. */
.pair-sec { margin: 0.2rem 0 0.3rem; color: var(--accent); font-weight: normal; }
.pair-books { display: grid; gap: 0.4rem; }
.pair-fold { border: 1px solid var(--border); border-radius: 0.4rem; padding: 0 0.6rem; }
.pair-fold > summary { min-height: 2.75rem; display: flex; align-items: center; gap: 0.4rem;
  flex-wrap: wrap; cursor: pointer; color: var(--accent); }
.pair-fold > summary::-webkit-details-marker { display: none; }
.pair-fold > summary::before { content: "\25B8"; color: var(--muted); }
.pair-fold[open] > summary::before { content: "\25BE"; }
.pair-fold h5.bonus-group { margin: 0.45rem 0 0.2rem; color: var(--muted); }
.pair-fold > p { margin: 0.2rem 0 0.5rem; font-size: 0.85rem; }
.pair-book { margin: 0 0 0.5rem; padding-left: 1.1rem; display: grid; gap: 0.3rem; font-size: 0.9rem; }
.pair-book li { overflow-wrap: anywhere; }
.pair-choose { align-self: flex-start; }
.pair.chosen .pair-choose { border-color: var(--accent-2); color: var(--accent-2); }
.agedetails-h { color: var(--accent); font-size: 1.15rem; letter-spacing: 0.04em;
  margin: 1.2rem 0 0.6rem; }
.agedetails-grid > .panel { flex: 1 1 300px; }

/* Pass 67.c: resource pages — the spec's bright-red box-less error, alpha panels */
.blocked { color: #ff5a5a; font-weight: 600; text-align: center; padding: 0.6rem 0; }
details.alpha { border: 1px dashed var(--border); padding: 0.3rem 0.6rem;
  margin: 0.5rem 0; font-size: 0.85rem; }
details.alpha pre { overflow-x: auto; margin: 0.4rem 0 0; }
details.panel-sub summary { cursor: pointer; font-weight: 600; }

/* Pass 67.b: the frame — mobile-only nav links, possession banner, footer, watermark */
.mobile-only { display: none; }
@media (max-width: 900px) { .mobile-only { display: inline-block; } }
#possessionbar { background: #7a1f1f; color: #fff; padding: 0.45rem 1rem;
  font-weight: 600; }
#possessionbar a { color: #ffd7d7; margin-left: 0.6rem; }
#gamefooter { margin: 1rem 0 0.5rem; text-align: center; font-size: 0.85rem;
  color: var(--muted); }
#gamefooter a { color: var(--muted); text-decoration: underline; }
.commstabs { display: flex; gap: 0.4rem; margin-bottom: 0.8rem; }

/* Pass 72: the chart facelift — legacy zebra + header bars, palette per theme.
   Every data table in the game view stripes (legacy stripes everything under
   .game-content); the header bar styles rows made only of <th>. Structural
   detection rides :has() — older browsers simply keep the flat look. The .matrix
   day grids, bordered .admin-table, and the .intel-stats/.throne-stats label/value
   panes are charts of a different shape and opt out. */
#view :where(table:not(.matrix, .admin-table, .intel-stats, .throne-stats, .intel-grid))
  tr:where(:nth-child(odd):has(> td)) { background: var(--row-alt); }
#view :where(table:not(.matrix, .admin-table, .intel-stats, .throne-stats, .intel-grid))
  tr:where(:has(> th):not(:has(> td))) th {
  background: var(--th-bg); color: var(--th-fg); text-shadow: var(--th-shadow);
  border-bottom: 0; padding: 0.3rem 0.7rem 0.3rem 0.3rem;
}
#view tr.subtotal { background: none; }   /* legacy tr.sub-total: ruled, not striped */
#view .msgwin tr { background: none; }    /* result windows keep their flat fills */

/* Pass 67.a: schedule matrices, science group heads (the old table.zebra rule is
   superseded by the global stripe above; the class stays in the markup) */
table.matrix th, table.matrix td { padding: 0.15rem 0.4rem; font-size: 0.85rem;
  border: 1px solid var(--border); text-align: center; }
table.matrix td:first-child, table.matrix th:first-child { text-align: left;
  white-space: nowrap; }
tr.group-head td { padding-top: 0.7rem; border-bottom: 1px solid var(--accent); }
/* Pass 82: the science-field names (Economy / Military / Arcane Arts) read as headlines */
tr.group-head b { color: var(--accent); font-size: 1.1em; letter-spacing: 0.04em; }

/* -- mobile (≤900px) -- */
@media (max-width: 900px) {
  body.game { padding-bottom: calc(var(--navstrip-h) + 8px); }
  /* the staff strip yields too — the fixed #ticker owns the top of the in-game
     mobile screen; staff phones reach the admin pages from the lobby */
  body.game footer, body.game #adminnav { display: none; }

  /* the ticker leaves the rail and pins full-width at the very top */
  #ticker {
    display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap;
    position: fixed; top: 0; left: 0; right: 0; z-index: 2500; height: var(--ticker-h);
    align-items: center; background: var(--chrome-bg);
    border-bottom: 1px solid var(--chrome-border); font-size: 0.82rem;
    color: var(--chrome-text);
  }
  body.game main { margin-top: calc(var(--ticker-h) + 6px); }
}
/* The site bar (logo, menu, account, Logout) yields in-game on phones only: an upright tablet
   (~820px) has room for it, and without it there was no menu or Logout (ticket-0099). */
@media (max-width: 600px) {
  body.game #topbar { display: none; }
}

/* ==================== Pass 65: the Classic theme ====================
   Black body, white text, Trebuchet, teal #103041 accents, silver links, and the
   engraved tan-plate panels. Content only — the chrome vars above stay untouched. */
:root[data-theme="classic"] {
  --bg: #000;
  --panel: #29261c;
  --panel-2: #1c1a12;
  --border: #103041;
  --text: #fffffe;
  --muted: #b5b2a6;
  --accent: #fffffe;
  --accent-2: #9fc06a;
  --danger: #e06a5a;
  --link: #c0c0c0;
  --font: 'Trebuchet MS', Helvetica, sans-serif;
  /* Pass 72: legacy flat-family charts — the EXACT legacy zebra wash and a solid
     header bar (legacy navy #000040, adapted to classic's established teal). */
  --row-alt: rgba(48, 48, 48, 0.6);
  --th-bg: #103041;
  --th-fg: #fffffe;
  --th-shadow: none;
}
/* legacy classic: the row-label cells read silver against the striped rows */
:root[data-theme="classic"] #view table tr:has(> td) th { color: silver; }
:root[data-theme="classic"] .panel,
:root[data-theme="classic"] .bonus-panel,
:root[data-theme="classic"] .server-card {
  border: 2px solid #103041; border-radius: 2px;
  background: radial-gradient(circle at 50% 30%, #7b7354, #29261c 75%);
  box-shadow: inset 1px 1px 0 rgba(255, 251, 241, 0.35),
              inset -2px -2px 4px rgba(124, 74, 20, 0.45), inset 0 0 14px #000;
}
:root[data-theme="classic"] a { color: var(--link); }
:root[data-theme="classic"] a:hover,
:root[data-theme="classic"] #mainnav a:hover { color: #fff; }
:root[data-theme="classic"] button:not(.chip):hover {
  background: #103041; color: #fff; border-color: #103041;
}
:root[data-theme="classic"] input:focus,
:root[data-theme="classic"] select:focus { outline: 1px solid #103041; }
:root[data-theme="classic"] nav.tabs button.active,
:root[data-theme="classic"] .panel h2 { color: #fffffe; }
:root[data-theme="classic"] #mainnav { background: #103041; }
:root[data-theme="classic"] #mainnav a { color: #c0c0c0; }
:root[data-theme="classic"] #mainnav a.active { color: #fff; border-color: #fff; }
/* 67.h.18: Classic flattens the result window (legacy classic_theme/theme.css:407 —
   flat fills, square 1px white border, no shadowing). */
:root[data-theme="classic"] .msgwin {
  border: 1px solid #fff; border-radius: 0; box-shadow: none; text-shadow: none;
}
:root[data-theme="classic"] .msgwin.good { background: green; }
:root[data-theme="classic"] .msgwin.bad { background: #400000; }
:root[data-theme="classic"] .msgwin.unique { background: #512067; }
:root[data-theme="classic"] .msgwin.info { background: #c46500; }

/* ==================== The Willow theme ====================
   The easy-reading skin, cut from Classic's cloth but soft where Classic is stark:
   moss-dark surfaces instead of black, warm parchment text instead of #FFFFFE,
   seafoam links, and a larger Verdana face (17px vs the house 15px) with the
   result-window reds/greens dimmed to match. Content only — the chrome vars stay
   untouched, and the rem-sized bars cannot follow --font-size by construction. */
:root[data-theme="willow"] {
  --bg: #232720;
  --panel: #2d322a;
  --panel-2: #272b25;
  --border: #4b5443;
  --text: #e4e0d0;
  --muted: #a6a892;
  --accent: #d4c690;
  --accent-2: #a7c489;
  --danger: #d69381;
  --link: #a3c9b4;
  --font: Verdana, Geneva, 'Trebuchet MS', sans-serif;
  --font-size: 17px;
  /* softened status colors — same hues, less shout */
  --bad: #e08d80;
  --result-good: #3d6b41;
  --result-bad: #8f4038;
  /* Pass 72 charts: a faint warm zebra and a flat moss header bar (Classic's
     flat-family structure, Willow's palette) */
  --row-alt: rgba(255, 255, 255, 0.045);
  --th-bg: #3b4534;
  --th-fg: #e4e0d0;
  --th-shadow: none;
}
:root[data-theme="willow"] a { color: var(--link); }
:root[data-theme="willow"] a:hover,
:root[data-theme="willow"] #mainnav a:hover { color: #d3ecdf; }
:root[data-theme="willow"] .panel,
:root[data-theme="willow"] .bonus-panel,
:root[data-theme="willow"] .server-card {
  border: 1px solid var(--border); border-radius: 8px;
  background: linear-gradient(#2f342c, #2a2e27);
}
:root[data-theme="willow"] button:not(.chip):hover {
  background: #3b4534; color: var(--text); border-color: #7f8f6e;
}
:root[data-theme="willow"] input:focus,
:root[data-theme="willow"] select:focus { outline: 1px solid #7f8f6e; }
:root[data-theme="willow"] nav.tabs button.active,
:root[data-theme="willow"] .panel h2 { color: var(--accent); }
/* the result window keeps its shape but drops the glare: no white flash text */
:root[data-theme="willow"] .msgwin { text-shadow: none; }

.throne-kd { font-size: 0.8rem; }   /* the kingdom (kd:island) link on the Throne */

tr.focus td { background: var(--panel-2); border-top: 1px solid var(--accent);
              border-bottom: 1px solid var(--accent); }

/* The normal realm's Throne owns its compact status hierarchy. */
body.realm-throne-ui #ticker, body.realm-throne-ui #resourcebar { display: none; }
body.realm-manage-ui #ticker, body.realm-manage-ui #resourcebar { display: none; }
body.realm-kingdom-ui #ticker, body.realm-kingdom-ui #resourcebar { display: none; }
body.realm-monarchy-ui #ticker, body.realm-monarchy-ui #resourcebar { display: none; }
.realm-throne { max-width: 46rem; margin: 0 auto .9rem; }
.realm-page-header { max-width: 46rem; margin: .7rem auto 0; }
.realm-kingdom-ui .realm-page-header, .realm-monarchy-ui .realm-page-header { padding-bottom: 1rem; }
.realm-kingdom-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .4rem; max-width: 46rem; margin: .7rem auto; padding-bottom: .45rem; border-bottom: 1px solid var(--chrome-border); }
.realm-kingdom-tabs button { min-width: 0; min-height: 2.75rem; border: 1px solid var(--chrome-border) !important; border-radius: .5rem; padding: .45rem .35rem; color: var(--chrome-text) !important; background: var(--chrome-panel) !important; text-transform: none; overflow-wrap: anywhere; }
@media (min-width: 600px) { .realm-kingdom-tabs { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.realm-kingdom-tabs button.active { border-color: var(--chrome-gold-2) !important; color: #1a1408 !important; background: linear-gradient(var(--chrome-gold-1), var(--chrome-gold-2)) !important; }
.realm-throne-clock { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .6rem; padding: .65rem .8rem; border: 1px solid var(--chrome-border); border-radius: .6rem; color: var(--chrome-muted); background: var(--chrome-bg); font-size: .82rem; font-weight: bold; }
.realm-throne-clock span:first-child, .realm-throne-clock span:nth-child(2) { color: var(--chrome-gold-1); }
.realm-throne-clock span:nth-child(3) { margin-left: auto; text-transform: uppercase; }
.realm-throne-clock b { color: var(--chrome-text); }
.realm-throne-resources { display: grid; grid-template-columns: 1.25fr 1fr 1fr .9fr .95fr; margin-top: .65rem; overflow: hidden; border: 1px solid var(--chrome-border); border-radius: .6rem; background: var(--chrome-bg); }
.realm-throne-resources > div { min-width: 0; padding: .5rem .2rem; border-right: 1px solid var(--chrome-border); text-align: center; }
.realm-throne-resources > div:last-child { border: 0; }
.realm-throne-resources span { display: block; overflow: hidden; color: var(--chrome-muted); font-size: .6rem; font-weight: bold; letter-spacing: .02em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.realm-throne-resources b { display: block; overflow: hidden; color: var(--chrome-gold-1); text-overflow: ellipsis; white-space: nowrap; }
/* ticket-0049 (owner, 2026-10-03): the strip also carries Land and Net worth. Phone first:
   two rows of four tracks — Gold / Food / Runes / Land, then Net worth (two tracks) / Mana /
   Stealth; one row of seven from 760px. */
.realm-throne-resources.wide { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.realm-throne-resources.wide > div:nth-child(-n+4) { border-bottom: 1px solid var(--chrome-border); }
.realm-throne-resources.wide > div:nth-child(4) { border-right: 0; }
.realm-throne-resources.wide > .res-nw { grid-column: span 2; }
@media (min-width: 760px) {
  .realm-throne-resources.wide { grid-template-columns: 1.25fr 1fr 1fr 1fr 1.15fr .9fr .95fr; }
  .realm-throne-resources.wide > div:nth-child(-n+4) { border-bottom: 0; }
  .realm-throne-resources.wide > div:nth-child(4) { border-right: 1px solid var(--chrome-border); }
  .realm-throne-resources.wide > .res-nw { grid-column: auto; }
}
/* 2026-09-29 (owner): the Throne's resources leave the header for their own card under the
   Kingdom Chat / Royal Command / Politics buttons. Phone-first: one full-width row per resource
   (label left, figure right, wrapping rather than clipping) so seven-plus-digit gold and
   six-digit food/runes always read in full; five centred cells from 40rem up.
   Owner 2026-09-29 (same day): Mana and Stealth are short percentages, so on the phone they
   share the last row (two half-width cells, a rule between them) to save a line. */
.realm-resources-card { max-width: 46rem; margin: .7rem auto 0; }
.realm-resources-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; }
.realm-resources-list > div { display: flex; grid-column: 1 / -1; justify-content: space-between; align-items: baseline; gap: .75rem; min-width: 0; padding: .5rem .1rem; border-bottom: 1px solid var(--chrome-border); }
.realm-resources-list > div:nth-child(4), .realm-resources-list > div:nth-child(5) { grid-column: auto; border-bottom: 0; }
.realm-resources-list > div:nth-child(4) { padding-right: .6rem; border-right: 1px solid var(--chrome-border); }
.realm-resources-list > div:nth-child(5) { padding-left: .6rem; }
/* ticket-0074: with Land + Net worth (cells 4–5) the phone pairs are Land|Net worth and Mana|Stealth */
.realm-resources-list.with-standing > div:nth-child(6), .realm-resources-list.with-standing > div:nth-child(7) { grid-column: auto; border-bottom: 0; }
.realm-resources-list.with-standing > div:nth-child(4), .realm-resources-list.with-standing > div:nth-child(5) { border-bottom: 1px solid var(--chrome-border); }
.realm-resources-list.with-standing > div:nth-child(6) { padding-right: .6rem; border-right: 1px solid var(--chrome-border); }
.realm-resources-list.with-standing > div:nth-child(7) { padding-left: .6rem; }
.realm-resources-list span { flex: 0 0 auto; color: var(--muted); font-size: .72rem; font-weight: bold; letter-spacing: .04em; text-transform: uppercase; }
.realm-resources-list b { min-width: 0; color: var(--accent); font-size: 1.1rem; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; text-align: right; }
@media (min-width: 40rem) {
  .realm-resources-list { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .5rem; }
  .realm-resources-list.with-standing { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .realm-resources-list.with-standing > div { border-bottom: 0; padding: .5rem .2rem; }
  .realm-resources-list > div { grid-column: auto; flex-direction: column; align-items: center; justify-content: flex-start; gap: .15rem; padding: .5rem .2rem; border-bottom: 0; border-right: 1px solid var(--chrome-border); text-align: center; }
  .realm-resources-list > div:last-child { border-right: 0; }
  .realm-resources-list b { text-align: center; }
}
.realm-throne-identity { padding: .9rem 0 .35rem; }
.realm-throne-identity h2 { margin: 0; color: var(--accent); }
.realm-throne-identity h2 a { color: var(--pa); text-decoration: none; }
.realm-throne-identity p { margin: .25rem 0; color: var(--muted); }
.realm-throne-identity p b { color: var(--text); }
.realm-throne-identity .realm-throne-ruler span { color: var(--accent); font-weight: bold; }
/* Owner 2026-09-29: the identity block reads Kingdom (x:x) → Province → Ruler with title →
   Race → Personality, one labelled line each; the kingdom line links to the Kingdom page. */
.realm-throne-identity p span { color: var(--accent); font-weight: bold; }
.realm-throne-identity .realm-throne-kingdom a { color: var(--pa); font-weight: bold; text-decoration: none; }
.realm-throne-identity h2 { margin: .15rem 0 .35rem; }
.realm-throne-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin-top: .65rem; }
.throne-stat-cards { display: grid; gap: .7rem; max-width: 46rem; margin: 0 auto .9rem; }
.throne-stat-cards article { padding: .8rem; border: 1px solid var(--chrome-border); border-radius: .6rem; background: var(--chrome-bg); }
.throne-stat-cards h3 { margin: 0 0 .6rem; color: var(--accent); font-size: 1rem; }
.throne-stat-cards dl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .35rem .7rem; margin: 0; }
.throne-stat-cards dl > div { min-width: 0; padding: .35rem 0; border-bottom: 1px solid var(--chrome-border); }
.throne-stat-cards dt { color: var(--chrome-muted); font-size: .72rem; font-weight: bold; letter-spacing: .03em; text-transform: uppercase; }
.throne-stat-cards dd { margin: .12rem 0 0; overflow-wrap: anywhere; color: var(--chrome-text); font-weight: bold; }
/* Growth sub-tabs + the Internal Affairs building ledger (owner 2026-09-27), phone first:
   the four chips sit 2-up at 2.75rem, ledger rows stack; from 600px the chips flow in a row and
   from 760px the ledger is a three-column grid. */
nav.tabs.growth-tabs, nav.tabs.pill-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .4rem; border-bottom: 0; }
nav.tabs.growth-tabs .chip, nav.tabs.pill-tabs .chip { display: grid; place-items: center; min-width: 0; min-height: 2.75rem; padding: .3rem .5rem; white-space: normal; text-align: center; border-radius: .5rem; }
/* Phone first for every realm page (owner 2026-09-27, Warfare audit): fields and selects are
   2.75rem tall and 16px so phones neither zoom nor mis-tap; the tournament frame has its own rule.
   The Legacy layout (body.realm-legacy-ui, 2026-10-02) shares it — same pages, other chrome. */
body.realm-bottom-tabs #view select, body.realm-legacy-ui #view select,
body.realm-bottom-tabs #view input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=file]):not([type=range]),
body.realm-legacy-ui #view input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=file]):not([type=range]) {
  min-height: 2.75rem; font-size: max(1rem, 16px); box-sizing: border-box; }
.ia-bld { display: grid; gap: .5rem; }
.ia-row { display: grid; gap: .15rem; padding: .5rem 0; border-bottom: 1px solid var(--border); }
.ia-row .ia-name { font-weight: bold; }
.ia-row .ia-num { color: var(--muted); font-size: .9rem; }
.ia-row .ia-fx { overflow-wrap: anywhere; }
.ia-row.ia-head { display: none; }
.ia-matrix { margin-top: .8rem; }
.ia-matrix summary { min-height: 2.75rem; display: flex; align-items: center; cursor: pointer; color: var(--accent); }
@media (min-width: 600px) {
  nav.tabs.growth-tabs, nav.tabs.pill-tabs { display: flex; flex-wrap: wrap; }
  nav.tabs.growth-tabs .chip, nav.tabs.pill-tabs .chip { min-height: 2.4rem; padding-inline: .9rem; }
}
@media (min-width: 760px) {
  .ia-bld { gap: 0; }
  .ia-row { grid-template-columns: minmax(0, 1.1fr) 9rem minmax(0, 3fr); gap: .8rem; align-items: start; }
  .ia-row .ia-num { font-size: inherit; }
  .ia-row.ia-head { display: grid; color: var(--muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .03em; }
}
/* Province card top tabs (2026-09-27): the Monarchy pill strip reused — 2-up at phone width,
   2.75rem tall; Internal Affairs arrivals stack as a plain list. */
.throne-stat-cards article nav.tabs.mon-pills { margin: 0 0 .7rem; }
.throne-stat-cards .throne-card-sub { margin-top: .8rem; }
.throne-arrivals { margin: 0; padding-left: 1.1rem; display: grid; gap: .3rem; }
.throne-arrivals li { overflow-wrap: anywhere; }
/* Phone first (owner 2026-09-27): the four province quick actions (Spells / Manage / State / Aid)
   sit 2-up at phone width, each a full-cell 2.75rem button; from 600px they flow in one row. */
.realm-throne-quick-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.realm-throne-quick-actions button { min-height: 2.75rem; width: auto; min-width: 0; }
@media (min-width: 600px) {
  .realm-throne-quick-actions { display: flex; flex-wrap: wrap; justify-content: center; }
  .realm-throne-quick-actions button { flex: 0 1 auto; }
}
/* The combat row (Manage Warfare / Mentor, owner 2026-09-27) follows the same 2-up phone grid;
   from 600px the two sit side by side, each capped at 18rem. */
@media (min-width: 600px) {
  .realm-throne-combat-actions { flex-wrap: nowrap; }
  .realm-throne-combat-actions button { width: min(100%, 18rem); }
}
.realm-mobile-tabs { display: none; }
@media (min-width: 760px) {
  .throne-stat-cards { grid-template-columns: 1fr; }
  .realm-throne-quick-actions { align-self: start; }
}
@media (max-width: 520px) {
  .realm-throne { margin-right: -.15rem; margin-left: -.15rem; }
  .realm-throne-clock { gap: .2rem .45rem; font-size: .75rem; }
  .realm-throne-identity h2 { font-size: 1.35rem; }
}

/* ==================== Pass 67: the Bubble theme ====================
   The legacy "bubble" look from the common-layout spec — near-black, primary gold
   #ffc300, Cinzel faces (vendored OFL woff2, Georgia fallback). Content only; the
   chrome bars stay on --chrome-*. */
@font-face {
  font-family: "Cinzel";
  font-style: normal; font-weight: 700; font-display: swap;
  src: url("cinzel-700.woff2") format("woff2");
}
@font-face {
  font-family: "Cinzel Decorative";
  font-style: normal; font-weight: 700; font-display: swap;
  src: url("cinzel-decorative-700.woff2") format("woff2");
}
:root[data-theme="bubble"] {
  --bg: #0b0c0f;
  --panel: #1c1f26;
  --panel-2: #14161b;
  --border: rgba(255, 195, 0, 0.25);
  --text: #d7dbe2;
  --muted: #8f96a3;
  --accent: #ffc300;
  --accent-2: #90ee90;
  --danger: #ec7566;
  --link: #7fa8e6;
  --advice: #ffe9a8;
  --font: "Cinzel", Georgia, "Times New Roman", serif;
  /* Pass 72: chart facelift — a faint gold zebra wash and a gold-on-slate header bar */
  --row-alt: rgba(255, 195, 0, 0.055);
  --th-bg: linear-gradient(#252833, #171a20);
  --th-fg: #ffc300;
  --th-shadow: none;
}
:root[data-theme="bubble"] body,
:root[data-theme="bubble"] {
  /* the solid colour first: Firefox for Android leaves the area past a fixed gradient
     unpainted (white) when the page is zoomed out (ticket-0045) */
  background: #0b0c0f linear-gradient(#0b0c0f, #14161b) fixed;
}
:root[data-theme="bubble"] .panel,
:root[data-theme="bubble"] .bonus-panel,
:root[data-theme="bubble"] .server-card,
:root[data-theme="bubble"] .pair {
  background: linear-gradient(#1c1f26, #14161b);
  border: 1px solid rgba(255, 195, 0, 0.35);
  border-radius: 16px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55),
              inset 0 1px 0 rgba(255, 233, 168, 0.12);
}
:root[data-theme="bubble"] .panel h2,
:root[data-theme="bubble"] .agedetails-h {
  font-family: "Cinzel Decorative", "Cinzel", Georgia, serif;
  color: #ffc300;
}
:root[data-theme="bubble"] th { color: #cc9c00; }
:root[data-theme="bubble"] a { color: #7fa8e6; }
:root[data-theme="bubble"] a:hover { color: #a9c6f5; }
:root[data-theme="bubble"] button:not(.chip) {
  background: #ffc300; color: #14141f; border-color: #ffc300; border-radius: 6px;
}
:root[data-theme="bubble"] button:not(.chip):hover { background: #ffe9a8; }
:root[data-theme="bubble"] button.quiet, :root[data-theme="bubble"] a.btnlink {
  background: var(--panel-2); color: var(--muted);
  border-color: rgba(255, 195, 0, 0.25);
}
:root[data-theme="bubble"] a.btnlink:hover { background: var(--panel-2); color: var(--text); }
:root[data-theme="bubble"] input, :root[data-theme="bubble"] select,
:root[data-theme="bubble"] textarea {
  border-color: rgba(255, 195, 0, 0.35);
}

/* ================= Pass 67.d: the Maneuvers set (mystics/thievery/war-room/
   uniques/targets/aid). Pill + bubble grids, the hostility meter, the war-room
   allocation table. Colors ride the theme variables so all three themes work. */

.warn { color: var(--advice); }

.pill-grid, .bubble-grid {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0;
}
.pill {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 12px; border-radius: 999px; cursor: pointer;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); font: inherit; font-size: 0.92em;
}
.pill span { font-size: 0.8em; color: var(--muted); }
.pill:hover { border-color: var(--accent); }
.pill.active { outline: 2px solid var(--accent); }
.pill.unknown { opacity: 0.45; cursor: default; }
.pill-intel { border-color: #4a6f9d; }           /* espionage runs blue */
.pill-intel:hover { border-color: #7fa8e6; }
.pill-sab { border-color: #8d4a41; }             /* sabotage runs red */
.pill-sab:hover { border-color: var(--danger); }

/* 67.h.11 (mystics): spell pills colored by time remaining on the province —
   grey = not cast, red < 1 tick, yellow < 4, green ≥ 4 or enduring. */
.pill-grey { border-color: var(--border); }
.pill-time-red { border-color: var(--bad); box-shadow: inset 0 0 0 1px var(--bad); }
.pill-time-yellow { border-color: var(--advice); box-shadow: inset 0 0 0 1px var(--advice); }
.pill-time-green { border-color: var(--good); box-shadow: inset 0 0 0 1px var(--good); }
.pill-time-red .pill-days { color: var(--bad); }
.pill-time-yellow .pill-days { color: var(--advice); }
.pill-time-green .pill-days { color: var(--good); }
.pill .pill-days { font-size: 0.75em; }
/* Spell bubbles (Auras / Support Spells / Combat; owner, 2026-09-29): four stacked lines —
   name, original name, rune cost, ticks left — no longer fit a full 999px pill, whose curved
   ends ate the first and last line. A rounded bubble with real padding and a floor width
   keeps every line centred and clear of the edge; the original name gets its own line. */
.pill.pill-spell {
  border-radius: 1.4rem; padding: .7rem .9rem; max-width: 100%;
  flex: 1 1 calc(50% - 4px);        /* phone first: two even bubbles per row, thumb-sized */
  justify-content: center; text-align: center; line-height: 1.25; gap: 3px;
  box-sizing: border-box; white-space: normal; overflow-wrap: anywhere;
}
.pill.pill-spell .old-name { display: block; margin: 0; max-width: 100%; white-space: normal; }
.pill.pill-spell > span { display: block; }
@media (min-width: 600px) {           /* tablet / desktop: natural width with a floor */
  .pill.pill-spell { flex: 0 1 auto; min-width: 9rem; padding: .7rem 1.2rem; }
}

/* Legacy (pre-rebrand) name beside the re-authored one — a quiet pill after every spell,
   race and building name in every theme (owner, 2026-09-28) so returning players
   recognise each item; Willow keeps its Classic-style teal italic. Always inline so a
   sentence ("Race Heartlander · Personality …") never breaks around it. */
.old-name { display: inline-block; margin-left: .3em; font-weight: normal; font-style: normal;
  font-size: .72rem; line-height: 1.3; color: #aebbd4; border: 1px solid #4d5f88;
  border-radius: 999px; padding: 0 .45rem; vertical-align: middle; white-space: nowrap;
  width: fit-content; justify-self: start; align-self: center; }
:root[data-theme="willow"] .old-name {
  font-style: italic;
  color: #86b3a4;                 /* Classic's teal family, lightened to read on Willow */
  border-color: #5f8f80;
  opacity: 0.9;
}

/* A hoverable term (throne Info durations): dotted underline + help cursor cue
   the title-attribute explanation. */
.has-tip { cursor: help; text-decoration: underline dotted 1px; text-underline-offset: 2px; }

/* 67.h.18: the result window — ONE component for every action outcome (spells,
   thievery, attacks, ritual casts), replacing the flat 67.h.12 box. An on-theme
   shell holds a bold centered message window: green = success, dark red = failure,
   purple = unique procs, amber = notices (legacy common/messages.html good / bad /
   unique / info, with the default theme's radial fills). Extras (intel, recast
   buttons) ride inside the shell, below the window. */
.result-shell {
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px; margin: 0 0 1rem; text-align: center;
}
.msgwin {
  padding: 10px 14px; border-radius: 8px; border: 1px solid rgba(254, 255, 234, 0.8);
  color: #fff; font-weight: bold; text-align: center; line-height: 1.5;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.4);
}
.msgwin + .msgwin { margin-top: 8px; }
.msgwin.good {
  background: #718d16;
  background: radial-gradient(ellipse at center, #789316 0%, #5d7a19 100%);
}
.msgwin.bad {
  background: #521802;
  background: radial-gradient(ellipse at center, #641e04 0%, #401100 100%);
}
.msgwin.unique {
  background: #3d1a4d; border-color: #dbb6ff;
  background: radial-gradient(ellipse at center, #512067 0%, #2a1233 100%);
}
/* a unique that COULD have procced but didn't — dimmed, faint, so it reads as "not this time" */
.msgwin.unique.dim {
  background: #241030; border-color: rgba(219, 182, 255, 0.4);
  background: radial-gradient(ellipse at center, #2c1638 0%, #180a20 100%);
  color: rgba(255, 255, 255, 0.72); font-weight: normal;
}
.msgwin.info {
  background: #a97a26;
  background: radial-gradient(ellipse at center, #d09734 0%, #594118 100%);
}
.msgwin .muted, .msgwin .pill-days { color: rgba(255, 255, 255, 0.85); }
.result-shell button { margin-top: 8px; }
/* transient messages (owner, 2026-09-29): outcome windows and the note strip fade out on their own */
.result-shell, #actionnote { transition: opacity .6s ease; }
.result-shell.fading, #actionnote.fading { opacity: 0; pointer-events: none; }
#arc-result .cast-error { transition: opacity .6s ease; }   /* fades like an outcome (ticket-0047) */
#arc-result .cast-error.fading { opacity: 0; pointer-events: none; }

/* The "show the math (and the code)" receipt (traceHtml) — a collapsible ledger of the
   arithmetic behind an action, each cited formula opening the ACTUAL source that ran.
   Lives inside the result-shell (attack/spell) or #sci-trace, so it re-establishes the
   left alignment the centered shell overrides. All colors ride the theme vars. */
.calc-trace {
  margin-top: 10px; text-align: left; border: 1px solid var(--border);
  border-radius: 8px; background: var(--panel); overflow: hidden;
}
.calc-trace > summary {
  cursor: pointer; padding: 6px 10px; color: var(--accent);
  font-weight: bold; list-style: none; user-select: none;
}
.calc-trace > summary::-webkit-details-marker { display: none; }
.calc-trace > summary::before { content: "\25B8\00a0"; color: var(--muted); }
.calc-trace[open] > summary::before { content: "\25BE\00a0"; }
.ct-body { padding: 4px 10px 10px; }
table.ct-steps { width: 100%; border-collapse: collapse; }
table.ct-steps td { padding: 2px 6px; vertical-align: top; border: none; background: none; }
.ct-steps .ct-group td {
  color: var(--accent); font-weight: bold; padding-top: 8px;
  border-bottom: 1px solid var(--border);
}
.ct-label { color: var(--text); white-space: nowrap; }
.ct-mid { color: var(--muted); width: 100%; }
.ct-formula { font-family: var(--mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace); }
.ct-val { color: var(--text); white-space: nowrap; font-weight: bold; text-align: right; }
.ct-note td { color: var(--muted); font-style: italic; padding-top: 0; }
a.ct-ref {
  color: var(--accent); text-decoration: none; font-size: 0.8em; vertical-align: super;
}
a.ct-ref:hover { text-decoration: underline; }
.ct-sources { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 6px; }
.ct-sources-head {
  color: var(--muted); font-size: 0.82em; text-transform: uppercase;
  letter-spacing: 0.04em; margin-bottom: 4px;
}
details.ct-code { margin: 3px 0; }
details.ct-code > summary {
  cursor: pointer; color: var(--muted); list-style: none; padding: 2px 0;
}
details.ct-code > summary::-webkit-details-marker { display: none; }
details.ct-code .ct-num { color: var(--accent); font-weight: bold; }
details.ct-code .ct-loc { color: var(--muted); font-size: 0.85em; margin-left: 6px; }
.ct-code pre {
  margin: 4px 0 6px; padding: 8px 10px; overflow-x: auto;
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  font-family: var(--mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace);
  font-size: 0.85em; line-height: 1.45; color: var(--text); white-space: pre;
}
.ct-code pre code { background: none; padding: 0; font: inherit; color: inherit; }

/* 67.h.12 rule, kept: anything that stops an action short is plain red text, never
   a box (legacy spells.html cast-error / thievery.html thieves-error). */
.op-error { color: var(--danger); font-weight: 700; }
.cast-error {
  color: #ff2d2d; font-weight: bold; text-align: center; font-size: 1.05em;
  margin: 10px auto 16px; text-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
}

/* 67.h.13: the legacy change-kingdom control (Kingdom : Island boxes) + shortcuts. */
.kd-boxes { align-items: flex-end; }
.kd-boxes .kd-colon { font-weight: 700; padding: 0 2px; }
.kd-chips { flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
.kd-chip { font-size: 0.85em; }
.kd-nav { gap: 6px; margin-bottom: 8px; }

/* 67.h.18 addendum: the War Room condensed — stat grids fold into single fact lines,
   and numeric inputs lose their spinner buttons everywhere (owner direction: the
   step arrows are useless at game magnitudes). */
.atk-facts { margin: 4px 0; color: var(--muted); }
.atk-facts b { color: var(--text); }
/* the march panel: one control per line; the key march figures glow white */
.march-lines label {
  display: flex; align-items: center; gap: 6px; margin: 3px 0; color: var(--muted);
}
.hl { color: #fff; font-weight: 700; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* Tournament coordinator: compact fields become clear setup sections on every screen width. */
.tournament-form { display: grid; gap: 1rem; margin-top: 1rem; }
.tournament-form label { display: grid; gap: 0.3rem; color: var(--muted); font-weight: bold; }
.tournament-form label > span { font-size: 0.86rem; }
.tournament-form input, .tournament-form select { width: 100%; box-sizing: border-box; }
.tm-core, .tm-settings, .tm-kingdoms { display: grid; gap: 0.8rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tm-settings { grid-template-columns: repeat(4, minmax(0, 1fr)); background: var(--panel-2); padding: 0.85rem; border: 1px solid var(--border); border-radius: 0.4rem; }
.tm-settings small, .tm-team legend small { color: var(--muted); font-weight: normal; }
.tm-teams { display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tm-team { min-width: 0; margin: 0; padding: 0.9rem; border: 1px solid var(--border); border-radius: 0.4rem; }
.tm-team legend { padding: 0 0.35rem; color: var(--accent); font-weight: bold; }
.tm-team > div { display: grid; gap: 0.65rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tm-player output { min-height: 2.3rem; padding: 0.55rem 0.65rem; border: 1px solid var(--border); border-radius: 0.3rem; background: var(--panel-2); color: var(--text); font-weight: normal; overflow-wrap: anywhere; }
.tm-actions { display: flex; justify-content: flex-end; padding-top: 0.2rem; }

.eyebrow { margin: 0; color: var(--muted); font-size: 0.82rem; font-weight: bold; letter-spacing: 0.08em; text-transform: uppercase; }
.tm-status-grid { display: grid; gap: 0.75rem; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 1.25rem 0; }
.tm-status-grid div { padding: 0.75rem; border: 1px solid var(--border); border-radius: 0.4rem; background: var(--panel-2); }
.tm-status-grid span, .tm-status-grid b { display: block; }.tm-status-grid span { color: var(--muted); font-size: 0.82rem; }.tm-status-grid b { margin-top: 0.2rem; }
.tournament-admin-shell { display: grid; gap: 1rem; }
.tournament-admin-tabs { display: flex; gap: 0.45rem; flex-wrap: wrap; padding: 0.75rem; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--panel-2); }
.tournament-admin-primary-tabs button.active, .tm-age-tabs button.active {
  border: 3px solid #fff0a8 !important;
  color: #171208 !important;
  background: linear-gradient(135deg, #ffd84b, #d99d00) !important;
  box-shadow: 0 0 0 2px #6d4b00, 0 .35rem .9rem rgba(0, 0, 0, .45) !important;
  font-weight: 800;
  text-shadow: none;
}
/* The Tournament command tabs need enough room for their labels. Keep the phone
   layout to two centered columns, then form a deliberate two-row command deck. */
.tournament-admin-primary-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); justify-content: center; gap: .6rem; }
.tournament-admin-primary-tabs button { width: 100%; min-height: 3.15rem; padding: .55rem .65rem; line-height: 1.2; text-wrap: balance; }
@media (min-width: 700px) {
  .tournament-admin-primary-tabs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tournament-admin-primary-tabs button:nth-child(7):last-child { grid-column: 2 / span 2; }
}
.tournament-control-room { border-color: var(--accent); }
.tm-enrollment { display: grid; gap: 0.45rem; margin: 1rem 0; padding: 0.8rem; border: 1px solid var(--accent); border-radius: 0.4rem; background: var(--panel-2); }
.tm-enrollment b { color: var(--accent); }.tm-enrollment span { color: var(--muted); }.tm-enrollment div { display: flex; gap: 0.45rem; flex-wrap: wrap; }
.tournament-season-form { display: grid; grid-template-columns: minmax(8rem, 0.75fr) minmax(15rem, 1.5fr) minmax(8rem, 0.75fr) auto; gap: 0.85rem; align-items: end; margin-top: 1rem; padding-top: 0.85rem; border-top: 1px solid var(--border); }
.tournament-season-form label { display: grid; gap: 0.3rem; color: var(--muted); font-weight: bold; }
.tournament-season-form label > span { font-size: 0.86rem; }
.tournament-season-form input { width: 100%; min-height: 2.55rem; }
.tournament-season-form button { min-height: 2.55rem; padding-inline: 1rem; white-space: nowrap; }
@media (max-width: 820px) { .tournament-season-form { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .tournament-season-form { grid-template-columns: 1fr; } }
.tm-age-season, .tm-age-roster, .tm-age-mods { margin: 0; padding: 1rem; border: 1px solid var(--border); border-radius: .45rem; background: var(--panel-2); }
.tm-age-season { display: grid; gap: .85rem; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.tm-age-season legend, .tm-age-roster legend { padding: 0 .35rem; color: var(--accent); font-weight: bold; }
.tm-age-roster summary, .tm-age-rules summary { color: var(--accent); cursor: pointer; font-weight: bold; }
.tm-age-roster summary span { color: var(--muted); font-size: .9rem; font-weight: normal; }
.tm-age-roster > p { margin-top: .85rem; }.tm-age-choice-list { display: grid; gap: .65rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tm-age-rules { margin: 0; padding: 1rem; border: 1px solid var(--border); border-radius: .45rem; background: var(--panel-2); }
.tm-age-rule-body { display: grid; gap: .75rem; margin-top: .85rem; }
.tm-age-tabs { margin: 1rem 0; }.tm-race-mods { display: grid; gap: .75rem; }
.tm-race-mods > details { padding: .85rem; border: 1px solid var(--border); border-radius: .4rem; background: var(--panel-2); }
.tm-race-mods summary { color: var(--accent); cursor: pointer; font-weight: bold; }.tm-race-mods summary span { color: var(--muted); font-weight: normal; }
.tm-race-mods details > div { margin-top: .75rem; }.tm-race-mods table { width: 100%; }
.tm-mod-direction { display: inline-block; padding: .18rem .42rem; border-radius: 999px; font-size: .78rem; font-weight: bold; white-space: nowrap; }
.tm-mod-direction.bonus-up { color: #155d34; background: #dff3e5; }.tm-mod-direction.bonus-down { color: #79430c; background: #fff0cf; }
.tm-delete-mod { min-width: 2rem; color: #9e2424; border-color: #9e2424; font-size: 1rem; }.tm-delete-mod:hover { color: #fff; background: #9e2424; }
/* Never expose the retired Race Quirk checkbox catalog. The table/dropdown builder replaces it. */
#tournament-race-mods .tm-quirk-builder > .tm-age-choice-list,
#tournament-race-mods .tm-quirk-builder > p { display: none !important; }
.tm-age-mods { color: var(--muted); }.tm-age-mods summary { color: var(--accent); cursor: pointer; font-weight: bold; }
.tm-upcoming-rules { padding: .75rem .85rem; border-left: 3px solid var(--accent); background: var(--panel-2); }
@media (max-width: 900px) { .tm-age-season { grid-template-columns: repeat(2, minmax(0, 1fr)); }.tm-age-choice-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .tm-age-season, .tm-age-choice-list { grid-template-columns: 1fr; } }
.tournament-form .tm-rule-toggle { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--border); border-radius: 0.4rem; background: var(--panel-2); color: var(--text); cursor: pointer; }
.tournament-form .tm-rule-toggle input { width: 1.1rem; height: 1.1rem; margin: 0; accent-color: var(--accent); }
.tournament-form .tm-rule-toggle span { display: grid; gap: 0.15rem; }.tournament-form .tm-rule-toggle small { color: var(--muted); font-weight: normal; }
.tm-match-rules { display: grid; gap: 0.75rem; margin: 0; padding: 1rem; border: 1px solid var(--accent); border-radius: 0.45rem; background: var(--panel-2); }
.tm-match-rules legend { padding: 0 0.35rem; color: var(--accent); font-weight: bold; }
.tm-live-list, .tm-roster-list { display: grid; gap: 0.7rem; }
.tm-live-list article, .tm-roster-list article { display: grid; gap: 0.35rem; padding: 0.85rem; border: 1px solid var(--border); border-radius: 0.4rem; background: var(--panel-2); }
.tm-live-list article b, .tm-roster-list article b { color: var(--accent); }
.tm-completed-match { border: 1px solid var(--border); border-radius: 0.4rem; background: var(--panel-2); }
.tm-completed-match summary { cursor: pointer; padding: 0.85rem; }
.tm-completed-match summary b { color: var(--accent); }
.tm-completed-match summary span { color: var(--muted); margin-left: 0.35rem; }
.tm-live-list .tm-completed-match > article { border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; }
.tm-roster-tabs { margin: 1rem 0; padding: 0.5rem; }
.tm-roster-kingdom { border: 1px solid var(--border); border-radius: 0.4rem; background: var(--panel-2); }
.tm-roster-kingdom summary { padding: 0.85rem; cursor: pointer; }.tm-roster-kingdom summary span { color: var(--muted); }
.tm-roster-provinces { display: grid; gap: 0.5rem; padding: 0 0.85rem 0.85rem; }
.tm-roster-provinces > div { display: grid; gap: 0.15rem; padding: 0.6rem; border-left: 3px solid var(--accent); background: var(--panel); }.tm-roster-provinces span { color: var(--muted); }
.tm-versus { color: var(--muted); font-weight: normal; }

.tournament-public-feed { display: grid; gap: 0.45rem; margin: 0; padding: 0; list-style: none; }
.tournament-public-feed li { padding: 0.65rem 0.8rem; border-left: 3px solid var(--accent); background: var(--panel-2); }
.tournament-public-feed b { color: var(--accent); }

@media print {
  header, nav, #mainnav, #adminnav, #gamefooter, button, .tm-status-grid + .muted { display: none !important; }
  body { background: #fff; color: #111; } .panel, .tm-team { border-color: #777; background: #fff; }
  .admin-table { color: #111; } .admin-table td, .admin-table th { border-color: #777; }
}
/* Tablet tier: the create/settings/kingdom/team grids default to 3-4 columns,
   which is cramped on a 768-900px portrait tablet. Collapse them to 2 columns
   here (the <=760 rule below refines to 1). Layout/function unchanged. */
@media (max-width: 900px) {
  .tm-settings { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-core, .tm-kingdoms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-team > div { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Wrapping niceties (additive, no layout change): roster/season dot-strings and the
   builder "select + Add Mod" row break cleanly instead of forcing wide content. */
.tournament-admin-shell .tm-roster-kingdom summary span,
.tournament-admin-shell .tm-age-roster summary span,
.tournament-admin-shell .tm-completed-match summary span { overflow-wrap: anywhere; }
.tournament-admin-shell .tm-builder-add { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.tournament-admin-shell .tm-builder-add select { flex: 1 1 14rem; min-width: 0; }
@media (max-width: 760px) {
  .tm-core, .tm-settings, .tm-kingdoms, .tm-teams { grid-template-columns: 1fr; }
  .tm-team > div { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-actions { justify-content: stretch; } .tm-actions button { width: 100%; }
  .tm-status-grid { grid-template-columns: 1fr; }
}

/* 67.h.14: the War Room — the attack blob and the fill-preset row. */
.atk-blob {
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 8px 12px; margin: 6px 0; font-size: 0.95em;
}
.atk-blob:empty { display: none; }
.fill-presets { flex-wrap: wrap; gap: 6px; align-items: center; }
.atk-extra-offense { display: flex; align-items: center; gap: 6px; margin: 0; padding: 0;
  border: 0; }
.atk-extra-offense legend { float: left; color: var(--muted); font-size: .72rem;
  font-weight: bold; text-transform: uppercase; }
.atk-extra-offense label { display: inline-flex; align-items: center; gap: 3px;
  min-height: 34px; border: 1px solid var(--border); border-radius: 6px; padding: 3px 7px; }
.atk-extra-offense label:has(input:checked) { border-color: var(--accent); color: var(--accent); }
.atk-extra-offense input { width: 15px; min-height: 15px; margin: 0; accent-color: var(--accent); }
.warfare-tabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; }
.warfare-tabs .chip { display: grid; place-items: center; min-width: 0; min-height: 2.75rem;
  padding: 5px 3px; text-align: center; overflow-wrap: anywhere; }
/* Manage Spells strip — Auras / Support Spells (owner, 2026-09-29: "hard to see, text a little
   squished"). The chrome chip's dark-blue pill sat on the brown panel with .22rem of padding.
   Two even, thumb-height buttons on the page's own palette: bordered panel tone at rest,
   the gold gradient when active. Phone first; natural width with a floor from 600px up. */
nav.tabs.warfare-tabs.spells-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .55rem; margin-bottom: 1rem; padding-bottom: 0; border-bottom: 0; }
nav.tabs.warfare-tabs.spells-tabs .chip {
  display: grid; place-items: center; min-height: 3rem; padding: .6rem 1rem; border-radius: .6rem;
  font-size: 1rem; font-weight: 600; letter-spacing: .01em; line-height: 1.2; text-align: center;
  white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--accent);
  box-shadow: inset 0 0 0 1px rgba(201, 164, 76, .18); }
nav.tabs.warfare-tabs.spells-tabs .chip:hover { color: var(--accent); border-color: var(--accent); }
nav.tabs.warfare-tabs.spells-tabs .chip.active { background: linear-gradient(var(--chrome-gold-1), var(--chrome-gold-2));
  color: #1a1408; border-color: var(--chrome-gold-2); font-weight: 700; box-shadow: none; }
@media (min-width: 600px) {
  nav.tabs.warfare-tabs.spells-tabs { display: flex; }
  nav.tabs.warfare-tabs.spells-tabs .chip { flex: 0 1 auto; min-width: 11rem; }
}
/* World page (owner, 2026-09-30, "hard to see/read"): Rankings / Archive / Directory wear the
   same buttons, three even columns on phones with tighter side padding so "Directory" fits at
   375px; natural width with a floor from 600px up like the rest. */
nav.tabs.warfare-tabs.spells-tabs.three-up { grid-template-columns: repeat(3, minmax(0, 1fr)); }
nav.tabs.warfare-tabs.spells-tabs.three-up .chip { padding: .6rem .4rem; }
@media (min-width: 600px) {
  nav.tabs.warfare-tabs.spells-tabs.three-up .chip { min-width: 9rem; padding: .6rem 1rem; }
}
.warfare-current-target { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px;
  align-items: center; margin-bottom: 8px; border: 1px solid #49628f; border-left: 4px solid var(--pa);
  border-radius: 7px; padding: 7px 9px; background: var(--panel-2); }
.warfare-current-target span { grid-column: 1; color: var(--muted); font-size: .65rem;
  font-weight: bold; text-transform: uppercase; }
.warfare-current-target b { grid-column: 1; }
.warfare-current-target a { grid-column: 2; grid-row: 1 / 3; }
.warfare-target-actions { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.intel-badge { min-height: 30px; border: 1px solid transparent; border-radius: 999px;
  padding: 3px 8px; color: #10170f; background: #91df9d; font-size: .68rem;
  font-weight: bold; text-transform: uppercase; }
.intel-badge.stale { color: #211603; background: #f2bd58; }
.intel-badge.none { color: #fff2f2; background: #89414a; }
/* Target Finder table (Discord bug-reports 2026-09-29): the Intel cell keeps the SoD badge
   and the archived-report chips on wrapped lines instead of a one-per-line pile; the
   table scrolls sideways inside its panel rather than squeezing; the province name is the
   selector on a desktop, so the Select button shows only in the phone cards. */
.tgt-table-wrap { overflow-x: auto; }
/* ticket-0072 follow-up (2026-10-06): Send aid's amount box and its Max button share a line
   when there's room and Max drops beneath on a phone, so the table fits the column instead of
   pushing Max (and the panel's text) off the right edge. */
.aid-amount { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .3rem; }
/* Tick totals under a cast / op result (2026-10-08) */
.tick-tally { margin: .5rem 0; font-size: .92rem; }
/* Quick cast on the Build / Military pages (2026-10-07) */
.quick-spell:empty { display: none; }
.quick-spell { border: 1px solid var(--border); border-radius: .5rem; padding: .5rem .7rem; margin: .4rem 0; }
.quick-spell-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem; }
.quick-spell-row > span { flex: 1 1 14rem; min-width: 0; }
.quick-spell-row button { min-height: 2.75rem; }
/* the button carries the spell's state (owner 2026-10-07): red = not cast (shows the rune cost),
   green = active (shows the ticks left) */
.quick-spell .qs-btn { color: #fff; font-weight: bold; border: 1px solid transparent; }
.quick-spell .qs-btn.qs-off { background: #9b2c2c; border-color: #c24a4a; }
.quick-spell .qs-btn.qs-on { background: #2f7d32; border-color: #4fa653; }
.quick-spell .qs-btn:disabled { opacity: .6; }
/* Bubble paints every button yellow (:root[data-theme="bubble"] button:not(.chip)) — the state
   colours must win there too */
:root[data-theme] .quick-spell button.qs-btn.qs-off:not(.chip), :root[data-theme] .quick-spell button.qs-btn.qs-off:not(.chip):hover { background: #9b2c2c; border-color: #c24a4a; color: #fff; }
:root[data-theme] .quick-spell button.qs-btn.qs-on:not(.chip), :root[data-theme] .quick-spell button.qs-btn.qs-on:not(.chip):hover { background: #2f7d32; border-color: #4fa653; color: #fff; }
.quick-spell .good { color: var(--accent-2); }
.quick-spell .bad { color: var(--danger); }
.quick-spell-note { margin: .4rem 0 0; }
/* "Your first days" new-player checklist on the Throne (2026-10-07) */
.tutorial-card h2 .muted { font-size: .8rem; font-weight: normal; }
.tutorial-steps { list-style: none; margin: .5rem 0 .8rem; padding: 0; display: grid; gap: .25rem; }
.tutorial-steps li { display: flex; align-items: center; gap: .6rem; min-height: 2.75rem; padding: 0 .3rem;
  border-bottom: 1px solid var(--border); }
.tutorial-steps li.done { color: var(--muted); }
.tutorial-tick { flex: 0 0 1.5rem; height: 1.5rem; display: grid; place-items: center;
  border: 1px solid var(--border); border-radius: 50%; color: var(--accent-2); font-weight: bold; }
.tutorial-steps li.done .tutorial-tick { border-color: var(--accent-2); }
/* Fallen-province report (2026-10-07): the dead province's last news on the lobby, newest first */
.fallen-card { border-color: var(--danger); }
.fallen-news { margin: .4rem 0 .8rem; padding-left: 1.2rem; display: grid; gap: .35rem; overflow-wrap: anywhere; }
/* ticket-0074: my net worth over another kingdom's table + each member's % of it */
.kdm-mynw { margin: .25rem 0 .5rem; }
.kdm-relnw { font-size: .8rem; color: var(--muted); white-space: nowrap; }
/* "out in N" protection countdowns (2026-10-05): the Target Finder and the Kingdom page */
.tgt-oop, .kdm-oop { display: inline-block; padding: 0 .4rem; border: 1px solid var(--border);
  border-radius: .6rem; font-size: .8rem; font-weight: normal; color: var(--muted); white-space: nowrap; }
#f-targets select { max-width: 100%; }
#f-targets .tgt-out-within input { width: 4.5rem; min-width: 0; font-size: 16px; }
#tgt-table td.tgt-intel { min-width: 12rem; }
@media (min-width: 701px) {
  #tgt-table .tgt-select { display: none; }
  #tgt-table .intel-open { min-height: 0; padding: 2px 8px; font-size: .8rem; }
}
@media (max-width: 700px) {
  .warfare-target-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: 8px; border: 1px solid var(--border); border-radius: 8px; padding: 7px;
    background: var(--panel-2); }
  .warfare-target-row td { display: block; padding: 3px 5px; border: 0; }
  /* the phone card names its figures (the table's headings are hidden here) */
  .warfare-target-row td[data-l]::before { content: attr(data-l) " "; color: var(--muted);
    font-size: .8em; }
  .warfare-target-row td.num[data-l] { display: flex; justify-content: space-between; gap: .5rem; }
  .warfare-target-row td:first-child, .warfare-target-row td:nth-last-child(-n+2) { grid-column: 1 / -1; }
  #tgt-table > tbody > tr:first-child, #tgt-table > tr:first-child { display: none; }
}

/* Pass 71: the intelligence report — the legacy two-column throne mirror and the
   generic data tables the council mirrors share. */
.intel-report { text-align: left; margin-top: 8px; }
.intel-report h3 { margin: 10px 0 6px; }
table.intel-stats { width: 100%; border-collapse: collapse; }
table.intel-stats th { text-align: right; color: var(--muted); font-weight: normal;
  padding: 2px 8px 2px 2px; white-space: nowrap; width: 18%; }
table.intel-stats td { text-align: left; padding: 2px 14px 2px 2px; width: 32%; }
/* Phone first (owner, 2026-10-01: "can't see any information on SoT on mobile" — the four
   legacy columns ran off the right edge and the unit counts were clipped): the throne mirror
   draws a two-column stack (province pairs, then military pairs) below 760px and the
   four-column table from 760px. */
table.intel-stats-wide { display: none; }
table.intel-stats-stack th { width: 45%; white-space: normal; }
table.intel-stats-stack tr { border-top: 1px solid var(--border); }
@media (min-width: 760px) {
  table.intel-stats-stack { display: none; }
  table.intel-stats-wide { display: table; }
}
table.data { border-collapse: collapse; margin: 4px 0; }
table.data th, table.data td { padding: 2px 10px; border-bottom: 1px solid var(--border); }
table.data th { text-align: left; color: var(--muted); font-weight: normal; }
table.data td.num, table.data th.num { text-align: right; }
/* the military availability grids (advisor + SoM mirror): compact columns sized to their
   figures — the grid no longer stretches across the page, so the armies sit evenly side
   by side instead of drifting apart on a wide screen (owner, 2026-10-04) */
table.data.army { width: auto; max-width: 100%; table-layout: auto; }
col.army-col-name { width: 11rem; }
col.army-col-home { width: 10rem; }
col.army-col-slot { width: 7.5rem; }
table.data.army td { text-align: right; }
/* the column headers sit flush over their numbers — right-aligned like the entries
   below, label column left (both the advisor grid and the SoM mirror) */
table.data.army th, table.army-grid th { text-align: right; }
table.data.army th:first-child, table.army-grid th:first-child,
table.army-grid td:first-child { text-align: left; }
table.army-grid { width: auto; max-width: 100%; table-layout: auto; }
/* The Military advisor's Army Availability, phone first (owner, 2026-09-30: the grid's
   numbers ran together): one card per army, label left / number right; the grid itself
   shows from 760px, its cells padded so neighbouring numbers never touch. */
.army-grid-wrap { display: none; overflow-x: auto; }
.army-cards { display: grid; gap: 0.6rem; }
.army-card { border: 1px solid var(--border); border-radius: 0.5rem; padding: 0.5rem 0.75rem; }
.army-card h4 { margin: 0 0 0.3rem; }
.army-card h4 .muted { font-weight: normal; font-size: 0.85em; }
.army-line { display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; padding: 0.3rem 0; border-top: 1px solid var(--border); }
.army-line .num { text-align: right; white-space: nowrap; }
/* "You can send about N offense right now" under the army grid, and the Throne's "home now" half. */
/* Military Strength: one label/number pair per row so no figure is clipped on a phone. */
table.mil-strength th { text-align: left; font-weight: normal; }
table.mil-strength td { white-space: nowrap; }
.send-now { margin: 0.6rem 0 0; }
.send-now a { display: inline-flex; align-items: center; min-height: 2.75rem; }
.home-now { display: block; color: var(--muted); font-size: 0.85em; }
.home-now b { color: var(--text); }
table.army-grid th, table.army-grid td { padding: 0.3rem 0.6rem; }
/* Aid page: Kingdom aid requests wear the same two faces (ticket-0031, 2026-09-30). */
.aidreq-grid-wrap { display: none; overflow-x: auto; }
.aidreq-cards { display: grid; gap: 0.6rem; }
.aidreq-cards .army-line a { min-height: 2.75rem; display: inline-flex; align-items: center; }
@media (min-width: 760px) {
  .army-cards { display: none; }
  .army-grid-wrap { display: block; }
  .aidreq-cards { display: none; }
  .aidreq-grid-wrap { display: block; }
}
#atk-kd-meter .hostmeter { margin: 8px 0 4px; }

/* 67.h.18 addendum: the atk-cols split is gone — the march orders live in their own
   half-width panel beside the target kingdom (the shared .cols row), the blob inside
   it. Own-kingdom red banner; bubbles' relative-networth third line. */
.own-kd-banner {
  color: var(--danger); font-weight: 700; text-align: center;
  border: 1px solid var(--danger); border-radius: 8px; padding: 6px 10px;
  margin-bottom: 8px;
}
.bubble .bubble-nw { font-size: 0.78em; color: var(--pa); }

/* 67.h.16: collapsible page blurbs (the Aid description). */
/* Pass 82: a foldable panel section — the summary reads like the panel's own h3 */
.panel details.fold > summary {
  cursor: pointer; font-size: 1rem; font-weight: bold;
  color: var(--text); margin: 1rem 0 0.4rem;
}
/* The Military page's Barracks stats, folded behind their arrow under all four top buttons
   (owner, 2026-10-04): the closed summary is the whole card, a thumb-sized tap target. The
   Mentor hall's introduction (owner, 2026-10-05, Legacy only — app.js renderMentor) wears the
   same fold as .intro-fold: one rule set, the Barracks selector last so it reads as before. */
.panel details.intro-fold > summary, .panel details.barracks-fold > summary { margin: 0; min-height: 2.75rem; display: flex; align-items: center; gap: .5rem; color: var(--accent); list-style: none; cursor: pointer; }
.panel details.intro-fold > summary h2, .panel details.barracks-fold > summary h2 { margin: 0; }
.panel details.intro-fold > summary::-webkit-details-marker, .panel details.barracks-fold > summary::-webkit-details-marker { display: none; }
.panel details.intro-fold > summary::after, .panel details.barracks-fold > summary::after { content: "▸"; margin-left: auto; font-size: 1.2rem; }
.panel details.intro-fold[open] > summary::after, .panel details.barracks-fold[open] > summary::after { content: "▾"; }
.panel details.intro-fold[open] > summary, .panel details.barracks-fold[open] > summary { margin-bottom: .5rem; }
.panel details.intro-fold > p { margin-bottom: 0; }
/* The personality's share of a unit's off/def on the Military page ("Freak: +5 off · −2 def"):
   its own line under the card header on a phone and under the Off/Def figure in the table. */
.unit-bonus { display: block; font-size: .85rem; color: var(--muted); }
.unit-bonus b.good { color: var(--good); }
.unit-bonus b.bad { color: var(--bad); }
/* The Military page's four top buttons (Training / Draft Calculator / Release / Advisor): a 2×2
   grid on a phone, one row from tablet width. */
nav.tabs.military-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .4rem; }
nav.tabs.military-tabs .chip { justify-content: center; min-width: 0; text-align: center; }
@media (min-width: 760px) {
  nav.tabs.military-tabs { display: flex; }
}
details.pagehelp { margin: 0.2rem 0 0.6rem; }
details.pagehelp summary { cursor: pointer; color: var(--link); font-size: 0.9em; }
details.pagehelp p { margin: 0.4rem 0 0; }
.pill-days.age-green { color: var(--good); }
.pill-days.age-yellow { color: var(--advice); }
.pill-days.age-red { color: var(--bad); }

.bubble {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: 6px 10px; border-radius: 10px; cursor: pointer;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); font: inherit; font-size: 0.9em;
}
.bubble span { font-size: 0.8em; color: var(--muted); }
.bubble:hover { border-color: var(--accent); }
.bubble.active { outline: 2px solid var(--accent); }
.bubble:disabled { opacity: 0.4; cursor: default; }
/* intel freshness (thievery.md §A5): green < 2 ticks, yellow 2–4, red older */
.bubble.fresh-green { border-left: 4px solid var(--good); }
.bubble.fresh-yellow { border-left: 4px solid var(--advice); }
.bubble.fresh-red { border-left: 4px solid var(--bad); }
.bubble.fresh-none { border-left: 4px solid var(--border); }

/* the inline hostility meter (war-room.md §A3.5) */
.hostmeter { display: flex; align-items: center; gap: 10px; margin: 8px 0; }
.hostmeter .hm-band b { letter-spacing: 0.05em; }
.hm-normal { color: var(--good); }
.hm-unfriendly { color: var(--advice); }
.hm-hostile, .hm-war { color: var(--bad); }
.hm-bar {
  position: relative; flex: 1; max-width: 340px; height: 10px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 5px;
}
.hm-fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: linear-gradient(90deg, var(--accent-2), var(--danger));
  border-radius: 5px 0 0 5px;
}
.hm-mark { position: absolute; top: -2px; bottom: -2px; width: 1px; background: var(--muted); }
.hm-proj {
  position: absolute; top: -5px; width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 7px solid var(--advice);
}

.unique-inline h3 { margin-top: 0; }
.unique-card { border-top: 1px solid var(--border); padding: 6px 0; }
.unique-card:first-of-type { border-top: none; }
.unique-card.passive { opacity: 0.9; }

.atk-units td, .atk-units th { padding: 3px 8px; }
.atk-units input[type="number"] { text-align: right; width: 7em; }
th.sortable { cursor: pointer; text-decoration: underline dotted; }
.mystic-intro summary h2 { display: inline; }

/* pill/bubble polish under the Bubble theme */
:root[data-theme="bubble"] .pill, :root[data-theme="bubble"] .bubble {
  background: linear-gradient(#1c1f26, #14161b);
  border-radius: 999px;
}
:root[data-theme="bubble"] .pill.active, :root[data-theme="bubble"] .bubble.active {
  outline-color: #ffc300;
}
/* Pills are buttons, and the theme's yellow `button:not(.chip)` rule outranked the dark
   pill above — spell bubbles came out yellow with their grey old name, grey rune cost and
   green "enduring" unreadable on it (ticket-0047, 2026-10-03). Keep pills dark. */
:root[data-theme="bubble"] button.pill:not(.chip) {
  background: linear-gradient(#1c1f26, #14161b); color: var(--text);
  border-color: var(--border); border-radius: 999px;
}
:root[data-theme="bubble"] button.pill.pill-spell:not(.chip) { border-radius: 1.4rem; }
:root[data-theme="bubble"] button.pill:not(.chip):hover {
  background: linear-gradient(#262a33, #1a1d23); border-color: var(--accent);
}
:root[data-theme="bubble"] button.pill.pill-time-red:not(.chip) { border-color: var(--bad); }
:root[data-theme="bubble"] button.pill.pill-time-yellow:not(.chip) { border-color: var(--advice); }
:root[data-theme="bubble"] button.pill.pill-time-green:not(.chip) { border-color: var(--good); }

/* Pass 67.e: the confirm modal (surrender / force-cease-fire / raze) — theme-neutral,
   riding the panel styles so all three themes dress it themselves. */
.modal-overlay {
  position: fixed; inset: 0; z-index: 70; display: flex;   /* above #watermark (z-60) */
  align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .55);
}
.modal-overlay .modal { max-width: 420px; margin: 1rem; }
.kd-flag { font-size: 1.05em; }

/* Pass 67.f: the Preferences hub's disabled cards */
.pref-card.disabled { opacity: .55; }
.pref-card.disabled h3 { color: inherit; }
/* the Display-preferences box: each toggle's brief description tucks under it */
.pref-note { margin: .1rem 0 .8rem 1.6rem; }

/* Pass 67.h.6: the Growth refinement — two-column buildings list, inline
   checkbox rows, and the legacy-parity percent build calculator. */
.grow-cols { display: flex; gap: 1.5rem; flex-wrap: wrap; align-items: flex-start; }
.grow-cols > div { flex: 1 1 260px; min-width: 0; }
/* The two building tables fit their columns on every theme (owner, 2026-10-01: Willow and
   Bubble's wider type gave each column a horizontal scroll bar): fixed layout, the number
   columns sized, the entry box filling its cell, long names wrapping. */
.grow-cols table, form.stack.wide > div > table.zebra { table-layout: fixed; width: 100%; }
.grow-cols table th:nth-child(2), .grow-cols table th:nth-child(3) { width: 4.2rem; }
.grow-cols table th:last-child { width: 5.6rem; }
.grow-cols table td:first-child { overflow-wrap: anywhere; }
.grow-cols td.grow-in input, td.grow-in input { width: 100%; min-width: 0; box-sizing: border-box; }
th.ctr, td.ctr { text-align: center; }
form.stack.wide { max-width: none; }
form.stack label.check {
  flex-direction: row; align-items: center; gap: 0.5rem; margin-top: 0.35rem;
}
form.stack label.check input { margin: 0; }
/* Sign-up's Discord block (owner 2026-10-11): the player's own Discord ID and the bot-message
   yes/no; the two answers are thumb-sized rows on a phone. */
.su-discord { display: flex; flex-direction: column; gap: 0.45rem; margin: 0.3rem 0 0;
  padding: 0.6rem 0.8rem 0.7rem; border: 1px solid var(--border); border-radius: 4px; }
.su-discord legend { padding: 0 0.3rem; color: var(--text); }
.su-help { margin: 0; font-size: 0.88em; }
.su-ask { margin: 0.3rem 0 0; color: var(--text); }
.su-discord label.check { min-height: 2.75rem; margin-top: 0; }
/* Only the box and its words toggle a checkbox (ticket-0049, Grant, 2026-10-04): in a stack
   form the label stretched the whole row, so clicking the empty space beside "rush" — to
   leave a number box — ticked Rush by accident. */
form.stack label.check { align-self: flex-start; }
/* Owner 2026-07-21: the Modify page's details box reads as aligned "label — box"
   lines — each field label and its entry share a row (fixed columns keep the boxes
   ranked), the entries slim down, and the form sheds the narrow stack cap so the
   inline confirm statement no longer wraps at half the panel. */
#f-pref-modify { max-width: none; }
#f-pref-modify > label:not(.check), #modify-identity label {
  display: grid; grid-template-columns: 8.5rem 15rem;
  column-gap: 0.6rem; align-items: center;
}
/* 67.h.7: the Sciences page's what-if line under an effect ("↳ +N books would add +X%") */
.proj { font-size: 0.85rem; margin-top: 0.15rem; }

/* 67.h.8: the Military page — the two policy boxes center their forms as a block;
   the release table gets roomier columns (its form already rides .stack.wide). */
.policy-box h3 { text-align: center; }
.policy-box form.stack, .policy-box > p {
  max-width: 24rem; margin-left: auto; margin-right: auto;
}
/* Keep the Draft / Future-draft boxes truly side by side (like the mystics
   Support-Spells / Wizards pair). Their selects hold long date & rate options,
   whose intrinsic width would otherwise inflate the box's minimum size and make
   .cols wrap them into a stack — so let the boxes and their selects shrink. */
.cols > .panel.policy-box { min-width: 0; }
.policy-box form.stack label { min-width: 0; }
.policy-box form.stack select { width: 100%; min-width: 0; }
table.release-table th, table.release-table td { padding: 0.45rem 1.4rem 0.45rem 0; }

.calc-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: .65rem; width: 100%; padding: .4rem 0;
}
/* One card per building, four rows (owner, 2026-10-01: the two-column card "looks wonky" on
   the themes): the name, its old-name pill, the percent typed, and the acres to build or
   raze — each on its own line, the same on every theme. */
.calc-card { display: grid; grid-template-columns: minmax(0, 1fr); gap: .3rem;
  align-content: start; padding: .55rem; border: 1px solid var(--border); border-radius: .45rem;
  background: var(--panel-2); }
/* Cards in one grid row share their four row tracks (subgrid, where supported), so the boxes
   line up across the row even when a name or pill wraps. */
@supports (grid-template-rows: subgrid) {
  .calc-card { grid-row: span 4; grid-template-rows: subgrid; }
}
.calc-name { min-width: 0; font-size: .9rem; color: var(--text); font-weight: bold; line-height: 1.2;
  overflow-wrap: anywhere; }
.calc-old { min-height: 1.2rem; }
.calc-old .old-name { display: inline-block; margin: 0; max-width: 100%; white-space: normal;
  overflow-wrap: normal; line-height: 1.35; }
.calc-grid input { width: 100%; min-width: 0; box-sizing: border-box; padding: .45rem; text-align: center; }
.calc-delta {
  min-width: 0; max-width: 100%; font-size: .8rem; border-radius: 3px; text-align: center;
  padding: .2rem .3rem; background: var(--panel); color: var(--muted);
}
.calc-delta.pos { color: var(--good); }
.calc-delta.neg { color: var(--bad); }
.calc-total {
  display: inline-block; font-size: 1.05rem; font-weight: 600; color: var(--bad);
  background: var(--panel-2); border-radius: 4px; padding: 0.15rem 0.6rem;
  margin: 0.5rem 0 0.2rem;
}
.calc-total.ok { background: var(--good); color: #1c3316; }

/* ==================== Pass 74: the Kingdom page ====================
   Legacy-parity layout + the owner's war identification: a faint red wash over
   ANY warring kingdom's page plus the banner strip. Member-row colors are TEXT
   colors, exactly the legacy classes (.protected/.monarch/.chamberlain). */
:root { --war-wash: rgba(190, 35, 25, 0.08); }
:root[data-theme="classic"] { --war-wash: rgba(255, 70, 50, 0.10); }
:root[data-theme="bubble"] { --war-wash: rgba(190, 35, 25, 0.07); }
.kd-page { position: relative; }
.kd-page.kd-war::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--war-wash); z-index: 5; border-radius: 6px;
}
.kd-warbanner {
  background: #7a1f1f; color: #fff; padding: 0.45rem 1rem; font-weight: 600;
  border-radius: 6px; margin-bottom: 0.8rem;
}
.kd-warbanner a { color: #ffd7d7; }
.kd-warbanner .kd-warnote { display: block; font-weight: normal; font-size: 0.85em;
  color: #e9baba; }
.kd-banner-box { text-align: center; }
.kd-banner { max-width: 600px; max-height: 100px; width: auto; object-fit: contain; }
/* Pass 74 addendum II (owner layout): centered head with the stance called out
   large; ONE centered stat grid — paired totals↔ranks, "Wars Won / War Score"
   spanning it centered, and every unpaired row (avg size / history entries /
   open relations) sharing the totals' label column so they align. */
.kd-head { text-align: center; }
.kd-head .kd-nav, .kd-head .kd-boxes {
  display: flex; justify-content: center; align-items: center; gap: 6px;
  flex-wrap: wrap;
}
.kd-head .kd-headline { margin: 0.1rem 0 0.5rem; }
.kd-stance { margin: 0.15rem 0 0.1rem; font-size: 1.15rem; letter-spacing: 0.05em; }
.kd-stance b { color: var(--accent); text-transform: uppercase; }
.kd-statsbox {
  display: grid; grid-template-columns: max-content max-content max-content max-content;
  gap: 3px 16px; margin: 0.9rem auto 0.5rem; width: fit-content;
  align-items: baseline;
}
.kd-statsbox .kd-col2 { margin-left: 1.5rem; }
/* addendum III: both label columns hug their values from the right, and the
   whole attitude block (rows, meter, taunt link) centers in the panel */
.kd-statsbox > .muted { text-align: right; }
.kd-attitude { text-align: center; }
.kd-attitude .kdmeter-box { margin: 0 auto; }
.kd-warscore {
  grid-column: 1 / -1; text-align: center; margin: 0.5rem 0 0.35rem;
  border-top: 1px solid var(--border); padding-top: 0.5rem;
}
.kd-warscore b { color: var(--accent); }
.kd-statsbox .kd-wide { grid-column: 2 / -1; }
/* addendum V: the two-line avg-opponent row centers its value (and label)
   vertically instead of riding the first line's baseline */
.kd-statsbox .kd-vcenter { align-self: center; }
.kdm-table-wrap { width: 100%; }
/* legacy member-row text colors (kingdom_details CSS) + the greyed empty slots */
#view tr.kdm-protected > td { color: #99ffbb; }
#view tr.kdm-monarch > td { color: #F28585; }
#view tr.kdm-officer > td { color: #FFC583; }
#view tr.unused-slot > td { color: #B0B0B0; }
#view #kdm-table tr.me > td { font-weight: 700; }
.kdm-slot { color: var(--muted); font-size: 0.85em; }
#view tr.kdm-dead > td { color: var(--danger); }
#kdm-table th { cursor: pointer; white-space: nowrap; }
#kdm-table th.sort-asc::after { content: " ▲"; font-size: 0.75em; }
#kdm-table th.sort-desc::after { content: " ▼"; font-size: 0.75em; }
.kdm-legend { font-size: 0.85em; }
@media (max-width: 600px) {
  .kd-statsbox { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: .35rem .65rem; width: 100%; }
  .kd-statsbox .kd-col2 { margin-left: 0; }
  .kd-statsbox > .muted, .kd-statsbox > span { min-width: 0; overflow-wrap: anywhere; }
  .kd-statsbox > .muted { text-align: left; }
  .kd-statsbox .kd-wide { grid-column: 2; }
  .kdm-table-wrap, #kdm-table, #kdm-table tbody { display: block; width: 100%; }
  #kdm-table .kdm-head { display: none; }
  #kdm-tbody { display: grid; gap: .55rem; }
  #kdm-tbody tr { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; padding: .45rem .55rem; border: 1px solid var(--border); border-radius: .5rem; }
  #kdm-tbody td { display: grid; min-width: 0; gap: .1rem; padding: .3rem .2rem; border-bottom: 1px solid var(--border); overflow-wrap: anywhere; text-align: left; }
  #kdm-tbody td::before { content: attr(data-label); color: var(--muted); font-size: .7rem; font-weight: bold; letter-spacing: .03em; text-transform: uppercase; }
  #kdm-tbody td:nth-last-child(-n+2) { border-bottom: 0; }
}
/* the war-history badges + open-relations levels (legacy palette) */
.wh-win { color: #2fa84a; } .wh-loss { color: #e04b3a; }
.wh-mutual { color: #FFBF00; } .wh-ongoing { color: var(--danger); }
.rel-unfriendly { color: #FFBF00; } .rel-hostile { color: #FF4000; }
/* the two-pointer hostility meter (legacy band hexes; WAR rides past the scale).
   Addendum I: each pointer is a centered arrow+label stack, its ARROW TIP on the
   value's exact spot; the box reserves room so the labels never collide. */
.kdmeter-box { padding: 26px 0; max-width: 380px; }
.kdmeter { position: relative; display: flex; height: 14px;
  border: 1px solid var(--border); border-radius: 5px; }
.kdm-seg { height: 100%; }
.kdm-seg.seg-normal { background: #01DF01; }
.kdm-seg.seg-unfriendly { background: #FFBF00; }
.kdm-seg.seg-hostile { background: #FF4000; }
.kdm-seg.seg-war { background: #FF0000; }
.kdm-ptr { position: absolute; font-size: 10px; line-height: 1.1;
  display: flex; flex-direction: column; align-items: center;
  transform: translateX(-50%); color: var(--text); white-space: nowrap; }
.kdm-ptr b { font-size: 11px; }
.kdm-ptr i { font-style: normal; }
.kdm-ptr.kdm-us { top: calc(100% + 1px); }
.kdm-ptr.kdm-them { bottom: calc(100% + 1px); }
/* Pass 75: the throne hall's sub-pages — Monarch Options half-width with the
   enemy + banner stacked beside it; the right column's boxes split the height */
.mon-cols { display: flex; gap: 1rem; align-items: stretch; flex-wrap: wrap; }
.mon-cols .mon-left { flex: 1 1 340px; display: flex; }
.mon-cols .mon-left > .panel { flex: 1; margin-bottom: 0; }
.mon-cols .mon-right { flex: 1 1 340px; display: flex; flex-direction: column; gap: 1rem; }
.mon-cols .mon-right > .panel { flex: 1; margin-bottom: 0; }
.mon-cols { margin-bottom: 1rem; }
/* Phone-first (2026-09-29): a flex column's automatic min-width is its content's min-content,
   so the right column (banner file input, enemy boxes) held 380px and zoomed the whole page out
   at 375px. Columns may shrink, unbreakable controls fit their panel, the boxes row wraps. */
.mon-cols .mon-left, .mon-cols .mon-right, .mon-cols .panel { min-width: 0; max-width: 100%; }
.mon-cols input[type="file"], .mon-cols select, .mon-cols textarea { max-width: 100%; min-width: 0; }
.mon-cols form.stack .row { flex-wrap: wrap; min-width: 0; }
.mon-cols form.stack .row > * { min-width: 0; }
.kd-boxes { flex-wrap: wrap; }
.mon-tabs { margin-top: 0.2rem; }
/* Monarchy sub-pages, phone first (2026-09-26): the Monarchy tabs and the Dragons / Rituals
   pills are two-column grids of thumb-height buttons; cards stack; every field is full
   width and 16px+; stat tiles sit two across. From tablet width the tabs line up, the
   choice cards and tiles go three across, and the field rows relax. Min-width only. */
nav.tabs.mon-tabs, nav.tabs.mon-pills { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.4rem;
  border-bottom: 0; margin-bottom: 0.9rem; }
nav.tabs.mon-tabs button, nav.tabs.mon-pills button { min-height: 2.75rem; padding: 0.4rem 0.4rem; border: 1px solid var(--border);
  border-radius: 999px; font-size: 0.9rem; text-align: center; }
nav.tabs.mon-pills button.active { background: var(--panel); color: var(--accent); border-color: var(--accent);
  font-weight: bold; border-radius: 999px; }
.stat-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.45rem; margin: 0.6rem 0; }
.stat-tile { display: grid; gap: 0.15rem; padding: 0.5rem 0.6rem; border: 1px solid var(--border); border-radius: 0.4rem;
  background: var(--panel-2); overflow-wrap: anywhere; }
.stat-tile span { color: var(--muted); font-size: 0.78rem; }
.mon-cards { display: grid; gap: 0.5rem; }
.mon-card { display: grid; gap: 0.3rem; padding: 0.6rem 0.7rem; border: 1px solid var(--border); border-radius: 0.45rem;
  background: var(--panel-2); }
.mon-card > b { color: var(--accent); }
.mon-card p { margin: 0; }
.mon-choice { grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 0.7rem; cursor: pointer; min-height: 2.75rem; }
.mon-choice input { width: 1.5rem; height: 1.5rem; margin: 0.15rem 0 0; }
.mon-choice > span { display: grid; gap: 0.2rem; }
.mon-choice:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.mon-form { gap: 0.6rem; }
.mon-field { display: grid; gap: 0.25rem; }
.mon-field > span { color: var(--muted); font-size: 0.85rem; }
.mon-field > span small { display: block; }
.mon-field input, .mon-form input[type="number"], .mon-form input[type="text"] { width: 100%; box-sizing: border-box;
  min-height: 2.75rem; font-size: max(1rem, 16px); }
.mon-actions { display: grid; gap: 0.5rem; margin-top: 0.3rem; }
.mon-actions button { min-height: 2.75rem; width: 100%; }
.mon-confirm { display: grid; gap: 0.5rem; margin-top: 0.6rem; }
.mon-fold > summary { cursor: pointer; font-weight: bold; color: var(--accent); min-height: 2.75rem; display: flex;
  align-items: center; gap: 0.5rem; }
.mon-fold > summary .muted { font-weight: normal; }
.mon-fold[open] > summary { margin-bottom: 0.5rem; }
.slay-unit .mon-field { margin-top: 0.2rem; }
@media (min-width: 760px) {
  nav.tabs.mon-tabs, nav.tabs.mon-pills { display: flex; flex-wrap: wrap; }
  nav.tabs.mon-tabs button, nav.tabs.mon-pills button { min-height: 2.4rem; padding-inline: 0.9rem; }
  .stat-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .mon-cards.mon-choices, .mon-cards.slay-units { grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }
  .mon-field input, .mon-form input[type="number"], .mon-form input[type="text"] { min-height: 2.4rem; font-size: 1rem; }
  .mon-actions { display: flex; flex-wrap: wrap; justify-content: flex-start; }
  .mon-actions button { width: auto; min-width: 12rem; min-height: 2.4rem; }
}
/* Monarchy strip buttons (owner, 2026-09-30, "hard to see/read due to color"): the Manage
   Spells look — panel tone with a gold outline at rest, the gold gradient when selected — as
   two even columns of thumb-height buttons on phones, natural width with a floor from 760px
   up. Sits after the 760px block above so it wins the tie on min-height and padding. */
nav.tabs.mon-tabs button, :root[data-theme] nav.tabs.mon-tabs button {
  min-height: 3rem; padding: .6rem .6rem; border-radius: .6rem; font-size: 1rem; font-weight: 600;
  letter-spacing: .01em; line-height: 1.2; white-space: normal; overflow-wrap: anywhere;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--accent);
  box-shadow: inset 0 0 0 1px rgba(201, 164, 76, .18); }
nav.tabs.mon-tabs button:hover, :root[data-theme] nav.tabs.mon-tabs button:hover {
  background: var(--panel-2); color: var(--accent); border-color: var(--accent); }
/* The `:root[data-theme]` twins outrank the Classic / Willow theme rules that paint every active
   tab button's text white / accent (owner, 2026-09-30: "full yellow button with dull white text"). */
nav.tabs.mon-tabs button.active, nav.tabs.mon-tabs button[aria-current="page"],
:root[data-theme] nav.tabs.mon-tabs button.active, :root[data-theme] nav.tabs.mon-tabs button[aria-current="page"] {
  background: linear-gradient(var(--chrome-gold-1), var(--chrome-gold-2)); color: #1a1408;
  border-color: var(--chrome-gold-2); font-weight: 700; box-shadow: none; }
@media (min-width: 760px) {
  nav.tabs.mon-tabs button { flex: 0 1 auto; min-width: 9rem; padding-inline: 1rem; }
}
/* News feed row — Province News / Chronicle / Kingdom News (owner, 2026-09-30: "hard to read
   and the text is almost too long"): the Manage Spells look — panel tone with a gold outline at
   rest, the gold gradient when selected — three even columns of thumb-height buttons. Labels
   wrap at their space only ("Province" / "News"), never mid-word; the fluid size eases from
   16px to 13.6px on a 320px screen so each word still fits its column. Natural width from
   600px up. `#view [data-feed]` + !important already outranks
   the Classic / Willow active-tab text rules (see the Monarchy strip's theme trap above). */
nav.tabs.feed-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .55rem;
  margin-bottom: 1rem; padding-bottom: 0; border-bottom: 0; }
.feed-tabs button {
  display: grid; place-items: center; min-width: 0; min-height: 3rem; padding: .6rem .3rem;
  border-radius: .6rem; font-size: clamp(.85rem, 4.2vw, 1rem); font-weight: 600; letter-spacing: 0;
  line-height: 1.2; text-align: center; white-space: normal; overflow-wrap: normal; hyphens: manual;
}
#view [data-feed] {
  background: var(--panel-2) !important; border: 1px solid var(--accent) !important;
  color: var(--text) !important; box-shadow: inset 0 0 0 1px rgba(201, 164, 76, .18) !important;
}
#view [data-feed]:hover { color: var(--accent) !important; }
#view [data-feed].active,
#view [data-feed][aria-current="page"] {
  background: linear-gradient(var(--chrome-gold-1), var(--chrome-gold-2)) !important;
  border-color: var(--chrome-gold-2) !important; color: #1a1408 !important; font-weight: 700;
  box-shadow: none !important;
}
@media (min-width: 600px) {
  nav.tabs.feed-tabs { display: flex; flex-wrap: wrap; }
  .feed-tabs button { flex: 0 1 auto; min-width: 9rem; padding: .6rem 1rem; }
}

/* the world directory: warring kingdoms carry the same faint wash */
#view tr.kd-warrow > td { background: var(--war-wash); }

/* ==================== Pass 76: the intel grid + site ====================
   The shared 6-tab sortable grid (kingdom page panel + the standalone site).
   Age pills keep the legacy literal traffic-light colors — semantic on every
   theme; structural colors ride the theme vars. */
.intel-host .intel-scroll, .intel-section .intel-scroll { overflow-x: auto; }
table.intel-grid {
  width: 100%; border-collapse: collapse; font-size: 12px; white-space: nowrap;
}
table.intel-grid th {
  position: sticky; top: 0; cursor: pointer; text-align: right;
  padding: 3px 7px; color: var(--muted); border-bottom: 1px solid var(--border);
  background: var(--panel);
}
table.intel-grid th:nth-child(2), table.intel-grid td:nth-child(2) { text-align: left; }
table.intel-grid td { text-align: right; padding: 2px 7px;
  border-bottom: 1px solid var(--panel-2); }
table.intel-grid tr:hover td { background: rgba(120, 140, 160, 0.08); }
table.intel-grid th.sorted-asc::after { content: " \25B4"; }
table.intel-grid th.sorted-desc::after { content: " \25BE"; }
table.intel-grid td.dim, .intel-grid .dim { color: rgba(255, 255, 255, 0.35); }
.ig-slot { color: var(--muted); font-size: 0.85em; }
.intel-tabs { display: flex; gap: 2px; flex-wrap: wrap; margin: 4px 0 8px; }
.intel-tabs a {
  padding: 3px 10px; font-size: 12px; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--muted); text-decoration: none;
  border-bottom: 2px solid transparent;
}
.intel-tabs a.active { color: var(--accent); border-bottom-color: var(--accent); }
.intel-meta { color: var(--muted); font-size: 0.85em; margin: 4px 0; }
.intel-age {
  display: inline-block; min-width: 30px; text-align: center; font-size: 11px;
  border-radius: 9px; padding: 0 6px;
}
.intel-age.fresh { background: #1b5e20; color: #c8e6c9; }
.intel-age.ok { background: #7a5c00; color: #ffe082; }
.intel-age.stale { background: #7f1d1d; color: #ffcdd2; }
.intel-age.none { background: #2c2c2c; color: rgba(255, 255, 255, 0.35); }

/* Pass 79.a — the Age Manager's document form (the council's input boxes) */
.docform { max-height: 32rem; overflow-y: auto; border: 1px solid var(--border);
           padding: .5rem .75rem; border-radius: 4px; }
.docform .docrow { display: flex; align-items: center; gap: .5rem; margin: .15rem 0; }
.docform .dockey { flex: 0 0 16rem; color: var(--muted); overflow-wrap: anywhere; }
.docform input[type="text"], .docform input[type="number"] {
  flex: 1 1 8rem; min-width: 6rem; }
.docform .dockill { flex: 0 0 auto; }
.docform details { margin: .3rem 0 .3rem .5rem; }
.docform details > summary { cursor: pointer; }
.docform .docentry > summary b { color: var(--th-fg, inherit); }

/* Pass 79.b — the council's race & personality tables */
.edpanel h4 { margin: .8rem 0 .3rem; }
.edstats td, .edstats th { padding: .1rem .5rem; text-align: left; }
.edstats input { width: 6rem; }
/* Mods, war doctrines and the elite-NW row each get their own line, keys aligned in
   a fixed column (like the generic docform), instead of wrapping inline. */
.edpanel .docrow { display: flex; align-items: center; gap: .5rem; margin: .15rem 0; }
/* Wide enough that the common mod keys sit on one line; the few 40+ char keys still
   wrap rather than overflow. */
.edpanel .dockey { flex: 0 0 20rem; color: var(--muted); overflow-wrap: anywhere; }
.edpanel .docrow input[type="number"] { width: 8rem; }
.edpanel .dockill { flex: 0 0 auto; }
/* The player-facing "shown as" preview next to each mod value. */
.edpanel .modshown { flex: 1 1 10rem; color: var(--muted); font-style: italic;
  overflow-wrap: anywhere; }
.edpanel .modshown::before { content: "→ "; opacity: .7; }
/* The elite's dynamically-calculated NW factor, shown beside the stored field. */
.edpanel .elitecalc { flex: 1 1 auto; color: var(--muted); font-style: italic; }
/* "What it does" line under the unique-ability and war-doctrine dropdowns. */
.edpanel .edeffect { color: var(--muted); font-style: italic; margin: .15rem 0 .5rem;
  max-width: 60ch; }
/* A race/personality not offered this age can't be edited — greyed and unclickable. */
.edpanel button.quiet:disabled { opacity: .4; cursor: not-allowed; }
.edgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
          gap: .1rem .75rem; max-height: 18rem; overflow-y: auto;
          border: 1px solid var(--border); padding: .4rem .6rem; border-radius: 4px; }
.edchip { display: inline-block; border: 1px solid var(--border); border-radius: 3px;
          padding: 0 .35rem; margin: .1rem 0; }

/* DM-style mail (2026-09-02): conversation list + bubble thread + composer. Theme
   colors only (panel/border/accent) so every skin re-dresses it. */
.dm { display: grid; grid-template-columns: minmax(200px, 270px) 1fr; gap: 0.8rem; margin-bottom: 0.6rem; }
.dm-list, .dm-thread {
  background: var(--panel); border: 1px solid var(--border); border-radius: 4px;
  display: flex; flex-direction: column; min-height: 60vh; overflow: hidden;
}
.dm-list-head { display: flex; gap: 0.4rem; flex-wrap: wrap; padding: 0.6rem; border-bottom: 1px solid var(--border); }
.dm-rows { flex: 1; overflow-y: auto; }
.dm-row {
  display: grid; grid-template-columns: 1fr auto; column-gap: 0.4rem;
  padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--border);
  color: var(--text); text-decoration: none; position: relative;
}
.dm-row:hover { background: var(--panel-2); }
.dm-row.active { background: var(--panel-2); box-shadow: inset 3px 0 0 var(--accent); }
.dm-row-name { font-weight: bold; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dm-row.unread .dm-row-name { color: var(--accent); }
.dm-row-tick { font-size: 0.8em; align-self: center; }
.dm-row-snip { grid-column: 1 / -1; font-size: 0.9em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dm-badge {
  position: absolute; right: 0.6rem; bottom: 0.5rem;
  background: var(--accent); color: var(--bg); border-radius: 1em; padding: 0 0.5em;
  font-size: 0.78em; font-weight: bold;
}
.dm-row.unread .dm-row-snip { padding-right: 2em; }
.dm-foot { margin: 0; padding: 0.5rem 0.7rem; border-top: 1px solid var(--border); font-size: 0.9em; }
.dm-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--border); }
.dm-head h2 { margin: 0; flex: 1; font-size: 1.05rem; color: var(--accent); }
.dm-msgs { flex: 1; overflow-y: auto; max-height: 62vh; padding: 0.9rem; display: flex; flex-direction: column; gap: 0.6rem; }
.dm-msg { max-width: 78%; display: flex; flex-direction: column; }
.dm-msg.in { align-self: flex-start; }
.dm-msg.out { align-self: flex-end; align-items: flex-end; }
.dm-subj { font-size: 0.85em; color: var(--muted); margin-bottom: 0.15rem; }
.dm-bubble {
  padding: 0.5rem 0.8rem; border-radius: 12px; white-space: pre-wrap; overflow-wrap: anywhere;
  background: var(--panel-2); border: 1px solid var(--border);
}
.dm-msg.in .dm-bubble { border-bottom-left-radius: 3px; }
.dm-msg.out .dm-bubble {
  border-color: var(--accent); border-bottom-right-radius: 3px;
  background: color-mix(in srgb, var(--accent) 18%, var(--panel-2));
}
.dm-meta { font-size: 0.8em; margin-top: 0.15rem; }
.dm-compose { display: flex; gap: 0.5rem; align-items: flex-end; padding: 0.6rem 0.9rem; border-top: 1px solid var(--border); }
.dm-compose textarea { flex: 1; resize: vertical; min-height: 2.6em; font: inherit; }
.dm-foot a, .dm-meta a { color: var(--link); }
.dm-pick { padding: 0.9rem; }
.dm-empty { padding: 2rem 1rem; text-align: center; margin: 0; }
.dm-back { display: none; }
@media (max-width: 760px) {
  .dm { grid-template-columns: 1fr; }
  .dm.dm-open .dm-list { display: none; }
  .dm:not(.dm-open) .dm-thread { display: none; }
  .dm-back { display: inline-block; }
  .dm-msg { max-width: 92%; }
}
.live-feed-summary { margin: .45rem 0; }
.live-feed-summary > b { display: block; color: var(--gold, #ffd13d); }
.live-feed-summary > span { display: block; margin-top: .15rem; }

.live-feed-controls {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));  /* ReWoL · ReGenesis / Tournament · Clear, in a 640px lobby */
  gap: .65rem;
  margin: 1rem 0;
}
.live-feed-controls button { width: 100%; min-height: 2.55rem; padding: .45rem .7rem; white-space: nowrap; }
@media (max-width: 480px) { .live-feed-controls { grid-template-columns: 1fr; } }

/* ——— Mobile UX fixes (≤760px / ≤480px / ≤640px) ——— */

/* C1: Resource bar scroll hint — fade mask shows more columns exist on mobile.
   The table only scrolls below its min-width (640px), so only fade there; on
   wider-but-narrow screens the full table already fits without wasting space. */
@media (max-width: 640px) {
  #resourcebar {
    mask-image: linear-gradient(to right, black 75%, transparent);
    -webkit-mask-image: linear-gradient(to right, black 75%, transparent);
  }
}

/* C4: Feedlog — stack date above message on small screens */
@media (max-width: 480px) {
  .feedlog .entry {
    grid-template-columns: 1fr;
    gap: 0.1rem;
  }
  .feedlog .entry .t { text-align: left; }
}

/* The primary Tournament command tabs remain fully visible and centered on phones;
   Season Changes sub-tabs retain their independent wrapping behavior below. */
@media (max-width: 760px) {
  .tournament-admin-primary-tabs { padding: .65rem; }
  .tournament-admin-primary-tabs button { min-height: 3.3rem; font-size: .88rem; }
}

/* m1: Mod direction badges — abbreviate on mobile. The badge has a light,
   theme-invariant fill with a dark text color (defined at .tm-mod-direction);
   the mobile overlay keeps that same dark text so it matches on every theme. */
@media (max-width: 760px) {
  .tm-mod-direction.bonus-up, .tm-mod-direction.bonus-down {
    position: relative;
    color: transparent;
    min-width: 3.5rem;
    text-align: center;
  }
  .tm-mod-direction.bonus-up::after { content: "\2191 Bonus"; position: absolute; inset: 0; color: #155d34; }
  .tm-mod-direction.bonus-down::after { content: "\2193 Bonus"; position: absolute; inset: 0; color: #79430c; }
}

/* m2: Delete button — 44px touch target (Apple HIG) */
.tm-delete-mod {
  min-width: 2.75rem;
  min-height: 2.75rem;
  font-size: 1.1rem;
  line-height: 1;
}

/* Medium #6: The Race Mods / Personality Mods builder tables are the only admin
   tables without an overflow wrapper. Let them scroll within their builder block
   (keeping columns and inputs at usable widths) instead of squeezing on phones. */
.tm-race-mods table.admin-table,
.tm-race-mods .tm-quirk-builder table.admin-table {
  display: block;
  overflow-x: auto;
  width: 100%;
}
.tm-race-mods table.admin-table input[type="number"] {
  min-width: 5rem;
}

/* Fix 4: Mobile touch targets — on phones the default button/input/link sizing is
   too short for thumbs. Bump vertical padding to reach ~44px, scoped to ≤900px so
   desktop and base-game layouts are untouched. */
@media (max-width: 900px) {
  input, select, button, .btn, a.btnlink { padding-top: 0.55rem; padding-bottom: 0.55rem; }
  nav.tabs button { padding-top: 0.55rem; padding-bottom: 0.55rem; }
  /* Tournament coordinator action rows that sit inside form fields / report boxes
     and aren't covered by the generic bump above — guarantee a thumb-height tap
     box without widening the row (min-height, not padding, so layout holds). */
  [data-load-roster],
  .tm-enrollment div button {
    min-height: 2.5rem;
  }
  .tournament-form .tm-rule-toggle { min-height: 3.25rem; }
  .tm-completed-match > summary,
  .tm-roster-kingdom > summary { min-height: 3rem; }
}

/* Fix 5: Intel grid — the fixed 12px face and thin 3px tab padding are hard to read
   and tap on phones. Enlarge scoped to ≤900px so the desktop grid stays dense. */
@media (max-width: 900px) {
  table.intel-grid { font-size: 13px; }
  table.intel-grid th { padding-top: 5px; padding-bottom: 5px; }
  table.intel-grid td { padding-top: 5px; padding-bottom: 5px; }
  .intel-tabs a { padding: 6px 10px; font-size: 13px; }
  .intel-age { font-size: 12px; min-width: 34px; padding: 1px 8px; }
}

/* Medium #8: Pill/bubble touch targets — the 6px vertical padding is too short
   for thumbs. Bump to ~44px on phones (scoped; desktop stays compact). */
@media (max-width: 900px) {
  .pill, .bubble { padding-top: 10px; padding-bottom: 10px; }
}

/* m6: Docform — stack key above input on narrow screens */
@media (max-width: 640px) {
  .docform .docrow { flex-direction: column; align-items: stretch; }
  .docform .dockey { flex: 0 0 auto; }
  .docform input[type="text"], .docform input[type="number"] { min-width: 0; }
}

/* #13: Card layout for the mods/quirk/spell/military builder tables on narrow
   screens. Scoped to .tournament-admin-shell (Tournament admin only — the wider
   IP/account/debug admin tables are untouched) and only to cells carrying a
   data-label, so each row becomes a card with its column heading above the value.
   Raised from ≤480 to ≤760 so phones AND tablets get the stacked cards instead of
   side-scrolling multi-column tables (mobile-first, no horizontal scroll). The
   mobile number/checkbox/delete inputs keep working: same DOM, new layout. */
@media (max-width: 760px) {
  .tournament-admin-shell table.admin-table { display: block; overflow-x: hidden; }
  .tournament-admin-shell table.admin-table thead, .tournament-admin-shell table.admin-table tr:has(th) { display: none; }
  .tournament-admin-shell table.admin-table tbody { display: block; }
  .tournament-admin-shell table.admin-table tr { display: block; border: 1px solid var(--border); border-radius: 0.4rem; padding: 0.45rem 0.6rem; margin: 0 0 0.6rem; background: var(--panel-2); }
  .tournament-admin-shell table.admin-table td {
    display: flex; justify-content: space-between; align-items: center; gap: 0.75rem;
    border: none; border-bottom: 1px dashed var(--border); padding: 0.35rem 0;
    min-width: 0;
  }
  .tournament-admin-shell table.admin-table td:last-child { border-bottom: none; }
  .tournament-admin-shell table.admin-table td::before {
    content: attr(data-label); flex: 0 0 35%; color: var(--muted); font-size: 0.78rem;
    font-weight: bold; text-transform: uppercase; letter-spacing: 0.04em;
  }
  .tournament-admin-shell table.admin-table td > span, .tournament-admin-shell table.admin-table td > b,
  .tournament-admin-shell table.admin-table td > small { min-width: 0; overflow-wrap: anywhere; }
  /* C: let the value/number and its unit fit a narrow card instead of forcing width */
  .tournament-admin-shell table.admin-table input[type="number"],
  .tournament-admin-shell table.admin-table select { flex: 1 1 auto; min-width: 0; }
  .tournament-admin-shell table.admin-table td[data-label="Value"] { justify-content: flex-start; }
  .tournament-admin-shell table.admin-table td[data-label="Remove"] { justify-content: flex-end; }
  .tournament-admin-shell table.admin-table td[data-label="Remove"]::before { display: none; }
}

/* Race configuration is deeply nested inside an expanded builder. Keep those cards
   within the phone viewport and give every editable military value a real column. */
@media (max-width: 760px) {
  #tournament-race-mods .tm-race-builder,
  #tournament-race-mods .tm-race-builder > div,
  #tournament-race-mods .tm-race-military { min-width: 0; max-width: 100%; }
  #tournament-race-mods .tm-race-military { padding: .75rem; overflow: hidden; }
  #tournament-race-mods .tm-race-military .muted { overflow-wrap: anywhere; }
  #tournament-race-mods .tm-race-military table.admin-table { width: 100%; min-width: 0; overflow: visible; }
  #tournament-race-mods .tm-race-military table.admin-table td {
    display: grid;
    grid-template-columns: minmax(5.5rem, 35%) minmax(0, 1fr);
    align-items: center;
    gap: .65rem;
  }
  #tournament-race-mods .tm-race-military table.admin-table td::before { min-width: 0; }
  #tournament-race-mods .tm-race-military table.admin-table input[type="number"] {
    width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box;
  }
  #tournament-race-mods .tm-race-military table.admin-table td[data-label="Unit"] > b { grid-column: 2; }
}

/* Personality and spell configuration reuse the same data, controls, and save path
   as desktop. These phone-only rules only keep their nested editor cards readable. */
@media (max-width: 760px) {
  #tournament-personality-mods .tm-race-builder,
  #tournament-personality-mods .tm-race-builder > div,
  #tournament-personality-mods .tm-quirk-builder,
  #tournament-spells,
  #tournament-spells .tm-race-mods { min-width: 0; max-width: 100%; }
  #tournament-personality-mods .tm-race-builder .muted,
  #tournament-spells .muted { overflow-wrap: anywhere; }
  #tournament-personality-mods table.admin-table,
  #tournament-spells table.admin-table { width: 100%; min-width: 0; overflow: visible; }
  #tournament-personality-mods table.admin-table td {
    display: grid;
    grid-template-columns: minmax(5.5rem, 35%) minmax(0, 1fr);
    align-items: center;
    gap: .65rem;
  }
  #tournament-personality-mods table.admin-table td::before { min-width: 0; }
  #tournament-personality-mods table.admin-table input[type="number"] {
    width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box;
  }
  #tournament-personality-mods .tm-builder-add { display: grid; grid-template-columns: 1fr; }
  #tournament-personality-mods .tm-builder-add select,
  #tournament-personality-mods .tm-builder-add button { width: 100%; min-width: 0; }
  #tournament-spells .tm-spells-disclosure { min-width: 0; overflow: hidden; }
  #tournament-spells table.admin-table td { min-width: 0; overflow-wrap: anywhere; }
}

/* Saved Personality spells must be visible before the long modifier editor, not
   buried after it. This changes presentation only; the existing controls save them. */
#tournament-personality-mods .tm-racial-spells { display: grid; gap: .65rem; margin: .75rem 0; padding: .8rem; border: 1px solid #806117; border-radius: .6rem; background: #201c10; }
#tournament-personality-mods .tm-racial-spells h4, #tournament-personality-mods .tm-saved-spell-count b { margin: 0; color: #f0c867; }
#tournament-personality-mods .tm-racial-spells p { margin: 0; }
#tournament-personality-mods .tm-racial-spells p:not(.muted):not(.tm-saved-spell-count) { display: flex; flex-wrap: wrap; gap: .4rem; }
#tournament-personality-mods .tm-racial-spells p:not(.muted):not(.tm-saved-spell-count) button { margin: 0; }
@media (max-width: 760px) {
  #tournament-personality-mods .tm-racial-spells > select,
  #tournament-personality-mods .tm-racial-spells > button { width: 100%; min-width: 0; }
}
.tm-change-sets { display: grid; gap: .75rem; }
.tm-change-sets h3, .tm-change-set summary b { color: var(--accent); }
.tm-change-set { display: grid; gap: .7rem; padding: .9rem; border: 1px solid var(--border); border-radius: .55rem; background: var(--panel-2); }
.tm-change-set header { display: grid; gap: .2rem; text-align: center; }
.tm-change-set h4 { margin: 0; color: var(--accent); font-size: 1.1rem; }
.tm-change-set header span { color: var(--muted); font-weight: bold; letter-spacing: .06em; }
.tm-change-set > p { margin: 0; text-align: center; color: var(--muted); }

.tm-change-set-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem; }
.tm-change-set-actions button:disabled { opacity: .5; cursor: not-allowed; }
.tm-change-set p { overflow-wrap: anywhere; }

/* B: The Season Changes sub-tab bar reuses .tournament-admin-tabs, which scrolls
   sideways on narrow screens. That's undesirable for the four Season Changes
   sub-tabs (long labels would need side-swiping to reach "Spells"). Let THIS bar
   wrap onto multiple rows instead, with no fade mask, so every sub-tab is visible
   and tappable on phones. */
@media (max-width: 760px) {
  .tm-age-tabs {
    flex-wrap: wrap;
    overflow-x: visible;
    mask-image: none;
    -webkit-mask-image: none;
  }
  .tm-age-tabs button { flex: 1 1 auto; }
}

/* Tournament player shell: a phone-first Throne composition over the existing
   authoritative action pages. Normal ReGenesis chrome keeps its established rail. */
.tournament-throne { padding: .75rem; padding-bottom: 4.75rem; }
.tournament-match-bar { display: grid; grid-template-columns: 1fr auto; gap: .3rem .75rem; padding: .65rem .75rem; border: 1px solid var(--chrome-border); border-radius: .6rem; background: var(--chrome-bg); color: var(--chrome-muted); }
.tournament-match-bar b { display: block; color: var(--chrome-gold-1); }
.tournament-match-bar > div:last-child { text-align: right; }
.tournament-age span, .tournament-phase span { display: block; color: var(--pa); font-size: .72rem; font-weight: bold; letter-spacing: .04em; text-transform: uppercase; }
.tournament-age b { font-size: 1rem; }
.tournament-phase { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem; padding-top: .45rem; border-top: 1px solid var(--chrome-border); text-align: left !important; }
.tournament-phase b { display: inline; }
.tournament-phase small { color: var(--chrome-muted); }
.tournament-phase strong { width: 100%; color: var(--good); font-size: .8rem; }
.tournament-resources, .tournament-readiness { display: grid; margin-top: .7rem; border: 1px solid var(--chrome-border); border-radius: .6rem; overflow: hidden; background: var(--chrome-bg); }
.tournament-resources { grid-template-columns: 1.25fr 1fr 1fr .9fr .95fr; }
.tournament-readiness { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.tournament-resources > div { min-width: 0; padding: .5rem .2rem; border-right: 1px solid var(--chrome-border); text-align: center; }
.tournament-resources > div:last-child { border: 0; }
.tournament-resources span, .tournament-action-grid span { display: block; color: var(--chrome-muted); font-size: .67rem; font-weight: bold; letter-spacing: .04em; text-transform: uppercase; }
.tournament-resources span { font-size: .6rem; letter-spacing: .02em; white-space: nowrap; }
.tournament-resources b { display: block; overflow: hidden; color: var(--chrome-gold-1); text-overflow: ellipsis; white-space: nowrap; }
.tournament-identity { padding: .9rem 0 .4rem; }
.tournament-identity h2 { margin: 0; color: #f0c867; }
.tournament-identity h2 span { color: var(--pa); font-size: .82em; }
.tournament-identity p { margin: .2rem 0; color: var(--muted); }
.tournament-identity p b { color: #f4f6ff; }
.tournament-role { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; margin-top: .55rem !important; }
.tournament-role b { color: #f0c867; }
.tournament-role button { border: 1px solid #6577a5; border-radius: 999px; padding: .3rem .6rem; color: #eef1ff; background: #293858; text-transform: none; }
.tournament-identity-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .65rem; }
.tournament-spellbook-button, .tournament-royal-button { border: 1px solid #6577a5; border-radius: .5rem; padding: .5rem .75rem; color: #dce8ff; background: #1d3152; font-weight: bold; text-transform: none; }
.tournament-royal-button { border-color: #806117; color: #f0c867; background: #2a220d; }
.tournament-armies-intel { display: grid; gap: .55rem; margin-bottom: .75rem; border-color: #52658e; background: #121b30; }
.tournament-armies-intel h3 { margin: 0; color: #f0c867; }
.tournament-armies-intel p { margin: 0; }
.tournament-army-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.tournament-army-cards article { display: grid; gap: .2rem; min-width: 0; padding: .65rem; border: 1px solid #6079ad; border-radius: .5rem; background: #172845; }
.tournament-army-cards article b { color: #f7f9ff; }
.tournament-army-cards article span { color: #c9d4e9; font-size: .85rem; }
.tournament-army-cards strong { color: #f0c867; }
@media (max-width: 600px) { .tournament-army-cards { grid-template-columns: 1fr; } }
.tournament-royal { border-color: var(--accent); }
.tournament-royal { border-color: #806117; background: linear-gradient(120deg, #2a220d, #141814); }
.tournament-royal h3 { color: #f0c867; }
.tournament-royal .row { display: flex; flex-wrap: wrap; gap: .65rem; margin-top: .9rem; }
.tournament-royal .row button { min-height: 2.75rem; padding-right: 1rem; padding-left: 1rem; }
.tournament-royal-dialog { position: fixed; z-index: 2900; inset: 0; display: grid; place-items: center; padding: 1rem; }
.tournament-royal-dialog-card { position: relative; display: grid; gap: .8rem; width: min(100%, 35rem); padding: 1rem; border: 1px solid #6879a5; border-radius: .85rem; color: #d7def0; background: #192541; box-shadow: 0 1rem 3rem #000b; }
.tournament-royal-dialog-card header { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin: -1rem -1rem 0; padding: 1rem; border-bottom: 1px solid #485a83; }
.tournament-royal-dialog-card h2 { margin: 0; color: #f0c867; }
.tournament-royal-dialog-card label { display: grid; gap: .4rem; color: #eef1ff; }
.tournament-royal-dialog-card textarea { width: 100%; box-sizing: border-box; border: 1px solid #6577a5; border-radius: .45rem; padding: .55rem; color: #f4f6ff; background: #0d1322; font: inherit; resize: vertical; }
.tournament-royal-dialog-card .row { display: flex; flex-wrap: wrap; gap: .65rem; margin-top: .2rem; }
.tournament-royal-dialog-card .row button { min-height: 2.75rem; padding-right: 1rem; padding-left: 1rem; }

.tournament-sheet-card * { min-width: 0; overflow-wrap: anywhere; }

.tournament-spellbook-page { display: grid; gap: 1rem; width: min(100%, 800px); margin: 0 auto; padding: 0 1rem 5rem; }
.tournament-spellbook-page > header { display: grid; gap: .25rem; margin: 0 -1rem; padding: 1rem; border-bottom: 1px solid #485a83; }
.tournament-spellbook-page header span { color: #82b7ff; font-size: .7rem; font-weight: bold; text-transform: uppercase; }
.tournament-spellbook-page header p { margin: 0; color: #d0d9ef; }
.tournament-spell-resources { margin: 0; color: #b7c5df; font-size: 1rem; }
.tournament-spell-resources b { color: #f7f9ff; font-size: 1.12em; }
.tournament-spellbook-page h2, .tournament-spellbook-page h3 { margin: 0; color: #e1bd71; }
.tournament-spellbook-page h2 { font-size: clamp(1.45rem, 5vw, 2rem); }
.tournament-spell-section { display: grid; gap: .55rem; padding: .8rem; border: 1px solid #52658e; border-radius: .65rem; background: #121b30; }
.tournament-spell-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45rem; }
.tournament-spell-tabs button { min-height: 2.9rem; border: 1px solid #6079ad !important; border-radius: .5rem; padding: .45rem .25rem; color: #d5deef !important; background: #172845 !important; font-size: .82rem; text-transform: none; box-shadow: none; }
.tournament-spell-tabs button.active { border: 2px solid #d6ae4d !important; padding: calc(.45rem - 1px) calc(.25rem - 1px); color: #f3d58d !important; background: #24210f !important; }
.tournament-spell-group { display: grid; gap: .45rem; }
.tournament-spell-group + .tournament-spell-group { padding-top: .7rem; border-top: 1px solid #354568; }
.tournament-spell-group h3 { margin: 0; color: #dfbd72; font-size: 1rem; }
.tournament-active-spells { display: grid; gap: .55rem; }
.tournament-spell-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.tournament-active-spells { padding: 0; border: 0; border-radius: 0; background: transparent; }
.tournament-active-spells > div, .tournament-spell-actions button { display: flex; justify-content: space-between; gap: .75rem; width: 100%; border: 1px solid #6479a8 !important; border-radius: .5rem; padding: .75rem; color: #eef1ff !important; background: #162541 !important; text-align: left; text-transform: none; box-shadow: none; }
.tournament-active-spells > div { margin-bottom: .55rem; border: 1px solid #6079ad !important; border-radius: .55rem; padding: .75rem .85rem; color: #f7f9ff; background: #1b2c4b; }
.tournament-active-spells > div:last-child { margin-bottom: 0; }
.tournament-active-spells > div b { color: #f7f9ff; }
.tournament-active-spells > div span { color: #d4deef; }
.tournament-active-spell-labels { display: none; }
.tournament-active-spells > div { display: grid; gap: .45rem; }
.tournament-active-spell-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; }
.tournament-active-spells > div p { margin: 0; color: #c9d4e9; line-height: 1.4; }
@media (min-width: 680px) { .tournament-active-spell-labels { display: grid; grid-template-columns: minmax(9rem, 1fr) 8rem minmax(0, 2fr); gap: .75rem; padding: 0 .75rem; color: #aebbd4; font-size: .75rem; font-weight: bold; text-transform: uppercase; } .tournament-active-spells > div { grid-template-columns: minmax(9rem, 1fr) 8rem minmax(0, 2fr); align-items: start; } .tournament-active-spell-head { display: contents; } .tournament-active-spells > div p { grid-column: 3; grid-row: 1; } }
.tournament-active-spells > div.beneficial { border: 3px solid #4cbb72 !important; padding: calc(.75rem - 2px) calc(.85rem - 2px); }
.tournament-active-spells > div.destructive { border: 3px solid #d95b5b !important; padding: calc(.75rem - 2px) calc(.85rem - 2px); }
.tournament-spell-actions button { display: grid; align-content: center; min-height: 4.8rem; }
.tournament-spell-actions button:hover { border-color: #91a9dc !important; background: #1d3152 !important; }
.tournament-spell-actions button:active { border-color: #e1bd71 !important; background: #243a61 !important; }
.tournament-spell-actions button.active { border: 3px solid #d6ae4d !important; padding: calc(.75rem - 2px); background: #24210f !important; }
.tournament-spell-actions button:disabled { border-color: #3c4965 !important; color: #8793aa !important; background: #101727 !important; cursor: not-allowed; opacity: .72; }
.tournament-spell-actions button .good { color: #1a1408 !important; font-weight: 800; }
/* The pre-rename spell name beside the new one (Graymantle · Fog) in the Province Spellbook — a
   quiet pill, never bold, wraps under the name on narrow buttons (owner, 2026-09-28). */
.tournament-spell-actions button:disabled .old-name { color: #8793aa; border-color: #3c4965; }
.tournament-spell-actions button.active .old-name { color: #d9c88f; border-color: #8a7433; }
.tournament-advisor { display: grid; gap: 1rem; padding: 1rem 1rem 5rem; }
.tournament-advisor header { padding-bottom: .8rem; border-bottom: 1px solid #485a83; }.tournament-advisor header span{color:#82b7ff;font:700 .72rem system-ui;text-transform:uppercase}.tournament-advisor h2,.tournament-advisor h3{margin:.25rem 0;color:#dfbd72}.tournament-advisor header p{margin:0;color:#c9d4e9}.tournament-advisor section{display:grid;gap:.55rem}.advisor-item{display:grid;gap:.25rem;width:100%;border:2px solid #6079ad !important;border-radius:.6rem;padding:.8rem;color:#f7f9ff !important;background:#172845 !important;text-align:left;text-transform:none;box-shadow:none}.advisor-item b{color:#f7f9ff}.advisor-item span{color:#b9c7df}.advisor-item.critical{border-color:#d95b5b !important}.advisor-item.warning{border-color:#d6ae4d !important}.advisor-item.good,.advisor-item.stable{border-color:#4cbb72 !important}.advisor-item.info{border-color:#6079ad !important}.advisor-clear{padding:.75rem;border:1px solid #4cbb72;border-radius:.55rem;color:#d8f5de;background:#12281b}.advisor-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.55rem}.advisor-grid div{padding:.7rem;border:1px solid #354568;border-radius:.55rem;background:#121b30}.advisor-grid span{display:block;color:#aebbd4;font-size:.8rem}.advisor-grid b{color:#f7f9ff}.advisor-links{display:grid;gap:.55rem}.advisor-links button{border:1px solid #6079ad;border-radius:.55rem;padding:.7rem;color:#eef1ff;background:#1b2c4b;text-align:left;text-transform:none}

.kingdom-readiness{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.45rem}.kingdom-readiness span{border:1px solid #6079ad;border-radius:999px;padding:.18rem .42rem;font-size:.72rem}.kingdom-readiness .good{border-color:#4cbb72;color:#d8f5de}.kingdom-readiness .warning{border-color:#d6ae4d;color:#f3d58d}
.effect-chip{display:inline-block;margin:.15rem .25rem .15rem 0;border:2px solid #6079ad;border-radius:.45rem;padding:.28rem .42rem;color:#f7f9ff}.effect-chip.beneficial{border-color:#4cbb72}.effect-chip.destructive{border-color:#d95b5b}

.tournament-active-spells span, .tournament-spell-actions span { color: #aebbd4; text-align: right; }
.battle-intel-board { display: grid; gap: .75rem; width: min(100%, 800px); margin: 0 auto; padding: .75rem .75rem 5rem; }
.battle-intel-board > header { display: grid; gap: .25rem; padding-bottom: .8rem; border-bottom: 1px solid #485a83; }
.battle-intel-board > header span { color: #82b7ff; font: 700 .72rem system-ui; text-transform: uppercase; }
.battle-intel-board h2, .battle-intel-board h3, .battle-intel-board h4 { margin: 0; color: #dfbd72; }
.battle-intel-board > header p, .battle-intel-panel > p { margin: 0; color: #c9d4e9; }
.battle-intel-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem; }
.battle-intel-tabs button { min-height: 2.9rem; border: 1px solid #6079ad !important; border-radius: .55rem; padding: .5rem .35rem; color: #d5deef !important; background: #172845 !important; font-size: .84rem; text-transform: none; box-shadow: none; }
.battle-intel-tabs button.active { border: 2px solid #d6ae4d !important; padding: calc(.5rem - 1px) calc(.35rem - 1px); color: #f3d58d !important; background: #24210f !important; }
.battle-intel-panel { display: grid; gap: .65rem; padding: .75rem; border: 1px solid #52658e; border-radius: .7rem; background: #121b30; }
.battle-intel-ledger { display: grid; grid-template-columns: 1fr; gap: .55rem; }
.battle-intel-ledger-row { display: grid; gap: .3rem; min-width: 0; padding: .65rem; border: 1px solid #6079ad; border-radius: .55rem; background: #172845; }
.battle-intel-ledger-row p { margin: 0; color: #d5deef; }
.battle-intel-reports { display: flex; flex-wrap: wrap; gap: .3rem; }
.battle-intel-reports .chip { margin: 0; font-size: .74rem; }
.battle-advisor-list { display: grid; gap: .5rem; }
.battle-advisor-list p { margin: 0; padding: .7rem; border: 1px solid #6079ad; border-radius: .55rem; background: #172845; }
.battle-friendly-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .45rem; }
.battle-friendly-summary > div { min-width: 0; padding: .6rem; border: 1px solid #52658e; border-radius: .5rem; background: #172845; }
.battle-friendly-summary span { display: block; overflow: hidden; color: #aebbd4; font-size: .74rem; text-overflow: ellipsis; white-space: nowrap; }
.battle-friendly-summary b { color: #f7f9ff; font-size: .9rem; }
.battle-friendly-roster { display: grid; gap: .6rem; }
.battle-friendly-card { display: grid; gap: .55rem; padding: .75rem; border: 1px solid #6079ad; border-radius: .6rem; background: #172845; }
.battle-friendly-card summary { display: grid; gap: .15rem; cursor: pointer; color: #f7f9ff; }
.battle-friendly-card summary span { color: #c5d0e4; font-size: .84rem; }
.battle-province-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem; }
.battle-province-stats section { display: grid; gap: .18rem; min-width: 0; padding: .55rem; border: 1px solid #354568; border-radius: .45rem; background: #121b30; }
.battle-province-stats section > b { color: #dfbd72; }
.battle-province-stats span { color: #c9d4e9; font-size: .8rem; }
.battle-province-stats strong { color: #f7f9ff; }
.battle-army-list { display: grid; gap: .28rem; margin: 0; padding: 0; list-style: none; }
.battle-army-list li { color: #c9d4e9; font-size: .8rem; line-height: 1.35; }
.battle-friendly-effects { display: flex; flex-wrap: wrap; gap: .3rem; }
.battle-live-tables { display: grid; gap: .6rem; padding: .65rem; border: 1px solid #354568; border-radius: .55rem; background: #101827; }
.battle-live-tables summary { cursor: pointer; color: #dfbd72; font-weight: bold; }
@media (min-width: 760px) { .battle-intel-tabs { grid-template-columns: repeat(4, minmax(0, 1fr)); } .battle-intel-ledger { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .battle-friendly-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); } .battle-province-stats { grid-template-columns: 1fr; } }
@media (max-width: 420px) { .tournament-spellbook-page { padding-inline: .75rem; } .tournament-spellbook-page > header { margin-inline: -.75rem; } .tournament-spell-actions button { min-height: 4.6rem; padding: .65rem; font-size: .88rem; } }
.tournament-section-heading { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; margin: 1rem 0 .5rem; }
.tournament-section-heading h3 { margin: 0; color: #f0c867; }
.tournament-section-heading small { color: var(--muted); }
.tournament-action-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.tournament-action-grid button { min-height: 8.5rem; border: 1px solid #354568; border-radius: .65rem; padding: .7rem; color: #d8dfef; background: #121b30 !important; text-align: left; text-transform: none; box-shadow: none; }
.tournament-action-grid button:hover { border-color: #6579a8; background: #18243d !important; }
.tournament-action-grid button:first-child { border-color: #435885; }
.tournament-action-grid b { display: block; margin: .25rem 0; color: #f0c867; font-size: 1rem; }
.tournament-action-grid small { color: #aebbd4; }
.tournament-readiness { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tournament-readiness > div { padding: .55rem .65rem; border-right: 1px solid var(--chrome-border); border-bottom: 1px solid var(--chrome-border); }
.tournament-readiness > div:nth-child(even) { border-right: 0; }
.tournament-readiness span { display: block; color: var(--muted); font-size: .8rem; }
.tournament-readiness b { color: var(--text); }
.tournament-activity { margin-top: .45rem; border: 1px solid #354568; border-radius: .65rem; overflow: hidden; background: #121b30; }
.tournament-activity > div { display: grid; grid-template-columns: 4.5rem minmax(0, 1fr); gap: .65rem; padding: .75rem; border-bottom: 1px solid #354568; }
.tournament-activity > div:last-child { border-bottom: 0; }
.tournament-activity time { color: #82b7ff; font-size: .78rem; font-weight: bold; white-space: nowrap; }
.tournament-activity p { margin: 0; color: #d8dfef; }
.tournament-war-board { display: grid; gap: .65rem; padding: .75rem; border: 1px solid #52658e; border-radius: .65rem; background: #121b30; }
.war-board-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45rem; }
.war-board-summary div { padding: .6rem; border: 1px solid #354568; border-radius: .5rem; background: #172845; }
.war-board-summary span, .tournament-war-board li span { display: block; color: #b9c7df; font-size: .8rem; }
.war-board-summary b { color: #f7f9ff; }
.tournament-war-board h4 { margin: .1rem 0; color: #dfbd72; }
.tournament-war-board ul { display: grid; gap: .4rem; margin: 0; padding: 0; list-style: none; }
.tournament-war-board li { padding: .6rem; border-left: 3px solid #6079ad; background: #172845; }
.tournament-war-board li.good { border-left-color: #4cbb72; }
.tournament-admin-tools-card { width: min(44rem, calc(100vw - 1.5rem)); max-height: min(48rem, calc(100vh - 1.5rem)); overflow: auto; }
.tournament-admin-tools-card header > div { display: grid; gap: .1rem; }
.tournament-admin-tools-card header span { color: #82b7ff; font-size: .75rem; font-weight: bold; letter-spacing: .06em; text-transform: uppercase; }
.tournament-admin-tools-card header h2 { margin: 0; color: #dfbd72; }
.tournament-admin-tool-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.tournament-admin-tool-grid button { display: grid; gap: .35rem; min-height: 5.2rem; padding: .8rem; border: 1px solid #6079ad !important; border-radius: .6rem; color: #f7f9ff !important; background: #172845 !important; text-align: left; text-transform: none; box-shadow: none; }
.tournament-admin-tool-grid button:hover { border-color: #d6ae4d !important; background: #243a61 !important; }
.tournament-admin-tool-grid button b { padding: 0 !important; border: 0 !important; border-radius: 0 !important; color: #f3d58d !important; background: transparent !important; font-size: .95rem; line-height: 1.15; }
.tournament-admin-tool-grid button span { color: #d5deef !important; font-size: .8rem; font-weight: 600; line-height: 1.35; }
@media (max-width: 420px) { .tournament-admin-tool-grid { grid-template-columns: 1fr; } .tournament-admin-tool-grid button { min-height: 4.4rem; } }
.admin-world-clock { display: grid; gap: .8rem; }
.admin-world-clock h2 { margin: 0; }
.admin-world-clock-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .55rem; }
.admin-world-clock-grid div { padding: .7rem; border: 1px solid #52658e; border-radius: .55rem; background: #121b30; }
.admin-world-clock-grid span { display: block; color: #aebbd4; font-size: .78rem; }
.admin-world-clock-grid b { color: #f7f9ff; font-size: .9rem; overflow-wrap: anywhere; }
@media (max-width: 600px) { .admin-world-clock-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.prefreeze-tabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .65rem; margin: .9rem 0 1rem; }
.prefreeze-tabs button { min-height: 3.2rem; border: 1px solid #6079ad !important; border-radius: .55rem; padding: .65rem .4rem; color: #d5deef !important; background: #172845 !important; text-transform: none; box-shadow: none; }
.prefreeze-tabs button.active { border: 2px solid #d6ae4d !important; padding: calc(.65rem - 1px) calc(.4rem - 1px); color: #f3d58d !important; background: #24210f !important; }
.tournament-manage-shell { display: grid; gap: .85rem; margin-bottom: 1.1rem; }
.tournament-manage-shell + nav.tabs { gap: .55rem; margin-top: .9rem; }
.tournament-manage-shell + nav.tabs button { min-height: 2.9rem; padding: .6rem .85rem; border-radius: .5rem .5rem 0 0; }
@media (max-width: 360px) { .prefreeze-tabs { gap: .45rem; } .prefreeze-tabs button { padding-inline: .2rem; font-size: .85rem; } }
@media (max-width: 600px) {
  .tournament-paid-manage-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; }
  .tournament-paid-manage-tabs button { min-height: 3.5rem; padding: .65rem .55rem; font-size: .9rem; line-height: 1.2; }
}
.training-mobile-list, .scientist-mobile-list, .science-invest-mobile-list { display: none; }
@media (max-width: 600px) {
  .training-desktop-table, .scientist-desktop-table, .science-invest-desktop-table { display: none; }
  .training-mobile-list, .scientist-mobile-list, .science-invest-mobile-list { display: grid; gap: .7rem; }
  .training-mobile-card, .scientist-mobile-card, .science-invest-mobile-card { display: grid; gap: .65rem; padding: .85rem; border: 1px solid #52658e; border-radius: .65rem; background: #121b30; }
  .training-mobile-card header { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; color: #f0c867; }
  .training-mobile-card > div { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem; color: #b9c7df; }
  .training-mobile-card > div span { display: grid; gap: .12rem; }
  .training-mobile-card label, .scientist-mobile-card label { display: grid; gap: .3rem; color: #d5deef; }
  .training-mobile-card label > span { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .55rem; }
.training-mobile-card input, .training-mobile-card button, .scientist-mobile-card select { min-height: 2.75rem; }
  .scientist-mobile-card > div { display: flex; flex-wrap: wrap; gap: .35rem .7rem; color: #b9c7df; font-size: .88rem; }
  .science-invest-mobile-list > section { display: grid; gap: .55rem; }
  .science-invest-mobile-list h4 { margin: 0; padding-bottom: .45rem; border-bottom: 1px solid #675117; color: #f0c867; }
  .science-invest-mobile-list h4 span { color: #b9c7df; font-size: .82rem; font-weight: normal; }
  .science-invest-mobile-card header { display: flex; justify-content: space-between; gap: .7rem; color: #f0c867; }
  .science-invest-mobile-card header span { color: #b9c7df; font-size: .85rem; }
  .science-invest-mobile-card p { margin: 0; color: #d5deef; line-height: 1.45; }
  .science-invest-mobile-card label { display: grid; gap: .3rem; color: #d5deef; }
  .science-invest-mobile-card label > span { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .55rem; }
.science-invest-mobile-card input, .science-invest-mobile-card button { min-height: 2.75rem; }
}
.patreon-panel { display: grid; place-items: center; text-align: center; }
.patreon-link { display: flex; flex-direction: column; align-items: center; gap: .35rem; width: max-content; max-width: 100%; color: #ff7a6b; font-size: .72rem; font-weight: 700; text-decoration: none; }
.patreon-link img { width: min(7rem, 42vw); height: min(7rem, 42vw); border: 1px solid #ff7a6b; border-radius: .6rem; object-fit: cover; }
.patreon-link:hover, .patreon-link:focus-visible { color: #ffb0a8; text-decoration: underline; }
.tournament-mobile-tabs { position: fixed; z-index: 2600; right: 0; bottom: 0; left: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); width: min(100%, 800px); max-width: 100%; margin: auto; overflow: hidden; padding: .3rem .25rem max(.3rem, env(safe-area-inset-bottom)); border: 1px solid var(--chrome-border); border-bottom: 0; border-radius: .75rem .75rem 0 0; background: var(--chrome-bg); }
.tournament-mobile-tabs button { display: grid; place-items: center; gap: .1rem; min-width: 0; min-height: 3.2rem; padding: .3rem .15rem; overflow: hidden; border: 1px solid transparent; border-radius: .5rem; color: #c5d0e4 !important; background: transparent !important; font-size: .75rem; font-weight: 700; text-align: center; text-transform: none; text-shadow: none; box-shadow: none; }
.tournament-mobile-tabs .tournament-tab-icon { display: block; color: #82b7ff !important; font-size: 1rem; line-height: 1; }
.tournament-mobile-tabs .tournament-tab-label { display: block; max-width: 100%; color: inherit !important; font: inherit; font-size: clamp(10px, 3vw, .75rem); line-height: 1.1; }
/* The realm labels carry no badge, so they may clip with an ellipsis as a last resort; the
   Tournament bar's Advisor label holds the alert count badge and must never be cut. */
.realm-mobile-tabs .tournament-tab-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tournament-mobile-tabs .tournament-tab-label i { display:inline-block; min-width:1rem; border-radius:999px; padding:.02rem .22rem; color:#1a1020; background:#d9b7ff; font-style:normal; }
.tournament-mobile-tabs button.active { color: #f0c867 !important; border-color: #675117; background: #31270f !important; }
.tournament-mobile-tabs button.active .tournament-tab-icon { color: #f0c867 !important; }
.tournament-sheet { position: fixed; z-index: 2800; inset: 0; display: grid; place-items: center; padding: 1rem; }
.tournament-sheet-backdrop { position: absolute; inset: 0; background: #000b !important; }
.tournament-sheet-card { position: relative; display: grid; gap: .7rem; width: min(100%, 34rem); max-height: min(82vh, 44rem); overflow-x: hidden; overflow-y: auto; padding: 1rem; border: 1px solid #6879a5; border-radius: .85rem; color: #d7def0; background: #192541; box-shadow: 0 1rem 3rem #000b; }
.tournament-sheet-card header { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.tournament-sheet-card h2 { margin: 0; color: #f0c867; }
.tournament-sheet-card section { display: grid; gap: .45rem; }

.tournament-sheet-label { margin: 0; color: #82b7ff; font-size: .72rem; font-weight: bold; letter-spacing: .06em; text-transform: uppercase; }
.tournament-sheet-label b, .tournament-sheet-card button b { display: inline-block; min-width: 1.2rem; border-radius: 999px; padding: .05rem .32rem; color: #1a1020; background: #d9b7ff; text-align: center; }
.tournament-staff-callout { padding: .85rem; border: 1px solid #7057a4; border-radius: .75rem; background: #171329; }
.tournament-staff-callout p { margin: 0; color: #c2c9df; }
.tournament-more-actions { display: flex; flex-wrap: wrap; gap: .45rem; }
.tournament-sheet-card .tournament-more-actions button { width: auto; border: 1px solid #6577a5; border-radius: .55rem; padding: .55rem .8rem; color: #eef1ff !important; background: #293858 !important; font-weight: bold; text-transform: none; box-shadow: none; }
.tournament-sheet-card .tournament-more-actions button:hover { border-color: #aab9e1; background: #34466d !important; }
.realm-more-theme { display: flex; align-items: center; gap: .45rem; min-height: 2.75rem; padding: .45rem .65rem; border: 1px solid #6577a5; border-radius: .55rem; color: #eef1ff; background: #293858; font-weight: bold; }
.realm-more-theme select { min-width: 0; padding: .35rem .45rem; border-color: #6577a5; color: #eef1ff; background: #172845; font: inherit; }
.tournament-council-tools-card > header span { color: #82b7ff; font-size: .72rem; font-weight: bold; letter-spacing: .06em; text-transform: uppercase; }
.tournament-council-tools-card > p { margin: 0; }
.tournament-council-tools-actions { display: grid; gap: .65rem; }
.tournament-council-tools-actions button { min-height: 3.25rem; border: 2px solid #f0c867; border-radius: .6rem; color: #171208 !important; background: linear-gradient(135deg, #ffd84b, #d99d00) !important; font-weight: 800; text-align: left; text-transform: none; box-shadow: 0 .35rem .9rem rgba(0, 0, 0, .35); }
.tournament-council-tools-actions button:disabled { border-color: #53617e; color: #8490a9 !important; background: #101727 !important; cursor: not-allowed; box-shadow: none; opacity: 1; }
@media (max-width: 520px) { .tournament-sheet { align-items: end; padding: .5rem; } .tournament-sheet-card { max-height: 88vh; border-radius: .85rem .85rem 0 0; } }
@media (max-width: 520px) { .realm-more-sheet { align-items: start; } }
/* Tournament mode owns its frame. The normal game's rail, staff strip, resource bar,
   and advisor tabs must never surround the phone-first Tournament surface. */
body.tournament-ui > #topbar, body.tournament-ui > #adminnav, body.tournament-ui > #mainnav,
body.tournament-ui > footer { display: none !important; }
body.tournament-ui { padding: 0; background: #070a11; }
body.tournament-ui main, body.game.tournament-ui main { width: 100%; max-width: none; margin: 0; }
body.tournament-ui #tournament-frame { width: min(100%, 800px); min-height: 100vh; margin: 0 auto; border-right: 1px solid var(--chrome-border); border-left: 1px solid var(--chrome-border); background: #0b1020; }
body.tournament-ui #view { min-height: 100vh; padding-bottom: 4.75rem; }
/* Tournament controls and data must remain operable without sideways scrolling. */
body.tournament-ui button, body.tournament-ui input, body.tournament-ui select {
  min-height: 2.75rem;
  box-sizing: border-box;
}
body.tournament-ui #view { overflow-x: clip; }
body.tournament-ui #view table { max-width: 100%; }
.tournament-spell-actions button,
.tournament-spell-actions button b,
.tournament-spell-actions button span { min-width: 0; overflow-wrap: anywhere; }
.tournament-sheet-card header button, .tournament-sheet-card .tournament-more-actions button {
  min-height: 2.75rem;
}

@media (max-width: 600px) {
  body.tournament-ui #view table { width: 100%; table-layout: fixed; }
  body.tournament-ui #view th, body.tournament-ui #view td { overflow-wrap: anywhere; }
  body.tournament-ui #view table input, body.tournament-ui #view table select {
    width: 100% !important;
    min-width: 0 !important;
  }
  .tournament-spell-actions { grid-template-columns: 1fr; }
  .tournament-spell-actions button { min-height: 4.25rem; }
  .tournament-spell-actions button span { text-align: left; }
}
@media (min-width: 761px) { .tournament-action-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Normal realms reuse the actual Tournament tab component at every viewport size. */
body.realm-bottom-tabs.game { padding-bottom: 4.75rem; }
/* Every normal-realm tab uses the shared status header, never the legacy chrome bars. */
body.realm-bottom-tabs #ticker, body.realm-bottom-tabs #resourcebar { display: none; }
/* Keep the realm game surface bounded like Tournament while the site header stays outside it. */
@media (min-width: 901px) {
  body.realm-bottom-tabs main {
    width: min(100%, 800px); max-width: none; min-height: calc(100vh - 4.9rem); margin: 0 auto;
    padding: .75rem .75rem 5.5rem; border: 1px solid var(--chrome-border); border-top: 0;
    background: #0b1020;
  }
}
.realm-mobile-tabs { display: grid !important; }
/* Phone-first guard (2026-09-29): the realm page never scrolls sideways. Content is built to
   fit, and this clip keeps a stray wide element from widening the page if one slips through. */
@media (max-width: 900px) { body.realm-bottom-tabs main { overflow-x: clip; } }
/* The by-race rankings table (Race + five metric columns) cannot fit a phone: under 760px each
   race becomes a card whose links read the metric name instead of "view". */
.rank-race-table .rank-metric { display: none; }
@media (max-width: 760px) {
  .rank-race-table, .rank-race-table tbody { display: block; width: 100%; }
  .rank-race-table .rank-race-head { display: none; }
  .rank-race-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; padding: .45rem .1rem; border-bottom: 1px solid var(--border); }
  .rank-race-table td { display: block; min-width: 0; padding: 0; border: 0; }
  .rank-race-table td.rank-race-name { flex: 1 0 100%; font-weight: bold; }
  .rank-race-table td a { display: inline-block; min-height: 2.75rem; line-height: 2.75rem; padding: 0 .65rem; border: 1px solid var(--border); border-radius: 999px; text-decoration: none; }
  .rank-race-table .rank-view { display: none; }
  .rank-race-table .rank-metric { display: inline; }
}
/* The Monarchy stance catalog (four columns, long effect text) becomes one card per stance
   under 760px: name + the two timings side by side, the effects wrapped beneath. */
@media (max-width: 760px) {
  .stance-table, .stance-table tbody { display: block; width: 100%; }
  .stance-table .stance-head { display: none; }
  .stance-table tr { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .15rem .6rem; padding: .5rem .55rem; margin-bottom: .5rem; border: 1px solid var(--border); border-radius: .5rem; }
  .stance-table tr.me { border-color: var(--accent); }
  .stance-table td { display: grid; min-width: 0; gap: .1rem; padding: .15rem 0; border: 0; text-align: left; overflow-wrap: anywhere; }
  .stance-table td::before { content: attr(data-label); color: var(--muted); font-size: .7rem; font-weight: bold; letter-spacing: .03em; text-transform: uppercase; }
  .stance-table td[data-label="Stance"] { grid-column: 1 / -1; font-weight: bold; }
  .stance-table td[data-label="Stance"]::before { display: none; }
  .stance-table td.stance-effects { grid-column: 1 / -1; }
}
/* Phone-first: a form row (select + button + note) wraps instead of squeezing its items
   into 375px; its buttons keep the 2.75rem touch height; the stance form's note takes a line. */
@media (max-width: 760px) {
  form.stack .row { flex-wrap: wrap; }
  form.stack .row > button { min-height: 2.75rem; }
  #f-stance .row > .muted { flex: 1 0 100%; }
}
/* The normal realm frame has no legacy rail; navigation lives in its bottom tabs and More sheet. */
@media (max-width: 900px) { body.realm-manage-ui main, body.realm-kingdom-ui main, body.realm-monarchy-ui main { margin-top: 0; } }
/* Phone-first (2026-09-29, player reports): the five tabs must always fit the screen, 320px up.
   Plain `1fr` tracks cannot shrink below a label's width, and the site-wide button padding
   (1rem a side) pushed the row past 375px — "More" fell off the edge and the bar scrolled.
   Every track is minmax(0, …), the buttons drop the wide padding, the label scales with the
   viewport (never under 10px) and clips with an ellipsis as a last resort, never overflowing. */
/* A bar with more than four picks (tablet and up, owner 2026-10-08) sizes its own columns. */
@media (max-width: 900px) { .realm-mobile-tabs:not(.realm-tabs-many) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.18fr) minmax(0, .91fr) minmax(0, .91fr) !important; } }
/* D: Never let an unbroken builder/spell/tag string escape the column on mobile —
   wrap anywhere. */
@media (max-width: 760px) {
  .tournament-admin-shell .tm-race-mods summary,
  .tournament-admin-shell .tm-race-military h4,
  .tournament-admin-shell .tm-builder-add select,
  .tournament-admin-shell .tournament-form .tm-rule-toggle b,
  .tournament-admin-shell .tournament-form .tm-rule-toggle small { overflow-wrap: anywhere; }
}

.rankings-archive-grid { align-items: start; }
.rankings-archive-age, .rankings-tournament-season { border-top: 1px solid var(--border); padding: .65rem 0; }
.rankings-archive-age summary, .rankings-tournament-season summary { color: var(--accent); cursor: pointer; font-weight: bold; }
.rankings-archive-age summary span, .rankings-tournament-season summary span { color: var(--muted); font-size: .9rem; font-weight: normal; }
.rankings-archive-age p { margin: .65rem 0 0; }
.rankings-tournament-match { border-bottom: 1px solid var(--border); padding: .65rem 0; }
.rankings-tournament-match b, .rankings-tournament-match span,
.rankings-tournament-match em { display: block; }
.rankings-tournament-match span { color: var(--muted); }
.rankings-tournament-match em { color: var(--good); font-size: .9rem; font-style: normal; }

/* --- Spells currently cast: cards on phones (ticket-0046, 2026-10-03) ---
   The three-column table ran past a phone's edge (the description column squeezed to a word
   per line and pushed off-screen). Below tablet width each spell is a card: name + duration
   pill on top, description beneath — the same fold the Legacy layout uses (ui-legacy.css).
   From 760px it is the striped table again (the restore repeats the base table/zebra values,
   since #view's zebra rule outranks plain class selectors) — except in the Mystics side
   column (.arc-side, 2026-10-04), which is narrow at every width and keeps the cards. */
#view table.active-spells { display: block; width: 100%; margin-top: .5rem; }
#view table.active-spells tbody { display: block; }
#view table.active-spells tr:first-child { display: none; }
#view table.active-spells tr { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: .2rem .6rem; align-items: start; padding: .6rem .7rem; margin-bottom: .45rem;
  border: 1px solid var(--border); border-radius: .55rem; background: var(--panel-2); }
#view table.active-spells td { display: block; min-width: 0; padding: 0; border: 0; text-align: left; }
#view table.active-spells td:first-child { font-weight: bold; }
#view table.active-spells td.num { grid-column: 2; grid-row: 1; justify-self: end;
  padding: .15rem .6rem; border: 1px solid var(--border); border-radius: 999px; font-size: .8rem;
  white-space: nowrap; }
#view table.active-spells td.muted { grid-column: 1 / -1; font-size: .9rem; line-height: 1.4;
  overflow-wrap: anywhere; }
@media (min-width: 760px) {
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells { display: table; }
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells tbody { display: table-row-group; }
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells tr { display: table-row; padding: 0;
    margin: 0; border: 0; border-radius: 0; background: none; }
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells tr:nth-child(odd) { background: var(--row-alt); }
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells td { display: table-cell;
    padding: 0.25rem 0.7rem 0.25rem 0; font-size: inherit; line-height: inherit; }
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells td:first-child { font-weight: normal; }
  :root:not([data-ui="legacy"]) #view .panel:not(.arc-side) table.active-spells td.num { text-align: right; border: 0;
    border-radius: 0; white-space: normal; }
}

/* --- Mystics: spells first, status beside them (owner, 2026-10-04) ---
   Players wanted the spells higher up on tablet and PC: the Mystic Circle header, the four
   stats and "Spells currently cast" filled the top of the page. Phones keep the stack
   (header, stats, cast list, spells). From tablet width the header is one slim row (tabs
   left, the Mystic Circle fold right) and the page splits: spells in the wide left column,
   stats + spells currently cast in a narrow right column, where each cast spell stays a
   card (the table restore above skips .arc-side). Sorcery keeps its single header panel. */
.arc-main { min-width: 0; }
@media (min-width: 760px) {
  .arc-layout { display: grid; grid-template-columns: minmax(0, 1fr) 13rem; gap: 0 .8rem;
    align-items: start; }
  .arc-layout > .arc-head { grid-column: 1 / -1; display: flex; flex-wrap: wrap;
    align-items: center; justify-content: space-between; gap: .3rem 1rem; }
  .arc-layout > .arc-head { padding-top: .7rem; padding-bottom: .7rem; }
  .arc-layout > .arc-head nav.tabs { flex: 0 1 24rem; margin: 0; }
  .arc-layout > .arc-head .mystic-intro summary h2 { margin: 0; font-size: 1rem; }
  .arc-layout > .arc-head .mystic-intro[open] { flex-basis: 100%; }
  .arc-layout > .arc-head .mystic-intro p { margin: .4rem 0 0; }
  .arc-layout > .arc-side { grid-column: 2; grid-row: 2; }
  .arc-layout > .arc-main { grid-column: 1; grid-row: 2; }
  .arc-layout > .arc-main > #arc-body > .panel:first-child h3:first-child { margin-top: 0; }
  .arc-side .statgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .4rem .8rem; }
  .arc-side #arc-active { margin-top: .7rem; padding-top: .6rem; border-top: 1px solid var(--border); }
}
@media (min-width: 900px) {
  .arc-layout { grid-template-columns: minmax(0, 1fr) 15rem; }
}
@media (min-width: 1100px) {
  .arc-layout { grid-template-columns: minmax(0, 1fr) 19rem; }
}

/* --- Spell outcomes float at the top of the screen (ticket-0047, 2026-10-03) ---
   On the Mystics / Sorcery page the cast result landed above the spell list, so a player
   casting from further down never saw it before it faded. Under the default layout the
   result window (and a red cast error) now floats at the top of the viewport wherever the
   page is scrolled; a report that stays (intel) scrolls inside it and has a Close button.
   The Legacy layout floats it at the foot instead (ui-legacy.css). */
:root:not([data-ui="legacy"]) #arc-result .result-shell,
:root:not([data-ui="legacy"]) #arc-result .cast-error {
  position: fixed; top: .75rem; left: .75rem; right: .75rem; z-index: 2650; margin: 0;
  max-height: 55vh; overflow: auto; overscroll-behavior: contain;
  box-shadow: 0 .6rem 1.6rem rgba(0, 0, 0, .65);
}
:root:not([data-ui="legacy"]) #arc-result .cast-error {
  padding: .7rem .9rem; border: 1px solid var(--danger); border-radius: .6rem;
  background: var(--panel-2);
}
/* the ✕ on a report or a pinned window (receipt opened) — any page, default layout */
.result-shell .result-close { position: sticky; top: 0; float: right; z-index: 1; width: 2.75rem;
  height: 2.75rem; margin: 0 0 .25rem .5rem; padding: 0; border: 1px solid var(--border);
  border-radius: 50%; background: var(--panel); color: var(--text); font-size: 1rem; line-height: 1; }
/* Bubble's yellow button rule outranks the plain one above — keep the ✕ a round dark chip */
:root[data-theme="bubble"] .result-shell button.result-close:not(.chip) {
  border-radius: 50%; background: var(--panel); color: var(--text); border-color: var(--border); }
@media (min-width: 760px) {
  :root:not([data-ui="legacy"]) #arc-result .result-shell,
  :root:not([data-ui="legacy"]) #arc-result .cast-error {
    left: auto; right: 1.25rem; top: 1.25rem; width: min(34rem, calc(100vw - 2.5rem));
  }
}

/* --- Admin province page (owner, 2026-10-04): the editor's figures as read-only cards —
   one column on a phone, two from tablet width, three on a desktop. --- */
.apv-cards { display: grid; gap: .6rem; grid-template-columns: minmax(0, 1fr); }
.apv-actions { flex-wrap: wrap; }
@media (min-width: 760px) { .apv-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .apv-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* --- Admin Server: 24-hour host-metric graphs (owner, 2026-10-05) ---
   Small multiples, one measure each on a fixed 0–100% scale: one column on a phone, two from
   tablet width. Every theme is dark, so the series uses the dark-surface blue (validated >= 3:1
   on all four panel colours); text stays in the theme's own ink, the grid recessive. */
.host-graphs { --hg-series: #3987e5; display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr);
  margin-top: 1rem; }
.host-graph { margin: 0; min-width: 0; }
.host-graph figcaption { font-size: .9rem; margin-bottom: .25rem; }
.host-graph-plot { position: relative; width: 100%; }
.host-graph svg { display: block; touch-action: pan-y; }
.hg-grid { stroke: var(--border); stroke-width: 1; }
.hg-axis { fill: var(--muted); font-size: 11px; }
.hg-line { fill: none; stroke: var(--hg-series); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.hg-area { fill: var(--hg-series); opacity: .1; }
.hg-dot { fill: var(--hg-series); stroke: var(--panel); stroke-width: 2; }
.hg-cross { stroke: var(--muted); stroke-width: 1; }
.hg-hit { fill: transparent; cursor: crosshair; }
.hg-tip { position: absolute; top: -.25rem; padding: .2rem .5rem; border: 1px solid var(--border);
  border-radius: .4rem; background: var(--panel-2); color: var(--text); font-size: .8rem;
  white-space: nowrap; pointer-events: none; }
.host-graph-table { margin-top: .8rem; }
@media (min-width: 760px) { .host-graphs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* players-online hour-of-day bars (owner, 2026-10-05): the same series blue, 4px-rounded tops */
.og-bar { fill: var(--hg-series, #3987e5); }
.og-bar.og-on { fill: #6fa8ee; }

/* --- Age Manager: change draft for the running age (owner, 2026-10-05) --- */
.live-draft { margin: .6rem 0 1rem; padding: .8rem; border: 1px solid var(--accent); border-radius: .6rem; }
.live-changes { list-style: none; margin: .5rem 0; padding: 0; display: grid; gap: .4rem; }
.live-changes li { display: grid; grid-template-columns: 1.6rem minmax(0, 1fr); gap: .4rem;
  padding: .45rem .6rem; border: 1px solid var(--border); border-radius: .5rem;
  overflow-wrap: anywhere; }
.live-changes li.lc-refused, .live-changes li.lc-not_here { border-color: var(--danger); }

/* Worship page (phase 2, 2026-10-11) — phone first: one column of god cards, two from 760px.
   The devotion bar shows the climb to Exalted with a tick mark at each tier. */
.worship-bar { position: relative; height: .9rem; margin: .6rem 0 .8rem; border-radius: 999px;
  background: color-mix(in srgb, var(--muted) 25%, transparent); overflow: hidden; }
.worship-bar span { position: absolute; inset: 0 auto 0 0; background: var(--accent); border-radius: 999px; }
.worship-bar i { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--panel, #000); opacity: .8; }
.worship-gods { display: grid; grid-template-columns: minmax(0, 1fr); gap: .8rem; }
.worship-god h3 { margin-top: 0; }
.worship-god.is-mine { border-color: var(--accent); }
.worship-god button { min-height: 2.75rem; width: 100%; }
.worship-god button + button { margin-top: 0.5rem; }   /* the monarch's Make patron */
.worship-patron button { min-height: 2.75rem; width: 100%; }
.worship-fx { margin: .3rem 0 .6rem; padding-left: 1.1rem; display: grid; gap: .2rem; }
.worship-note { margin: .2rem 0 .6rem; }
@media (min-width: 760px) {
  .worship-gods { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .worship-god button, .worship-patron button { width: auto; }
}

/* Pantheon tab (Worship phase 3): the tier table stays readable at phone width — it scrolls
   inside its own box (tbl-wrap) and the number boxes shrink to fit. */
.ed-tiers input[type=number] { width: 5.5rem; min-height: 2.75rem; font-size: 16px; }
