:root {
  --page: #ffffff;
  --board: #ffffff;
  --panel: #ffffff;
  --raised: #ffffff;
  --row: #f5f6f7;
  --line: #151515;
  --line-soft: #d7dadd;
  --signature-blue: #1f66c2;
  --player: var(--signature-blue);
  --text: #151515;
  --muted: #5f6368;
  --dim: #8b9097;
  --good: #16856e;
  --warn: #b36c00;
  --health: #ce382f;
  --shield: #2473cc;
  --accent: #8a3fbd;
  --enemy: #f05a28;
  --enemy-zone: #fef2ee;
  --player-zone: #edf3fa;
  --side-top: var(--enemy);
  --side-top-zone: var(--enemy-zone);
  --side-bottom: var(--player);
  --side-bottom-zone: var(--player-zone);
  --ink: #151515;
  --highlight: #c3ffff;
  --shadow: rgba(0, 0, 0, 0.12);
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  color: var(--text);
  background: var(--page);
  font: 400 14px/1.4 "Inter", "SF Pro Text", system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  overscroll-behavior: none;
}

h1, h2, h3, p, ol, ul, dl, dd, figure {
  margin: 0;
  padding: 0;
}

ol, ul {
  list-style: none;
}

button {
  font: inherit;
  color: inherit;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--raised);
  cursor: pointer;
  transition:
    border-color 120ms ease,
    background-color 120ms ease,
    color 120ms ease,
    opacity 120ms ease,
    transform 120ms ease,
    box-shadow 120ms ease;
}

button:disabled {
  cursor: default;
}

button,
a[href],
[role="button"] {
  -webkit-tap-highlight-color: rgba(21, 21, 21, 0.16);
}

:is(button:not(:disabled), a[href], [role="button"]):focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.micro {
  display: block;
  color: var(--muted);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

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

.app {
  height: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.stage {
  position: relative;
  min-width: 0;
  min-height: 0;
  height: 100%;
  display: grid;
  /* The command panel is content-sized and the squads absorb the slack, so the
     panel can never overflow its band and clip an action row. */
  grid-template-rows: auto auto minmax(0, 1fr) auto minmax(0, 1fr) auto;
  background: var(--board);
}

.combat-fx-layer {
  position: absolute;
  z-index: 40;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.pvp-challenge-fx {
  position: fixed;
  z-index: 85;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.pvp-challenge-fx[hidden] { display: none; }

.pvp-challenge-fx::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at center, rgba(195, 255, 255, .34), transparent 42%);
  opacity: 0;
}

.pvp-challenge-badge {
  --pvp-flight-x: 0px;
  --pvp-flight-y: 0px;
  --pvp-target-scale: .18;
  position: absolute;
  top: 50%;
  left: 50%;
  width: max-content;
  max-width: calc(100vw - 28px);
  padding: 21px 28px 22px;
  border: 3px solid var(--player);
  background: var(--highlight);
  box-shadow:
    0 0 0 4px rgba(255, 255, 255, .98),
    0 0 0 8px var(--player),
    0 18px 48px rgba(21, 21, 21, .28);
  color: var(--ink);
  font-size: clamp(22px, 4vw, 42px);
  font-weight: 900;
  letter-spacing: .015em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
  transform: translate(-50%, -50%) scale(.62) rotate(-1.5deg);
  opacity: 0;
}

.pvp-challenge-badge::after {
  content: "";
  position: absolute;
  inset: -14px;
  background:
    linear-gradient(90deg, var(--player) 52%, transparent 52%) 0 0 / 16px 3px repeat-x,
    linear-gradient(180deg, var(--player) 52%, transparent 52%) 100% 0 / 3px 16px repeat-y,
    linear-gradient(270deg, var(--player) 52%, transparent 52%) 0 100% / 16px 3px repeat-x,
    linear-gradient(0deg, var(--player) 52%, transparent 52%) 0 0 / 3px 16px repeat-y;
  opacity: .74;
  animation: turn-guidance-march .72s linear infinite;
}

.pvp-challenge-fx.is-announcing::before {
  animation: pvp-challenge-flash 650ms ease-out both;
}

.pvp-challenge-fx.is-announcing .pvp-challenge-badge {
  animation: pvp-challenge-arrive 460ms cubic-bezier(.16, 1.2, .3, 1) both;
}

.pvp-challenge-fx.is-homing .pvp-challenge-badge {
  animation: pvp-challenge-home 760ms cubic-bezier(.7, 0, .2, 1) both;
}

.pvp-challenge-fx.is-reduced .pvp-challenge-badge {
  transform: translate(-50%, -50%);
  opacity: 1;
}

@keyframes pvp-challenge-flash {
  0% { opacity: 0; }
  28% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes pvp-challenge-arrive {
  0% { transform: translate(-50%, -50%) scale(.62) rotate(-1.5deg); opacity: 0; }
  56% { transform: translate(-50%, -50%) scale(1.1) rotate(.7deg); opacity: 1; }
  76% { transform: translate(-50%, -50%) scale(.97) rotate(-.25deg); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1) rotate(0); opacity: 1; }
}

@keyframes pvp-challenge-home {
  0% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  68% { opacity: 1; }
  100% {
    transform:
      translate(
        calc(-50% + var(--pvp-flight-x)),
        calc(-50% + var(--pvp-flight-y))
      )
      scale(var(--pvp-target-scale));
    opacity: 0;
  }
}

.combat-trace {
  position: absolute;
  height: 0;
  color: var(--ink);
  transform-origin: 0 50%;
}

.combat-trace.by-you,
.combat-move-label.by-you,
.combat-resource-result.by-you { color: var(--player); }

.combat-trace.by-cpu,
.combat-move-label.by-cpu,
.combat-resource-result.by-cpu { color: var(--enemy); }

.combat-trace-line {
  position: absolute;
  top: -1px;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  box-shadow: 0 0 9px currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  animation: combat-trace-line var(--beat-duration, 950ms) ease-out both;
}

.combat-projectile {
  position: absolute;
  top: 0;
  left: 0;
  width: 15px;
  height: 15px;
  border: 2px solid currentColor;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .82), 0 0 18px currentColor;
  transform: translate(-50%, -50%) rotate(45deg);
  animation: combat-projectile var(--beat-duration, 950ms) cubic-bezier(.2, .72, .18, 1) both;
}

.combat-move-label,
.combat-resource-result {
  position: absolute;
  display: block;
  max-width: min(260px, calc(100vw - 28px));
  padding: 7px 12px;
  border: 2px solid currentColor;
  border-radius: 2px;
  background: rgba(255, 255, 255, .97);
  box-shadow: 0 8px 22px rgba(21, 21, 21, .2);
  color: var(--ink);
  font: 700 11px/1.15 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .08em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translate(-50%, -50%);
  animation: combat-move-label var(--beat-duration, 950ms) ease-out both;
}

.combat-move-label.by-you,
.combat-move-label.by-cpu,
.combat-resource-result.by-you,
.combat-resource-result.by-cpu { color: var(--ink); }

.combat-move-label.by-you,
.combat-resource-result.by-you { border-color: var(--player); }

.combat-move-label.by-cpu,
.combat-resource-result.by-cpu { border-color: var(--enemy); }

.combat-move-label.is-static { animation-name: combat-static-label; }

.combat-resource-result {
  font-size: clamp(17px, 2.1vw, 23px);
  font-weight: 800;
  letter-spacing: -.015em;
  animation: float-result var(--beat-duration, 2100ms) ease-out both;
}

.combat-resource-result.is-hype {
  color: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 8px 22px rgba(138, 63, 189, .24);
}

.pvp-match-intro {
  position: absolute;
  z-index: 7;
  width: min(600px, calc(100vw - 30px));
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: clamp(22px, 5vw, 44px);
  border: 4px solid var(--ink);
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--enemy) 10%, white) 0 50%, color-mix(in srgb, var(--player) 10%, white) 50% 100%);
  box-shadow: 0 0 0 6px white, 0 20px 50px rgb(21 21 21 / 28%);
  color: var(--ink);
  text-align: center;
  transform: translate(-50%, -50%);
  animation: pvp-match-intro var(--beat-duration, 7200ms) cubic-bezier(.16, 1, .3, 1) both;
}

.pvp-match-intro-name {
  display: block;
  width: 100%;
  max-width: 100%;
  font-size: clamp(24px, 5vw, 52px);
  font-weight: 850;
  line-height: 1;
  overflow-wrap: normal;
  white-space: nowrap;
}

.pvp-match-intro-versus {
  padding: 7px 10px;
  background: var(--ink);
  color: white;
  font: 850 clamp(12px, 2vw, 17px)/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-style: normal;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Modifiers get a separate explanatory beat before their result. This keeps a
   Character passive or game rule from looking like unexplained extra damage. */
.effect-trigger-callout {
  --trigger-owner: var(--ink);
  position: absolute;
  z-index: 4;
  display: grid;
  justify-items: center;
  width: min(285px, calc(100vw - 34px));
  gap: 4px;
  padding: 12px 17px 13px;
  border: 2px solid var(--trigger-owner);
  border-radius: 2px;
  background: rgba(255, 255, 255, .98);
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .92),
    0 0 0 5px var(--trigger-owner),
    0 13px 30px rgba(21, 21, 21, .22);
  color: var(--ink);
  text-align: center;
  transform: translate(-50%, -50%);
  animation: effect-trigger-in var(--beat-duration, 2700ms) cubic-bezier(.16, 1, .3, 1) both;
}

.effect-trigger-callout.by-you { --trigger-owner: var(--player); }
.effect-trigger-callout.by-cpu { --trigger-owner: var(--enemy); }
.effect-trigger-callout.is-rule { --trigger-owner: var(--accent); }
.effect-trigger-callout.is-field { --trigger-owner: var(--ink); }
.effect-trigger-callout.is-passive { width: min(340px, calc(100vw - 34px)); }

.effect-trigger-callout small {
  max-width: 100%;
  color: var(--trigger-owner);
  font: 800 9px/1.1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .16em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.effect-trigger-callout strong {
  max-width: 100%;
  font-size: clamp(16px, 2vw, 21px);
  font-weight: 800;
  line-height: 1.05;
  overflow-wrap: anywhere;
}

.effect-trigger-callout em {
  max-width: 100%;
  padding-top: 2px;
  color: var(--muted);
  font: 800 14px/1.1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-style: normal;
  letter-spacing: .015em;
  overflow-wrap: anywhere;
}

.effect-trigger-delta {
  display: inline-block;
  color: var(--ink);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.effect-trigger-delta.stat-health.is-loss { color: var(--health); }
.effect-trigger-delta.stat-health.is-gain { color: var(--good); }
.effect-trigger-delta.stat-shield { color: var(--shield); }
.effect-trigger-delta.stat-hype { color: var(--accent); }
.effect-trigger-delta.stat-damage { color: var(--ink); }

/* Modifier Cards have their own grammar: first a centered card-stamp reveal,
   then a segmented conduit. Neither borrows the attack beam or projectile. */
.modifier-reveal-card,
.modifier-cast-source {
  --modifier-owner: var(--ink);
  position: absolute;
  z-index: 2;
  display: grid;
  justify-items: center;
  color: var(--ink);
  border: 3px solid var(--ink);
  border-radius: 1px;
  background: var(--highlight);
  text-align: center;
  text-transform: uppercase;
  transform: translate(-50%, -50%);
}

.modifier-reveal-card.by-you,
.modifier-cast-source.by-you { --modifier-owner: var(--player); }

.modifier-reveal-card.by-cpu,
.modifier-cast-source.by-cpu { --modifier-owner: var(--enemy); }

.modifier-reveal-card {
  width: min(330px, calc(100vw - 34px));
  gap: 4px;
  padding: 17px 24px 18px;
  box-shadow:
    0 0 0 4px rgba(255, 255, 255, .96),
    0 0 0 7px var(--modifier-owner),
    0 16px 34px rgba(21, 21, 21, .24);
  animation: event-card-reveal var(--beat-duration, 1400ms) cubic-bezier(.16, 1, .3, 1) both;
}

.modifier-reveal-card small,
.modifier-cast-source small {
  font: 800 9px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .2em;
}

.modifier-reveal-card strong {
  max-width: 100%;
  font-size: clamp(21px, 3vw, 32px);
  font-weight: 800;
  letter-spacing: .025em;
  line-height: 1.05;
  overflow-wrap: anywhere;
}

.modifier-reveal-aura {
  position: absolute;
  z-index: -1;
  inset: -18px;
  border: 2px dashed var(--modifier-owner);
  opacity: 0;
  animation: modifier-reveal-aura var(--beat-duration, 1400ms) ease-out both;
}

.modifier-cast-source {
  min-width: 116px;
  max-width: min(220px, calc(100vw - 34px));
  gap: 3px;
  padding: 7px 12px 8px;
  border-width: 2px;
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .94),
    0 0 0 5px var(--modifier-owner),
    0 9px 22px rgba(21, 21, 21, .2);
  animation: modifier-cast-source var(--beat-duration, 1100ms) ease-out both;
}

.modifier-cast-source strong {
  max-width: 100%;
  font: 800 11px/1.05 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .035em;
  overflow-wrap: anywhere;
}

.modifier-conduit {
  position: absolute;
  z-index: 1;
  height: 0;
  color: var(--ink);
  transform-origin: 0 50%;
}

.modifier-conduit.by-you { color: var(--player); }
.modifier-conduit.by-cpu { color: var(--enemy); }

.modifier-conduit-line {
  position: absolute;
  top: -2px;
  left: 0;
  width: 100%;
  height: 0;
  border-top: 4px dashed currentColor;
  filter: drop-shadow(0 0 5px currentColor);
  transform: scaleX(0);
  transform-origin: left center;
  animation: modifier-conduit-line var(--beat-duration, 1100ms) ease-out both;
}

.modifier-wave {
  position: absolute;
  top: 0;
  left: 0;
  width: 24px;
  height: 24px;
  border: 3px solid currentColor;
  border-radius: 50%;
  background: var(--highlight);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .78), 0 0 20px currentColor;
  transform: translate(-50%, -50%);
  animation: modifier-wave var(--beat-duration, 1100ms) cubic-bezier(.18, .76, .18, 1) both;
}

.alpha-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 7px 14px;
  color: var(--ink);
  border-bottom: 0;
  background: var(--board);
  font: 700 10px/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.alpha-brand {
  display: inline-block;
  color: inherit;
  font-size: 12px;
  text-decoration: none;
  text-underline-offset: 3px;
  transition: opacity 120ms ease, transform 120ms ease;
}
.alpha-banner-copy { margin-left: auto; }

/* ------------------------------------------------------------ statusbar */

.statusbar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 51px;
  padding: 10px 14px 8px;
}

.status-summary {
  display: grid;
  grid-template-columns: repeat(2, minmax(72px, auto));
  align-items: start;
  justify-content: center;
  gap: clamp(22px, 4vw, 44px);
}

.status-summary.status-chat {
  display: flex;
  align-items: center;
  justify-content: center;
  width: auto;
}

.header-chat-btn {
  min-width: 104px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding-inline: 10px;
  background: var(--highlight);
  box-shadow: 2px 2px 0 rgba(21, 21, 21, .14);
}

.header-chat-btn > span:first-child {
  font-size: 16px;
  line-height: 1;
}

.header-chat-btn:disabled {
  background: var(--row);
  box-shadow: none;
  opacity: .48;
}

.header-chat-btn.is-cooling { opacity: .68; }

.header-chat-badge {
  min-width: 25px;
  padding: 2px 4px;
  border: 1px solid currentColor;
  background: #fff;
  font-size: 8px;
  line-height: 1;
  letter-spacing: 0;
}

.header-chat-badge[hidden] { display: none; }

.status-round {
  text-align: center;
}

.status-active {
  max-width: 100%;
  justify-self: start;
  text-align: center;
}

.status-active-line {
  display: flex;
  align-items: baseline;
  justify-content: center;
  margin-top: 2px;
}

.status-clock {
  display: inline-flex;
  align-items: baseline;
  order: 3;
}

.status-clock[hidden] { display: none !important; }

.status-clock::before {
  content: ":";
  margin-right: .3em;
  color: var(--ink);
  font-size: 15px;
  font-weight: 700;
}

.status-clock time {
  display: inline;
  min-width: 2ch;
  color: var(--ink);
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: normal;
}

.status-clock.is-urgent time {
  color: var(--health);
  animation: turn-clock-urgent 900ms ease-in-out infinite;
}

.status-turn-label {
  display: inline;
  order: 1;
  color: var(--ink);
  font-size: 15px;
  font-weight: 700;
  line-height: normal;
}

.status-turn-label.by-you { color: var(--player); }
.status-turn-label.by-cpu { color: var(--enemy); }

.status-opponent-link {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: .45em;
  order: 2;
  overflow: hidden;
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  line-height: normal;
  text-decoration-color: var(--enemy);
  text-decoration-thickness: 1px;
  text-overflow: ellipsis;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.status-opponent-link::before {
  content: "vs ";
  color: var(--muted);
  font-weight: 600;
  text-decoration: none;
}

.status-opponent-link[hidden] { display: none !important; }

.status-active-line.clock-after-turn-label .status-clock { order: 2; }
.status-active-line.clock-after-turn-label .status-opponent-link { order: 3; }

.player-name-link {
  color: inherit;
  font-weight: inherit;
  text-decoration-color: var(--signature-blue);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a.player-name-link:hover,
a.status-opponent-link:hover {
  text-decoration-thickness: 2px;
}

.status-tools,
.status-turn {
  position: absolute;
  top: 50%;
  display: flex;
  align-items: center;
  gap: 6px;
  transform: translateY(-50%);
}

.status-tools-left {
  left: 14px;
  justify-content: flex-start;
}

.status-turn {
  right: 14px;
  justify-content: flex-end;
}

.menu-btn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--panel);
  font-size: 18px;
  line-height: 1;
}

.status-turn #newGameBtn { display: none; }

.menu-list {
  display: grid;
  gap: 6px;
}

.menu-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 50px;
  padding: 10px 14px;
  text-align: left;
  border-color: var(--line-soft);
  border-radius: 7px;
  background: var(--row);
  font-size: 13px;
  font-weight: 600;
}

.menu-row b { color: var(--ink); font-variant-numeric: tabular-nums; }
.menu-row:disabled {
  cursor: default;
  opacity: .5;
}

.menu-control-state {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-width: 72px;
}

.menu-control-state > b {
  min-width: 20px;
  font-size: 10px;
  letter-spacing: .06em;
  text-align: right;
  text-transform: uppercase;
}

.menu-speed-meter {
  height: 18px;
  display: inline-flex;
  align-items: flex-end;
  gap: 3px;
}

.menu-speed-meter > i {
  width: 6px;
  border: 1px solid var(--ink);
  background: transparent;
}

.menu-speed-meter > i:nth-child(1) { height: 7px; }
.menu-speed-meter > i:nth-child(2) { height: 12px; }
.menu-speed-meter > i:nth-child(3) { height: 17px; }
.menu-speed-meter > i.is-active { background: var(--ink); }

.status-round strong {
  display: block;
  margin-top: 2px;
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.turn-pill {
  padding: 7px 14px;
  color: var(--ink);
  border-color: var(--ink);
  border-radius: 0;
  background: transparent;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.header-account-btn {
  max-width: 160px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  overflow: hidden;
}

.header-tool-label {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.header-sound-btn {
  width: 34px;
  min-width: 34px;
  height: 34px;
  padding: 0;
  display: inline-grid;
  place-items: center;
  font-size: 16px;
  letter-spacing: 0;
  line-height: 1;
}

.header-pvp-btn,
.header-leaderboard-btn {
  height: 34px;
  display: inline-flex;
  align-items: center;
}

.header-pvp-btn[hidden] { display: none !important; }

.header-pvp-btn.is-queue-live {
  --queue-guidance-color: var(--player);
  position: relative;
  background: var(--raised);
  isolation: isolate;
  animation: pvp-queue-attention 4.8s ease-in-out infinite;
}

.header-pvp-btn.is-arriving {
  visibility: hidden;
  pointer-events: none;
  animation: none !important;
}

.header-pvp-btn.is-queue-live::after {
  content: "";
  position: absolute;
  z-index: 1;
  inset: -3px;
  border-radius: inherit;
  background:
    linear-gradient(90deg, var(--queue-guidance-color) 52%, transparent 52%) 0 0 / 12px 2px repeat-x,
    linear-gradient(180deg, var(--queue-guidance-color) 52%, transparent 52%) 100% 0 / 2px 12px repeat-y,
    linear-gradient(270deg, var(--queue-guidance-color) 52%, transparent 52%) 0 100% / 12px 2px repeat-x,
    linear-gradient(0deg, var(--queue-guidance-color) 52%, transparent 52%) 0 0 / 2px 12px repeat-y;
  opacity: .72;
  box-shadow: 0 0 7px color-mix(in srgb, var(--queue-guidance-color) 28%, transparent);
  pointer-events: none;
  animation:
    turn-guidance-march 1.05s linear infinite,
    turn-guidance-glow 2.4s ease-in-out infinite;
}

@keyframes pvp-queue-attention {
  0%, 60%, 100% {
    translate: 0 0;
    rotate: 0deg;
    background: var(--raised);
  }
  64% {
    translate: -4px 0;
    rotate: -.4deg;
    background: color-mix(in srgb, var(--highlight) 65%, var(--raised));
  }
  68% { translate: 4px 0; rotate: .4deg; }
  72% { translate: -4px 0; rotate: -.32deg; }
  76% { translate: 3px 0; rotate: .25deg; }
  80% {
    translate: 0 0;
    rotate: 0deg;
    background: var(--highlight);
  }
  91% { background: color-mix(in srgb, var(--highlight) 38%, var(--raised)); }
}

.header-pvp-btn.is-queue-live:is(:hover, :focus-visible) {
  animation-play-state: paused;
  background: var(--highlight);
}

/* ---------------------------------------------------------------- squad */

.squad {
  min-height: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 230px);
  justify-content: center;
  gap: 10px;
  padding: 25px 14px 4px;
}

.squad.has-summoned-token {
  grid-auto-columns: minmax(0, min(190px, calc((100% - 24px) / 4)));
  gap: 8px;
}

.squad-frame {
  position: relative;
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}

.squad-frame-enemy { background: var(--enemy-zone); }
.squad-frame-ally { background: var(--player-zone); }
[data-board-side="top"] { --side-color: var(--side-top); background: var(--side-top-zone); }
[data-board-side="bottom"] { --side-color: var(--side-bottom); background: var(--side-bottom-zone); }

.squad-heading {
  --squad-heading-font-size: 11px;
  z-index: 5;
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 4px 14px 0;
}

.squad-label {
  min-width: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: 800 var(--squad-heading-font-size)/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .1em;
  text-align: left;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.squad-player-name-link {
  text-decoration-color: var(--side-color);
}

.modifier-hand-peek {
  --hand-owner: var(--player);
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, 15px);
  align-items: center;
  gap: 2px;
  min-height: 31px;
  margin-left: auto;
  justify-self: end;
  padding: 2px 3px;
  border-color: transparent;
  background: transparent;
}

.modifier-hand-peek.is-enemy { --hand-owner: var(--enemy); }

.modifier-hand-peek:disabled {
  cursor: default;
  opacity: .55;
}

.modifier-hand-thumb {
  display: block;
  width: 15px;
  aspect-ratio: 768 / 1365;
  overflow: hidden;
  border: 1px solid var(--hand-owner);
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .14);
  pointer-events: none;
  transition: opacity 120ms ease, transform 120ms ease;
}

.modifier-hand-thumb:nth-child(odd) { transform: rotate(-1deg); }
.modifier-hand-thumb:nth-child(even) { transform: rotate(1deg); }

.modifier-hand-thumb.is-spent {
  opacity: .3;
  filter: grayscale(1);
}

.modifier-hand-thumb-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
}

.squad-resources {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  min-width: 0;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.squad-resource {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--muted);
  font: 700 var(--squad-heading-font-size)/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.squad-resource-pips {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.squad-resource-pips > i {
  display: block;
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
  border: 1px solid var(--dim);
  background: transparent;
}

.squad-resource.is-ap .squad-resource-pips > i { border-radius: 50%; }

.squad-resource.is-ap .squad-resource-pips > i.is-filled {
  border-color: var(--ink);
  background: var(--ink);
}

.squad-resource.is-hype .squad-resource-pips > i {
  border-radius: 1px;
  transform: rotate(45deg) scale(.82);
}

.squad-resource.is-hype .squad-resource-pips > i.is-filled {
  border-color: var(--accent);
  background: var(--accent);
}

.squad-resource.is-hype.is-fully-drained .squad-resource-pips {
  animation: fully-drained-shake var(--beat-duration, 2100ms) ease-in-out both;
}

.squad-resource.is-hype.is-fully-drained .squad-resource-pips > i {
  animation: fully-drained-flash var(--beat-duration, 2100ms) ease-in-out both;
}

.squad-resource-label { color: var(--ink); }
.squad-resource.is-hype .squad-resource-label { color: var(--accent); }

.card {
  position: relative;
  min-width: 0;
  height: 100%;
  width: auto;
  aspect-ratio: 768 / 1365;
  justify-self: center;
  min-height: 0;
  max-height: 288px;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 0;
  overflow: visible;
  padding: 0;
  border: 2px solid var(--line);
  border-radius: 2px;
  background: var(--raised);
  box-shadow: 0 8px 22px var(--shadow);
  cursor: pointer;
  transition: opacity 140ms ease, transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}

/* A card's contents must never contribute a wider intrinsic grid size than the
   portrait itself. This also protects against future badges or long labels. */
.card > :not(.card-pills):not(.floats):not(.target-badge) {
  min-width: 0;
  width: 100%;
  max-width: 100%;
}

.squad-enemy .card { border-color: var(--enemy); }
.squad-ally .card { border-color: var(--player); }

.card-head {
  position: absolute;
  z-index: 3;
  inset: 0 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  min-height: 16px;
  padding: 7px 8px 6px;
  background: rgba(255, 255, 255, .94);
  border-bottom: 1px solid var(--line-soft);
  overflow: hidden;
}

.card-name {
  min-width: 0;
  color: var(--ink);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.card-art {
  position: relative;
  z-index: 1;
  grid-row: 1;
  min-height: 0;
  display: block;
  overflow: hidden;
  background: #f1f2f3;
}

.card-art-image {
  /* The receipt already contains its own title and archival signature. Keep
     the signature pinned to the bottom while the game title masks the small
     duplicated source-title band at the top. Its height follows the native
     receipt ratio so responsive card sizing can crop, but never stretch, the
     artwork. */
  position: absolute;
  inset: auto 0 0;
  width: 100%;
  height: auto;
  aspect-ratio: 768 / 1365;
  display: block;
}

.art-red    { background: linear-gradient(160deg, #4b2926, #2a1a19); }
.art-blue   { background: linear-gradient(160deg, #26384a, #16212c); }
.art-teal   { background: linear-gradient(160deg, #233f3b, #152523); }
.art-violet { background: linear-gradient(160deg, #3c3049, #221c2b); }
.art-gold   { background: linear-gradient(160deg, #4a3b22, #2a2214); }
.art-green  { background: linear-gradient(160deg, #293e2d, #18251b); }

.card-vitals {
  position: relative;
  z-index: 2;
  display: grid;
  gap: 2px;
  grid-row: 2;
  align-self: end;
  padding: 3px 5px;
  background: rgba(255, 255, 255, .96);
  border-top: 1px solid var(--line-soft);
  overflow: hidden;
}

.vital-line {
  min-width: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.hp {
  display: flex;
  align-items: baseline;
  color: var(--good);
  font-variant-numeric: tabular-nums;
}

.hp strong {
  font-size: 26px;
  font-weight: 400;
  line-height: 1;
}

.hp span {
  margin-left: 2px;
  color: var(--dim);
  font-size: 12px;
}

.card.hurt .hp { color: var(--warn); }
.card.danger .hp { color: var(--health); }

.bar {
  height: 5px;
  overflow: hidden;
  border-radius: 3px;
  background: #dfe2e5;
}

.bar > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--good);
  transition: background-color 260ms ease;
}

.card.hurt .bar > span { background: var(--warn); }
.card.danger .bar > span { background: var(--health); }

.shields {
  flex: 0 0 auto;
  min-width: 2ch;
  color: var(--shield);
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-align: right;
}

.shields.is-zero { visibility: hidden; }

.card-pending-damage {
  flex: 0 1 auto;
  min-width: 0;
  padding: 2px 4px;
  overflow: hidden;
  border: 1px solid var(--accent);
  border-radius: 2px;
  color: var(--ink);
  background: #fff;
  font-size: 7px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.03em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pill {
  flex: 0 0 auto;
  padding: 2px 6px;
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--muted);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.pill-exposed,
.pill-stunned {
  color: #000;
  background: #fff;
}

.pill-exposed { border-color: #7a3d3a; }
.pill-stunned { border-color: #7d5a2d; }
.pill-hidden  { color: var(--muted); border-color: var(--line-soft); }
.pill-ko      { color: var(--health); border-color: #7a3d3a; }
.pill-acted   { color: var(--dim); border-color: var(--line-soft); }
.pill-order-restricted {
  color: var(--ink);
  border-color: var(--ink);
  background: #fff;
  box-shadow: 0 2px 0 rgba(21, 21, 21, .16);
}

.pill-order-restricted,
.pill-order-bonus {
  max-width: 100%;
  line-height: 1.15;
  text-align: center;
  white-space: normal;
}

.pill-order-bonus {
  color: var(--ink);
  border-color: var(--player);
  background: #fff;
}

.pill-order-bonus.is-ready {
  border-color: var(--good);
  box-shadow: 0 0 0 1px rgba(22, 133, 110, .22);
}

.card-pills {
  position: absolute;
  z-index: 6;
  right: 0;
  bottom: calc(100% + 5px);
  left: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 3px;
  pointer-events: none;
}

.squad .card-pills {
  right: auto;
  left: 50%;
  width: max-content;
  max-width: calc(100% + 72px);
  transform: translateX(-50%);
}

@media (min-width: 521px) and (max-width: 899px) {
  .squad .card-pills .pill { padding: 1px 4px; font-size: 7px; line-height: 1; letter-spacing: 0.04em; }
}

/* card states */

.card.selectable { cursor: pointer; }

.card.selected {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px var(--ink), 0 10px 26px var(--shadow);
  transform: translateY(-2px);
}

.card.is-remote-selected {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px var(--ink), 0 10px 26px var(--shadow);
  transform: translateY(-2px);
}

.card.is-remote-target {
  --target-outline: var(--side-color, var(--ink));
  box-shadow: 0 0 0 2px var(--target-outline), 0 10px 26px var(--shadow);
}

.card.is-remote-chosen::before {
  border-color: var(--ink);
  opacity: .72;
}

.card.acted { opacity: 0.7; }

.card.blocked { opacity: 0.62; }

/* Action-order passives are temporary tactical information, not a generic
   disabled state. Keep the badge fully legible and dim only the receipt body. */
.card.blocked.order-restricted {
  opacity: 1;
  border-style: dashed;
  cursor: help;
}

.card.order-restricted > :is(.card-head, .card-art, .card-vitals) {
  opacity: .62;
}

.card.order-restricted.targetable > :is(.card-head, .card-art, .card-vitals) {
  opacity: 1;
}

.card.ko {
  opacity: 0.3;
  filter: grayscale(1);
}

.card.dimmed { opacity: 0.22; }

/* A legal target is always at full brightness — an enemy that has already acted
   must not read as unavailable while you are choosing who to hit. */
.card.targetable {
  --target-outline: var(--enemy);
  opacity: 1;
  border-color: var(--target-outline);
  box-shadow: 0 0 0 2px var(--target-outline), 0 10px 26px var(--shadow);
  cursor: pointer;
}

.squad-ally .card.targetable { --target-outline: var(--player); }

.target-badge {
  position: absolute;
  z-index: 4;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  padding: 5px 11px;
  color: var(--ink);
  border-radius: 6px;
  background: var(--target-outline, var(--enemy));
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.06em;
  white-space: nowrap;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.target-badge strong {
  font-size: 19px;
  font-weight: 800;
  line-height: 1;
}

.info-dot {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  padding: 0;
  color: var(--dim);
  border-color: transparent;
  border-radius: 50%;
  background: transparent;
  font-family: Georgia, serif;
  font-size: 11px;
}

/* --------------------------------------------------------- centre strip */

.centre-strip {
  position: relative;
  display: grid;
  justify-items: stretch;
  align-content: center;
  gap: 5px;
  min-height: 72px;
  padding: 4px 10px;
  background: linear-gradient(
    to bottom,
    var(--side-top-zone) 0 50%,
    var(--side-bottom-zone) 50% 100%
  );
}

.field-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  padding: 6px 16px;
  border: 2px solid var(--line);
  border-radius: 0;
  background: var(--panel);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  justify-self: center;
}

.field-chip[hidden] { display: none; }

.field-chip.is-entering {
  animation: field-chip-in var(--field-entry-duration, 650ms) cubic-bezier(0.16, 1, 0.3, 1) both;
}

.field-chip strong {
  color: var(--ink);
  font-weight: 500;
}

.field-chip .field-label {
  color: var(--muted);
  font-weight: 600;
}

.field-chip .field-name {
  color: var(--ink);
  font-weight: 800;
  letter-spacing: 0.08em;
}

.field-chip .field-duration {
  color: var(--dim);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
}

.field-chip .field-duration b {
  color: var(--ink);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.ticker {
  position: absolute;
  z-index: 12;
  display: none;
  justify-self: center;
  align-self: center;
  align-items: center;
  gap: 9px;
  max-width: calc(100% - 28px);
  padding: 7px 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  box-shadow: 0 8px 26px var(--shadow);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.35;
  text-align: center;
  white-space: normal;
  opacity: 0;
  pointer-events: none;
}

.ticker.is-live {
  animation: ticker-in var(--beat-duration, 1650ms) ease-out both;
}

.ticker.by-you { border-color: var(--player); }
.ticker.by-cpu { border-color: var(--enemy); }
.ticker.is-turn {
  display: flex;
  justify-content: center;
  border-width: 2px;
  min-width: 180px;
  padding: 10px 23px;
  font-size: 16px;
  letter-spacing: .025em;
}

.ticker.is-round {
  display: flex;
  justify-content: center;
  border-width: 2px;
  min-width: 210px;
  padding: 12px 28px;
  border-color: var(--ink);
  font-size: 20px;
  letter-spacing: .08em;
}

.ticker b {
  font-weight: 800;
}

.ticker em {
  font-style: normal;
  color: var(--muted);
  font-weight: 400;
}

.resolution-copy {
  min-width: 0;
  display: grid;
  gap: 3px;
  color: var(--text);
}

.resolution-provenance {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: inherit;
  gap: 2px 4px;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.resolution-provenance .feed-sub { margin-left: 8px; }

.resolution-outcomes {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: inherit;
  gap: 3px 10px;
  line-height: 1.15;
}

.resolution-primary,
.resolution-secondary {
  min-width: 0;
  color: var(--text);
  font-size: 11px;
  font-weight: 500;
}

.resolution-primary .feed-delta {
  font-size: 17px;
  line-height: 1;
}

.resolution-outcomes .feed-status {
  display: inline-block;
  padding: 2px 5px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--panel);
  font-size: 11px;
  line-height: 1.1;
}

.resolution-primary.is-critical,
.resolution-secondary.is-critical,
.feed-effect.is-critical {
  color: var(--health);
  font-weight: 800;
  text-transform: uppercase;
}

.ticker .resolution-copy {
  justify-items: center;
  max-width: 100%;
}

.ticker .resolution-provenance,
.ticker .resolution-outcomes {
  justify-content: center;
}

.ticker .resolution-provenance { font-size: 12px; }
.ticker .resolution-primary .feed-delta { font-size: 19px; }

.character-ref {
  color: inherit;
  font-weight: 700;
  white-space: nowrap;
  text-decoration-line: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  text-decoration-skip-ink: none;
}

.character-ref.by-you { text-decoration-color: var(--player); }
.character-ref.by-cpu { text-decoration-color: var(--enemy); }

.feed-separator {
  color: var(--dim);
  font-weight: 400;
}

.feed-action-label {
  color: var(--muted);
  font-weight: 600;
}

.feed-move-name {
  color: var(--muted);
  font-size: clamp(9px, 0.78em, 10px);
  font-weight: 600;
  letter-spacing: 0.075em;
  line-height: 1.1;
  text-transform: uppercase;
  white-space: nowrap;
}

.feed-effect-name {
  color: var(--ink);
  font-weight: 800;
  letter-spacing: 0.025em;
}

.feed-delta {
  display: inline-block;
  color: var(--ink);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
  white-space: nowrap;
}

.feed-modifier-value {
  color: var(--ink);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.025em;
}

.feed-effect {
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.015em;
  white-space: nowrap;
}

.feed-status {
  color: var(--ink);
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.activity-sheet-body { padding: 0; }

.activity-feed {
  min-height: 120px;
  overflow-y: auto;
}

.activity-feed .feed-entry.is-entering {
  animation: activity-entry-in 620ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* ------------------------------------------------------- command panel */

.command {
  position: relative;
  display: grid;
  gap: 9px;
  padding: 11px 14px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line-soft);
  background: var(--panel);
}

.action-offer-alpha {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  opacity: 0;
  pointer-events: none;
}

.command[data-command-view="opponent"] {
  border-top-color: var(--enemy);
  background: color-mix(in srgb, var(--enemy-zone) 45%, var(--panel));
}

.action.is-mirrored,
.target-chip.is-mirrored,
.btn.is-mirrored {
  cursor: default;
  opacity: 1;
}

/* Mirrored controls describe the opponent's decision; they are deliberately
   enemy-colored even when the same move would be blue on the local turn. */
.command[data-command-view="opponent"] .action.is-mirrored,
.command[data-command-view="opponent"] .target-chip.is-mirrored,
.command[data-command-view="opponent"] .btn.is-mirrored {
  color: var(--ink);
  border-color: var(--enemy);
  background: var(--enemy-zone);
}

.command[data-command-view="opponent"] .action.is-mirrored .action-icon {
  background: color-mix(in srgb, var(--enemy-zone) 82%, var(--panel));
}

.command[data-command-view="opponent"] .action.is-selected-action,
.command[data-command-view="opponent"] .target-chip.is-selected-target {
  border-color: var(--enemy);
  box-shadow: inset 4px 0 0 var(--enemy);
}

.action.is-selected-action,
.target-chip.is-selected-target {
  border-color: var(--ink);
  box-shadow: inset 4px 0 0 var(--ink);
}

.target-chip.target-top { border-color: var(--side-top); }
.target-chip.target-bottom { border-color: var(--side-bottom); }

.command-body {
  display: grid;
  gap: 6px;
  /* Reserved so the panel is the same height selected or not, and the board
     never jumps when a Character is chosen. */
  min-height: 214px;
  align-content: start;
}

/* resting / prompt state */

.prompt {
  display: grid;
  gap: 3px;
  align-content: center;
  padding: 4px 2px;
}

.prompt h2 {
  font-size: 17px;
  font-weight: 600;
}

.prompt.is-presentation h2 {
  font-size: 14px;
  font-weight: 560;
}

.prompt-heading-line {
  min-width: 0;
}

.prompt.has-inline-detail .prompt-heading-line {
  --prompt-inline-scale: 1;
  display: flex;
  flex-wrap: nowrap;
  align-items: baseline;
  gap: 2px 9px;
  overflow: hidden;
  white-space: nowrap;
}

.prompt.has-inline-detail .prompt-heading-line h2 {
  flex: 0 0 auto;
  font-size: calc(17px * var(--prompt-inline-scale));
}

.prompt.is-presentation.has-inline-detail .prompt-heading-line h2 {
  font-size: calc(14px * var(--prompt-inline-scale));
}

.prompt.has-inline-detail .prompt-heading-line p {
  flex: 0 0 auto;
  font-size: calc(11px * var(--prompt-inline-scale));
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.35;
}

.prompt p {
  color: var(--muted);
  font-size: 12px;
}

.prompt.targeting h2 { color: var(--ink); }

.multiplayer-reconnect-prompt h2 {
  display: flex;
  align-items: baseline;
}

.waiting-dots {
  display: inline-flex;
  width: 1.5em;
  margin-left: .05em;
}

.waiting-dots i {
  font-style: inherit;
}

.waiting-dots i:nth-child(2) {
  opacity: 0;
  animation: waiting-dot-two 1.2s step-end infinite;
}

.waiting-dots i:nth-child(3) {
  opacity: 0;
  animation: waiting-dot-three 1.2s step-end infinite;
}

@keyframes waiting-dot-two {
  0%, 32% { opacity: 0; }
  33%, 100% { opacity: 1; }
}

@keyframes waiting-dot-three {
  0%, 65% { opacity: 0; }
  66%, 100% { opacity: 1; }
}

.crumb {
  color: var(--muted);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* selected-character header */

.actor-head {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}

.actor-mono {
  display: grid;
  place-items: center;
  height: 42px;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  border-radius: 0;
  background: #f1f2f3;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.04em;
}

.actor-art-image {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center 54%;
}

.actor-id {
  min-width: 0;
}

.actor-id h2 {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.actor-id p {
  display: block;
  margin-top: 2px;
  overflow: visible;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.35;
  white-space: normal;
  overflow-wrap: anywhere;
}

.actor-id p b {
  color: var(--dim);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.actor-vitals {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--good);
  font-variant-numeric: tabular-nums;
}

.actor-vitals strong { font-size: 20px; font-weight: 400; }
.actor-vitals span { color: var(--dim); font-size: 11px; }
.actor-vitals.hurt { color: var(--warn); }
.actor-vitals.danger { color: var(--health); }

/* action rows */

.action {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-height: 52px;
  padding: 7px 11px 7px 7px;
  text-align: left;
  border: 2px solid var(--signature-blue);
  border-radius: 0;
  background: var(--row);
}

.action-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 5px;
  background: var(--panel);
}

.action-icon svg {
  width: 21px;
  height: 21px;
}

.actor-mono svg {
  width: 20px;
  height: 20px;
  color: var(--ink);
}

.action-copy { min-width: 0; }

.action-copy strong {
  display: block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.action-copy span {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.3;
}

.action-cost {
  display: flex;
  align-items: center;
  gap: 5px;
  font-variant-numeric: tabular-nums;
}

.action-cost b {
  font-size: 17px;
  font-weight: 600;
}

.action-cost i {
  width: 10px;
  height: 10px;
  background: var(--dim);
}

.action-cost i.ap { border-radius: 50%; }
.action-cost i.hype { border: 1px solid var(--ink); border-radius: 2px; background: var(--accent); transform: rotate(45deg); }

/* Every legal move uses one visual language. Move type is communicated by its
   label and icon; color communicates only whether the move can be played. */
.action,
.action.primary,
.action.signature {
  color: var(--ink);
  border-color: var(--signature-blue);
  background: var(--row);
  box-shadow: none;
}

.action.primary .action-copy span,
.action.signature .action-copy span { color: var(--muted); }
.action.signature .action-copy strong { color: var(--ink); }

.action.blocked,
.action.blocked.primary,
.action.blocked.signature {
  color: var(--dim);
  border-color: var(--line-soft);
  background: #121415;
  box-shadow: none;
  cursor: not-allowed;
}

.action.blocked .action-copy strong { color: #f5f6f7; }
.action.blocked .action-copy span { color: #c4c8cc; }
.action.blocked .action-icon { opacity: 0.4; background: rgba(255, 255, 255, 0.03); }
.action.blocked .action-cost { color: #c4c8cc; opacity: 0.72; }

.action.blocked[data-blocked-action-key] {
  cursor: pointer;
}

.action-copy .action-details[hidden],
.action-copy .action-compact-reason[hidden] {
  display: none;
}

.action-copy .action-details {
  margin-top: 4px;
}

.action-copy .action-description,
.action-copy .action-requirement {
  margin-top: 0;
}

.action.blocked .action-copy .action-requirement {
  padding-top: 4px;
  color: #f5f6f7;
}

.action-cost .action-disclosure-marker {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border: 1px solid currentColor;
  background: transparent;
  font-size: 15px;
  font-style: normal;
  line-height: 1;
}

.action.blocked.is-expanded {
  border-color: #7b8085;
  background: #1a1d1f;
}

/* target chips */

.target-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.target-chip {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 12px;
  border-color: var(--line);
  border-radius: 7px;
  background: var(--row);
  font-size: 12px;
  font-weight: 600;
}

.target-chip b {
  color: var(--ink);
  font-weight: 700;
}

.target-chip.lethal {
  border-color: #b8382c;
  background: rgba(184, 56, 44, 0.2);
}

.target-chip.lethal b { color: #ff9086; }

/* footer */

.command-footer {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 8px;
}

.command-primary-stack {
  display: grid;
  min-width: 0;
}

.command-primary-stack > * {
  grid-area: 1 / 1;
}

.command-primary-stack .action-offer-beta {
  z-index: 0;
  color: var(--ink);
  border-color: var(--line);
  background: var(--panel);
}

.command-primary-stack .action-offer-cover {
  z-index: 1;
  background: var(--panel);
}

.command-primary-stack .btn-primary {
  position: relative;
  z-index: 2;
}

.btn {
  min-height: 44px;
  padding: 10px 14px;
  border-radius: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.btn-quiet {
  color: var(--ink);
  border-color: var(--line);
  background: transparent;
}

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

.btn:disabled { opacity: 0.35; }

.btn[hidden] { display: none; }

/* --------------------------------------------------------------- rail */

.rail { display: none; }

/* -------------------------------------------------------------- sheets */

.scrim {
  position: fixed;
  z-index: 60;
  inset: 0;
  background: rgba(4, 5, 5, 0.72);
}

.scrim[hidden] { display: none; }

.sheet {
  position: fixed;
  z-index: 70;
  right: 0;
  bottom: 0;
  left: 0;
  max-height: 62vh;
  display: flex;
  flex-direction: column;
  padding-bottom: env(safe-area-inset-bottom);
  border-top: 2px solid var(--line);
  border-radius: 0;
  background: var(--panel);
  box-shadow: 0 -18px 48px var(--shadow);
  animation: sheet-up 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.sheet-tall { max-height: 80vh; }

.sheet[hidden] { display: none; }

#modifiersSheet.is-enemy-view {
  border-color: var(--enemy);
  background: var(--enemy-zone);
}

#modifiersSheet.is-enemy-view .sheet-grip { background: var(--enemy); }

.sheet-grip {
  width: 34px;
  height: 4px;
  margin: 8px auto 2px;
  border-radius: 2px;
  background: var(--line);
}

.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 14px 10px;
}

.sheet-head h2 {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.sheet-close {
  width: 30px;
  height: 30px;
  padding: 0;
  color: var(--muted);
  border-color: transparent;
  border-radius: 50%;
  background: transparent;
  font-size: 19px;
  line-height: 1;
}

.sheet-body {
  overflow-y: auto;
  padding: 0 14px 16px;
  -webkit-overflow-scrolling: touch;
}

.community-sheet { z-index: 110; }

.leaderboard-sheet-body,
.account-sheet-body {
  width: min(820px, 100%);
  margin-inline: auto;
}

.sheet-state {
  display: grid;
  justify-items: start;
  gap: 10px;
  min-height: 112px;
  align-content: center;
  padding: 16px 2px;
  color: var(--muted);
}

.sheet-state .btn { width: auto; }

.chat-sheet-body {
  width: min(620px, 100%);
  margin-inline: auto;
  padding-bottom: 24px;
}

.chat-status {
  min-height: 20px;
  margin-bottom: 12px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .04em;
  text-align: center;
}

.chat-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(64px, 1fr));
  gap: 8px;
}

.chat-emote-btn {
  min-height: 84px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 5px;
  padding: 8px 4px;
  background: #fff;
  box-shadow: 2px 2px 0 rgba(21, 21, 21, .13);
}

.chat-emote-btn:not(:disabled):hover,
.chat-emote-btn:not(:disabled):focus-visible {
  background: var(--highlight);
  transform: translateY(-2px);
  box-shadow: 4px 5px 0 rgba(21, 21, 21, .16);
}

.chat-emote-btn:not(:disabled):active {
  transform: translateY(1px) scale(.97);
  box-shadow: 1px 1px 0 rgba(21, 21, 21, .12);
}

.chat-emote-btn:disabled { opacity: .35; }

.chat-emote-symbol {
  font-size: 35px;
  line-height: 1;
}

.chat-emote-label {
  color: var(--muted);
  font-size: 8px;
  font-weight: 750;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.leaderboard-scroll {
  overflow-x: auto;
  border: 1px solid var(--line-soft);
  -webkit-overflow-scrolling: touch;
}

.leaderboard-table {
  width: 100%;
  min-width: 500px;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.leaderboard-table th,
.leaderboard-table td {
  padding: 10px 12px;
  text-align: right;
  border-bottom: 1px solid var(--line-soft);
}

.leaderboard-table th {
  color: var(--muted);
  background: var(--row);
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.leaderboard-table th:nth-child(2),
.leaderboard-table td:nth-child(2) { text-align: left; }
.leaderboard-table tbody tr:last-child td { border-bottom: 0; }
.leaderboard-table tr.is-you { background: var(--highlight); }
.leaderboard-table .leaderboard-gap td {
  padding-block: 6px;
  color: var(--muted);
  background: var(--row);
  font-size: 18px;
  font-weight: 800;
  letter-spacing: .2em;
  line-height: 1;
  text-align: center;
}
.leaderboard-table .leaderboard-rank { width: 52px; color: var(--muted); }
.leaderboard-table .leaderboard-name { font-weight: 800; overflow-wrap: anywhere; }

.account-card {
  display: grid;
  gap: 14px;
  padding: 18px;
  border: 2px solid var(--line);
  background: var(--row);
}

.account-identity { display: grid; gap: 3px; }
.account-identity strong { font-size: 22px; overflow-wrap: anywhere; }
.account-address {
  color: var(--muted);
  font: 600 11px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}

.account-record {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border: 1px solid var(--line-soft);
  background: var(--panel);
}

.account-record > span {
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: 10px 5px;
  border-right: 1px solid var(--line-soft);
}

.account-record > span:last-child { border-right: 0; }
.account-record b { font-size: 17px; font-variant-numeric: tabular-nums; }
.account-record small { color: var(--muted); font-size: 8px; letter-spacing: .08em; text-transform: uppercase; }
.account-recent { color: var(--muted); font-size: 11px; }
.account-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.account-actions .btn { margin: 0; }

.modifier-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
}

.modifier-card {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr);
  align-items: stretch;
  gap: 10px;
  padding: 11px;
  text-align: left;
  border: 2px solid var(--good);
  border-radius: 0;
  background: var(--row);
}

.modifier-art {
  min-height: 94px;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  background: #f1f2f3;
}

.modifier-art-image {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  object-position: center;
}

.modifier-copy { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; }

.modifier-type {
  display: inline-block;
  margin-bottom: 6px;
  padding: 3px 5px;
  border: 1px solid var(--line);
  font-size: 9px !important;
  font-weight: 600;
  letter-spacing: 0.055em;
  line-height: 1.1 !important;
  text-transform: uppercase;
}

.modifier-card.is-event .modifier-type {
  color: var(--ink);
  border-color: var(--ink);
  background: var(--highlight);
}

.modifier-card.is-field .modifier-type {
  color: #fff;
  border-color: var(--ink);
  background: var(--ink);
}

.modifier-card strong {
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.modifier-card span {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.3;
}

.modifier-card .modifier-cost {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 4px;
  color: var(--ink);
  font-size: 11px;
  font-weight: 700;
}

.modifier-card .modifier-cost i {
  width: 9px;
  height: 9px;
  background: var(--dim);
}

.modifier-card .modifier-cost i.ap { border-radius: 50%; }
.modifier-card .modifier-cost i.hype { border: 1px solid var(--ink); border-radius: 2px; background: var(--accent); transform: rotate(45deg); }

.modifier-card.blocked {
  border-color: var(--line-soft);
  background: #121415;
  cursor: not-allowed;
  opacity: 1;
}

.modifier-card.blocked strong { color: #f5f6f7; }
.modifier-card.blocked span { color: #c4c8cc; }
.modifier-card.blocked .modifier-cost { color: #c4c8cc; }
.modifier-card.spent {
  opacity: 0.58;
  cursor: default;
}

.modifier-card.is-read-only {
  border-color: var(--enemy);
  background: rgba(255, 255, 255, .84);
  cursor: default;
}

.modifier-card.is-read-only.spent { opacity: .5; }

.inspect-block {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}

.inspect-block b {
  display: block;
  margin-bottom: 3px;
  color: var(--ink);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.inspect-block p {
  color: var(--ink);
  font-size: 13px;
  line-height: 1.45;
}

.inspect-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.inspect-meta span {
  padding: 3px 8px;
  color: var(--muted);
  border: 1px solid var(--line-soft);
  border-radius: 0;
  font-size: 10px;
  font-weight: 600;
}

.inspect-layout {
  display: grid;
  grid-template-columns: minmax(180px, 300px) minmax(0, 1fr);
  align-items: start;
  gap: clamp(16px, 4vw, 38px);
}

.inspect-receipt {
  overflow: hidden;
  border: 2px solid var(--ink);
  background: #fff;
  box-shadow: 0 14px 34px var(--shadow);
}

.inspect-receipt-image { width: 100%; height: auto; display: block; }
.inspect-copy { min-width: 0; }

.rules-row {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
}

.rules-row dt { color: var(--ink); font-weight: 700; }
.rules-row dd { color: var(--muted); line-height: 1.4; }

.history-entry {
  position: relative;
  padding: 8px 10px 8px 14px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--text);
  font-size: 11px;
  line-height: 1.4;
}

.history-entry::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 3px;
  background: var(--line);
}

.history-entry.by-you::before { background: var(--player); }
.history-entry.by-cpu::before { background: var(--enemy); }

/* --------------------------------------------------------------- feed */

.feed-entry {
  position: relative;
  padding: 9px 11px 9px 14px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--text);
  background: var(--panel);
}

.feed-entry::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 3px;
  background: var(--line);
}

.feed-entry.by-you::before { background: var(--player); }
.feed-entry.by-cpu::before { background: var(--enemy); }

.feed-entry.is-latest { background: var(--panel); }

.feed-head {
  display: block;
  min-width: 0;
}

.feed-entry.is-latest .resolution-provenance { font-size: 13px; }

.feed-sub {
  color: var(--muted);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.feed-lines {
  display: grid;
  gap: 2px;
  margin-top: 5px;
}

.feed-lines li {
  color: var(--text);
  font-size: 11px;
  line-height: 1.35;
}

.feed-line-name {
  color: var(--text);
  font-weight: 700;
}

.feed-line-cause {
  margin-right: 5px;
  color: var(--accent);
  font: 700 9px/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .045em;
  text-transform: uppercase;
}

.feed-line-arrow {
  margin-right: 5px;
  color: var(--muted);
}

.feed-line-result {
  color: var(--text);
  font-weight: 500;
}

.feed-lines li.is-ko .feed-effect { color: var(--health); }

.feed-mods {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-top: 5px;
}

.feed-mods li {
  padding: 2px 6px;
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 9px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.feed-mods .feed-modifier-value { font-weight: 800; }
.feed-mods .feed-effect { color: var(--text); font-size: inherit; }

/* ------------------------------------------------------------ overlays */

.overlay {
  position: fixed;
  z-index: 90;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(4, 5, 5, 0.84);
}

.overlay[hidden] { display: none; }

.welcome-overlay {
  z-index: 100;
  overflow-y: auto;
  background: rgba(21, 21, 21, 0.48);
  backdrop-filter: blur(4px);
}

.dialog {
  width: min(360px, 100%);
  display: grid;
  gap: 8px;
  justify-items: center;
  padding: 26px 22px;
  text-align: center;
  border: 2px solid var(--line);
  border-radius: 0;
  background: var(--panel);
}

.dialog[hidden] { display: none; }

.dialog h2 { font-size: 26px; font-weight: 600; }
.dialog h1 { margin: 0; font-size: clamp(27px, 3vw, 36px); font-weight: 800; line-height: 1; letter-spacing: -.04em; white-space: nowrap; }
.dialog p { color: var(--muted); font-size: 12px; line-height: 1.5; }
.dialog .btn { width: 100%; margin-top: 8px; }

.welcome-dialog {
  position: relative;
  width: min(460px, 100%);
  gap: 16px;
  padding: clamp(28px, 6vw, 48px);
  box-shadow: 0 22px 60px rgba(21, 21, 21, .28);
}

.welcome-dialog h1 { white-space: pre-line; }

.welcome-close {
  position: absolute;
  top: 12px;
  right: 12px;
}

.welcome-dialog > p { max-width: 350px; font-size: 14px; }

.terms-gate {
  position: fixed;
  z-index: 200;
  inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  overflow-y: auto;
  place-items: center;
  padding: 20px;
  background: rgb(225 228 230 / 55%);
  backdrop-filter: grayscale(.7) blur(4px);
}

.terms-gate[hidden] { display: none; }

.terms-gate-dialog {
  width: 100%;
  max-width: 500px;
  min-width: 0;
  display: grid;
  gap: 20px;
  justify-items: center;
  border: 2px solid var(--line);
  background: var(--panel);
  padding: clamp(28px, 6vw, 48px);
  box-shadow: 0 22px 60px rgba(21, 21, 21, .28);
  text-align: center;
}

.terms-gate-dialog h2 {
  font-size: clamp(24px, 5vw, 34px);
  line-height: 1;
  letter-spacing: -.04em;
  overflow-wrap: anywhere;
}

.terms-gate-dialog p,
.terms-gate-link { font-size: 13px; line-height: 1.5; }

.terms-gate-dialog p { max-width: 390px; color: var(--muted); }

.terms-gate-enter {
  width: min(260px, 100%);
  min-height: 46px;
  font-weight: 900;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.terms-gate-link { color: var(--signature-blue); font-weight: 700; }
.dialog-error { color: var(--health) !important; font-weight: 700; }
.welcome-intro { margin-top: -4px; }
.welcome-intro span { display: block; }
.welcome-intro span:first-child { white-space: nowrap; }

.welcome-actions {
  width: min(310px, 100%);
  display: grid;
  justify-items: center;
  gap: 10px;
  margin-top: 8px;
}

.welcome-actions .btn {
  width: min(82%, 245px);
  min-height: 38px;
  margin: 0;
  padding-block: 7px;
  font-size: 10px;
}

.welcome-community-actions {
  width: min(326px, 100%);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.community-btn {
  min-height: 54px;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  text-align: left;
  border-color: var(--line-soft);
  background: var(--row);
}

.community-btn > span {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  background: var(--panel);
  font-weight: 900;
}

.community-btn b {
  min-width: 0;
  overflow: hidden;
  font-size: 9px;
  letter-spacing: .07em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.welcome-tutorial-btn {
  --turn-guidance-color: var(--player);
  position: relative;
  letter-spacing: .11em;
}

.welcome-tutorial-btn:not(:disabled)::after,
.tutorial-next:not(:disabled)::after {
  content: "";
  position: absolute;
  z-index: 1;
  inset: -5px;
  background:
    linear-gradient(90deg, var(--turn-guidance-color) 54%, transparent 54%) 0 0 / 12px 2px repeat-x,
    linear-gradient(180deg, var(--turn-guidance-color) 54%, transparent 54%) 100% 0 / 2px 12px repeat-y,
    linear-gradient(270deg, var(--turn-guidance-color) 54%, transparent 54%) 0 100% / 12px 2px repeat-x,
    linear-gradient(0deg, var(--turn-guidance-color) 54%, transparent 54%) 0 0 / 2px 12px repeat-y;
  opacity: .7;
  box-shadow: 0 0 10px color-mix(in srgb, var(--turn-guidance-color) 30%, transparent);
  pointer-events: none;
  animation:
    turn-guidance-march 1.05s linear infinite,
    turn-guidance-glow 2.4s ease-in-out infinite;
}

.welcome-standard-btn {
  color: var(--muted);
}

.welcome-pvp-btn {
  border-color: var(--side-top);
  color: var(--ink);
  font-weight: 800;
  letter-spacing: .1em;
}

.matchmaking-dialog {
  width: min(430px, 100%);
  gap: 14px;
  padding: clamp(30px, 6vw, 48px);
  box-shadow: 0 22px 60px rgba(21, 21, 21, .28);
}

.matchmaking-dialog h2 {
  max-width: 320px;
  font-size: clamp(22px, 5vw, 30px);
  font-weight: 800;
  line-height: 1.05;
}

.matchmaking-status {
  min-height: 1.5em;
  color: var(--ink) !important;
  font: 700 10px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace !important;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.matchmaking-pulse {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 20px;
}

.matchmaking-pulse i {
  width: 8px;
  height: 8px;
  border: 1px solid var(--ink);
  background: var(--highlight);
  animation: matchmaking-dot 1.2s ease-in-out infinite;
}

.matchmaking-pulse i:nth-child(2) { animation-delay: 160ms; }
.matchmaking-pulse i:nth-child(3) { animation-delay: 320ms; }

.matchmaking-invite-btn,
.matchmaking-cancel-btn {
  min-height: 44px;
  width: 100%;
  max-width: 230px;
}

.matchmaking-invite-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--highlight);
  text-decoration: none;
}

.matchmaking-invite-btn[hidden] {
  display: none !important;
}

.matchmaking-cancel-btn {
  background: var(--panel);
}

.matchmaking-dialog[data-state="error"] .matchmaking-pulse i {
  border-color: var(--health);
  background: color-mix(in srgb, var(--health) 15%, var(--panel));
  animation: none;
}

@keyframes matchmaking-dot {
  0%, 70%, 100% { translate: 0 0; opacity: .4; }
  35% { translate: 0 -5px; opacity: 1; }
}

.identity-overlay {
  z-index: 120;
  background: rgba(4, 5, 5, .88);
}

.identity-dialog {
  position: relative;
  width: min(420px, 100%);
  gap: 12px;
  padding: 32px 26px 26px;
}

.identity-dialog h2 { line-height: 1.1; }
.identity-dialog > p { max-width: 330px; }
.identity-close { position: absolute; top: 9px; right: 9px; }
.identity-wallet-actions,
.identity-username-form { width: 100%; }

.identity-username-form {
  display: grid;
  gap: 8px;
  text-align: left;
}

.identity-username-form[hidden] { display: none; }
.identity-username-form label { font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.identity-username-form input {
  width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  border: 2px solid var(--line);
  border-radius: 0;
  background: var(--panel);
  color: var(--text);
  font: 700 16px/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.identity-username-form input:focus-visible { outline: 3px solid var(--highlight); outline-offset: 0; }
.identity-username-form p { font-size: 10px; }
.identity-error { max-width: 340px; }
.dialog .game-over-players {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .35em;
  width: 100%;
  color: var(--ink) !important;
  font-size: 24px;
  font-weight: 800;
  line-height: 1.1 !important;
  white-space: nowrap;
}

.game-over-player {
  flex: 0 0 auto;
  color: inherit;
}

.game-over-verb {
  flex: 0 0 auto;
  font-weight: 400;
}

.game-over-overlay {
  overflow-y: auto;
  align-items: start;
}

.game-over-dialog {
  width: 100%;
  max-width: 760px;
  min-width: 0;
  margin: auto;
}

.game-over-dialog > * {
  min-width: 0;
  max-width: 100%;
}

.game-over-share-card {
  width: 100%;
  margin: 10px 0 0;
}

.game-over-share-card img {
  display: block;
  min-width: 0;
  max-width: 100%;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 2px solid var(--line);
  background: #fff;
  object-fit: contain;
}

.game-over-share-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  width: 100%;
}

.game-over-share-actions.is-pvp {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.game-over-share-actions .btn { margin-top: 0; }

.post-x-symbol {
  font-family: "STIX Two Math", "Cambria Math", "Times New Roman", serif;
  font-size: 1.18em;
  line-height: 0;
}

@media (max-width: 560px) {
  .game-over-overlay { padding: 10px; }
  .game-over-dialog { padding: 18px 14px; }
  .game-over-share-actions.is-pvp { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The same illustrated primer is inserted at the top of About. */
.about-primer { margin-bottom: 22px; }
.about-primer > h3 {
  margin: 0 0 10px;
  font-size: 15px;
  font-weight: 850;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.game-primer { width: 100%; display: grid; margin: 0; text-align: left; }
.game-primer > div {
  display: grid;
  grid-template-columns: 124px minmax(0, 1fr);
  gap: 14px;
  padding: 13px 0;
  border-top: 1px solid var(--line-soft);
}
.game-primer dt {
  display: grid;
  align-content: start;
  justify-items: start;
  gap: 8px;
  color: var(--ink);
  font-size: 11px;
  font-weight: 850;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.game-primer dd { margin: 0; color: var(--muted); font-size: 11px; line-height: 1.45; }
.primer-visual { min-height: 18px; }
.primer-trophy { font-size: 22px; line-height: 1; }
.primer-visual .squad-resource-pips { gap: 5px; }
.primer-visual .squad-resource-pips > i { width: 11px; height: 11px; }
.primer-modifier-cards {
  min-height: 29px;
  margin: -3px 0 0;
  justify-self: start;
  padding: 0;
  pointer-events: none;
}
.primer-modifier-cards .modifier-hand-thumb { background: var(--raised); }

.about-steps { display: grid; gap: 0; margin: 18px 0; counter-reset: about-step; }
.about-steps li { display: grid; grid-template-columns: 34px minmax(0, 1fr); padding: 14px 0; border-top: 1px solid var(--line-soft); counter-increment: about-step; }
.about-steps li::before { grid-row: 1 / span 2; content: counter(about-step); font: 800 20px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.about-steps b { font-size: 13px; }
.about-steps span { margin-top: 3px; color: var(--muted); font-size: 12px; line-height: 1.45; }
.about-rules { margin-top: 18px; border-top: 2px solid var(--ink); padding-top: 16px; }
.about-rules h3 { margin: 0 0 12px; font-size: 15px; font-weight: 850; letter-spacing: .1em; text-transform: uppercase; }
.about-alpha { display: grid; gap: 4px; border: 2px solid var(--ink); padding: 14px; background: var(--highlight); }
.about-alpha b { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; }
.about-alpha span { font-size: 12px; line-height: 1.45; }

/* ----------------------------------------------------- tutorial coach marks */

.tutorial-scrim {
  position: fixed;
  z-index: 104;
  inset: 0;
  display: none;
  background: rgb(225 228 230 / 55%);
  backdrop-filter: grayscale(.7) blur(1.5px);
  cursor: default;
  pointer-events: none;
}

body.is-tutorial-coaching .tutorial-scrim { display: block; }

/* End Tutorial is the one global escape hatch while coaching is active. The
   right control group creates its own stacking context, so lift the group—not
   only the button—above both the scrim and coach layer. */
body.is-tutorial .status-turn {
  z-index: 112;
  pointer-events: none;
}

body.is-tutorial .status-tools,
body.is-tutorial .header-pvp-btn,
body.is-tutorial .header-leaderboard-btn,
body.is-tutorial .status-turn .menu-btn { display: none; }

body.is-tutorial #newGameBtn {
  position: relative;
  display: inline-flex;
  align-items: center;
  pointer-events: auto;
  color: var(--ink);
  border-color: var(--ink);
  background: var(--panel);
}

.tutorial-overlay {
  position: fixed;
  z-index: 110;
  inset: 0;
  pointer-events: none;
}

.tutorial-overlay[hidden] { display: none; }

.tutorial-coachmark {
  position: fixed;
  left: var(--tutorial-coach-left, 50%);
  top: var(--tutorial-coach-top, 50%);
  width: min(390px, calc(100vw - 28px));
  display: grid;
  justify-items: center;
  gap: 9px;
  padding: 24px 22px 20px;
  border: 2px solid var(--ink);
  background: var(--panel);
  box-shadow: 0 18px 48px rgba(21, 21, 21, .24);
  text-align: center;
  pointer-events: auto;
  transform: translate(-50%, -50%);
}

.tutorial-overlay[data-placement="top"] .tutorial-coachmark {
  --tutorial-coach-top: max(96px, 18vh);
}

.tutorial-overlay[data-placement="bottom"] .tutorial-coachmark {
  top: auto;
  bottom: max(22px, calc(env(safe-area-inset-bottom) + 14px));
  transform: translateX(-50%);
}

.tutorial-overlay[data-placement="left"] .tutorial-coachmark {
  --tutorial-coach-left: max(205px, 24vw);
}

.tutorial-overlay[data-placement="right"] .tutorial-coachmark {
  --tutorial-coach-left: min(calc(100vw - 205px), 76vw);
}

.tutorial-overlay[data-placement="anchor"] .tutorial-coachmark {
  right: auto;
  bottom: auto;
  transform: none;
}

.tutorial-progress {
  align-self: start;
  justify-self: start;
  padding-top: 4px;
  color: var(--muted);
  font: 750 9px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tutorial-coach-heading {
  width: 100%;
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) 42px;
  align-items: start;
  gap: 6px;
}

.tutorial-coach-heading::after {
  content: "";
}

.tutorial-coachmark h2 {
  grid-column: 2;
  max-width: 100%;
  font-size: clamp(22px, 4vw, 30px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.025em;
}

.tutorial-coachmark > p {
  max-width: 320px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-line;
}

.tutorial-next {
  --turn-guidance-color: var(--player);
  position: relative;
}

.tutorial-coach-actions {
  width: min(340px, 100%);
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 9px;
  margin-top: 7px;
}

.tutorial-coach-actions .btn {
  width: min(230px, 100%);
  margin: 0;
}

.tutorial-coach-actions:has(.tutorial-alt:not([hidden])) .btn {
  width: auto;
  flex: 1 1 0;
  padding-inline: 9px;
  font-size: 10px;
}

.tutorial-alt[hidden] { display: none; }
.tutorial-overlay[data-interactive="true"] .tutorial-coach-actions { display: none; }

/* Add this class to the one real board control a lesson is discussing. The
   control rises above the neutral scrim and remains clickable. Owner/resource
   modifiers let the script preserve the board's established color language. */
body.is-tutorial-coaching .tutorial-spotlight {
  --tutorial-spotlight-color: var(--player);
  position: relative !important;
  z-index: 106 !important;
  outline: 3px solid var(--tutorial-spotlight-color);
  outline-offset: 5px;
  box-shadow:
    0 0 0 8px rgba(255, 255, 255, .95),
    0 0 25px color-mix(in srgb, var(--tutorial-spotlight-color) 45%, transparent) !important;
  isolation: isolate;
  animation: tutorial-spotlight-pulse 1.7s ease-in-out infinite;
  pointer-events: auto;
}

body.is-tutorial-coaching .tutorial-spotlight-player { --tutorial-spotlight-color: var(--player); }
body.is-tutorial-coaching .tutorial-spotlight-enemy { --tutorial-spotlight-color: var(--enemy); }
body.is-tutorial-coaching .tutorial-spotlight-effect { --tutorial-spotlight-color: var(--good); }
body.is-tutorial-coaching .tutorial-spotlight-resource { --tutorial-spotlight-color: var(--accent); }

/* Resource pips sit inside a deliberately layered squad heading. Lift that
   heading too when one of its children is the lesson target, otherwise its
   local stacking context would remain under the tutorial scrim. */
body.is-tutorial-coaching .squad-heading:has(.tutorial-spotlight) {
  position: relative;
  z-index: 106;
}

/* Mobile Safari and Chrome composite the backdrop-filter scrim separately.
   Lift the transparent content containers as well as the highlighted child so
   their real controls remain sharp and hit-test above that compositor layer. */
body.is-tutorial-coaching :is(.squad, .command-body):has(.tutorial-spotlight) {
  position: relative;
  z-index: 106;
}

/* The Modifier picker normally sits below the tutorial's neutral scrim.
   Lift it only for the lesson that asks the player to choose a real card. */
body.is-tutorial-coaching .sheet:has(.tutorial-spotlight) {
  z-index: 106;
}

@keyframes tutorial-spotlight-pulse {
  0%, 100% {
    outline-offset: 4px;
    filter: brightness(1);
  }
  50% {
    outline-offset: 7px;
    filter: brightness(1.08);
  }
}

/* ------------------------------------------------ interactive feedback */

/* Player-turn guidance follows the next legal decision instead of lighting up
   the whole interface at once. JavaScript adds turn-actionable only to choices
   accepted by legalActions(); the body gate is a second guard against stale
   cues during CPU turns and after the match ends. */
.turn-actionable {
  --turn-guidance-color: var(--player);
  position: relative;
}

.card.targetable.turn-actionable {
  --turn-guidance-color: var(--enemy);
}

.squad-ally .card.targetable.turn-actionable,
.target-chip.target-ally.turn-actionable {
  --turn-guidance-color: var(--player);
}

.target-chip.target-enemy.turn-actionable {
  --turn-guidance-color: var(--enemy);
}

.modifier-hand-peek.turn-actionable,
.modifier-card.turn-actionable {
  --turn-guidance-color: var(--good);
}

#cancelBtn.turn-actionable {
  --turn-guidance-color: var(--player);
}

#endTurnBtn.turn-actionable {
  --turn-guidance-color: var(--ink);
}

body.is-player-turn .turn-actionable:not(:disabled):not(.blocked):not(.spent)::after {
  content: "";
  position: absolute;
  z-index: 9;
  inset: -3px;
  border-radius: inherit;
  background:
    linear-gradient(90deg, var(--turn-guidance-color) 52%, transparent 52%) 0 0 / 12px 2px repeat-x,
    linear-gradient(180deg, var(--turn-guidance-color) 52%, transparent 52%) 100% 0 / 2px 12px repeat-y,
    linear-gradient(270deg, var(--turn-guidance-color) 52%, transparent 52%) 0 100% / 12px 2px repeat-x,
    linear-gradient(0deg, var(--turn-guidance-color) 52%, transparent 52%) 0 0 / 2px 12px repeat-y;
  opacity: 0.62;
  box-shadow: 0 0 5px color-mix(in srgb, var(--turn-guidance-color) 22%, transparent);
  pointer-events: none;
  animation:
    turn-guidance-march 1.05s linear infinite,
    turn-guidance-glow 2.4s ease-in-out infinite;
}

.turn-actionable:focus-visible::after {
  opacity: 0 !important;
  animation: none !important;
}

.squad .card:nth-child(2)::after,
.command-actions .action:nth-child(2)::after {
  animation-delay: 120ms;
}

.squad .card:nth-child(3)::after,
.command-actions .action:nth-child(3)::after {
  animation-delay: 240ms;
}

.modifier-grid .modifier-card:nth-child(3n + 2)::after { animation-delay: 120ms; }
.modifier-grid .modifier-card:nth-child(3n)::after { animation-delay: 240ms; }

@keyframes turn-guidance-march {
  to {
    background-position:
      24px 0,
      100% 24px,
      -24px 100%,
      0 -24px;
  }
}

@keyframes turn-guidance-glow {
  0%, 100% {
    opacity: 0.54;
    box-shadow: 0 0 4px color-mix(in srgb, var(--turn-guidance-color) 18%, transparent);
  }
  50% {
    opacity: 0.82;
    box-shadow: 0 0 9px color-mix(in srgb, var(--turn-guidance-color) 32%, transparent);
  }
}

/* Every operable element gets the same three-part affordance: a visible
   keyboard ring, a lift on pointer hover, and a short press on activation.
   Component colors still communicate ownership and availability. */
@media (hover: hover) {
  .alpha-brand:hover {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    transform: translateY(-1px);
  }

  :is(.turn-pill, .menu-btn, .field-chip, .btn, .sheet-close, .info-dot):not(:disabled):hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 0 rgba(21, 21, 21, 0.2);
  }

  .turn-pill:hover {
    color: var(--panel);
    background: var(--ink);
  }

  :is(.menu-btn, .sheet-close, .info-dot):hover {
    color: var(--text);
    background: var(--raised);
  }

  .field-chip:hover { background: var(--row); }

  .btn-quiet:hover:not(:disabled) {
    border-color: var(--ink);
    background: var(--row);
  }

  .menu-row:hover:not(:disabled) {
    border-color: var(--ink);
    background: var(--panel);
    box-shadow: 4px 0 0 rgba(21, 21, 21, 0.18);
    transform: translateX(3px);
  }

  .action:not(.blocked):hover:not(:disabled) {
    border-color: var(--signature-blue);
    background: var(--panel);
    box-shadow: 4px 4px 0 rgba(31, 102, 194, 0.2);
    transform: translate(-2px, -2px);
  }

  .action.blocked[data-blocked-action-key]:hover {
    border-color: #7b8085;
    background: #1a1d1f;
  }

  .target-chip:hover:not(:disabled) {
    background: var(--panel);
    box-shadow: 0 4px 0 rgba(21, 21, 21, 0.2);
    transform: translateY(-2px);
  }

  .modifier-card:not(.blocked):not(.spent):hover {
    background: var(--panel);
    box-shadow: 5px 5px 0 rgba(22, 133, 110, 0.2);
    transform: translate(-2px, -2px);
  }

  .modifier-hand-peek:not(:disabled):hover {
    border-color: var(--hand-owner);
    background: rgba(255, 255, 255, .58);
    box-shadow: 0 4px 0 color-mix(in srgb, var(--hand-owner) 28%, transparent);
    transform: translateY(-2px);
  }

  .modifier-hand-peek:not(:disabled):hover .modifier-hand-thumb:nth-child(odd) {
    transform: translateY(-2px) rotate(-2deg);
  }

  .modifier-hand-peek:not(:disabled):hover .modifier-hand-thumb:nth-child(even) {
    transform: translateY(-1px) rotate(2deg);
  }

  .card:not(.acting):not(.hit):not(.dying):not(.healed):not(.shielded):not(.restored):hover {
    box-shadow: 0 13px 30px var(--shadow);
    transform: translateY(-3px);
  }

  .card.selected:not(.acting):not(.hit):not(.dying):hover {
    box-shadow: 0 0 0 2px var(--ink), 0 13px 30px var(--shadow);
  }

  .card.targetable:not(.acting):not(.hit):not(.dying):hover {
    box-shadow: 0 0 0 2px var(--target-outline), 0 13px 30px var(--shadow);
  }
}

.alpha-brand:active {
  opacity: 0.68;
  transform: translateY(1px);
}

:is(.turn-pill, .menu-btn, .field-chip, .btn, .sheet-close, .info-dot):not(:disabled):active,
.target-chip:active:not(:disabled) {
  box-shadow: 0 1px 0 rgba(21, 21, 21, 0.25);
  transform: translateY(1px) scale(0.985);
}

.menu-row:active:not(:disabled) {
  box-shadow: 1px 0 0 rgba(21, 21, 21, 0.22);
  transform: translateX(1px) scale(0.99);
}

.action:not(.blocked):active:not(:disabled) {
  box-shadow: 1px 1px 0 rgba(31, 102, 194, 0.24);
  transform: translate(1px, 1px) scale(0.99);
}

.action.blocked[data-blocked-action-key]:active {
  transform: translateY(1px) scale(0.995);
}

.modifier-card:not(.blocked):not(.spent):active {
  box-shadow: 1px 1px 0 rgba(22, 133, 110, 0.25);
  transform: translate(1px, 1px) scale(0.99);
}

.modifier-hand-peek:not(:disabled):active {
  box-shadow: 0 1px 0 color-mix(in srgb, var(--hand-owner) 32%, transparent);
  transform: translateY(1px) scale(.985);
}

.card:not(.acting):not(.hit):not(.dying):not(.healed):not(.shielded):not(.restored):active {
  box-shadow: 0 3px 10px var(--shadow);
  transform: translateY(1px) scale(0.99);
}

.card.selected:not(.acting):not(.hit):not(.dying):active {
  box-shadow: 0 0 0 2px var(--ink), 0 3px 10px var(--shadow);
}

.card.targetable:not(.acting):not(.hit):not(.dying):active {
  box-shadow: 0 0 0 2px var(--target-outline), 0 3px 10px var(--shadow);
}

/* --------------------------------------------------------- animations */

.card.acting {
  z-index: 3;
  animation: lunge var(--beat-duration, 950ms) cubic-bezier(0.2, 0.8, 0.2, 1);
}

.card.acted.acting { animation-name: lunge-acted; }
.card.incoming { z-index: 3; }
.card.incoming-by-you { --incoming-color: var(--player); }
.card.incoming-by-cpu { --incoming-color: var(--enemy); }
.card.incoming::before { animation: incoming-target var(--beat-duration, 950ms) ease-out both; }
.card.modifier-receiving { z-index: 3; }
.card.modifier-receiving-by-you { --modifier-receive-color: var(--player); }
.card.modifier-receiving-by-cpu { --modifier-receive-color: var(--enemy); }
.card.modifier-receiving::before {
  animation: modifier-receiving var(--beat-duration, 1100ms) ease-out both;
}
.card.effect-triggering,
.card.effect-trigger-target { z-index: 4; }
.card.effect-triggering::before {
  border-color: var(--ink);
  animation: effect-trigger-card var(--beat-duration, 2700ms) ease-out both;
}
.card.effect-trigger-target:not(.effect-triggering)::before {
  border-color: var(--accent);
  animation: effect-trigger-target var(--beat-duration, 2700ms) ease-out both;
}
.card.awaiting-summon { visibility: hidden; }
.card.hit { z-index: 3; }

/* Motion and result emphasis live on separate layers. A self-damaging move can
   now lunge and register its impact instead of one animation overwriting the
   other. */
.card.hit > :is(.card-head, .card-art, .card-vitals) {
  animation: impact-shake var(--beat-duration, 2100ms) ease-out both;
}

.card::before {
  content: "";
  position: absolute;
  z-index: 7;
  inset: -2px;
  border: 3px solid transparent;
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
}

.card.health-hit::before { animation: impact-health var(--beat-duration, 2100ms) ease-out both; }
.card.shield-hit::before { animation: impact-shield var(--beat-duration, 2100ms) ease-out both; }
.card.healed::before { animation: pulse-good var(--beat-duration, 2100ms) ease-out both; }
.card.shielded::before { animation: pulse-shield var(--beat-duration, 2100ms) ease-out both; }
.card.restored::before { animation: pulse-restored var(--beat-duration, 2100ms) ease-out both; }
.card.dying { animation: dying var(--beat-duration, 2100ms) ease-out both; }

.floats {
  position: absolute;
  z-index: 8;
  inset: 31% -24px auto;
  display: grid;
  justify-items: center;
  gap: 5px;
  pointer-events: none;
}

.float {
  width: max-content;
  max-width: calc(100% + 48px);
  padding: 6px 11px;
  color: var(--ink);
  border: 2px solid currentColor;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.97);
  box-shadow: 0 8px 22px rgba(21, 21, 21, 0.22);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  text-align: center;
  animation: float-result var(--beat-duration, 2100ms) ease-out both;
}

.float-result { font-size: clamp(21px, 2.65vw, 29px); letter-spacing: -0.035em; }
.float-health.is-loss { color: var(--health); }
.float-shield { color: var(--shield); }
.float-result.is-gain { color: var(--good); }
.float-status { animation-name: float-status; }
.float-ko {
  color: var(--health);
  font-size: 15px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  animation-name: float-ko;
}

@keyframes lunge {
  0%, 100% { transform: translateY(0) scale(1); }
  38% { transform: translateY(-12px) scale(1.035); }
}

@keyframes lunge-acted {
  0%, 100% { opacity: 0.7; transform: translateY(0) scale(1); }
  18%, 62% { opacity: 1; }
  38% { opacity: 1; transform: translateY(-12px) scale(1.035); }
}

@keyframes incoming-target {
  0%, 100% { opacity: 0; box-shadow: none; }
  18%, 76% { opacity: .9; border-color: var(--incoming-color); box-shadow: 0 0 24px var(--incoming-color); }
}

@keyframes pvp-match-intro {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.72) rotate(-1deg); }
  10% { opacity: 1; transform: translate(-50%, -50%) scale(1.035) rotate(.25deg); }
  18%, 86% { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
}

@keyframes event-card-reveal {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.62) rotate(-1.5deg); }
  18% { opacity: 1; transform: translate(-50%, -50%) scale(1.045) rotate(.5deg); }
  30%, 80% { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(.92); }
}

@keyframes effect-trigger-in {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.76) rotate(-.6deg); }
  16% { opacity: 1; transform: translate(-50%, -50%) scale(1.04) rotate(.25deg); }
  29%, 78% { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
}

@keyframes effect-trigger-card {
  0%, 100% { opacity: 0; box-shadow: none; }
  18%, 74% { opacity: .92; box-shadow: 0 0 22px rgba(21, 21, 21, .38); }
}

@keyframes effect-trigger-target {
  0%, 100% { opacity: 0; box-shadow: none; }
  22%, 76% { opacity: .88; box-shadow: 0 0 24px var(--accent); }
}

@keyframes fully-drained-shake {
  0%, 12%, 70%, 100% { transform: translateX(0); }
  18%, 30%, 42%, 54% { transform: translateX(-4px); }
  24%, 36%, 48%, 60% { transform: translateX(4px); }
}

@keyframes fully-drained-flash {
  0%, 12%, 70%, 100% { border-color: var(--dim); box-shadow: none; }
  20%, 60% { border-color: var(--accent); box-shadow: 0 0 8px var(--accent); }
}

@keyframes modifier-reveal-aura {
  0% { opacity: 0; transform: scale(.72) rotate(0); }
  20% { opacity: .78; }
  72% { opacity: .42; transform: scale(1.08) rotate(2deg); }
  100% { opacity: 0; transform: scale(1.22) rotate(3deg); }
}

@keyframes modifier-cast-source {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.86); }
  12%, 84% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
}

@keyframes modifier-conduit-line {
  0% { opacity: 0; transform: scaleX(0); }
  12% { opacity: .82; }
  76% { opacity: .72; transform: scaleX(1); }
  100% { opacity: 0; transform: scaleX(1); }
}

@keyframes modifier-wave {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.45); }
  14% { opacity: 1; }
  75% { opacity: 1; transform: translate(calc(var(--trace-distance) - 50%), -50%) scale(1); }
  100% { opacity: 0; transform: translate(calc(var(--trace-distance) - 50%), -50%) scale(2); }
}

@keyframes modifier-receiving {
  0%, 100% { opacity: 0; box-shadow: none; }
  24%, 72% {
    opacity: .92;
    border: 3px dashed var(--modifier-receive-color);
    box-shadow: 0 0 0 5px rgba(195, 255, 255, .78), 0 0 28px var(--modifier-receive-color);
  }
}

@keyframes combat-trace-line {
  0% { opacity: 0; transform: scaleX(0); }
  12% { opacity: .72; }
  72% { opacity: .5; transform: scaleX(1); }
  100% { opacity: 0; transform: scaleX(1); }
}

@keyframes combat-projectile {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(45deg) scale(.55); }
  12% { opacity: 1; }
  76% { opacity: 1; transform: translate(calc(var(--trace-distance) - 50%), -50%) rotate(225deg) scale(1); }
  100% { opacity: 0; transform: translate(calc(var(--trace-distance) - 50%), -50%) rotate(225deg) scale(1.65); }
}

@keyframes combat-move-label {
  0% { opacity: 0; transform: translate(-50%, -42%) scale(.92); }
  14%, 76% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -56%) scale(.98); }
}

@keyframes combat-static-label {
  0% { opacity: 0; transform: translate(-50%, -42%) scale(.92); }
  12%, 82% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -58%) scale(.98); }
}

@keyframes impact-shake {
  0%, 100% { transform: translateX(0); }
  14% { transform: translateX(-6px); }
  28% { transform: translateX(6px); }
  44% { transform: translateX(-4px); }
  60% { transform: translateX(2px); }
}

@keyframes impact-health {
  0%, 100% { opacity: 0; box-shadow: none; }
  12%, 48% { opacity: 1; border-color: var(--health); box-shadow: 0 0 28px rgba(240, 107, 101, 0.5); }
}

@keyframes impact-shield {
  0%, 100% { opacity: 0; box-shadow: none; }
  12%, 48% { opacity: 1; border-color: var(--shield); box-shadow: 0 0 28px rgba(31, 102, 194, 0.42); }
}

@keyframes pulse-good {
  0%, 100% { opacity: 0; box-shadow: none; }
  16%, 58% { opacity: 1; border-color: var(--good); box-shadow: 0 0 28px rgba(115, 201, 138, 0.46); }
}

@keyframes pulse-shield {
  0%, 100% { opacity: 0; box-shadow: none; }
  16%, 58% { opacity: 1; border-color: var(--shield); box-shadow: 0 0 28px rgba(98, 182, 239, 0.5); }
}

@keyframes pulse-restored {
  0%, 100% { opacity: 0; box-shadow: none; }
  16%, 58% {
    opacity: 1;
    border-color: var(--good);
    box-shadow: 0 0 0 2px var(--shield), 0 0 30px rgba(115, 201, 138, 0.5);
  }
}

@keyframes dying {
  0% { transform: scale(1); filter: grayscale(0); opacity: 1; }
  35% { transform: scale(1.03); box-shadow: inset 0 0 0 3px var(--health); }
  100% { transform: scale(0.98); filter: grayscale(1); opacity: 0.3; }
}

@keyframes float-result {
  0% { opacity: 0; transform: translateY(10px) scale(0.82); }
  9% { opacity: 1; transform: translateY(0) scale(1); }
  72% { opacity: 1; transform: translateY(-3px) scale(1); }
  100% { opacity: 0; transform: translateY(-24px) scale(0.97); }
}

@keyframes float-status {
  0% { opacity: 0; transform: translateY(8px) scale(0.9); }
  10%, 74% { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(-18px); }
}

@keyframes float-ko {
  0% { opacity: 0; transform: translateY(8px) scale(0.8); }
  10%, 78% { opacity: 1; transform: translateY(0) scale(1.04); }
  100% { opacity: 0; transform: translateY(-20px) scale(1); }
}

@keyframes ticker-in {
  0% { opacity: 0; transform: scale(0.94); }
  3% { opacity: 1; transform: scale(1); }
  92% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes field-chip-in {
  0% {
    opacity: 0;
    transform: translateY(8px) scale(0.94);
  }
  62% {
    opacity: 1;
    transform: translateY(-1px) scale(1.02);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes ticker-hold {
  0%, 99.9% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: none; }
}

@keyframes activity-entry-in {
  0% {
    opacity: 0;
    background: var(--row);
    transform: translateY(-9px);
  }
  55% {
    opacity: 1;
    background: var(--row);
    transform: translateY(0);
  }
  100% {
    opacity: 1;
    background: var(--panel);
    transform: translateY(0);
  }
}

@keyframes sheet-up {
  from { transform: translateY(14px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

@keyframes throb {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

/* -------------------------------------------------------------- phone */

/* The Combat Log rail narrows the stage before the viewport itself becomes
   phone-sized. Compact the right-side controls anywhere that collision can
   occur, including the 900px desktop breakpoint. */
@media (max-width: 1400px) {
  .statusbar {
    display: grid;
    grid-template-columns:
      minmax(0, 1fr)
      minmax(0, min(440px, calc(100% - 400px)))
      minmax(0, 1fr);
    align-items: center;
    gap: 0;
  }
  .status-tools,
  .status-turn {
    position: static;
    top: auto;
    transform: none;
  }
  .status-tools { grid-column: 1; justify-self: start; }
  .status-summary {
    grid-column: 2;
    justify-self: center;
    width: fit-content;
    max-width: 100%;
    min-width: 0;
    grid-template-columns: 72px minmax(0, 1fr);
    gap: clamp(12px, 2vw, 32px);
  }
  .status-turn { grid-column: 3; justify-self: end; }
  .status-active,
  .status-active-line { min-width: 0; }
  .status-active-line { flex-wrap: nowrap; }
  .status-turn-label,
  .status-clock { flex: none; }
  .status-opponent-link { flex: 0 1 auto; }
}

@media (max-width: 1100px) {
  .statusbar {
    grid-template-columns:
      minmax(0, 1fr)
      minmax(0, min(440px, calc(100% - 300px)))
      minmax(0, 1fr);
  }
  .status-tools { left: 8px; gap: 3px; }
  .status-turn { right: 8px; gap: 3px; }
  .status-tools .turn-pill,
  .status-turn .turn-pill {
    height: 30px;
    min-width: 0;
    padding: 6px 8px;
    font-size: 8px;
    letter-spacing: .055em;
  }
  .header-account-btn.turn-pill { max-width: 108px; }
  .header-sound-btn { width: 30px; height: 30px; padding: 0; }
  .menu-btn { width: 30px; height: 30px; }
}

@media (max-width: 899px) {
  .centre-strip { min-height: 54px; }
}

/* Keep the proven narrow top-bar proportions through small-tablet widths.
   The wider controls collide between 521px and 700px, while the board itself
   does not need to enter the phone layout until 520px. */
@media (max-width: 700px) {
  .alpha-banner { padding: 6px 8px; font-size: 8px; }
  .alpha-brand { font-size: 10px; }
  .alpha-banner-copy { display: none; }
  .status-slot { min-width: 0; }
  .statusbar {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 6px 8px;
  }
  .status-tools,
  .status-turn {
    position: static;
    top: auto;
    transform: none;
  }
  .status-tools { grid-column: 1; gap: 2px; }
  .status-turn { grid-column: 3; gap: 2px; }
  .status-summary {
    grid-column: 2;
    display: flex;
    justify-content: center;
    width: 100%;
    min-width: 0;
  }
  .status-round { display: none; }
  .status-active > .micro { display: none; }
  .status-active-line {
    min-width: 0;
    margin: 0;
    gap: 3px;
    flex-wrap: nowrap;
  }
  .status-turn-label { flex: none; font-size: 10px; white-space: nowrap; }
  .status-opponent-link {
    flex: 0 1 auto;
    margin-left: 0;
    font-size: 9px;
  }
  .status-clock { flex: none; }
  .status-clock::before { margin-right: .15em; font-size: 11px; }
  .status-clock time { font-size: 11px; }
  .header-account-btn.turn-pill { max-width: 108px; }
  .header-sound-btn { width: 28px; min-width: 28px; height: 28px; padding: 0; font-size: 13px; }
  .menu-btn { width: 28px; height: 28px; }
  .turn-pill { max-width: 100%; padding: 6px 7px; overflow: hidden; font-size: 8px; letter-spacing: .055em; text-overflow: ellipsis; }
  .status-tools .turn-pill,
  .status-turn .turn-pill { height: 28px; padding-inline: 3px; letter-spacing: .035em; }
}

@media (max-width: 520px) {
  body { overflow-x: hidden; overflow-y: auto; }
  /* Keep all six public-record columns visible without making phone players
     pan the leaderboard sideways. Username takes the flexible column. */
  .leaderboard-sheet-body { padding-inline: 8px; }
  .leaderboard-table {
    min-width: 0;
    table-layout: fixed;
    font-size: 10px;
    line-height: 1.2;
  }
  .leaderboard-table th,
  .leaderboard-table td {
    padding: 7px 3px;
    white-space: nowrap;
  }
  .leaderboard-table th {
    font-size: 8px;
    letter-spacing: .025em;
  }
  .leaderboard-table th:first-child,
  .leaderboard-table .leaderboard-rank { width: 28px; }
  .leaderboard-table th:nth-child(3) { width: 34px; }
  .leaderboard-table th:nth-child(4) { width: 38px; }
  .leaderboard-table th:nth-child(5) { width: 34px; }
  .leaderboard-table th:nth-child(6) { width: 48px; }
  .leaderboard-table .leaderboard-name {
    overflow-wrap: anywhere;
    white-space: normal;
  }
  .welcome-overlay { padding: 12px; }
  .welcome-dialog { min-width: 0; padding: 28px 16px; }
  .welcome-dialog h1 { font-size: clamp(21px, 7vw, 27px); }
  .welcome-actions { width: min(280px, calc(100% - 12px)); }
  .game-primer > div { grid-template-columns: 108px minmax(0, 1fr); gap: 10px; }
  .tutorial-coachmark { padding: 21px 17px 18px; }
  .tutorial-overlay[data-placement="left"] .tutorial-coachmark,
  .tutorial-overlay[data-placement="right"] .tutorial-coachmark {
    --tutorial-coach-left: 50%;
  }
  .app { width: 100vw; min-width: 0; min-height: 100%; height: auto; }
  .stage { position: relative; width: 100vw; max-width: 100vw; min-width: 0; min-height: 100svh; height: 100dvh; overflow: hidden; }
  .stage > * { min-width: 0; max-width: 100vw; }
  .squad-heading { --squad-heading-font-size: 10px; gap: 4px; padding: 3px 8px 0; }
  .squad-resources { gap: 8px; }
  .squad-resource { gap: 3px; letter-spacing: .025em; }
  .squad-resource-pips { gap: 3px; }
  .squad-resource-pips > i { width: 8px; height: 8px; }
  .modifier-hand-peek {
    grid-template-columns: repeat(6, 11px);
    gap: 1px;
    min-height: 25px;
    padding: 1px 2px;
  }
  .modifier-hand-thumb { width: 11px; }
  .squad {
    display: flex;
    width: 100vw;
    max-width: 100vw;
    gap: 6px;
    padding: 22px 8px 3px;
    overflow: hidden;
  }

  .card { padding: 0; border-radius: 1px; }
  /* Keep cues inside the tighter phone gutters. Characters and action rows
     already have a 2px side-colored border; drawing the ants directly over it
     makes their transparent gaps reveal the same color and visually turns the
     animation back into a solid outline. Move those cues just inside their
     border while hands, targets, and End Turn keep the external ring. */
  body.is-player-turn .turn-actionable:not(:disabled):not(.blocked):not(.spent)::after { inset: -2px; }
  body.is-player-turn :is(.card, .action).turn-actionable:not(:disabled):not(.blocked):not(.spent)::after { inset: 1px; }
  /* A flex item can otherwise shrink only its width while retaining the
     height supplied by the board track, distorting the receipt around the
     middle of the phone breakpoint. Constrain height by both the available
     row and the width budget, then let aspect-ratio derive the width. */
  .squad .card {
    width: auto !important;
    height: min(100%, 288px, calc((100vw - 28px) / 1.6879121));
    max-width: none !important;
    align-self: center;
    flex: 0 0 auto;
  }
  .squad.has-summoned-token .card {
    width: auto !important;
    height: min(100%, 288px, calc((100vw - 34px) / 2.2505495));
    max-width: none !important;
    align-self: center;
    flex: 0 0 auto;
  }
  .card-art { min-width: 0; }
  .card-name { font-size: 8px; letter-spacing: 0.04em; }
  .card-head { min-height: 24px; padding: 5px 6px 4px; }
  .squad .card-pills { right: 0; left: 0; width: auto; max-width: none; gap: 1px; transform: none; }
  .card-pills .pill { padding: 1px 2px; font-size: 6px; line-height: 1; letter-spacing: 0; }
  .card-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hp strong { font-size: 20px; }
  .hp span { font-size: 10px; }
  .info-dot { display: none; }
  .centre-strip { min-height: 54px; padding: 6px 8px; }
  .command { padding: 9px 10px calc(10px + env(safe-area-inset-bottom)); }
  .command-body { min-height: 196px; }
  .action { grid-template-columns: 34px minmax(0, 1fr) auto; min-height: 46px; gap: 9px; }
  .action-icon { width: 34px; height: 34px; font-size: 15px; }
  .action-copy strong { font-size: 12px; }
  .action-copy span { font-size: 10px; }
  .btn { font-size: 11px; padding: 10px 8px; letter-spacing: 0.05em; }
  .inspect-layout { grid-template-columns: minmax(120px, 42vw) minmax(0, 1fr); gap: 12px; }
  .chat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .chat-emote-btn { min-height: 74px; }
  .chat-emote-symbol { font-size: 31px; }
}

@media (max-width: 360px) {
  .leaderboard-table { font-size: 9px; }
  .leaderboard-table th { font-size: 7px; }
  .welcome-community-actions { gap: 6px; }
  .community-btn {
    grid-template-columns: 26px minmax(0, 1fr);
    gap: 5px;
    padding-inline: 6px;
  }
  .community-btn > span { width: 26px; }
  .community-btn b {
    overflow: visible;
    font-size: 8px;
    letter-spacing: 0;
    text-overflow: clip;
  }
  .status-tools { left: 4px; gap: 3px; }
  .status-turn { right: 4px; }
  .status-tools .turn-pill,
  .status-turn .turn-pill { min-width: 0; padding-inline: 3px; font-size: 7px; letter-spacing: .035em; }
  .header-account-btn.turn-pill { max-width: 100px; }
  .status-turn .header-pvp-btn { max-width: 46px; font-size: 8px; }
  .status-turn .header-leaderboard-btn { max-width: 82px; font-size: 8px; }
  .squad-heading { --squad-heading-font-size: 9px; }
  .squad-label { letter-spacing: .05em; }
  .squad-resources { gap: 6px; }
  .squad-resource,
  .squad-resource-pips { gap: 2px; }

}

/* Compact phones keep navigation in a dedicated row below the brand. Round
   and turn remain available through their between-turn announcements. During
   the tutorial, the row contracts to the persistent End Tutorial escape. */
@media (max-width: 450px) {
  .alpha-banner {
    min-height: 30px;
    padding: 6px 8px;
  }

  .alpha-brand { font-size: 10px; }

  .statusbar {
    z-index: 20;
    min-height: 40px;
    height: auto;
    padding: 6px 8px;
  }

  /* This header normally sits below overlays. During the tutorial it contains
     the persistent exit control, so its mobile stacking context must clear the
     coach scrim just as the desktop control does. */
  body.is-tutorial .statusbar { z-index: 112; }

  .status-summary { display: none; }

  .chat-sheet-body { padding-inline: 10px; }

  body.is-tutorial .status-turn #newGameBtn {
    max-width: none;
    display: inline-flex;
    align-items: center;
    min-height: 34px;
    padding: 7px 9px;
    overflow: visible;
    font-size: 8px;
    letter-spacing: .055em;
    text-overflow: clip;
  }

  .tutorial-overlay[data-placement="top"] .tutorial-coachmark {
    --tutorial-coach-top: max(150px, 22vh);
  }
}

/* Short phone viewports keep the entire board inside the visual viewport and
   make the command body its own scroll region if a long passive plus three
   actions cannot fit. This avoids sending the actionable rows below Safari's
   browser chrome. */
@media (max-width: 520px) and (max-height: 850px) {
  body { overflow: hidden; }

  .app,
  .stage {
    min-height: 100svh;
    height: 100dvh;
  }

  .squad { padding: 12px 8px 2px; }
  .centre-strip { min-height: 36px; padding-block: 2px; }

  .command {
    gap: 4px;
    min-height: 0;
    max-height: 46dvh;
    overflow: hidden;
    padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
  }

  .command-body {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  .actor-head {
    grid-template-columns: 32px minmax(0, 1fr) auto;
    gap: 7px;
    padding-bottom: 4px;
  }

  .actor-mono { height: 32px; }
  .actor-id p { font-size: 10px; line-height: 1.25; }
  .action { min-height: 44px; }
  .command-footer .btn { min-height: 38px; padding-block: 7px; }
}

/* ------------------------------------------------------------ desktop */

@media (min-width: 900px) {
  .app {
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 8px;
    padding: 8px;
  }

  .stage {
    border: 2px solid var(--line);
    border-radius: 0;
    overflow: hidden;
  }

  .squad {
    grid-auto-columns: minmax(0, 250px);
    padding: 23px 18px 10px;
  }

  .squad.has-summoned-token {
    grid-auto-columns: minmax(0, min(190px, calc((100% - 24px) / 4)));
  }

  .squad-heading { padding-inline: 18px; }

  .centre-strip { min-height: 54px; place-items: center; padding: 4px 14px; }
  .ticker { display: flex; }

  .command {
    padding: 14px 18px;
  }

  .command-body { min-height: 116px; }

  .command-inner {
    display: grid;
    grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
    align-items: start;
    gap: 20px;
  }

  .actor-head {
    padding: 0 18px 0 0;
    border-right: 1px solid var(--line-soft);
    border-bottom: 0;
  }

  .command-actions {
    display: grid;
    gap: 6px;
  }

  .command-footer {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .command-footer .btn { min-width: 150px; }
  .command-primary-stack { margin-left: auto; }
  .command-footer .btn-primary { margin-left: 0; min-width: 190px; }

  .rail {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    border: 2px solid var(--line);
    border-radius: 0;
    background: var(--panel);
  }

  .rail-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 14px 12px;
    border-bottom: 1px solid var(--line-soft);
  }

  .rail-head h2 {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }

  .winner { color: var(--good); font-size: 11px; font-weight: 700; }

  .feed {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
  }

  .sheet {
    right: auto;
    bottom: auto;
    left: 50%;
    top: 50%;
    width: min(560px, calc(100vw - 40px));
    max-height: 76vh;
    border: 2px solid var(--line);
    border-radius: 0;
    transform: translate(-50%, -50%);
  }

  .sheet-grip { display: none; }
}

@media (min-width: 521px) and (max-width: 899px) {
  .centre-strip {
    min-height: 54px;
    padding: 6px 10px;
  }
}

/* Multiplayer keeps top/bottom positions shared while color remains
   viewer-relative: your side is blue and the opponent is red. */
body.is-pvp[data-local-side="bottom"] {
  --side-top: var(--enemy);
  --side-top-zone: var(--enemy-zone);
  --side-bottom: var(--player);
  --side-bottom-zone: var(--player-zone);
}

body.is-pvp[data-local-side="top"] {
  --side-top: var(--player);
  --side-top-zone: var(--player-zone);
  --side-bottom: var(--enemy);
  --side-bottom-zone: var(--enemy-zone);
}

body.is-pvp [data-board-side="top"] .card { border-color: var(--side-top); }
body.is-pvp [data-board-side="bottom"] .card { border-color: var(--side-bottom); }
body.is-pvp [data-board-side="top"] .modifier-hand-peek { --hand-owner: var(--side-top); }
body.is-pvp [data-board-side="bottom"] .modifier-hand-peek { --hand-owner: var(--side-bottom); }
body.is-pvp [data-board-side="top"] .card.targetable {
  --target-outline: var(--side-top);
}
body.is-pvp [data-board-side="bottom"] .card.targetable {
  --target-outline: var(--side-bottom);
}
body.is-pvp [data-board-side="top"] .card.targetable.turn-actionable {
  --turn-guidance-color: var(--side-top);
}
body.is-pvp [data-board-side="bottom"] .card.targetable.turn-actionable {
  --turn-guidance-color: var(--side-bottom);
}

.status-turn-label.by-top { color: var(--side-top); }
.status-turn-label.by-bottom { color: var(--side-bottom); }
.ticker.by-top { border-color: var(--side-top); }
.ticker.by-bottom { border-color: var(--side-bottom); }
.character-ref.by-top { text-decoration-color: var(--side-top); }
.character-ref.by-bottom { text-decoration-color: var(--side-bottom); }
.history-entry.by-top::before,
.feed-entry.by-top::before { background: var(--side-top); }
.history-entry.by-bottom::before,
.feed-entry.by-bottom::before { background: var(--side-bottom); }
.combat-trace.by-top,
.combat-move-label.by-top,
.combat-resource-result.by-top,
.modifier-conduit.by-top { color: var(--side-top); }
.combat-trace.by-bottom,
.combat-move-label.by-bottom,
.combat-resource-result.by-bottom,
.modifier-conduit.by-bottom { color: var(--side-bottom); }
.combat-move-label.by-top,
.combat-resource-result.by-top { color: var(--ink); border-color: var(--side-top); }
.combat-move-label.by-bottom,
.combat-resource-result.by-bottom { color: var(--ink); border-color: var(--side-bottom); }
.effect-trigger-callout.by-top { --trigger-owner: var(--side-top); }
.effect-trigger-callout.by-bottom { --trigger-owner: var(--side-bottom); }
.modifier-reveal-card.by-top,
.modifier-cast-source.by-top { --modifier-owner: var(--side-top); }
.modifier-reveal-card.by-bottom,
.modifier-cast-source.by-bottom { --modifier-owner: var(--side-bottom); }
.card.incoming-by-top { --incoming-color: var(--side-top); }
.card.incoming-by-bottom { --incoming-color: var(--side-bottom); }
.card.modifier-receiving-by-top { --modifier-receive-color: var(--side-top); }
.card.modifier-receiving-by-bottom { --modifier-receive-color: var(--side-bottom); }

.presence-layer {
  position: fixed;
  z-index: 80;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.emoji-fx-layer {
  position: fixed;
  z-index: 125;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  contain: layout paint;
}

.emoji-scene,
.emoji-particle {
  position: absolute;
  pointer-events: none;
}

.emoji-scene { inset: 0; }

.emoji-particle {
  display: block;
  font-size: var(--emoji-size, 54px);
  line-height: 1;
  opacity: 0;
  filter: drop-shadow(0 5px 5px rgba(21, 21, 21, .12));
  will-change: transform, opacity;
  animation-delay: var(--emoji-delay, 0ms);
  animation-duration: var(--emoji-duration, 2600ms);
  animation-fill-mode: both;
  animation-timing-function: cubic-bezier(.2, .72, .3, 1);
}

.emoji-scene--rain .emoji-particle {
  top: -16vh;
  left: var(--emoji-x);
  animation-name: emoji-rain;
}

.emoji-scene--sweep .emoji-particle {
  top: var(--emoji-y);
  left: -28vw;
  animation-name: emoji-sweep;
}

.emoji-scene--bounce .emoji-particle {
  bottom: -12vh;
  left: var(--emoji-x);
  animation-name: emoji-bounce;
}

.emoji-scene--burst .emoji-particle {
  top: 50%;
  left: 50%;
  animation-name: emoji-burst;
}

.emoji-scene--wave .emoji-particle {
  top: var(--emoji-y);
  left: -12vw;
  animation-name: emoji-wave;
}

.emoji-scene.is-reduced .emoji-particle {
  top: 50%;
  left: 50%;
  animation-name: emoji-reduced;
}

@keyframes emoji-rain {
  0% { opacity: 0; transform: translate3d(0, -8vh, 0) rotate(0deg) scale(.75); }
  12%, 76% { opacity: var(--emoji-opacity); }
  100% { opacity: 0; transform: translate3d(var(--emoji-drift), 126vh, 0) rotate(var(--emoji-spin)) scale(1); }
}

@keyframes emoji-sweep {
  0% { opacity: 0; transform: translate3d(0, 0, 0) rotate(-12deg) scale(.8); }
  14%, 82% { opacity: var(--emoji-opacity); }
  50% { transform: translate3d(65vw, -5vh, 0) rotate(var(--emoji-spin)) scale(1.08); }
  100% { opacity: 0; transform: translate3d(158vw, 2vh, 0) rotate(16deg) scale(.9); }
}

@keyframes emoji-bounce {
  0% { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg) scale(.65); }
  12% { opacity: var(--emoji-opacity); }
  38% { transform: translate3d(0, -72vh, 0) rotate(12deg) scale(1); }
  65% { transform: translate3d(var(--emoji-drift-half), -10vh, 0) rotate(-8deg) scale(.88); }
  82% { opacity: var(--emoji-opacity); transform: translate3d(var(--emoji-drift), -35vh, 0) rotate(var(--emoji-spin)) scale(.94); }
  100% { opacity: 0; transform: translate3d(var(--emoji-drift), 18vh, 0) rotate(var(--emoji-spin)) scale(.76); }
}

@keyframes emoji-burst {
  0% { opacity: 0; transform: translate3d(-50%, -50%, 0) scale(.1) rotate(0deg); }
  16%, 70% { opacity: var(--emoji-opacity); }
  100% { opacity: 0; transform: translate3d(calc(-50% + var(--emoji-dx)), calc(-50% + var(--emoji-dy)), 0) scale(1.08) rotate(var(--emoji-spin)); }
}

@keyframes emoji-wave {
  0% { opacity: 0; transform: translate3d(0, 18vh, 0) rotate(-15deg) scale(.7); }
  12% { opacity: var(--emoji-opacity); }
  28% { transform: translate3d(34vw, -14vh, 0) rotate(6deg) scale(1); }
  52% { transform: translate3d(68vw, 12vh, 0) rotate(-7deg) scale(.92); }
  76% { opacity: var(--emoji-opacity); transform: translate3d(102vw, -10vh, 0) rotate(8deg) scale(1); }
  100% { opacity: 0; transform: translate3d(128vw, 12vh, 0) rotate(var(--emoji-spin)) scale(.78); }
}

@keyframes emoji-reduced {
  0%, 100% { opacity: 0; transform: translate3d(-50%, -50%, 0) scale(.9); }
  20%, 75% { opacity: 1; transform: translate3d(-50%, -50%, 0) scale(1); }
}

.remote-pointer {
  --presence-color: var(--enemy);
  position: absolute;
  top: 0;
  left: 0;
  width: 15px;
  height: 20px;
  border: 2px solid #fff;
  border-radius: 10px 10px 10px 1px;
  background: var(--ink);
  box-shadow: 0 2px 8px rgba(21, 21, 21, .42);
  opacity: .92;
  pointer-events: none;
  transform-origin: 0 0;
  transition: transform 100ms linear, opacity 180ms ease;
  will-change: transform;
}

.remote-pointer::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: inherit;
  background: var(--presence-color);
}

.remote-pointer[data-side="top"] { --presence-color: var(--side-top); }
.remote-pointer[data-side="bottom"] { --presence-color: var(--side-bottom); }

.remote-pointer-label {
  position: absolute;
  z-index: 2;
  top: 14px;
  left: 19px;
  min-width: max-content;
  padding: 3px 6px;
  border: 1px solid var(--presence-color);
  background: #fff;
  box-shadow: 0 2px 7px rgba(21, 21, 21, .18);
  color: var(--ink);
  font: 800 8px/1.15 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .07em;
  text-transform: uppercase;
  white-space: nowrap;
}

.remote-pointer-label::before {
  content: "";
  position: absolute;
  right: 100%;
  top: 5px;
  width: 9px;
  border-top: 1px solid var(--presence-color);
  transform: rotate(26deg);
  transform-origin: right center;
}

.remote-pointer[data-pointer-type="touch"] {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: transparent;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--presence-color) 34%, transparent);
}

.remote-pointer[data-pointer-type="touch"]::after {
  inset: 6px;
  border-radius: 50%;
}

.remote-pointer[data-pointer-type="touch"] .remote-pointer-label {
  top: 20px;
  left: 27px;
}

.remote-pointer.is-stale { opacity: 0; }

@keyframes turn-clock-urgent {
  50% { opacity: .45; }
}

@media (max-width: 450px) {
  body.is-pvp .status-summary {
    position: static;
    grid-column: 2;
    grid-row: 1;
    display: flex;
    width: auto;
    transform: none;
  }

  body.is-pvp .statusbar {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: 30px;
    row-gap: 0;
    min-height: 42px;
    padding: 5px 8px;
  }

  body.is-pvp .status-tools {
    grid-column: 1;
    grid-row: 1;
  }

  body.is-pvp .status-turn {
    grid-column: 3;
    grid-row: 1;
  }

  body.is-pvp .header-chat-btn {
    min-width: 86px;
    height: 28px;
    padding-inline: 6px;
    font-size: 8px;
  }

  body.is-pvp .header-chat-btn > span:first-child { font-size: 14px; }
}

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

  .ticker.is-live {
    animation-name: ticker-hold !important;
    animation-duration: 5.25s !important;
  }

  body.is-player-turn .turn-actionable:not(:disabled):not(.blocked):not(.spent)::after {
    animation: none !important;
    opacity: 0.68;
    box-shadow: 0 0 4px color-mix(in srgb, var(--turn-guidance-color) 22%, transparent);
  }

  .remote-pointer,
  .status-clock.is-urgent time {
    animation: none !important;
    transition: opacity 1ms linear !important;
  }

  .waiting-dots i {
    opacity: 1;
    animation: none !important;
  }

  .header-pvp-btn.is-queue-live {
    background: var(--highlight);
    animation: none !important;
  }

  .pvp-challenge-badge::after {
    animation: none !important;
  }

  .emoji-scene.is-reduced .emoji-particle {
    animation-name: emoji-reduced !important;
    animation-duration: 1200ms !important;
  }

  .header-pvp-btn.is-queue-live::after,
  .matchmaking-pulse i {
    opacity: .82;
    animation: none !important;
  }
}
