/*
 * Fracle styles. Every colour, size, radius, font, duration and easing comes
 * from design/tokens.css (generated from design/tokens.toml). Do not write
 * raw values here; add a token instead. See design/README.md.
 *
 * Layers: 1. base  2. parts (reusable)  3. layout  4. screens  5. globe overlays
 */

/* ------------------------------------------------------------------ 1. base */

:root {
  color-scheme: dark;
  font-family: var(--font-ui);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--color-bg);
  color: var(--color-text);
  /* No pull-to-refresh and no scroll bounce on phones. */
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

#app {
  position: fixed;
  inset: 0;
}

#globe {
  display: block;
  width: 100%;
  height: 100%;
  /* The game handles all gestures; the browser must not scroll or zoom. */
  touch-action: none;
}

[hidden] { display: none !important; }

:focus-visible {
  outline: var(--border-focus) solid var(--color-focus);
  outline-offset: var(--border-focus);
}

/* Text that sits right on the globe needs a shadow to stay readable. */
.on-globe {
  text-shadow: var(--elevation-text);
}

/* ----------------------------------------------------------------- 2. parts */

/* Panel: the one surface for every floating box. */
.panel {
  pointer-events: auto;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  -webkit-backdrop-filter: blur(var(--blur-glass));
  backdrop-filter: blur(var(--blur-glass));
}

/* Buttons: default (quiet), primary (accent), big (full width). */
.button {
  pointer-events: auto;
  min-height: var(--size-touch);
  padding: 0 var(--space-lg);
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  font: var(--weight-medium) var(--text-md) var(--font-ui);
  cursor: pointer;
  transition: background-color var(--dur-quick) var(--ease-out), transform var(--dur-quick) var(--ease-out);
}

.button:active { background: var(--color-selected); transform: scale(0.97); }
.button:disabled { opacity: 0.4; cursor: default; }

.button.primary {
  border-color: transparent;
  background: var(--color-accent);
  color: var(--color-on-accent);
}

.button.big {
  width: 100%;
  min-height: calc(var(--size-touch) + var(--space-xxs));
}

/* Segmented control: one choice of a few. */
.segmented {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-xs);
  padding: var(--space-xs);
  border-radius: var(--radius-md);
  background: var(--color-surface-inset);
}

.segmented.five { grid-template-columns: repeat(5, 1fr); }

/* Slider with named marks under it (the map size). */
.field-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-sm);
}

.field-value {
  color: var(--color-text);
  font: var(--weight-medium) var(--text-sm) var(--font-ui);
  font-variant-numeric: tabular-nums;
}

.slider {
  width: 100%;
  min-height: var(--size-touch);
  margin: 0;
  accent-color: var(--color-accent);
  cursor: pointer;
}

.slider-marks {
  position: relative;
  min-height: var(--size-control);
  margin: 0 var(--space-sm);
}

/* --at: 0 (left end) to 1 (right end); the ends stay inside the panel. */
.slider-mark {
  position: absolute;
  top: 0;
  left: calc(var(--at) * 100%);
  transform: translateX(calc(var(--at) * -100%));
  display: grid;
  justify-items: center;
  padding: var(--space-xxs) var(--space-xs);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text-muted);
  font: var(--weight-regular) var(--text-xs) var(--font-ui);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: color var(--dur-quick) var(--ease-out), background-color var(--dur-quick) var(--ease-out);
}

.slider-mark b { font-weight: var(--weight-bold); }

.slider-mark[aria-pressed="true"] {
  color: var(--color-text);
  background: var(--color-surface-inset);
}

.segmented button {
  min-height: var(--size-control);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font: var(--weight-medium) var(--text-md) var(--font-ui);
  cursor: pointer;
  transition: background-color var(--dur-quick) var(--ease-out);
}

.segmented button[aria-pressed="true"] {
  background: var(--color-selected);
  box-shadow: inset 0 0 0 var(--border-hairline) var(--color-border);
}

/* Pill: a small rounded tag (phase steps, factors, the AI tag). */
.pill {
  padding: var(--space-xxs) var(--space-sm);
  border-radius: var(--radius-pill);
  background: var(--color-surface-inset);
  font-size: var(--text-xs);
}

/* Player symbol: every player has a colour AND a symbol (never colour alone). */
.sym {
  font-size: var(--text-sm);
  line-height: 1;
}

/* Sheet: a dialog that rises from the bottom (a centred card on big screens). */
.sheet {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: var(--color-scrim);
}

.sheet-panel {
  width: 100%;
  max-width: var(--size-sheet-max);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-lg);
  padding-bottom: max(var(--space-lg), env(safe-area-inset-bottom));
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  background: var(--color-surface-strong);
  animation: rise var(--dur-standard) var(--ease-out);
}

@media (min-width: 600px) and (min-height: 500px) {
  .sheet { align-items: center; }
  .sheet-panel { border-radius: var(--radius-xl); }
}

@keyframes rise {
  from { transform: translateY(var(--space-lg)); opacity: 0; }
}

.sheet-title {
  margin: 0;
  font-size: var(--text-lg);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

.code {
  pointer-events: auto;
  min-height: var(--size-touch);
  padding: 0 var(--space-xs);
  border: 0;
  background: none;
  color: var(--color-text-muted);
  font: var(--text-sm) var(--font-mono);
  cursor: copy;
}

/* The player's own action buttons wear their team colour (--me is set from
   Rust to var(--player-N); --on-me is its contrast-checked text colour). */
#app {
  --me: var(--player-0);
  --on-me: var(--player-0-on);
}

.button.primary.mine,
.turn-button.primary,
.battle-actions #btn-attack {
  background: var(--me);
  color: var(--on-me);
}

/* Colour and symbol pickers (Your side sheet). */
.swatches {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--space-sm);
}

.swatch-btn {
  min-height: var(--size-touch);
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-md);
  font: var(--weight-bold) var(--text-lg) var(--font-ui);
  cursor: pointer;
  transition: transform var(--dur-quick) var(--ease-out);
}

.swatch-btn[aria-pressed="true"] {
  outline: var(--border-ring) solid var(--color-highlight);
  outline-offset: var(--border-focus);
  transform: scale(1.06);
}

.side-preview {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

/* A troop counter in normal page flow (previews, style guide). */
.troop.inline {
  position: relative;
  display: inline-block;
  transform: none;
}

/* ---------------------------------------------------------------- 3. layout */

.top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding-top: max(var(--space-sm), env(safe-area-inset-top));
  padding-left: max(var(--space-md), env(safe-area-inset-left));
  padding-right: max(var(--space-md), env(safe-area-inset-right));
  pointer-events: none;
}

.topline {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.hud {
  position: absolute;
  left: 0;
  right: 0;
  display: flex;
  gap: var(--space-md);
  pointer-events: none;
  padding-left: max(var(--space-lg), env(safe-area-inset-left));
  padding-right: max(var(--space-lg), env(safe-area-inset-right));
}

.hud-bottom {
  bottom: 0;
  flex-direction: column;
  align-items: stretch;
  padding-bottom: max(var(--space-lg), env(safe-area-inset-bottom));
}

@media (min-width: 900px) {
  .hud-bottom {
    max-width: var(--size-panel-max);
    margin: 0 auto; /* centred: left and right are both 0 */
  }
}

/* With the menu open, only the globe stays behind it. */
#app.menu-open .top,
#app.menu-open .hud-bottom,
#app.menu-open .labels {
  visibility: hidden;
}

/* --------------------------------------------------------------- 4. screens */

/* Logo: the way into the menu. */
.logo {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: var(--size-touch);
  padding: 0 var(--space-sm) 0 var(--space-xxs);
  border: 0;
  background: none;
  color: var(--color-text);
  font: var(--weight-heavy) var(--text-lg) var(--font-ui);
  letter-spacing: var(--tracking-logo);
  text-transform: uppercase;
  text-shadow: var(--elevation-text);
  cursor: pointer;
}

.logo:active { opacity: 0.7; }

.logo-caret {
  font-size: var(--text-xs);
  opacity: 0.7;
  letter-spacing: 0;
}

/* Player chips: symbol, name, AI tag, territories / troops. */
.players {
  display: flex;
  gap: var(--space-xs);
  overflow-x: auto;
  scrollbar-width: none;
  pointer-events: auto;
}

.player {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex: none;
  min-height: var(--size-chip);
  padding: var(--space-xs) var(--space-sm);
  border: var(--border-hairline) solid transparent;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font: var(--text-sm) var(--font-ui);
  cursor: pointer;
  transition: border-color var(--dur-standard) var(--ease-out), opacity var(--dur-standard) var(--ease-out);
}

.player:active { filter: brightness(1.3); }
.player.current { border-color: var(--color-border-strong); color: var(--color-text); }
.player.out { opacity: 0.4; text-decoration: line-through; }
.player .name { font-weight: var(--weight-medium); color: var(--color-text); }
.player .stats { font-variant-numeric: tabular-nums; }

.kind {
  padding: 0 var(--space-xs);
  border-radius: var(--radius-xs);
  background: var(--color-surface-inset);
  font-size: var(--text-xxs);
}

/* Player card. */
.card-title {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.card-title .sym { font-size: var(--text-lg); }

.card-stats {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-sm) var(--space-lg);
  margin: 0;
  font-size: var(--text-md);
}

/* Rules sheet: a tall, scrolling panel. */
.sheet-panel.rules {
  max-height: 92dvh;
  max-width: var(--size-panel-max);
}

.rules-body {
  overflow-y: auto;
  overscroll-behavior: contain;
  display: grid;
  gap: var(--space-lg);
  font-size: var(--text-md);
  line-height: var(--leading-body);
  color: var(--color-text);
}

.rules-body h3 {
  margin: 0 0 var(--space-xs);
  font-size: var(--text-md);
  color: var(--color-text);
}

.rules-body p, .rules-body ul, .rules-body ol { margin: 0 0 var(--space-sm); }
.rules-body ul, .rules-body ol { padding-left: var(--space-lg); }
.rules-body li { margin-bottom: var(--space-xxs); }
.rules-body p, .rules-body li { color: var(--color-text-muted); }
.rules-body b { color: var(--color-text); }

.rules-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.rules-table th, .rules-table td {
  padding: var(--space-xs) var(--space-sm);
  border-bottom: var(--border-hairline) solid var(--color-border);
  text-align: left;
  vertical-align: top;
}

.rules-table th { color: var(--color-text-muted); font-weight: var(--weight-medium); }
.actions.single { grid-template-columns: 1fr; }

/* Two menu buttons side by side (Rules, Stats). */
.menu-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

.sheet-note {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.card-stats dt { color: var(--color-text-muted); }
.card-stats dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

/* New map sheet. */
.seed-row {
  display: flex;
  gap: var(--space-sm);
}

.seed-row input {
  flex: 1;
  min-width: 0;
  min-height: var(--size-touch);
  padding: 0 var(--space-md);
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-text);
  /* 16px or more stops iOS Safari from zooming the page on focus. */
  font: var(--text-lg) var(--font-mono);
  -webkit-user-select: text;
  user-select: text;
}

.code-preview {
  min-height: 1.4em;
  color: var(--color-text-muted);
  font: var(--text-sm) var(--font-mono);
}

/* Main menu: the globe turns slowly behind it, in view. */
.menu {
  position: absolute;
  inset: 0;
  z-index: 9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: max(var(--space-xl), env(safe-area-inset-top)) var(--space-lg) max(var(--space-lg), env(safe-area-inset-bottom));
  background: linear-gradient(to bottom, var(--color-scrim), transparent 22%, transparent 55%, var(--color-scrim));
}

.menu-head {
  text-align: center;
  pointer-events: none;
}

.menu-logo {
  margin: 0;
  font: var(--weight-heavy) var(--text-display) var(--font-ui);
  letter-spacing: var(--tracking-logo);
  text-transform: uppercase;
  text-shadow: var(--elevation-text-display);
}

.menu-tag {
  margin: var(--space-xxs) 0 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  text-shadow: var(--elevation-text-soft);
}

.menu-panel {
  width: 100%;
  max-width: var(--size-menu-max);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-xl);
  background: var(--color-surface);
  box-shadow: var(--elevation-overlay);
  -webkit-backdrop-filter: blur(var(--blur-glass-strong));
  backdrop-filter: blur(var(--blur-glass-strong));
}

.menu-game {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: 0 var(--space-xs);
}

.menu-info {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Wide screens: the panel on the left, the globe clear on the right. */
@media (min-width: 900px) {
  .menu {
    align-items: flex-start;
    justify-content: center;
    gap: var(--space-xxl);
    padding-left: calc(var(--space-xxl) * 1.75);
    background: linear-gradient(to right, var(--color-scrim), transparent 45%);
  }
  .menu-head { text-align: left; }
}

/* Battle / move preview (first tap on a target). */
.battle {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-md);
  font-size: var(--text-sm);
}

.battle-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.battle .side b { font-variant-numeric: tabular-nums; }
.side.atk, .factor.atk { color: var(--color-positive); }
.side.def, .factor.def { color: var(--color-negative); }
.vs { color: var(--color-text-muted); }

.battle-chance {
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
}

.factors {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.factor {
  padding: var(--space-xxs) var(--space-sm);
  border-radius: var(--radius-sm);
  background: var(--color-surface-inset);
  font-size: var(--text-label);
}

.battle-losses {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.battle-actions { justify-content: space-between; }
.battle-actions .segmented.amount { flex: none; }

.battle-actions #btn-attack {
  flex: 1;
  max-width: var(--size-action-max);
}

/* Troop amount: ¼ ½ ¾ All. */
.segmented.amount {
  display: inline-grid;
  grid-template-columns: repeat(4, var(--size-touch));
  padding: var(--space-xxs);
}

/* Turn panel: round, phase steps, what to do, tools. */
.turnbar {
  /* --player / --on-player are set per turn from Rust (the current player). */
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-sm) var(--space-sm) var(--space-md);
  border-top: var(--border-accent) solid var(--player);
  box-shadow: var(--elevation-raised);
  transition: border-color var(--dur-standard) var(--ease-out);
}

.turnbar-head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.round {
  color: var(--color-text-muted);
  font: var(--weight-bold) var(--text-label) var(--font-ui);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.steps {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin: 0 0 0 auto;
  padding: 0;
  list-style: none;
  font: var(--weight-bold) var(--text-xs) var(--font-ui);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.steps li {
  position: relative;
  padding: var(--space-xxs) var(--space-sm);
  border-radius: var(--radius-pill);
  color: var(--color-text-muted);
  transition: background-color var(--dur-standard) var(--ease-out), color var(--dur-standard) var(--ease-out);
}

/* The arrow sits between the pills, outside the coloured one. */
.steps li + li::before {
  content: '›';
  position: absolute;
  left: calc(var(--space-md) * -0.85);
  color: var(--color-text-muted);
}

.turnbar[data-phase="reinforce"] [data-step="reinforce"],
.turnbar[data-phase="attack"] [data-step="attack"],
.turnbar[data-phase="move"] [data-step="move"] {
  background: var(--player);
  color: var(--on-player);
}

.turnbar[data-phase="over"] .steps,
.turnbar[data-phase="capital"] .steps {
  display: none;
}

.turnbar-main {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.instruction {
  flex: 1;
  min-width: 0;
  font: var(--weight-medium) var(--text-lg) / var(--leading-tight) var(--font-ui);
}

.turn-button { flex: none; }

.turn-button.speed {
  min-width: var(--size-speed-min);
  font-variant-numeric: tabular-nums;
}

.turnbar-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
}

.status {
  flex: 1 1 var(--size-status-min);
  min-width: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.status:empty { display: none; }

/* -------------------------------------------------------- 5. globe overlays */

.labels {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Troop labels. --fade (0..1) is set per frame: labels shrink and fade
   toward the globe's edge. */
.troop {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  will-change: transform;
  opacity: var(--fade, 1);
  font: var(--weight-bold) var(--text-label) / var(--leading-label) var(--font-ui);
  font-variant-numeric: tabular-nums;
}

/* North and south pole markers: small, quiet, behind everything else. */
.troop.pole {
  display: grid;
  place-items: center;
  width: var(--size-pole);
  height: var(--size-pole);
  border-radius: var(--radius-pill);
  background: var(--color-surface-strong);
  color: var(--color-text);
  font: var(--weight-heavy) var(--text-xxs) / 1 var(--font-ui);
  letter-spacing: 0;
  box-shadow: var(--elevation-text);
  pointer-events: none;
}

/* Neutral: a plain number on the land, no box. */
.troop.neutral {
  color: var(--color-on-label-neutral);
  font-weight: var(--weight-medium);
  text-shadow: 0 0 var(--space-xs) var(--color-label-halo), 0 0 var(--space-xxs) var(--color-label-halo);
}

/* Owned: a counter in the owner's colour with their symbol and troops. */
.troop.counter {
  min-width: var(--size-counter);
  height: var(--size-counter);
  padding: 0 var(--space-xs);
  border: var(--border-hairline) solid var(--color-line);
  border-radius: var(--radius-pill);
  text-align: center;
  line-height: calc(var(--size-counter) - 2 * var(--border-hairline));
  box-shadow: var(--elevation-arrow);
}

.troop.p0 { background: var(--player-0); color: var(--player-0-on); }
.troop.p1 { background: var(--player-1); color: var(--player-1-on); }
.troop.p2 { background: var(--player-2); color: var(--player-2-on); }
.troop.p3 { background: var(--player-3); color: var(--player-3-on); }
.troop.p4 { background: var(--player-4); color: var(--player-4-on); }
.troop.p5 { background: var(--player-5); color: var(--player-5-on); }

.troop.acted { opacity: calc(var(--fade, 1) * 0.5); }
.troop.dim { opacity: calc(var(--fade, 1) * 0.45); }

/* Your selected territory and its targets stand out. */
.troop.source {
  outline: var(--border-ring) solid var(--color-highlight);
  outline-offset: var(--border-hairline);
}

/* Targets: a dashed white ring (the source ring is solid), never a hue. */
.troop.target { outline: var(--border-ring) dashed var(--color-highlight); outline-offset: var(--border-hairline); }
.troop.target.preview { outline-style: solid; }
.troop.neutral.target { text-shadow: 0 0 var(--space-xs) var(--color-highlight), 0 0 var(--space-xxs) var(--color-label-halo); outline: none; }

/* Battle arrow and push dots (colour set per action from Rust). */
.arrows {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
  filter: drop-shadow(var(--elevation-arrow));
}

.arrows path {
  fill: none;
  stroke: currentColor;
  stroke-width: var(--size-arrow-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.arrows polygon { fill: currentColor; }

/* A sea attack by boat: the path becomes a dashed wake behind the boat. */
.arrows path.wake {
  stroke-width: var(--border-focus);
  stroke-dasharray: var(--space-xs) var(--space-xs);
}

.arrows .boat path {
  fill: currentColor;
  stroke: var(--color-line);
  stroke-width: var(--border-hairline);
  stroke-linejoin: round;
}

.arrows .boat .boat-sail { fill: var(--color-highlight); }

.arrows .push circle {
  fill: currentColor;
  stroke: var(--color-line);
  stroke-width: var(--border-focus);
}

/* Stalemate pop-up. */
.toast {
  position: absolute;
  left: 50%;
  top: 42%;
  z-index: 5;
  padding: var(--space-md) var(--space-xl);
  border-radius: var(--radius-lg);
  background: var(--color-toast);
  color: var(--color-on-toast);
  font: var(--weight-heavy) var(--text-toast) var(--font-ui);
  white-space: nowrap;
  box-shadow: var(--elevation-toast);
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.6);
  pointer-events: none;
}

.toast.show { animation: toast-pop var(--dur-toast) var(--ease-out) forwards; }

@keyframes toast-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.6) rotate(-4deg); }
  14% { opacity: 1; transform: translate(-50%, -50%) scale(1.06) rotate(2deg); }
  24% { transform: translate(-50%, -50%) scale(1) rotate(-1deg); }
  32% { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  80% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(0.95); }
}

@media (prefers-reduced-motion: reduce) {
  /* No wobble: a plain fade, held long enough to read. */
  .toast.show { animation: toast-fade var(--dur-toast) linear forwards; }
  @keyframes toast-fade {
    0%, 85% { opacity: 1; transform: translate(-50%, -50%); }
    100% { opacity: 0; transform: translate(-50%, -50%); }
  }
}
