:root {
  color-scheme: dark;
  --ink: #eee6d5;
  --muted: #a89e8b;
  --black: #0d0c0a;
  --panel: #181511;
  --panel-light: #211d17;
  --line: #3d3529;
  --gold: #c8a76a;
  --gold-bright: #eed69a;
  --red: #9d302d;
  --red-bright: #da5b50;
  --blue: #265a78;
  --blue-bright: #5aa5c9;
  --green: #759266;
  --shadow: 0 18px 50px rgba(0, 0, 0, .38);
}

* { box-sizing: border-box; }

html, body { min-height: 100%; }

body {
  margin: 0;
  overflow-x: hidden;
  color: var(--ink);
  font-family: Inter, system-ui, sans-serif;
  background:
    radial-gradient(circle at 20% 0, rgba(113, 79, 39, .16), transparent 35%),
    linear-gradient(rgba(8, 7, 5, .97), rgba(12, 10, 8, .99)),
    repeating-linear-gradient(90deg, transparent 0 6px, rgba(255,255,255,.015) 6px 7px);
}

button, input { font: inherit; }
button { color: inherit; }

button:focus-visible, input:focus-visible, canvas:focus-visible {
  outline: 2px solid var(--gold-bright);
  outline-offset: 3px;
}

.app-shell { max-width: 1640px; margin: 0 auto; padding: 0 24px 28px; }

.masthead {
  min-height: 94px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--line);
}

.brand-block { display: flex; align-items: baseline; gap: 14px; }
.brand-block h1, h2, h3 { font-family: Cinzel, Georgia, serif; }
.brand-block h1 { margin: 0; font-size: clamp(1.9rem, 4vw, 3.2rem); letter-spacing: .08em; text-transform: uppercase; }
.brand-block .eyebrow { position: absolute; top: 13px; }
.edition { color: var(--gold); font-family: Cinzel, Georgia, serif; font-size: .84rem; letter-spacing: .16em; text-transform: uppercase; }

.eyebrow {
  color: var(--gold);
  font-size: .65rem;
  font-weight: 700;
  letter-spacing: .19em;
  text-transform: uppercase;
}

.header-actions, .tray-buttons, .dialog-actions { display: flex; align-items: center; gap: 10px; }
.text-button, .icon-button, .secondary-button, .primary-button, .link-button {
  border: 0;
  cursor: pointer;
}
.text-button, .icon-button {
  min-height: 40px;
  padding: 0 16px;
  border: 1px solid var(--line);
  background: rgba(255,255,255,.025);
  text-transform: uppercase;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .1em;
}
.online-link { display: inline-grid; place-items: center; text-decoration: none; }
.online-status { max-width: 180px; overflow: hidden; color: var(--muted); font-size: .58rem; font-weight: 700; letter-spacing: .08em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.online-status.my-turn { color: var(--gold-bright); }
/* The strip is width-capped and ellipsises, so the opponent's state is a mark, not a phrase.
   Filled for present, hollow for away: red and green alone separate nothing for the ~8% of men who
   cannot tell those two hues apart, so the shape has to carry the difference as well as the colour. */
.online-status.opponent-here,
.online-status.opponent-away { display: inline-flex; align-items: center; gap: 6px; max-width: 200px; }
.online-status.opponent-here::before,
.online-status.opponent-away::before { content: ''; width: 7px; height: 7px; flex: 0 0 auto; border-radius: 50%; }
.online-status.opponent-here { color: #7fd6a4; }
.online-status.opponent-here::before { background: #7fd6a4; box-shadow: 0 0 0 3px rgba(127,214,164,.16); }
.online-status.opponent-away { color: #c9705f; }
.online-status.opponent-away::before { background: transparent; border: 2px solid #c9705f; }
.icon-button { width: 40px; padding: 0; color: var(--gold); }
.text-button:hover, .icon-button:hover, .secondary-button:hover { border-color: var(--gold); background: rgba(200,167,106,.08); }

.game-layout {
  display: grid;
  grid-template-columns: minmax(600px, 1.65fr) minmax(330px, .75fr);
  gap: 22px;
  padding-top: 22px;
}

.battle-column, .command-column { min-width: 0; }
.command-column { display: flex; flex-direction: column; gap: 12px; }

.phase-strip {
  min-height: 85px;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 11px 14px 13px;
  border: 1px solid var(--line);
  border-bottom: 0;
  background: var(--panel);
}
.round-seal, .initiative-step {
  width: 58px;
  height: 58px;
  flex: 0 0 58px;
  display: grid;
  place-content: center;
  text-align: center;
  border: 1px solid var(--gold);
  transform: rotate(45deg);
}
.round-seal > *, .initiative-step > * { transform: rotate(-45deg); }
.round-seal span, .initiative-step span { color: var(--muted); font-size: .55rem; text-transform: uppercase; letter-spacing: .1em; }
.round-seal strong, .initiative-step strong { font-family: Cinzel, serif; font-size: 1.3rem; }
.phase-copy { min-width: 0; flex: 1; }
.phase-copy h2 { margin: 3px 0 2px; font-size: clamp(1rem, 2.1vw, 1.35rem); }
.phase-copy p { margin: 0; color: var(--muted); font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.initiative-step { border-color: var(--line); }

.battlefield-frame {
  position: relative;
  overflow: hidden;
  border: 1px solid #514536;
  background: #29251d;
  box-shadow: var(--shadow);
  aspect-ratio: 117 / 83;
}
#battlefield { display: block; width: 100%; height: 100%; cursor: crosshair; touch-action: none; }
#battlefield.read-only { cursor: default; }
.canvas-hint {
  position: absolute;
  left: 50%;
  bottom: 15px;
  translate: -50% 0;
  max-width: calc(100% - 28px);
  padding: 9px 16px;
  color: #efe7d5;
  background: rgba(11, 9, 7, .86);
  border: 1px solid rgba(200,167,106,.35);
  font-size: .73rem;
  text-align: center;
  pointer-events: none;
  transition: opacity .2s;
}
.measurement { position: absolute; pointer-events: none; padding: 4px 7px; border-radius: 3px; background: #0d0c0a; color: var(--gold-bright); font-size: .68rem; }

/* The walkthrough sits in the lower-left of the board, clear of the action tray beneath it and of
   the opponent notice above.

   It is pinned to the viewport, which on a narrow screen means it spans the full width and lands on
   whatever happens to be at the bottom of the display: usually the front rank of knights. A tester
   could not move them at all. So the panel takes no taps of its own and the board keeps receiving
   them straight through it. Only the close button is a target, and it is a real one rather than a
   16-pixel glyph, because reaching for it is exactly what someone does when it is in the way. */
.tutorial-coach {
  position: fixed; z-index: 30; left: 18px; bottom: 18px;
  width: min(330px, calc(100vw - 36px)); padding: 14px 42px 14px 15px;
  border: 1px solid rgba(200,167,106,.72); background: rgba(18,16,13,.94);
  box-shadow: 0 16px 40px rgba(0,0,0,.5); backdrop-filter: blur(5px);
  pointer-events: none;
}
.tutorial-coach .tutorial-title { display: block; margin-top: 3px; font-family: Cinzel, Georgia, serif; font-size: .88rem; }
.tutorial-coach .tutorial-body { margin: 6px 0 0; color: var(--muted); font-size: .68rem; line-height: 1.55; }
/* Inside a dialog the note sits under the decision, since the backdrop hides anything outside. */
.tutorial-inline { margin-top: 18px; padding: 12px 14px; border: 1px solid rgba(200,167,106,.45); background: rgba(200,167,106,.06); }
.tutorial-inline strong { display: block; margin-top: 3px; font-family: Cinzel, Georgia, serif; font-size: .8rem; }
.tutorial-inline p { margin: 5px 0 0; color: var(--muted); font-size: .68rem; line-height: 1.55; }
.tutorial-close {
  position: absolute; top: 2px; right: 2px; display: grid; place-items: center;
  width: 40px; height: 40px; color: var(--muted); border: 0; background: none;
  cursor: pointer; font-size: 1.2rem; line-height: 1; pointer-events: auto;
}
.tutorial-close:hover { color: var(--ink); }
/* Both controls have to claim pointer events back, since the panel itself takes none. */
.tutorial-coach .tutorial-stop { margin-top: 11px; padding: 4px 0; pointer-events: auto; }
/* Naming the part of the screen the note is about beats describing where to look. */
.tutorial-target { outline: 2px solid var(--gold); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
  .tutorial-target { animation: tutorial-pulse 2.2s ease-in-out infinite; }
}
@keyframes tutorial-pulse {
  0%, 100% { outline-color: rgba(200,167,106,.85); }
  50% { outline-color: rgba(200,167,106,.28); }
}
@media (max-width: 650px) {
  .tutorial-coach { left: 10px; right: 10px; bottom: 10px; width: auto; }
}.opponent-activity {
  position: absolute; z-index: 5; top: 14px; left: 50%; translate: -50% 0;
  width: min(430px, calc(100% - 28px)); padding: 13px 40px 13px 15px;
  border: 1px solid rgba(200,167,106,.72); background: rgba(18,16,13,.76);
  box-shadow: 0 12px 35px rgba(0,0,0,.35); backdrop-filter: blur(5px);
}
.opponent-activity > strong { display: block; margin-top: 3px; font-family: Cinzel, Georgia, serif; font-size: .88rem; }
.opponent-activity > p { margin: 5px 0 0; color: var(--muted); font-size: .66rem; line-height: 1.4; }
.opponent-activity-close { position: absolute; top: 6px; right: 8px; color: var(--muted); border: 0; background: none; cursor: pointer; font-size: 1.2rem; }
.opponent-activity-close:hover { color: var(--ink); }
.opponent-activity .spectator-dice { margin: 10px 0 0; }
.opponent-activity .spectator-choices { margin: 10px 0 0; }
.spectator-rolls { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.spectator-rolls > div { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 0 8px; padding: 8px 10px; border: 1px solid var(--line); background: rgba(0,0,0,.22); }
.spectator-rolls span { color: var(--muted); font-size: .57rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.spectator-rolls strong { grid-row: span 2; color: var(--gold-bright); font: 1.35rem Cinzel, serif; }
.spectator-rolls small { color: var(--muted); font-size: .61rem; line-height: 1.35; }
.spectator-result-note { margin-top: 7px; color: var(--muted); font-size: .6rem; text-align: center; }

.action-tray {
  min-height: 76px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-top: 0;
  background: var(--panel);
}
.action-summary { display: flex; align-items: center; gap: 13px; }
.action-summary > div { min-width: 0; }
.action-summary strong { display: block; margin-top: 2px; font-family: Cinzel, serif; }
#action-name { max-width: min(42vw, 430px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.action-number {
  width: 43px; height: 43px; display: grid; place-items: center;
  color: #19130a; background: var(--gold); font-family: Cinzel, serif; font-size: 1.3rem; font-weight: 700;
  clip-path: polygon(25% 6%,75% 6%,100% 50%,75% 94%,25% 94%,0 50%);
}
.primary-button, .secondary-button {
  min-height: 42px;
  padding: 0 18px;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.primary-button { color: #18120a; background: linear-gradient(#e0c17f, #b28b48); border: 1px solid #f2d997; }
.primary-button:hover { filter: brightness(1.08); }
.primary-button:disabled { cursor: not-allowed; filter: grayscale(1); opacity: .45; }
.secondary-button { color: var(--ink); border: 1px solid var(--line); background: #201c16; }

.player-panel, .roster-panel, .chronicle-panel {
  border: 1px solid var(--line);
  background: linear-gradient(125deg, rgba(255,255,255,.02), transparent 45%), var(--panel);
}
.player-panel { padding: 14px; position: relative; overflow: hidden; }
.player-panel::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--red); }
.player-panel.player-two::before { background: var(--blue); }
.player-panel.active { border-color: var(--gold); box-shadow: inset 0 0 18px rgba(200,167,106,.08); }
.player-panel.clash-attacker { border-color: var(--gold); box-shadow: inset 0 0 22px rgba(238,214,154,.11); }
.player-panel.clash-defender { border-color: #8fc6d7; box-shadow: inset 0 0 22px rgba(143,198,215,.09); }
.player-heading, .force-status, .section-heading { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.player-heading h3 { margin: 2px 0 0; font-size: 1rem; }
.turn-marker { display: none; color: var(--gold-bright); font-size: .58rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
.active .turn-marker { display: inline; }
.clash-attacker .turn-marker, .clash-defender .turn-marker { display: inline; }
.clash-defender .turn-marker { color: #a9d9e7; }
.force-status { margin-top: 11px; color: var(--muted); font-size: .68rem; }
.force-status strong { color: var(--ink); }
.dice-rack { min-height: 34px; display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.die {
  width: 31px; height: 31px; display: grid; place-items: center;
  border: 1px solid #655943; border-radius: 4px; color: #21190d; background: #d9c99f;
  font-weight: 800; font-size: .8rem; box-shadow: inset 0 0 0 2px rgba(255,255,255,.2);
}
.die.spent { opacity: .18; filter: grayscale(1); }
.die.current { box-shadow: 0 0 0 2px var(--gold), inset 0 0 0 2px rgba(255,255,255,.25); transform: translateY(-2px); }
.die.selectable { cursor: pointer; }
.die.selected { color: #fff; background: #8f352f; border-color: #e47769; }
.empty-dice { color: var(--muted); font-size: .68rem; font-style: italic; }

.roster-panel { padding: 13px 14px 10px; }
.section-heading { padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.legend-item { color: var(--muted); font-size: .58rem; }
.weapon-icon { display: inline-block; width: 7px; height: 7px; margin-right: 3px; border: 1px solid currentColor; transform: rotate(45deg); }
.shield-icon { color: var(--gold); }
.blade-icon { color: #b8c3c7; border-radius: 50% 0; }
.roster { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 8px; margin-top: 8px; }
.roster-card {
  min-width: 0; display: grid; grid-template-columns: 22px 1fr auto; align-items: center; gap: 5px;
  padding: 5px; border: 1px solid transparent; cursor: pointer; font-size: .63rem;
}
.roster-card:hover, .roster-card.selected { background: rgba(200,167,106,.07); border-color: #4e4232; }
.roster-card.clash-attacker { border-color: var(--gold); background: rgba(200,167,106,.1); }
.roster-card.clash-defender { border-color: #75afc1; background: rgba(89,160,183,.09); }
.roster-card.dead { opacity: .33; text-decoration: line-through; }
.roster-token { width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; background: var(--red); color: white; font-family: Cinzel, serif; font-size: .6rem; }
.team-1 .roster-token { background: var(--blue); }
.roster-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clash-role { grid-column: 2 / -1; color: var(--gold-bright); font-size: .49rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.clash-defender .clash-role { color: #a9d9e7; }
.pips { display: flex; gap: 2px; }
.pip { width: 5px; height: 5px; border-radius: 50%; border: 1px solid #706654; }
.pip.damage { background: var(--red-bright); border-color: var(--red-bright); }
.pip.momentum { background: var(--gold); border-color: var(--gold); }

.chronicle-panel { min-height: 160px; padding: 13px 14px; flex: 1; }
.link-button { color: var(--muted); background: none; font-size: .6rem; text-transform: uppercase; letter-spacing: .08em; }
.link-button:hover { color: var(--ink); }
.battle-log { max-height: 190px; overflow: auto; margin: 9px 0 0; padding: 0 0 0 22px; color: var(--muted); font-size: .66rem; line-height: 1.55; scrollbar-width: thin; }
.battle-log li::marker { color: #6e604a; }

/* Chronicle marks. A die is the thing a player wants to find again when arguing about a result,
   so it gets the strongest treatment; the modifiers behind it are named but kept quiet. */
.battle-log .roll { display: inline-block; min-width: 17px; padding: 0 3px; color: #17120b; background: var(--gold-bright); border-radius: 2px; font-weight: 800; text-align: center; }
.battle-log .mod { color: var(--muted); font-weight: 700; }
.battle-log .total { color: var(--ink); font-weight: 800; }
.battle-log .atk { color: #e08a6a; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; font-size: .92em; }
.battle-log .def { color: #8fc4dd; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; font-size: .92em; }
/* The fighters carry the same two tints as the labels, but stay names: no caps, no tracking. */
.battle-log .atk-name { color: #e08a6a; font-weight: 700; }
.battle-log .def-name { color: #8fc4dd; font-weight: 700; }
.battle-log em { display: block; margin-top: 2px; color: var(--muted); font-size: .92em; font-style: normal; opacity: .85; }.battle-log strong { color: var(--ink); font-weight: 600; }

.game-dialog {
  width: min(680px, calc(100vw - 30px));
  max-height: calc(100vh - 30px);
  overflow: auto;
  padding: 28px;
  color: var(--ink);
  border: 1px solid var(--gold);
  background: linear-gradient(145deg, #242019, #12100d 65%);
  box-shadow: 0 30px 90px rgba(0,0,0,.75);
}
.game-dialog::backdrop { background: rgba(5,4,3,.82); backdrop-filter: blur(4px); transition: background .16s ease, backdrop-filter .16s ease; }
.game-dialog h2 { margin: 5px 0 8px; font-size: 1.65rem; }
.game-dialog p { color: var(--muted); font-size: .84rem; line-height: 1.55; }
.name-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 20px 0; }
.name-grid label > span, fieldset legend { display: block; margin-bottom: 6px; color: var(--gold); font-size: .65rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; }
.name-grid input { width: 100%; padding: 11px; color: var(--ink); border: 1px solid var(--line); background: #0d0c0a; }
fieldset { display: grid; gap: 8px; margin: 0 0 20px; padding: 0; border: 0; }
.radio-card, .settings-option { display: flex; align-items: center; gap: 12px; padding: 11px; border: 1px solid var(--line); cursor: pointer; }
.radio-card:has(input:checked), .settings-option:has(input:checked) { border-color: var(--gold); background: rgba(200,167,106,.07); }
.radio-card input, .settings-option input { accent-color: var(--gold); }
.radio-card span, .settings-option span { display: grid; gap: 2px; }
.radio-card strong, .settings-option strong { font-size: .76rem; }
.radio-card small, .settings-option small { color: var(--muted); font-size: .65rem; line-height: 1.55; }
.dialog-actions { justify-content: flex-end; margin-top: 18px; }

.decision-dialog { width: min(560px, calc(100vw - 30px)); transition: opacity .16s ease; }
.decision-dialog h2 { font-size: 1.3rem; }

/* Peeking at the fight the dialog is asking about.
   Fading the panel alone is not enough: the backdrop carries an 82% dim and a 4px blur, so both
   have to lift together or the field comes back grey and smeared. The content stops taking taps
   while faded, because a choice you cannot see is one you must not be able to commit by accident;
   the dialog itself keeps taking them, so the tap that ends the peek lands anywhere on screen. */
.decision-dialog.peeking { opacity: .08; }
.decision-dialog.peeking::backdrop { background: transparent; backdrop-filter: blur(0); }
.decision-dialog.peeking > * { pointer-events: none; }
.peek-hint { margin: 14px 0 0; color: var(--muted); font-size: .62rem; letter-spacing: .06em; text-align: center; text-transform: uppercase; opacity: .75; }
.decision-dialog.peeking .peek-hint { visibility: hidden; }
.choice-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 16px 0; }
.choice-button {
  padding: 13px; color: var(--ink); text-align: left; border: 1px solid var(--line); background: #171410; cursor: pointer;
}
.choice-button:hover, .choice-button.selected { border-color: var(--gold); background: rgba(200,167,106,.09); }
.choice-button strong, .choice-button small { display: block; }
.choice-button strong { font-family: Cinzel, serif; font-size: .85rem; }
.choice-button small { margin-top: 3px; color: var(--muted); font-size: .65rem; line-height: 1.4; }
.roll-display { display: flex; align-items: center; justify-content: center; gap: 18px; margin: 22px 0; }
.large-die { width: 62px; height: 62px; display: grid; place-items: center; border: 2px solid var(--gold); background: #d7c598; color: #19130a; font-size: 1.55rem; font-weight: 800; }
/* The plate carries the total, so it is not dressed as a die face — the die it came from is named
   underneath instead. */
.roll-total {
  width: 62px; height: 62px; display: grid; place-items: center;
  border: 2px solid var(--gold); background: rgba(0,0,0,.34);
  color: var(--gold-bright); font-family: Cinzel, serif; font-size: 1.55rem; font-weight: 800;
}
.roll-side { text-align: center; }
.roll-side span { display: block; margin-top: 6px; color: var(--muted); font-size: .62rem; }
.roll-side .roll-label { margin-top: 8px; color: var(--gold-bright); font-size: .58rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.roll-side .roll-parts { margin-top: 2px; }
.versus { color: var(--gold); font-family: Cinzel, serif; }
.bonus-list { margin: 12px 0; padding: 9px 12px; background: rgba(255,255,255,.025); color: var(--muted); font-size: .7rem; line-height: 1.65; }
.momentum-picker { display: flex; align-items: center; gap: 9px; margin: 14px 0; }
.momentum-picker button { width: 34px; height: 34px; border: 1px solid var(--line); background: #171410; cursor: pointer; }
.momentum-picker strong { min-width: 28px; text-align: center; }
.result-banner { padding: 12px; border-left: 3px solid var(--gold); background: rgba(200,167,106,.08); }
.result-banner strong { display: block; font-family: Cinzel, serif; }
.result-banner span { color: var(--muted); font-size: .72rem; }
.spectator-pulse {
  display: inline-block; width: 8px; height: 8px; margin-right: 8px; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 0 rgba(200,167,106,.5); animation: spectator-pulse 1.5s infinite;
}
.spectator-dice { margin: 16px 0; }
.spectator-choices { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin: 16px 0; }
.spectator-choices span { padding: 9px 5px; color: var(--muted); border: 1px solid var(--line); font-size: .62rem; font-weight: 700; text-align: center; text-transform: uppercase; }
.spectator-choices span.selected { color: var(--ink); border-color: #a9d9e7; background: rgba(143,198,215,.1); }
@keyframes spectator-pulse { 70% { box-shadow: 0 0 0 8px rgba(200,167,106,0); } 100% { box-shadow: 0 0 0 0 rgba(200,167,106,0); } }

.rules-dialog { width: min(920px, calc(100vw - 30px)); }
.settings-dialog { width: min(520px, calc(100vw - 30px)); }
.settings-note { margin: 6px 0 16px; color: var(--muted); font-size: .68rem; line-height: 1.6; }
.dialog-close { position: absolute; top: 12px; right: 14px; color: var(--muted); border: 0; background: none; font-size: 1.7rem; cursor: pointer; }
.rules-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 24px; }
.rules-grid section { border-top: 1px solid var(--line); }
.rules-grid h3 { margin: 12px 0 0; font-size: .94rem; }
.rules-grid p, .rules-actions { font-size: .72rem; }
.rules-actions { padding-left: 25px; color: var(--muted); line-height: 1.55; }
.rules-actions li::marker { color: var(--gold); font-weight: 700; }
.rules-note { padding: 10px; border: 1px solid var(--line); }
.rules-done { float: right; }

.toast {
  position: fixed; z-index: 20; left: 50%; bottom: 24px; translate: -50% 20px;
  padding: 10px 15px; color: #161009; background: var(--gold-bright); box-shadow: var(--shadow);
  font-size: .72rem; font-weight: 700; opacity: 0; pointer-events: none; transition: .2s;
}
.toast.show { opacity: 1; translate: -50% 0; }

@media (max-width: 1050px) {
  .game-layout { grid-template-columns: 1fr; }
  .command-column { display: grid; grid-template-columns: 1fr 1fr; }
  .roster-panel, .chronicle-panel { grid-column: span 1; }
  .battle-log { max-height: 140px; }
}

@media (max-width: 650px) {
  .app-shell { padding: 0 10px 16px; }
  .masthead { min-height: 74px; }
  .brand-block { display: block; }
  .brand-block .eyebrow { top: 7px; }
  .brand-block h1 { font-size: 1.65rem; }
  .edition { display: none; }
  /* The row already fitted to the pixel before the settings button joined it, so let it wrap
     rather than shave padding off every control until one of them stops being tappable. */
  .header-actions { gap: 5px; flex-wrap: wrap; justify-content: flex-end; }
  .online-status { display: none; }
  .icon-button { display: none; }
  #settings-button { display: inline-grid; place-items: center; width: 34px; min-height: 34px; padding: 0; }
  .text-button { min-height: 34px; padding: 0 9px; font-size: .62rem; }
  .game-layout { padding-top: 10px; gap: 10px; }
  .phase-strip { min-height: 72px; gap: 11px; padding: 9px 10px; }
  .round-seal, .initiative-step { width: 45px; height: 45px; flex-basis: 45px; }
  .round-seal strong, .initiative-step strong { font-size: 1rem; }
  .phase-copy p { max-width: 57vw; }
  .battlefield-frame { aspect-ratio: 117 / 83; }
  /* The board's own note is a floating panel across the lower third of the field. On a phone the
     field is barely 260px tall, so that panel lands on the front rank and hides it, and a knight
     you cannot see is one you cannot aim a tap at. Pointer-transparency was the fix last time and
     it does nothing here: this one blocks the eye, not the finger. Everything it says is already
     on screen at this width - the phase strip directly above the board carries the same
     instruction, the status pill carries "waiting for the opposing commander", and the tray button
     carries the confirm label. The one exception is staged placement, which has no other home and
     is a touch preference in the first place, so that note alone still shows. */
  .canvas-hint { display: none; }
  .canvas-hint.placement { display: block; }
  .action-tray { align-items: stretch; flex-direction: column; padding: 9px; }
  .action-tray .toast {
    position: static;
    width: 100%;
    max-height: 0;
    overflow: hidden;
    padding: 0 12px;
    opacity: 0;
    translate: none;
    box-shadow: none;
    transition: max-height .2s, padding .2s, opacity .2s;
  }
  .action-tray .toast.show { max-height: 72px; padding: 10px 12px; opacity: 1; translate: none; }
  .tray-buttons > button { flex: 1; padding: 0 10px; }
  .command-column { grid-template-columns: 1fr; }
  .roster-panel, .chronicle-panel { grid-column: auto; }
  .name-grid, .rules-grid { grid-template-columns: 1fr; }
  .game-dialog {
    width: calc(100% - 20px);
    max-width: calc(100% - 20px);
    margin: 10px auto;
    padding: 20px;
    overflow-x: hidden;
  }
  .game-dialog form, .game-dialog fieldset, .radio-card, .radio-card span, .settings-option, .settings-option span { min-width: 0; max-width: 100%; }
  .radio-card small, .settings-option small { overflow-wrap: anywhere; }
  .choice-grid { grid-template-columns: 1fr; }
  .opponent-activity { top: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; }
  .spectator-pulse { animation: none; }
}
