/* board.css — the pair board (the run page).
 *
 * Loaded AFTER /static/slink.css; redefines none of its tokens.
 * The page is zones — Now, then one per section of the board, then the log — each a real
 * heading with a rule and space between them. Every zone sits on the same three-track
 * grid: A's column, the spine, B's column — so a player's side reads straight down the
 * page and the bond between two mons is drawn where it is, between them. The log is a
 * column beside the zones from 1400px.
 *
 * Grew out of the Track A mockup (docs/ui_mockup_brief.md); the .mk- prefix stayed so the
 * brief's rationale still names the classes it talks about.
 */

/* Jersey 20 as the board's whole UI face, not only its figures (the face itself is
 * declared in slink.css beside --font-num). The overlays wear it too (slink.css
 * body.stream), checked at their catalogue sizes. */
/* ── Type scale ──────────────────────────────────────────────────────────
 * One scale for every Manager page, in rem, so a size never depends on how deep an
 * element sits. xs captions · sm secondary · md controls and body copy · base · lg
 * emphasis · h1 the page/run name. Figures wear --font-num at the same sizes. */
body.mgr { font-size: 16px; --fs-xs: .75rem; --fs-sm: .8125rem; --fs-md: .875rem; --fs-base: 1rem; --fs-lg: 1.125rem; --fs-h1: 1.3rem; }
/* The run's panels (Twitch, OBS, debug, patcher, calc) bring their own markup; they
 * share the scale and the face, and their controls never fall back to the browser's. */
body.mgr :is(.twitch-panel, .obs-panel, .debug-panel, .patcher-wrap) { font-family: var(--font-ui); font-size: var(--fs-md); line-height: 1.45; }
body.mgr :is(.twitch-panel, .obs-panel, .debug-panel, .patcher-wrap) :is(input, select, textarea, button, .btn) { font-family: inherit; font-size: var(--fs-md); }
body.mgr :is(.twitch-panel > h1, .obs-panel > h1, .debug-panel > h1, .patcher-head h1) { display: none; }   /* the run header names the page */
body.mgr :is(.twitch-panel, .obs-panel, .debug-panel) h2 { font-family: var(--font-ui); font-size: var(--fs-lg); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--c-txt); }
body.mgr :is(.twitch-panel, .obs-panel, .debug-panel, .patcher-wrap) :is(pre, code, .num) { font-family: var(--font-num); font-size: var(--fs-sm); }
body.board { --font-ui: 'Jersey 20', 'Pixelify Sans', monospace; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body.board img.mon-sprite, body.board .mk-spr img { image-rendering: pixelated; }

/* The board lives inside the dashboard shell (sidebar + main) rather than owning the page. */

#content > .phase-banner { margin-bottom: var(--space-4); }
.phase-banner.phase-stopped .phase-dot { background: var(--c-dim); box-shadow: none; }

/* Banners the old dashboard drew with inline styles. */
.game-over { background: var(--c-dead); color: #fff; text-align: center; padding: 1em .5em; font-size: 1.8rem; font-weight: bold; letter-spacing: .15em; border-radius: 8px; margin-bottom: 1em; }
/* One warning surface for anything the operator must act on. .mk-warn is the general
   per-player warning (usable as "mk-now-body mk-warn" in a Now card or standalone);
   the save banner and the bad connection states share it. */
.save-warn, .mk-warn, .mk-conn.wrong_game, .mk-conn.identity {
  border-left: 3px solid var(--c-dead); background: color-mix(in srgb, var(--c-dead) 12%, transparent);
  color: var(--c-txt); padding: var(--space-3); border-radius: 4px; }
.save-warn { margin-bottom: var(--space-3); }
/* Not an error, just not playing: waiting, connecting, stopped, disconnected. */
.mk-conn { border-left: 3px solid var(--c-edge-ui, var(--c-edge)); padding: var(--space-3); border-radius: 4px; }
.mk-conn.disconnected { border-left-color: var(--c-dim); }
/* Active rule clauses above the board. */
.lock-rules { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: var(--space-3); color: var(--c-dim); font-size: var(--fs-sm); }
.badge-lock { display: inline-flex; align-items: center; gap: 4px; padding: 1px var(--chip-pad-x); border: 1px solid var(--c-edge-ui, var(--c-edge)); color: var(--c-txt); white-space: nowrap; }

/* An uncertain native trade (--c-pend, same amber as a pending capture) escalates to a
 * conflict (--c-dead) once it's clear it needs a human — same shape as .identity-warn. */
.trade-problem { margin-bottom: var(--space-3); padding: var(--space-3); border-left: 3px solid var(--c-pend); background: color-mix(in srgb, var(--c-pend) 12%, transparent); color: var(--c-txt); }
.trade-problem.trade-problem-conflict { border-left-color: var(--c-dead); background: color-mix(in srgb, var(--c-dead) 12%, transparent); }
.trade-problem b { display: block; margin-bottom: .25em; }
.trade-problem-mons, .trade-problem-verdict, .trade-problem-text { display: block; font-size: var(--fs-sm); }
/* conn-watch.js: the board's poll stopped getting answers. Empty (connected), it takes no space. */
.mk-connlost { margin: var(--space-2) var(--space-5) 0; padding: var(--space-2) var(--space-3); border-left: 3px solid var(--c-pend); background: color-mix(in srgb, var(--c-pend) 12%, transparent); color: var(--c-txt); border-radius: 4px; font-size: var(--fs-sm); }
.mk-connlost:empty { display: none; }
body.conn-lost #content { opacity: .6; transition: opacity .3s; }
.trade-resolve { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }
.trade-resolve-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin: 0; padding: 0; border: 0; font-size: var(--fs-sm); }
.trade-resolve select { font: inherit; }
.trade-resolve-out:empty { display: none; }
.trade-last-note { margin-bottom: var(--space-3); font-size: var(--fs-sm); opacity: .75; }

:root {
  --density: 1;
  --mk-rail: calc(var(--scale-step) * 8.2);
  --mk-radius: 10px;
  --mk-pad: calc(var(--space-3) * var(--density));
  --mk-log: calc(var(--scale-step) * 14);
  /* Sprite sizes, both tracking --scale-step. funnotbun sprites are 64px native and Gen
   * 1's PokeAPI ones 56px, so the pair size sits at or above 1:1 on any real monitor and
   * upscales pixelated past that; the small size is for the Now cards' fight rows. */
  --mk-spr: clamp(60px, calc(var(--scale-step) * 3.1), 104px);
  --mk-spr-s: clamp(44px, calc(var(--scale-step) * 2.2), 72px);
  /* The spine: the bond column between the two players, same width in every zone so the
   * halves line up straight down the page. */
  --mk-spine: calc(var(--scale-step) * 6.2);
}
body.density-compact { --density: .7; }

/* ── Shell ─────────────────────────────────────────────────────────────── */

/* Text for screen readers only: what a glyph means, the "HP" before a fraction. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* ── Live announcements + toasts ──────────────────────────────────────────
 * dashboard.js diffs the board between polls and speaks a new link, a pair death or
 * the run ending here -- #mk-announcer is sr-only (the message), toasts are the same
 * three events shown briefly on screen. Both are outside #content, so the 2s poll
 * swap never touches them and never gets read aloud. */

.mk-announce-toggle { font-size: var(--fs-sm); padding: var(--space-1) var(--space-3); margin-left: auto; }
.mk-announce-toggle[aria-pressed="true"] { border-color: var(--c-brand); color: var(--c-brand); }
.mk-toast-host {
  position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 200;
  display: flex; flex-direction: column; gap: var(--space-2);
  max-width: min(340px, calc(100vw - var(--space-5))); pointer-events: none;
}
.mk-toast {
  padding: var(--space-3) var(--space-4); border-radius: var(--mk-radius); border: 1px solid var(--c-edge);
  background: color-mix(in srgb, var(--c-bg) 92%, var(--c-card)); color: var(--c-txt); font-size: var(--fs-md);
  box-shadow: 0 8px 24px rgba(0,0,0,.4); opacity: 0; transform: translateY(8px);
  transition: opacity .2s ease-out, transform .2s ease-out;
}
.mk-toast.show { opacity: 1; transform: translateY(0); }
.mk-toast.mk-toast-link { border-color: color-mix(in srgb, var(--c-alive) 45%, var(--c-edge)); }
.mk-toast.mk-toast-death, .mk-toast.mk-toast-over { border-color: color-mix(in srgb, var(--c-dead) 45%, var(--c-edge)); }
@media (prefers-reduced-motion: reduce) {
  .mk-toast { transition-duration: 0s; transform: none; }
}


/* ── Shell: the Manager's rail + main ──────────────────────────────────── */

.mk { display: grid; grid-template-columns: var(--mk-rail) minmax(0, 1fr); min-height: 100vh; align-items: start; }
body.mgr { margin: 0; }
/* The overlay gallery (stream_index.html) is the second column of whatever grid holds it. */
/* The overlay gallery under the Manager's header: the launcher is the page body. */
body.mgr .launcher { min-height: 0; max-height: calc(100vh - 57px); }

/* ── Rail ──────────────────────────────────────────────────────────────── */

.mk-rail {
  position: sticky; top: 0; box-sizing: border-box; height: 100vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--space-3) var(--space-2);
  background: color-mix(in srgb, var(--c-card) 60%, var(--c-bg)); border-right: 1px solid var(--c-edge);
}
.mk-rail-brand { display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-2) var(--space-2); color: var(--c-txt); text-decoration: none; }
.mk-rail-brand :is(svg, .mk-brand-ball) { width: calc(var(--scale-step) * 1.1); height: calc(var(--scale-step) * 1.1); flex: none; }
.mk-rail-brandtext { display: flex; flex-direction: column; line-height: 1.05; min-width: 0; }
.mk-rail-brandtext b { color: var(--c-brand); font-size: var(--fs-md); letter-spacing: .04em; }
.mk-rail-brandtext span { color: var(--c-dim); font-size: var(--fs-xs); }
.mk-rail-sep { border: none; border-top: 1px solid var(--c-sep); margin: var(--space-2); }
/* The runs scroll between the pinned top and the pinned destinations; the rail itself only
   scrolls when a window is too short to hold both pinned parts. */
.mk-rail-runs {
  flex: 1 1 auto; min-height: calc(var(--scale-step) * 5); overflow-y: auto; scrollbar-width: thin;
  display: flex; flex-direction: column; gap: var(--space-1);
  margin: 0 calc(var(--space-2) * -1); padding: 0 var(--space-2);
}
.mk-rail-fold { display: flex; flex-direction: column; gap: var(--space-1); }
.mk-rail-fold summary { list-style: none; color: var(--c-dim); }
.mk-rail-fold summary::-webkit-details-marker { display: none; }
.mk-rail-fold summary::before { content: '▸'; font-size: var(--fs-sm); width: 1.05em; text-align: center; flex: none; }
.mk-rail-fold[open] summary::before { content: '▾'; }
.mk-rail-fold .mk-rail-item:not(summary) { padding-left: calc(var(--space-3) + 14px); }
.mk-rail-item {
  text-decoration: none; box-sizing: border-box;
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  padding: var(--space-2); border: 1px solid transparent; border-radius: 8px;
  background: none; color: var(--c-txt); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer;
}
.mk-rail-item:hover { background: var(--c-card); }
.mk-rail-item.active { background: color-mix(in srgb, var(--c-brand) 16%, transparent); border-color: color-mix(in srgb, var(--c-brand) 45%, transparent); }
.mk-rail-item.new { color: var(--c-brand); border-style: dashed; border-color: color-mix(in srgb, var(--c-brand) 35%, transparent); }
.mk-rail-item svg { width: 1.05em; height: 1.05em; flex: none; }
.mk-rail-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.mk-rail-pin { font-size: var(--fs-xs); color: var(--c-gold); }
/* The run's game, as plain text under its name (owner: no new chips or badges). */
.mk-rail-game { display: block; font-size: var(--fs-xs); color: var(--c-dim); overflow: hidden; text-overflow: ellipsis; }
.mk-dot { width: .6em; height: .6em; border-radius: 50%; flex: none; background: var(--c-dim); }
.mk-dot.running  { background: var(--c-alive); box-shadow: 0 0 6px var(--c-alive); }
.mk-dot.archived { background: none; border: 1px solid var(--c-dim); }

/* The calc page loads Bootstrap and the calc's own theme, which style bare elements
 * (body font, links) for the whole document; the shell restates what it needs. */
body.calc-host .mk-rail, body.calc-host .mk-runhdr { font-family: var(--font-ui) !important; font-size: var(--scale-step) !important; line-height: 1.4; color: var(--c-txt); }
body.calc-host .mk-rail a, body.calc-host .mk-runhdr a { color: inherit !important; }
body.calc-host .mk-rail-item.new { color: var(--c-brand) !important; }
body.calc-host .mk-tab.active { color: var(--c-brand) !important; }
body.calc-host .mk-rail-brandtext b { color: var(--c-brand); }
html:has(> body.calc-host) { font-size: 16px !important; }   /* the calc's theme sets html to 14px; the scale is rem */
/* Inside the Manager the calc is one page of the run: the run header names it, so the
 * strip and the calc's own title go, and the calc's `monospace !important` gives way to
 * the UI face (Jersey has tabular figures, which is what a calc wants). */
body.calc-host .slink-header, body.calc-host .mk-page .title-text { display: none; }
body.calc-host .mk-page, body.calc-host .mk-page :is(input, select, button, textarea, table, label, .btn, code),
body.calc-host #slink-bridge-panel, body.calc-host #slink-bridge-panel * { font-family: var(--font-ui) !important; }
body.calc-host .mk-page { padding-top: var(--space-3); }

/* ── Run header: sticky, one line, tabs in the middle ──────────────────── */

.mk-main { min-width: 0; }
.mk-runhdr {
  position: sticky; top: 0; z-index: 10;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
  padding: var(--space-3) var(--space-5);
  background: color-mix(in srgb, var(--c-bg) 92%, var(--c-card)); border-bottom: 1px solid var(--c-edge);
  backdrop-filter: blur(6px);
}
.mk-runname { margin: 0; font-size: var(--fs-h1); }
.mk-pill { padding: 2px var(--chip-pad-x); font-size: var(--fs-xs); letter-spacing: .1em; text-transform: uppercase; border: 1px solid currentColor; }
.mk-pill.running  { color: var(--c-alive); }
.mk-pill.stopped  { color: var(--c-dim); }
.mk-pill.archived { color: var(--c-dim); opacity: .7; }
.mk-hdr-spacer { flex: 1 1 auto; }
/* the memorial page's own title, and the Twitch / OBS panels: the header already names them */
body.mgr #memorial-main > h1, body.mgr #memorial-main > .subtitle { display: none; }
body.mgr .twitch-panel, body.mgr .obs-panel { max-width: 1100px; }
.mk-rail-item.sub { padding-left: calc(var(--space-3) + 14px); font-size: var(--fs-md); }
.mk-rail-item.sub svg { width: 14px; height: 14px; }
.mk-meta { font-size: var(--fs-sm); color: var(--c-dim); font-variant-numeric: tabular-nums; }
.mk-meta b { color: var(--c-txt); font-weight: 400; }
.mk-meta code { color: var(--c-dim); }
.mk-tabs { display: flex; gap: var(--space-1); }
.mk-tab { padding: var(--space-1) max(var(--space-3), var(--chip-pad-x)); border: 1px solid transparent; background: none; color: var(--c-dim); font: inherit; font-size: var(--fs-md); cursor: pointer; }
.mk-tab:hover { color: var(--c-txt); }
.mk-tab.active { color: var(--c-brand); border-color: color-mix(in srgb, var(--c-brand) 45%, transparent); background: color-mix(in srgb, var(--c-brand) 12%, transparent); }

.mk-btn {
  display: inline-flex; align-items: center; gap: 5px; padding: var(--space-2) var(--space-3);
  /* --c-edge is the hairline divider everywhere; a control's border must reach 3:1 (WCAG
     1.4.11), so buttons and inputs take --c-edge-ui where a theme defines one. */
  border: 1px solid var(--c-edge-ui, var(--c-edge)); border-radius: 8px; background: var(--c-card); color: var(--c-txt);
  font: inherit; font-size: var(--fs-md); cursor: pointer;
}
.mk-btn:hover { border-color: var(--c-brand); }
.mk-btn.primary { border-color: var(--c-brand); color: var(--c-brand); }
.mk-btn.danger:hover { border-color: var(--c-dead); color: var(--c-dead); }
.mk-btn.active { background: color-mix(in srgb, var(--c-gold) 18%, transparent); border-color: var(--c-gold); color: var(--c-gold); }
.mk-btn:disabled { opacity: .4; cursor: default; }
.mk-pop-anchor { position: relative; }
.mk-pop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 20;
  display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-2); min-width: 240px;
  /* the theme's surfaces are translucent (OBS); the board must not read through a menu */
  border: 1px solid var(--c-edge); border-radius: 8px; background: var(--c-bg); backdrop-filter: blur(14px); box-shadow: 0 8px 28px rgba(0,0,0,.5);
}
.mk-pop .mk-cap { padding: 2px var(--space-2); }

/* ── Page + zones ──────────────────────────────────────────────────────── */

.mk-page { padding: var(--space-4) var(--space-5) var(--space-6); }
.mk-boardpage { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); align-items: start; }
@media (min-width: 1400px) {
  .mk-boardpage { grid-template-columns: minmax(0, 1fr) var(--mk-log); }
  .mk-logcol { position: sticky; top: calc(var(--scale-step) * 3.2); }
  .mk-logcol .mk-feed { max-height: calc(100vh - var(--scale-step) * 6); }
}
.mk-zones { display: flex; flex-direction: column; gap: var(--space-5); min-width: 0; }
.mk-zone { display: flex; flex-direction: column; gap: var(--space-3); }
.mk-cards3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr)); gap: var(--space-5); align-items: start; }

/* A real heading: the name, a rule that takes the rest of the line, a count. This is
 * what divides the areas; the gap above does the rest. */
.mk-h2 { display: flex; align-items: center; gap: var(--space-3); margin: 0; font-size: var(--fs-md); font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--c-txt); }
.mk-h2 i { flex: 1; height: 1px; background: var(--c-edge); }
.mk-h2 em { font-style: normal; font-weight: 400; letter-spacing: .04em; text-transform: none; color: var(--c-dim); font-size: var(--fs-base); }
.mk-h2.split { gap: var(--space-3); }
.mk-h2-side { display: inline-flex; align-items: center; gap: var(--space-2); letter-spacing: .04em; text-transform: none; font-weight: 500; }
.mk-h2-side.b { flex-direction: row-reverse; }
.mk-h2-mid { display: inline-flex; align-items: baseline; gap: var(--space-2); }
.zone-fallen .mk-h2 { color: var(--c-dim); }
.zone-pending .mk-h2-mid > span:first-child { color: var(--c-pend); }

.mk-card { border: 1px solid var(--c-edge); border-radius: var(--mk-radius); background: var(--c-card); overflow: hidden; }
.mk-card-body { padding: var(--mk-pad); }
.mk-cap { font-size: var(--fs-sm); letter-spacing: .06em; color: var(--c-dim); }
.mk-sub { font-size: var(--fs-md); color: var(--c-dim); }
.mk-sub.faint { opacity: .75; }
.mk-empty { padding: var(--space-5); text-align: center; color: var(--c-dim); font-size: var(--fs-md); }
.mk-side { font-size: var(--fs-lg); font-weight: 700; color: var(--c-brand); }
.mk-side.small { font-size: var(--fs-sm); margin-right: var(--space-2); }

/* ── NOW ───────────────────────────────────────────────────────────────
 * The two player cards, in the two player columns, equal height. The head names the
 * player and counts their badges; the body leads with where they are; a fight, when there
 * is one, is a tinted box with the foe and their own mon; wild encounters flow as chips so
 * they spend width, not height. */

.mk-now { display: grid; grid-template-columns: minmax(0, 1fr) var(--mk-spine) minmax(0, 1fr); gap: var(--space-3); align-items: stretch; }
.mk-nowcard { display: flex; flex-direction: column; border-left: 4px solid var(--c-dim); }
.mk-nowcard.online { border-left-color: var(--c-alive); }
.mk-now-head { display: flex; align-items: center; gap: var(--space-3); padding: var(--mk-pad) var(--mk-pad) var(--space-2); border-bottom: 1px solid var(--c-sep); }
.mk-now-head .mk-side { width: 1.6em; height: 1.6em; display: grid; place-items: center; border-radius: 6px; background: color-mix(in srgb, var(--c-brand) 18%, transparent); font-size: var(--fs-base); }
.mk-now-name { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; flex: 1; }
.mk-now-name b { font-weight: 600; font-size: var(--fs-lg); }
.mk-pchip-game { color: var(--c-info); font-size: var(--fs-sm); }
.mk-badges { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-sm); color: var(--c-dim); font-variant-numeric: tabular-nums; }
.mk-pchip-badges { display: flex; gap: 3px; }
.mk-badge-pip { width: 9px; height: 9px; border-radius: 2px; border: 1px solid var(--c-edge); }
.mk-badge-pip.on { background: var(--c-gold); border-color: var(--c-gold); }
.mk-now-body { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-3) var(--mk-pad) var(--mk-pad); flex: 1; }
.mk-now-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3); font-size: var(--fs-md); color: var(--c-dim); }
.mk-now-line b { color: var(--c-txt); font-weight: 600; font-size: var(--fs-lg); }

/* ── The battle, on the player's NOW card ──────────────────────────────
 * Own active mon, then each foe (`vs`), each with status, HP, stat stages and moves; when
 * there is no battle the card shows the party lead the same way. The pair rows only mark
 * which mon is out (⚔ + the red edge). */
.mk-battle, .mk-lead { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2) var(--space-3); border: 1px solid var(--c-edge); border-radius: calc(var(--mk-radius) - 2px); background: color-mix(in srgb, var(--c-bg) 40%, var(--c-card)); }
.mk-battle { border-color: color-mix(in srgb, var(--c-dead) 40%, var(--c-edge)); }
.mk-battle-head { display: flex; align-items: baseline; gap: var(--space-2); }
.mk-cbt { display: flex; align-items: flex-start; gap: var(--space-2); min-width: 0; }
.mk-cbt.foe { padding-top: var(--space-2); border-top: 1px dashed color-mix(in srgb, var(--c-dead) 35%, var(--c-edge)); }
.mk-cbt.bench { opacity: .6; }
.mk-cbt .mk-spr { flex: none; width: var(--mk-spr-s); height: var(--mk-spr-s); }
.mk-cbt-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.mk-cbt-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1); }
.mk-cbt-name b { font-weight: 600; }
.mk-cbt-label { color: var(--c-dead); font-size: var(--fs-sm); letter-spacing: .1em; font-weight: 600; text-transform: uppercase; }
.mk-cbt .mk-hp { flex-direction: row; align-items: center; gap: var(--space-2); }
.mk-cbt .mk-hp-bar { flex: 1; }
.mk-moves { display: flex; flex-wrap: wrap; gap: 3px; }
.mk-move { display: inline-flex; align-items: baseline; gap: 4px; padding: 1px 6px; border-radius: 3px; font-size: var(--fs-sm); color: var(--c-txt); background: rgba(var(--mt, 145,145,145), .18); border: 1px solid rgba(var(--mt, 145,145,145), .5); white-space: nowrap; }
.mk-move .faint { opacity: .7; }
.mk-cbt .sc { font-size: var(--fs-xs); }
.mk-cbt .stat-stages-row { padding: 0; }

.mk-wild { margin-top: auto; font-size: var(--fs-md); color: var(--c-dim); }
.mk-wild summary { display: flex; align-items: baseline; gap: var(--space-2); cursor: pointer; list-style: none; }
.mk-wild summary::-webkit-details-marker { display: none; }
.mk-wild summary::before { content: '▸'; font-size: var(--fs-sm); color: var(--c-dim); }
.mk-wild[open] summary::before { content: '▾'; }
.mk-wild-list { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); padding-top: var(--space-2); }
.mk-wild-row { display: inline-flex; align-items: baseline; gap: var(--space-1); }

/* ── Upcoming Key Trainers (Radical Red; server.py builds the rows) ── a fold like Wild here,
   one compact row per trainer that unfolds into the party, variants when the fight has them */
.trainer-widget { font-size: var(--fs-md); color: var(--c-dim); }
.trainer-widget > summary, .trainer-row > summary { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; list-style: none; }
.trainer-widget > summary::-webkit-details-marker, .trainer-row > summary::-webkit-details-marker { display: none; }
.trainer-widget > summary::before, .trainer-row > summary::before { content: '▸'; font-size: var(--fs-sm); color: var(--c-dim); }
.trainer-widget[open] > summary::before, .trainer-row[open] > summary::before { content: '▾'; }
.trainer-widget > summary .inline-ico { width: 1em; height: 1em; }
.trainer-list { display: flex; flex-direction: column; gap: var(--space-1); padding-top: var(--space-2); }
.trainer-row { border-left: 2px solid color-mix(in srgb, var(--c-link) 35%, transparent); padding-left: var(--space-2); }
.trainer-row.tr-state-past { opacity: .55; }
.trainer-row.tr-state-current { border-left-color: var(--c-pend); }
.trainer-row > summary { line-height: 1.4; flex-wrap: wrap; }
.tr-sprite { width: 32px; height: 32px; object-fit: contain; image-rendering: pixelated; flex-shrink: 0; }
.tr-class { font-size: var(--fs-sm); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.tr-name { color: var(--c-txt); font-weight: 700; }
.tr-size, .tr-cap { font-size: var(--fs-sm); white-space: nowrap; }
.tr-fight-label, .tr-variant-count { font-size: var(--fs-sm); border-radius: 3px; padding: 0 5px; white-space: nowrap; }
.tr-fight-label { background: color-mix(in srgb, var(--c-info) 22%, transparent); color: var(--c-info); }
.tr-variant-count { background: color-mix(in srgb, var(--c-pend) 25%, transparent); color: var(--c-pend); }
.tr-calc-btn, .tr-variant-calc { margin-left: auto; background: color-mix(in srgb, var(--c-pend) 18%, transparent); border: 1px solid color-mix(in srgb, var(--c-pend) 35%, transparent); color: var(--c-pend); border-radius: 4px; padding: 1px 6px; font: inherit; line-height: 1; cursor: pointer; flex-shrink: 0; }
.tr-calc-btn:hover, .tr-variant-calc:hover { background: color-mix(in srgb, var(--c-pend) 35%, transparent); }
.tr-party { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-1) 0 var(--space-2) calc(32px + var(--space-2)); }
.tr-party-row { font-size: var(--fs-sm); line-height: 1.4; padding: 2px 0; border-top: 1px dashed color-mix(in srgb, var(--c-dim) 30%, transparent); }
.tr-party-row:first-child { border-top: 0; }
.tr-mon-hdr { display: flex; align-items: baseline; gap: var(--space-2); }
.tr-species { font-weight: 700; color: var(--c-txt); }
.tr-lv-rule { color: var(--c-info); }
.tr-mon-meta { color: color-mix(in srgb, var(--c-txt) 75%, var(--c-dim)); }
.tr-ability { color: var(--c-link); }
.tr-item { color: var(--c-pend); }
.tr-nature { font-style: italic; }
.tr-moves { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 2px; }
.tr-move { background: color-mix(in srgb, var(--c-dim) 18%, transparent); border-radius: 3px; padding: 0 5px; white-space: nowrap; }
.tr-variants { display: flex; flex-direction: column; gap: var(--space-2); }
.tr-variant { border-left: 2px solid color-mix(in srgb, var(--c-pend) 50%, transparent); padding-left: var(--space-2); }
.tr-variant-hdr { display: flex; align-items: baseline; gap: var(--space-2); margin-bottom: 2px; }
.tr-variant-label { color: var(--c-pend); font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.mk-tag { display: inline-block; padding: 1px var(--chip-pad-x); font-size: var(--fs-sm); letter-spacing: .06em; border: 1px solid var(--c-edge); color: var(--c-dim); white-space: nowrap; }
.mk-tag.off { color: var(--c-dead); border-color: color-mix(in srgb, var(--c-dead) 45%, transparent); }
.mk-tag.fight { color: var(--c-dead); border-color: color-mix(in srgb, var(--c-dead) 45%, transparent); }

/* ── Sprites (shared) ──────────────────────────────────────────────────
 * Two shapes come out of the payload. Gen 3 is a bare <img class="mon-sprite">. Gen 1 is
 * a 40px overflow-hidden <span> cropping a 69px <img> at margin:-14px, all inline styles
 * (its art is a 56px cell on a 96px canvas: scale 96/56 = 12/7, offset 20/56 = 5/14).
 * Scaling the second means scaling the wrapper AND its image by the same factor, in plain
 * lengths -- `scale(calc(60px / 40px))` divides a length by a length, which CSS rejects,
 * and that is why the previous attempt left Gen 1 at 40px. The inline styles need
 * !important to lose; the proper fix is the server emitting a sprite that sizes itself,
 * which is a Phase 1 line in the brief. */
.mk-spr { flex: none; line-height: 0; display: grid; place-items: center; width: var(--mk-spr-s); height: var(--mk-spr-s); }
.mk-spr img.mon-sprite { width: var(--mk-spr-s); height: var(--mk-spr-s); object-fit: contain; image-rendering: pixelated; }
.mk-spr > span { width: var(--mk-spr-s) !important; height: var(--mk-spr-s) !important; }
.mk-spr > span > img { width: calc(var(--mk-spr-s) * 12 / 7) !important; height: calc(var(--mk-spr-s) * 12 / 7) !important; max-width: none; margin: calc(var(--mk-spr-s) * -5 / 14) !important; image-rendering: pixelated; }
.mk-spr.big { width: var(--mk-spr); height: var(--mk-spr); }
.mk-spr.big img.mon-sprite { width: var(--mk-spr); height: var(--mk-spr); }
.mk-spr.big > span { width: var(--mk-spr) !important; height: var(--mk-spr) !important; }
.mk-spr.big > span > img { width: calc(var(--mk-spr) * 12 / 7) !important; height: calc(var(--mk-spr) * 12 / 7) !important; margin: calc(var(--mk-spr) * -5 / 14) !important; }

.mk-hp { display: flex; flex-direction: column; gap: 3px; min-width: calc(var(--scale-step) * 3.4); }
.mk-hp-num { font-size: var(--fs-sm); font-variant-numeric: tabular-nums; color: var(--c-dim); }
.mk-hp-bar { display: block; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--c-txt) 12%, transparent); overflow: hidden; }
.mk-hp-fill { display: block; height: 100%; background: var(--c-hp-high); }
.mk-hp-fill.mid { background: var(--c-hp-mid); }
.mk-hp-fill.low { background: var(--c-hp-low); }

/* ── Pair rows — the team ──────────────────────────────────────────────
 * One row per pair, spanning both player columns: A's half, the bond, B's half. Each row
 * is its own card so the pairs read as units, and the halves keep enough room to be read
 * from a couch. B's half mirrors A's so the sprites sit at the outer edges. */

.mk-pairs { display: flex; flex-direction: column; gap: var(--space-3); }

.mk-pair {
  display: grid; grid-template-columns: minmax(0, 1fr) var(--mk-spine) minmax(0, 1fr); align-items: center;
  border: 1px solid var(--c-edge); border-radius: var(--mk-radius); background: var(--c-card);
}
/* All three cells on one row. The halves are placed in columns 1 and 3 and the bond asks
 * for column 2 after them; with an auto row, sparse placement will not step the cursor
 * backwards, so the bond landed on a second row under the pair -- which read as "the
 * route symbols don't line up" and doubled every row's height. */
.mk-pair > * { grid-row: 1; }
.mk-pair.fallen { background: color-mix(in srgb, var(--c-card) 50%, transparent); border-style: dashed; }
.mk-pair.fallen .mk-spr { filter: grayscale(1); opacity: .55; }
.mk-pair.fallen .mk-half-nick { text-decoration: line-through; color: var(--c-dim); }

.mk-half { min-width: 0; padding: var(--mk-pad); }
.mk-half-in { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.mk-half.b .mk-half-in { flex-direction: row-reverse; text-align: right; }
.mk-half.b .mk-half-txt { align-items: flex-end; }
.mk-half-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; line-height: 1.2; }
.mk-half-nick { font-size: var(--fs-lg); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.mk-half-txt .mk-hp { flex-direction: row; align-items: center; gap: var(--space-2); margin-top: 3px; min-width: 0; width: 100%; }
.mk-half-txt .mk-hp-bar { flex: 1; height: 8px; }
.mk-half-txt .mk-hp-num { flex: none; }
.mk-half.b .mk-half-txt .mk-hp { flex-direction: row-reverse; }
.mk-active { color: var(--c-dead); font-size: var(--fs-sm); margin-right: 3px; }
/* Per half, never per row: battle is a player state, in that player's game only. The
 * fighting half gets a red outer edge; the partner's half shows nothing about it. */
.mk-half.fighting.a { box-shadow: inset 4px 0 0 var(--c-dead); }
.mk-half.fighting.b { box-shadow: inset -4px 0 0 var(--c-dead); }
.mk-item { color: var(--c-gold); cursor: help; }
.mk-half-in.slot { opacity: .7; }
.mk-half.b .mk-half-in.slot { flex-direction: row-reverse; }
.mk-slot { width: var(--mk-spr); height: var(--mk-spr); flex: none; border: 1px dashed var(--c-edge); border-radius: 8px; }

/* The bond cell: route on top, the tie, and the state under it. It is the row's header,
 * placed where the link actually is — between the two. */
.mk-bond {
  align-self: stretch; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: var(--space-2) var(--space-1); text-align: center; min-width: 0;
  border-inline: 1px solid var(--c-sep); background: color-mix(in srgb, var(--c-bg) 35%, transparent);
}
.mk-bond-area { font-size: var(--fs-sm); color: var(--c-info); letter-spacing: .04em; line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.mk-bond-glyph { font-family: var(--font-mono); font-size: var(--fs-lg); letter-spacing: .1em; color: var(--c-alive); }
.mk-bond.pending .mk-bond-glyph { color: var(--c-pend); }
.mk-bond.dead .mk-bond-glyph, .mk-bond.memorial .mk-bond-glyph, .mk-bond.dead_zone .mk-bond-glyph { color: var(--c-dead); }
.mk-bond-state { font-size: var(--fs-sm); color: var(--c-dim); line-height: 1.15; }
.mk-bond-state b { font-weight: 600; }
.mk-bond.dead .mk-bond-state, .mk-bond.memorial .mk-bond-state, .mk-bond.dead_zone .mk-bond-state { color: color-mix(in srgb, var(--c-dead) 75%, var(--c-dim)); }

/* Compact rows for waiting / boxed. */
.mk-pairs.compact .mk-half { padding: var(--space-2) var(--mk-pad); }
.mk-pairs.compact .mk-spr.big { width: var(--mk-spr-s); height: var(--mk-spr-s); }
.mk-pairs.compact .mk-spr.big img.mon-sprite { width: var(--mk-spr-s); height: var(--mk-spr-s); }
.mk-pairs.compact .mk-spr.big > span { width: var(--mk-spr-s) !important; height: var(--mk-spr-s) !important; }
.mk-pairs.compact .mk-spr.big > span > img { width: calc(var(--mk-spr-s) * 1.3) !important; height: calc(var(--mk-spr-s) * 1.3) !important; margin: calc(var(--mk-spr-s) * -0.15) !important; }
.mk-pairs.compact .mk-slot { width: var(--mk-spr-s); height: var(--mk-spr-s); }
.mk-pairs.compact .mk-sub.faint { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }  /* .sr-only: off screen, still read */


@media (max-width: 760px) {
  .mk-now, .mk-pair { grid-template-columns: minmax(0, 1fr); }
  .mk-now > *, .mk-pair > * { grid-column: 1 !important; }
  .mk-bond { border-inline: none; border-block: 1px solid var(--c-sep); }
}

/* ── Phone: rail becomes a top app bar + overlay drawer ───────────────────
 * dashboard.js builds .mk-topbar (menu button + run identity) and .mk-scrim once
 * per page load -- no template change, same trick as the theme-switcher relocation
 * below. The rail itself is untouched markup, just repositioned as the drawer it
 * opens into. .mk-rail-open on .mk is the only state the JS toggles. */
.mk-topbar, .mk-scrim { display: none; }
@media (max-width: 900px) {
  .mk { grid-template-columns: minmax(0, 1fr); }
  .mk-topbar {
    display: flex; align-items: center; gap: var(--space-3);
    position: fixed; top: 0; left: 0; right: 0; height: 56px; z-index: 101;
    padding: 0 var(--space-3);
    /* --c-card is a low-alpha overlay meant to sit ON an opaque --c-bg (see .mk-runhdr
       below) -- mixing it card-dominant here left the bar ~12% opaque and the board
       showed through underneath a fixed bar. bg-dominant, same as .mk-runhdr. */
    background: color-mix(in srgb, var(--c-bg) 92%, var(--c-card)); border-bottom: 1px solid var(--c-edge);
  }
  .mk-menu-btn {
    width: 44px; height: 44px; flex: none; display: grid; place-items: center;
    border: 1px solid var(--c-edge-ui, var(--c-edge)); border-radius: 8px;
    background: var(--c-card); color: var(--c-txt); font-size: 1.3rem; line-height: 1; cursor: pointer;
  }
  .mk-topbar-title { font-size: var(--fs-lg); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mk-main { padding-top: 56px; }
  .mk-runhdr { top: 56px; }
  .mk-rail {
    position: fixed; top: 0; left: 0; height: 100vh; width: min(320px, 85vw);
    transform: translateX(-100%); transition: transform .2s ease-out; z-index: 100;
    box-shadow: 2px 0 24px rgba(0, 0, 0, .45);
    /* The rail's own background is a translucent color-mix (fine sitting beside the page);
       as an overlay drawer it must not let the board read through it. Same double-opaque
       trick as .mgr-rail-theme .theme-pills below, since --c-bg itself is translucent in
       some themes. */
    background: linear-gradient(var(--c-card), var(--c-card)), linear-gradient(var(--c-bg), var(--c-bg)), linear-gradient(var(--c-bg), var(--c-bg));
  }
  .mk.mk-rail-open .mk-rail { transform: translateX(0); }
  .mk-scrim {
    display: block; position: fixed; inset: 0; z-index: 99; border: 0; padding: 0;
    background: rgba(0, 0, 0, .5);
  }
  .mk-scrim[hidden] { display: none; }
  @media (prefers-reduced-motion: reduce) {
    .mk-rail { transition-duration: 0s; }
  }
}

/* ── Phone pairs: A | bond | B stays side by side down to 320px ───────────
 * decisions.md #2: a slim spectator card (sprite, name, level, HP), no ability, item
 * or moves. Overrides the 760px stack above -- later in the cascade wins -- back to
 * the three-column spine, just tighter. .mk-now (the per-player battle card) keeps
 * stacking; only the pair row is pinned side by side. */
@media (max-width: 600px) {
  /* fit-content caps the bond column, so a long route wraps (.mk-bond-area below) instead of
   * widening the spine and squeezing both halves. */
  .mk-pair { grid-template-columns: minmax(0, 1fr) fit-content(32%) minmax(0, 1fr); gap: 0; }
  .mk-pair > *:nth-child(1) { grid-column: 1 !important; }
  .mk-pair > *:nth-child(2) { grid-column: 2 !important; }
  .mk-pair > *:nth-child(3) { grid-column: 3 !important; }
  .mk-pair .mk-half { padding: var(--space-2) var(--space-1); }
  .mk-pair .mk-half-in { gap: var(--space-1); }
  .mk-pair .mk-half-nick { font-size: var(--fs-sm); }
  .mk-pair .mk-half-txt .mk-sub { font-size: var(--fs-xs); }
  .mk-pair .mk-sub.faint { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }   /* ability + held item: decisions.md #2; .sr-only, so still read */
  .mk-pair .mk-spr.big, .mk-pair .mk-spr.big > span { width: 40px !important; height: 40px !important; }
  .mk-pair .mk-spr.big img.mon-sprite { width: 40px; height: 40px; }
  .mk-pair .mk-spr.big > span > img { width: calc(40px * 12 / 7) !important; height: calc(40px * 12 / 7) !important; margin: calc(40px * -5 / 14) !important; }
  .mk-pair .mk-slot { width: 40px; height: 40px; }
  .mk-pair .mk-half-txt .mk-hp-num { font-size: 10px; }
  .mk-bond { padding: var(--space-1) 2px; border-inline: 1px solid var(--c-sep); border-block: none; }
  /* Two lines rather than an ellipsis: on a phone the route name is the row's only label. */
  .mk-bond-area { font-size: 10px; white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
  .mk-bond-glyph { font-size: var(--fs-sm); }
  .mk-bond-state { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
}

/* ── Timeline (/timeline): the run's story, one row per event ─────────────── */
.tl-list { list-style: none; margin: 0; padding: 0; }
.tl-ev { display: grid; grid-template-columns: 9.5em minmax(0, 1fr); gap: var(--space-3); align-items: start; padding: var(--space-3); border-bottom: 1px solid var(--c-sep); border-left: 3px solid var(--c-alive); }
.tl-ev:last-child { border-bottom: none; }
.tl-ev.death, .tl-ev.dead_zone { border-left-color: var(--c-dead); }
.tl-ev.memorial { border-left-color: var(--c-dim); }
.tl-ev.open { grid-template-columns: minmax(0, 1fr); border-left-color: var(--c-pend); }
.tl-when { color: var(--c-dim); font-size: var(--fs-sm); padding-top: 2px; }
.tl-what { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.tl-mons { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.tl-mon { display: inline-flex; align-items: center; gap: var(--space-1); }
.tl-ev.death .mk-spr, .tl-ev.dead_zone .mk-spr { filter: grayscale(1); opacity: .6; }
.tl-tie { font-family: var(--font-mono); color: var(--c-dim); }
.mk-zone > .mk-note { margin: 0 0 var(--space-3); }
@media (max-width: 600px) { .tl-ev { grid-template-columns: minmax(0, 1fr); gap: var(--space-1); } }

/* ── Log ───────────────────────────────────────────────────────────────── */

.mk-logcol { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.mk-feed { display: flex; flex-direction: column; max-height: calc(var(--scale-step) * 14); overflow-y: auto; }
.mk-ev { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: var(--space-2); align-items: baseline; padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--c-sep); font-size: var(--fs-md); }
.mk-ev:last-child { border-bottom: none; }
.mk-ev-ts { color: var(--c-dim); font-variant-numeric: tabular-nums; }
.mk-ev-who { color: var(--c-brand); }

/* ── Tables, forms ─────────────────────────────────────────────────────── */

table.mk-tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
.mk-tbl th { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--c-edge); text-align: left; font-weight: 400; font-size: var(--fs-sm); letter-spacing: .1em; text-transform: uppercase; color: var(--c-dim); }
.mk-tbl td { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--c-sep); vertical-align: middle; }
.mk-tbl tr:last-child td { border-bottom: none; }
.mk-form { max-width: calc(var(--scale-step) * 42); display: flex; flex-direction: column; gap: var(--space-5); }
.mk-group { display: flex; flex-direction: column; gap: var(--space-3); }
.mk-field { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-md); }
.mk-field span { color: var(--c-dim); }
.mk-field :is(input, select) { padding: var(--space-2); border: 1px solid var(--c-edge-ui, var(--c-edge)); border-radius: 6px; background: var(--c-bg); color: var(--c-txt); font: inherit; font-size: var(--fs-base); min-width: 0; }
.mk-field select { text-overflow: ellipsis; }
/* the preset row: saved list, name, actions; wraps on a narrow page */
.mk-presets { display: flex; flex-wrap: wrap; gap: var(--space-1); align-items: center; }
.mk-presets :is(input, select) { padding: var(--space-2); border: 1px solid var(--c-edge-ui, var(--c-edge)); border-radius: 6px; background: var(--c-bg); color: var(--c-txt); font: inherit; font-size: var(--fs-md); min-width: 0; min-height: 40px; box-sizing: border-box; }
.mk-presets select { flex: 1 1 12em; } .mk-presets input[type=text] { flex: 1 1 10em; }
/* a text field or select with its file-dialog button */
.mk-filerow { display: flex; gap: var(--space-1); }
.mk-filerow > :is(input, select) { flex: 1; }
.mk-filerow > .mk-btn { flex: none; }
.mk-btn.busy { opacity: .6; pointer-events: none; }
/* the file input stays in the tab order (Enter / Space open the dialog); the label is the button */
.mk-btn:has(> input[type=file]) { position: relative; }
.mk-btn > input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip: rect(0 0 0 0); }
.mk-field input.big { font-size: var(--fs-h1); }
.mk-opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--space-3); }
.mk-opt { display: flex; flex-wrap: wrap; align-items: center; align-content: start; gap: var(--space-1) var(--space-2); padding: var(--space-3); border: 1px solid var(--c-edge); border-radius: var(--mk-radius); background: var(--c-card); font-size: var(--fs-md); cursor: pointer; }
.mk-opt.on { border-color: color-mix(in srgb, var(--c-alive) 55%, transparent); }
.mk-opt.off-unavailable, .mk-range.off-unavailable { opacity: .5; cursor: default; }
.mk-gchip:disabled { opacity: .45; cursor: default; }
.mk-gchip:disabled:hover { border-color: var(--c-edge-ui, var(--c-edge)); }
.mk-opt-why { flex: 1 1 100%; font-size: var(--fs-md); line-height: 1.4; color: var(--c-dim); }
.mk-note { padding: var(--space-3); border-left: 2px solid var(--c-info); background: color-mix(in srgb, var(--c-info) 8%, transparent); font-size: var(--fs-md); color: var(--c-dim); }
code { font-family: var(--font-mono); font-size: var(--fs-md); color: var(--c-link); }
kbd { padding: 1px 5px; border: 1px solid var(--c-edge); border-bottom-width: 2px; border-radius: 3px; background: var(--c-bg); font-family: var(--font-mono); font-size: var(--fs-sm); }

/* ── New run ───────────────────────────────────────────────────────────
 * Form on the left, the run-to-be on the right. Options carry their description; a game
 * chosen up front greys what it cannot honour, with the reason, before anyone connects. */
.mk-newpage { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); align-items: start; }
@media (min-width: 1100px) { .mk-newpage { grid-template-columns: minmax(0, 1.6fr) minmax(300px, 1fr); } }
.mk-newpage .mk-form { max-width: none; gap: var(--space-5); }
.mk-field.big input { font-size: var(--fs-h1); padding: var(--space-3); }
.mk-games { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.mk-gchip { padding: var(--space-2) max(var(--space-3), var(--chip-pad-x)); border: 1px solid var(--c-edge-ui, var(--c-edge)); background: var(--c-card); color: var(--c-txt); font: inherit; font-size: var(--fs-md); cursor: pointer; }
.mk-gchip:hover { border-color: var(--c-brand); }
.mk-gchip.active { color: var(--c-bg); background: var(--c-brand); border-color: var(--c-brand); }
.mk-optgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: var(--space-3); }
/* the randomizer's option groups: one fieldset per UPR area, chips for modes, a range per curve */
.mk-rgroups { columns: 2 340px; column-gap: var(--space-3); }
.mk-rgroup { display: flex; flex-direction: column; gap: var(--space-3); margin: 0 0 var(--space-3); break-inside: avoid; padding: var(--space-3); border: 1px solid var(--c-edge); border-radius: calc(var(--mk-radius) + var(--space-3)); background: var(--c-card); min-width: 0; }
.mk-rgroup legend { padding: 0 var(--space-1); color: var(--c-dim); font-size: var(--fs-sm); }
.mk-rgroup .mk-opt { padding: var(--space-2) var(--space-3); min-height: 40px; box-sizing: border-box; }
.mk-rlabel { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); align-items: baseline; font-size: var(--fs-md); color: var(--c-dim); }
.mk-rlabel em { font-style: normal; }
/* a choice row's chosen meaning, and the note that qualifies a row */
.mk-rhelp { font-size: var(--fs-sm); color: var(--c-dim); line-height: 1.45; text-wrap: pretty; }
.mk-rhelp.note { color: var(--c-pend); }
.mk-rchoice { display: flex; flex-direction: column; gap: var(--space-2); }
.mk-rchips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.mk-rchips .mk-gchip { padding: var(--space-1) max(var(--space-3), var(--chip-pad-x)); min-height: 36px; }
.mk-range { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "label out" "range out"; gap: 2px var(--space-3); align-items: center; }
.mk-range .mk-rlabel { grid-area: label; }
.mk-range input[type=range] { grid-area: range; width: 100%; margin: 0; min-height: 28px; accent-color: var(--c-brand); }
.mk-range output { grid-area: out; min-width: 4ch; text-align: right; font-size: var(--fs-lg); color: var(--c-dim); }
.mk-range output.set { color: var(--c-txt); }
.mk-banner { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); margin: 0 0 var(--space-3); padding: var(--space-2) var(--space-3); border: 1px solid var(--c-edge); border-radius: var(--mk-radius); background: var(--c-card); font-size: var(--fs-md); text-wrap: pretty; }
.mk-banner.error { border-color: color-mix(in srgb, var(--c-dead) 45%, var(--c-edge)); background: color-mix(in srgb, var(--c-dead) 8%, var(--c-card)); }
.mk-banner b { color: var(--c-dead); }
.mk-linkbtn { border: 0; padding: 0; background: none; color: var(--c-brand); font: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.mk-opt.described { align-items: flex-start; flex-wrap: nowrap; gap: var(--space-3); }
.mk-opt.described input { margin-top: 3px; }
.mk-opt-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.mk-opt-name { font-weight: 500; }
.mk-opt-desc { font-size: var(--fs-md); color: var(--c-dim); line-height: 1.35; }
.mk-opt.described .mk-opt-why { flex: none; color: var(--c-pend); }
.mk-form-actions { display: flex; align-items: center; gap: var(--space-3); }
.mk-btn.big { font-size: var(--fs-base); padding: var(--space-3) var(--space-5); }
.mk-newside { display: flex; flex-direction: column; gap: var(--space-5); position: sticky; top: calc(var(--scale-step) * 3.2); }
.mk-preview { padding: var(--space-2); }
.mk-preview-body { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3) var(--space-2) var(--space-2); }
.mk-preview-rules { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.mk-tag.on { color: var(--c-alive); border-color: color-mix(in srgb, var(--c-alive) 45%, transparent); }
.mk-firstrun { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4) var(--space-5); }
.mk-firstrun > b { font-size: var(--fs-base); }
.mk-firstrun .mk-steps li { line-height: 2; }
.mk-firstrun .mk-btn { margin: 0 2px; vertical-align: middle; }
.mk-steps { margin: 0; padding-left: 1.4em; display: flex; flex-direction: column; gap: var(--space-3); font-size: var(--fs-md); line-height: 1.4; color: var(--c-dim); }
.mk-steps li::marker { color: var(--c-brand); font-weight: 600; }
.mk-steps b { color: var(--c-txt); font-weight: 500; }
.mk-steps em { color: var(--c-txt); font-style: normal; text-decoration: underline; text-decoration-color: var(--c-pend); }

/* ── Rail switcher slots (from the retired manager.css) ────────────────
 * dashboard.js relocates the theme switcher into this. */
/* Theme switcher slot — dashboard.js relocates the floating switcher here,
 * styled to fill the rail width with its dropdown opening upward to avoid
 * colliding with the runs list above. */
.mgr-rail-theme {
  margin-top: auto;              /* pinned to the bottom of the rail, under the runs list */
  padding: 10px 12px;
  border-top: 1px solid color-mix(in srgb, var(--c-brand) 14%, var(--c-edge));
}
.mgr-rail-theme:empty { display: none; }
.mgr-rail-theme .theme-switcher--in-sidebar {
  position: static !important;
  top: auto !important;
  right: auto !important;
  width: 100%;
}
.mgr-rail-theme .theme-switcher--in-sidebar details {
  background: var(--c-card);
  border: 1px solid color-mix(in srgb, var(--c-brand) 22%, var(--c-edge));
  width: 100%;
  /* Override the inline `min-width: 130px` from `_theme_switcher.html`
   * (loaded after this stylesheet) so the picker fits the rail width
   * rather than overflowing into the runs list. */
  min-width: 0 !important;
  max-width: 100%;
  position: relative;
}
.mgr-rail-theme .theme-switcher--in-sidebar summary {
  padding: 7px 10px;
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  letter-spacing: 0.04em;
}
.mgr-rail-theme .theme-switcher--in-sidebar .theme-pills {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 0;
  right: 0;
  /* A pop-up floats over the page, so it must be opaque. Default's --c-card is 4% white
   * and its --c-bg 90% opaque: card over bg twice leaves nothing showing through. */
  background: linear-gradient(var(--c-card), var(--c-card)), linear-gradient(var(--c-bg), var(--c-bg)), linear-gradient(var(--c-bg), var(--c-bg));
  border: 1px solid color-mix(in srgb, var(--c-brand) 22%, var(--c-edge));
  border-radius: 6px;
  padding: 4px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .5);
  z-index: 60;
}

/* ── Feel ──────────────────────────────────────────────────────────────
 * The details that compound: interruptible colour transitions on hover (never
 * `transition: all`), a 0.96 press on anything that is a button, hit areas that reach
 * 40px on a desktop, nested corners that stay concentric, and prose that does not orphan. */
.mk-btn, .mk-gchip, .mk-tab, .mk-rail-item, .mk-opt {
  transition-property: background-color, border-color, color, scale;
  transition-duration: .12s;
  transition-timing-function: ease-out;
}
.mk-btn:active, .mk-gchip:active, .mk-tab:active { scale: .96; }
.mk-btn:disabled:active { scale: 1; }
.mk-btn, .mk-gchip, .mk-tab, .mk-rail-item { min-height: 40px; box-sizing: border-box; }
/* .mk-gchip / .mk-tab are clipped chips: their ring is inset (slink.css, the chip rule). */
.mk-btn:focus-visible, .mk-btn:has(> input:focus-visible), .mk-rail-item:focus-visible, .mk-opt:focus-within {
  outline: 2px solid var(--c-brand); outline-offset: 2px;
}
/* Concentric: a button inside a padded 8px/10px surface keeps its corners inside the parent's. */
.mk-pop .mk-btn, .mk-preview .mk-rail-item, .mk-card-body .mk-btn { border-radius: 4px; }
.mk-hp-fill { transition-property: width, background-color; transition-duration: .3s; transition-timing-function: ease-out; }
.mk-opt-desc, .mk-opt-why, .mk-empty, .mk-steps li, .mk-cap, .mk-note, .mk-sub { text-wrap: pretty; }
.mk-h2, .mk-runname { text-wrap: balance; }
@media (prefers-reduced-motion: reduce) {
  .mk-btn, .mk-gchip, .mk-tab, .mk-rail-item, .mk-opt, .mk-hp-fill { transition-duration: 0s; }
  .mk-btn:active, .mk-gchip:active, .mk-tab:active { scale: 1; }
}
