/* My 50's Life -- hand-written CSS, no build step, no framework.
   Palette is period: cream, teal, coral, brass, charcoal. */

:root {
  --color-bg: #f4ece0;
  --color-surface: #fffaf1;
  --color-surface-alt: #ece0cd;
  --color-text: #241f1b;
  --color-text-muted: #6b5f52;
  --color-border: #cbb9a0;
  --color-primary: #1f7a75;
  --color-primary-hover: #17605c;
  --color-accent: #d4573f;
  --color-accent-hover: #b8452f;
  --color-brass: #b8894a;
  --color-danger: #a8322a;
  --color-success: #3f7a45;
  --color-wealth: #b8894a;
  --color-knowledge: #3b6ea8;
  --color-happiness: #d4573f;
  --color-standing: #7a4f9e;
  --shadow: 0 2px 0 var(--color-border), 0 6px 18px rgba(36, 31, 27, 0.12);
  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #171a1c;
    --color-surface: #21262a;
    --color-surface-alt: #2b3136;
    --color-text: #f2ece2;
    --color-text-muted: #a79c8d;
    --color-border: #3d454b;
    --color-primary: #4bc0b8;
    --color-primary-hover: #6fd4cd;
    --color-accent: #ef7a5f;
    --color-accent-hover: #ff9276;
    --color-brass: #d6a765;
    --color-danger: #e2685e;
    --color-success: #6bbf72;
    --color-wealth: #d6a765;
    --color-knowledge: #6fa8e0;
    --color-happiness: #ef7a5f;
    --color-standing: #b58fd0;
    --shadow: 0 2px 0 #000, 0 6px 20px rgba(0, 0, 0, 0.5);
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background-color: var(--color-bg);
  color: var(--color-text);
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

h1,
h2,
h3 {
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

h1 {
  font-size: clamp(1.8rem, 5vw, 3rem);
}

a {
  color: var(--color-primary);
}

/* --- shared shell --------------------------------------------------------- */

.wrap {
  max-width: 44rem;
  margin: 0 auto;
  padding: 2rem 1.25rem 4rem;
}

.card {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.5rem;
}

.card + .card {
  margin-top: 1.25rem;
}

.muted {
  color: var(--color-text-muted);
}

.tagline {
  color: var(--color-text-muted);
  font-size: 1.05rem;
  margin-top: 0.5rem;
}

.rule {
  height: 4px;
  background: repeating-linear-gradient(
    90deg,
    var(--color-accent) 0 18px,
    var(--color-primary) 18px 36px
  );
  border-radius: 2px;
  margin: 1.25rem 0;
}

/* --- buttons -------------------------------------------------------------- */

.btn {
  display: inline-block;
  font: inherit;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.85rem 1.4rem;
  border-radius: var(--radius);
  border: 2px solid var(--color-primary);
  background: var(--color-primary);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
}

.btn:hover {
  background: var(--color-primary-hover);
  border-color: var(--color-primary-hover);
}

.btn-accent {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.btn-accent:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
}

.btn-ghost {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-border);
}

.btn-block {
  display: block;
  width: 100%;
}

.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* --- forms ---------------------------------------------------------------- */

label {
  display: block;
  font-weight: 700;
  margin-bottom: 0.35rem;
}

/* Every text-entry control is styled together. Listing only text and
   password left email inputs, number inputs, selects and the contact
   textarea on browser defaults, which is why they read as unfinished
   beside the buttons -- the era this game is set in did not do bland. */

input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="search"],
input[type="tel"],
input[type="url"],
input[type="date"],
textarea,
select {
  font: inherit;
  width: 100%;
  padding: 0.75rem 0.9rem;
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  /* The same seated look the cards and buttons have. */
  box-shadow: inset 0 2px 0 rgba(36, 31, 27, 0.06);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

textarea {
  display: block;
  min-height: 8rem;
  resize: vertical;
  line-height: 1.5;
}

/* The arrow is drawn here rather than fetched, so the control still has one
   with the native appearance turned off and no request goes out for it. */
select {
  appearance: none;
  padding-right: 2.4rem;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
    linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
  background-position:
    right 1.15rem top 55%,
    right 0.85rem top 55%;
  background-size: 0.34rem 0.34rem, 0.34rem 0.34rem;
  background-repeat: no-repeat;
  cursor: pointer;
}

input::placeholder,
textarea::placeholder {
  color: var(--color-text-muted);
  opacity: 0.85;
}

input[type="text"]:hover,
input[type="password"]:hover,
input[type="email"]:hover,
input[type="number"]:hover,
input[type="search"]:hover,
textarea:hover,
select:hover {
  border-color: var(--color-text-muted);
}

input[type="text"]:focus,
input[type="password"]:focus,
input[type="email"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="date"]:focus,
textarea:focus,
select:focus {
  border-color: var(--color-primary);
  box-shadow: inset 0 2px 0 rgba(36, 31, 27, 0.06),
              0 0 0 3px rgba(31, 122, 117, 0.18);
  outline: none;
}

input:disabled,
textarea:disabled,
select:disabled {
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--color-primary);
  width: 1.05rem;
  height: 1.05rem;
}

input[type="range"] {
  accent-color: var(--color-primary);
}

/* Focus-visible still wins for keyboard users, over the softer focus ring. */
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
.btn:focus-visible,
.avatar-option:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

.field-hint {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

.field + .field {
  margin-top: 1rem;
}

.error {
  color: var(--color-danger);
  font-weight: 700;
  margin-bottom: 0.75rem;
}

/* --- avatar picker -------------------------------------------------------- */

.avatar-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.75rem;
  margin-top: 0.5rem;
}

.avatar-option {
  position: relative;
  display: block;
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface-alt);
  padding: 0.6rem;
  cursor: pointer;
  text-align: center;
}

.avatar-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.avatar-option:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--color-surface);
  box-shadow: inset 0 0 0 2px var(--color-accent);
}

.avatar-option[data-taken="true"] {
  opacity: 0.4;
}

.avatar-swatch {
  width: 100%;
  height: 4.5rem;
  border-radius: 6px;
  margin-bottom: 0.4rem;
}

.avatar-name {
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.25;
}

/* --- controller (phone) --------------------------------------------------- */

/* --- the phone controller ------------------------------------------------- */

/* A controller is a game pad, not a document, and every browser gesture that
   treats it as a document is a bug in the middle of somebody's turn.
   `overscroll-behavior: none` is the one that matters: on Chrome for Android
   a downward swipe on a non-scrolling page triggers pull-to-refresh, which
   reloads the controller mid-question. It has to be set on the element that
   defines the viewport, hence the `:has()` on `html` as well as the body.
   The horizontal half stops an edge swipe from navigating back. */

html:has(body.controller-body),
body.controller-body {
  overscroll-behavior: none;
  height: 100%;
  overflow: hidden;
}

body.controller-body {
  /* No double-tap zoom and no 300ms wait before a tap registers. */
  touch-action: manipulation;
  /* A long press on a button should not offer to copy its label. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

/* Anything a player genuinely types into stays selectable. */
body.controller-body input,
body.controller-body textarea {
  -webkit-user-select: text;
  user-select: text;
}

.controller {
  height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  /* Clear of the notch, the rounded corners and the home indicator. */
  padding:
    calc(0.9rem + env(safe-area-inset-top))
    calc(0.9rem + env(safe-area-inset-right))
    calc(0.9rem + env(safe-area-inset-bottom))
    calc(0.9rem + env(safe-area-inset-left));
}


.ctl-header {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
}

.ctl-chip {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  flex: 0 0 auto;
  border: 2px solid var(--color-border);
}

.ctl-name {
  font-weight: 800;
}

.ctl-tracks {
  display: flex;
  gap: 0.4rem;
  font-size: 0.78rem;
  margin-left: auto;
  text-align: right;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.track {
  font-weight: 700;
  white-space: nowrap;
}

.track-wealth { color: var(--color-wealth); }
.track-knowledge { color: var(--color-knowledge); }
.track-happiness { color: var(--color-happiness); }
.track-standing { color: var(--color-standing); }

.ctl-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.75rem;
  /* The prompt is the only thing on the controller that scrolls, and its
     scrolling never escapes to the page behind it -- which is the other
     half of keeping a stray swipe from reloading the game. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.ctl-status {
  text-align: center;
  color: var(--color-text-muted);
  font-weight: 700;
  padding: 2rem 1rem;
}

.ctl-prompt {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1rem;
  font-size: 1.05rem;
  font-weight: 600;
}

.ctl-choices {
  display: grid;
  gap: 0.6rem;
}

.choice-btn {
  font: inherit;
  font-weight: 700;
  text-align: left;
  padding: 1rem;
  min-height: 3.6rem;
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
}

.choice-btn:active {
  background: var(--color-surface-alt);
}

.choice-effects {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-muted);
  margin-top: 0.25rem;
}

.distance-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.5rem;
}

.distance-btn {
  font: inherit;
  font-size: 1.3rem;
  font-weight: 800;
  padding: 1rem 0;
  border: 2px solid var(--color-primary);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-primary);
  cursor: pointer;
}

/* With previews the buttons carry a label, so they need room to say it and
   two to a row rather than five. */

.distance-grid.is-detailed {
  grid-template-columns: repeat(2, 1fr);
}

.distance-btn.is-detailed {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  padding: 0.7rem 0.8rem;
  text-align: left;
  line-height: 1.25;
}

.distance-btn .distance-n {
  font-size: 1.25rem;
  font-weight: 800;
}

.distance-btn .distance-label {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-text);
}

.distance-btn .distance-extra {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-wealth);
}

/* The space kinds worth spotting from across a room. */

.distance-btn.kind-payday {
  border-color: var(--color-wealth);
  color: var(--color-wealth);
}

.distance-btn.kind-gated {
  border-color: var(--color-brass);
  color: var(--color-brass);
}

.distance-btn.kind-contest {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.distance-btn.kind-goal {
  border-color: var(--color-knowledge);
  color: var(--color-knowledge);
}

.distance-btn.kind-junction,
.distance-btn.kind-finish {
  border-color: var(--color-text-muted);
  color: var(--color-text-muted);
}

.method-grid {
  display: grid;
  gap: 0.75rem;
}

.method-btn {
  font: inherit;
  padding: 1.4rem 1rem;
  border-radius: var(--radius);
  border: 2px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
  text-align: left;
}

.method-btn strong {
  display: block;
  font-size: 1.15rem;
  margin-bottom: 0.2rem;
}

.method-btn span {
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.method-btn.is-dice { border-color: var(--color-primary); }
.method-btn.is-skill { border-color: var(--color-accent); }

.verdict {
  text-align: center;
  font-weight: 800;
  font-size: 1.1rem;
  padding: 1rem;
  border-radius: var(--radius);
}

.verdict-correct { background: var(--color-success); color: #fff; }
.verdict-near { background: var(--color-brass); color: #fff; }
.verdict-far { background: var(--color-danger); color: #fff; }

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translateX(-50%);
  background: var(--color-text);
  color: var(--color-bg);
  padding: 0.7rem 1.1rem;
  border-radius: var(--radius);
  font-weight: 700;
  z-index: 50;
  max-width: calc(100vw - 2rem);
}

/* --- big screen ----------------------------------------------------------- */

body.display-body {
  overflow: hidden;
  background: #0d1113;
}

#scene {
  position: fixed;
  inset: 0;
  display: block;
}

.overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  font-family: system-ui, sans-serif;
}

.hud {
  position: absolute;
  top: 1rem;
  left: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.hud-player {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: rgba(14, 18, 20, 0.82);
  border: 2px solid rgba(255, 255, 255, 0.14);
  border-left-width: 6px;
  border-radius: 8px;
  padding: 0.45rem 0.7rem;
  color: #f2ece2;
  min-width: 20rem;
}

.hud-player.is-active {
  border-color: #f0d264;
  box-shadow: 0 0 0 2px rgba(240, 210, 100, 0.35);
}

.hud-player .hud-name {
  font-weight: 800;
  font-size: 1.05rem;
}

.hud-player .hud-stats {
  margin-left: auto;
  display: flex;
  gap: 0.7rem;
  font-size: 0.9rem;
  font-weight: 700;
}

/* A stat that is moving.
   The number counts rather than snapping, so these two states are held for
   as long as the count runs and the row is visibly busy while it does. Money
   runs to seven figures and its width changes as it counts, so the cells are
   fixed-width and tabular or the whole row jitters on every frame. */

.hud-player .hud-stat {
  display: inline-block;
  text-align: right;
  font-variant-numeric: tabular-nums;
  transition: transform 140ms ease, text-shadow 140ms ease;
}

.hud-player .hud-money {
  min-width: 6.5rem;
}

.hud-player .hud-knowledge,
.hud-player .hud-happiness,
.hud-player .hud-standing {
  min-width: 3.6rem;
}

.hud-player .hud-stat.is-rising {
  transform: scale(1.16);
  text-shadow: 0 0 12px currentColor;
}

.hud-player .hud-stat.is-falling {
  transform: scale(1.16);
  text-shadow: 0 0 12px #ef7a5f;
}

/* The pip counter that runs beside a walk. Deliberately not the banner: the
   banner is over the middle of the board, which is where the walk is. */

.walk-count {
  position: absolute;
  left: 50%;
  top: 6.2rem;
  transform: translateX(-50%);
  z-index: 3;
  background: rgba(14, 18, 20, 0.86);
  border: 2px solid rgba(255, 255, 255, 0.2);
  border-radius: 999px;
  color: #f2ece2;
  padding: 0.3rem 1.1rem;
  font-size: 1.05rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

/* Sound controls. They sit above the lobby panel so the same control works
   before, during and after a game. The big screen is dark in both themes,
   so these colors are stated rather than drawn from the palette tokens. */

.sound-controls {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  z-index: 3;
  pointer-events: auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.9rem;
  padding: 0.6rem 0.85rem;
  background: rgba(14, 18, 20, 0.82);
  border: 2px solid rgba(255, 255, 255, 0.14);
  border-radius: 10px;
  color: #f2ece2;
}

.sound-toggle {
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  padding: 0.35rem 0.75rem;
  border-radius: 8px;
  border: 2px solid rgba(255, 255, 255, 0.22);
  background: transparent;
  color: #f2ece2;
}

.sound-toggle:hover {
  border-color: #f0d264;
}

.sound-toggle.is-muted {
  border-color: #ef7a5f;
  color: #ef7a5f;
}

.sound-level {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #a79c8d;
}

.sound-level input[type="range"] {
  width: 7rem;
  accent-color: #f0d264;
}

.banner {
  position: absolute;
  left: 50%;
  top: 1.5rem;
  transform: translateX(-50%);
  background: rgba(14, 18, 20, 0.9);
  border: 2px solid #f0d264;
  border-radius: 10px;
  color: #f2ece2;
  padding: 0.8rem 1.6rem;
  font-size: 1.4rem;
  font-weight: 800;
  text-align: center;
  max-width: 70vw;
}

.ticker {
  position: absolute;
  left: 1rem;
  bottom: 1rem;
  width: min(34rem, 40vw);
  background: rgba(14, 18, 20, 0.82);
  border: 2px solid rgba(255, 255, 255, 0.14);
  border-radius: 8px;
  color: #d8d2c6;
  padding: 0.6rem 0.8rem;
  font-size: 0.92rem;
  max-height: 9rem;
  overflow: hidden;
}

.ticker div + div {
  margin-top: 0.2rem;
}

.question-card {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(52rem, 80vw);
  background: rgba(14, 18, 20, 0.94);
  border: 3px solid #4bc0b8;
  border-radius: 14px;
  color: #f7f2e8;
  padding: 2rem;
  text-align: center;
}

.question-card .q-subject {
  color: #f0d264;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 0.95rem;
  margin-bottom: 0.8rem;
}

.question-card .q-prompt {
  font-size: 1.7rem;
  font-weight: 700;
  line-height: 1.35;
}

.question-card .q-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem;
  margin-top: 1.4rem;
}

.question-card .q-option {
  border: 2px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  padding: 0.7rem;
  font-size: 1.15rem;
  font-weight: 700;
}

/* The action card: what is being decided, and by whom.
   Centered and large, which is what the table asked for and what it should
   always have been. It used to sit against the right edge at 30rem wide with
   body text at 1.05rem, so the one thing everybody in the room is meant to be
   reading was the smallest and furthest-off thing on the screen. The board
   behind it is not doing anything while a decision is open -- the pawn that
   is deciding is stationary by definition -- so there is nothing being
   covered that anybody needs. */

.event-card,
.payday-card {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(52rem, 72vw);
  max-height: 82vh;
  overflow: auto;
  background: rgba(14, 18, 20, 0.95);
  border: 3px solid #ef7a5f;
  border-radius: 16px;
  color: #f7f2e8;
  padding: 2.2rem 2.6rem;
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.55);
}

.event-card h2,
.payday-card h2 {
  font-size: 2.2rem;
  line-height: 1.15;
  margin-bottom: 0.8rem;
  color: #f0d264;
}

.event-card p {
  font-size: 1.5rem;
  line-height: 1.45;
}

.event-card ol {
  margin: 1.4rem 0 0 1.4rem;
  font-size: 1.3rem;
}

.event-card li + li {
  margin-top: 0.7rem;
}

/* The payday, itemized. Money to the right in a fixed column so the figures
   line up under each other and the arithmetic reads as arithmetic. */

.payday-card {
  border-color: #d6a765;
  width: min(40rem, 60vw);
}

.payday-table {
  width: 100%;
  margin-top: 1rem;
  border-collapse: collapse;
  font-size: 1.3rem;
  font-variant-numeric: tabular-nums;
}

.payday-table td {
  padding: 0.4rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.payday-table td:last-child {
  text-align: right;
  font-weight: 800;
  white-space: nowrap;
  padding-left: 1.5rem;
}

.payday-table .is-in td:last-child {
  color: #8fd08a;
}

.payday-table .is-out td:last-child {
  color: #ef7a5f;
}

.payday-table .is-net td {
  border-bottom: none;
  border-top: 2px solid rgba(255, 255, 255, 0.28);
  padding-top: 0.7rem;
  font-size: 1.5rem;
  font-weight: 800;
  color: #f0d264;
}

.payday-note {
  margin-top: 0.9rem;
  font-size: 1rem;
  color: #a79c8d;
}

/* The colors a car may be painted, shown on the big screen while the phone
   holding the decision picks one. */

.color-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-top: 1.2rem;
}

.color-swatch {
  width: 3.4rem;
  height: 2.2rem;
  border-radius: 6px;
  border: 2px solid rgba(255, 255, 255, 0.35);
}

.lobby-panel {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3rem;
  background: rgba(9, 12, 14, 0.9);
  color: #f7f2e8;
  pointer-events: auto;
  padding: 2rem;
  flex-wrap: wrap;
}

.lobby-panel .qr {
  background: #fffaf1;
  padding: 1rem;
  border-radius: 12px;
  width: 18rem;
  height: 18rem;
}

.lobby-panel .qr svg {
  width: 100%;
  height: 100%;
}

.lobby-code {
  font-size: clamp(3rem, 9vw, 6rem);
  font-weight: 900;
  letter-spacing: 0.16em;
  color: #f0d264;
  line-height: 1;
}

.lobby-roster {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1.25rem 0;
  max-width: 32rem;
}

.roster-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: rgba(255, 255, 255, 0.08);
  border: 2px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  padding: 0.35rem 0.8rem 0.35rem 0.35rem;
  font-weight: 700;
}

.roster-dot {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.4);
}

/* Recenter. Top right is the only corner the game does not already use: the
   HUD holds top left, the banner top center, the log bottom left and the sound
   controls bottom right. Deliberately quiet -- it is a way out of a pan, not a
   feature to advertise, and it is only on screen while a pan is in effect. */
.recenter-btn {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 3;
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.85rem 0.5rem 0.7rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  color: #e8e0d2;
  background: rgba(14, 18, 20, 0.66);
  border: 2px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  opacity: 0.72;
  transition: opacity 140ms ease, border-color 140ms ease, color 140ms ease;
}

.recenter-btn:hover,
.recenter-btn:focus-visible {
  opacity: 1;
  color: #f0d264;
  border-color: #f0d264;
}

.recenter-btn svg {
  width: 1.15rem;
  height: 1.15rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.recenter-btn svg .pip {
  fill: currentColor;
  stroke: none;
}

.standings {
  position: absolute;
  inset: 0;
  background: rgba(9, 12, 14, 0.94);
  color: #f7f2e8;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  pointer-events: auto;
  overflow-y: auto;
}

.standings table {
  border-collapse: collapse;
  margin-top: 1.5rem;
  font-size: 1.1rem;
}

.standings th,
.standings td {
  padding: 0.5rem 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  text-align: left;
}

.standings tr:first-child td {
  color: #f0d264;
  font-weight: 800;
}

.hidden {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- resuming a game ------------------------------------------------------ */

.resume-list {
  margin: 0 0 1.25rem;
}

.resume-list h3 {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 0.6rem;
}

.resume-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.7rem 0.85rem;
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface-alt);
  text-decoration: none;
  color: var(--color-text);
  margin-bottom: 0.5rem;
}

.resume-row:hover {
  border-color: var(--color-primary);
}

.resume-code {
  font-weight: 800;
  letter-spacing: 0.1em;
  font-size: 1.05rem;
  color: var(--color-primary);
}

.resume-detail {
  font-size: 0.88rem;
  font-weight: 600;
}

.resume-go {
  margin-left: auto;
  font-weight: 800;
  font-size: 0.85rem;
  color: var(--color-accent);
  white-space: nowrap;
}

/* Taking a seat back in a game already under way. */

.seat-list {
  display: grid;
  gap: 0.5rem;
  margin-top: 1rem;
}

.seat-btn {
  font: inherit;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.65rem 0.8rem;
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
  text-align: left;
}

.seat-btn:hover {
  border-color: var(--color-primary);
}

.seat-chip {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  flex: 0 0 auto;
  border: 2px solid var(--color-border);
}

.seat-name {
  font-weight: 800;
}

.seat-take {
  margin-left: auto;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-primary);
}

/* --- host menubar --------------------------------------------------------- */
/* Sits above the hero, dark against the board art below it, so a signed-in
   host has one place for account and console links. */

.menubar {
  background: #171a1c;
  color: #f2ece2;
  border-bottom: 3px solid var(--color-brass);
}

.menubar-inner {
  max-width: 62rem;
  margin: 0 auto;
  padding: 0.6rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.menubar-brand {
  font-weight: 800;
  letter-spacing: 0.02em;
  color: #f2ece2;
  text-decoration: none;
}

.menubar-brand:hover {
  color: #4bc0b8;
}

.menubar-links {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex-wrap: wrap;
}

.menubar-links a {
  color: #d8cfc1;
  text-decoration: none;
  font-weight: 700;
  font-size: 0.92rem;
  padding: 0.25rem 0;
  border-bottom: 2px solid transparent;
}

.menubar-links a:hover {
  color: #f2ece2;
  border-bottom-color: var(--color-brass);
}

.menubar-user {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.92rem;
}

.menubar-name {
  color: #a79c8d;
  font-weight: 700;
}

.menubar-user form {
  display: inline;
}

.menubar-user .linkish {
  color: #4bc0b8;
  font-weight: 700;
}

@media (max-width: 34rem) {
  .menubar-user {
    margin-left: 0;
    width: 100%;
  }
}

/* --- landing page --------------------------------------------------------- */

/* Deep teal, and no board.
   A hand-faked board used to fill this header, which meant the first thing the
   page showed was a board the generator would never produce -- advertising the
   wrong game to anybody who then played it. The type was never legible over it
   without a scrim heavy enough to hide most of it anyway, so the scrim is now
   simply the background, with a brass glow where the sun used to be. */
.landing-hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(38% 46% at 88% 6%, rgba(240, 210, 100, 0.24) 0%,
                                       rgba(240, 210, 100, 0) 100%),
    radial-gradient(110% 80% at 10% 0%, #16414a 0%, rgba(22, 65, 74, 0) 62%),
    linear-gradient(165deg, #103038 0%, #0b2026 58%, #123840 100%);
  color: #f7f2e8;
  /* Deep enough that the overlapping card below still sits on the hero. */
  padding: 3.5rem 0 7rem;
  border-bottom: 6px solid var(--color-accent);
}

.landing-hero .wrap {
  position: relative;
  z-index: 1;
}

/* --- coming soon teaser ------------------------------------------------- */

.soon-teaser {
  margin-top: 1.5rem;
}

.soon-tag {
  display: inline-block;
  background: rgba(0, 0, 0, 0.22);
  border: 2px solid rgba(240, 210, 100, 0.45);
  border-radius: 10px;
  padding: 0.5rem 1rem;
  font-size: 1.5rem;
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #f0d264;
}

.soon-note {
  margin-top: 0.75rem;
  max-width: 34rem;
  font-size: 0.88rem;
  color: rgba(247, 242, 232, 0.78);
}

.beta-card {
  border-color: var(--color-accent);
  border-width: 3px;
}


.landing-hero h1 {
  font-size: clamp(2.4rem, 8vw, 4.5rem);
  letter-spacing: -0.02em;
}

.landing-hero .wrap {
  padding-bottom: 0;
}

.beta-badge {
  display: inline-block;
  background: var(--color-accent);
  color: #fff;
  font-weight: 800;
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  margin-bottom: 1rem;
}

.hero-line {
  font-size: clamp(1.1rem, 3vw, 1.45rem);
  font-weight: 600;
  margin-top: 0.75rem;
  color: #f0d264;
}

.hero-sub {
  margin-top: 1rem;
  max-width: 34rem;
  color: rgba(247, 242, 232, 0.85);
}

/* The card overlaps the hero on purpose, but it has to land inside the
   colored band with air on both sides -- flush against the accent rule it
   reads as a collision rather than a layer. */
.join-card {
  position: relative;
  margin-top: -3.25rem;
}

.landing-hero + .wrap {
  padding-top: 0;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem;
  margin-top: 1.25rem;
}

.feature h3 {
  font-size: 1.1rem;
  margin-bottom: 0.4rem;
  color: var(--color-primary);
}

.feature p {
  font-size: 0.95rem;
}

.host-card {
  border-color: var(--color-primary);
  border-width: 3px;
}

.footer-note {
  margin-top: 3rem;
  font-size: 0.88rem;
  text-align: center;
}

/* --- legal pages and footer ----------------------------------------------- */

.legal-content h2 {
  font-size: 1.15rem;
  margin: 1.75rem 0 0.5rem;
  color: var(--color-primary);
}

.legal-content p,
.legal-content ul {
  margin-bottom: 0.75rem;
}

.legal-content ul {
  padding-left: 1.4rem;
}

.legal-content li {
  margin-bottom: 0.3rem;
}

.site-footer {
  margin-top: 3rem;
  text-align: center;
  font-size: 0.9rem;
}

.site-footer p {
  margin-bottom: 0.4rem;
}

.site-footer span {
  color: var(--color-text-muted);
  margin: 0 0.4rem;
}

/* --- utilities ------------------------------------------------------------ */

.u-hide { display: none !important; }

.u-visually-hidden,
.form-aux {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.u-nowrap { white-space: nowrap; }

.u-right { text-align: right; }

/* A duel is the one prompt two phones hold at once, so it is marked as
   clearly as the milestone prompts are. */

.duel-tag {
  display: inline-block;
  background: var(--color-accent);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  margin-bottom: 0.4rem;
}

.ctl-prompt.is-duel {
  border-color: var(--color-accent);
}

.milestone-tag {
  display: inline-block;
  background: var(--color-brass);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  margin-bottom: 0.4rem;
}

/* --- lobby voting --------------------------------------------------------- */

.vote-block {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.75rem;
  margin-bottom: 0.6rem;
}

.vote-block.is-agreed {
  border-color: var(--color-success);
}

.vote-question {
  font-weight: 800;
  font-size: 0.95rem;
  margin-bottom: 0.5rem;
}

.vote-choices {
  display: grid;
  gap: 0.4rem;
}

.vote-btn {
  font: inherit;
  text-align: left;
  padding: 0.6rem 0.7rem;
  border: 2px solid var(--color-border);
  border-radius: 8px;
  background: var(--color-bg);
  color: var(--color-text);
  cursor: pointer;
}

.vote-btn.is-picked {
  border-color: var(--color-accent);
  box-shadow: inset 0 0 0 2px var(--color-accent);
}

.vote-label {
  font-weight: 700;
  display: block;
}

.vote-count {
  display: inline-block;
  background: var(--color-primary);
  color: #fff;
  border-radius: 999px;
  font-size: 0.72rem;
  padding: 0.05rem 0.45rem;
  margin-left: 0.4rem;
}

.ctl-status.agreed {
  color: var(--color-success);
}

.lobby-options {
  margin: 0.75rem 0 1rem;
  max-width: 32rem;
}

.opt-row {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.3rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.9rem;
}

.opt-row.is-agreed .opt-label {
  color: #6bbf72;
}

.opt-label {
  flex: 0 0 13rem;
  color: #a79c8d;
}

.opt-choice {
  margin-right: 0.7rem;
  color: #d8d2c6;
}

.opt-choice.is-settled {
  color: #f0d264;
  font-weight: 700;
}

/* --- management console --------------------------------------------------- */

body.console-body {
  background: var(--color-bg);
}

.console {
  max-width: 74rem;
  margin: 0 auto;
  padding: 0 1rem 4rem;
}

.console-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1rem 0;
  border-bottom: 3px solid var(--color-primary);
  margin-bottom: 1.5rem;
}

.console-brand {
  font-weight: 900;
  text-decoration: none;
  color: var(--color-text);
  letter-spacing: -0.01em;
}

.console-nav {
  display: flex;
  gap: 0.9rem;
  flex-wrap: wrap;
}

.console-nav a {
  text-decoration: none;
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--color-text-muted);
}

.console-nav a.is-active {
  color: var(--color-accent);
}

.console-user {
  margin-left: auto;
  font-size: 0.88rem;
  color: var(--color-text-muted);
}

.linkish {
  background: none;
  border: 0;
  font: inherit;
  color: var(--color-primary);
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}

.flash {
  background: var(--color-surface-alt);
  border-left: 4px solid var(--color-success);
  padding: 0.6rem 0.9rem;
  border-radius: 6px;
  margin-bottom: 0.5rem;
  font-weight: 600;
}

.panel {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.1rem;
  margin-bottom: 1.25rem;
}

.panel h2 {
  font-size: 1.05rem;
  margin-bottom: 0.6rem;
}

.two-col {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 1.25rem;
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.stat {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.8rem;
  text-align: center;
}

.stat-n {
  display: block;
  font-size: 1.7rem;
  font-weight: 900;
  color: var(--color-primary);
}

.stat-l {
  display: block;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

table.grid {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

table.grid th,
table.grid td {
  text-align: left;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

table.grid th {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
}

.inline-form {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 0.75rem;
}

.inline-form input {
  width: auto;
  flex: 1 1 10rem;
}

.btn-danger {
  background: var(--color-danger);
  border-color: var(--color-danger);
}

.codebox {
  background: var(--color-surface-alt);
  border-radius: 6px;
  padding: 0.6rem;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.78rem;
  overflow-x: auto;
  max-height: 22rem;
  white-space: pre-wrap;
  word-break: break-all;
}

.logbox {
  font-size: 0.85rem;
  max-height: 22rem;
  overflow-y: auto;
}

.logbox div {
  padding: 0.15rem 0;
  border-bottom: 1px solid var(--color-border);
}

.qr-block {
  background: #fffaf1;
  padding: 0.75rem;
  border-radius: 8px;
  width: 15rem;
  height: 15rem;
}

.qr-block svg {
  width: 100%;
  height: 100%;
}

.ok { color: var(--color-success); font-weight: 800; }
.bad { color: var(--color-danger); font-weight: 800; }

.draft ol { margin: 0.6rem 0 0.9rem 1.2rem; }


/* --- who the figure is, on the join page ---------------------------------
   Asked before the face because it changes what every face on the grid is
   drawn as. Three wide buttons rather than a select: this is a phone, in a
   room, with somebody waiting on you. */

.build-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
}

@media (min-width: 30rem) {
  .build-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.build-option {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.7rem 0.85rem;
  border: 2px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-surface);
  cursor: pointer;
}

.build-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.build-option:has(input:checked) {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px var(--color-accent);
}

.build-option:has(input:focus-visible) {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.build-label {
  font-weight: 800;
}

.build-blurb {
  font-size: 0.82rem;
  color: var(--color-text-muted);
  line-height: 1.35;
}

/* --- the paint, on the phone ---------------------------------------------
   A color is chosen by looking at it, so the swatch is the button and the
   name is underneath it for the benefit of anybody saying it out loud. */

.color-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: 0.6rem;
  margin-top: 0.9rem;
}

.color-btn {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.4rem;
  padding: 0.6rem;
  font: inherit;
  font-weight: 700;
  text-align: center;
  color: var(--color-text);
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: 10px;
  cursor: pointer;
  /* Same target size as every other button on this screen: a phone held at
     arm's length in a lit room, one-handed. */
  min-height: 5.5rem;
}

.color-btn:active {
  border-color: var(--color-accent);
}

.color-chip {
  display: block;
  height: 2.6rem;
  border-radius: 6px;
  border: 2px solid rgba(0, 0, 0, 0.25);
}

/* A job that only a second degree opens is worth marking as one. */

.choice-btn.kind-advanced {
  border-color: #9d6bb5;
}

/* --- the build stamp -----------------------------------------------------
   Which build is running, said quietly in four places: the footer of every
   public page, the back office, the big screen and the phone. It exists for
   beta triage -- a report of "the dice look funny" is worth much less when
   nobody can tell whether the tester was on the build before the fix.

   Discreet everywhere. It is a diagnostic, not a feature, and it must never
   compete with anything a player is actually trying to read. */

.build-stamp {
  margin-top: 0.4rem;
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  opacity: 0.75;
}

.console-build {
  margin: 0 0 1rem;
  text-align: right;
}

/* The big screen. Bottom center, which is the one part of this overlay that
   nothing else claims: roster and ticker sit left, sound controls right, and
   the recenter control top right. Dim enough to disappear from ten feet
   unless somebody is looking for it, which is exactly when it is wanted. */

.screen-build {
  position: absolute;
  z-index: 4;
  left: 50%;
  bottom: 0.45rem;
  transform: translateX(-50%);
  margin: 0;
  font-family: system-ui, sans-serif;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  color: #f2ece2;
  opacity: 0.32;
  pointer-events: none;
  white-space: nowrap;
}

/* The phone. Below every button, outside the scrolling prompt, so it never
   moves and never takes a tap that was meant for an answer. */

.ctl-build {
  flex: 0 0 auto;
  margin: 0;
  text-align: center;
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  opacity: 0.7;
}
