/* Neo-Mirai tabletop visual system — the single consolidated theme, after
   the 2026-06 "Heirloom Table" overhaul: resource cards carry ivory coin
   icons that echo the board's harbor tokens, the dice are a physical
   ivory-and-red pair with a once-per-roll tumble, and modals fade in via the
   persistent backdrop node (inner re-renders never replay the entrance).
   Individual UI transitions stay under ~700ms, ease-out, and are disabled by the
   prefers-reduced-motion block at the bottom of this file. */

:root {
  color-scheme: light;
  --bg: oklch(0.93 0.038 78);
  --paper: oklch(0.955 0.026 82);
  --ink: oklch(0.205 0.034 65);
  --muted: oklch(0.46 0.04 68);
  --line: oklch(0.71 0.048 72);
  --accent: oklch(0.61 0.18 45);
  --accent-strong: oklch(0.51 0.18 39);
  --focus: oklch(0.7 0.16 76);
  --deep: oklch(0.175 0.045 161);
  --deep-soft: oklch(0.235 0.052 157);
  --gold: oklch(0.74 0.14 78);
  --grid-line: oklch(0.48 0.055 72 / 0.12);
  --radius: 0;
  font-family: "Segoe UI", Arial, system-ui, sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
    radial-gradient(circle at 82% 14%, oklch(0.85 0.14 82 / 0.44), transparent 25rem),
    var(--bg);
  background-size: 64px 64px, 64px 64px, auto, auto;
  color: var(--ink);
}

body::before {
  position: fixed;
  z-index: -1;
  inset: 0;
  background:
    linear-gradient(90deg, transparent 49.96%, oklch(0.38 0.055 68 / 0.13) 50%, transparent 50.04%),
    linear-gradient(transparent 49.96%, oklch(0.38 0.055 68 / 0.1) 50%, transparent 50.04%);
  content: "";
  pointer-events: none;
}

.eyebrow,
.label,
.sub-label,
.setup-option-group h3,
.table-wordmark {
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 850;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.eyebrow {
  margin: 0 0 3px;
}

.table-identity {
  display: flex;
  align-items: center;
  gap: 11px;
}

.table-wordmark {
  color: var(--ink);
  font-size: 0.83rem;
}

.table-mark {
  position: relative;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  display: block;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background:
    conic-gradient(from 0deg, var(--accent) 0 25%, var(--gold) 0 50%, oklch(0.88 0.048 79) 0 75%, var(--deep-soft) 0);
  overflow: hidden;
}

.table-mark::before,
.table-mark::after {
  position: absolute;
  content: "";
  background: var(--ink);
}

.table-mark::before {
  top: 50%;
  right: 0;
  left: 0;
  height: 1px;
}

.table-mark::after {
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
}

.table-mark i {
  position: absolute;
  z-index: 1;
  top: 4px;
  right: 4px;
  width: 12px;
  height: 12px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--paper);
}

.setup-screen {
  position: relative;
  isolation: isolate;
  height: 100vh;
  min-height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 42px;
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
    radial-gradient(circle at 18% 20%, oklch(0.98 0.025 85 / 0.96), transparent 24rem),
    linear-gradient(118deg, oklch(0.965 0.035 85), oklch(0.89 0.07 76));
  background-size: 64px 64px, 64px 64px, auto, auto;
}

/* Match the opening's first frame while the entry module initializes. */
.setup-screen:empty { background: #123d33; }
.setup-screen:empty::before, .setup-screen:empty::after { display: none; }

.setup-screen::before {
  position: absolute;
  z-index: -1;
  top: -17vw;
  right: -7vw;
  width: min(58vw, 780px);
  aspect-ratio: 1;
  border: 1px solid oklch(0.71 0.12 73 / 0.52);
  border-radius: 999px;
  background: oklch(0.79 0.16 72 / 0.42);
  box-shadow: inset 0 0 0 28px oklch(0.94 0.08 78 / 0.18);
  content: "";
}

.setup-screen::after {
  position: absolute;
  z-index: -1;
  bottom: 34px;
  left: 42px;
  color: oklch(0.38 0.07 61 / 0.56);
  content: "STANDARD TABLE / SOLO PROTOCOL 01";
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  writing-mode: vertical-rl;
}

.setup-layout {
  width: min(1320px, 100%);
  min-height: calc(100vh - 84px);
  display: grid;
  grid-template-columns: minmax(340px, 0.88fr) minmax(590px, 1.12fr);
  gap: clamp(46px, 7vw, 118px);
  align-items: center;
  margin: 0 auto;
}

.setup-intro {
  align-self: start;
  padding: 3vh 0 0 56px;
}

.setup-identity {
  margin-bottom: 72px;
}

.setup-intro h1 {
  max-width: 7ch;
  margin: 0;
  color: var(--ink);
  font-family: "Arial Narrow", "Aptos Display", "Segoe UI", sans-serif;
  font-size: clamp(4.9rem, 8vw, 7.6rem);
  font-stretch: condensed;
  font-weight: 320;
  letter-spacing: -0.085em;
  line-height: 0.82;
  text-transform: uppercase;
}

.setup-intro > p:not(.eyebrow) {
  max-width: 34ch;
  color: oklch(0.34 0.045 66);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.22rem;
  font-weight: 500;
  line-height: 1.48;
  margin: 30px 0 0;
}

.setup-intro-actions {
  margin-top: 14px;
}

.setup-vignette {
  width: min(348px, 92%);
  height: auto;
  display: block;
  margin: 30px 0 0;
  filter: drop-shadow(10px 12px 0 oklch(0.27 0.06 62 / 0.13));
}

.setup-island-mark {
  display: block;
  flex: 0 0 64px;
  width: 64px;
  height: calc(64px * 250 / 360);
}

.setup-island-mark .setup-vignette {
  width: 100%;
  max-height: none;
  height: 100%;
  margin: 0;
  filter: none;
}

/* The welcome lasts 3.7 seconds, then this same island lands in the masthead. */
.welcome-intro {
  position: fixed;
  inset: 0;
  z-index: 10000;
  overflow: hidden;
  isolation: isolate;
  color: #f6eed8;
}

.welcome-backdrop {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 50% 46%, #48756660, transparent 56%),
    radial-gradient(ellipse at 50% 90%, #8b763520, transparent 65%),
    #123d33;
}

.welcome-backdrop::before,
.welcome-backdrop::after {
  content: "";
  position: absolute;
  width: min(720px, 120vw);
  aspect-ratio: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-12deg);
  border: 1px dashed #b6c19823;
  border-radius: 50%;
}

.welcome-backdrop::after {
  width: min(860px, 150vw);
  border-style: solid;
  border-color: #b6c19812;
}

.welcome-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: max(24px, env(safe-area-inset-top)) 16px max(60px, env(safe-area-inset-bottom));
  pointer-events: none;
}

.welcome-heading {
  text-align: center;
  margin-bottom: 12px;
}

.welcome-heading span {
  display: block;
  font-size: 10px;
  font-weight: 750;
  letter-spacing: .28em;
  color: #ddc68e;
}

.welcome-heading strong {
  display: block;
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(42px, 8vw, 76px);
  font-weight: 700;
  letter-spacing: .09em;
  text-indent: .09em;
  line-height: 1.2;
  text-shadow: 0 3px 0 #092a25;
}

.welcome-island {
  flex: 0 0 auto;
  width: min(520px, 88vw, calc((100svh - 210px) * 1.44));
  aspect-ratio: 360 / 250;
  transform-origin: top left;
  will-change: transform;
}

.welcome-island .setup-vignette {
  width: 100%;
  max-height: none;
  height: 100%;
  margin: 0;
  overflow: visible;
  filter: none;
}

.welcome-island [data-intro] {
  transform-box: fill-box;
  transform-origin: center;
}

.welcome-caption {
  margin: 18px 0 0;
  color: #d3d7bf;
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(14px, 2vw, 17px);
  text-align: center;
}

.welcome-skip,
.welcome-sound {
  position: absolute;
  right: max(24px, env(safe-area-inset-right));
  bottom: max(18px, env(safe-area-inset-bottom));
  min-width: 115px;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid #a3b49d60;
  border-radius: 30px;
  background: #173e34;
  box-shadow: none;
  color: #f6eed8;
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .03em;
}

.welcome-skip span { margin-left: 8px; }
.welcome-sound { right: auto; left: max(24px, env(safe-area-inset-left)); }
.welcome-skip:hover, .welcome-sound:hover { background: #31564a; color: #fff6dc; }
.welcome-skip:focus-visible, .welcome-sound:focus-visible { outline: 2px solid #e9ce8b; outline-offset: 4px; }

@media (max-height: 480px) and (orientation: landscape) {
  .welcome-heading { margin-bottom: 2px; }
  .welcome-heading strong { font-size: 40px; }
  .welcome-heading span { font-size: 9px; }
  .welcome-caption { margin-top: 6px; font-size: 13px; }
  .welcome-center { padding-block: 16px 42px; }
  .welcome-island { width: min(420px, 64vw, calc((100svh - 150px) * 1.44)); }
}

.setup-note {
  position: relative;
  max-width: 35ch;
  display: grid;
  gap: 7px;
  border: 1px solid oklch(0.27 0.055 158);
  border-radius: var(--radius);
  background: var(--deep);
  color: oklch(0.93 0.045 83);
  margin-top: 46px;
  padding: 18px 19px;
}

.setup-note::after {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 11px;
  height: 11px;
  border: 1px solid var(--gold);
  border-radius: 999px;
  content: "";
}

.setup-note strong {
  color: var(--gold);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.setup-note span {
  color: oklch(0.85 0.035 80);
  font-size: 0.8rem;
  font-weight: 650;
  line-height: 1.45;
}

.setup-form {
  position: relative;
  border: 1px solid oklch(0.48 0.052 67);
  border-radius: var(--radius);
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
    oklch(0.955 0.026 82);
  background-size: 32px 32px;
  box-shadow: 16px 18px 0 oklch(0.27 0.06 62 / 0.14);
  overflow: hidden;
}

.setup-form::before {
  display: block;
  border-bottom: 1px solid var(--line);
  background: var(--deep);
  color: var(--gold);
  content: "TABLE CONFIGURATION / 01";
  padding: 11px 20px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
}

.setup-section {
  display: grid;
  gap: 17px;
  padding: 21px 24px;
}

.setup-section + .setup-section {
  border-top: 1px solid var(--line);
  border-color: var(--line);
}

.setup-section-heading {
  display: grid;
  grid-template-columns: 36px 1fr;
  gap: 10px;
}

.setup-step {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: transparent;
  color: var(--accent-strong);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.72rem;
  font-weight: 900;
}

.setup-section h2,
.setup-option-group h3 {
  margin: 0;
}

.setup-section h2 {
  color: var(--ink);
  font-family: "Arial Narrow", "Aptos Display", "Segoe UI", sans-serif;
  font-size: 1.34rem;
  font-weight: 680;
  letter-spacing: 0.055em;
  line-height: 1.15;
  text-transform: uppercase;
}

.setup-section-heading p,
.setup-empty {
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 650;
  line-height: 1.42;
  margin: 3px 0 0;
}

.setup-field,
.setup-fieldset {
  display: grid;
  gap: 7px;
  border: 0;
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 820;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
  padding: 0;
}

.setup-field {
  max-width: 260px;
}

.color-choice-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 7px;
}

.color-choice .color-piece { width: 36px; height: 34px; flex: none; }
.color-choice-row .color-choice {
  position: relative;
  min-width: 0;
  min-height: 66px;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 5px 3px;
  text-align: center;
  font-size: 12px;
}
.color-choice-row .color-choice input {
  position: absolute;
  top: 7px;
  left: 7px;
  width: 12px;
  height: 12px;
}

.color-choice {
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: oklch(0.98 0.02 84 / 0.76);
  color: var(--ink);
  padding: 7px 10px;
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 760;
}

.color-choice input {
  margin: 0;
}

.color-swatch {
  width: 15px;
  height: 15px;
  border: 1px solid oklch(0.25 0.02 70 / 0.28);
  border-radius: 999px;
  background: var(--player-color);
}

.setup-option-group {
  display: grid;
  gap: 7px;
}

.module-option,
.turn-order-option {
  min-height: 52px;
  display: grid;
  grid-template-columns: 18px 1fr;
  align-items: start;
  gap: 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: oklch(0.98 0.02 84 / 0.76);
  padding: 10px;
  cursor: pointer;
}

.module-option:hover,
.turn-order-option:hover,
.color-choice:hover {
  border-color: var(--accent);
  background: oklch(0.94 0.06 80);
}

/* same specificity as :hover above — must stay after it so a checked option
   keeps the checked background while hovered */
.module-option:has(input:checked),
.turn-order-option:has(input:checked),
.color-choice:has(input:checked) {
  border-color: var(--accent);
  background: oklch(0.93 0.075 76);
  box-shadow: inset 0 -3px 0 var(--accent);
}

.module-option input,
.turn-order-option input {
  margin: 2px 0 0;
}

.module-option-copy,
.turn-order-option span {
  display: grid;
  gap: 3px;
}

.module-option-copy strong,
.turn-order-option strong {
  color: var(--ink);
  font-size: 0.88rem;
}

.module-option-copy span,
.turn-order-option small {
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 640;
  line-height: 1.35;
}

.module-option-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
  gap: 8px;
}

.module-option-row .module-option {
  min-width: 0;
}

.directions-link {
  min-height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.68rem;
  font-weight: 850;
  letter-spacing: 0.07em;
  padding: 8px 10px;
  text-transform: uppercase;
}

.directions-link:hover {
  border-color: var(--accent);
  background: oklch(0.94 0.06 80);
}

.directions-link:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.scenario-field {
  max-width: none;
  border: 1px solid var(--line);
  background: oklch(0.98 0.02 84 / 0.76);
  padding: 12px;
  /* Nested under its expansion's checkbox row: indent to read as a child. */
  margin: 2px 0 12px 30px;
}

.scenario-field small {
  max-width: 68ch;
  color: var(--muted);
  font-family: "Segoe UI", Arial, system-ui, sans-serif;
  font-size: 0.78rem;
  font-weight: 650;
  letter-spacing: 0;
  line-height: 1.45;
  text-transform: none;
}

.scenario-story {
  display: grid;
  gap: 7px;
}

/* The voyage's story, set like flavor text on the back of the box. */
.scenario-synopsis {
  max-width: 62ch;
  margin: 2px 0 0;
  color: oklch(0.33 0.05 64);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.92rem;
  font-style: italic;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.5;
  text-transform: none;
}

.scenario-field-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.turn-order-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.setup-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  border-top: 1px solid var(--line);
  border-color: var(--line);
  background: oklch(0.93 0.05 78);
  padding: 16px 24px;
}

.setup-actions button {
  min-width: 152px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.setup-form-column {
  min-width: 0;
  display: grid;
  gap: 26px;
  align-content: center;
}

.continue-card,
.records-card {
  border: 1px solid oklch(0.48 0.052 67);
  border-radius: var(--radius);
  background: oklch(0.955 0.026 82);
  box-shadow: 16px 18px 0 oklch(0.27 0.06 62 / 0.14);
  overflow: hidden;
}

.continue-card::before,
.records-card::before {
  display: block;
  border-bottom: 1px solid var(--line);
  background: var(--deep);
  color: var(--gold);
  padding: 11px 20px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
}

.continue-card::before {
  content: "UNFINISHED VOYAGES";
}

.records-card::before {
  content: "TABLE RECORDS";
}

.continue-entry {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 15px 20px;
}

.continue-entry + .continue-entry {
  border-top: 1px solid var(--line);
}

.continue-meta {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.continue-meta strong {
  font-size: 1.02rem;
}

.continue-detail {
  color: oklch(0.42 0.04 66);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
}

.continue-standings {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 0.82rem;
  font-weight: 650;
}

.continue-seat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.continue-seat .color-swatch {
  width: 12px;
  height: 12px;
}

.continue-actions {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.continue-actions button {
  min-width: 108px;
  min-height: 34px;
  font-size: 0.85rem;
}

.records-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
  border-bottom: 1px solid var(--line);
}

.record-stat {
  display: grid;
  gap: 3px;
  background: oklch(0.955 0.026 82);
  padding: 11px 14px;
  /* Hairline separators that survive a ragged last row (no gap-color leak). */
  box-shadow: -1px -1px 0 0 var(--line);
}

.record-stat span {
  color: oklch(0.42 0.04 66);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.record-stat strong {
  font-size: 1.06rem;
}

.recent-games {
  display: grid;
  border-bottom: 1px solid var(--line);
}

.recent-game {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 16px;
  font-size: 0.84rem;
}

.recent-game + .recent-game {
  border-top: 1px solid var(--line);
}

.recent-result {
  min-width: 44px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.recent-game.won .recent-result {
  color: oklch(0.5 0.13 152);
}

.recent-game.lost .recent-result {
  color: var(--accent-strong);
}

.recent-game.quit .recent-result {
  color: oklch(0.45 0.03 66);
}

.recent-scenario {
  font-weight: 700;
}

.recent-detail {
  color: oklch(0.42 0.04 66);
  font-size: 0.76rem;
}

.records-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  background: oklch(0.93 0.05 78);
  padding: 12px 16px;
}

.records-actions button {
  min-height: 34px;
  font-size: 0.8rem;
}

button,
select,
input {
  font: inherit;
}

button {
  min-height: 40px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--accent);
  color: oklch(0.96 0.02 83);
  cursor: pointer;
  font-weight: 700;
  letter-spacing: 0.015em;
  transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1), background 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}

/* Terrain-colored card buttons keep their own card face on hover (their
   feedback is the lift + ring); everything else darkens to the accent.
   :where() keeps the exclusions at zero specificity so the many
   class-level hover rules (.secondary-button etc.) still win. */
button:hover:not(:disabled):where(:not(.trade-move-card)):where(:not(.resource-choice)):where(:not(.trade-token)):where(:not(.radial-wedge-tag)) {
  background: var(--accent-strong);
}

button:active:not(:disabled):where(:not(.radial-wedge-tag)) {
  transform: translate(2px, 2px);
}

button:focus-visible,
select:focus-visible,
input:focus-visible {
  outline: 3px solid oklch(0.72 0.17 73 / 0.9);
  outline-offset: 2px;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

input[type="radio"],
input[type="checkbox"] {
  accent-color: var(--accent);
}

select,
input[type="number"] {
  width: 100%;
  min-height: 38px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: oklch(0.98 0.02 84);
  color: var(--ink);
  padding: 0 10px;
}

.secondary-button,
.ghost-button,
.icon-button {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--line);
}

.secondary-button:hover:not(:disabled),
.ghost-button:hover:not(:disabled),
.icon-button:hover:not(:disabled) {
  border-color: var(--accent);
  background: oklch(0.93 0.058 79);
}

.icon-button {
  width: 32px;
  min-height: 32px;
  padding: 0;
  font-size: 1rem;
}

/* ==========================================================================
   Full-screen overlay HUD. The board canvas fills the viewport; every control
   is a zone anchored to an edge on top of it. Mobile-first: the base rules are
   the phone layout; the min-width:1040px block widens the roster into a left
   column and lays the dock out in a single row. Setup screen (#setupScreen)
   keeps its own grid layout below and is untouched by this section.
   ========================================================================== */

:root {
  --dock-clearance: 128px;
}

.app-shell {
  position: fixed;
  inset: 0;
  padding: 0;
  overflow: hidden;
}

/* Screen-reader heading: the visible game title lived in the retired top-right
   topbar; the page still needs an h1, so it moves off-screen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* Shared line-icon vocabulary for the dock, the Actions radial, and board
   tools. */
.radial-sat-icon svg,
.radial-wedge-tag svg,
.radial-close-x svg,
.dock-history svg,
.board-tools svg,
.end-turn-button svg,
.audio-toggle svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Zone 4 retired: table utilities (Directions, Sound, Log, Concede, New game)
   live under the Actions radial's Menu wedge.

   The Actions radial: ACTIONS opens a full-screen overlay that soft-focuses
   the table. Category wedges arc around a CLOSE hub pinned over the dock
   corner, and the chosen category's actions ride an outer arc as ivory token
   satellites — the same disc vocabulary as the board's number chits and
   harbor coins. hud.js computes all geometry (angles, radii, sizes) inline;
   these rules only dress it. */
.action-radial {
  position: fixed;
  inset: 0;
  z-index: 18;
  background: oklch(0.24 0.035 130 / 0.32);
  pointer-events: auto;
  animation: backdrop-in 180ms cubic-bezier(0.22, 1, 0.36, 1);
}

.action-radial.hidden {
  display: none;
}

/* Wedge ring: deep teal cardboard sectors; the selected one flips to paper.
   The SVG itself never intercepts clicks — only the wedge paths do. */
.radial-wedges {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 560px;
  height: 520px;
  overflow: visible;
  pointer-events: none;
}

.radial-wedge {
  pointer-events: auto;
  cursor: pointer;
  fill: var(--deep);
  stroke: oklch(0.925 0.028 82 / 0.92);
  stroke-width: 2;
  stroke-linejoin: round;
  transition: fill 140ms ease;
}

.radial-wedge:hover:not(.selected) {
  fill: var(--deep-soft);
}

.radial-wedge.selected {
  fill: var(--paper);
  stroke: oklch(0.38 0.045 68);
}

.radial-guide {
  fill: none;
  stroke: oklch(0.945 0.022 83 / 0.65);
  stroke-width: 2;
  stroke-dasharray: 2 7;
  stroke-linecap: round;
  animation: radial-dash 9s linear infinite;
}

@keyframes radial-dash {
  to {
    stroke-dashoffset: -121;
  }
}

/* Wedge icon + name overlay; hud.js pins each tag at its wedge's centroid. */
.radial-tags {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.radial-wedge-tag {
  position: absolute;
  transform: translate(50%, 50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: oklch(0.925 0.028 82);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.52rem;
  font-weight: 850;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.radial-wedge-tag.selected {
  color: var(--ink);
}

.radial-wedge-tag svg {
  width: 17px;
  height: 17px;
}

/* Satellites: each button is a positioned shell (hud.js sets right/bottom to
   its arc point); the token span inside is the visible ivory disc so hover
   and press transforms never fight the centering translate. */
.radial-sats {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.radial-sat.radial-page-hidden { display: none; }

.radial-sats.hidden {
  display: none;
}

.radial-sat {
  position: absolute;
  width: var(--sat-size, 66px);
  height: var(--sat-size, 66px);
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  transform: translate(50%, 50%);
  pointer-events: auto;
  cursor: pointer;
  display: block;
}

/* The global button vocabulary (orange fill, hover darken, active nudge) must
   not reach the radial controls: satellites are invisible positioned shells —
   the token span inside carries all visual feedback — and the hub keeps its
   deep-teal medallion. The .action-radial prefix outranks the global rules. */
.action-radial .radial-sat,
.action-radial .radial-sat:hover,
.action-radial .radial-sat:active {
  background: none;
  transform: translate(50%, 50%);
}

.action-radial .radial-close:hover {
  background: var(--deep-soft);
}

.action-radial .radial-close:active {
  transform: translate(50%, 50%);
}

.radial-sat-token {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border: 1.5px solid oklch(0.5 0.05 70);
  border-radius: 50%;
  background: radial-gradient(circle at 38% 30%, oklch(0.975 0.014 82), oklch(0.935 0.032 81));
  box-shadow: 3px 4px 0 oklch(0.18 0.04 120 / 0.34);
  color: var(--ink);
  transition:
    transform 140ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 140ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 140ms ease;
}

.radial-sat:hover:not(.unavailable) .radial-sat-token {
  transform: translate(-1px, -2px);
  border-color: var(--accent);
  box-shadow: 5px 7px 0 oklch(0.18 0.04 120 / 0.36);
}

.radial-sat:active:not(.unavailable) .radial-sat-token {
  transform: translate(2px, 2px);
  box-shadow: 1px 2px 0 oklch(0.18 0.04 120 / 0.3);
}

.radial-sat:focus-visible {
  outline: none;
}

.radial-sat:focus-visible .radial-sat-token {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* Dimmed satellites stay tappable (aria-disabled) so the readout can explain
   why; the dashed rim marks them as not-yet-available, never invisible. */
.radial-sat.unavailable {
  cursor: default;
}

.radial-sat.unavailable .radial-sat-token {
  border-style: dashed;
  border-color: oklch(0.58 0.045 70);
  background: oklch(0.93 0.022 82);
  box-shadow: none;
}

.radial-sat.unavailable .radial-sat-token > * {
  opacity: 0.5;
}

.radial-sat.unavailable .radial-sat-label {
  opacity: 0.65;
}

/* hud.js hands each label a radial offset (--label-x/y from the token center)
   plus the outward unit vector (--label-ux/uy); the transform anchors the
   label box's hub-facing edge at that point, so labels above the ring center
   themselves while labels beside it extend away from the tokens. */
.radial-sat-label {
  position: absolute;
  left: calc(50% + var(--label-x, 0px));
  top: calc(50% + var(--label-y, -42px));
  transform: translate(calc(-50% + var(--label-ux, 0) * 50%), calc(-50% + var(--label-uy, -1) * 50%));
  white-space: nowrap;
  color: oklch(0.955 0.018 83);
  text-shadow: 0 1px 0 oklch(0.18 0.03 130 / 0.6);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.64rem;
  font-weight: 850;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Token art: the shared build icons ride bare inside the disc (no boxed chip
   background), and utility line icons inherit walnut ink. */
.radial-sat-token .build-icon {
  width: 28px;
  height: 26px;
  border: 0;
  background: none;
  box-shadow: none;
}

.radial-sat-token .build-icon svg {
  width: 26px;
  height: 26px;
}

.radial-sat-icon {
  display: grid;
  place-items: center;
  color: var(--ink);
}

.radial-sat-icon svg {
  width: 22px;
  height: 22px;
}

/* Cost pips: one tinted card-sliver per resource, colored by the same terrain
   classes the hand and cost cards use. */
.radial-sat-pips {
  display: flex;
  justify-content: center;
  gap: 2px;
}

.radial-pip {
  display: inline-block;
  width: 7px;
  height: 10px;
  border: 1px solid oklch(0.3 0.04 66 / 0.85);
  border-radius: 2px;
}

/* The CLOSE hub: a deep-teal medallion with a dashed inner ring, sitting where
   the ACTIONS toggle lives so open/close feel like the same control. */
.radial-close {
  position: fixed;
  z-index: 19;
  right: var(--radial-hub-right, 110px);
  bottom: var(--radial-hub-bottom, 96px);
  transform: translate(50%, 50%);
  width: 104px;
  height: 104px;
  margin: 0;
  padding: 0;
  border: 2px solid oklch(0.925 0.028 82 / 0.92);
  border-radius: 50%;
  background: var(--deep);
  color: oklch(0.945 0.022 83);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  cursor: pointer;
  box-shadow: 4px 5px 0 oklch(0.1 0.028 164 / 0.4);
  animation: radial-hub-pop 240ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
  touch-action: none;
  user-select: none;
}

.radial-close.dragging { cursor: grabbing; }
.radial-close:active:not(:disabled) { transform: translate(50%, 50%); }
.radial-close[aria-expanded="false"] .radial-close-label { font-size: 10px; letter-spacing: .08em; }

.radial-close:hover:not(:disabled) {
  background: var(--deep-soft);
}

.radial-close:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

.radial-close-ring {
  position: absolute;
  inset: 5px;
  border: 1.5px dashed oklch(0.925 0.028 82 / 0.45);
  border-radius: 50%;
  pointer-events: none;
}

.radial-close-x svg {
  width: 18px;
  height: 18px;
}

.radial-close-label {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.56rem;
  font-weight: 850;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

@keyframes radial-hub-pop {
  from {
    opacity: 0;
    transform: translate(50%, 50%) scale(0.72);
  }
  to {
    opacity: 1;
    transform: translate(50%, 50%) scale(1);
  }
}

/* The readout card: a paper plaque that narrates the hovered or focused
   satellite. It anchors near the radial on wide screens and hugs the lower
   left corner on phones (the satellite arc stays clear of it). */
.radial-readout {
  position: fixed;
  left: max(10px, calc(100vw - 700px));
  bottom: 12px;
  width: min(320px, calc(100vw - 176px));
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px 13px;
  border: 1px solid oklch(0.45 0.05 70);
  background: var(--paper);
  box-shadow: 5px 6px 0 oklch(0.18 0.04 120 / 0.3);
  animation: backdrop-in 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.radial-readout-row {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 20px;
}

.radial-readout-row strong {
  font-size: 0.95rem;
  font-weight: 750;
  color: var(--ink);
}

.radial-readout-row .radial-pip {
  width: 9px;
  height: 13px;
  border-radius: 2.5px;
}

.radial-readout-note {
  margin-left: auto;
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.62rem;
  font-weight: 750;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.radial-readout-status {
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.6rem;
  font-weight: 850;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.radial-readout-status.blocked {
  color: oklch(0.5 0.16 40);
}

/* The signature move: on open the wedges pop out of the hub, rotating flat,
   and the satellites deal onto the arc nearest-first. One-shot (the .opening
   class drops after the deal); switching wedges replays only the satellites. */
.action-radial.opening .radial-wedge {
  transform-box: view-box;
  transform-origin: 450px 424px;
  animation: radial-wedge-pop 320ms cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
  animation-delay: calc(var(--wedge-index, 0) * 45ms);
}

@keyframes radial-wedge-pop {
  from {
    opacity: 0;
    transform: scale(0.55) rotate(9deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.action-radial.opening .radial-wedge-tag {
  animation: radial-tag-in 320ms ease-out backwards;
  animation-delay: calc(var(--wedge-index, 0) * 45ms + 60ms);
}

@keyframes radial-tag-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Dynamic satellites animate whenever they are (re)built — opening and wedge
   switches both deal fresh buttons. The static utilities replay via the
   .dealt class hud.js re-applies when they return to the arc. */
.radial-sats:not(.radial-menu-sats) .radial-sat,
.radial-menu-sats.dealt .radial-sat {
  animation: radial-sat-pop 300ms cubic-bezier(0.2, 1.4, 0.4, 1) backwards;
  animation-delay: calc(55ms + var(--sat-index, 0) * 50ms);
}

@keyframes radial-sat-pop {
  from {
    opacity: 0;
    transform: translate(50%, 50%) scale(0.3);
  }
  to {
    opacity: 1;
    transform: translate(50%, 50%) scale(1);
  }
}

/* A rebuild that only refreshes data on the same wedge (hud.js sets no-deal)
   keeps the tokens still — the deal is for wedge switches, not for a docked
   panel's side effects. */
.radial-sats.no-deal .radial-sat {
  animation: none;
}

/* =============================================================
   Docked dialogs. A dialog spawned from a radial satellite docks beside the
   wheel as an extension of it: the radial stays open and interactive (no
   second scrim), the spawning satellite inverts to the hub's deep-teal
   medallion, and a dashed tether runs from the CLOSE hub to the panel.
   hud.js owns the lifecycle (swap in place, close together) and computes the
   --radial-dock-* offsets from the live arc geometry. */
.radial-sat.active .radial-sat-token {
  background: var(--deep);
  border-color: oklch(0.925 0.028 82 / 0.92);
  color: oklch(0.945 0.022 83);
}

.radial-sat.active .radial-sat-token .build-icon,
.radial-sat.active .radial-sat-icon {
  color: oklch(0.945 0.022 83);
}

.radial-sat.active .radial-sat-label {
  color: oklch(0.99 0.012 83);
}

/* The tether shares the guide arc's drifting-dash vocabulary, reversed so the
   motion reads hub-to-panel. hud.js draws the path per render. */
.radial-tether {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.radial-tether.hidden {
  display: none;
}

.radial-tether path {
  fill: none;
  stroke: oklch(0.945 0.022 83 / 0.55);
  stroke-width: 1.5;
  stroke-dasharray: 3 8;
  animation: radial-dash 7s linear infinite reverse;
}

/* The panel takes over the readout card's narration while it is docked. */
.action-radial.docked .radial-readout {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .action-radial,
  .action-radial.opening .radial-wedge,
  .action-radial.opening .radial-wedge-tag,
  .radial-sats:not(.radial-menu-sats) .radial-sat,
  .radial-menu-sats.dealt .radial-sat,
  .radial-close,
  .radial-readout {
    animation: none;
  }

  .radial-guide,
  .radial-tether path {
    animation: none;
  }

  .modal-backdrop.radial-docked.dock-swap .trade-dialog > *,
  .log-popover.radial-docked.dock-swap > *,
  .directions-panel.radial-docked.dock-swap > * {
    animation: none;
  }
}

/* Dock ACTIONS toggle: orange primary while it holds turn actions, paper
   secondary when it is only the menu handle. The compound selector overrides
   .action-button's icon/label grid (defined later in the file) so the plain
   "Actions" label centers instead of sitting in the 36px icon column. */
.action-button.actions-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 16px;
  font-weight: 750;
  text-align: center;
}

/* On the human's action turn ACTIONS is the primary CTA: orange, the one thing
   the player reaches for most. */
.actions-toggle:not(.menu-only) {
  background: var(--accent);
  color: oklch(0.96 0.02 83);
  border: 1px solid var(--accent-strong);
  box-shadow: 3px 4px 0 oklch(0.33 0.1 42 / 0.2);
}

/* Off-turn it is only the menu handle: quiet paper. */
.actions-toggle.menu-only {
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: 3px 4px 0 oklch(0.24 0.04 67 / 0.14);
}

.actions-toggle[aria-expanded="true"] {
  box-shadow: inset 0 0 0 2px oklch(0.9 0.08 76 / 0.55), 3px 4px 0 oklch(0.24 0.04 67 / 0.16);
}

.end-turn-button {
  width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
}

/* Zone 1: full-bleed board. Fit insets tell the canvas how much of each edge
   the overlays cover, so the auto-fitted board centers in the visible window.
   `env()` inside calc() resolves through getComputedStyle for the fit math. */
.board-region {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background:
    linear-gradient(oklch(0.83 0.05 80 / 0.08) 1px, transparent 1px),
    linear-gradient(90deg, oklch(0.83 0.05 80 / 0.08) 1px, transparent 1px),
    radial-gradient(circle at 74% 16%, oklch(0.68 0.12 75 / 0.22), transparent 23rem),
    linear-gradient(142deg, oklch(0.245 0.07 163), oklch(0.17 0.05 165));
  background-size: 54px 54px, 54px 54px, auto, auto;
  --board-safe-top: calc(96px + env(safe-area-inset-top, 0px));
  --board-safe-right: calc(12px + env(safe-area-inset-right, 0px));
  /* --dock-clearance is measured from the live dock height (game.js) so the
     board never hides behind a taller dock, e.g. C&K's commodity hand row. */
  --board-safe-bottom: calc(var(--dock-clearance, 128px) + 12px);
  --board-safe-left: calc(12px + env(safe-area-inset-left, 0px));
}

/* Zone 3: top-center status banner. Holds #turnTitle + #phaseHelp; never has
   its own textContent written (that would wipe the children). */
.status-banner {
  position: fixed;
  z-index: 8;
  top: calc(10px + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: min(680px, calc(100vw - 132px));
  min-height: 42px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px 4px;
  border: 1px solid oklch(0.65 0.07 72);
  border-radius: var(--radius);
  background: oklch(0.97 0.03 83 / 0.96);
  color: var(--ink);
  padding: 9px 12px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.78rem;
  font-weight: 650;
  line-height: 1.45;
  box-shadow: 6px 7px 0 oklch(0.12 0.03 164 / 0.18);
}

.status-banner #turnTitle {
  font-family: "Arial Narrow", "Aptos Display", "Segoe UI", sans-serif;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.status-banner #phaseHelp {
  font-weight: 500;
}

.status-banner #phaseHelp:not(:empty) {
  margin-left: 8px;
}

.status-banner.game-won {
  border-color: oklch(0.68 0.14 88);
  background: oklch(0.95 0.06 88);
  box-shadow: 6px 7px 0 oklch(0.45 0.1 80 / 0.25);
}

/* Event toasts: things done TO you while another seat acts. Centered below
   the status banner. */
.board-notices {
  position: fixed;
  z-index: 8;
  top: calc(var(--board-safe-top, 96px) + 8px);
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  gap: 7px;
  max-width: min(420px, calc(100vw - 34px));
  pointer-events: none;
}

/* Zone 2 + 7: left column stacking the roster over the expansion drawer.
   pointer-events pass through the gaps so board panning still works there. */
.hud-left {
  position: fixed;
  z-index: 8;
  top: calc(8px + env(safe-area-inset-top, 0px));
  left: calc(8px + env(safe-area-inset-left, 0px));
  /* The top-right utility cluster is gone, so the roster strip owns the full
     width of the top band (it scrolls horizontally when the cards overflow). */
  right: calc(8px + env(safe-area-inset-right, 0px));
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}

.hud-left > * {
  pointer-events: auto;
}

.player-roster {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.roster-heading {
  display: none;
}

.player-list {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
}

.player-list::-webkit-scrollbar {
  display: none;
}

/* Bottom dock (zone 5) + action sheet (zone 6). The dock is a fixed footer;
   the sheet sits above the dock bar and is display:none until it is either
   auto-shown (.inline, non-action phases) or toggled open (.open). */
.bottom-dock {
  position: fixed;
  z-index: 10;
  left: 0;
  right: 0;
  bottom: 0;
  padding:
    8px
    calc(10px + env(safe-area-inset-right, 0px))
    calc(8px + env(safe-area-inset-bottom, 0px))
    calc(10px + env(safe-area-inset-left, 0px));
  /* Transparent: the dock is just its floating controls, so the board shows
     through the gaps. The container passes pointer events through; only the
     visible leaf controls below opt back in, so clicking or dragging the board
     between/around the controls reaches the canvas. */
  background: transparent;
  pointer-events: none;
}

/* Visible, opaque controls capture clicks; the transparent containers that
   span the empty gaps do not. */
.bottom-dock button,
.bottom-dock .dice-readout,
.bottom-dock .compact-resource-card {
  pointer-events: auto;
}

.dock-bar {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  grid-template-areas:
    "hand hand hand"
    "dice history primary";
  align-items: center;
  gap: 8px;
}

.dock-bar .turn-hand {
  grid-area: hand;
}

.dock-bar #diceReadout {
  grid-area: dice;
}

.dock-history {
  grid-area: history;
  display: flex;
  gap: 6px;
}

.dock-history button {
  width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
}

.dock-primary {
  grid-area: primary;
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  flex-wrap: wrap;
  min-width: 0;
}

.dock-primary button {
  min-height: 44px;
}

@media (max-width: 600px) {
  .dock-primary [data-action="cancel"] { width: 44px; padding: 0; display: grid; place-items: center; }
  .dock-primary [data-action="cancel"] > span:last-child { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

@media (max-width: 420px) {
  .dock-bar:has(.event-die) { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "hand hand" "dice history" "primary primary"; }
  .dock-bar:has(.event-die) .dock-history { justify-content: flex-end; }
}

.action-sheet {
  display: none;
  margin-bottom: 8px;
}

.action-sheet.inline {
  display: block;
}

/* Auto-shown contextual controls (setup, hazard, resource choice, skip) sit as
   a compact centered cluster of content-width buttons, not a full-width grid. */
.action-sheet.inline .control-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 7px;
}

.action-sheet.inline .control-grid > * {
  grid-column: auto;
  width: auto;
  min-width: 0;
}
.action-sheet.inline .control-grid > button:not(.action-button) { min-height: 44px; border-radius: 10px; }

/* Expansion drawer (zone 7). Content styles for #modulePanels stay below with
   the other module-panel rules; this only governs the drawer shell. */
.module-drawer {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: 320px;
}

.module-drawer.hidden {
  display: none;
}

.module-drawer-toggle {
  align-self: flex-start;
  min-height: 40px;
  padding: 0 12px;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 850;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

/* Keep the paper control legible before and during the mobile drawer transition. */
.module-drawer-toggle:hover:not(:disabled),
.module-drawer-toggle:focus-visible {
  background: #eee5d2;
  color: #174c40;
}

.module-drawer:not(.open) .module-panels {
  display: none;
}

.module-drawer.open .module-panels {
  display: block;
  max-height: 40vh;
  overflow-y: auto;
  margin-top: 6px;
  padding: 10px;
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: 6px 7px 0 oklch(0.24 0.04 67 / 0.12);
}

@media (min-width: 1040px) {
  .hud-left {
    top: calc(16px + env(safe-area-inset-top, 0px));
    left: calc(16px + env(safe-area-inset-left, 0px));
    right: auto;
    bottom: calc(var(--dock-clearance, 128px) + 16px);
    width: 288px;
    gap: 12px;
  }

  .roster-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    color: oklch(0.92 0.03 82);
    text-shadow: 0 1px 2px oklch(0.12 0.03 164 / 0.6);
    flex-shrink: 0;
    padding-inline: 6px;
  }

  .roster-heading strong {
    color: oklch(0.92 0.03 82);
  }

  .player-list {
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    min-height: 0;
    padding: 4px 6px 14px;
    scroll-padding-block: 4px 14px;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: #d7c6a199 transparent;
  }

  .player-list::-webkit-scrollbar { display: block; width: 6px; }
  .player-list::-webkit-scrollbar-thumb { background: #d7c6a199; border-radius: 6px; }
  .player-chip-sub { flex-wrap: wrap; gap: 4px 12px; }

  .player-roster { min-height: 0; max-height: 100%; flex-shrink: 0; }
  .hud-left:not(:has(.module-drawer.open:not(.hidden))) .player-roster { max-height: 100%; }

  .status-banner {
    left: calc(50% + 160px);
    max-width: min(680px, calc(100vw - 356px));
  }

  .board-region {
    --board-safe-top: calc(80px + env(safe-area-inset-top, 0px));
    --board-safe-left: 320px;
    --board-safe-right: 24px;
    /* The dock is transparent and its controls hug the far corners, so the
       board can grow down into the bottom band; only its lower ocean sits
       behind the floating controls. */
    --board-safe-bottom: 40px;
  }

  .dock-bar {
    grid-template-columns: 1fr auto auto auto;
    grid-template-areas: "hand dice history primary";
    max-width: 1280px;
    margin: 0 auto;
    gap: 12px;
  }

  .action-sheet {
    position: relative;
    max-width: 1280px;
    margin: 0 auto 8px;
  }

  .module-drawer {
    max-width: none;
    min-height: 0;
  }

  .module-drawer.open { flex: 0 1 auto; }
  .module-drawer-toggle { flex-shrink: 0; }

  .module-drawer.open .module-panels {
    max-height: none;
    min-height: 0;
    flex: 0 1 auto;
    border-radius: 12px;
  }
}

/* Below the desktop column layout the roster is a horizontal chip row across
   the top, so the status banner drops beneath it (full width) instead of
   fighting it for the top-center strip. */
@media (max-width: 1039px) {
  /* The roster/banner/dock float over transparent gaps, so the board fills the
     phone screen and only its outer ocean tucks under them — a small inset
     keeps the width the fit constraint so the island fills the screen instead
     of floating small in the middle. */
  .board-region {
    --board-safe-top: calc(76px + env(safe-area-inset-top, 0px));
    --board-safe-left: calc(4px + env(safe-area-inset-left, 0px));
    --board-safe-right: calc(4px + env(safe-area-inset-right, 0px));
    --board-safe-bottom: calc(var(--dock-clearance, 128px) * 0.55 + 8px);
  }

  .status-banner {
    top: calc(56px + env(safe-area-inset-top, 0px));
    left: calc(8px + env(safe-area-inset-left, 0px));
    right: calc(8px + env(safe-area-inset-right, 0px));
    transform: none;
    width: auto;
    max-width: none;
  }

  .board-notices {
    top: calc(var(--board-safe-top, 112px) + 4px);
  }

  .module-drawer { margin-top: calc(var(--status-height, 70px) + 8px); }
  .module-drawer-toggle { min-height: 44px; }
  .module-drawer.open .module-panels { max-height: min(40vh, max(100px, calc(100dvh - var(--dock-clearance, 128px) - var(--status-height, 70px) - 90px))); }
}

/* Compact landscape phones: keep the board breathing room by shrinking the
   dock to a single row and trimming the fit insets. */
@media (max-height: 480px) {
  .board-region {
    --board-safe-top: calc(56px + env(safe-area-inset-top, 0px));
  }

  .dock-bar {
    grid-template-columns: 1fr auto auto auto;
    grid-template-areas: "hand dice history primary";
  }
}

/* Module popover for a board piece's action menu (knight orders, ship
   orders). Opens centered over the board so it never covers the selected
   piece; any non-button surface is a drag handle. */
.board-popover {
  position: absolute;
  z-index: 5;
  min-width: 190px;
  max-width: 240px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px;
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: 3px 4px 0 oklch(0.22 0.04 68 / 0.22);
  cursor: grab;
  touch-action: none;
}

.board-popover.dragging {
  cursor: grabbing;
}

.board-popover button {
  cursor: pointer;
}

.board-popover.hidden {
  display: none;
}

.board-popover-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 2px;
}

.board-notice {
  display: flex;
  align-items: center;
  gap: 9px;
  border: 1px solid oklch(0.52 0.14 40);
  border-radius: var(--radius);
  background: oklch(0.34 0.09 38 / 0.97);
  color: oklch(0.97 0.02 80);
  padding: 9px 12px;
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1.35;
  box-shadow: 5px 6px 0 oklch(0.12 0.03 164 / 0.22);
  animation: notice-in 280ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}

.board-notice-icon {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  color: oklch(0.88 0.07 70);
}

.board-notice-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

@keyframes notice-in {
  from {
    opacity: 0;
    transform: translateX(-14px);
  }
}

/* Victory celebration: confetti canvas over the whole board region plus a
   scorepad plaque. The layer itself ignores the pointer so the table stays
   browsable behind the falling paper; only the plaque is interactive. */
.celebration-layer {
  position: fixed;
  z-index: 24;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.confetti-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.victory-plaque {
  position: relative;
  pointer-events: auto;
  width: min(380px, calc(100% - 48px));
  max-height: calc(100% - 32px);
  overflow: auto;
  border: 1px solid oklch(0.54 0.055 68);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: 12px 14px 0 oklch(0.15 0.035 67 / 0.22);
  padding: 26px 30px 24px;
  text-align: center;
  animation: victory-rise 520ms cubic-bezier(0.16, 1, 0.3, 1) 140ms backwards;
}

/* Inner gold rule, like the certificate line on the physical award tiles. */
.victory-plaque::before {
  content: "";
  position: absolute;
  inset: 7px;
  border: 1.5px solid oklch(0.74 0.14 78 / 0.65);
  pointer-events: none;
}

.victory-plaque .eyebrow {
  animation: victory-fade-up 380ms cubic-bezier(0.22, 1, 0.36, 1) 300ms backwards;
}

.victory-crown {
  display: block;
  width: 56px;
  height: 56px;
  margin: 10px auto 2px;
  animation: victory-crown-pop 460ms cubic-bezier(0.34, 1.3, 0.5, 1) 360ms backwards;
}

.victory-crown svg {
  display: block;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 2px 0 oklch(0.45 0.1 80 / 0.3));
}

.victory-plaque h2 {
  margin: 0;
  font-family: "Arial Narrow", "Aptos Display", "Segoe UI", sans-serif;
  font-size: 2.55rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  line-height: 0.95;
  text-transform: uppercase;
  animation: victory-fade-up 380ms cubic-bezier(0.22, 1, 0.36, 1) 420ms backwards;
}

.victory-line {
  margin: 5px 0 0;
  color: var(--muted);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.05rem;
  font-style: italic;
  animation: victory-fade-up 380ms cubic-bezier(0.22, 1, 0.36, 1) 480ms backwards;
}

.victory-standings {
  margin-top: 17px;
  animation: victory-fade-up 380ms cubic-bezier(0.22, 1, 0.36, 1) 540ms backwards;
}

.victory-rows {
  list-style: none;
  margin: 7px 0 0;
  padding: 0;
}

.victory-row {
  display: flex;
  align-items: center;
  gap: 9px;
  border-top: 1px solid oklch(0.71 0.048 72 / 0.55);
  padding: 7px 8px;
  font-size: 0.92rem;
}

.victory-row:first-child {
  border-top: 0;
}

.victory-row-winner {
  background: oklch(0.95 0.06 88);
  font-weight: 800;
}

.victory-row-name {
  flex: 1;
  min-width: 0;
  text-align: left;
  font-weight: 700;
}

.victory-row-score {
  font-family: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, monospace;
  font-size: 0.8rem;
  font-weight: 850;
  white-space: nowrap;
}

.victory-row-label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.victory-actions {
  display: grid;
  gap: 9px;
  margin-top: 18px;
  animation: victory-fade-up 380ms cubic-bezier(0.22, 1, 0.36, 1) 600ms backwards;
}

@media (orientation: landscape) and (max-height: 500px) and (max-width: 1100px) {
  .victory-plaque {
    display: grid;
    grid-template-columns: minmax(0, .95fr) minmax(0, 1.25fr);
    gap: 10px 20px;
    width: min(760px, calc(100% - 32px));
    max-height: calc(100% - 24px);
    padding: 14px 24px;
  }
  .victory-heading { align-self: center; min-width: 0; }
  .victory-plaque .eyebrow { margin: 0 0 8px; font-size: .65rem; }
  .victory-plaque h2 { font-size: 1.7rem; line-height: 1; letter-spacing: .025em; }
  .victory-crown { width: 36px; height: 36px; margin: 0 auto 7px; }
  .victory-line { font-size: .85rem; line-height: 1.2; margin-top: 9px; }
  .victory-standings { margin-top: 0; align-self: center; min-width: 0; }
  .victory-row { min-height: 30px; padding: 4px 6px; gap: 6px; font-size: .82rem; }
  .victory-row-score { font-size: .75rem; }
  .victory-row-detail { display: block; font-size: .65rem; line-height: 1.1; }
  .victory-actions { grid-column: 1 / -1; grid-template-columns: 1fr 1fr; margin-top: 0; }
  .victory-actions button { min-height: 44px; padding: 7px 12px; }
  .victory-actions .wide { grid-column: auto; }
}

@keyframes victory-rise {
  from {
    opacity: 0;
    transform: translateY(26px) scale(0.96);
  }
}

@keyframes victory-fade-up {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

@keyframes victory-crown-pop {
  from {
    opacity: 0;
    transform: scale(0.3) rotate(-10deg);
  }
}

.board {
  width: 100%;
  height: 100%;
  min-height: 0;
  display: block;
  cursor: grab;
  touch-action: none;
  user-select: none;
  /* Mirror the --board-safe-* insets onto scroll-margin so the fit code can
     read them resolved to px (custom-property calc()/env() values never resolve
     via getComputedStyle). scroll-margin is inert on a canvas. */
  scroll-margin-top: var(--board-safe-top, 28px);
  scroll-margin-right: var(--board-safe-right, 28px);
  scroll-margin-bottom: var(--board-safe-bottom, 28px);
  scroll-margin-left: var(--board-safe-left, 28px);
}

/* Zone 8: board view tools, anchored bottom-right above the dock. */
/* Board view tools collapse to a single lens; hover (pointer) or tap (touch)
   fans out zoom-out / reset / zoom-in, which fold back after a short idle. Most
   play is trackpad/pinch, so the explicit controls stay out of the way. */
.board-tools {
  position: absolute;
  z-index: 3;
  bottom: calc(var(--dock-clearance) + 12px);
  right: calc(12px + env(safe-area-inset-right, 0px));
}

.board-tools .zoom-toggle {
  width: 42px;
  min-height: 42px;
  padding: 0;
  border: 1px solid oklch(0.62 0.065 74);
  background: oklch(0.96 0.032 83 / 0.96);
  box-shadow: 5px 6px 0 oklch(0.12 0.03 164 / 0.18);
}

.board-tools.expanded .zoom-toggle {
  border-color: var(--accent);
}

/* The fan sits to the left of the lens (absolute, so the lens stays compact and
   the fan never reflows the board). Only opacity/transform animate. */
.board-tools-fan {
  position: absolute;
  right: calc(100% + 6px);
  top: 50%;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px;
  border: 1px solid oklch(0.62 0.065 74);
  border-radius: var(--radius);
  background: oklch(0.96 0.032 83 / 0.96);
  box-shadow: 5px 6px 0 oklch(0.12 0.03 164 / 0.18);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-50%) translateX(8px);
  transition:
    opacity 160ms ease,
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear 220ms;
}

.board-tools.expanded .board-tools-fan {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(-50%) translateX(0);
  transition:
    opacity 160ms ease,
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s;
}

.board-tools-fan .icon-button {
  width: 36px;
  min-height: 34px;
  padding: 0;
}

@media (prefers-reduced-motion: reduce) {
  .board-tools-fan {
    transition: none;
  }
}

/* .panel / .panel-heading survive for the log popover and the hidden legacy
   trade/dev hosts. */
.panel {
  border: 0;
  background: transparent;
  box-shadow: none;
  padding: 13px;
}

.panel-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}

.panel-heading strong {
  font-size: 0.98rem;
}

/* Dice readout lives in the dock; tap-to-roll keeps the orange CTA styling. */
.dice-readout {
  min-width: 92px;
  min-height: 56px;
  display: grid;
  place-items: center;
  /* No container chrome: the dice pair and total coin have their own faces and
     float directly over the board. The roll CTA below reinstates the button
     look when a roll is actually available. */
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 1.7rem;
  font-weight: 850;
}

.dice-readout.roll-action {
  border-color: var(--accent);
  background: var(--accent);
  color: oklch(0.96 0.02 83);
  cursor: pointer;
  box-shadow: inset 0 0 0 1px oklch(0.9 0.08 76 / 0.48), 5px 5px 0 oklch(0.33 0.1 42 / 0.18);
}

.dice-readout.roll-action:hover {
  background: var(--accent-strong);
  transform: translateY(-1px);
}

.dice-readout.roll-action .dice-placeholder {
  color: oklch(0.985 0.006 150);
}

.dice-readout.roll-action:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.turn-hand {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(calc(var(--hand-columns, 5) + 1), minmax(44px, 64px));
  align-items: start;
  gap: 5px;
  max-width: 400px;
  min-width: 0;
}
.turn-hand:not(:has(.dev-hand-card)) { grid-template-columns: minmax(0, 1fr); }

.hand-resource-rows {
  grid-column: 1 / -2;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.turn-hand:not(:has(.dev-hand-card)) .hand-resource-rows { grid-column: 1 / -1; }
.turn-hand .hand-divider { display: none; }

.hand-resource-rows::-webkit-scrollbar {
  display: none;
}

.compact-hand-row {
  display: grid;
  /* Rows share catalog-driven columns; development cards stay outside the
     scrolling resources so their control is always reachable. */
  grid-template-columns: repeat(var(--hand-columns, 5), minmax(44px, 64px));
  align-items: stretch;
  gap: 5px;
  margin-top: 6px;
}

.compact-hand-row:first-child {
  margin-top: 0;
}

/* Coins and other non-card inventories stay readable without consuming a
   whole card row in the board's usable height. */
.compact-currency-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.compact-currency { display: flex; align-items: center; gap: 5px; min-height: 28px; padding: 2px 9px 2px 5px; color: var(--paper); background: rgba(0, 0, 0, .2); border: 1px solid rgba(243, 229, 191, .24); border-radius: 20px; font-size: 12px; }
.compact-currency strong { font-size: 16px; }
.compact-currency .resource-coin { width: 20px; height: 20px; margin: 0; }



.trade-hand-row {
  display: grid;
  grid-template-columns: repeat(5, 56px);
  justify-content: center;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
}

.trade-hand-row.summary {
  grid-template-columns: repeat(auto-fit, 56px);
}

/* The bank tab's hand rides one compact strip in the slot where the player
   trade seats its rival chips, so the two panels share a footprint and the
   docked swap between them barely morphs. Rates live on the give tokens. */
.bank-hand-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding-top: 4px;
}

.bank-hand-strip .sub-label {
  white-space: nowrap;
}

.bank-hand-rows {
  display: grid;
  gap: 4px;
}

.bank-hand-strip .trade-hand-row {
  margin-top: 0;
  grid-template-columns: repeat(5, 52px);
}

.bank-hand-strip .compact-resource-card {
  min-height: 52px;
}

/* Resource card faces: a terrain-colored card with an ivory resource coin,
   echoing the board's harbor tokens. */
.compact-resource-card {
  min-width: 0;
  min-height: 64px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  border: 1px solid oklch(0.2 0.035 68 / 0.55);
  border-radius: 4px;
  color: oklch(0.98 0.006 80);
  padding: 6px 2px 5px;
  background-image: linear-gradient(oklch(1 0 0 / 0.14), oklch(0.2 0.05 70 / 0.08));
  box-shadow: inset 0 0 0 1px oklch(0.98 0.006 80 / 0.16), 2px 3px 0 oklch(0.22 0.04 68 / 0.14);
}

.resource-coin {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid #a99a7d;
  border-radius: 50%;
  background: #f6eed8;
  filter: drop-shadow(0 1px 0 oklch(0.2 0.04 60 / 0.3));
}


.turn-hand .compact-resource-card { height: 84px; grid-template-rows: 26px 18px 22px; align-content: center; }
.turn-hand .compact-resource-card > span:last-child { display: grid; align-items: center; }
@media (max-height: 480px) and (max-width: 1039px) {
  .turn-hand .compact-resource-card { height: 58px; grid-template-rows: 20px 22px; }
}

.resource-coin svg {
  display: block;
  width: 78%;
  height: 78%;
}

.compact-resource-card strong {
  font-size: 1.06rem;
  line-height: 1;
}

.compact-resource-card span {
  max-width: 100%;
  overflow: hidden;
  font-size: 0.62rem;
  font-weight: 860;
  line-height: 1.1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compact-resource-card > span:last-child { white-space: normal; overflow: visible; overflow-wrap: normal; text-align: center; }
@media (max-width: 360px) and (min-height: 481px) {
  .turn-hand .compact-resource-card > span:last-child { font-size: 9.5px; }
}

.compact-resource-card.terrain-hills,
.trade-move-card.terrain-hills,
.trade-token.terrain-hills,
.resource-choice.terrain-hills,
.cost-resource-pill.terrain-hills,
.radial-pip.terrain-hills {
  background-color: oklch(0.55 0.13 40);
}

.compact-resource-card.terrain-forest,
.trade-move-card.terrain-forest,
.trade-token.terrain-forest,
.resource-choice.terrain-forest,
.cost-resource-pill.terrain-forest,
.radial-pip.terrain-forest {
  background-color: oklch(0.45 0.09 148);
}

.compact-resource-card.terrain-pasture,
.trade-move-card.terrain-pasture,
.trade-token.terrain-pasture,
.resource-choice.terrain-pasture,
.cost-resource-pill.terrain-pasture,
.radial-pip.terrain-pasture {
  background-color: oklch(0.66 0.1 122);
  color: oklch(0.2 0.025 122);
}

.compact-resource-card.terrain-fields,
.trade-move-card.terrain-fields,
.trade-token.terrain-fields,
.resource-choice.terrain-fields,
.cost-resource-pill.terrain-fields,
.radial-pip.terrain-fields {
  background-color: oklch(0.75 0.12 84);
  color: oklch(0.24 0.018 68);
}

.compact-resource-card.terrain-mountains,
.trade-move-card.terrain-mountains,
.trade-token.terrain-mountains,
.resource-choice.terrain-mountains,
.cost-resource-pill.terrain-mountains,
.radial-pip.terrain-mountains {
  background-color: oklch(0.52 0.035 245);
}

.owned-ports {
  display: grid;
  gap: 5px;
  margin-top: 7px;
}

.owned-port-list {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

/* Harbor chips: ivory tokens matching the board's port badges. */
.port-chip {
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid oklch(0.62 0.06 70);
  border-radius: 999px;
  background: oklch(0.965 0.025 84);
  color: var(--ink);
  padding: 2px 9px 2px 3px;
  font-size: 0.68rem;
  font-weight: 780;
  line-height: 1;
  box-shadow: 1.5px 2px 0 oklch(0.25 0.055 67 / 0.12);
}

.port-chip .resource-coin {
  width: 21px;
  height: 21px;
  filter: none;
}

.port-chip strong {
  font-size: 0.74rem;
  font-family: Georgia, "Times New Roman", serif;
}

.port-chip.empty {
  background: oklch(0.93 0.022 82);
  border-color: var(--line);
  box-shadow: none;
  color: var(--muted);
  padding: 2px 9px;
}

.hand-divider {
  width: 1px;
  height: 40px;
  background: var(--line);
}

/* Bonus award tiles: gold-trimmed cardboard, like the physical tiles. */
.award-tile {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid oklch(0.62 0.13 80);
  border-radius: 4px;
  background: oklch(0.965 0.04 86);
  padding: 4px 9px 4px 5px;
  box-shadow: 0 0 0 1.5px oklch(0.74 0.14 78 / 0.4), 2px 2.5px 0 oklch(0.25 0.055 67 / 0.16);
}

.award-tile-art {
  display: block;
  width: 30px;
  height: 30px;
}

.award-tile-art svg {
  display: block;
  width: 100%;
  height: 100%;
}

.award-tile-copy {
  display: grid;
  line-height: 1.2;
}

.award-tile-copy strong {
  font-size: 0.74rem;
}

.award-tile-copy small {
  color: oklch(0.45 0.08 70);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.66rem;
  font-weight: 800;
}

.player-award {
  display: inline-block;
  width: 17px;
  height: 17px;
  margin-left: 5px;
  vertical-align: -3px;
}

.player-award svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* The development deck reads as a card back: deep teal with a gold-trimmed
   crest coin, same card face dimensions as the resource cards. */
.dev-hand-card {
  width: 100%;
  border-color: oklch(0.16 0.04 160);
  background-color: var(--deep-soft);
  background-image: linear-gradient(oklch(1 0 0 / 0.1), oklch(0.1 0.04 160 / 0.2));
  color: oklch(0.96 0.025 84);
  box-shadow: inset 0 0 0 1px oklch(0.74 0.14 78 / 0.45), 2px 3px 0 oklch(0.22 0.04 68 / 0.14);
}

.dev-hand-card:hover:not(:disabled) {
  background-color: oklch(0.29 0.055 157);
}

.dev-coin {
  display: grid;
  place-items: center;
  background: #f6eed8;
  border: 1px solid oklch(0.55 0.07 70);
  border-radius: 999px;
}

.dev-coin svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: oklch(0.42 0.06 68);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.dice-placeholder {
  color: var(--muted);
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.dice-pair {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

/* Ivory tabletop dice. The tumble plays once per fresh roll: the hud only
   sets .rolling on the render that first shows a new dice object. */
.die {
  position: relative;
  width: 44px;
  height: 44px;
  border: 1px solid oklch(0.74 0.045 78);
  border-radius: 10px;
  background:
    linear-gradient(148deg, oklch(0.985 0.018 84), oklch(0.93 0.03 80));
  box-shadow:
    inset 0 -3px 6px oklch(0.4 0.04 72 / 0.14),
    inset 0 2px 3px oklch(1 0 0 / 0.65),
    0 3px 7px oklch(0.2 0.02 70 / 0.2);
}

.die .pip {
  position: absolute;
  width: 7.5px;
  height: 7.5px;
  border-radius: 999px;
  background: oklch(0.24 0.03 60);
  box-shadow: inset 0 1.4px 1.6px oklch(0.1 0.02 60 / 0.85);
}

/* The classic table pair: one ivory die, one red. */
.die.die-1 {
  border-color: oklch(0.4 0.13 30);
  background:
    linear-gradient(148deg, oklch(0.58 0.19 32), oklch(0.46 0.17 30));
  box-shadow:
    inset 0 -3px 6px oklch(0.2 0.1 30 / 0.4),
    inset 0 2px 3px oklch(0.85 0.08 40 / 0.5),
    0 3px 7px oklch(0.2 0.02 70 / 0.2);
}

.die.die-1 .pip {
  background: oklch(0.97 0.02 84);
  box-shadow: inset 0 1.4px 1.6px oklch(0.75 0.06 60 / 0.9);
}

.die .tl { left: 9px; top: 9px; }
.die .tr { right: 9px; top: 9px; }
.die .ml { left: 9px; top: 18px; }
.die .c { left: 18px; top: 18px; }
.die .mr { right: 9px; top: 18px; }
.die .bl { left: 9px; bottom: 9px; }
.die .br { right: 9px; bottom: 9px; }

.dice-pair.rolling .die-0 {
  animation: die-tumble-a 560ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}

.dice-pair.rolling .die-1 {
  animation: die-tumble-b 640ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}

.dice-pair.rolling .die .pip {
  animation: pip-land 700ms ease-out backwards;
}

@keyframes die-tumble-a {
  from {
    transform: translate(-10px, -26px) rotate(-150deg);
  }
}

@keyframes die-tumble-b {
  from {
    transform: translate(8px, -30px) rotate(120deg);
  }
}

@keyframes pip-land {
  0%,
  55% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

.phase-help {
  display: inline;
}

.phase-help:empty {
  display: none;
}

.control-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
}

.action-button {
  min-height: 58px;
  display: grid;
  /* The trailing auto column holds the pieces-remaining chip; it collapses
     to nothing on buttons without one. */
  grid-template-columns: 36px 1fr auto;
  align-items: center;
  gap: 8px;
  border-color: oklch(0.61 0.06 70);
  background: oklch(0.965 0.025 82);
  color: var(--ink);
  padding: 8px;
  text-align: left;
}

/* Pieces left in the player's supply, pinned to a build button's edge. */
.supply-count {
  align-self: start;
  color: oklch(0.45 0.04 66);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1.4;
}

.action-button:disabled .supply-count {
  color: inherit;
}

.action-button:hover:not(:disabled) {
  border-color: var(--accent);
  background: oklch(0.92 0.07 78);
  box-shadow: inset 0 -3px 0 var(--accent);
}

.action-button.selected {
  border-color: var(--accent);
  background: oklch(0.92 0.07 78);
  box-shadow: inset 0 -3px 0 var(--accent);
}

.cost-link-button {
  min-height: 30px;
  justify-content: center;
  padding: 0 10px;
  font-size: 0.78rem;
}

.build-icon {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid oklch(0.58 0.06 70);
  border-radius: var(--radius);
  background: oklch(0.95 0.04 80);
  color: var(--ink);
  font-size: 0.72rem;
  font-weight: 900;
}

.build-icon svg {
  width: 23px;
  height: 23px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Wooden-piece icons from the asset catalog: drawn art, not stroked glyphs. */
.build-icon.piece-icon {
  border: 0;
  background: transparent;
}

.build-icon.piece-icon svg {
  width: 30px;
  height: 30px;
  fill: revert;
  stroke: revert;
  stroke-width: revert;
  filter: drop-shadow(0 1.5px 0 oklch(0.3 0.04 60 / 0.25));
}

.ship-icon {
  position: relative;
  border: 0;
  background: transparent;
}

.ship-icon::before {
  position: absolute;
  right: 3px;
  bottom: 5px;
  left: 3px;
  height: 7px;
  border: 2px solid currentColor;
  border-top: 0;
  content: "";
  transform: skewX(-24deg);
}

.ship-icon::after {
  position: absolute;
  top: 3px;
  bottom: 8px;
  left: 50%;
  width: 2px;
  background: currentColor;
  box-shadow: 5px 4px 0 -1px currentColor;
  content: "";
}

/* pre-merge artifact: every build icon is flat beige — the themed .build-icon
   background overrode the per-icon backgrounds (and the road icon's gradient
   and pill radius); only clip-paths, height, and icon colors survived.
   Revisit during the redesign */
.road-icon {
  height: 12px;
}

.settlement-icon {
  clip-path: polygon(50% 6%, 94% 42%, 84% 94%, 16% 94%, 6% 42%);
}

.city-icon {
  clip-path: polygon(6% 94%, 6% 38%, 26% 18%, 46% 38%, 46% 94%, 54% 94%, 54% 28%, 76% 6%, 94% 28%, 94% 94%);
}

.dev-icon {
  color: oklch(0.5 0.05 80);
}

.bank-icon {
  color: oklch(0.28 0.06 160);
}

.trade-icon {
  color: oklch(0.32 0.08 165);
}

.cancel-icon {
  color: oklch(0.48 0.012 70);
}

.control-grid button.wide,
.wide {
  grid-column: 1 / -1;
}

.resource-row {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 5px;
}

.resource-pill {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-height: 43px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: oklch(0.97 0.009 72);
}

.resource-pill strong {
  font-size: 1rem;
  line-height: 1;
}

.resource-pill span {
  width: 100%;
  overflow: hidden;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 750;
  text-align: center;
  text-overflow: ellipsis;
}

.choice-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.choice-grid label {
  display: grid;
  gap: 5px;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 800;
}

.resource-input-section {
  display: grid;
  gap: 6px;
  margin-top: 10px;
}

/* Bank give/want cards match the sidebar hand's card dimensions exactly. */
.resource-choice-grid {
  display: grid;
  grid-template-columns: repeat(5, 56px);
  justify-content: center;
  gap: 5px;
}

/* Inside the dark dialogs the bank's give/take choices become satellite
   token discs on the same orbit rows as the player trade: count badge above,
   rate coin below, dashed rim when the trade is out of reach. The orbit wrap
   carries the arc offset and deal animation. */
.trade-dialog .resource-choice {
  width: var(--token-size, 58px);
  height: var(--token-size, 58px);
  min-height: 0;
  border-radius: 50%;
  border-width: 1.5px;
  padding: 0 3px;
  gap: 1px;
  box-shadow: inset 0 0 0 1px oklch(0.98 0.006 80 / 0.2), 4px 5px 0 oklch(0.05 0.015 164 / 0.55);
  transition:
    transform 140ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 140ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 140ms ease;
}

.trade-dialog .resource-choice:hover:not(:disabled) {
  transform: translate(-1px, -2px);
}

.trade-dialog .resource-choice strong {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  min-width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border: 1.5px solid oklch(0.35 0.04 66);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  padding: 0 5px;
  font-size: 0.74rem;
  font-weight: 850;
  line-height: 1;
  pointer-events: none;
  box-shadow: 1px 2px 0 oklch(0.08 0.02 164 / 0.4);
}

.trade-dialog .resource-choice span:last-child {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.5rem;
  font-weight: 850;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.trade-dialog .resource-choice .trade-rate {
  top: auto;
  right: 50%;
  bottom: -11px;
  transform: translateX(50%);
}

.trade-dialog .resource-choice.selected {
  border-color: oklch(0.985 0.006 80);
  box-shadow: inset 0 0 0 1.5px oklch(0.98 0.006 80 / 0.85), 0 0 0 2.5px var(--gold);
}

.trade-dialog .resource-choice:disabled {
  border-style: dashed;
  border-color: oklch(0.6 0.03 75 / 0.7);
  background-image: linear-gradient(oklch(0.4 0.01 80 / 0.55), oklch(0.25 0.02 80 / 0.6));
  box-shadow: none;
  filter: none;
  opacity: 1;
}

.trade-dialog .resource-choice:disabled > :not(.trade-rate) {
  opacity: 0.55;
}

.resource-choice {
  position: relative;
  min-height: 64px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  border-color: oklch(0.2 0.035 68 / 0.55);
  border-radius: 4px;
  color: oklch(0.985 0.006 80);
  padding: 6px 2px 5px;
  background-image: linear-gradient(oklch(1 0 0 / 0.14), oklch(0.2 0.05 70 / 0.08));
  box-shadow: inset 0 0 0 1px oklch(0.98 0.006 80 / 0.16), 2px 3px 0 oklch(0.22 0.04 68 / 0.14);
}

/* Price tag pinned to a give card: your effective rate for that resource.
   Port rates get the gold trim so owned ports stand out at a glance. */
.trade-rate {
  position: absolute;
  z-index: 1;
  top: -8px;
  right: -5px;
  border: 1px solid oklch(0.62 0.06 70);
  border-radius: 999px;
  background: oklch(0.965 0.025 84);
  color: oklch(0.34 0.04 62);
  padding: 1px 6px;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.66rem;
  font-weight: 800;
  line-height: 1.3;
  box-shadow: 1px 1.5px 0 oklch(0.25 0.055 67 / 0.18);
}

.trade-rate-port {
  border-color: oklch(0.62 0.13 80);
  box-shadow: 0 0 0 1.5px oklch(0.74 0.14 78 / 0.55), 1px 1.5px 0 oklch(0.25 0.055 67 / 0.18);
  color: oklch(0.3 0.06 70);
}

.resource-choice-grid {
  padding-top: 6px;
}

.resource-choice strong {
  font-size: 1.06rem;
  line-height: 1;
}

.resource-choice span:last-child {
  overflow: hidden;
  max-width: 100%;
  color: currentColor;
  font-size: 0.62rem;
  font-weight: 860;
  line-height: 1.1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.resource-choice.selected {
  border-color: oklch(0.98 0.006 80);
  box-shadow: inset 0 0 0 2px oklch(0.98 0.006 80 / 0.92), 0 0 0 2px var(--accent);
}

.resource-choice:disabled {
  filter: grayscale(0.35);
}

.bank-icon-row {
  display: grid;
  grid-template-columns: 34px 1fr;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-size: 0.84rem;
}

/* Discard dialog: hand row + discard-pile row in the trading post's card
   language. Five resource columns (no wildcard card here); cards move on
   tap, not drag, so they take the pointer cursor. */
.trade-card-row.discard-cards {
  grid-template-columns: repeat(5, minmax(44px, 56px));
}

.discard-cards .trade-move-card {
  cursor: pointer;
  height: 82px;
  grid-template-rows: 26px 18px 22px;
  align-content: center;
}

.discard-cards .trade-move-card > span { white-space: normal; text-overflow: clip; overflow: visible; }

/* Secondary controls on the teal plaque go quiet: cream outline, no fill. */
.trade-dialog .ghost-button,
.trade-dialog .secondary-button {
  border-color: oklch(0.925 0.028 82 / 0.5);
  background: transparent;
  color: var(--cream);
}

.trade-dialog .ghost-button:hover:not(:disabled),
.trade-dialog .secondary-button:hover:not(:disabled) {
  border-color: oklch(0.925 0.028 82 / 0.9);
  background: oklch(1 0 0 / 0.08);
}

/* The backdrop is a persistent node, so this entrance plays once per open
   (display: none -> grid) and is untouched by re-renders inside the dialog.
   The scrim stays light so the board remains readable behind any dialog. */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  background: oklch(0.15 0.045 160 / 0.24);
  padding: 18px;
  animation: backdrop-in 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes backdrop-in {
  from {
    opacity: 0;
  }
}

/* Docked to the Actions radial: the backdrop stops being a wall — no scrim of
   its own (the radial's is already up) and no pointer trap, so the wheel
   behind stays fully interactive. The panel anchors beside the satellite arc;
   hud.js supplies the offsets from the live geometry. */
.modal-backdrop.radial-docked {
  display: block;
  padding: 0;
  background: none;
  pointer-events: none;
  animation: none;
}

.modal-backdrop.radial-docked .trade-dialog {
  position: absolute;
  right: var(--radial-dock-right, 440px);
  bottom: 88px;
  max-width: var(--radial-dock-max-width, 640px);
  max-height: var(--radial-dock-max-height, calc(100vh - 116px));
  pointer-events: auto;
}

/* The docked frame rises once. While the same panel stays open (dock-settled)
   re-renders hold it still, and swapping panels (dock-swap) morphs the frame
   between the two sizes — hud.js drives the width/height transition inline —
   while the incoming contents fade in. Never a close-and-reopen jolt. */
.modal-backdrop.radial-docked.dock-settled .trade-dialog,
.modal-backdrop.radial-docked.dock-swap .trade-dialog {
  animation: none;
}

/* Same rule one level down, for every dialog docked or not: while the content
   key holds steady (hud.js dialog-settled) an interaction re-render keeps all
   the furniture still — the frame rise, the token deal, the rival-chip rise,
   and the hub pop are opening moves, not tap feedback. Infinite loops (the
   waiting pulse, the orbit dash) live on child elements and keep running. */
.dialog-settled .trade-dialog,
.dialog-settled .trade-token-wrap,
.dialog-settled .trade-response,
.dialog-settled .trade-hub {
  animation: none;
}

.modal-backdrop.radial-docked.dock-swap .trade-dialog > * {
  animation: dock-content-in 180ms ease-out;
}

@keyframes dock-content-in {
  from {
    opacity: 0;
  }
}

/* Viewports without room beside the arc park the panel above the radial. */
.modal-backdrop.radial-docked.dock-top {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 12px;
}

.modal-backdrop.radial-docked.dock-top .trade-dialog {
  position: static;
  max-width: none;
}

/* The log popover and directions drawer dock with the same anchor when
   spawned from the open radial — they are the panel themselves, with no
   backdrop wrapper. Scoped above phone width so the phone layouts win. */
@media (min-width: 681px) {
  .log-popover.radial-docked,
  .directions-panel.radial-docked {
    top: auto;
    right: var(--radial-dock-right, 440px);
    bottom: 88px;
    left: auto;
    z-index: 20;
    max-width: var(--radial-dock-max-width, 640px);
    max-height: var(--radial-dock-max-height, calc(100vh - 116px));
  }

  .log-popover.radial-docked.dock-top,
  .directions-panel.radial-docked.dock-top {
    right: auto;
    bottom: auto;
    left: 50%;
    top: 12px;
    translate: -50%;
  }
}

.log-popover.radial-docked.dock-settled,
.log-popover.radial-docked.dock-swap,
.directions-panel.radial-docked.dock-settled,
.directions-panel.radial-docked.dock-swap {
  animation: none;
}

.log-popover.radial-docked.dock-swap > *,
.directions-panel.radial-docked.dock-swap > * {
  animation: dock-content-in 180ms ease-out;
}

/* Dialogs share the Actions radial's vocabulary: a deep-teal plaque with a
   cream rule, mono protocol headings, and ivory paper insets for anything
   card-shaped. Slightly translucent and draggable by the header, so they
   never wall off the board. */
.trade-dialog {
  --cream: oklch(0.945 0.022 83);
  --cream-muted: oklch(0.87 0.03 84 / 0.85);
  --cream-line: oklch(0.925 0.028 82 / 0.28);
  width: min(700px, 100%);
  max-height: min(820px, calc(100vh - 36px));
  display: flex;
  flex-direction: column;
  border: 2px solid oklch(0.925 0.028 82 / 0.92);
  /* Dialogs are radial extensions: rounded like the wheel's discs, not the
     square setup-screen paper. */
  border-radius: 18px;
  background: oklch(0.175 0.045 161 / 0.95);
  color: var(--cream);
  box-shadow: 6px 7px 0 oklch(0.1 0.028 164 / 0.4);
  overflow: hidden;
  animation: dialog-rise 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes dialog-rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

.trade-dialog-header {
  cursor: default;
}

@media (min-width: 681px) {
  .trade-dialog-header[data-dialog-drag="true"] { cursor: grab; user-select: none; touch-action: none; }
  .trade-dialog-header[data-dialog-drag="true"].dragging { cursor: grabbing; }
}

.trade-dialog-body {
  flex: 1;
  min-height: 0;
}

.trade-dialog.compact {
  width: min(540px, 100%);
}

/* The trading post fits its token arcs (six 58px discs) beside the hub
   medallion; anything wider is empty margin. */
.trade-dialog.trading-post {
  width: min(620px, 100%);
}

.trade-dialog-actions .trade-status-bar {
  flex: 1;
}

/* Discard rows are five cards wide, plus the DISCARD hub beside them. */
.trade-dialog.discard-dialog {
  width: min(508px, 100%);
}

/* No ruled separators between header, body, and actions: the plaque reads as
   one clean surface, like the radial's own chrome. */
.trade-dialog-header,
.trade-dialog-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: transparent;
}

/* Protocol heading: mono uppercase title with a muted side note, echoing the
   radial readout card's voice. */
.trade-dialog-header h2 {
  margin: 0;
  color: var(--cream);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.94rem;
  font-weight: 850;
  letter-spacing: 0.18em;
  line-height: 1.2;
  text-transform: uppercase;
}

.trade-dialog-title {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.trade-dialog-note {
  color: var(--cream-muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.64rem;
  font-weight: 750;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Old eyebrow-above-title headers (module dialogs) inherit the dark voice. */
.trade-dialog-header .eyebrow {
  color: var(--cream-muted);
}

.trade-dialog-buttons {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Round ivory disc controls in the header: the satellite-token vocabulary. */
.trade-dialog .icon-button,
.log-popover .icon-button,
.directions-panel .icon-button {
  width: 32px;
  min-height: 32px;
  border: 1.5px solid oklch(0.5 0.05 70);
  border-radius: 50%;
  background: radial-gradient(circle at 38% 30%, oklch(0.975 0.014 82), oklch(0.935 0.032 81));
  color: var(--ink);
  box-shadow: 2px 3px 0 oklch(0.08 0.02 164 / 0.4);
}

.trade-dialog .icon-button:hover:not(:disabled),
.log-popover .icon-button:hover:not(:disabled),
.directions-panel .icon-button:hover:not(:disabled) {
  border-color: var(--accent);
  background: radial-gradient(circle at 38% 30%, oklch(0.975 0.014 82), oklch(0.955 0.032 81));
}

.trade-dialog-body {
  display: grid;
  gap: 14px;
  overflow-x: hidden;
  overflow-y: auto;
  padding: 16px;
}

.trade-dialog-actions {
  justify-content: flex-end;
  flex-wrap: wrap;
}

/* Body copy on the teal plaque flips to cream; copy inside the ivory paper
   insets below keeps the walnut palette. */
.trade-dialog .sub-label,
.trade-dialog .toast-line,
.trade-dialog .trade-message,
.trade-dialog .panel-heading .label,
.trade-dialog .choice-grid label {
  color: var(--cream-muted);
}

.trade-dialog .panel-heading strong {
  color: var(--cream);
}

.trade-dialog .trade-drop-row .sub-label,
.trade-dialog .trade-drop-row .trade-message,
.trade-dialog .trade-status-bar .sub-label {
  color: var(--muted);
}

/* Buttons share the row and grow to fill it, so a three-button row (Decline /
   Counter / Accept) keeps symmetric left+right padding in the narrow trading
   -post dialog instead of overflowing and clipping the leftmost button. */
.trade-dialog-actions button {
  flex: 1 1 auto;
  min-width: 116px;
}

/* Rival response chips: ivory tiles that flip green when a rival accepts.
   Declined rivals dim behind a dashed rim (the radial's "unavailable"
   grammar); waiting rivals pulse their status line. */
.trade-response-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.trade-response {
  min-height: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 6px;
  border: 1.5px solid oklch(0.5 0.05 70);
  border-radius: 12px;
  background: var(--paper);
  color: var(--ink);
  text-align: center;
  box-shadow: 3px 4px 0 oklch(0.05 0.015 164 / 0.45);
  animation: dialog-rise 200ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
  animation-delay: calc(var(--chip-index, 0) * 60ms);
}

.trade-response-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.74rem;
  font-weight: 850;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.trade-response strong {
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.58rem;
  font-weight: 850;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.trade-response.waiting strong {
  animation: trade-waiting-pulse 1.2s ease-in-out infinite;
}

@keyframes trade-waiting-pulse {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
}

/* A refusal settles into a quiet grey plaque with a rust DECLINED line; the
   seat stays solid, just clearly out of play. */
.trade-response:disabled {
  border-color: oklch(0.62 0.02 76);
  background: oklch(0.72 0.014 80);
  color: oklch(0.34 0.03 68);
  box-shadow: none;
}

.trade-response:disabled strong {
  color: oklch(0.45 0.13 35);
}

/* Rivals still weighing the offer keep their ivory seat. */
.trade-response.waiting:disabled {
  border-color: oklch(0.5 0.05 70);
  background: var(--paper);
  color: var(--ink);
  box-shadow: 3px 4px 0 oklch(0.05 0.015 164 / 0.45);
}

.trade-response.waiting:disabled strong {
  color: var(--muted);
}

.trade-response.accepted {
  border-color: oklch(0.945 0.022 83);
  background: oklch(0.5 0.09 152);
  color: oklch(0.955 0.018 83);
}

.trade-response.accepted strong {
  color: oklch(0.95 0.025 120);
}

.trade-response:hover:not(:disabled) {
  background: var(--paper);
}

.trade-response.accepted:hover:not(:disabled) {
  background: oklch(0.55 0.095 152);
  border-color: oklch(0.98 0.01 83);
}

.trade-response.accepted.selected {
  outline: 2.5px solid var(--gold);
  outline-offset: 2px;
}


.trade-response-terms {
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 720;
  line-height: 1.25;
}

.trade-response.accepted .trade-response-terms {
  color: oklch(0.95 0.02 110);
}

/* Visible score beside each responder: who can afford to get stronger? */
.trade-response-vp {
  display: inline-block;
  margin-left: 4px;
  border-radius: 999px;
  background: oklch(0.89 0.055 78);
  color: var(--ink);
  padding: 1px 7px;
  font-size: 0.68rem;
  font-weight: 850;
  vertical-align: 1px;
}

.trade-message {
  margin: 8px 0 0;
  color: var(--cream-muted, var(--muted));
  font-size: 0.88rem;
  font-weight: 700;
}

.trade-summary-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

/* ==========================================================================
   The trade orbit: the trading post speaks the Actions radial's language.
   Give/want resources ride shallow arcs as terrain-colored token discs (count
   badge above, remove chip below), a drifting dashed guide runs behind each
   arc, and the primary action is a round hub medallion. A paper status bar
   narrates the offer with the radial's cost pips.
   ========================================================================== */
.trade-orbit-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 14px;
  align-items: center;
}

.trade-orbit {
  min-width: 0;
  display: grid;
  gap: 14px;
}

.trade-orbit-zone {
  position: relative;
  display: grid;
  gap: 12px;
  padding: 24px 6px 14px;
}

.trade-orbit-label {
  position: absolute;
  top: 6px;
  left: 6px;
  color: var(--cream-muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.62rem;
  font-weight: 850;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.trade-orbit-row {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 13px;
  padding-top: 12px;
}

/* The guide arc drifts slowly behind the tokens; the second zone's arc runs
   the other way, like the radial's paired rings. */
/* SVG is a replaced element: with only left/right set its intrinsic viewBox
   width (640px) would win and overflow the dialog, so the width is explicit. */
.trade-orbit-arc {
  position: absolute;
  top: 26px;
  left: 12px;
  width: calc(100% - 24px);
  height: 40px;
  overflow: visible;
  pointer-events: none;
}

.trade-orbit-arc path {
  fill: none;
  stroke: oklch(0.945 0.022 83 / 0.32);
  stroke-width: 1.5;
  stroke-dasharray: 2 6;
  animation: trade-orbit-dash 9s linear infinite;
}

.trade-orbit-zone:nth-of-type(2) .trade-orbit-arc path {
  animation-duration: 13s;
  animation-direction: reverse;
}

@keyframes trade-orbit-dash {
  to {
    stroke-dashoffset: -120;
  }
}

/* Each token wrap carries its arc offset (--orbit-dy) and deal order
   (--sat-index) from hud-side markup. */
.trade-token-wrap {
  position: relative;
  flex: 0 0 auto;
  transform: translateY(var(--orbit-dy, 0px));
  animation: trade-token-pop 300ms cubic-bezier(0.2, 1.4, 0.4, 1) backwards;
  animation-delay: calc(40ms + var(--sat-index, 0) * 45ms);
}

@keyframes trade-token-pop {
  from {
    opacity: 0;
    transform: translateY(var(--orbit-dy, 0px)) scale(0.3);
  }
  to {
    opacity: 1;
    transform: translateY(var(--orbit-dy, 0px)) scale(1);
  }
}

.trade-token {
  width: var(--token-size, 58px);
  height: var(--token-size, 58px);
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  margin: 0;
  padding: 0 3px;
  border: 1.5px solid oklch(0.2 0.035 68 / 0.55);
  border-radius: 50%;
  color: oklch(0.985 0.006 80);
  background-image: linear-gradient(oklch(1 0 0 / 0.16), oklch(0.2 0.05 70 / 0.1));
  box-shadow: inset 0 0 0 1px oklch(0.98 0.006 80 / 0.2), 4px 5px 0 oklch(0.05 0.015 164 / 0.55);
  cursor: pointer;
  transition:
    transform 140ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 140ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 140ms ease;
}

.trade-token .resource-coin {
  width: 22px;
  height: 22px;
}

.trade-token-name {
  max-width: 100%;
  overflow: hidden;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.5rem;
  font-weight: 850;
  letter-spacing: 0.06em;
  line-height: 1.1;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.trade-token:hover:not(:disabled):not(.unavailable) {
  transform: translate(-1px, -2px);
  border-color: oklch(0.985 0.006 80);
  box-shadow: inset 0 0 0 1px oklch(0.98 0.006 80 / 0.3), 5px 7px 0 oklch(0.08 0.02 164 / 0.42);
}

.trade-token.active {
  border-color: oklch(0.985 0.006 80);
  box-shadow: inset 0 0 0 1.5px oklch(0.98 0.006 80 / 0.85), 3px 4px 0 oklch(0.08 0.02 164 / 0.4);
}

/* The wildcard "any card" token: ivory stock, walnut ink. */
.trade-token.terrain-any {
  background-color: oklch(0.93 0.024 82);
  background-image: none;
  color: var(--ink);
  border-style: dashed;
  border-color: oklch(0.45 0.045 68);
}

/* Resources you cannot give keep their seat with the radial's dashed
   "unavailable" rim; taps land on the status bar explanation instead. */
.trade-token.unavailable {
  cursor: default;
  border-style: dashed;
  border-color: oklch(0.6 0.03 75 / 0.7);
  background-image: linear-gradient(oklch(0.4 0.01 80 / 0.55), oklch(0.25 0.02 80 / 0.6));
  box-shadow: none;
}

.trade-token.unavailable > * {
  opacity: 0.55;
}

.trade-token-count {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  min-width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border: 1.5px solid oklch(0.35 0.04 66);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  padding: 0 5px;
  font-size: 0.78rem;
  font-weight: 850;
  line-height: 1;
  pointer-events: none;
  box-shadow: 1px 2px 0 oklch(0.08 0.02 164 / 0.4);
}

.trade-token-minus {
  position: absolute;
  right: -8px;
  bottom: -5px;
  width: 22px;
  height: 22px;
  min-height: 0;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 0;
  border: 1.5px solid oklch(0.945 0.022 83);
  border-radius: 50%;
  background: var(--accent);
  color: oklch(0.96 0.02 83);
  font-size: 0.9rem;
  font-weight: 850;
  line-height: 1;
  cursor: pointer;
  box-shadow: 1px 2px 0 oklch(0.08 0.02 164 / 0.4);
}

.trade-token-minus:hover:not(:disabled) {
  background: var(--accent-strong);
}

/* The hub medallion: the dialog's one primary action, dressed exactly like
   the radial's CLOSE hub but in action orange when armed. */
.trade-hub {
  position: relative;
  width: 106px;
  height: 106px;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  justify-self: center;
  margin: 0;
  padding: 0;
  border: 2px solid oklch(0.925 0.028 82 / 0.92);
  border-radius: 50%;
  background: var(--accent);
  color: oklch(0.96 0.02 83);
  cursor: pointer;
  box-shadow: 4px 5px 0 oklch(0.1 0.028 164 / 0.4);
  animation: radial-hub-pop 240ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.trade-hub:hover:not(:disabled) {
  background: var(--accent-strong);
}

/* Idle (not yet armed) the hub keeps the CLOSE hub's grammar: a solid cream
   rim around a deep-teal medallion with the dashed ring inside — substantial,
   just not orange. */
.trade-hub:disabled {
  opacity: 1;
  border-style: solid;
  border-color: oklch(0.925 0.028 82 / 0.8);
  background: var(--deep-soft);
  color: var(--cream-muted);
  cursor: not-allowed;
}

.trade-hub-ring {
  position: absolute;
  inset: 6px;
  border: 1.5px dashed oklch(0.925 0.028 82 / 0.5);
  border-radius: 50%;
  pointer-events: none;
}

.trade-hub-icon svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Hubs that track a quota (the discard medallion) carry a serif counter. */
.trade-hub-count {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.35rem;
  font-weight: 800;
  line-height: 1;
}

.trade-hub-label {
  max-width: 88px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.58rem;
  font-weight: 850;
  letter-spacing: 0.18em;
  line-height: 1.25;
  text-align: center;
  text-transform: uppercase;
}

/* The status bar: a paper plaque that narrates the offer (give pips, want
   pips) and tells the player what the table needs next. */
.trade-status-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  border: 1px solid oklch(0.45 0.05 70);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 3px 4px 0 oklch(0.1 0.028 164 / 0.35);
  padding: 9px 12px;
}

.trade-status-pips {
  display: flex;
  align-items: center;
  gap: 3px;
  flex-wrap: wrap;
}

.trade-status-pips .radial-pip {
  width: 9px;
  height: 13px;
  border-radius: 2.5px;
}

.radial-pip.terrain-any {
  border-style: dashed;
  background-color: oklch(0.95 0.02 82);
}

.trade-status-pips .trade-status-empty {
  width: 9px;
  height: 13px;
  border: 1.5px dashed oklch(0.6 0.045 70);
  border-radius: 2.5px;
}

.trade-status-arrow {
  color: var(--ink);
  font-weight: 850;
}

.trade-status-text {
  flex: 1;
  min-width: 140px;
  margin-left: auto;
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.6rem;
  font-weight: 850;
  letter-spacing: 0.12em;
  text-align: right;
  text-transform: uppercase;
}

.trade-status-text.blocked {
  color: oklch(0.5 0.16 40);
}

.trade-status-bar button {
  min-height: 32px;
  padding: 0 14px;
  font-size: 0.78rem;
}

/* Card rows ride ivory paper plaques on the teal panel, the same paper the
   radial readout card uses. */
.trade-drop-row {
  display: grid;
  gap: 6px;
  border: 1px solid oklch(0.45 0.05 70);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 3px 4px 0 oklch(0.1 0.028 164 / 0.35);
  padding: 10px;
}

.trade-drop-row.projected {
  background: oklch(0.955 0.03 156);
}

.trade-row-heading {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 10px;
}

.trade-row-heading small {
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 680;
  line-height: 1.2;
  text-align: right;
}

/* Identical card dimensions to the sidebar hand (56px column, same face
   metrics), so every resource card in the trading post reads as the same
   physical card. */
.trade-card-row {
  display: grid;
  grid-template-columns: repeat(6, 56px);
  justify-content: center;
  gap: 5px;
}

.trade-move-card {
  min-width: 0;
  min-height: 64px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  border: 1px solid oklch(0.2 0.035 68 / 0.55);
  border-radius: 4px;
  color: oklch(0.985 0.006 80);
  padding: 6px 2px 5px;
  cursor: grab;
  background-image: linear-gradient(oklch(1 0 0 / 0.14), oklch(0.2 0.05 70 / 0.08));
  box-shadow: inset 0 0 0 1px oklch(0.98 0.006 80 / 0.16), 2px 3px 0 oklch(0.22 0.04 68 / 0.14);
  transition: transform 150ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 150ms ease;
}

.trade-move-card:disabled {
  cursor: default;
  opacity: 0.42;
}

.trade-move-card:hover:not(:disabled),
.trade-response:hover:not(:disabled) {
  border-color: oklch(0.985 0.006 80);
  box-shadow: inset 0 0 0 2px oklch(0.985 0.006 80 / 0.84), 0 0 0 2px var(--accent);
}

.trade-move-card:hover:not(:disabled) {
  transform: translateY(-2px);
}

.trade-move-card.terrain-any {
  background-color: oklch(0.93 0.024 82);
  background-image: none;
  color: var(--ink);
}

.trade-move-card > strong {
  font-size: 1.06rem;
  line-height: 1;
}

.trade-move-card > span {
  max-width: 100%;
  overflow: hidden;
  font-size: 0.62rem;
  font-weight: 860;
  line-height: 1.1;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cost-card-grid {
  display: grid;
  gap: 8px;
}

.cost-card-row {
  min-height: 66px;
  display: grid;
  grid-template-columns: 38px minmax(102px, 0.62fr) minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  border: 1px solid oklch(0.45 0.05 70);
  border-radius: 10px;
  background: oklch(0.965 0.018 83);
  color: var(--ink);
  box-shadow: 3px 4px 0 oklch(0.1 0.028 164 / 0.35);
  padding: 10px;
}

.cost-card-row .build-icon.piece-icon svg {
  width: 34px;
  height: 34px;
}

.cost-card-title {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.94rem;
  font-weight: 820;
  line-height: 1.15;
}

/* How many of this piece are still left to build (or cards left in the deck). */
.cost-card-remaining {
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* On the human's action turn each cost row carries a build/buy button in a
   trailing column, so the reference card doubles as the purchase surface
   without growing an extra row. */
.cost-card-row.buildable {
  grid-template-columns: 38px minmax(90px, 0.5fr) minmax(0, 1fr) auto;
}

.cost-build-button {
  min-height: 44px;
  min-width: 44px;
  padding: 0 16px;
  border: 1px solid var(--accent-strong);
  border-radius: 8px;
  background: var(--accent);
  color: oklch(0.96 0.02 83);
  font-weight: 800;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.cost-build-button:hover:not(:disabled) {
  background: var(--accent-strong);
}

.cost-build-button:disabled {
  opacity: 0.5;
  cursor: default;
  background: var(--paper);
  color: var(--muted);
  border-color: var(--line);
}

.cost-resource-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 5px;
}

.cost-resource-pill {
  width: 98px;
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid oklch(0.24 0.02 70 / 0.28);
  border-radius: 999px;
  color: oklch(0.985 0.006 80);
  padding: 3px 9px 3px 4px;
  font-size: 0.74rem;
  font-weight: 780;
  line-height: 1;
}

/* Plugins can color resources that do not map to a terrain. The fallback
   also keeps future resource cards opaque until their own palette is supplied. */
.resource-face {
  background-color: var(--resource-color, #355149);
  color: var(--resource-ink, #fff5dc);
}

.cost-resource-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cost-resource-pill .resource-coin {
  width: 21px;
  height: 21px;
  filter: none;
}

.cost-resource-pill strong {
  font-size: 0.82rem;
}

.dev-card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* Development cards as physical card stock: a kind-colored art panel above
   ivory copy, with the count chip pinned to the corner. Kind accents are
   custom properties so module-added cards inherit the language. */
.dev-card-face {
  --dev-accent: oklch(0.5 0.09 150);
  --dev-accent-soft: oklch(0.9 0.05 145);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  border: 1px solid oklch(0.5 0.05 68);
  border-radius: 5px;
  background: oklch(0.97 0.026 84);
  color: var(--ink);
  padding: 0;
  text-align: left;
  overflow: hidden;
  box-shadow: 2px 3px 0 oklch(0.22 0.04 68 / 0.14);
}

.dev-kind-knight {
  --dev-accent: oklch(0.52 0.14 33);
  --dev-accent-soft: oklch(0.88 0.055 40);
}

.dev-kind-vp {
  --dev-accent: oklch(0.66 0.13 80);
  --dev-accent-soft: oklch(0.93 0.06 88);
}

.dev-card-art {
  display: grid;
  place-items: center;
  min-height: 74px;
  background:
    radial-gradient(circle at 50% 130%, oklch(1 0 0 / 0.42), transparent 72%),
    var(--dev-accent-soft);
  border-bottom: 2px solid var(--dev-accent);
}

.dev-card-art svg {
  width: 46px;
  height: 46px;
  filter: drop-shadow(0 1px 0 oklch(0.35 0.04 60 / 0.22));
}

.dev-card-copy {
  min-width: 0;
  display: grid;
  gap: 3px;
  padding: 8px 10px 10px;
}

.dev-card-kind {
  color: var(--dev-accent);
  font-family: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, monospace;
  font-size: 0.6rem;
  font-weight: 850;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.dev-card-title {
  color: var(--ink);
  font-size: 0.95rem;
  font-weight: 820;
  line-height: 1.15;
}

.dev-card-description {
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 650;
  line-height: 1.3;
}

.dev-card-count {
  position: absolute;
  top: 6px;
  right: 6px;
  min-width: 26px;
  min-height: 26px;
  display: grid;
  place-items: center;
  border: 1px solid oklch(0.62 0.06 70);
  border-radius: 999px;
  background: oklch(0.97 0.025 84);
  padding: 0 6px;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.78rem;
  font-weight: 800;
  box-shadow: 1px 1.5px 0 oklch(0.25 0.055 67 / 0.18);
}

.dev-card-note {
  position: absolute;
  top: 8px;
  left: 8px;
  border: 1px solid oklch(0.74 0.08 84);
  border-radius: 999px;
  background: oklch(0.95 0.06 88);
  color: oklch(0.4 0.07 70);
  padding: 2px 7px;
  font-size: 0.62rem;
  font-weight: 850;
  letter-spacing: 0.04em;
  line-height: 1.1;
  text-transform: uppercase;
}

/* Playable cards keep their card face on hover — feedback is the kind ring
   and a slightly deeper lift, not the global accent repaint. */
button.dev-card-face:hover:not(:disabled) {
  background: oklch(0.97 0.026 84);
  border-color: var(--dev-accent);
  box-shadow: 0 0 0 1.5px var(--dev-accent), 3px 4px 0 oklch(0.22 0.04 68 / 0.18);
}

/* Timing can disable play without making an owned card's rules harder to read. */
button.dev-card-face:disabled {
  opacity: 1;
}

button.dev-card-face:disabled .dev-card-art {
  filter: saturate(0.35);
}

button.dev-card-face:disabled .dev-card-copy {
  opacity: 1;
}

.dev-card-unowned {
  opacity: 0.5;
}
.dev-hand-hint, .dev-hand-empty { margin: 0; padding: 12px; border: 1px solid #b8b293; border-radius: 10px; background: #f5efdc; color: #374638; font: 500 13px/1.5 system-ui, sans-serif; }
.dev-owned-grid:empty { display: none; }
.dev-card-guide { min-width: 0; border-top: 1px solid #a79c7b; padding-top: 8px; }
.dev-card-guide > summary { min-height: 44px; padding: 10px 4px; cursor: pointer; font: 700 14px/1.5 system-ui, sans-serif; }
.dev-card-guide > summary:focus-visible { outline: 3px solid #b98942; outline-offset: 2px; border-radius: 5px; }
.dev-card-guide > p { font: 500 13px/1.4 system-ui, sans-serif; margin: 4px 0 12px; }
.dev-card-guide .dev-card-reference { opacity: 1; }
.dev-card-guide .dev-card-art { padding-top: 0; }

/* The buy reveal: the drawn card flips over from the deck, on the same
   deep-teal plaque as the other table dialogs. */
.dev-reveal-dialog {
  width: min(320px, 100%);
  display: grid;
  justify-items: center;
  gap: 6px;
  border: 2px solid oklch(0.925 0.028 82 / 0.92);
  border-radius: 18px;
  background: oklch(0.175 0.045 161 / 0.96);
  color: oklch(0.945 0.022 83);
  box-shadow: 6px 7px 0 oklch(0.1 0.028 164 / 0.4);
  padding: 18px 20px 20px;
  text-align: center;
  animation: dialog-rise 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.dev-reveal-dialog h2 {
  margin: 0;
  font-size: 1.3rem;
  font-weight: 820;
  line-height: 1.2;
}

.dev-reveal-dialog .eyebrow,
.dev-reveal-dialog .toast-line {
  color: oklch(0.87 0.03 84 / 0.85);
}

.dev-reveal-dialog .toast-line {
  margin: 2px 0 8px;
}

.dev-reveal-dialog .wide {
  width: 100%;
}

.dev-reveal-flip {
  perspective: 900px;
  width: 196px;
  margin: 8px 0 2px;
}

.dev-reveal-flip-inner {
  position: relative;
  transform-style: preserve-3d;
  animation: dev-flip 620ms cubic-bezier(0.22, 1, 0.36, 1) 240ms backwards;
}

@keyframes dev-flip {
  from {
    transform: rotateY(180deg);
  }
}

.dev-reveal-flip .dev-card-face {
  width: 100%;
  min-height: 264px;
  backface-visibility: hidden;
}

.dev-reveal-flip .dev-card-art {
  min-height: 122px;
}

.dev-reveal-flip .dev-card-art svg {
  width: 72px;
  height: 72px;
}

.dev-reveal-flip .dev-card-title {
  font-size: 1.12rem;
}

.dev-reveal-flip .dev-card-description {
  font-size: 0.78rem;
}

.dev-card-back {
  position: absolute;
  inset: 0;
  min-height: 0;
  transform: rotateY(180deg);
  border-color: oklch(0.28 0.05 161);
  background:
    repeating-linear-gradient(45deg, oklch(0.33 0.055 160) 0 10px, oklch(0.29 0.05 160) 10px 20px),
    oklch(0.3 0.05 160);
}

.dev-card-back::after {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1.5px solid oklch(0.74 0.14 78 / 0.6);
}

/* Roster card (zone 2). A two-line button that toggles the shared detail card:
   the top line carries a color swatch, the seat name and the VP tally; the
   muted mono sub-line carries the hand size, module stats and the round. The
   active seat gets a full orange border with a soft glow, the winner a gold
   one. On phones the cards scroll horizontally, so each keeps its intrinsic
   width. These cards intentionally round their corners against the flat print
   language of the rest of the HUD — they read as floating tiles on the board. */
.player-chip {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 0 0 auto;
  border: 2px solid transparent;
  border-radius: 14px;
  background: var(--paper);
  padding: 11px 15px;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  box-shadow: 0 1px 2px oklch(0.2 0.03 60 / 0.14), 0 5px 14px oklch(0.14 0.03 160 / 0.22);
}

.player-chip.current {
  border-color: var(--accent);
  box-shadow:
    0 0 0 4px oklch(0.61 0.18 45 / 0.16),
    0 1px 2px oklch(0.2 0.03 60 / 0.14),
    0 5px 14px oklch(0.14 0.03 160 / 0.22);
}

/* Roster cards contain muted statistics, so a saturated button fill would
   erase their contrast. Keep the paper face and highlight its edge. */
.player-chip:hover:not(:disabled) {
  background: var(--paper);
  border-color: var(--accent);
}

.player-chip.winner {
  border-color: var(--gold);
  box-shadow:
    0 0 0 4px oklch(0.74 0.14 78 / 0.2),
    0 1px 2px oklch(0.2 0.03 60 / 0.14),
    0 5px 14px oklch(0.14 0.03 160 / 0.22);
}

.player-chip.expanded {
  background: oklch(0.94 0.04 80);
}

/* Top line: swatch + name (flexes to fill) + VP tally pinned right. */
.player-chip-main {
  display: flex;
  align-items: center;
  gap: 9px;
}

/* Solid color tile standing in for the seat's playing piece. The translucent
   dark border and top highlight read the same across every seat color. */
.player-swatch {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  background: var(--player-color);
  border: 1.5px solid oklch(0.22 0.03 60 / 0.4);
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.25);
}

/* Muted mono sub-line, indented to align under the name (past the swatch). */
.player-chip-sub {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-left: 27px;
  color: var(--muted);
  font-family: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, monospace;
  font-size: 0.76rem;
  font-weight: 600;
}

/* The single floating roster detail card. */
.player-detail {
  position: relative;
  z-index: 9;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  padding: 12px;
  box-shadow: 12px 14px 0 oklch(0.24 0.04 67 / 0.12);
  max-width: 320px;
}

.player-detail.hidden {
  display: none;
}

.player-detail-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.player-detail-heading > strong { min-width: 0; overflow-wrap: anywhere; }
.player-detail-heading > .label { flex: 1; text-align: right; }
.player-detail-close { flex: none; width: 44px; height: 44px; min-height: 44px; padding: 0; font-size: 24px; }

@media (min-width: 1040px) {
  /* Full-width cards down the left column; the name flexes so every VP tally
     lines up against a shared right edge. */
  .player-chip {
    width: 100%;
  }
}

/* Below the desktop column the roster is a horizontal strip across the top, so
   the cards collapse to their smallest identity: a color swatch and the VP
   tally. Names are dropped (seats read by color) so all seats fit the strip
   without scrolling; the name still rides along for screen readers, and hand
   size, round and module stats live in the tap-expand detail. The two wrappers
   flatten (display: contents) so swatch and VP become one flex row. (Placed
   after the base rules so it wins on source order.) */
@media (max-width: 1039px) {
  /* Cards share the strip width equally (flex: 1) so every seat always fits,
     at any width and player count — the strip can never overflow or clip a
     seat. */
  .player-list {
    gap: 6px;
  }

  .player-chip {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 7px 8px;
    border-radius: 12px;
  }

  .player-chip-main,
  .player-chip-sub {
    display: contents;
  }

  .player-swatch {
    order: 0;
  }

  /* Name kept in the accessibility tree, out of the visual flow. */
  .player-name {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
  }

  .player-score {
    order: 3;
  }

  .player-score-num {
    font-size: 1.12rem;
  }

  .player-card-count,
  .player-round,
  .player-stat {
    display: none;
  }
}

/* Longest-route length, always visible per seat; the current award holder's
   stat turns gold to echo the award tile. */
.player-route {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 800;
  white-space: nowrap;
}

/* Module stat pinned to the collapsed player row (collectPlayerSummary
   `stats`), e.g. Cities & Knights' standing/total knights. */
.player-stat {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 800;
  white-space: nowrap;
}

.player-route svg {
  width: 13px;
  height: 13px;
}

.player-route.holder {
  color: oklch(0.5 0.1 76);
}

.player-piece {
  display: block;
  width: 17px;
  height: 17px;
}

.player-piece svg {
  display: block;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 1px 0 oklch(0.3 0.04 60 / 0.3));
}

.winner-crown {
  display: inline-block;
  width: 15px;
  height: 15px;
  margin-left: 6px;
  vertical-align: -2px;
}

.winner-crown svg {
  display: block;
  width: 100%;
  height: 100%;
}

.player-name {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  font-weight: 820;
  font-size: 1.02rem;
}

.player-name-text { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

@media (min-width: 1040px) {
  .player-chip { container: player-card / inline-size; }
  @container player-card (max-width: 180px) {
    .player-chip-main { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 3px 7px; }
    .player-name { grid-column: 1 / -1; grid-row: 1; font-size: 13px; }
    .player-swatch { grid-column: 1; grid-row: 2; }
    .player-score { grid-column: 2; grid-row: 2; justify-content: flex-start; }
  }
}

.player-card-count {
  white-space: nowrap;
}

/* VP tally: large number with a small muted unit, no pill. */
.player-score {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.player-score-num {
  font-size: 1.45rem;
  font-weight: 850;
  line-height: 1;
}

.player-score-unit {
  color: var(--muted);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.player-score-stacked { flex-direction: column; align-items: center; gap: 0; }
.player-score-stacked .player-score-unit { font-size: 8px; letter-spacing: .02em; }

.player-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.78rem;
}

.mini-chip {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: oklch(0.98 0.02 82);
  padding: 2px 7px;
  font-weight: 700;
}
.illustrated-award { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); }
.illustrated-award-icon { display: block; width: 36px; height: 36px; flex: none; }
.illustrated-award-icon svg { display: block; width: 100%; height: 100%; }

.log-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: min(360px, 46vh);
  overflow: auto;
  margin: 0;
  padding-left: 20px;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.35;
}

/* The log popover and directions drawer wear the same deep-teal plaque as
   the table dialogs. */
.log-popover,
.directions-panel {
  --cream: oklch(0.945 0.022 83);
  --cream-muted: oklch(0.87 0.03 84 / 0.85);
  --cream-line: oklch(0.925 0.028 82 / 0.28);
}

.log-popover {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 18;
  width: min(430px, calc(100vw - 36px));
  border: 2px solid oklch(0.925 0.028 82 / 0.92);
  border-radius: 18px;
  background: oklch(0.175 0.045 161 / 0.95);
  color: var(--cream);
  box-shadow: 6px 7px 0 oklch(0.1 0.028 164 / 0.4);
  padding: 12px;
  animation: dialog-rise 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.log-popover .panel-heading {
  margin-bottom: 8px;
}

.log-popover .panel-heading .label {
  color: var(--cream);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
}

.log-popover .log-list {
  color: var(--cream-muted);
}

.hidden {
  display: none !important;
}

.toast-line {
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.35;
  margin: 7px 0 0;
}

.winner {
  border-color: oklch(0.68 0.14 88);
  background: oklch(0.95 0.035 86);
}

.directions-panel {
  position: fixed;
  z-index: 32;
  top: 18px;
  right: 18px;
  bottom: 18px;
  width: min(560px, calc(100vw - 36px));
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  border: 2px solid oklch(0.925 0.028 82 / 0.92);
  border-radius: 18px;
  overflow: hidden;
  background: oklch(0.175 0.045 161 / 0.97);
  color: var(--cream);
  box-shadow: 6px 7px 0 oklch(0.1 0.028 164 / 0.4);
  animation: dialog-rise 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.directions-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: transparent;
  padding: 14px 16px;
}

.directions-panel-header h2 {
  margin: 0;
  color: var(--cream);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.94rem;
  font-weight: 850;
  letter-spacing: 0.18em;
  line-height: 1.2;
  text-transform: uppercase;
}

.directions-panel .trade-dialog-note {
  color: var(--cream-muted);
}

/* No top padding on the scroller: sticky offsets resolve against the content
   edge, so a padded scroller would pin the nav 16px down and let scrolled
   text peek through the strip above it. */
.directions-content {
  overflow: auto;
  padding: 0 16px 16px;
}

.directions-nav {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0 -16px 16px;
  background: oklch(0.16 0.042 161);
  padding: 10px 16px;
}

/* Section links speak the dialog's protocol voice: quiet mono uppercase tags
   on the teal, filling to ivory only under the pointer. */
.directions-nav a {
  border: 1px solid var(--cream-line);
  border-radius: 999px;
  background: none;
  color: var(--cream);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.62rem;
  font-weight: 850;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 5px 11px;
  text-decoration: none;
}

.directions-nav a:hover {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
}

.directions-document {
  display: grid;
  gap: 14px;
  border: 1px solid oklch(0.45 0.05 70);
  border-radius: 12px;
  background: oklch(0.965 0.02 82);
  color: var(--ink);
  box-shadow: 3px 4px 0 oklch(0.1 0.028 164 / 0.35);
  padding: 15px;
}

.directions-document + .directions-document {
  margin-top: 14px;
}

.directions-document-heading {
  display: grid;
  gap: 6px;
}

.directions-kind {
  width: max-content;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: oklch(0.93 0.075 76);
  color: var(--ink);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.64rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  padding: 3px 8px;
  text-transform: uppercase;
}

.directions-document h3,
.directions-section h4 {
  margin: 0;
  color: var(--ink);
}

.directions-document h3 {
  font-size: 1.18rem;
}

.directions-document-heading p,
.directions-section p,
.directions-section li,
.directions-snapshot figcaption,
.directions-snapshot-note {
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 650;
  line-height: 1.5;
}

.directions-section {
  display: grid;
  gap: 9px;
  border-top: 1px solid var(--line);
  padding-top: 13px;
}

.directions-section h4 {
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.directions-section ul {
  display: grid;
  gap: 7px;
  margin: 0;
  padding-left: 20px;
}

.directions-snapshot {
  display: grid;
  gap: 8px;
  margin: 0;
}

.directions-snapshot img {
  width: 100%;
  max-height: 320px;
  border: 1px solid oklch(0.29 0.055 156);
  background: oklch(0.18 0.05 165);
  object-fit: cover;
}

.directions-snapshot-note {
  border: 1px solid var(--line);
  background: oklch(0.96 0.032 83);
  margin: 0;
  padding: 10px;
}

@media (max-width: 1040px) {
  .setup-layout {
    grid-template-columns: 1fr;
    gap: 30px;
  }

  .setup-form {
    min-width: 0;
  }

  .setup-intro {
    padding: 5vh 0 0 44px;
  }

  .setup-identity {
    margin-bottom: 48px;
  }

  .setup-vignette {
    margin-top: 24px;
  }
}

@media (max-width: 680px) {
  .setup-screen {
    padding: 18px 14px 34px;
  }

  .setup-screen::after {
    display: none;
  }

  .setup-intro {
    padding: 14px 4px 0;
  }

  .setup-identity {
    margin-bottom: 42px;
  }

  .setup-intro h1 {
    font-size: 4.55rem;
  }

  .setup-intro > p:not(.eyebrow) {
    font-size: 1.03rem;
    margin-top: 21px;
  }

  .setup-vignette {
    width: min(300px, 100%);
  }

  .setup-note {
    margin-top: 28px;
  }

  .setup-form {
    box-shadow: 8px 9px 0 oklch(0.27 0.06 62 / 0.14);
  }

  .setup-section {
    padding: 17px 15px;
  }

  .turn-order-options {
    grid-template-columns: 1fr;
  }

  .setup-actions {
    display: grid;
    grid-template-columns: 1fr;
  }


  .module-option-row {
    grid-template-columns: 1fr;
  }

  .scenario-field-heading {
    align-items: stretch;
    flex-direction: column;
  }

  .status-banner {
    max-width: calc(100vw - 16px);
    min-height: 38px;
    font-size: 0.72rem;
  }

  .board-tools-fan .icon-button {
    min-height: 40px;
  }

  .control-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .action-button {
    min-height: 52px;
  }

  .resource-row {
    grid-template-columns: repeat(5, minmax(48px, 1fr));
  }

  .resource-choice-grid,
  .trade-hand-row {
    grid-template-columns: repeat(5, minmax(48px, 1fr));
  }

  /* Dialogs fill the whole screen on phones: opaque, edge to edge, no drag.
     Docked panels included — the radial link survives as pure lifecycle
     (closing the sheet returns to the open wheel), so the side-dock layout
     and tether stand down. */
  .modal-backdrop {
    align-items: stretch;
    padding: 0;
  }

  .modal-backdrop.radial-docked,
  .modal-backdrop.radial-docked.dock-top {
    display: grid;
    padding: 0;
  }

  .modal-backdrop.radial-docked .trade-dialog {
    position: static;
    max-width: none;
    max-height: none;
  }

  .radial-tether {
    display: none;
  }

  .trade-dialog,
  .trade-dialog.compact,
  .trade-dialog.trading-post,
  .trade-dialog.discard-dialog {
    width: 100%;
    height: 100dvh;
    max-height: none;
    border: 0;
    border-radius: 0;
    background: oklch(0.175 0.045 161);
    box-shadow: none;
  }

  /* The orbit stacks: token arcs on top, the hub medallion centered below. */
  .trade-orbit-layout {
    grid-template-columns: 1fr;
  }

  .trade-orbit-zone {
    padding-right: 2px;
    padding-left: 2px;
  }

  .trade-orbit-row {
    gap: 7px;
  }

  .trade-token-wrap {
    --token-size: 46px;
  }

  .trade-token .resource-coin {
    width: 18px;
    height: 18px;
  }


  .trade-dialog-header {
    padding: calc(12px + env(safe-area-inset-top, 0px)) 12px 12px;
    cursor: default;
  }

  /* Full-screen sheets top-align their content instead of stretching the
     single grid row across the leftover viewport height. */
  .trade-dialog-body {
    align-content: start;
  }

  .trade-dialog-actions {
    padding: 12px 12px calc(12px + env(safe-area-inset-bottom, 0px));
  }

  .trade-response-list,
  .trade-summary-grid,
  .dev-card-grid {
    grid-template-columns: 1fr;
  }

  .dev-card-grid .dev-card-face {
    display: grid;
    grid-template-columns: 76px minmax(0, 1fr);
  }

  .dev-card-grid .dev-card-art {
    min-height: 110px;
    padding-top: 16px;
    border-bottom: 0;
    border-right: 2px solid var(--dev-accent);
  }

  .dev-card-grid .dev-card-art svg {
    width: 58px;
    height: 58px;
  }

  .dev-card-grid .dev-card-count {
    top: 5px;
    left: 5px;
    right: auto;
  }

  .dev-card-grid .dev-card-note {
    top: auto;
    bottom: 5px;
    left: 5px;
    max-width: 64px;
  }

  .dev-card-grid .dev-card-copy {
    align-content: center;
    padding: 10px;
  }

  .dev-card-grid .dev-card-description {
    font-size: 0.75rem;
    line-height: 1.4;
  }

  .trade-dialog-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .trade-card-row {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .cost-card-row,
  .cost-card-row.buildable {
    grid-template-columns: 38px 1fr;
  }

  .cost-resource-list {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }

  /* Narrow rows stack again: the build button returns to its own full row. */
  .cost-build-button {
    grid-column: 1 / -1;
  }

  .trade-dialog-actions button {
    width: 100%;
    min-height: 46px;
  }

  .directions-panel {
    inset: 10px;
    width: auto;
    box-shadow: 7px 8px 0 oklch(0.15 0.035 67 / 0.22);
  }

  .directions-panel-header {
    padding: 13px;
  }

  .directions-content {
    padding: 0 13px 13px;
  }

  .directions-nav {
    margin: 0 -13px 13px;
    padding: 10px 13px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ---- Play online card (setup screen) -------------------------------- */

.online-card {
  border: 1px solid oklch(0.48 0.052 67);
  border-radius: var(--radius);
  background: oklch(0.955 0.026 82);
  box-shadow: 16px 18px 0 oklch(0.27 0.06 62 / 0.14);
  overflow: hidden;
}

.online-heading {
  margin: 0;
  text-transform: uppercase;
  display: block;
  border-bottom: 1px solid var(--line);
  background: var(--deep);
  color: var(--gold);
  padding: 11px 20px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
}

.online-card > * {
  margin: 0;
  padding-left: 20px;
  padding-right: 20px;
}

.online-card .online-hint {
  padding-top: 14px;
  color: oklch(0.42 0.04 66);
  font-size: 0.92rem;
}

.online-form,
.online-card .online-actions {
  display: grid;
  gap: 12px;
  padding-top: 12px;
  padding-bottom: 16px;
}

.online-actions {
  grid-template-columns: 1fr auto;
  align-items: end;
}

.online-actions > button.wide {
  grid-column: 1 / -1;
}
.online-actions > button { min-height: 44px; }
.online-recovery-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.online-recovery-actions > button { min-width: 0; white-space: normal; }
.online-card .online-recovery-heading { padding-top: 12px; font-size: 1.15rem; line-height: 1.3; }

.online-count {
  max-width: 110px;
}

.online-intent-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding-block: 16px 0; }
.online-intent-tabs [role="tab"] { min-height: 48px; padding: 10px 8px; font-size: .95rem; background: transparent; color: var(--ink); box-shadow: none; border: 1px solid var(--line); }
.online-intent-tabs [aria-selected="true"] { background: var(--deep); color: var(--paper); border-color: var(--deep); box-shadow: inset 0 -3px var(--gold); }
.online-intent-tabs [role="tab"]:hover { background: var(--paper); color: var(--ink); }
.online-intent-tabs [aria-selected="true"]:hover { background: var(--deep); color: var(--paper); }
.online-setup-panel { display: grid; gap: 12px; min-width: 0; }
.online-setup-panel[hidden], #onlineSetupForm > button[hidden] { display: none; }
.online-form .online-hint { padding-top: 0; margin: 0; }
.online-form > button[type="submit"] { min-height: 48px; }

.online-expansion-picker {
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.25);
  min-width: 0;
}
.online-expansion-picker summary {
  padding: 14px 12px;
  min-height: 44px;
  box-sizing: border-box;
  cursor: pointer;
  font-weight: 750;
  font-size: 0.9rem;
}
.online-expansion-picker > .online-hint { padding: 0 12px 12px; margin: 0; }
.online-expansion-choices { max-height: 340px; overflow-y: auto; overscroll-behavior: contain; padding: 0 12px 12px; }
.online-expansion-choices fieldset { border: 0; padding: 0; margin: 8px 0 0; min-width: 0; }
.online-expansion-choices legend { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); padding: 8px 0; }
.online-expansion-choice { padding: 5px 0 10px; border-top: 1px solid var(--line); }
.online-expansion-choice > label { display: flex; gap: 10px; align-items: center; min-height: 44px; cursor: pointer; font-size: 0.9rem; }
.online-expansion-choice input[type="checkbox"] { width: 20px; height: 20px; flex: 0 0 20px; accent-color: var(--deep); margin: 0; }
.online-expansion-choice > small { display: block; padding-left: 30px; font-size: 0.79rem; line-height: 1.45; color: oklch(0.42 0.04 66); overflow-wrap: anywhere; }
.online-expansion-choice.unavailable > label { cursor: default; color: oklch(0.46 0.02 66); }
.online-expansion-choice .setup-field { display: grid; margin: 8px 0 0 30px; }
.online-expansion-choice select { width: 100%; min-width: 0; }
.setup-form select, .online-form select, .online-form input:not([type="checkbox"]) {
  min-height: 44px;
  box-sizing: border-box;
  padding: 9px 10px;
  font-size: 16px;
}
.setup-form select, .online-form select {
  appearance: none;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding-right: 30px;
  color: var(--ink);
  background-color: var(--paper);
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%), linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 15px) 19px, calc(100% - 10px) 19px;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}
.online-table-summary {
  margin-top: 12px;
  border: 1px solid rgba(45, 98, 91, 0.3);
  border-radius: 10px;
  padding: 12px;
  background: linear-gradient(125deg, rgba(183, 209, 194, 0.3), rgba(228, 206, 152, 0.15));
  overflow-wrap: anywhere;
}
.online-table-summary-heading { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.online-table-summary-heading > strong { font: 750 0.76rem ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.online-table-summary-heading > span { font-size: 0.8rem; }
.online-table-summary ul { list-style: none; padding: 0; margin: 10px 0 0; display: grid; gap: 8px; }
.online-table-summary li { display: grid; gap: 2px; font-size: 0.87rem; border-left: 3px solid #78968b; padding-left: 10px; }
.online-table-summary li > span { font-size: 0.8rem; color: oklch(0.42 0.04 66); }
.online-card > .online-table-summary { margin: 12px 20px; }
.online-selection-notice { margin: 10px 0; font-size: 0.83rem; line-height: 1.45; }

.online-code-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding-top: 14px;
}

.online-code-row span {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: oklch(0.42 0.04 66);
}

.online-code {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 1.45rem;
  letter-spacing: 0.3em;
  color: var(--deep);
}

.online-members {
  list-style: none;
  display: grid;
  gap: 8px;
  padding-top: 12px;
  padding-bottom: 4px;
}

.online-member {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
.online-member > strong { min-width: 0; flex: 1 1 120px; overflow-wrap: anywhere; }
.online-room-dialog .online-members { margin: 8px 0 0; padding: 0; gap: 6px; }

.online-member .color-swatch {
  flex: none;
}

.online-badge {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: oklch(0.94 0.03 82);
  color: oklch(0.42 0.04 66);
}

.online-badge.alert {
  border-color: oklch(0.62 0.14 35);
  color: oklch(0.5 0.16 35);
}

.online-roll {
  margin-left: auto;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.85rem;
  color: var(--deep);
}

.online-draft {
  padding-bottom: 8px;
}

.online-color {
  cursor: pointer;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: oklch(0.965 0.015 85);
  padding: 8px 10px;
}

.online-color:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.online-error {
  color: oklch(0.5 0.16 35);
  font-weight: 600;
  padding-bottom: 14px;
}

/* Module-contributed event dice and panels. */

/* The extra event die: a colored chip with a discipline/ship glyph, sitting
   beside the two production dice in the readout. */
.event-die {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 9px;
  border: 1px solid color-mix(in oklch, var(--event-die-color, #74695f) 60%, #1c140a);
  background: linear-gradient(148deg, color-mix(in oklch, var(--event-die-color, #74695f) 80%, white), var(--event-die-color, #74695f));
  box-shadow: inset 0 -3px 6px oklch(0.2 0.02 70 / 0.3), inset 0 2px 3px oklch(1 0 0 / 0.4), 0 3px 7px oklch(0.2 0.02 70 / 0.2);
}
.event-die-glyph {
  font-size: 1.2rem;
  line-height: 1;
  color: oklch(0.99 0.02 84);
  filter: drop-shadow(0 1px 1px oklch(0.2 0.02 70 / 0.5));
}
.event-die-label {
  font-weight: 800;
  font-size: 0.75rem;
  color: oklch(0.99 0.02 84);
}

/* The sidebar panel under the primary controls. */
.module-panels {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}
.module-panels.hidden { display: none; }

.module-overview { display: none; }
@media (min-width: 1040px) {
  .module-drawer.has-overview.open > .module-overview { display: grid; gap: 8px; }
  .module-drawer.has-overview > .module-panels { display: none; }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-list { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-chip { padding: 7px 10px; gap: 3px; }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-chip-main { gap: 7px; }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-score-num { font-size: 24px; }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-chip-sub { padding-left: 0; gap: 4px 6px; font-size: 11px; }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-round { display: none; }
}
.module-status { padding: 10px; border: 1px solid #bba77d; border-radius: 12px; background: #f6efde; color: #292214; }
.module-status h3 { margin: 0 0 8px; font-size: 16px; line-height: 1.2; }
.module-status dl { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 8px; margin: 0; }
.module-status dl:has(> div:nth-child(4)):not(:has(> div:nth-child(5))) { grid-template-columns: repeat(2,minmax(0,1fr)); }
.module-status dt { font-size: 11px; line-height: 1.2; color: #655b48; }
.module-status dd { font-size: 18px; line-height: 1.1; font-weight: 750; margin: 3px 0 0; }
.module-status p { margin: 8px 0 0; font-size: 12px; line-height: 1.4; }
.module-overview > button { min-height: 44px; }
.module-overview > select { min-height: 32px; }
@media (min-width: 1040px) and (max-height: 850px) {
  .hud-left:has(.module-drawer.open:not(.hidden)) { gap: 6px; }
  .hud-left:has(.module-drawer.open:not(.hidden)) .player-list { padding-bottom: 4px; }
  .module-drawer.has-overview.open > .module-overview { gap: 4px; }
  .module-overview .module-status { padding: 8px; }
  .module-overview .module-status dl { row-gap: 6px; }
}
/* The selector already names the active expansion. Keep its repeated heading
   available to assistive technology without spending another row of the HUD. */
.module-overview:has(> select) .module-status h3 { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.module-control-dialog { width: min(760px,calc(100vw - 32px)); max-height: calc(100dvh - 32px); padding: 0; border: 1px solid #bba77d; border-radius: 16px; background: #f6efde; color: #292214; }
.module-control-dialog::backdrop { background: #001b14a0; }
.module-control-dialog > header { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; background: #f6efde; border-bottom: 1px solid #cfc0a0; }
.module-control-dialog h2 { margin: 0; font-size: 20px; }
.module-control-dialog > header button { padding: 8px 12px; min-height: 44px; }
.module-control-content { padding: 16px; }
.module-control-content .module-panels { display: grid; gap: 12px; }

/* Reusable framed expansion panels. */
.expansion-panel {
  border: 1px solid var(--line);
  background: oklch(0.97 0.022 82);
  padding: 11px 12px 13px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.expansion-panel-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.expansion-panel-heading .label {
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 0.72rem;
  color: var(--muted);
}
/* Incompatible expansions gray out while their counterpart is checked. */
.module-option-row.module-option-blocked { opacity: 0.55; }
.module-option-row.module-option-blocked .module-option { cursor: not-allowed; }

/* The catalog has its own browse order; rule composition remains unchanged. */
.setup-library-tools { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: 12px; }
.setup-library-tools .setup-field { min-width: 0; max-width: none; }
.setup-library-tools input { width: 100%; min-height: 44px; box-sizing: border-box; background: var(--paper); color: var(--ink); border: 1px solid var(--line); padding: 10px 12px; font-size: 16px; }
.setup-selection { display: grid; gap: 8px; padding: 14px; background: var(--paper); border: 1px solid var(--line); }
.setup-selection > span, .setup-library-count { color: var(--muted); font-size: .82rem; line-height: 1.4; }
.setup-selection > div { display: flex; flex-wrap: wrap; gap: 6px; }
.setup-selection button { min-height: 44px; padding: 8px 10px; font-size: .8rem; }
.setup-selection > button { justify-self: start; }
.setup-selection-error { padding: 12px; border: 1px solid var(--accent); background: var(--paper); color: var(--ink); font-size: .88rem; }
.setup-library-count { margin: 0; }
.setup-catalog-group { display: grid; gap: 10px; margin-bottom: 26px; }
.setup-catalog-group[hidden], .setup-game-entry[hidden] { display: none; }
.setup-catalog-heading { border-bottom: 1px solid var(--line); padding-bottom: 10px; }
.setup-catalog-heading h3 { font-size: 1.08rem; letter-spacing: 0; text-transform: none; margin: 0 0 4px; }
.setup-catalog-heading p { font-size: .83rem; line-height: 1.4; margin: 0; color: var(--muted); }
.setup-game-entry .module-option-row { grid-template-columns: minmax(0, 1fr) 58px; gap: 6px; }
.setup-game-entry .directions-link { min-height: 44px; padding-inline: 6px; }
.setup-game-entry .module-option { padding: 12px 10px; }
.setup-game-entry .module-option-copy strong { font-size: .95rem; }
.setup-game-entry .module-option-copy > span { font-size: .82rem; font-weight: 500; line-height: 1.4; }
.setup-game-entry .scenario-field { margin: 6px 0 0; }
.setup-game-entry .scenario-field select { max-width: 100%; }
.setup-game-entry .scenario-field-heading { flex-direction: row; align-items: center; }
.setup-game-entry .scenario-field-heading label { min-width: 0; }
.setup-game-section > #setupNextTable { min-height: 44px; }
@media (max-width: 600px) {
  .setup-library-tools { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .setup-game-entry .module-option-copy > span { font-size: .8rem; }
}
.module-conflict-note {
  font-size: 0.74rem;
  font-style: italic;
  color: oklch(0.5 0.09 40);
}
.module-conflict-note.hidden { display: none; }

/* Module bank-tab currencies (gold coins) sit beside the resource cards. */
.resource-choice.currency-choice {
  background: oklch(0.93 0.06 92);
  border-color: oklch(0.62 0.09 88);
}
.resource-choice.currency-choice svg.resource-coin {
  width: 26px;
  height: 26px;
}

/* Comfortable table controls, shared by phones and keyboard navigation. */
.setup-quick-actions { display: grid; gap: 10px; margin: 22px 0 12px; max-width: 390px; }
.setup-quick-actions button { min-height: 48px; }
.setup-quick-actions small { font-size: 0.8rem; color: var(--ink); text-align: center; }
.preferences-dialog { width: min(480px, calc(100vw - 24px)); max-height: calc(100dvh - 32px); overflow: auto; padding: 24px; color: var(--ink); background: var(--paper); border: 2px solid var(--ink); box-shadow: 8px 8px 0 #001d1690; }
.preferences-dialog::backdrop { background: #001c18b8; }
.preferences-header { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.preferences-header h2 { margin: 0; font-size: 1.7rem; }
.preferences-dialog > p { font-size: 0.9rem; line-height: 1.5; }
.preference-audio-controls { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 16px 0 6px; }
.preference-audio-controls button { min-height: 44px; padding: 10px 8px; font-size: .85rem; }
.preference-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 15px 0; border-bottom: 1px solid #79654440; font-size: 0.92rem; font-weight: 700; }
.preference-row small { display: block; margin-top: 3px; font-size: 0.78rem; font-weight: 400; }
.preference-row input[type=checkbox] { width: 24px; height: 24px; flex: none; accent-color: var(--accent); }
.preference-row input[type=range] { max-width: 150px; accent-color: var(--accent); }
.preference-row select { min-height: 44px; max-width: 125px; }
.preferences-note { color: var(--muted); }
.reduce-motion *, .reduce-motion *::before, .reduce-motion *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
@media (max-width: 600px) {
  .setup-intro h1 { font-size: clamp(3.2rem, 16vw, 4.8rem); }
  .setup-vignette { max-height: 175px; }
  .setup-note { margin-top: 14px; }
  .setup-quick-actions { margin-top: 18px; }
  .preferences-dialog { padding: 18px; }
  .board-popover button, .module-panels button, .delivery-choice button { min-height: 44px; }
}
/* Short phone screens keep the welcome's play choices in its first view. */
@media (orientation: landscape) and (max-height: 600px) and (max-width: 1040px) {
  .setup-screen { padding: 14px max(18px, env(safe-area-inset-right)) 28px max(18px, env(safe-area-inset-left)); }
  .setup-screen::after { display: none; }
  .setup-intro { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(22px, 5vw, 48px); row-gap: 8px; padding: 0; }
  .setup-identity { grid-column: 1; grid-row: 1; margin: 0; }
  .setup-island-mark { flex-basis: 44px; width: 44px; height: calc(44px * 250 / 360); }
  .setup-identity .table-wordmark { font-size: .72rem; letter-spacing: .08em; }
  .setup-intro > .eyebrow { grid-column: 1; grid-row: 2; margin: 4px 0 0; font-size: .66rem; }
  .setup-intro h1 { grid-column: 1; grid-row: 3; max-width: 10ch; font-size: clamp(2.5rem, 6.4vw, 3.6rem); line-height: .9; }
  .setup-intro > p:not(.eyebrow) { grid-column: 1; grid-row: 4; margin: 4px 0 0; font-size: .96rem; line-height: 1.35; }
  .setup-intro > .setup-vignette { grid-column: 2; grid-row: 1 / 3; justify-self: center; width: 116px; max-height: 80px; margin: 0; }
  .setup-quick-actions { grid-column: 2; grid-row: 3 / 5; align-self: center; margin: 0; max-width: none; gap: 8px; }
  .setup-quick-actions button { padding: 8px 10px; min-height: 44px; font-size: .88rem; }
  .setup-quick-actions small { font-size: .7rem; line-height: 1.3; }
  .setup-note { grid-column: 1 / -1; margin-top: 18px; }
  .setup-intro-actions { grid-column: 1 / -1; margin-top: 0; }
}
.board:focus-visible { outline: 3px solid var(--accent); outline-offset: -4px; }
.board-guide { position: fixed; z-index: 16; left: 16px; bottom: calc(var(--dock-clearance, 110px) + 20px); width: 286px; padding: 14px; border: 1px solid #b4a171; background: #fbf1da; color: #261b0c; box-shadow: 6px 6px 0 #001b1480; }
.board-guide-heading { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.board-guide-heading .icon-button { min-height: 44px; height: 44px; min-width: 44px; width: 44px; }
.board-guide-heading strong { font-size: 0.9rem; }
.board-guide p { font-size: 0.87rem; line-height: 1.45; margin: 8px 0; }
.board-guide small { display: block; font-size: 0.74rem; line-height: 1.4; color: #645338; }
.board-guide [data-guide-tip] { font-size: 0.74rem; }
.board-guide [data-guide-confirm] { width: 100%; min-height: 44px; margin-top: 4px; }
.board-guide [hidden] { display: none; }
@media (max-width: 760px) {
  .board-guide { left: 10px; right: 10px; width: auto; bottom: calc(var(--dock-clearance, 150px) + 8px); padding: 12px; }
  .board-guide p { margin: 4px 0; }
}
@media (max-height: 480px) and (max-width: 1039px) {
  .board-region {
    --board-safe-top: calc(64px + var(--status-height, 44px) + env(safe-area-inset-top, 0px));
    --board-safe-bottom: calc(var(--dock-clearance, 80px) + 8px);
  }
  .board-guide { top: 108px; bottom: auto; right: auto; width: 248px; max-height: calc(100dvh - 120px); overflow-y: auto; padding: 10px; }
  .board-guide [data-guide-tip], .board-guide [data-guide-pips] { display: none; }
}
.table-decision-dialog h2 { font-size: 1.45rem; margin-top: 0; }
[data-decision-options] { display: grid; gap: 10px; }
[data-decision-options] button { text-align: left; min-height: 48px; padding: 12px; }
[data-decision-options] small { display: block; margin-top: 5px; font-size: 0.77rem; font-weight: 400; line-height: 1.45; }
.grid-choice-dialog [data-decision-options] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-choice-dialog [data-decision-options] button { min-width: 0; }
@media (max-width: 620px), (max-height: 500px) {
  .grid-choice-dialog { padding: 16px; }
  .grid-choice-dialog h2 { margin: 0 0 10px; font-size: 1.2rem; }
  .grid-choice-dialog > p { margin: 0 0 12px; font-size: 14px; }
  .grid-choice-dialog [data-decision-options] { gap: 8px; }
  .grid-choice-dialog [data-decision-options] button { padding: 9px 10px; font-size: 14px; }
  .grid-choice-dialog [data-decision-options] small { margin-top: 3px; line-height: 1.3; }
}
button.radial-wedge-tag { pointer-events: auto; cursor: pointer; background: transparent; border: 0; box-shadow: none; padding: 4px; min-width: 44px; min-height: 44px; }
button.radial-wedge-tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Mandatory choices stay attached to an understandable physical location. */
.table-decision-dialog { max-height: calc(100dvh - 32px); overscroll-behavior: contain; border: 1px solid #b6a57f; border-radius: 18px; box-shadow: 0 20px 70px #061e1bb3, inset 0 0 0 3px #fff9eb; }
.table-decision-dialog h2 { color: #163f35; line-height: 1.25; }
[data-decision-art] { float: right; width: 72px; height: 54px; margin: 0 0 8px 10px; }
[data-decision-art] svg { display: block; width: 100%; height: 100%; }
[data-decision-art][hidden] { display: none; }
.dev-kind-immediate .dev-card-art { background: linear-gradient(145deg, #c9d4b9, #9fb99e); }
.table-decision-dialog > p { color: #65563d; line-height: 1.5; }
[data-decision-options] button { color: #193e34; background: linear-gradient(135deg, #fffdf5, #f1e9d6); border: 1px solid #b7aa89; border-radius: 10px; box-shadow: 0 2px 0 #b7aa894d; }
[data-decision-options] button:hover { background: #e0ecdc; border-color: #35634e; }
[data-decision-options] button:focus-visible { outline: 3px solid #cc690d; outline-offset: 2px; background: #e7eddb; }
.table-decision-dialog.has-map { width: min(900px, calc(100vw - 32px)); max-width: 900px; }
.decision-layout { display: grid; gap: 20px; }
.has-map .decision-layout { grid-template-columns: minmax(0, 1fr) minmax(230px, 0.85fr); align-items: start; }
[data-decision-map] { position: sticky; top: 0; padding: 10px; border-radius: 12px; background: var(--surface-dark, #123d3b); color: var(--paper, #f6ecd7); }
[data-decision-map][hidden] { display: none; }
[data-decision-map] svg { display: block; width: 100%; max-height: 48dvh; border-radius: 8px; background: #37616a; box-shadow: inset 0 0 0 1px #d9ead22b; }
[data-decision-map] small { display: block; padding: 8px 4px 2px; text-align: center; line-height: 1.5; }
.decision-map-itinerary line { stroke: #ffd66b; stroke-width: 7; stroke-linecap: round; filter: drop-shadow(0 1px 1px #43351d); pointer-events: none; }
.decision-map-annotation rect { stroke: #fff3d5; stroke-width: 1; }
.decision-map-annotation text { fill: #fff3d5; text-anchor: middle; font: 700 12px sans-serif; }
.decision-map-controls button { border-radius: 8px; }
.decision-map-target circle { fill: #174f4c; stroke: #fff9e9; stroke-width: 2; }
.decision-map-target text { text-anchor: middle; font: bold var(--map-label-size, 11px) sans-serif; fill: #fff9e9; }
.decision-map-target.selected circle { fill: #ffe08b; stroke: #173d36; stroke-width: 4; }
.decision-map-target.selected text { fill: #173d36; }
.has-map [data-decision-options] { max-height: 52dvh; overflow-y: auto; padding: 3px; scrollbar-gutter: stable; }
@media (max-width: 620px) {
  .has-map .decision-layout { grid-template-columns: 1fr; gap: 12px; }
  [data-decision-map] svg { max-height: 25dvh; }
  [data-decision-map] small { display: none; }
  .has-map [data-decision-options] { max-height: 35dvh; }
  .table-decision-dialog h2 { font-size: 1.2rem; }
}

.table-insights-dialog { width: min(840px, calc(100vw - 32px)); max-width: 840px; max-height: calc(100dvh - 32px); padding: 28px; }
.table-insights-dialog h2 { margin: 5px 0 0; font-size: 1.7rem; }
.insight-eyebrow { font: 600 0.7rem var(--font-mono, monospace); text-transform: uppercase; letter-spacing: 0.12em; color: #626348; }
.insight-summary { display: grid; grid-template-columns: repeat(3, 1fr); margin: 24px 0; background: #173f38; color: #f7efd9; padding: 22px 12px; }
.insight-summary > div { display: grid; text-align: center; gap: 6px; }
.insight-summary strong { font: 700 2rem Georgia, serif; }
.insight-summary span { font-size: 0.72rem; letter-spacing: 0.02em; }
.insight-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; }
.insight-grid h3 { font-size: 1rem; margin: 0 0 16px; }
.insight-yield-row { display: grid; grid-template-columns: 60px 1fr 34px; align-items: center; gap: 10px; margin: 12px 0; font-size: 0.78rem; }
.insight-yield-row strong { text-align: right; font-variant-numeric: tabular-nums; }
.insight-yield-track { background: #dfd7bf; height: 11px; }
.insight-yield-track i { display: block; height: 100%; background: var(--yield-color); }
.insight-note { font-size: 0.72rem; line-height: 1.6; color: #655b45; margin: 15px 0 0; }
.insight-blocked { font-size: 0.78rem; line-height: 1.5; color: #913e22; }
.insight-plan { display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid #cbbd9e; }
.insight-plan strong { font-size: 0.87rem; }
.insight-plan small { display: block; font-size: 0.75rem; color: #655b45; margin-top: 5px; }
.insight-plan > span { white-space: nowrap; font-size: 0.7rem; font-weight: 700; }
.insight-plan button { min-height: 44px; padding: 8px 12px; }
.insight-dice { display: grid; grid-template-columns: repeat(11, 1fr); gap: 6px; }
.insight-die-column { text-align: center; font-size: 0.7rem; }
.insight-die-column > div { height: 108px; position: relative; margin: 6px 0; background: #e4dac2; }
.insight-die-column i { position: absolute; bottom: 0; left: 0; right: 0; background: #3e7660; min-height: 0; }
.insight-die-column b { position: absolute; left: -2px; right: -2px; border-top: 2px dashed #8a3d1e; }
.insight-standings { margin: 0; padding: 0; list-style: none; }
.insight-standings li { display: flex; justify-content: space-between; align-items: center; padding: 12px 0; border-bottom: 1px solid #cbbd9e; font-size: 0.85rem; }
.insight-standings i { display: inline-block; width: 12px; height: 12px; margin-right: 8px; border: 1px solid #322a1b80; }
@media (max-width: 620px) {
  .table-insights-dialog { padding: 18px; }
  .insight-grid { grid-template-columns: 1fr; gap: 26px; }
  .insight-summary { padding: 18px 8px; margin: 20px 0; }
  .insight-summary strong { font-size: 1.6rem; }
  .insight-summary span { font-size: 0.65rem; }
}

.preferences-dialog > .preferences-header { position: sticky; top: -24px; padding: 12px 0; margin-top: -12px; background: var(--paper); z-index: 1; }
@media (max-width: 600px) { .preferences-dialog > .preferences-header { top: -18px; } }

.decision-map-art { pointer-events: none; }
.decision-map-target { cursor: pointer; filter: drop-shadow(0 1px 1px #142b29aa); }
.decision-location-number { display: inline-grid; place-items: center; width: 25px; height: 25px; margin-right: 9px; border-radius: 50%; background: #f6ecd7; color: #153b37; font-size: 0.78rem; flex-shrink: 0; }
#tableDecisionDialog.has-map [data-decision-options] button { background: #ece1c8; color: #283e33; border: 1px solid #a79b7c; transition: box-shadow 120ms ease; }
#tableDecisionDialog.has-map [data-decision-options] button:hover, #tableDecisionDialog.has-map [data-decision-options] button:focus { background: #234d40; color: #fff8e7; }

/* Map controls remain real buttons even when the board is zoomed. */
.decision-map-controls { display: flex; gap: 6px; margin-bottom: 8px; }
.decision-map-controls button { transition: box-shadow 120ms ease; min-width: 44px; min-height: 44px; padding: 6px 10px; color: #173d36; background: #f6ecd7; border: 1px solid #bfa979; font-size: 16px; }
.decision-map-controls button:last-child { margin-left: auto; font-size: 13px; }
.decision-map-controls button:hover:not(:disabled), .decision-map-controls button:focus { color: #fff9e9; background: #245346; }
.decision-map-controls button:disabled { opacity: .45; cursor: default; }
.decision-map-origin circle { fill: none; stroke: #ffe58a; stroke-width: 5; paint-order: stroke; }
[data-decision-map] svg.is-zoomed { cursor: grab; }
[data-decision-map] svg.is-zoomed:active { cursor: grabbing; }

.decision-map-origin { pointer-events: none; }
.decision-map-destination { pointer-events: none; }
.decision-map-destination circle { fill: #164f48; stroke: #ffe58a; stroke-width: 3; }
.decision-map-destination text { fill: #fff1c5; text-anchor: middle; font: 800 var(--map-label-size) system-ui, sans-serif; }
.decision-map-itinerary .decision-map-transfer { stroke-width: 3; stroke-dasharray: 7 7; }
.decision-map-target .decision-map-marker-leader { stroke: #f4dfa2; stroke-width: 2; stroke-dasharray: 4 3; pointer-events: none; }
.decision-map-legend { display: block; color: #ffe58a; font-size: 13px; margin: 0 4px 6px; }

/* Private-table connection and room details. */
.online-connection { min-height: 36px; padding: 4px 9px; margin-left: auto; font: inherit; font-size: 0.7rem; color: var(--ink); background: var(--paper); border: 1px solid var(--line); }
.online-connection.disconnected { color: #7a2e14; background: #fff0dc; }
.online-connection:hover:not(:disabled) { color: var(--ink); background: #fff8e9; border-color: #927c52; }
.online-connection.disconnected:hover:not(:disabled) { color: #7a2e14; background: #ffe5c1; }
.online-play .dock-history { display: none; }
.online-play .dock-bar { grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "hand dice primary"; }
.online-play .dock-bar:has(.event-die) { grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "hand dice primary"; }
@media (max-width: 1039px) and (min-height: 481px) {
  .online-play .dock-bar, .online-play .dock-bar:has(.event-die) { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "hand hand" "dice primary"; }
}
.online-play .dock-primary button { padding-inline: 10px; }
.online-play .status-banner { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 4px 12px; }
.online-play .status-banner #turnTitle { grid-column: 1; grid-row: 1; overflow-wrap: anywhere; }
.online-play .status-banner #phaseHelp { grid-column: 1 / -1; grid-row: 2; margin-left: 0; }
.online-play .online-connection { grid-column: 2; grid-row: 1; border-radius: 8px; }
@media (min-width: 1040px) {
  .online-play .status-banner { grid-template-columns: auto minmax(0, 1fr) auto; }
  .online-play .status-banner #turnTitle { max-width: 16ch; }
  .online-play .status-banner #phaseHelp { grid-column: 2; grid-row: 1; overflow-wrap: anywhere; }
  .online-play .online-connection { grid-column: 3; }
}
@media (max-height: 480px) and (max-width: 1039px) {
  .online-play .status-banner { grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; padding-block: 4px; }
  .online-play .status-banner #phaseHelp { grid-column: 2; grid-row: 1; margin-left: 0; }
  .online-play .online-connection { grid-column: 3; }
  .bottom-dock .compact-resource-card { grid-template-columns: 20px minmax(0, 1fr); min-height: 46px; padding: 5px; }
  .bottom-dock .compact-resource-card .resource-coin { width: 20px; height: 20px; }
  .bottom-dock .compact-resource-card > span:last-child { grid-column: 1 / -1; }
}
.online-room-dialog { box-sizing: border-box; width: min(620px, calc(100vw - 16px)); max-height: calc(100dvh - 16px); overflow: hidden; padding: 16px; color: var(--ink); background: var(--paper); border: 2px solid var(--line); border-radius: 16px; }
.online-room-dialog[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 12px; }
.online-room-dialog::backdrop { background: rgb(0 20 15 / 65%); }
.online-room-dialog header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.online-room-dialog h2 { margin: 0; font-size: 1.25rem; }
.online-room-dialog button { min-height: 44px; }
.online-room-dialog [data-room-close] { flex: 0 0 44px; min-width: 44px; }
.online-room-body { min-height: 0; min-width: 0; overflow: auto; overscroll-behavior: contain; padding: 0 6px 6px 0; }
.online-room-body > p { margin: 0 0 12px; line-height: 1.4; }
.online-room-body [data-room-reload], .online-room-body [data-room-reconnect] { margin-bottom: 12px; }
.online-presence-help { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 8px; }
.online-presence-help summary { display: flex; align-items: center; min-height: 44px; cursor: pointer; font-size: .85rem; font-weight: 700; }
.online-presence-help summary::before { content: "+"; margin-right: 8px; }
.online-presence-help[open] summary::before { content: "−"; }
.online-room-columns { display: grid; gap: 16px; }
.online-room-columns > section { min-width: 0; }
.online-room-columns > section > p:first-child { margin: 0 0 8px; }
.online-room-dialog .online-table-summary { margin-top: 0; padding: 8px; }
.online-room-dialog .online-table-summary ul { margin-top: 6px; gap: 6px; }
.online-room-dialog .online-invite { padding-top: 0; gap: 6px; }
.online-room-dialog .online-hint { margin: 0; font-size: .8rem; line-height: 1.4; }
.online-room-body > .online-storage-hint { margin-bottom: 8px; }
.online-room-dialog footer { border-top: 1px solid var(--line); padding-top: 10px; }
@media (min-width: 560px) {
  .online-room-columns { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
@media (max-height: 480px) {
  .online-room-dialog[open] { padding: 12px; gap: 8px; }
}
@media (max-width: 680px) { .online-connection { min-height: 44px; } }


.cost-card-note {
  display: block;
  font-size: 0.75rem;
  line-height: 1.4;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.01em;
}

/* Mobile table: the board stays in view until a player explicitly opens a sheet. */
.board-targets-button { min-height: 44px; padding: 8px 12px; border: 1px solid #d4c19a; border-radius: 12px; background: #fbf1da; color: #173d36; font: 700 13px system-ui, sans-serif; box-shadow: 0 3px 12px #001b1438; white-space: nowrap; }
.board-targets-button[hidden] { display: none; }
.board-targets-button:hover:not(:disabled) { color: #173d36; background: #fff8e9; border-color: #927c52; }
.module-drawer:not(.open) { pointer-events: none; }
.module-drawer-toggle { pointer-events: auto; }
.board-guide-navigation { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 10px 0; }
.board-guide-navigation button { width: 48px; min-height: 44px; border-radius: 10px; padding: 6px; }
.board-guide-navigation span { font: 600 12px system-ui, sans-serif; color: #645338; }
.board-guide { border-radius: 16px; box-shadow: 0 8px 28px #001b1460; }
.board-guide [data-guide-confirm] { border-radius: 10px; }
.board-guide.compact-preview { padding: 10px; }
.board-guide.compact-preview [data-guide-pips] { display: none; }
.board-guide.compact-preview [data-guide-tiles] { font-size: 12px; line-height: 1.35; margin: 4px 0; }
.board-guide.compact-preview .board-guide-navigation { margin: 4px 0; }
.board-guide.compact-preview [data-guide-confirm] { position: sticky; bottom: 0; min-height: 44px; box-shadow: 0 -4px 0 #fbf1da; }
@media (max-width: 1039px) {
  .app-shell { background: radial-gradient(ellipse at 55% 35%, #1d5753 0, #103e37 45%, #062820 100%); }
  .player-roster { position: relative; }
  .player-detail { position: absolute; top: calc(100% + 6px); left: 0; width: min(320px, calc(100vw - 16px)); max-height: calc(100dvh - var(--dock-clearance, 128px) - 76px); overflow-y: auto; overscroll-behavior: contain; border-radius: 14px; box-shadow: 0 8px 28px #001b1460; }
  .status-banner { border: 1px solid #e4d7b980; border-radius: 12px; padding: 10px 12px; background: #faf2e1f5; box-shadow: 0 4px 16px #001b1428; font: 500 13px/1.45 system-ui, sans-serif; }
  .status-banner #turnTitle { font: 750 10px system-ui, sans-serif; letter-spacing: .08em; color: #566653; }
  .status-banner #phaseHelp { font: inherit; }
  .player-chip { border-radius: 12px; box-shadow: 0 3px 12px #001b1430; }
  .module-drawer-toggle { border-radius: 12px; min-height: 44px; font: 750 12px system-ui, sans-serif; letter-spacing: .02em; text-transform: none; box-shadow: 0 3px 10px #001b1428; }
  .module-drawer.open { position: fixed; z-index: 30; left: max(8px, env(safe-area-inset-left, 0px)); right: max(8px, env(safe-area-inset-right, 0px)); bottom: max(8px, env(safe-area-inset-bottom, 0px)); top: auto; width: auto; max-width: none; margin: 0; padding: 6px; border: 1px solid #d7c6a1; border-radius: 20px; background: #fbf3e2; box-shadow: 0 -12px 60px #001b1470; pointer-events: auto; }
  .module-drawer.open .module-drawer-toggle { align-self: stretch; min-height: 48px; text-align: left; padding: 12px 16px; border: 0; border-bottom: 1px solid #d7c6a1; border-radius: 14px 14px 0 0; background: #fbf3e2; box-shadow: none; color: #174c40; font-size: 15px; }
  .module-drawer.open .module-panels { max-height: min(62dvh, calc(100dvh - 150px)); padding: 16px 12px; margin: 0; border: 0; border-radius: 0 0 14px 14px; box-shadow: none; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  .module-panels h3 { font-size: 1.35rem; }
  .module-panels button { border-radius: 10px; }
  .board-tools { gap: 8px; align-items: center; }
  .board-tools .icon-button { min-width: 44px; min-height: 44px; border-radius: 12px; box-shadow: 0 3px 12px #001b1438; }
  .bottom-dock { background: linear-gradient(transparent, #062820bb 35%, #062820f5); padding-top: 18px; }
  .bottom-dock .compact-resource-card { border-radius: 10px; box-shadow: inset 0 1px 0 #fff6, 0 2px 5px #001b1429; }
  .dock-primary button, .dock-history button, .dice-readout { border-radius: 12px; }
  .board-guide { max-height: min(45dvh, 310px); overflow-y: auto; overscroll-behavior: contain; }
  .board-guide [data-guide-tip] { display: none; }
}
@media (max-height: 480px) and (max-width: 1039px) {
  .module-drawer.open { left: auto; width: min(400px, 55vw); }
  .module-drawer.open .module-panels { max-height: calc(100dvh - 82px); }
  .board-guide-navigation { margin: 4px 0; }
  .board-guide { max-height: calc(100dvh - 120px); }
}

.board-region { background: radial-gradient(ellipse at 52% 40%, #28665a55, transparent 66%), radial-gradient(ellipse at 8% 95%, #071c1f 0, transparent 58%), linear-gradient(145deg, #16493f, #07342d 58%, #082c28); background-size: auto; }
@media (max-width: 1039px) {
  .hud-left:has(.module-drawer.open) { z-index: 30; }
  .board-tools { display: flex; }
  .board-tools.expanded .board-targets-button { visibility: hidden; }
  .board-tools-fan { right: 52px; }
  .module-drawer.open .module-drawer-toggle:hover, .module-drawer.open .module-drawer-toggle:focus { color: #174c40; background: #eee5d2; }
  .board-guide-navigation button { color: #174c40; background: #eee4cd; border: 1px solid #bca984; box-shadow: none; }
  .board-guide-navigation button:hover { color: #fff5df; background: #174c40; }
}

/* Keep the one-handed Actions fan on phones and tablets. */
@media (max-width: 1039px) {
  .action-radial { background: #072b25cc; }
  .radial-close { width: 80px; height: 80px; }
  .action-radial button.radial-wedge-tag { width: 44px; height: 44px; padding: 2px; border-radius: 50%; clip-path: circle(50%); font-size: 9px; letter-spacing: 0; }
  .action-radial .radial-wedge-tag svg { width: 16px; height: 16px; }
  .action-radial .radial-wedge-tag:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
  .action-radial .radial-sat-label { z-index: 1; left: 50%; top: auto; bottom: 10px; transform: translateX(-50%); width: calc(100% - 12px); white-space: normal; text-align: center; color: var(--ink); text-shadow: none; font: 650 12px/1.15 system-ui, sans-serif; letter-spacing: 0; text-transform: none; }
  .action-radial .radial-sat-token { justify-content: flex-start; padding-top: 8px; }
  .action-radial .radial-sat-token .build-icon, .action-radial .radial-sat-icon { width: 22px; height: 20px; }
  .action-radial .radial-sat-token svg { width: 20px; height: 20px; }
  .action-radial .radial-sat-pips { display: none; }
  .action-radial .radial-readout { left: 12px; top: var(--radial-readout-top, 12px); bottom: auto; width: calc(100vw - 24px); max-height: 128px; overflow: auto; padding: 10px 12px; border-radius: 12px; }
  .action-radial .radial-readout-row { flex-wrap: wrap; }
  .action-radial .radial-readout-note { white-space: normal; }
  .action-radial .radial-readout-status { font: 500 12px/1.4 system-ui, sans-serif; letter-spacing: 0; text-transform: none; }
  .player-chip .player-stat, .player-chip .player-route { display: none; }
  .player-chip:has(.player-score-stacked) { padding-inline: 4px; gap: 4px; }
  .player-chip:has(.player-score-stacked) .player-swatch { width: 12px; }
  .player-score-stacked { flex-direction: column; align-items: center; gap: 0; }
  .player-score-stacked .player-score-unit { font-size: 8px; letter-spacing: .02em; }
  .board-guide .board-guide-navigation button:not(:disabled) { color: #174c40; background: #eee4cd; }
}
@media (max-height: 480px) and (max-width: 1039px) {
  .action-radial .radial-readout { left: 12px; top: auto; bottom: 12px; width: min(320px, calc(100vw - 390px)); }
  .action-radial.hub-on-left .radial-readout { left: auto; right: 12px; }
}
@media (max-width: 1039px) {
  .bottom-dock .compact-resource-card > span:last-child { white-space: normal; overflow: visible; overflow-wrap: normal; text-align: center; }
  .board-popover { position: fixed; left: 10px; right: 10px; top: auto; bottom: calc(var(--dock-clearance, 150px) + 8px); min-width: 0; max-width: none; max-height: calc(100dvh - var(--dock-clearance, 150px) - 160px); overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; cursor: auto; padding: 12px; border-radius: 16px; background: #fbf3e2; border: 1px solid #d7c6a1; box-shadow: 0 8px 28px #001b1460; }
  .board-popover button { min-height: 44px; border-radius: 10px; }
}
@media (max-height: 480px) and (max-width: 1039px) {
  .board-popover { left: auto; right: 10px; width: min(360px, calc(100vw - 30px)); max-height: calc(100dvh - var(--dock-clearance, 80px) - 120px); }
}

.victory-row-detail { display: block; margin-top: 3px; color: var(--muted); font-size: .7rem; font-weight: 400; }

/* Keep the invite usable on narrow phones and on LAN pages without Clipboard API. */
.online-card { scroll-margin-top: 16px; }
.online-invite { display: grid; gap: 10px; padding-top: 16px; padding-bottom: 8px; min-width: 0; }
.online-invite input, .online-form input { width: 100%; min-width: 0; box-sizing: border-box; }
.online-invite .online-hint:empty { display: none; }
.online-local-help { padding-top: 12px; padding-bottom: 20px; font-size: .9rem; line-height: 1.5; }
.online-local-help summary { cursor: pointer; padding-block: 10px; font-weight: 700; }
.online-local-help code { overflow-wrap: anywhere; }
.online-form input, .online-invite input {
  min-height: 44px; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: 0; background: var(--paper); color: var(--ink); font-size: 16px;
}
.online-form .setup-field, .online-invite .setup-field { min-width: 0; max-width: none; }
.online-invite button { min-height: 44px; }
.online-invite select { width: 100%; min-height: 44px; }

/* Reserve a landing spot for the movable hub so its default position never
   covers resources, history, or the end-turn button. */
.action-hub-home { grid-area: hub; width: 104px; height: 104px; pointer-events: none; }
@media (min-width: 1040px), (min-width: 681px) and (max-height: 480px) {
  .dock-bar, .online-play .dock-bar { grid-template-columns: minmax(0, 1fr) auto auto auto auto; grid-template-areas: "hand dice history primary hub"; }
}
@media (max-width: 1039px) {
  .action-hub-home { width: 80px; height: 80px; }
}
@media (max-width: 1039px) and (min-height: 481px), (max-width: 680px) {
  .dock-bar, .dock-bar:has(.event-die) { grid-template-columns: auto minmax(0, 1fr) 80px; grid-template-areas: "hand hand hand" "dice history hub" "primary primary hub"; }
  .dock-primary { justify-content: flex-end; }
  .dock-history { justify-content: flex-end; }
  .online-play .dock-bar { grid-template-columns: auto minmax(0, 1fr) 80px; grid-template-areas: "hand hand hand" "dice primary hub"; }
}

/* Larger tables keep every score tappable without another row over the board. */
@media (max-width: 480px) {
  .player-list:has(.player-chip:nth-child(5)) .player-chip {
    flex-direction: column;
    gap: 2px;
    padding: 4px 2px;
    min-height: 48px;
  }
  .player-list:has(.player-chip:nth-child(5)) .player-swatch { width: 24px; height: 6px; border-radius: 3px; }
  .player-list:has(.player-chip:nth-child(5)) .player-score { gap: 2px; }
  .player-list:has(.player-chip:nth-child(5)) .player-score-num { font-size: 20px; }
  .player-list:has(.player-chip:nth-child(5)) .player-score-unit { font-size: 8px; }
}

@media (min-width: 1040px) and (max-height: 850px) {
  .hud-left { gap: 8px; }
  .player-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .player-chip.expanded { grid-column: 1 / -1; }
  .player-chip { padding: 7px 10px; gap: 3px; }
  .player-chip-main { gap: 7px; }
  .player-chip .player-score-num { font-size: 24px; }
  .player-chip-sub { font-size: 11px; padding-left: 0; gap: 4px 6px; }
  .module-drawer-toggle { padding: 8px 10px; }
  .module-drawer.open .module-panels { padding: 6px; }
}

/* A board choice can have hundreds of legal edges. Keep its controls fixed
   and browse one location at a time instead of requiring a long choice list. */
.map-choice-dialog .decision-layout { grid-template-columns: 1fr; gap: 12px; }
.map-choice-dialog [data-decision-map] { position: static; }
.map-choice-dialog [data-decision-map] svg { max-height: 44dvh; }
.map-choice-dialog [data-decision-map] small { display: none; }
.map-choice-dialog [data-decision-options] { max-height: none; overflow: visible; scrollbar-gutter: auto; padding: 0; }
.decision-map-navigation { display: grid; grid-template-columns: 48px minmax(0, 1fr) 48px; align-items: center; gap: 8px; }
.decision-map-navigation button { text-align: center; font-size: 24px; }
.decision-map-selection { text-align: center; color: #193e34; line-height: 1.3; }
.decision-map-selection strong { display: block; }
.decision-map-selection small { display: block; margin-top: 3px; color: #65563d; }
.decision-map-selection .decision-option-detail { font-size: 12px; line-height: 1.35; }
.map-choice-dialog [data-decision-confirm] { text-align: center; font-size: 16px; font-weight: 700; }
.decision-map-actions { display: grid; gap: 6px; }
.decision-map-actions button { min-height: 44px; text-align: center; font-size: 14px; line-height: 1.25; }
.compact-map-choice .decision-map-target:not(.selected) text { display: none; }
.compact-map-choice .decision-map-target:not(.selected) circle { fill: #a9cfaf; stroke: #173d36; stroke-width: 2; r: 5; }
@media (max-width: 620px) {
  .map-choice-dialog { padding: 16px; }
  .map-choice-dialog > p { margin: 8px 0 12px; font-size: 14px; }
  .map-choice-dialog [data-decision-map] svg { max-height: 37dvh; }
}
@media (max-height: 500px) and (min-width: 621px) {
  .map-choice-dialog { padding: 12px 18px; height: calc(100dvh - 32px); }
  .map-choice-dialog[open] { display: flex; flex-direction: column; }
  .map-choice-dialog h2 { margin: 0 0 4px; font-size: 1.2rem; }
  .map-choice-dialog [data-decision-art]:not([hidden]) { position: absolute; top: 10px; right: 16px; width: 44px; height: 44px; margin: 0; }
  .map-choice-dialog:has([data-decision-art]:not([hidden])) > h2 { padding-right: 58px; min-height: 44px; display: flex; align-items: center; }
  .map-choice-dialog > p { margin: 0 0 8px; font-size: 13px; }
  .map-choice-dialog > h2, .map-choice-dialog > p { flex-shrink: 0; }
  .map-choice-dialog .decision-layout { grid-template-columns: minmax(0, 1.6fr) minmax(180px, 1fr); align-items: center; flex: 1; min-height: 0; }
  .map-choice-dialog [data-decision-map] { display: flex; flex-direction: column; height: 100%; min-height: 0; }
  .map-choice-dialog .decision-map-controls, .map-choice-dialog .decision-map-legend { flex-shrink: 0; }
  .map-choice-dialog [data-decision-map] svg { flex: 1; height: 100%; min-height: 0; max-height: none; }
}

/* Landscape puts table information beside the island, leaving its full
   height available for inspecting routes at a useful playing zoom. */
@media (max-width: 1039px) and (max-height: 480px) and (orientation: landscape) {
  .app-shell { --landscape-rail: clamp(164px, 20vw, 184px); }
  .board-region {
    --board-safe-top: calc(8px + env(safe-area-inset-top, 0px));
    --board-safe-left: calc(var(--landscape-rail) + 20px + env(safe-area-inset-left, 0px));
    --board-safe-right: calc(8px + env(safe-area-inset-right, 0px));
    --board-safe-bottom: calc(var(--dock-clearance, 80px) + 4px);
  }
  .hud-left { right: auto; width: var(--landscape-rail); gap: 6px; }
  .player-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px; overflow: visible; }
  .player-list:has(.player-chip:nth-child(5)) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .player-chip {
    display: grid; grid-template-columns: 12px minmax(0, 1fr); grid-template-rows: 12px 18px;
    align-items: center; min-height: 46px; padding: 4px 6px; gap: 2px 4px; border-radius: 10px;
  }
  .player-chip .player-name {
    position: static; grid-column: 1 / -1; grid-row: 1; width: auto; height: auto; margin: 0;
    clip: auto; clip-path: none; overflow: hidden; text-overflow: ellipsis;
    font: 700 11px/13px system-ui, sans-serif; text-align: left;
  }
  .player-chip .player-swatch { grid-column: 1; grid-row: 2; width: 12px; height: 12px; border-radius: 4px; }
  .player-chip .player-score { grid-column: 2; grid-row: 2; justify-content: flex-start; gap: 3px; }
  .player-chip .player-score-num { font-size: 18px; line-height: 20px; }
  .player-chip .player-score-unit { font-size: 8px; line-height: 9px; letter-spacing: 0; }
  .player-chip .player-score-stacked { flex-direction: row; flex-wrap: wrap; gap: 0 3px; }
  .player-chip:has(.player-score-stacked) { gap: 2px 4px; }
  .player-list:has(.player-chip:nth-child(5)) .player-chip { grid-template-columns: 8px minmax(0, 1fr); padding-inline: 4px; column-gap: 2px; }
  .player-list:has(.player-chip:nth-child(5)) .player-swatch { width: 8px; }
  .player-list:has(.player-chip:nth-child(5)) .player-score-unit { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .hud-left .status-banner {
    position: static; transform: none; width: 100%; max-width: none; min-height: 0;
    display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding: 9px 10px; font-size: 12px; line-height: 1.4;
  }
  .online-play .online-connection { position: fixed; top: max(8px, env(safe-area-inset-top, 0px)); right: max(8px, env(safe-area-inset-right, 0px)); min-height: 44px; max-width: 150px; margin: 0; }
  .online-play .board-notices { right: 166px; }
  .status-banner #phaseHelp:not(:empty) { margin-left: 0; }
  .module-drawer { margin-top: 0; }
  .module-drawer:not(.open) .module-drawer-toggle { width: 100%; }
  .board-notices { top: max(8px, env(safe-area-inset-top, 0px)); left: calc(var(--landscape-rail) + 28px); right: 12px; transform: none; margin-inline: auto; }
  .player-detail { position: fixed; left: calc(var(--landscape-rail) + 20px); top: 8px; width: min(320px, calc(100vw - var(--landscape-rail) - 32px)); max-height: calc(100dvh - var(--dock-clearance) - 16px); overflow-y: auto; }
  .bottom-dock { padding-top: 8px; background: none; }
  .dock-bar, .online-play .dock-bar, .dock-bar:has(.event-die) {
    grid-template-columns: minmax(0, 1fr) auto auto auto auto; grid-template-areas: "hand dice history primary hub"; gap: 6px;
  }
  .online-play .dock-bar { grid-template-columns: minmax(0, 1fr) auto auto auto; grid-template-areas: "hand dice primary hub"; }
  /* Extra resources share one sideways strip. Keep the development-card
     button outside it, and expose a scrollbar when a small phone needs it. */
  .turn-hand { display: flex; max-width: none; gap: 4px; align-items: center; }
  .hand-resource-rows { display: flex; flex: 0 1 auto; gap: 4px; padding-block: 3px; pointer-events: auto; touch-action: pan-x; scrollbar-width: thin; scrollbar-color: #c4bea2 #082e27; }
  .hand-resource-rows::-webkit-scrollbar { display: block; height: 3px; }
  .hand-resource-rows::-webkit-scrollbar-thumb { background: #c4bea2; border-radius: 2px; }
  .compact-hand-row { display: contents; }
  .bottom-dock .compact-resource-card { flex: 0 0 48px; width: 48px; padding-inline: 3px; }
  .compact-currency-row { flex: 0 0 auto; flex-wrap: nowrap; align-items: center; margin-top: 0; }
  .dice-readout { min-width: 64px; }
  .dice-pair { gap: 4px; }
  .dice-pair:has(.event-die) { display: grid; grid-template-columns: 44px 44px; gap: 2px 4px; }
  .dice-pair .event-die { grid-column: 1 / -1; justify-self: center; width: 28px; height: 28px; }
  .dice-pair .event-die-glyph { width: 24px; height: 24px; font-size: 20px; }
  .board-guide { top: max(8px, env(safe-area-inset-top, 0px)); left: 8px; right: auto; bottom: auto; width: 210px; max-height: calc(100dvh - var(--dock-clearance) - 20px); }
}
.board-tools-fan .play-view { width: 68px; min-width: 68px; padding: 4px; font: 750 11px/1.2 system-ui, sans-serif; white-space: normal; }

/* Sideways phones have room for the two piles beside each other. Keep the
   confirmation medallion beside both, including commodity-heavy hands. */
@media (orientation: landscape) and (max-height: 500px) and (min-width: 560px) and (max-width: 1100px) {
  .trade-dialog.discard-dialog { width: min(100%, 980px); max-height: calc(100dvh - 16px); }
  .discard-dialog .trade-dialog-header { padding: 10px 12px; flex-shrink: 0; }
  .discard-dialog .trade-dialog-body { padding: 6px 12px; }
  .discard-dialog .trade-dialog-actions { padding: 8px 12px max(8px, env(safe-area-inset-bottom, 0px)); flex-shrink: 0; }
  .discard-dialog .trade-orbit-layout { grid-template-columns: minmax(0, 1fr) 84px; gap: 12px; }
  .discard-dialog .trade-orbit { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .discard-dialog .trade-drop-row { grid-template-columns: repeat(5, minmax(44px, 1fr)); gap: 5px; padding: 8px; align-content: start; }
  .discard-dialog .trade-row-heading { grid-column: 1 / -1; display: grid; gap: 4px; align-content: start; }
  .discard-dialog .trade-row-heading small { text-align: left; font-size: 10px; }
  .discard-dialog .trade-card-row.discard-cards { display: contents; }
  .discard-dialog .trade-move-card { height: 72px; grid-template-rows: 20px 16px 22px; padding: 4px 2px; }
  .discard-dialog .trade-move-card .resource-coin { width: 20px; height: 20px; }
  .discard-dialog .trade-hub { width: 84px; height: 84px; }
  .discard-dialog .trade-hub-label { font-size: 9px; letter-spacing: .12em; }
}
@media (orientation: landscape) and (max-height: 500px) and (min-width: 560px) and (max-width: 639px) {
  .discard-dialog .trade-drop-row { grid-template-columns: repeat(4, minmax(44px, 1fr)); }
}

/* On a shorter phone, two shallow rows keep all commodities visible. Their
   total height stays close to the thumb hub instead of stacking full cards. */
@media (max-width: 760px) and (max-height: 480px) and (orientation: landscape) {
  .turn-hand { gap: 3px; }
  .hand-resource-rows { gap: 3px; }
  .bottom-dock .compact-resource-card { flex-basis: 46px; width: 46px; }
  .turn-hand:has(.compact-hand-row:nth-child(2)), .turn-hand:has(.compact-currency-row) { align-items: flex-start; }
  .hand-resource-rows:has(.compact-hand-row:nth-child(2)) { display: grid; grid-template-columns: repeat(5, 46px); overflow: visible; }
  .hand-resource-rows:has(.compact-currency-row) { display: grid; grid-template-columns: repeat(5, 46px); overflow: visible; }
  .compact-currency-row { grid-column: span 2; align-self: center; }
  .turn-hand:has(.compact-hand-row:nth-child(2)) .dev-hand-card, .turn-hand:has(.compact-currency-row) .dev-hand-card { margin-top: 3px; }
  .bottom-dock .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-resource-card {
    height: 46px; grid-template-rows: 18px 18px; padding-block: 4px;
  }
  .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-resource-card .resource-coin { width: 18px; height: 18px; }
  .bottom-dock .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-resource-card > span:last-child { font-size: 9px; line-height: 9px; }
}

/* View and history live in the Actions fan. The map toolbar is temporary. */
.radial-sat[hidden] { display: none; }
.board-tools-fan { top: auto; bottom: 0; right: 0; transform: translateY(8px); }
.board-tools.expanded .board-tools-fan { transform: translateY(0); }
.dock-bar, .online-play .dock-bar, .dock-bar:has(.event-die) {
  grid-template-columns: minmax(0, 1fr) auto auto auto; grid-template-areas: "hand dice primary hub";
}
@media (max-width: 1039px) and (min-height: 481px), (max-width: 680px) and (orientation: portrait) {
  .dock-bar, .online-play .dock-bar, .dock-bar:has(.event-die) {
    grid-template-columns: auto minmax(0, 1fr) 80px; grid-template-areas: "hand hand hand" "dice primary hub";
  }
}

.setup-objective { margin: 0; padding: 10px 12px; border-left: 3px solid var(--line); color: var(--ink); background: var(--paper); font-size: .9rem; line-height: 1.45; }

#devChoiceHost:not(:empty) { padding: 12px; margin-bottom: 12px; border: 1px solid #a79c7b; border-radius: 8px; }
.dev-choice-title { margin: 0 0 10px; font: 700 14px/1.4 system-ui, sans-serif; }
.dev-choice-cancel { margin-top: 8px; }

#devChoiceHost select, #devChoiceHost button { min-height: 44px; }
#devChoiceHost select { appearance: none; min-width: 0; width: 100%; height: 44px; padding: 8px 24px 8px 8px; border: 1px solid #a79c7b; border-radius: 6px; color: #302a20; background: #fff5df url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='m2 2 4 4 4-4' fill='none' stroke='%23302a20' stroke-width='2'/%3E%3C/svg%3E") no-repeat right 8px center; font: 600 16px/1.4 system-ui, sans-serif; }
#devChoiceHost .dev-choice-cancel { display: block; width: 100%; }
#devChoiceHost #confirmDevChoice { width: 100%; }

.online-invite-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.online-invite-actions > button { min-height: 44px; flex: 1 1 140px; }

/* A private draw briefly unfolds above the hand without taking board focus. */
.card-receipt {
  position: fixed;
  z-index: 12;
  width: min(300px, calc(100vw - 24px));
  display: flex;
  border: 1px solid #a49a72;
  border-radius: 12px;
  background: #f6efdc;
  color: #231e13;
  box-shadow: 0 3px 0 #b9ae8b, 0 9px 22px #001e1d66;
  overflow: hidden;
}
.card-receipt-arriving { animation: card-receipt-in 360ms cubic-bezier(.2,.75,.25,1) both; }
.card-receipt-open, .card-receipt-dismiss {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  color: inherit;
  margin: 0;
  transform: none;
}
.card-receipt-open {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 10px;
  min-width: 0;
  flex: 1;
  text-align: left;
}
.card-receipt-open:hover, .card-receipt-dismiss:hover { background: #e9dfc6; color: #231e13; transform: none; }
.card-receipt-open:focus-visible, .card-receipt-dismiss:focus-visible { outline: 3px solid #24715c; outline-offset: -4px; }
.card-receipt-art {
  display: grid;
  place-items: center;
  width: 52px;
  height: 64px;
  flex: 0 0 auto;
  border: 1px solid #ada17f;
  border-radius: 5px;
  background: #e8dbb8;
  box-shadow: 2px 3px 0 #c8bb99;
  transform: rotate(-5deg);
}
.card-receipt-art svg { width: 48px; height: 56px; }
.card-receipt-copy { display: grid; gap: 3px; min-width: 0; line-height: 1.2; }
.card-receipt-copy small { font-size: 10px; text-transform: uppercase; letter-spacing: .1em; color: #655a40; }
.card-receipt-copy strong { font-size: 15px; overflow-wrap: anywhere; }
.card-receipt-copy > span { font-size: 11px; font-weight: 500; color: #326149; }
.card-receipt-dismiss { flex: 0 0 44px; min-height: 44px; padding: 0; font-size: 23px; align-self: stretch; }
.card-receipt[data-deck="science"] .card-receipt-art { background: #d4dfad; }
.card-receipt[data-deck="politics"] .card-receipt-art { background: #c4d9e4; }
.card-receipt[data-deck="trade"] .card-receipt-art { background: #ecd79c; }
@keyframes card-receipt-in { from { opacity: 0; transform: translateY(12px) rotate(1deg); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .card-receipt { animation: none; } }

/* Recovery keeps its next step visible instead of offering a stale invitation. */
.online-room-dialog.needs-recovery .online-room-columns,
.online-room-dialog.needs-recovery .online-presence-help { display: none; }

/* Portrait hands with extra card types use two shallow, balanced rows. The
   separate Dev control remains reachable, and currencies occupy spare cells
   instead of adding another full-width row over the board. */
@media (orientation: portrait) and (max-width: 680px) {
  .turn-hand:has(.compact-hand-row:nth-child(2)) {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
  .turn-hand:has(.compact-hand-row:nth-child(2)):not(:has(.dev-hand-card)) {
    grid-template-columns: minmax(0, 1fr);
  }
  .hand-resource-rows:has(.compact-hand-row:nth-child(2)) {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; overflow: visible;
  }
  .hand-resource-rows:has(.compact-hand-row:nth-child(2)) .compact-hand-row { display: contents; }
  .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-currency-row {
    grid-column: span 2; align-self: center; margin-top: 0;
  }
  .bottom-dock .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-resource-card {
    height: 58px; min-height: 58px; grid-template-columns: 20px minmax(0, 1fr);
    grid-template-rows: 20px 22px; padding: 4px;
  }
  .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-resource-card .resource-coin { width: 20px; height: 20px; }
  .turn-hand:has(.compact-hand-row:nth-child(2)) .compact-resource-card > span:last-child { grid-column: 1 / -1; }
}

/* A brief opening ceremony, with every seat's dice kept on the table. */
.opening-roll-dialog { margin: auto; max-width: calc(100vw - 28px); width: min(760px, calc(100vw - 28px)); max-height: calc(100dvh - 28px); padding: clamp(18px, 3vw, 32px); border: 2px solid var(--line); border-radius: 26px; background: var(--paper); color: var(--ink); }
.opening-roll-dialog::backdrop { background: #061d19d9; backdrop-filter: blur(8px); }
.opening-roll-heading { display: flex; align-items: start; justify-content: space-between; gap: 16px; }
.opening-roll-heading h2 { margin: 5px 0 0; font-size: clamp(26px, 4vw, 38px); letter-spacing: -.035em; }
.opening-roll-heading button { min-width: 44px; min-height: 44px; border-radius: 50%; }
.opening-roll-intro { margin: 10px 0 22px; color: var(--muted); }
.opening-roll-seats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.opening-roll-seat { display: flex; flex-direction: column; align-items: center; gap: 10px; min-width: 0; padding: 18px 10px; border: 2px solid transparent; border-radius: 18px; background: #e6e0ce; box-shadow: 0 3px 0 #34473818; transition: border-color .2s, background .2s; }
.opening-roll-seat.is-current { border-color: #9b792c; background: #f7edca; }
.opening-roll-seat.is-winner { border-color: #37775b; background: #d8e8cf; }
.opening-roll-seat h3 { display: flex; align-items: center; gap: 8px; margin: 0; max-width: 100%; overflow-wrap: anywhere; font-size: 17px; }
.opening-roll-badge { flex-shrink: 0; width: 14px; height: 14px; border-radius: 4px; background: var(--player-color); border: 1px solid #0004; box-shadow: inset 0 2px 0 #fff6; }
.opening-roll-dice { display: grid; place-items: center; min-height: 58px; }
.opening-roll-dice .die { width: 48px; height: 48px; }
.opening-roll-waiting { color: #6a695c; font-size: 13px; }
.opening-roll-result { min-height: 36px; font: 700 32px/1.1 Georgia, serif; }
.opening-roll-history { min-height: 16px; color: #586457; font-size: 12px; }
.opening-roll-footer { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 22px; }
.opening-roll-footer p { margin: 0; max-width: 38ch; }
.opening-roll-footer button { min-height: 48px; min-width: 160px; }
@media (max-width: 550px) { .opening-roll-seats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } .opening-roll-seat { padding: 12px 8px; gap: 6px; } .opening-roll-footer { flex-direction: column; align-items: stretch; gap: 12px; } }
@media (max-height: 500px) and (min-width: 551px) { .opening-roll-dialog { padding: 14px 22px; } .opening-roll-seats { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; } .opening-roll-seat { padding: 8px; gap: 4px; } .opening-roll-seat h3 { font-size: 14px; } .opening-roll-dice { min-height: 38px; } .opening-roll-dice .die { width: 34px; height: 34px; } .opening-roll-result { font-size: 24px; min-height: 26px; } .opening-roll-intro { margin: 6px 0 10px; } .opening-roll-footer { margin-top: 12px; } }
@media (prefers-reduced-motion: reduce) { .opening-roll-seat { transition: none; } .opening-roll-dialog .rolling .die { animation: none; } }
.opening-roll-seats[data-seat-count="4"], .opening-roll-seats[data-seat-count="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.opening-roll-history:empty { display: none; }
.online-opening { padding: 18px; border-radius: 20px; background: var(--paper); color: var(--ink); margin: 16px 0; }
.online-opening > h3 { margin: 0 0 16px; }
@media (max-height: 500px) and (min-width: 551px) {
  .opening-roll-seat { display: grid; grid-template-columns: 1fr auto; justify-items: center; }
  .opening-roll-seat h3, .opening-roll-history { grid-column: 1 / -1; }
  .opening-roll-result { padding-right: 12px; }
}
.opening-roll-dice .die .pip { width: 16%; height: 16%; transform: translate(-50%, -50%); right: auto; bottom: auto; }
.opening-roll-dice .die .tl, .opening-roll-dice .die .ml, .opening-roll-dice .die .bl { left: 25%; }
.opening-roll-dice .die .tr, .opening-roll-dice .die .mr, .opening-roll-dice .die .br { left: 75%; }
.opening-roll-dice .die .c { left: 50%; }
.opening-roll-dice .die .tl, .opening-roll-dice .die .tr { top: 25%; }
.opening-roll-dice .die .ml, .opening-roll-dice .die .mr, .opening-roll-dice .die .c { top: 50%; }
.opening-roll-dice .die .bl, .opening-roll-dice .die .br { top: 75%; }
.opening-roll-seat.is-eliminated { background: #dedbd0; color: #666a60; }
.opening-roll-seat.is-eliminated .opening-roll-dice { opacity: .65; }
