/* ============================================================
   BLINDSPOT REDESIGN — Phase 4b: Battle (Vein theme)
   Faithful static mock of the design's battle screen. JS hooks
   (arena-*, bs-*-bar, bs-move-card) are stashed offscreen so
   bs-arena-battle-ui.js etc. don't error when writing to them.
   This screen is visually faithful but non-functional.
   ============================================================ */

/* ---------- SCREEN SHELL ----------
   Beats legacy `.bs-screen.active#bs-screen-battle { max-width: 860px }`
   at blindspot.css:5676 — that rule has specificity (0,1,2,0); ours
   needs to be at least equal and load later.
   Only `.active` shows; legacy `.bs-screen { display: none }` keeps
   the inactive state hidden. */
/* play.html: ID-qualified to beat legacy `.bs-screen.active#bs-screen-battle`
   index.html: separate selector — has the same Vein wrapper class but
   uses #bs-battle-container as ID, no .bs-screen / .active class
   (visibility is toggled via inline style.display, not a screen router).
   Display property kept on play.html only since the inline-style model
   on index.html would fight it. */
.bs-screen.active#bs-screen-battle.blindspot-battle {
  position: relative;
  min-height: calc(100vh - 69px);
  max-width: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  display: block;
  font-family: var(--blindspot-font-body);
  color: var(--blindspot-text);
  flex: unset;
  /* Solid background covers gutters on wide viewports where the
     centered .arena-battle (1480px max) doesn't fill horizontally. */
  background: var(--blindspot-bg);
}
#bs-battle-container.blindspot-battle {
  position: relative;
  /* index.html has no topbar above the battle (deliberately dropped in
     the Apr 30 splash redesign), so use the full viewport rather than
     the - 69px that #bs-screen-battle subtracts for play.html's
     topbar. Without this the page leaves a 69px dead band at the
     bottom of the onboarding battle. */
  min-height: 100vh;
  max-width: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  font-family: var(--blindspot-font-body);
  color: var(--blindspot-text);
  flex: unset;
  /* On index.html the page particles canvas would show through the
     gutters otherwise. */
  background: var(--blindspot-bg);
}

/* ---------- ARENA BG ---------- */
.blindspot-battle__arena {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  filter: blur(2px) brightness(0.4) saturate(0.8);
}
.blindspot-battle__arena-veil {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: radial-gradient(ellipse at center, transparent 30%, rgba(0, 0, 0, 0.85) 80%);
}

.blindspot-battle__shell {
  position: relative;
  z-index: 1;
  padding: 1rem 2rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  min-height: calc(100vh - 69px);
  max-width: 1480px;
  margin: 0 auto;
}

/* ---------- HUD TOP ---------- */
.blindspot-battle__hud-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-tile);
  padding: 0.6rem 1rem;
  backdrop-filter: blur(8px);
}
.blindspot-battle__round {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.95rem;
  flex-shrink: 0;
}
.blindspot-battle__round-num {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  color: var(--blindspot-accent);
  font-size: 1.4rem;
  font-weight: 600;
}
.blindspot-battle__intent {
  flex: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.5em 0.9em;
  background: var(--blindspot-surface);
  border: 1px solid var(--blindspot-border-2);
  border-left: 3px solid var(--blindspot-epic);
  border-radius: var(--blindspot-radius-button);
  font-size: 0.9rem;
  color: var(--blindspot-text-dim);
  font-style: italic;
}
.blindspot-battle__intent i {
  color: var(--blindspot-epic);
  flex-shrink: 0;
}
.blindspot-battle__top-actions {
  display: flex;
  gap: 0.4rem;
  flex-shrink: 0;
}
.blindspot-icon-btn {
  background: transparent;
  border: 1px solid var(--blindspot-border);
  color: var(--blindspot-text-dim);
  border-radius: var(--blindspot-radius-button);
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color var(--blindspot-transition-fast),
              border-color var(--blindspot-transition-fast);
}
.blindspot-icon-btn:hover {
  color: var(--blindspot-accent);
  border-color: var(--blindspot-accent-dim);
}

/* ---------- STAGE: 3-col ---------- */
.blindspot-battle__stage {
  display: grid;
  grid-template-columns: 1fr 240px 1fr;
  gap: 1.2rem;
  align-items: stretch;
}
@media (max-width: 1100px) {
  .blindspot-battle__stage {
    grid-template-columns: 1fr 1fr;
    gap: 0.8rem;
  }
  .blindspot-battle__center {
    grid-column: 1 / -1;
    order: -1;
    flex-direction: row !important;
  }
}

/* ---------- COMBATANT ---------- */
.blindspot-combatant {
  background: rgba(0, 0, 0, 0.5);
  border: 1px solid var(--blindspot-border-2);
  border-radius: var(--blindspot-radius-card);
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  backdrop-filter: blur(6px);
  position: relative;
  overflow: hidden;
}
.blindspot-combatant--you  { border-left: 2px solid var(--blindspot-accent); }
.blindspot-combatant--them { border-right: 2px solid var(--blindspot-danger); }

.blindspot-combatant__plate {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.blindspot-combatant__name {
  font-family: var(--blindspot-font-display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--blindspot-text);
}
.blindspot-combatant__sub {
  font-family: var(--blindspot-font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blindspot-text-muted);
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}
.blindspot-combatant__sub i {
  color: var(--blindspot-text-dim);
}

.blindspot-combatant__portrait {
  aspect-ratio: 16 / 10;
  background-size: cover;
  background-position: center top;
  border: 1px solid var(--blindspot-border-2);
  border-radius: var(--blindspot-radius-tile);
}

.blindspot-combatant__hp-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.85rem;
  margin-bottom: 0.2rem;
}
.blindspot-combatant__hp-row .blindspot-eyebrow,
.blindspot-combatant__hp-row .blindspot-num {
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.blindspot-combatant__hp-row .blindspot-num {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.05em;
  text-transform: none;
  font-weight: 600;
  color: var(--blindspot-accent);
  font-size: 0.95rem;
}
.blindspot-combatant--them .blindspot-combatant__hp-row .blindspot-num {
  color: var(--blindspot-danger);
}

/* HP bar variants — block-style */
.blindspot-bar--hp .blindspot-bar__fill {
  background: linear-gradient(90deg, var(--blindspot-accent-dim), var(--blindspot-accent));
}
.blindspot-bar--hp.blindspot-bar--enemy .blindspot-bar__fill {
  background: linear-gradient(90deg, var(--blindspot-danger), #ff8a6a);
}
.blindspot-bar--hype .blindspot-bar__fill {
  background: linear-gradient(90deg, var(--blindspot-epic), #d8a9ff);
}

/* Stamina pips */
.blindspot-stam-pips {
  display: flex;
  gap: 4px;
}
.blindspot-stam-pip {
  flex: 1;
  height: 8px;
  background: var(--blindspot-bg-2);
  border: 1px solid var(--blindspot-border);
  border-radius: 2px;
}
.blindspot-stam-pip.is-on {
  background: linear-gradient(180deg, var(--blindspot-accent-gold), var(--blindspot-accent));
  border-color: var(--blindspot-accent);
}

/* Buffs */
.blindspot-combatant__buffs {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
  margin-top: 0.2rem;
}
.blindspot-buff {
  font-family: var(--blindspot-font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  padding: 0.25em 0.65em;
  border-radius: 999px;
  border: 1px solid;
  text-transform: uppercase;
}
.blindspot-buff--good {
  color: var(--blindspot-accent);
  border-color: var(--blindspot-accent-dim);
  background: rgba(200, 48, 44, 0.08);
}
.blindspot-buff--bad {
  color: var(--blindspot-danger);
  border-color: rgba(200, 48, 44, 0.45);
  background: rgba(200, 48, 44, 0.08);
}
.blindspot-buff--combo {
  color: var(--blindspot-epic);
  border-color: rgba(142, 93, 171, 0.55);
  background: rgba(142, 93, 171, 0.12);
  animation: blindspot-pulse 1.5s ease-in-out infinite;
}
@keyframes blindspot-pulse {
  0%, 100% { opacity: 0.65; }
  50%      { opacity: 1; }
}

/* ---------- CENTER ---------- */
.blindspot-battle__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 0;
}
.blindspot-battle__vs {
  font-family: var(--blindspot-font-display);
  font-style: italic;
  font-weight: 600;
  font-size: 2.6rem;
  color: var(--blindspot-accent);
  letter-spacing: 0.08em;
  text-shadow: 0 0 40px rgba(200, 48, 44, 0.5);
}
.blindspot-battle__hype {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.blindspot-battle__hype-label {
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-epic);
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}
.blindspot-battle__hype-hint {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-text-muted);
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
}
.blindspot-battle__stances {
  display: flex;
  gap: 0.4rem;
  width: 100%;
  justify-content: space-around;
}
.blindspot-stance-btn {
  flex: 1;
  background: var(--blindspot-surface);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-tile);
  padding: 0.55rem 0.3rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  font-size: 0.6rem;
  color: var(--blindspot-text-muted);
  font-family: var(--blindspot-font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: color var(--blindspot-transition-fast),
              border-color var(--blindspot-transition-fast),
              background var(--blindspot-transition-fast);
}
.blindspot-stance-btn__g {
  font-size: 1.15rem;
  font-family: var(--blindspot-font-display);
  font-weight: 600;
  color: inherit;
}
.blindspot-stance-btn:hover {
  border-color: var(--blindspot-accent-dim);
  color: var(--blindspot-text);
}
.blindspot-stance-btn.is-active {
  border-color: var(--blindspot-accent);
  color: var(--blindspot-accent);
  background: rgba(200, 48, 44, 0.1);
}

/* ---------- LOG ---------- */
.blindspot-battle__log {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-tile);
  padding: 0.7rem 1rem;
  font-size: 0.9rem;
  backdrop-filter: blur(8px);
  max-height: 130px;
  overflow-y: auto;
}
.blindspot-battle__log-head {
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-accent);
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  margin-bottom: 0.5rem;
}
.blindspot-battle__log-rows {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.blindspot-log-row {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.15rem 0;
}
.blindspot-log-row__round {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-text-muted);
  font-size: 0.7rem;
  letter-spacing: 0.05em;
}
.blindspot-log-row__text {
  color: var(--blindspot-text-dim);
}
.blindspot-log-row__dmg {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  color: var(--blindspot-accent);
  font-weight: 600;
  font-size: 0.9rem;
}
.blindspot-log-row__dmg.is-crit { color: var(--blindspot-danger); }
.blindspot-log-row--reflect .blindspot-log-row__text { color: var(--blindspot-info); }
.blindspot-log-row--crit    .blindspot-log-row__text { color: var(--blindspot-text); }

/* ---------- HAND ---------- */
.blindspot-battle__hand-wrap { margin-top: auto; }
.blindspot-battle__hand-rail {
  display: flex;
  gap: 0.5em;
  align-items: center;
  margin-bottom: 0.6rem;
  color: var(--blindspot-text-muted);
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.blindspot-battle__hand-rail .blindspot-num {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  color: var(--blindspot-accent);
  font-weight: 600;
}
.blindspot-battle__hand-rail-combo {
  margin-left: auto;
  color: var(--blindspot-accent);
}
.blindspot-battle__hand {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.7rem;
}
@media (max-width: 1100px) {
  .blindspot-battle__hand { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .blindspot-battle__hand { grid-template-columns: 1fr; }
}

/* ---------- MOVE CARD ---------- */
.blindspot-move-card {
  background: linear-gradient(180deg, var(--blindspot-surface), var(--blindspot-bg-2));
  border: 1px solid var(--blindspot-border-2);
  border-radius: var(--blindspot-radius-card);
  padding: 0.75rem;
  text-align: left;
  color: var(--blindspot-text);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  position: relative;
  transition: transform 200ms cubic-bezier(0.2, 0.8, 0.2, 1),
              border-color 200ms,
              box-shadow 200ms;
  overflow: hidden;
  font-family: var(--blindspot-font-body);
}
.blindspot-move-card:hover {
  transform: translateY(-6px);
  border-color: var(--blindspot-accent);
  box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.8),
              0 0 30px -8px rgba(200, 48, 44, 0.4);
}
.blindspot-move-card.is-disabled {
  opacity: 0.4;
  pointer-events: none;
}
.blindspot-move-card.is-selected {
  border-color: var(--blindspot-accent);
  box-shadow: 0 0 60px -10px var(--blindspot-accent);
}
.blindspot-move-card.is-combo {
  border-color: var(--blindspot-accent);
  animation: blindspot-glow 1.6s ease-in-out infinite;
}
@keyframes blindspot-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200, 48, 44, 0); }
  50%      { box-shadow: 0 0 28px 4px rgba(200, 48, 44, 0.55); }
}

/* Per-move accent (--mc) */
.blindspot-move-card[data-move="strike"]  { --mc: #ff7a3a; }
.blindspot-move-card[data-move="guard"]   { --mc: #6cc4ff; }
.blindspot-move-card[data-move="ability"] { --mc: #b47cf5; }
.blindspot-move-card[data-move="heal"]    { --mc: #6cffb0; }
.blindspot-move-card[data-move="counter"] { --mc: #ffd97a; }

.blindspot-move-card__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
}
.blindspot-move-card__type {
  font-family: var(--blindspot-font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mc);
}
.blindspot-move-card__name {
  font-family: var(--blindspot-font-display);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1.05;
  letter-spacing: 0.01em;
  margin-top: 0.15rem;
}
.blindspot-move-card__energy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  background: #000;
  border: 1px solid var(--blindspot-border-2);
  padding: 0.25rem 0.45rem;
  min-width: 40px;
  border-radius: 2px;
}
.blindspot-move-card__energy-num {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--blindspot-text);
  font-weight: 600;
}
.blindspot-move-card__energy-lbl {
  font-family: var(--blindspot-font-mono);
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blindspot-text-muted);
  margin-top: 2px;
}
.blindspot-move-card__art {
  aspect-ratio: 16 / 9;
  background-size: cover;
  background-position: center;
  border-radius: var(--blindspot-radius-tile);
  position: relative;
  border: 1px solid var(--blindspot-border);
}
.blindspot-move-card__art-veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 60%, rgba(0, 0, 0, 0.5));
  border-radius: inherit;
}
.blindspot-move-card__tags {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}
.blindspot-move-card__tag {
  font-family: var(--blindspot-font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.22em 0.55em;
  background: var(--blindspot-surface-2);
  border: 1px solid var(--blindspot-border-2);
  color: var(--blindspot-text-muted);
  border-radius: 999px;
}
.blindspot-move-card__tag--hl {
  background: var(--mc);
  color: #0E0A06;
  border-color: var(--mc);
}
.blindspot-move-card__num {
  font-family: var(--blindspot-font-mono);
  font-size: 0.72rem;
  color: var(--mc);
  letter-spacing: 0.08em;
}
.blindspot-move-card__desc {
  font-size: 0.85rem;
  color: var(--blindspot-text-dim);
  line-height: 1.4;
  font-style: italic;
}
.blindspot-move-card__foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto;
  padding-top: 0.4rem;
  border-top: 1px solid var(--blindspot-border);
  font-family: var(--blindspot-font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blindspot-text-muted);
}
.blindspot-move-card__charge {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-epic);
  font-size: 0.7rem;
  letter-spacing: 0.05em;
}
.blindspot-move-card__combo {
  position: absolute;
  top: 8px;
  right: 8px;
  background: var(--blindspot-accent);
  color: #FFF6E8;
  font-family: var(--blindspot-font-mono);
  font-size: 0.55rem;
  padding: 0.25em 0.55em;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-radius: 999px;
  font-weight: 700;
}

/* ============================================================
   SCOPE-RESTYLE — legacy arena-* / bs-move-card markup
   `bs-arena-battle-ui.js` writes into the legacy arena-* DOM. Rather
   than replacing it (which broke gameplay), we recolor the legacy
   styles in place within #bs-screen-battle.blindspot-battle scope.
   Selectors are at least 0,1,2,0 to beat `.bs-page .arena-*` (0,0,2,0).
   ============================================================ */

/* HP bar — recolor from amber to red gradient */
#bs-screen-battle.blindspot-battle .arena-hp-bar__track , #bs-battle-container.blindspot-battle .arena-hp-bar__track  {
  background: var(--blindspot-bg-2);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-pill);
}
#bs-screen-battle.blindspot-battle .arena-hp-bar__fill , #bs-battle-container.blindspot-battle .arena-hp-bar__fill  {
  border-radius: inherit;
  transition: width 0.4s ease;
}
/* Phase 1 unification: HP fill is the SAME red on both player and
   opponent so the bar reads as "HP" regardless of side, matching the
   heart pill color (#ef4444). The legacy --player / --opponent
   modifiers are neutralised; only --low (critical state) retains a
   distinct treatment for high-contrast feedback. */
#bs-screen-battle.blindspot-battle .arena-hp-bar__fill--player,
#bs-screen-battle.blindspot-battle .arena-hp-bar__fill--opponent,
#bs-battle-container.blindspot-battle .arena-hp-bar__fill--player,
#bs-battle-container.blindspot-battle .arena-hp-bar__fill--opponent {
  background: linear-gradient(180deg, #ef4444 0%, #b91c1c 100%);
}
#bs-screen-battle.blindspot-battle .arena-hp-bar__fill--low , #bs-battle-container.blindspot-battle .arena-hp-bar__fill--low  {
  background: linear-gradient(180deg, #fb923c 0%, #b91c1c 100%);
  box-shadow: 0 0 12px rgba(251, 146, 60, 0.55);
}
#bs-screen-battle.blindspot-battle .arena-hp-bar__text, #bs-battle-container.blindspot-battle .arena-hp-bar__text,
#bs-screen-battle.blindspot-battle .arena-hp-text , #bs-battle-container.blindspot-battle .arena-hp-text  {
  font-family: var(--blindspot-font-numeric);
  color: var(--blindspot-text);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
}

/* Stamina bar — render as 6 pips per the design (one per stamina
   point). The legacy markup is a single continuous bar, so we fake
   the pip look with vertical dividers via a ::after overlay.
   Assumes default stamMax of 6; non-default cards will look slightly
   off but the visual intent reads correctly. */
#bs-screen-battle.blindspot-battle .arena-stamina-bar , #bs-battle-container.blindspot-battle .arena-stamina-bar  {
  width: 100%;
  height: 10px;
  background: var(--blindspot-bg-2);
  border: 1px solid var(--blindspot-border);
  border-radius: 2px;
  overflow: hidden;
  margin: 0;
  padding: 0;
  position: relative;
}
#bs-screen-battle.blindspot-battle .arena-stamina-bar__fill , #bs-battle-container.blindspot-battle .arena-stamina-bar__fill  {
  height: 100%;
  background: linear-gradient(180deg, var(--blindspot-accent-gold), var(--blindspot-accent-gold-dim));
  border-radius: 0;
  box-shadow: 0 0 4px rgba(245, 192, 120, 0.3);
  transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
#bs-screen-battle.blindspot-battle .arena-stamina-bar::after , #bs-battle-container.blindspot-battle .arena-stamina-bar::after  {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0,
    transparent calc(100% / 6 - 1.5px),
    var(--blindspot-bg) calc(100% / 6 - 1.5px),
    var(--blindspot-bg) calc(100% / 6 + 0.5px)
  );
  pointer-events: none;
  z-index: 2;
}
#bs-screen-battle.blindspot-battle .arena-stamina-bar--exhausted .arena-stamina-bar__fill , #bs-battle-container.blindspot-battle .arena-stamina-bar--exhausted .arena-stamina-bar__fill  {
  background: linear-gradient(180deg, var(--blindspot-accent-dim), #6e3a1a);
}
#bs-screen-battle.blindspot-battle .arena-stamina-bar__text , #bs-battle-container.blindspot-battle .arena-stamina-bar__text  {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-text-muted);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-align: right;
  display: block;
  margin-top: 0.15rem;
  position: static;
  inset: auto;
}

/* Hype bar — recolor to epic purple. Track is bumped to 10px and given
   a lighter surface tone + inner shadow so the empty bar reads at 0%
   against the obsidian bg (was 6px on a near-black track that
   disappeared into the page). Label color bumped from --blindspot-epic
   (#8E5DAB, too washed out against the dark surface) to a brighter
   purple with bolder weight + a tighter glow for readability. */
#bs-screen-battle.blindspot-battle .arena-hype-bar , #bs-battle-container.blindspot-battle .arena-hype-bar  {
  background: rgba(0, 0, 0, 0.85);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-tile);
  /* Phase 2: ambient purple glow so the meter reads as the dynamic
     element in the center column. Inside-out lift, low alpha so it
     doesn't compete with the ::after fill shadow when filling. */
  box-shadow: 0 0 14px rgba(216, 169, 255, 0.22);
  padding: 0.45rem 0.6rem;
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__label , #bs-battle-container.blindspot-battle .arena-hype-bar__label  {
  font-family: var(--blindspot-font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #C9A3E8;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  /* Dark drop shadow first (legibility on light arena bgs) +
     purple glow (mood / brand) layered on top. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95),
               0 0 8px rgba(201, 163, 232, 0.5),
               0 0 2px rgba(201, 163, 232, 0.8);
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__label i , #bs-battle-container.blindspot-battle .arena-hype-bar__label i  {
  line-height: 1;
  margin: 0;
  color: #D8A9FF;
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__track , #bs-battle-container.blindspot-battle .arena-hype-bar__track  {
  /* `flex: 0 0 14px` overrides the legacy `flex: 1` from the .bs-page
     hype-bar__track rule that was making the track collapse to 2px
     because the parent bar's flex-column layout gave it almost no
     leftover vertical space. Locks the track to 14px regardless of
     parent flex behaviour. */
  flex: 0 0 14px;
  height: 14px;
  background: var(--blindspot-surface-2, #251512);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  border-radius: var(--blindspot-radius-pill);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5),
              inset 0 0 8px rgba(0, 0, 0, 0.4);
  margin-top: 0.3rem;
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__fill , #bs-battle-container.blindspot-battle .arena-hype-bar__fill  {
  background: linear-gradient(90deg, var(--blindspot-epic), #D8A9FF);
  box-shadow: 0 0 12px rgba(216, 169, 255, 0.55),
              inset 0 1px 1px rgba(255, 255, 255, 0.18);
  border-radius: inherit;
  height: 100%;
}
/* Hint caption ("CRIT BOOST AT 100% • 100% TO GO") — was unstyled in
   the arena scope. White text with a dark drop shadow so it stays
   legible on top of the dark Hype bar bg AND on lighter arena
   backgrounds (was muted text-muted color which got lost behind the
   purple HYPE label). */
#bs-screen-battle.blindspot-battle .arena-hype-bar__hint,
#bs-battle-container.blindspot-battle .arena-hype-bar__hint {
  font-family: var(--blindspot-font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #ffffff;
  margin-top: 0.35rem;
  text-align: center;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
}

/* Stance buttons — red active state. Default state was reading as
   "disabled" (text-muted is very dim); bumped to text-dim + explicit
   opacity so unselected stances feel selectable. */
#bs-screen-battle.blindspot-battle .arena-stance-btn , #bs-battle-container.blindspot-battle .arena-stance-btn  {
  background: var(--blindspot-surface);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-tile);
  color: var(--blindspot-text-dim);
  opacity: 0.85;
  transition: opacity var(--blindspot-transition-fast),
              color var(--blindspot-transition-fast),
              border-color var(--blindspot-transition-fast),
              background var(--blindspot-transition-fast);
}
#bs-screen-battle.blindspot-battle .arena-stance-btn:hover , #bs-battle-container.blindspot-battle .arena-stance-btn:hover  {
  border-color: var(--blindspot-accent-dim);
  color: var(--blindspot-text);
  opacity: 1;
}
#bs-screen-battle.blindspot-battle .arena-stance-btn--active , #bs-battle-container.blindspot-battle .arena-stance-btn--active  {
  opacity: 1;
}
#bs-screen-battle.blindspot-battle .arena-stance-btn--active , #bs-battle-container.blindspot-battle .arena-stance-btn--active  {
  border-color: var(--blindspot-accent);
  color: var(--blindspot-accent);
  background: rgba(200, 48, 44, 0.1);
}
#bs-screen-battle.blindspot-battle .arena-stance-btn[data-stance="balanced"].arena-stance-btn--active , #bs-battle-container.blindspot-battle .arena-stance-btn[data-stance="balanced"].arena-stance-btn--active  {
  border-color: var(--blindspot-accent-gold);
  color: var(--blindspot-accent-gold);
  background: rgba(245, 192, 120, 0.1);
}
#bs-screen-battle.blindspot-battle .arena-stance-btn[data-stance="aggressive"].arena-stance-btn--active , #bs-battle-container.blindspot-battle .arena-stance-btn[data-stance="aggressive"].arena-stance-btn--active  {
  border-color: var(--blindspot-accent);
  color: var(--blindspot-accent);
}
#bs-screen-battle.blindspot-battle .arena-stance-btn[data-stance="defensive"].arena-stance-btn--active , #bs-battle-container.blindspot-battle .arena-stance-btn[data-stance="defensive"].arena-stance-btn--active  {
  border-color: var(--blindspot-info);
  color: var(--blindspot-info);
  background: rgba(102, 136, 170, 0.1);
}

/* Move cards (legacy bs-move-card) — Vein restyle */
#bs-screen-battle.blindspot-battle .arena-move-btn, #bs-battle-container.blindspot-battle .arena-move-btn,
#bs-screen-battle.blindspot-battle .bs-move-card , #bs-battle-container.blindspot-battle .bs-move-card  {
  background: linear-gradient(180deg, var(--blindspot-surface), var(--blindspot-bg-2));
  border: 1px solid var(--blindspot-border-2);
  border-radius: var(--blindspot-radius-card);
  color: var(--blindspot-text);
  transition: transform 200ms cubic-bezier(0.2, 0.8, 0.2, 1),
              border-color 200ms,
              box-shadow 200ms;
}
#bs-screen-battle.blindspot-battle .arena-move-btn:hover, #bs-battle-container.blindspot-battle .arena-move-btn:hover,
#bs-screen-battle.blindspot-battle .bs-move-card:hover , #bs-battle-container.blindspot-battle .bs-move-card:hover  {
  transform: translateY(-4px);
  border-color: var(--blindspot-accent);
  box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.8),
              0 0 30px -8px rgba(200, 48, 44, 0.4);
}
#bs-screen-battle.blindspot-battle .bs-move-card__type-label , #bs-battle-container.blindspot-battle .bs-move-card__type-label  {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-accent);
  letter-spacing: 0.18em;
}
#bs-screen-battle.blindspot-battle .bs-move-card__name , #bs-battle-container.blindspot-battle .bs-move-card__name  {
  font-family: var(--blindspot-font-display);
  font-weight: 600;
  letter-spacing: 0.01em;
}
#bs-screen-battle.blindspot-battle .bs-move-card__energy , #bs-battle-container.blindspot-battle .bs-move-card__energy  {
  background: #000;
  border: 1px solid var(--blindspot-border-2);
  border-radius: 2px;
}
#bs-screen-battle.blindspot-battle .bs-move-card__energy-num , #bs-battle-container.blindspot-battle .bs-move-card__energy-num  {
  font-family: var(--blindspot-font-numeric);
  color: var(--blindspot-text);
  font-weight: 600;
}
#bs-screen-battle.blindspot-battle .bs-move-card__energy-label , #bs-battle-container.blindspot-battle .bs-move-card__energy-label  {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-text-muted);
  letter-spacing: 0.16em;
}
#bs-screen-battle.blindspot-battle .bs-move-card__tag , #bs-battle-container.blindspot-battle .bs-move-card__tag  {
  font-family: var(--blindspot-font-mono);
  background: var(--blindspot-surface-2);
  border: 1px solid var(--blindspot-border-2);
  color: var(--blindspot-text-muted);
  border-radius: 999px;
}
#bs-screen-battle.blindspot-battle .bs-move-card__tag--active , #bs-battle-container.blindspot-battle .bs-move-card__tag--active  {
  background: var(--blindspot-accent);
  color: #FFF6E8;
  border-color: var(--blindspot-accent);
}
#bs-screen-battle.blindspot-battle .bs-move-card__desc , #bs-battle-container.blindspot-battle .bs-move-card__desc  {
  font-family: var(--blindspot-font-body);
  font-style: italic;
  color: var(--blindspot-text-dim);
}
#bs-screen-battle.blindspot-battle .bs-move-card__footer , #bs-battle-container.blindspot-battle .bs-move-card__footer  {
  border-top: 1px solid var(--blindspot-border);
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-text-muted);
}
#bs-screen-battle.blindspot-battle .bs-move-card__badge , #bs-battle-container.blindspot-battle .bs-move-card__badge  {
  color: var(--blindspot-text-muted);
}
#bs-screen-battle.blindspot-battle .bs-move-card__dot , #bs-battle-container.blindspot-battle .bs-move-card__dot  {
  background: var(--blindspot-border-2);
}
#bs-screen-battle.blindspot-battle .bs-move-card__dot--active , #bs-battle-container.blindspot-battle .bs-move-card__dot--active  {
  background: var(--blindspot-accent);
}
#bs-screen-battle.blindspot-battle .arena-move-btn__charge , #bs-battle-container.blindspot-battle .arena-move-btn__charge  {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-epic);
}
/* Hard-block state — Ability when player can't afford its cost. The
   only move that's truly disabled, so it's the only one that should
   ghost. */
#bs-screen-battle.blindspot-battle .arena-move-btn--no-stamina,
#bs-battle-container.blindspot-battle .arena-move-btn--no-stamina {
  opacity: 0.45;
}
#bs-screen-battle.blindspot-battle .arena-move-btn--no-stamina .arena-move-btn__cost,
#bs-battle-container.blindspot-battle .arena-move-btn--no-stamina .arena-move-btn__cost {
  color: var(--blindspot-danger);
}

/* Exhaustion warning — applies to ALL buttons when stamina < 5, but
   the moves themselves stay usable (Strike / Guard / Heal / Counter
   never hard-block; only Ability does). Was sharing the ghost opacity
   with --no-stamina, which made it look like the whole move-grid was
   disabled. Now: keep buttons full opacity, signal the warning via a
   red-tinted cost badge and a subtle danger-red bottom border. The
   stamina bar's own --exhausted pulse carries the loud part of the
   warning. */
#bs-screen-battle.blindspot-battle .arena-move-btn--exhausted,
#bs-battle-container.blindspot-battle .arena-move-btn--exhausted {
  opacity: 1;
  border-bottom: 2px solid var(--blindspot-danger);
}
#bs-screen-battle.blindspot-battle .arena-move-btn--exhausted .arena-move-btn__cost,
#bs-battle-container.blindspot-battle .arena-move-btn--exhausted .arena-move-btn__cost {
  color: var(--blindspot-danger);
  text-shadow: 0 0 6px rgba(200, 48, 44, 0.5);
}

/* Battle header (round + intent + forfeit bar) — round and intent
   group tight on the left, action buttons pushed to the right. */
#bs-screen-battle.blindspot-battle .arena-battle__header , #bs-battle-container.blindspot-battle .arena-battle__header  {
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--blindspot-border);
  border-radius: var(--blindspot-radius-tile);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.6rem;
  padding: 0.4rem 0.85rem;
}
/* First action button picks up margin-left: auto to flush the right group. */
#bs-screen-battle.blindspot-battle .arena-battle__header #bs-combat-help-btn, #bs-battle-container.blindspot-battle .arena-battle__header #bs-combat-help-btn,
#bs-screen-battle.blindspot-battle .arena-battle__header #arena-forfeit-btn , #bs-battle-container.blindspot-battle .arena-battle__header #arena-forfeit-btn  {
  margin-left: 0;
}
#bs-screen-battle.blindspot-battle .arena-battle__header #bs-combat-help-btn , #bs-battle-container.blindspot-battle .arena-battle__header #bs-combat-help-btn  {
  margin-left: auto;
}

/* Square icon-only header buttons (Help + Forfeit) — bundle-style. */
#bs-screen-battle.blindspot-battle .arena-battle__header .arena-btn , #bs-battle-container.blindspot-battle .arena-battle__header .arena-btn  {
  width: 36px;
  height: 36px;
  min-width: 36px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  gap: 0;
}
#bs-screen-battle.blindspot-battle .arena-battle__header .arena-btn i , #bs-battle-container.blindspot-battle .arena-battle__header .arena-btn i  {
  font-size: 0.9rem;
}
#bs-screen-battle.blindspot-battle .arena-battle__round , #bs-battle-container.blindspot-battle .arena-battle__round  {
  font-family: var(--blindspot-font-display);
  color: var(--blindspot-accent);
  font-weight: 600;
}
#bs-screen-battle.blindspot-battle .arena-battle__vs-text , #bs-battle-container.blindspot-battle .arena-battle__vs-text  {
  font-family: var(--blindspot-font-display);
  font-style: italic;
  color: var(--blindspot-accent);
  text-shadow: 0 0 24px rgba(200, 48, 44, 0.4);
}

/* Combatant frame and nameplate */
#bs-screen-battle.blindspot-battle .arena-combatant , #bs-battle-container.blindspot-battle .arena-combatant  {
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--blindspot-border-2);
  border-radius: var(--blindspot-radius-card);
  backdrop-filter: blur(6px);
}
/* Panels both use a dynamic accent that tracks HP — green at high
   health, gold at mid, red at low. JS (updateHpBars) toggles the
   --hp-high / --hp-mid / --hp-low class on each panel; rules below
   set border + glow per state with a smooth transition. The default
   (no class) renders red so an unstarted battle still reads as
   "danger" before the first HP write. */
#bs-screen-battle.blindspot-battle .arena-combatant--player , #bs-battle-container.blindspot-battle .arena-combatant--player  {
  border-left: 2px solid var(--blindspot-accent);
  box-shadow: inset 4px 0 16px -10px rgba(200, 48, 44, 0.45);
  transition: border-color 600ms ease, box-shadow 600ms ease;
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent , #bs-battle-container.blindspot-battle .arena-combatant--opponent  {
  border-right: 2px solid var(--blindspot-accent);
  box-shadow: inset -4px 0 16px -10px rgba(200, 48, 44, 0.45);
  transition: border-color 600ms ease, box-shadow 600ms ease;
}

/* HP tier 1 — high (≥66%): green */
#bs-screen-battle.blindspot-battle .arena-combatant--player.arena-combatant--hp-high,
#bs-battle-container.blindspot-battle .arena-combatant--player.arena-combatant--hp-high {
  border-left-color: #6E9F4A;
  box-shadow: inset 4px 0 16px -10px rgba(110, 159, 74, 0.5);
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent.arena-combatant--hp-high,
#bs-battle-container.blindspot-battle .arena-combatant--opponent.arena-combatant--hp-high {
  border-right-color: #6E9F4A;
  box-shadow: inset -4px 0 16px -10px rgba(110, 159, 74, 0.5);
}

/* HP tier 2 — mid (33–65%): gold */
#bs-screen-battle.blindspot-battle .arena-combatant--player.arena-combatant--hp-mid,
#bs-battle-container.blindspot-battle .arena-combatant--player.arena-combatant--hp-mid {
  border-left-color: var(--blindspot-accent-gold, #F5C078);
  box-shadow: inset 4px 0 16px -10px rgba(245, 192, 120, 0.5);
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent.arena-combatant--hp-mid,
#bs-battle-container.blindspot-battle .arena-combatant--opponent.arena-combatant--hp-mid {
  border-right-color: var(--blindspot-accent-gold, #F5C078);
  box-shadow: inset -4px 0 16px -10px rgba(245, 192, 120, 0.5);
}

/* HP tier 3 — low (<33%): red, slightly stronger glow for urgency */
#bs-screen-battle.blindspot-battle .arena-combatant--player.arena-combatant--hp-low,
#bs-battle-container.blindspot-battle .arena-combatant--player.arena-combatant--hp-low {
  border-left-color: #ef4444;
  box-shadow: inset 4px 0 18px -8px rgba(239, 68, 68, 0.65);
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent.arena-combatant--hp-low,
#bs-battle-container.blindspot-battle .arena-combatant--opponent.arena-combatant--hp-low {
  border-right-color: #ef4444;
  box-shadow: inset -4px 0 18px -8px rgba(239, 68, 68, 0.65);
}

/* Stance colors the rendered card's own border (NOT the panel — the
   panel border is the HP indicator). Card chrome reflects current
   stance: gold = balanced, red = aggressive, blue = defensive. The
   stance class lives on the panel; descendant selector picks up the
   .bs-rendered-card inside. Smooth transition for stance shifts. */
#bs-screen-battle.blindspot-battle .arena-combatant .bs-rendered-card,
#bs-battle-container.blindspot-battle .arena-combatant .bs-rendered-card {
  transition: border-color 600ms ease, box-shadow 600ms ease;
}
#bs-screen-battle.blindspot-battle .arena-combatant--stance-balanced .bs-rendered-card,
#bs-battle-container.blindspot-battle .arena-combatant--stance-balanced .bs-rendered-card {
  border-color: var(--blindspot-accent-gold, #F5C078);
  box-shadow: 0 0 12px -2px rgba(245, 192, 120, 0.35);
}
#bs-screen-battle.blindspot-battle .arena-combatant--stance-aggressive .bs-rendered-card,
#bs-battle-container.blindspot-battle .arena-combatant--stance-aggressive .bs-rendered-card {
  border-color: var(--blindspot-accent, #C8302C);
  box-shadow: 0 0 12px -2px rgba(200, 48, 44, 0.4);
}
#bs-screen-battle.blindspot-battle .arena-combatant--stance-defensive .bs-rendered-card,
#bs-battle-container.blindspot-battle .arena-combatant--stance-defensive .bs-rendered-card {
  border-color: var(--blindspot-info, #6688AA);
  box-shadow: 0 0 12px -2px rgba(102, 136, 170, 0.4);
}

/* Boss stance indicator — small chip in the bottom zone above the
   player stance buttons. Color tracks the boss's current stance so
   the player always sees what posture they're up against. */
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--blindspot-font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.3rem 0.7rem;
  border-radius: var(--blindspot-radius-pill, 999px);
  background: rgba(13, 8, 7, 0.7);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  color: var(--blindspot-text-dim, #B89A82);
  align-self: center;
  transition: border-color 600ms ease, color 600ms ease, box-shadow 600ms ease;
  margin-bottom: 0.3rem;
}
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator__lbl,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator__lbl {
  opacity: 0.7;
  font-weight: 600;
}
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator__icon,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator__icon {
  font-size: 0.85rem;
  line-height: 1;
}
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator__name,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator__name {
  font-weight: 700;
}
/* Stance variants — gold balanced, red aggressive, blue defensive */
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator--balanced,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator--balanced {
  border-color: var(--blindspot-accent-gold, #F5C078);
  color: var(--blindspot-accent-gold, #F5C078);
  box-shadow: 0 0 10px -2px rgba(245, 192, 120, 0.3);
}
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator--aggressive,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator--aggressive {
  border-color: var(--blindspot-accent, #C8302C);
  color: var(--blindspot-accent, #C8302C);
  box-shadow: 0 0 10px -2px rgba(200, 48, 44, 0.4);
}
#bs-screen-battle.blindspot-battle .bs-boss-stance-indicator--defensive,
#bs-battle-container.blindspot-battle .bs-boss-stance-indicator--defensive {
  border-color: var(--blindspot-info, #6688AA);
  color: var(--blindspot-info, #6688AA);
  box-shadow: 0 0 10px -2px rgba(102, 136, 170, 0.4);
}
#bs-screen-battle.blindspot-battle .arena-combatant__name , #bs-battle-container.blindspot-battle .arena-combatant__name  {
  font-family: var(--blindspot-font-display);
  font-weight: 600;
  color: var(--blindspot-text);
}
#bs-screen-battle.blindspot-battle .arena-element-badge , #bs-battle-container.blindspot-battle .arena-element-badge  {
  font-family: var(--blindspot-font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blindspot-text-dim);
}

/* (Boss intent banner styling consolidated below into the
    `.arena-battle__header .arena-boss-intent` rule — single source of truth.) */

/* Battle log */
#bs-screen-battle.blindspot-battle .arena-battle__log , #bs-battle-container.blindspot-battle .arena-battle__log  {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--blindspot-border);
  border-radius: 2px;
  backdrop-filter: blur(8px);
  font-family: var(--blindspot-font-body);
  /* Extra bottom padding so the last log entry has breathing room
     above the log's bottom border. */
  padding: 0.45rem 0.85rem 1rem;
  /* flex: 1 so the log grows to fill any leftover vertical inside
     the .arena-battle flex column (stage + moves at content height,
     log absorbs the rest) — without pushing past the viewport
     because the parent caps at calc(100vh - 69px). min-height keeps
     a sensible floor when there's not much room.
     `height: auto; max-height: none` explicitly override the legacy
     `.bs-page .arena-battle__log { height: 56px; max-height: 56px }`
     rule in blindspot.css:3048 (desktop @media block) which would
     otherwise lock the log at 56px regardless of flex-grow. */
  flex: 1;
  height: auto;
  min-height: 80px;
  max-height: none;
  overflow-y: auto;
  margin: 0;
  /* Hide scrollbars cross-browser. Firefox uses scrollbar-width,
     WebKit uses ::-webkit-scrollbar. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
#bs-screen-battle.blindspot-battle .arena-battle__log::-webkit-scrollbar,
#bs-battle-container.blindspot-battle .arena-battle__log::-webkit-scrollbar {
  display: none;
}
#bs-screen-battle.blindspot-battle .arena-log-entry , #bs-battle-container.blindspot-battle .arena-log-entry  {
  color: var(--blindspot-text-dim);
  font-size: 0.9rem;
}

/* ---------- LAYOUT RESTRUCTURE ----------
   Force the field into a real 3-col stage (you / center / them),
   each combatant into a column with nameplate above portrait, and
   the move grid into a 5-card hand below. */

#bs-screen-battle.blindspot-battle .arena-battle , #bs-battle-container.blindspot-battle .arena-battle  {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0 2rem 0;
  background: transparent;
  border: 0;
  max-width: 1480px;
  margin: 0 auto;
  width: 100%;
  position: relative;
  /* Fill the screen so the log can use margin-top: auto to anchor to the
     bottom edge instead of floating mid-screen. Matches the screen wrapper's
     min-height so the flex column actually has space to distribute. */
  min-height: calc(100vh - 69px);
}
/* Override for #bs-battle-container — index.html has no topbar above
   the battle, so reclaim the 69px the play.html rule subtracts for
   its topbar. Without this the column stops short and a 69px gap
   appears below the battle log on the onboarding flow. */
#bs-battle-container.blindspot-battle .arena-battle {
  min-height: 100vh;
}

/* ---------- UTILITY CLUSTER — INLINE BELOW STANCES ----------
   Help / Forfeit / post-battle (Again, Back) used to sit in a tall
   header above the field, then briefly floated in the top-right
   corner — both layouts had alignment issues and the corner cluster
   wasted dead space. They now live inline below the stance row
   inside the VS center column, in the previously-empty slot. JS
   still targets every button by id (#bs-combat-help-btn,
   #arena-forfeit-btn, #arena-battle-post, etc.) so the move is
   DOM-safe. Buttons forced to a uniform 36×36 to fix the regression
   where the third icon rendered larger than its siblings. */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  margin-top: 0.4rem;
  flex-wrap: wrap;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn {
  width: 36px;
  height: 36px;
  min-width: 36px;
  padding: 0;
  margin: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  gap: 0;
  border-radius: var(--blindspot-radius-button, 2px);
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn i,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn i {
  font-size: 0.9rem;
  line-height: 1;
  transition: transform var(--blindspot-transition-fast),
              color var(--blindspot-transition-fast);
}
/* Hover treatment — these buttons read as flat icons by default. Gold
   shift + soft glow + 1.05x icon scale signals they're interactive. */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn:hover,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn:hover {
  color: var(--blindspot-accent-gold, #F5C078);
  border-color: var(--blindspot-accent-gold-dim, #B97417);
  box-shadow: 0 0 12px rgba(245, 192, 120, 0.3);
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn:hover i,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn:hover i {
  transform: scale(1.08);
  color: inherit;
}
/* Post-battle pair (Again, Back) needs to lay out as a compact inline
   group when its parent span is shown. Default of the surrounding
   <span> is inline so flex-gap takes care of spacing; just normalize
   the buttons inside. */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__post-actions,
#bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__post-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__post-actions .arena-btn,
#bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__post-actions .arena-btn {
  width: auto;
  min-width: 0;
  padding: 0 0.85em;
  gap: 0.4em;
}

/* Boss intent banner — inline in the VS center column between the
   VS glyph and the matchup chip. Predictable placement (was floating
   top-center of .arena-battle and overlapping the round pill). When
   empty (no boss intent active), the inline element collapses to
   nothing because its inner spans are empty. */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-boss-intent,
#bs-battle-container.blindspot-battle .blindspot-battle__center .arena-boss-intent {
  position: static;
  align-self: center;
  width: 100%;
  max-width: 280px;
  margin: 0;
  font-size: 0.78rem;
  text-align: center;
  white-space: normal;
  overflow: hidden;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-boss-intent:empty,
#bs-battle-container.blindspot-battle .blindspot-battle__center .arena-boss-intent:empty {
  display: none;
}

/* Boss flavor / opening line — sits inside the .bs-vs-zone--mid wrapper.
   Italic Cinzel, gold-tinted. Borders moved up to the mid-zone wrapper in
   Phase 2 so the entire "state of the fight" group reads as one unit. */
#bs-screen-battle.blindspot-battle .bs-vs-flavor,
#bs-battle-container.blindspot-battle .bs-vs-flavor {
  align-self: center;
  width: 100%;
  max-width: 280px;
  margin: 0;
  padding: 0.2rem 0.6rem;
  font-family: var(--blindspot-font-display, 'Cinzel', serif);
  font-style: italic;
  font-size: 0.82rem;
  line-height: 1.35;
  color: var(--bs-accent-glow, #f5c078);
  text-align: center;
  text-shadow: 0 0 8px rgba(245, 192, 120, 0.25);
}
#bs-screen-battle.blindspot-battle .bs-vs-flavor:empty,
#bs-battle-container.blindspot-battle .bs-vs-flavor:empty,
#bs-screen-battle.blindspot-battle .bs-vs-flavor[hidden],
#bs-battle-container.blindspot-battle .bs-vs-flavor[hidden] {
  display: none;
}

/* ---------- CENTER COLUMN — 3-ZONE HIERARCHY (Phase 2) ----------
   Children of .blindspot-battle__center wrap into 3 zones (top / mid /
   bottom). Parent's justify-content: space-between pushes them to the
   column edges; within each zone, items stack tight via gap: 0.4rem.
   The mid zone gets thin gold dividers above + below so the "state of
   the fight" cluster (intent, matchup, flavor, Hype) reads as a unit. */
#bs-screen-battle.blindspot-battle .bs-vs-zone,
#bs-battle-container.blindspot-battle .bs-vs-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
}
#bs-screen-battle.blindspot-battle .bs-vs-zone--mid,
#bs-battle-container.blindspot-battle .bs-vs-zone--mid {
  padding: 0.5rem 0;
  border-top: 1px solid rgba(245, 192, 120, 0.18);
  border-bottom: 1px solid rgba(245, 192, 120, 0.18);
}
/* Collapse the mid-zone divider treatment when every child inside it is
   empty/hidden (e.g. before any boss data resolves) so the dividers don't
   render as a floating pair of lines. */
#bs-screen-battle.blindspot-battle .bs-vs-zone--mid:not(:has(:not([hidden]):not(:empty))),
#bs-battle-container.blindspot-battle .bs-vs-zone--mid:not(:has(:not([hidden]):not(:empty))) {
  border-top: 0;
  border-bottom: 0;
  padding: 0;
}

@media (max-width: 600px) {
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils {
    gap: 0.3rem;
  }
  #bs-screen-battle.blindspot-battle .arena-battle > .arena-boss-intent,
  #bs-battle-container.blindspot-battle .arena-battle > .arena-boss-intent {
    max-width: calc(100% - 32px);
    font-size: 0.78rem;
  }
}
/* Stage hosts the arena background-image (set by ArenaBackgrounds JS as
   `arena-stage--<id>` per blindspot.css:1747-1752). The Vein theme used
   to suppress this entirely because the legacy overlay let amber bleed
   through the field; instead, we now keep the image and apply a
   stronger top-to-bottom darkening overlay so combatant portraits +
   HUD stay legible against any arena. */
#bs-screen-battle.blindspot-battle .arena-battle__stage , #bs-battle-container.blindspot-battle .arena-battle__stage  {
  background-color: var(--blindspot-bg);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  padding: 0;
  border: 0;
  box-shadow: none;
  outline: 0;
  position: relative;
  /* Top corners squared (stage meets the topbar cleanly); bottom
     corners sharpened to 2px for a chiseled silhouette. The bg image
     clips to this shape automatically; the ::before scrim inherits
     via `border-radius: inherit` already set on it. */
  border-radius: 0 0 2px 2px;
  /* Legacy `.bs-page .arena-battle__stage { max-height: 420px }` was
     capping the stage box even when the field columns grew taller
     (frame 270 + nameplate + HP + stamina + items + buffs + status =
     ~490px). Visible-overflow content spilled past the cap and
     overlapped the battle log that sits in flow below the stage.
     Unset the cap so the stage grows with column content. */
  max-height: none;
  overflow: visible;
  flex: 0 0 auto;
}
#bs-screen-battle.blindspot-battle .arena-battle__stage::before , #bs-battle-container.blindspot-battle .arena-battle__stage::before  {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  border-radius: inherit;
  background: linear-gradient(180deg,
    rgba(10, 8, 6, 0.72) 0%,
    rgba(10, 8, 6, 0.55) 45%,
    rgba(10, 8, 6, 0.88) 100%);
}
#bs-screen-battle.blindspot-battle .arena-battle__stage::after , #bs-battle-container.blindspot-battle .arena-battle__stage::after  { content: none; }
#bs-screen-battle.blindspot-battle .arena-battle__field , #bs-battle-container.blindspot-battle .arena-battle__field  { position: relative; z-index: 1; }
#bs-screen-battle.blindspot-battle .arena-battle__field , #bs-battle-container.blindspot-battle .arena-battle__field  {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(220px, 300px) minmax(320px, 1fr);
  gap: 0.75rem;
  align-items: stretch;
  padding: 0;
  background: transparent;
  max-width: 1320px;
  /* Field bottom margin trimmed to 0 — action buttons sit tight
     below the cards row. Top stays 25 for topbar headroom. */
  margin: 25px auto 0;
  width: 100%;
}
@media (max-width: 1100px) {
  #bs-screen-battle.blindspot-battle .arena-battle__field {
    grid-template-columns: 1fr 1fr;
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center {
    grid-column: 1 / -1;
    order: -1;
  }
}

/* Combatant column — flex column with nameplate first (per design),
   then a portrait-shaped frame, then HP / stamina pips / buffs.
   Vertical budget bumped from min(60vh, 460px) → min(78vh, 620px)
   to fit the new 300px card frame + full HUD stack (HP, stamina,
   items, buffs, status). The previous cap was set when the floating
   header didn't exist; we've since freed ~80px above the field so
   columns can grow taller without pushing the move grid off-screen.
   `overflow: hidden` removed — was clipping the stamina + items rows
   off the bottom of the column when the frame grew. */
#bs-screen-battle.blindspot-battle .arena-combatant , #bs-battle-container.blindspot-battle .arena-combatant  {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.3rem 0.45rem;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(6px);
  border-radius: var(--blindspot-radius-card);
  position: relative;
  overflow: visible;
  min-width: 0;
  max-width: none;
  width: 100%;
  margin: 0;
  max-height: min(82vh, 560px);
}

/* ---------- VERTICAL HP / STAMINA RAILS ----------
   Move HP and stamina out of the column flow into vertical rails
   anchored to the LEFT and RIGHT edges of the portrait frame. This
   reclaims ~70-100px of vertical real estate previously eaten by the
   horizontal HP bar + stamina bar + meta rows, so the card frame
   itself can grow much taller (340px+ on 1080p+). The bars use the
   inline height set by JS (we now write both width and height in
   updateHpBars / updateStaminaBars) and the legacy width is
   neutralized via !important. */
#bs-screen-battle.blindspot-battle .arena-combatant__frame,
#bs-battle-container.blindspot-battle .arena-combatant__frame {
  padding: 0.25rem 32px !important;
}

#bs-screen-battle.blindspot-battle .arena-hp-bar,
#bs-battle-container.blindspot-battle .arena-hp-bar,
#bs-screen-battle.blindspot-battle .arena-stamina-bar,
#bs-battle-container.blindspot-battle .arena-stamina-bar {
  position: absolute;
  /* Anchored to the card frame. Reserve 32px above for the heart/bolt
     glyph + breathing room, and 32px below for the readout pill. */
  top: 50%;
  bottom: auto;
  width: 12px;
  height: calc(100% - 64px);
  transform: translateY(-50%);
  /* Squared-frame look matching the stamina pip rail — thin radius,
     dark padded inner area, soft inner shadow. */
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.5);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
  padding: 2px;
  z-index: 4;
  display: flex;
  align-items: flex-end;
  /* overflow:visible so the heart/bolt glyph pseudo-element above
     the bar doesn't get clipped. Fill + pip elements clip themselves
     via their own positioning. */
  overflow: visible;
  margin: 0;
}

/* HP track wrapper — fills the padded inner frame area. Acts as the
   clip context for the single thermometer fill so the fill doesn't
   bleed past the rounded corners. */
#bs-screen-battle.blindspot-battle .arena-hp-bar__track,
#bs-battle-container.blindspot-battle .arena-hp-bar__track {
  position: relative;
  width: 100%;
  height: 100%;
  background: var(--blindspot-bg-2, #170D0B);
  border: 0;
  border-radius: 1px;
  overflow: hidden;
}
/* Stamina has no track wrapper — apply overflow clipping to the
   bar itself via a dedicated pseudo so the glyph stays exempt.
   We use a clipped inner via the fill + ::after pip overlay both
   border-radius:inherit which keeps them visually contained even
   without overflow:hidden on the parent. The pip overlay's
   gradient terminates at the bar's box edges naturally. */
/* Mirror the rails so HP faces inward on both columns (toward the VS
   center) and stamina faces outward — fighting-game HUD convention.
   Rails sit 8px inset from the frame edges (was flush 0; CEO flagged
   too cramped). The frame side padding picks up extra breathing room
   for the card art past the rails. */
#bs-screen-battle.blindspot-battle .arena-combatant--player .arena-hp-bar,
#bs-battle-container.blindspot-battle .arena-combatant--player .arena-hp-bar {
  /* Player HP — inner (right edge of left column = toward VS) */
  right: 18px;
  left: auto;
}
#bs-screen-battle.blindspot-battle .arena-combatant--player .arena-stamina-bar,
#bs-battle-container.blindspot-battle .arena-combatant--player .arena-stamina-bar {
  /* Player stamina — outer (left edge of left column = far-left of screen) */
  left: 18px;
  right: auto;
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-hp-bar,
#bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-hp-bar {
  /* Opponent HP — inner (left edge of right column = toward VS) */
  left: 18px;
  right: auto;
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-stamina-bar,
#bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-stamina-bar {
  /* Opponent stamina — outer (right edge of right column = far-right of screen) */
  right: 18px;
  left: auto;
}

/* Override the legacy track wrapper styling so the fill can use the
   vertical mode cleanly. */
#bs-screen-battle.blindspot-battle .arena-hp-bar__track,
#bs-battle-container.blindspot-battle .arena-hp-bar__track {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  background: transparent;
  border: 0;
  border-radius: inherit;
  display: flex;
  align-items: flex-end;
}

/* HP fill — gradient + outline border, matching pip style. Single
   continuous block (NOT pip-segmented), grows bottom-up. */
#bs-screen-battle.blindspot-battle .arena-hp-bar__fill,
#bs-battle-container.blindspot-battle .arena-hp-bar__fill {
  width: 100% !important;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  border-radius: 1px;
  border: 1px solid rgba(0, 0, 0, 0.5);
  box-sizing: border-box;
  transition: height 0.4s ease;
  background: linear-gradient(180deg, #ef4444, #b91c1c);
}
/* Stamina fill is hidden (pips replace it) but keep the rule defined
   for any consumer that might still reference the element. */
#bs-screen-battle.blindspot-battle .arena-stamina-bar__fill,
#bs-battle-container.blindspot-battle .arena-stamina-bar__fill {
  display: none !important;
}

/* ---------- STAT GLYPHS ABOVE THE RAILS ----------
   Phase 1: small icon above each rail so HP / stamina is identifiable
   without relying on color alone (heart for HP, lightning for
   stamina). Uses Font Awesome 6 unicode via pseudo-elements so no
   HTML edit is needed. The bars are already position: relative
   (anchor) → wait, they're position: absolute inside the frame, so
   our pseudo-element resolves to the bar's box. We nudge the icon
   above the rail with negative top.

   Tightened position-context: pseudo `position: absolute` resolves to
   the bar's containing block (the frame) rather than the bar itself
   when the bar is also `position: absolute` — so we explicitly anchor
   relative to the bar's own coordinate space. */
/* Plain heart / bolt glyphs above each rail. No circular badge — just
   the colored icon floating above the rail top with a soft glow. */
#bs-screen-battle.blindspot-battle .arena-hp-bar::before,
#bs-battle-container.blindspot-battle .arena-hp-bar::before {
  content: '\f004';                          /* fa-heart */
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  color: #ef4444;
  font-size: 0.7rem;
  line-height: 1;
  text-shadow: 0 0 6px rgba(239, 68, 68, 0.55);
  pointer-events: none;
  z-index: 5;
}
#bs-screen-battle.blindspot-battle .arena-stamina-bar::before,
#bs-battle-container.blindspot-battle .arena-stamina-bar::before {
  content: '\f0e7';                          /* fa-bolt */
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  color: var(--blindspot-accent-gold, #F5C078);
  font-size: 0.7rem;
  line-height: 1;
  text-shadow: 0 0 6px rgba(245, 192, 120, 0.55);
  pointer-events: none;
  z-index: 5;
}

/* True pips — JS renders N discrete .arena-stamina-pip divs into
   each stamina bar (one per max-stamina point). The legacy
   continuous gold fill + line-overlay illusion is hidden so only
   the new pips render. */
#bs-screen-battle.blindspot-battle .arena-stamina-bar__fill,
#bs-battle-container.blindspot-battle .arena-stamina-bar__fill {
  display: none !important;
}
#bs-screen-battle.blindspot-battle .arena-stamina-bar::after,
#bs-battle-container.blindspot-battle .arena-stamina-bar::after {
  content: none;
}

/* The bar becomes a flex column of pips, stacked bottom-up so the
   first filled pip is at the bottom (intuitive: stamina drains from
   the top down as you spend it). */
#bs-screen-battle.blindspot-battle .arena-stamina-bar,
#bs-battle-container.blindspot-battle .arena-stamina-bar {
  flex-direction: column-reverse;
  justify-content: flex-start;
  align-items: stretch;
  padding: 2px;
  gap: 2px;
  background: rgba(0, 0, 0, 0.5);
}

#bs-screen-battle.blindspot-battle .arena-stamina-pip,
#bs-battle-container.blindspot-battle .arena-stamina-pip {
  flex: 1 1 auto;
  width: 100%;
  min-height: 4px;
  border-radius: 1px;
  transition: background 160ms ease, box-shadow 160ms ease, opacity 160ms ease;
}
#bs-screen-battle.blindspot-battle .arena-stamina-pip--filled,
#bs-battle-container.blindspot-battle .arena-stamina-pip--filled {
  background: linear-gradient(180deg, var(--blindspot-accent-gold, #F5C078), var(--blindspot-accent-gold-dim, #B97417));
  border: 1px solid rgba(0, 0, 0, 0.5);
  box-sizing: border-box;
}
#bs-screen-battle.blindspot-battle .arena-stamina-pip--empty,
#bs-battle-container.blindspot-battle .arena-stamina-pip--empty {
  background: var(--blindspot-bg-2, #170D0B);
  border: 1px solid rgba(0, 0, 0, 0.5);
  box-sizing: border-box;
}
#bs-screen-battle.blindspot-battle .arena-combatant__hp-meta,
#bs-screen-battle.blindspot-battle .arena-combatant__stam-meta,
#bs-battle-container.blindspot-battle .arena-combatant__hp-meta,
#bs-battle-container.blindspot-battle .arena-combatant__stam-meta {
  display: none;
}

/* Numeric value below each vertical rail. The text spans live
   inside the bar element (last child) so they inherit the bar's
   `position: relative` + `overflow: visible` and can float just
   below the rail with absolute positioning. JS targets them by id
   (#arena-player-hp-text etc.) — same ids that used to live in the
   readout pill row, just relocated. */
#bs-screen-battle.blindspot-battle .arena-bar-readout,
#bs-battle-container.blindspot-battle .arena-bar-readout {
  position: absolute;
  bottom: -16px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--blindspot-font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  color: var(--blindspot-text-dim, #B89A82);
  white-space: nowrap;
  pointer-events: none;
  text-shadow: 0 0 4px rgba(0, 0, 0, 0.7);
  z-index: 5;
}
#bs-screen-battle.blindspot-battle .arena-bar-readout--hp,
#bs-battle-container.blindspot-battle .arena-bar-readout--hp {
  color: #ef4444;
}
#bs-screen-battle.blindspot-battle .arena-bar-readout--stam,
#bs-battle-container.blindspot-battle .arena-bar-readout--stam {
  color: var(--blindspot-accent-gold, #F5C078);
}
#bs-screen-battle.blindspot-battle .arena-combatant__readout-pill,
#bs-battle-container.blindspot-battle .arena-combatant__readout-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.18rem 0.55rem;
  border-radius: var(--blindspot-radius-pill, 999px);
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  color: var(--blindspot-text-dim, #B89A82);
  white-space: nowrap;
}
#bs-screen-battle.blindspot-battle .arena-combatant__readout-pill--hp i,
#bs-battle-container.blindspot-battle .arena-combatant__readout-pill--hp i {
  color: #ef4444;
}
#bs-screen-battle.blindspot-battle .arena-combatant__readout-pill--stam i,
#bs-battle-container.blindspot-battle .arena-combatant__readout-pill--stam i {
  color: var(--blindspot-accent-gold, #F5C078);
}

/* Item tray now shares the right gutter with the stamina rail — shift
   it inward so its icons don't overlap the rail. The tray was at
   right:8px; with stamina at right:4px (12px wide), we need the tray
   to start at right:24px+ to clear the rail. */
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray {
  right: 28px;
}
#bs-screen-battle.blindspot-battle .arena-combatant__nameplate , #bs-battle-container.blindspot-battle .arena-combatant__nameplate  {
  order: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45em;
  row-gap: 0.15rem;
  text-align: left;
  border: 0;
  padding: 0;
  background: transparent;
}
/* Name takes the full first row; element badge / boss stance / subtitle
   all flow on the second row inline. */
#bs-screen-battle.blindspot-battle .arena-combatant__nameplate .arena-combatant__name , #bs-battle-container.blindspot-battle .arena-combatant__nameplate .arena-combatant__name  {
  flex-basis: 100%;
  margin: 0;
}
/* Combatant column — relative anchor for the backdrop. Do NOT add
   overflow:hidden here; it clips HP/stamina/items/buffs below the
   frame and was the cause of the missing-bars regression. The
   backdrop scopes itself to just the frame area below. */
#bs-screen-battle.blindspot-battle .arena-combatant--player,
#bs-screen-battle.blindspot-battle .arena-combatant--opponent,
#bs-battle-container.blindspot-battle .arena-combatant--player,
#bs-battle-container.blindspot-battle .arena-combatant--opponent {
  position: relative;
  isolation: isolate;
}

/* Atmospheric backdrop — full-bleed copy of the card / boss avatar
   behind the foreground card. Pinned to the TOP of the column at the
   frame height so it sits behind the card. JS sets background-image
   inline. Bumped brightness + opacity from the first pass — the
   combined dim factors were knocking visibility down to ~14% which
   read as invisible against the dark page bg. HUD elements live
   BELOW this layer, not over it, so the legibility scrim isn't
   needed. */
#bs-screen-battle.blindspot-battle .arena-combatant__backdrop,
#bs-battle-container.blindspot-battle .arena-combatant__backdrop {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 360px;
  z-index: 0;
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
  filter: blur(22px) saturate(1.3) brightness(0.95);
  opacity: 0.9;
  pointer-events: none;
  overflow: hidden;
  border-radius: var(--blindspot-radius-card, 4px);
}
/* Soft fade-to-black at the bottom edge so the backdrop dissolves
   into the column rather than cutting hard. */
#bs-screen-battle.blindspot-battle .arena-combatant__backdrop::after,
#bs-battle-container.blindspot-battle .arena-combatant__backdrop::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, transparent 60%, rgba(13, 8, 7, 0.5) 100%);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  #bs-screen-battle.blindspot-battle .arena-combatant__backdrop,
  #bs-battle-container.blindspot-battle .arena-combatant__backdrop {
    filter: blur(16px) saturate(1.1) brightness(0.9);
  }
}

/* Foreground frame — taller than before so the full card has room to
   breathe. Transparent background so the backdrop reads through; no
   border (the rendered card brings its own chrome). z-index above the
   backdrop layer. */
#bs-screen-battle.blindspot-battle .arena-combatant__frame , #bs-battle-container.blindspot-battle .arena-combatant__frame  {
  order: 1;
  width: 100%;
  margin: 0;
  /* Trimmed 400 → 360 to shrink the field row another notch. */
  height: 360px;
  padding: 0.25rem 32px;
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: transparent;
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
#bs-screen-battle.blindspot-battle .arena-combatant__card , #bs-battle-container.blindspot-battle .arena-combatant__card  {
  width: 100%;
  height: 100%;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Rendered card — preserve its own border-radius / shadow so it reads
   as a card, not a portrait fill. Lock to CardForge's 5:7 portrait
   aspect ratio (375x525 source) so it never stretches square in a
   wide column. Height drives the box; width derives from aspect. */
#bs-screen-battle.blindspot-battle .arena-combatant__card .bs-rendered-card , #bs-battle-container.blindspot-battle .arena-combatant__card .bs-rendered-card  {
  height: 100%;
  width: auto;
  aspect-ratio: 5 / 7;
  max-width: 100%;
  margin: 0 auto;
  filter: drop-shadow(0 18px 32px rgba(0, 0, 0, 0.75));
}
/* Opponent now renders a full boss card via BsBossCard.render — the
   markup matches `.bs-rendered-card` so it inherits the player card
   styling. The card-frame wrapper just centers + sizes it, no longer
   draws its own border (the inner card brings its own chrome). */
#bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-combatant__card,
#bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-combatant__card {
  height: 100%;
  width: 100%;
  max-width: none;
  margin: 0;
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: transparent;
  box-shadow: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------- BOSS CARD — REDACTED MIRROR ----------
   `.bs-rc--boss` shares all the player-card styling and adds a few
   boss-only treatments: a tier badge in the art slot, redacted stat
   bars (silhouette fill + "???" value) when the data's `revealed`
   flag is false, and a locked trait chip row at the bottom. */

/* Element badge inside the card — icon-only AND inline with the
   class label on the same row, mirroring the legacy nameplate
   layout above the card (which had name on row 1, then class +
   element-icon together on row 2). The shared player card renderer
   adds a text label after the icon (visible elsewhere — forge,
   lobby, gallery); we suppress that label here without forking the
   render path by zeroing font-size on the container and restoring
   it on the icon. Applies to both player and boss cards. */
#bs-screen-battle.blindspot-battle .arena-combatant .bs-rc__class,
#bs-battle-container.blindspot-battle .arena-combatant .bs-rc__class {
  display: inline-block;
  vertical-align: middle;
}
#bs-screen-battle.blindspot-battle .arena-combatant .bs-rc__element,
#bs-battle-container.blindspot-battle .arena-combatant .bs-rc__element {
  display: inline-block;
  vertical-align: middle;
  margin-left: 0.5em;
  font-size: 0;
  letter-spacing: 0;
}
#bs-screen-battle.blindspot-battle .arena-combatant .bs-rc__element i,
#bs-battle-container.blindspot-battle .arena-combatant .bs-rc__element i {
  font-size: 0.95rem;
  line-height: 1;
}

/* Tier badge — top-right of the art slot, mirrors the player title
   badge position. Colour escalates with tier 1→5 from neutral grey
   to blood-red Vein accent. */
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc__tier-badge,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc__tier-badge {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 22px;
  padding: 0 0.45rem;
  font-family: var(--blindspot-font-mono);
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  border-radius: var(--blindspot-radius-pill, 999px);
  background: rgba(0, 0, 0, 0.7);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  color: var(--blindspot-text-dim, #B89A82);
  backdrop-filter: blur(4px);
}
#bs-screen-battle.blindspot-battle .bs-rc--boss[data-tier="1"] .bs-rc__tier-badge,
#bs-battle-container.blindspot-battle .bs-rc--boss[data-tier="1"] .bs-rc__tier-badge { color: #B89A82; border-color: #B89A82; }
#bs-screen-battle.blindspot-battle .bs-rc--boss[data-tier="2"] .bs-rc__tier-badge,
#bs-battle-container.blindspot-battle .bs-rc--boss[data-tier="2"] .bs-rc__tier-badge { color: var(--blindspot-accent-gold, #F5C078); border-color: var(--blindspot-accent-gold, #F5C078); }
#bs-screen-battle.blindspot-battle .bs-rc--boss[data-tier="3"] .bs-rc__tier-badge,
#bs-battle-container.blindspot-battle .bs-rc--boss[data-tier="3"] .bs-rc__tier-badge { color: #f59e0b; border-color: #f59e0b; }
#bs-screen-battle.blindspot-battle .bs-rc--boss[data-tier="4"] .bs-rc__tier-badge,
#bs-battle-container.blindspot-battle .bs-rc--boss[data-tier="4"] .bs-rc__tier-badge { color: #ef4444; border-color: #ef4444; }
#bs-screen-battle.blindspot-battle .bs-rc--boss[data-tier="5"] .bs-rc__tier-badge,
#bs-battle-container.blindspot-battle .bs-rc--boss[data-tier="5"] .bs-rc__tier-badge {
  color: #fff;
  border-color: var(--blindspot-accent, #C8302C);
  background: linear-gradient(180deg, var(--blindspot-accent, #C8302C), var(--blindspot-accent-dim, #8E2220));
  box-shadow: 0 0 12px rgba(200, 48, 44, 0.55);
}

/* Redacted stat bar — dim silhouette, no fill colour. The track is
   visible but the fill is a low-opacity dashed pattern hinting at
   "unknown amount". */
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-stat__bar--redacted,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-stat__bar--redacted {
  position: relative;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  background-image: repeating-linear-gradient(
    -45deg,
    transparent 0,
    transparent 4px,
    rgba(255, 255, 255, 0.05) 4px,
    rgba(255, 255, 255, 0.05) 8px
  );
}
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-stat__val--redacted,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-stat__val--redacted {
  font-family: var(--blindspot-font-mono);
  color: var(--blindspot-text-muted, #7A5E4C);
  letter-spacing: 0.05em;
  opacity: 0.7;
}

/* Trait chip row at bottom of card. Revealed traits get a coloured
   border, locked traits show a lock icon + "???". */
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-traits,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-traits {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  /* Padding-top trimmed (was 0.4rem) so the trait row sits flush against
     the bottom of the stats block without a visible gap. The 1px divider
     does the visual separation. */
  padding: 0.3rem 0.5rem 0.5rem;
  margin: 0;
  border-top: 1px solid var(--blindspot-border, #3A1F1A);
  background: rgba(0, 0, 0, 0.35);
}
/* Boss card has 3 stat rows vs the player's 5. To eliminate the dead
   space between stats and traits inside the boss card body, let the
   stats container grow to fill the remaining vertical space. Stat rows
   stay anchored to the top via flex-direction: column + flex-start. */
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-stats,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-stats {
  flex: 1;
  justify-content: flex-start;
  padding-bottom: 0;
}
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-trait,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-trait {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  font-family: var(--blindspot-font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  padding: 0.18rem 0.5rem;
  border-radius: var(--blindspot-radius-pill, 999px);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  background: rgba(13, 8, 7, 0.55);
  color: var(--blindspot-text-dim, #B89A82);
  white-space: nowrap;
}
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-trait--revealed,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-trait--revealed {
  border-color: var(--blindspot-accent, #C8302C);
  color: var(--blindspot-accent, #C8302C);
}
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-trait--locked,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-trait--locked {
  opacity: 0.65;
}
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc-trait--locked i,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc-trait--locked i {
  color: var(--blindspot-text-muted, #7A5E4C);
}

/* Boss avatar art — top-align so faces / heads aren't clipped at the
   top of the card. The legacy `.bs-rc__avatar` rule uses `object-fit:
   cover` with default `object-position: center` (= center center)
   which crops both top and bottom equally. Boss portraits are
   composed with the head near the top of the source image, so
   `center top` preserves the face. */
#bs-screen-battle.blindspot-battle .bs-rc--boss .bs-rc__avatar,
#bs-battle-container.blindspot-battle .bs-rc--boss .bs-rc__avatar {
  object-position: center top;
}

/* Boss card itself — share the player card aspect but accommodate the
   trait row at the bottom. Inherits .bs-rendered-card layout from
   blindspot.css. The combatant frame already sets the size context. */
#bs-screen-battle.blindspot-battle .arena-combatant--opponent .bs-rendered-card,
#bs-battle-container.blindspot-battle .arena-combatant--opponent .bs-rendered-card {
  height: 100%;
  width: auto;
  aspect-ratio: 5 / 7;
  max-width: 100%;
  margin: 0 auto;
  filter: drop-shadow(0 18px 32px rgba(0, 0, 0, 0.75));
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-combatant__img,
#bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-combatant__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
/* HUD elements (readout pills, buffs, status) sit above the backdrop.
   Keep their stacking explicit. The combatant nameplate is hidden —
   name + class are now rendered inside the card itself (player card +
   boss card both have built-in name/class labels) so the row above
   the card was redundant. */
#bs-screen-battle.blindspot-battle .arena-combatant__nameplate,
#bs-battle-container.blindspot-battle .arena-combatant__nameplate {
  display: none;
}
#bs-screen-battle.blindspot-battle .arena-combatant__readout,
#bs-screen-battle.blindspot-battle .arena-player-buffs,
#bs-screen-battle.blindspot-battle .arena-status-row,
#bs-battle-container.blindspot-battle .arena-combatant__readout,
#bs-battle-container.blindspot-battle .arena-player-buffs,
#bs-battle-container.blindspot-battle .arena-status-row {
  position: relative;
  z-index: 2;
}
/* Order rules removed for HP/stamina bars — they're absolute-positioned
   inside the frame and not in the column flow anymore. */
#bs-screen-battle.blindspot-battle .arena-player-items , #bs-battle-container.blindspot-battle .arena-player-items  { order: 4; }
#bs-screen-battle.blindspot-battle .arena-player-buffs, #bs-battle-container.blindspot-battle .arena-player-buffs,
#bs-screen-battle.blindspot-battle .arena-opponent-buffs , #bs-battle-container.blindspot-battle .arena-opponent-buffs  {
  order: 5;
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
  /* Tight against the frame so the strip reads as "attached to the card",
     mirroring how the boss traits sit flush below the boss card stats. */
  margin-top: 0;
  justify-content: center;
}
#bs-screen-battle.blindspot-battle .arena-status-row , #bs-battle-container.blindspot-battle .arena-status-row  {
  order: 6;
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 0;
}

/* Title badge — repositioned to the TOP-LEFT corner of the card in
   battle context so it doesn't collide with the power badge that
   sits in the top-right. Battle-scope only — lobby / gallery / forge
   keep the original top-right placement. */
#bs-screen-battle.blindspot-battle .arena-combatant .bs-rc__title-badge,
#bs-battle-container.blindspot-battle .arena-combatant .bs-rc__title-badge {
  top: 6px;
  left: 6px;
  right: auto;
}

/* Power readout (⚡ 60) — repositioned to the top-right corner of the
   player card in battle context, mirroring the boss card's tier
   badge slot. Card has `position: relative` so absolute positioning
   resolves to the card box. Battle-scope only — lobby / gallery /
   forge keep the bottom-of-card placement. */
#bs-screen-battle.blindspot-battle .arena-combatant--player .bs-rendered-card .bs-rc__power,
#bs-battle-container.blindspot-battle .arena-combatant--player .bs-rendered-card .bs-rc__power {
  position: absolute;
  top: 0.45rem;
  right: 0.45rem;
  z-index: 3;
  padding: 0.22rem 0.55rem;
  background: rgba(13, 8, 7, 0.7);
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  border-radius: var(--blindspot-radius-pill, 999px);
  font-family: var(--blindspot-font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--blindspot-accent-gold, #F5C078);
  text-shadow: 0 0 6px rgba(245, 192, 120, 0.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  width: auto;
  text-align: center;
}

/* Player buff strip stays at panel level (Option B reconciliation,
   2026-04-28): both sides display permanent identity inside the
   card chrome and transient active buffs in the panel space below.
   The "move buffs into rendered card" override was removed from
   BsBattlePalette.apply() — buffs now sit naturally in the panel
   stack between the card frame and the status row. */
/* Player buff / status pills — match the boss trait pill aesthetic so
   both sides read as the same visual language. Selectors target the
   common pill child markup (span or div) inside the buff/status rows. */
#bs-screen-battle.blindspot-battle .arena-player-buffs > *,
#bs-screen-battle.blindspot-battle .arena-opponent-buffs > *,
#bs-screen-battle.blindspot-battle .arena-status-row > *,
#bs-battle-container.blindspot-battle .arena-player-buffs > *,
#bs-battle-container.blindspot-battle .arena-opponent-buffs > *,
#bs-battle-container.blindspot-battle .arena-status-row > * {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  font-family: var(--blindspot-font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  padding: 0.18rem 0.5rem;
  border-radius: var(--blindspot-radius-pill, 999px);
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  background: rgba(13, 8, 7, 0.55);
  color: var(--blindspot-accent-gold, #F5C078);
  white-space: nowrap;
}


/* Move the battle log to the bottom of the .arena-battle flex
   column — under the abilities/move grid instead of between the
   field and the moves. The arena-battle is already
   `display: flex; flex-direction: column` so a high `order` value
   sinks the log without touching DOM order. */
#bs-screen-battle.blindspot-battle .arena-battle__log,
#bs-battle-container.blindspot-battle .arena-battle__log {
  order: 99;
  /* Phase 5: moves now stretch (flex: 1) to absorb leftover vertical, so
     the auto-margin from Phase 1.5 is no longer needed and would create
     inverse spacing. Natural small gap below moves. */
  margin-top: 0.4rem;
}

/* ---------- VS CENTER COLUMN — round pill + matchup chip ----------
   The center column had a lot of empty space between the VS glyph and
   the HYPE bar. Two new elements fill it usefully:
   - .bs-vs-round: prominent round counter pill above VS — duplicates
     the small header counter so the player's eye can track rounds
     without leaving the field.
   - .bs-vs-matchup: single elemental advantage call-out under HYPE.
     Hidden when neutral (mirror or chaos-vs-anything) so it collapses
     cleanly. Replaces what would otherwise be guesswork from reading
     both nameplate element badges.
   ---------------------------------------------------------------- */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-round,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-round {
  font-family: var(--blindspot-font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--blindspot-accent-gold, #F5C078);
  padding: 0.4rem 1.1rem;
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  border-radius: var(--blindspot-radius-pill, 999px);
  background: rgba(28, 16, 13, 0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  align-self: center;
  text-shadow: 0 0 12px rgba(245, 192, 120, 0.5);
  box-shadow: 0 0 16px rgba(245, 192, 120, 0.18);
}

#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  font-family: var(--blindspot-font-mono);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.55rem 1rem;
  border-radius: var(--blindspot-radius-pill, 999px);
  background: rgba(28, 16, 13, 0.7);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  color: var(--blindspot-text-dim, #B89A82);
  align-self: center;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup[hidden],
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup[hidden] {
  display: none;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup span,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup span {
  opacity: 0.85;
  font-weight: 600;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup--good,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup--good {
  color: var(--blindspot-success, #6E9F4A);
  border-color: rgba(110, 159, 74, 0.55);
  text-shadow: 0 0 6px rgba(110, 159, 74, 0.45);
  animation: bs-vs-matchup-pulse-good 2.4s ease-in-out infinite;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup--bad,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup--bad {
  color: var(--blindspot-accent, #C8302C);
  border-color: rgba(200, 48, 44, 0.55);
  text-shadow: 0 0 6px rgba(200, 48, 44, 0.45);
  animation: bs-vs-matchup-pulse-bad 2.4s ease-in-out infinite;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup--neutral,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup--neutral {
  color: var(--blindspot-text-dim, #B89A82);
}
@keyframes bs-vs-matchup-pulse-good {
  0%, 100% { box-shadow: 0 0 14px rgba(110, 159, 74, 0.18); }
  50%      { box-shadow: 0 0 24px rgba(110, 159, 74, 0.42); }
}
@keyframes bs-vs-matchup-pulse-bad {
  0%, 100% { box-shadow: 0 0 14px rgba(200, 48, 44, 0.18); }
  50%      { box-shadow: 0 0 24px rgba(200, 48, 44, 0.42); }
}
@media (prefers-reduced-motion: reduce) {
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup--good,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup--good,
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup--bad,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup--bad {
    animation: none;
    box-shadow: 0 0 18px currentColor;
  }
}

/* ---------- ITEM / CHARM TRAY ----------
   Vertical strip of compact hoverable icons overlaying the right edge
   of the player portrait. Replaces the legacy `.arena-items-row` strip
   that sat between battle log and move grid (pushed moves below the
   fold once the player brought 3+ items in). Lives inside
   .arena-combatant__frame which is already position:relative +
   overflow:hidden, so we stay inside the portrait box. Hover/title
   gives the full name + description as a native browser tooltip. */
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray {
  position: absolute;
  top: 8px;
  right: 8px;
  bottom: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 3;
  pointer-events: none;
}
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray:empty,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray:empty {
  display: none;
}

/* When BsBattlePalette.apply() relocates the item tray from inside
   the frame to be a direct child of the panel, override the
   right-edge vertical layout above with a horizontal strip below the
   card. Direct-child selector ensures only the moved tray gets these
   rules; any tray that's still inside a frame (legacy code path)
   keeps the original right-edge treatment.
   `order: 10` sits the strip after every other panel child (frame=1,
   items=4, buffs=5, status=6) — without it, the default `order: 0`
   would shove the tray to the TOP of the panel, above the card. */
#bs-screen-battle.blindspot-battle .arena-combatant > .arena-combatant__item-tray,
#bs-battle-container.blindspot-battle .arena-combatant > .arena-combatant__item-tray {
  position: static;
  order: 10;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
  padding: 0.35rem 0.5rem;
  pointer-events: auto;
  width: auto;
  inset: auto;
  background: rgba(0, 0, 0, 0.45);
  border-top: 1px solid var(--blindspot-border, #3A1F1A);
  border-radius: var(--blindspot-radius-tile, 4px);
}

/* Compact icon button inside the tray. Re-enable pointer-events on
   the button itself; container stays click-through so the portrait
   underneath remains interactive everywhere else. */
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn {
  pointer-events: auto;
  position: relative;
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  min-height: 0;
  max-width: 32px;
  padding: 0;
  margin: 0;
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  border-radius: var(--blindspot-radius-button, 2px);
  background: rgba(28, 16, 13, 0.85);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color 160ms ease,
              background 160ms ease,
              transform 160ms ease,
              box-shadow 160ms ease;
  cursor: pointer;
}
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn i,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn i {
  font-size: 0.95rem;
  color: var(--blindspot-accent-gold, #F5C078);
  text-shadow: 0 0 6px rgba(245, 192, 120, 0.4);
}
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn:hover:not(:disabled),
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn:hover:not(:disabled) {
  border-color: var(--blindspot-accent-gold, #F5C078);
  background: rgba(245, 192, 120, 0.14);
  transform: translateX(-1px);
  box-shadow: 0 0 12px rgba(245, 192, 120, 0.25);
}
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn:focus-visible,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn:focus-visible {
  outline: 2px solid var(--blindspot-accent-gold, #F5C078);
  outline-offset: 2px;
}
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn--used,
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn:disabled,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn--used,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  border-color: var(--blindspot-border, #3A1F1A);
  transform: none;
  box-shadow: none;
}

/* Defensive: hide any legacy text spans if the JS path renders the
   non-compact markup (shouldn't happen since compact is true whenever
   the tray exists, but cheap insurance against markup drift). */
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn__label,
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn__stat,
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn__desc,
#bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn__glow,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn__label,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn__stat,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn__desc,
#bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn__glow {
  display: none;
}

/* Boss intent — banner inside HUD top, between Round and the action
   buttons. Mirrors the bundle's `.battle__intent`: subtle dark surface,
   uniform 1px border (no left accent stripe), italic text, icon picks up
   the move's dynamic color via `--intent-color` (set on the container by
   JS in showBossIntent). */
#bs-screen-battle.blindspot-battle .arena-battle__header .arena-boss-intent , #bs-battle-container.blindspot-battle .arena-battle__header .arena-boss-intent  {
  flex: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.5em 0.9em;
  background: var(--blindspot-surface);
  border: 1px solid var(--blindspot-epic);
  border-radius: var(--blindspot-radius-button);
  font-family: var(--blindspot-font-body);
  font-size: 0.82rem;
  color: var(--blindspot-text-dim);
  font-style: italic;
  min-width: 0;
}
#bs-screen-battle.blindspot-battle .arena-battle__header .arena-boss-intent:has(.arena-boss-intent__text:empty), #bs-battle-container.blindspot-battle .arena-battle__header .arena-boss-intent:has(.arena-boss-intent__text:empty),
#bs-screen-battle.blindspot-battle .arena-battle__header .arena-boss-intent:empty , #bs-battle-container.blindspot-battle .arena-battle__header .arena-boss-intent:empty  {
  display: none;
}
#bs-screen-battle.blindspot-battle .arena-boss-intent__icon , #bs-battle-container.blindspot-battle .arena-boss-intent__icon  {
  color: var(--intent-color, var(--blindspot-epic));
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
}
#bs-screen-battle.blindspot-battle .arena-boss-intent__icon i , #bs-battle-container.blindspot-battle .arena-boss-intent__icon i  {
  color: inherit;
}
#bs-screen-battle.blindspot-battle .arena-boss-intent__text , #bs-battle-container.blindspot-battle .arena-boss-intent__text  {
  /* Allow up to 2 lines of wrapped text before ellipsing — was
     `white-space: nowrap` which forced everything onto one line. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
  min-width: 0;
}

/* Center column — VS glyph + hype + stances */
#bs-screen-battle.blindspot-battle .blindspot-battle__center , #bs-battle-container.blindspot-battle .blindspot-battle__center  {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 0;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__vs , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__vs  {
  position: static;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  width: auto;
  height: auto;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__vs-text , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__vs-text  {
  font-family: var(--blindspot-font-display);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(3rem, 6vw, 4rem);
  color: var(--blindspot-accent);
  letter-spacing: 0.08em;
  text-shadow: 0 0 40px rgba(200, 48, 44, 0.5);
  line-height: 1;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__vs::before, #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__vs::before,
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__vs::after , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__vs::after  {
  content: none;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-hype-bar , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-hype-bar  {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  background: transparent;
  border: 0;
  padding: 0;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-hype-bar__track , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-hype-bar__track  {
  width: 100%;
  margin: 0;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-row , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-row  {
  width: 100%;
  display: flex;
  gap: 0.4rem;
  justify-content: space-around;
  background: transparent;
  border: 0;
  padding: 0;
  position: static;
  flex-direction: row;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn  {
  flex: 1;
  width: auto;
  height: auto;
  padding: 0.6rem 0.4rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  font-size: 1.1rem;
  font-family: var(--blindspot-font-mono);
}
/* Add text labels via ::after pseudo-content (avoids markup change) */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn[data-stance="balanced"]::after , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn[data-stance="balanced"]::after  {
  content: "Balanced";
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn[data-stance="aggressive"]::after , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn[data-stance="aggressive"]::after  {
  content: "Aggressive";
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn[data-stance="defensive"]::after , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn[data-stance="defensive"]::after  {
  content: "Defensive";
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn::after , #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn::after  {
  font-size: 0.55rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: inherit;
  opacity: 0.85;
}

/* Hand rail — eyebrow above the move grid */
#bs-screen-battle.blindspot-battle .blindspot-battle__hand-rail , #bs-battle-container.blindspot-battle .blindspot-battle__hand-rail  {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  white-space: nowrap;
  gap: 0.5em;
  padding: 0.25rem 0.2rem 0.4rem;
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-text-muted);
}
#bs-screen-battle.blindspot-battle .blindspot-battle__hand-rail i , #bs-battle-container.blindspot-battle .blindspot-battle__hand-rail i  {
  color: var(--blindspot-accent);
}

/* Move hand — 5 cards centered horizontally at a fixed width. Reverted
   from `repeat(5, 1fr) + flex: 1` (Phase 5) which stretched cards to
   fill leftover vertical and triggered a 100%-zoom render bug where
   the card grid (grid-template-rows: repeat(5, auto)) collapsed and
   clipped the energy column + left-side text. Smaller centered cards
   read as a tighter "hand" and avoid the bug entirely. */
#bs-screen-battle.blindspot-battle .arena-battle__moves , #bs-battle-container.blindspot-battle .arena-battle__moves  {
  display: grid;
  grid-template-columns: repeat(5, 240px);
  gap: 0.6rem;
  justify-content: center;
  margin-top: 0;
  padding: 0;
  background: transparent;
}
@media (max-width: 1100px) {
  #bs-screen-battle.blindspot-battle .arena-battle__moves {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 600px) {
  #bs-screen-battle.blindspot-battle .arena-battle__moves {
    grid-template-columns: 1fr;
  }
}
#bs-screen-battle.blindspot-battle .arena-move-btn, #bs-battle-container.blindspot-battle .arena-move-btn,
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card , #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card  {
  width: auto;
  margin: 0;
}
/* Move-card art aspect ratio. Reverted from Phase 5's 3/2 back to 2/1
   — the taller art at 3/2 caused horizontal text clipping on the
   second move card at exact 100% zoom. The 949p / 800p tiers below
   stay at 3/1 / 4/1 for laptop viewport compaction. */
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__art,
#bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__art {
  aspect-ratio: 2 / 1;
}

/* ---------- HEIGHT-RESPONSIVE COMPRESSION ----------
   Laptop viewports (720p / 768p / 800p) need aggressive compaction
   or the move grid drops below the fold and gets clipped by
   body.bs-battle-active { overflow: hidden }. The defaults above
   target 900p+ monitors with the lush 270px combatant frame; for
   anything shorter we shrink the frame, slim the move-card art,
   and strip the desc + tags so the 5-card row stays in view. */
@media (max-height: 949px) {
  #bs-screen-battle.blindspot-battle .arena-combatant__frame,
  #bs-battle-container.blindspot-battle .arena-combatant__frame {
    /* 280 → 380 — uses the spare ~113px of headroom at 1440×900. */
    height: 380px;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant__backdrop,
  #bs-battle-container.blindspot-battle .arena-combatant__backdrop {
    height: 380px;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant,
  #bs-battle-container.blindspot-battle .arena-combatant {
    padding: 0.35rem;
    gap: 0.18rem;
    max-height: min(96vh, 480px);
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__art,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__art {
    aspect-ratio: 3 / 1;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__log,
  #bs-battle-container.blindspot-battle .arena-battle__log {
    max-height: 50px;
  }
  /* Strip move-card body to header + art + footer — desc + tags hidden. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__desc,
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__tags,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__desc,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__tags {
    display: none;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card {
    padding: 0.45rem 0.5rem !important;
    gap: 0.3rem;
    min-height: 0;
  }
}
@media (max-height: 800px) {
  #bs-screen-battle.blindspot-battle .arena-combatant__frame,
  #bs-battle-container.blindspot-battle .arena-combatant__frame {
    /* 220 → 250 (+14%). Uses most of the 43px headroom at 1366×768. */
    height: 250px;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant__backdrop,
  #bs-battle-container.blindspot-battle .arena-combatant__backdrop {
    height: 250px;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__art,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__art {
    aspect-ratio: 4 / 1;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__log,
  #bs-battle-container.blindspot-battle .arena-battle__log {
    max-height: 40px;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant,
  #bs-battle-container.blindspot-battle .arena-combatant {
    padding: 0.3rem;
    gap: 0.12rem;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__footer,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__footer {
    display: none;
  }
}

/* ============================================================
   SLICE 1 — bundle alignment (Apr 2026)
   Move-card color coding, hype hint, log header/grid, hand-rail
   readout. Purely additive; no existing rules modified.
   ============================================================ */

/* ---------- MOVE CARDS — color code per move (mirrors bundle's --mc) ---------- */
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move="strike"]   , #bs-battle-container.blindspot-battle .arena-move-btn[data-move="strike"]    { --bs-move-color: #ff7a3a; }
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move="guard"]    , #bs-battle-container.blindspot-battle .arena-move-btn[data-move="guard"]     { --bs-move-color: #6cc4ff; }
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move="ability"]  , #bs-battle-container.blindspot-battle .arena-move-btn[data-move="ability"]   { --bs-move-color: #b47cf5; }
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move="heal"]     , #bs-battle-container.blindspot-battle .arena-move-btn[data-move="heal"]      { --bs-move-color: #6cffb0; }
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move="counter"]  , #bs-battle-container.blindspot-battle .arena-move-btn[data-move="counter"]   { --bs-move-color: #ffd97a; }

#bs-screen-battle.blindspot-battle .arena-move-btn[data-move] .bs-move-card__type-label , #bs-battle-container.blindspot-battle .arena-move-btn[data-move] .bs-move-card__type-label  {
  color: var(--bs-move-color, var(--blindspot-accent));
}
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move] .bs-move-card__tag--active , #bs-battle-container.blindspot-battle .arena-move-btn[data-move] .bs-move-card__tag--active  {
  background: var(--bs-move-color, var(--blindspot-accent));
  border-color: var(--bs-move-color, var(--blindspot-accent));
  color: #0E0A06;
}
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move]:hover , #bs-battle-container.blindspot-battle .arena-move-btn[data-move]:hover  {
  border-color: var(--bs-move-color, var(--blindspot-accent));
  box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.8),
              0 0 30px -8px var(--bs-move-color, rgba(200, 48, 44, 0.4));
}
#bs-screen-battle.blindspot-battle .arena-move-btn[data-move] .bs-move-card__dot--active , #bs-battle-container.blindspot-battle .arena-move-btn[data-move] .bs-move-card__dot--active  {
  background: var(--bs-move-color, var(--blindspot-accent));
}

/* ---------- HYPE HINT (under the hype bar) ---------- */
#bs-screen-battle.blindspot-battle .arena-hype-bar__hint , #bs-battle-container.blindspot-battle .arena-hype-bar__hint  {
  font-family: var(--blindspot-font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* White (was --blindspot-epic purple, which got lost behind the
     purple HYPE label above). Dark drop shadow keeps it legible on
     lighter arena backgrounds. */
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
  text-align: center;
  margin-top: 0.25rem;
  display: block;
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__hint:empty , #bs-battle-container.blindspot-battle .arena-hype-bar__hint:empty  {
  display: none;
}

/* ---------- BATTLE LOG (header + grid rows when JS injects structured spans) ---------- */
#bs-screen-battle.blindspot-battle .arena-battle__log-head , #bs-battle-container.blindspot-battle .arena-battle__log-head  {
  font-family: var(--blindspot-font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-accent);
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  margin-bottom: 0.45rem;
}
/* Grid layout activates only when JS injects __round/__text/__dmg children
   so flat-string log entries written by older code stay readable. */
#bs-screen-battle.blindspot-battle .arena-log-entry:has(.arena-log-entry__round) , #bs-battle-container.blindspot-battle .arena-log-entry:has(.arena-log-entry__round)  {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.18rem 0;
  font-size: 0.82rem;
}
#bs-screen-battle.blindspot-battle .arena-log-entry__round , #bs-battle-container.blindspot-battle .arena-log-entry__round  {
  font-family: var(--blindspot-font-mono);
  font-size: 0.65rem;
  color: var(--blindspot-text-muted);
  letter-spacing: 0.08em;
}
#bs-screen-battle.blindspot-battle .arena-log-entry__text , #bs-battle-container.blindspot-battle .arena-log-entry__text  {
  color: var(--blindspot-text-dim);
}
#bs-screen-battle.blindspot-battle .arena-log-entry__dmg , #bs-battle-container.blindspot-battle .arena-log-entry__dmg  {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--blindspot-accent);
  white-space: nowrap;
}
#bs-screen-battle.blindspot-battle .arena-log-entry__dmg--crit , #bs-battle-container.blindspot-battle .arena-log-entry__dmg--crit  {
  color: var(--blindspot-danger);
}
#bs-screen-battle.blindspot-battle .arena-log-entry__dmg--reflect , #bs-battle-container.blindspot-battle .arena-log-entry__dmg--reflect  {
  color: var(--blindspot-info);
}

/* ---------- HAND RAIL — stamina readout + combo hint ---------- */
#bs-screen-battle.blindspot-battle .blindspot-battle__hand-rail-stamina , #bs-battle-container.blindspot-battle .blindspot-battle__hand-rail-stamina  {
  color: var(--blindspot-text-muted);
  letter-spacing: 0.14em;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__hand-rail-combo:empty , #bs-battle-container.blindspot-battle .blindspot-battle__hand-rail-combo:empty  {
  display: none;
}

/* ============================================================
   SLICE 2 — Combatant HP/Stamina meta rows (Apr 2026) [RETIRED]
   Originally rendered "HP 132/132" and "Stamina 4/6" label-and-value
   rows above each horizontal bar. The Phase-1 vertical-rail redesign
   moved numeric values to the readout pills below the card frame, so
   the meta rows are now hidden in HTML. This rule was forcing them
   back to display:flex regardless and breaking the [hidden] attribute
   — kill them all so the HTML hidden attribute wins.
   ============================================================ */
#bs-screen-battle.blindspot-battle .arena-combatant__hp-meta, #bs-battle-container.blindspot-battle .arena-combatant__hp-meta,
#bs-screen-battle.blindspot-battle .arena-combatant__stam-meta , #bs-battle-container.blindspot-battle .arena-combatant__stam-meta  {
  display: none !important;
}
#bs-screen-battle.blindspot-battle .arena-combatant__meta-lbl , #bs-battle-container.blindspot-battle .arena-combatant__meta-lbl  {
  display: none !important;
}
#bs-screen-battle.blindspot-battle .arena-combatant__meta-val , #bs-battle-container.blindspot-battle .arena-combatant__meta-val  {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--blindspot-accent);
}
#bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-combatant__meta-val , #bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-combatant__meta-val  {
  color: var(--blindspot-danger);
}

/* HP/stamina bars + their meta rows are no longer in column flow —
   they live as absolute rails inside the frame (see VERTICAL HP /
   STAMINA RAILS). Only items/buffs/status need flex ordering now. */
#bs-screen-battle.blindspot-battle .arena-player-items, #bs-battle-container.blindspot-battle .arena-player-items,
#bs-screen-battle.blindspot-battle .arena-opponent-items       , #bs-battle-container.blindspot-battle .arena-opponent-items        { order: 6; }
#bs-screen-battle.blindspot-battle .arena-player-buffs, #bs-battle-container.blindspot-battle .arena-player-buffs,
#bs-screen-battle.blindspot-battle .arena-opponent-buffs       , #bs-battle-container.blindspot-battle .arena-opponent-buffs        { order: 7; }
#bs-screen-battle.blindspot-battle .arena-status-row           , #bs-battle-container.blindspot-battle .arena-status-row            { order: 8; }

/* ============================================================
   SLICE 4 — Round indicator polish (Apr 2026)
   The boxed treatment was stripped from `.bs-page .arena-battle__round`
   in blindspot.css. New structure: eyebrow "Round" + accent-coloured
   mono number. JS updates the `#arena-round-num` span directly with a
   zero-padded value (01, 02, …).
   ============================================================ */
#bs-screen-battle.blindspot-battle .arena-battle__round , #bs-battle-container.blindspot-battle .arena-battle__round  {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
}
#bs-screen-battle.blindspot-battle .arena-battle__round-eyebrow , #bs-battle-container.blindspot-battle .arena-battle__round-eyebrow  {
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-text-muted);
}
#bs-screen-battle.blindspot-battle .arena-battle__round-num , #bs-battle-container.blindspot-battle .arena-battle__round-num  {
  font-family: var(--blindspot-font-numeric);
  font-feature-settings: "tnum" on, "lnum" on;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--blindspot-accent);
  line-height: 1;
}

/* ============================================================
   SLICE 5 — Combatant subtitle line (Apr 2026)
   GUARDIAN · LV 386 / BOSS 9 · DIFF 9 — eyebrow row under name.
   JS populates via renderCombatants. Hidden when empty.
   ============================================================ */
#bs-screen-battle.blindspot-battle .arena-combatant__sub , #bs-battle-container.blindspot-battle .arena-combatant__sub  {
  display: block;
  font-family: var(--blindspot-font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-text-muted);
  margin-top: 0.1rem;
}
#bs-screen-battle.blindspot-battle .arena-combatant__sub:empty , #bs-battle-container.blindspot-battle .arena-combatant__sub:empty  {
  display: none;
}

/* Hide empty content rows so they don't reserve vertical space. JS only
   populates these when there's something to show (items in inventory,
   active buffs, status messages). Blank rows otherwise = wasted height. */
#bs-screen-battle.blindspot-battle .arena-player-items:empty, #bs-battle-container.blindspot-battle .arena-player-items:empty,
#bs-screen-battle.blindspot-battle .arena-opponent-items:empty, #bs-battle-container.blindspot-battle .arena-opponent-items:empty,
#bs-screen-battle.blindspot-battle .arena-player-buffs:empty, #bs-battle-container.blindspot-battle .arena-player-buffs:empty,
#bs-screen-battle.blindspot-battle .arena-opponent-buffs:empty, #bs-battle-container.blindspot-battle .arena-opponent-buffs:empty,
#bs-screen-battle.blindspot-battle .arena-status-row:empty , #bs-battle-container.blindspot-battle .arena-status-row:empty  {
  display: none;
}

/* ---------- VICTORY / DEFEAT RESULTS MODAL — VEIN PASS ----------
   Restyles the .arena-results-overlay with the same Vein language used
   on the stranger-win + prefight overlays:
   - Floating gold embers behind the modal
   - Gold corner brackets on the modal frame
   - Cormorant italic title
   - Blood-red primary CTA, gold ghost CTA
   - Dark deep bg + subtle gold inner glow
   These rules are scoped to .arena-results-overlay so other modals on
   the page are unaffected. */

.arena-results-overlay {
  background: rgba(10, 8, 6, 0.94);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Inner modal can exceed viewport on long XP/banner copy. Without
     this the bottom CTAs are unreachable on a phone. -webkit prefix
     keeps iOS Safari momentum scroll behavior. */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Ember layer — full-overlay, rises behind the modal */
.arena-results__embers {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.arena-results__ember {
  position: absolute;
  bottom: -10px;
  width: 3px;
  height: 3px;
  background: var(--blindspot-accent-gold, #F5C078);
  border-radius: 50%;
  opacity: 0;
  box-shadow: 0 0 8px rgba(245, 192, 120, 0.55);
  animation: arena-results-ember 5s ease-in-out infinite;
}
@keyframes arena-results-ember {
  0%   { opacity: 0; transform: translateY(0) scale(0.5); }
  35%  { opacity: 0.55; }
  100% { opacity: 0; transform: translateY(-260px) scale(0); }
}
@media (prefers-reduced-motion: reduce) {
  .arena-results__ember { animation: none; opacity: 0; }
}

/* Modal frame — keep the existing layout but swap colors + chrome */
.bs-page .arena-results-overlay .arena-results,
.arena-results-overlay .arena-results {
  position: relative;
  z-index: 1;
  background: linear-gradient(180deg,
    rgba(28, 16, 13, 0.92) 0%,
    rgba(13, 8, 7, 0.96) 100%);
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  border-radius: 2px;
  box-shadow:
    0 0 32px rgba(245, 192, 120, 0.18),
    inset 0 0 24px rgba(245, 192, 120, 0.05);
  padding: 2.25rem 1.75rem 1.5rem;
}

/* Gold corner brackets — same treatment as stranger-win */
.arena-results__corner {
  position: absolute;
  width: 28px;
  height: 28px;
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  opacity: 0.7;
  pointer-events: none;
  z-index: 2;
}
.arena-results__corner--tl { top: 0; left: 0; border-right: none; border-bottom: none; }
.arena-results__corner--tr { top: 0; right: 0; border-left: none; border-bottom: none; }
.arena-results__corner--bl { bottom: 0; left: 0; border-right: none; border-top: none; }
.arena-results__corner--br { bottom: 0; right: 0; border-left: none; border-top: none; }

/* Title — italic Cinzel with gold glow, matches Vein voice */
.bs-page .arena-results-overlay .arena-results__banner h2,
.bs-page .arena-results-overlay .arena-results__banner h1,
.arena-results-overlay .arena-results__banner h2,
.arena-results-overlay .arena-results__banner h1 {
  font-family: 'Cormorant Garamond', 'Cinzel', serif;
  font-style: italic;
  font-weight: 600;
  font-size: 2rem;
  letter-spacing: 0.02em;
  color: var(--blindspot-accent-gold, #F5C078);
  text-shadow: 0 0 18px rgba(245, 192, 120, 0.4);
  margin: 0.5rem 0 0.4rem;
}
.bs-page .arena-results-overlay .arena-results__banner p,
.arena-results-overlay .arena-results__banner p {
  font-family: var(--blindspot-font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blindspot-text-dim, #B89A82);
}

/* XP amount — same gold accent, weightier */
.bs-page .arena-results-overlay .arena-results__xp-amount,
.arena-results-overlay .arena-results__xp-amount {
  color: var(--blindspot-accent-gold, #F5C078);
  text-shadow: 0 0 12px rgba(245, 192, 120, 0.35);
  font-family: var(--blindspot-font-display, 'Cinzel', serif);
  font-size: 1.15rem;
  letter-spacing: 0.06em;
}

/* Close button — gold hover */
.arena-results-overlay .arena-results__close {
  color: var(--blindspot-text-dim, #B89A82);
  transition: color 200ms ease;
}
.arena-results-overlay .arena-results__close:hover {
  color: var(--blindspot-accent-gold, #F5C078);
}

/* CTAs — primary blood-red, ghost gold-rim */
.arena-results-overlay .arena-results__actions .arena-btn--primary,
.arena-results-overlay #arena-results-again {
  background: linear-gradient(180deg, var(--blindspot-accent, #C8302C), #8E211E);
  border: 1px solid var(--blindspot-accent, #C8302C);
  color: #ffffff;
  font-family: var(--blindspot-font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  padding: 0.65rem 1.4rem;
  border-radius: 2px;
  box-shadow: 0 0 18px rgba(200, 48, 44, 0.4);
  transition: all 200ms ease;
}
.arena-results-overlay .arena-results__actions .arena-btn--primary:hover,
.arena-results-overlay #arena-results-again:hover {
  box-shadow: 0 0 26px rgba(200, 48, 44, 0.6);
  transform: translateY(-1px);
}
.arena-results-overlay .arena-results__actions .arena-btn--ghost,
.arena-results-overlay #arena-results-lobby {
  background: transparent;
  border: 1px solid var(--blindspot-accent-gold-dim, #B97417);
  color: var(--blindspot-accent-gold, #F5C078);
  font-family: var(--blindspot-font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 0.65rem 1.4rem;
  border-radius: 2px;
  transition: all 200ms ease;
}
.arena-results-overlay .arena-results__actions .arena-btn--ghost:hover,
.arena-results-overlay #arena-results-lobby:hover {
  background: rgba(245, 192, 120, 0.08);
  border-color: var(--blindspot-accent-gold, #F5C078);
}

/* XP bar — gold fill on dark track */
.arena-results-overlay .arena-progress__bar {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--blindspot-border-2, #4F2A23);
  border-radius: 2px;
  height: 10px;
}
.arena-results-overlay .arena-progress__bar-fill {
  background: linear-gradient(90deg, var(--blindspot-accent-gold-dim, #B97417), var(--blindspot-accent-gold, #F5C078));
  box-shadow: 0 0 12px rgba(245, 192, 120, 0.4);
}

/* Stat readouts — keep numbers but tint labels in mono */
.arena-results-overlay .arena-results__stat-label,
.arena-results-overlay [class*="arena-results__stat"] {
  font-family: var(--blindspot-font-mono);
  letter-spacing: 0.14em;
}

/* ============================================================
   2026-04-28 POLISH PASS — battle screen craft refinements
   Scope: battle context only (#bs-screen-battle.blindspot-battle
   + #bs-battle-container.blindspot-battle). Lobby / index / forge
   keep their current chrome. Each block is numbered to match the
   polish triage so future-you can find the intent.
   ============================================================ */

/* #1 — Move type-label is decorative + redundant with the footer
   `TYPE: ATTACK` badge. Hide in battle scope only. Lobby / index
   keep the eyebrow because there's no footer badge there. */
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__type-label,
#bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__type-label {
  display: none;
}

/* #2 — Energy badge: drop the "ENERGY" sub-label, keep just the
   number with a lightning glyph above. Tighter, less shouty,
   and the cost is the only thing that matters at a glance. */
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy-label,
#bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy-label {
  display: none;
}
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy,
#bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy {
  width: 36px;
  min-height: 36px;
  padding: 0;
  border-radius: 8px;
  position: relative;
  background: linear-gradient(180deg, #100806, #0a0604);
}
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy::before,
#bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy::before {
  content: '\f0e7'; /* fa-bolt */
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  position: absolute;
  top: 2px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.5rem;
  color: var(--blindspot-accent-gold, #F5C078);
  opacity: 0.55;
  line-height: 1;
}
#bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy-num,
#bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy-num {
  font-size: 1.05rem;
  margin-top: 0.4rem;
}

/* #4 — Battle log heading was kissing the top border. The
   `0.45rem` top padding was set when there was no head element;
   now that `<div class="arena-battle__log-head">Battle Log</div>`
   sits inside the scroll area, the head needs breathing room
   above OR sticky-top treatment so it doesn't scroll out with
   entries. We pin it to the top, opaque, and pad it. */
#bs-screen-battle.blindspot-battle .arena-battle__log,
#bs-battle-container.blindspot-battle .arena-battle__log {
  padding: 0 0.85rem 1rem;
  position: relative;
}
#bs-screen-battle.blindspot-battle .arena-battle__log-head,
#bs-battle-container.blindspot-battle .arena-battle__log-head {
  position: sticky;
  top: 0;
  z-index: 2;
  margin: 0 -0.85rem 0.5rem;
  padding: 0.6rem 0.85rem 0.4rem;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.92) 0%, rgba(0, 0, 0, 0.92) 60%, rgba(0, 0, 0, 0) 100%);
  border-bottom: 1px solid rgba(245, 192, 120, 0.12);
}

/* #5 — Help / Forfeit utility buttons get visible mono-caps
   labels under each so they read as proper utility actions
   instead of mystery icons. Stack icon-over-label without
   blowing up the click target. */
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils {
  gap: 1rem;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn {
  flex-direction: column;
  width: 52px;
  height: 48px;
  min-width: 52px;
  gap: 0.18rem;
  padding: 0.3rem 0;
}
#bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::after,
#bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::after {
  content: attr(aria-label);
  font-family: var(--blindspot-font-mono);
  font-size: 0.46rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: inherit;
  opacity: 0.7;
  line-height: 1;
}
#bs-screen-battle.blindspot-battle #bs-combat-help-btn::after,
#bs-battle-container.blindspot-battle #bs-combat-help-btn::after {
  content: 'Guide';
}
#bs-screen-battle.blindspot-battle #arena-forfeit-btn::after,
#bs-battle-container.blindspot-battle #arena-forfeit-btn::after {
  content: 'Forfeit';
}

/* #6 — Dead space above the field. `.arena-battle__field` had
   25px top margin from the topbar. The round-counter pill +
   VS glyph already provide the breathing room; cut to 12px. */
#bs-screen-battle.blindspot-battle .arena-battle__field,
#bs-battle-container.blindspot-battle .arena-battle__field {
  margin-top: 12px;
}

/* #7 — Ability charge "0/2" text pip read like a notification
   badge. Replace with a 2-pip dot row that mirrors the existing
   `bs-move-card__dot` motif used in the move-card footer. JS
   keeps writing to the span (back-compat); CSS hides the text
   and renders pips via data attributes set by the JS update.

   Visual: two stacked dots, top-right corner of the ability
   move card. Filled when charge available, hollow when used. */
#bs-screen-battle.blindspot-battle .arena-move-btn--ability,
#bs-battle-container.blindspot-battle .arena-move-btn--ability {
  position: relative;
}
/* Sits in the header band, just left of the energy badge. Frees the
   FX art panel of overlay UI so Wild Card / class-variant ability art
   reads at the same visual scale as the other four moves. left/right
   are both reset so the inherited blindspot.css rule's left:0.95rem
   doesn't stretch the absolute box. */
#bs-screen-battle.blindspot-battle .arena-move-btn__charge,
#bs-battle-container.blindspot-battle .arena-move-btn__charge {
  position: absolute;
  top: 1rem;
  left: auto;
  right: 5rem;
  bottom: auto;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.3rem;
  font-size: 0;
  color: transparent;
  background: transparent;
  border: 0;
  padding: 0;
  pointer-events: none;
  z-index: 3;
}
@media (max-height: 949px) {
  #bs-screen-battle.blindspot-battle .arena-move-btn__charge,
  #bs-battle-container.blindspot-battle .arena-move-btn__charge {
    top: 0.85rem;
    right: 4.5rem;
  }
}
@media (max-height: 800px) {
  #bs-screen-battle.blindspot-battle .arena-move-btn__charge,
  #bs-battle-container.blindspot-battle .arena-move-btn__charge {
    top: 0.7rem;
    right: 4rem;
  }
}
#bs-screen-battle.blindspot-battle .arena-move-btn__charge::before,
#bs-screen-battle.blindspot-battle .arena-move-btn__charge::after,
#bs-battle-container.blindspot-battle .arena-move-btn__charge::before,
#bs-battle-container.blindspot-battle .arena-move-btn__charge::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid var(--blindspot-epic, #b47cf5);
  background: transparent;
  transition: background 200ms ease, box-shadow 200ms ease;
}
/* Filled state — JS toggles data-charge="N/N" via existing
   updateAbilityCharges; we read the leading digit. Default
   to empty (no fill) until JS writes the attribute. */
#bs-screen-battle.blindspot-battle .arena-move-btn__charge[data-filled="1"]::before,
#bs-battle-container.blindspot-battle .arena-move-btn__charge[data-filled="1"]::before,
#bs-screen-battle.blindspot-battle .arena-move-btn__charge[data-filled="2"]::before,
#bs-battle-container.blindspot-battle .arena-move-btn__charge[data-filled="2"]::before {
  background: var(--blindspot-epic, #b47cf5);
  box-shadow: 0 0 8px rgba(180, 124, 245, 0.55);
}
#bs-screen-battle.blindspot-battle .arena-move-btn__charge[data-filled="2"]::after,
#bs-battle-container.blindspot-battle .arena-move-btn__charge[data-filled="2"]::after {
  background: var(--blindspot-epic, #b47cf5);
  box-shadow: 0 0 8px rgba(180, 124, 245, 0.55);
}

/* #8 — Hype meter at 0%. The empty track read as static. Add
   a slow diagonal sheen that sweeps across the empty track so
   the meter signals "this is alive but unfilled" instead of
   "broken UI." Stops once any fill exists. */
@keyframes bs-hype-empty-sheen {
  0%   { transform: translateX(-30%); opacity: 0; }
  35%  { opacity: 0.5; }
  65%  { opacity: 0.5; }
  100% { transform: translateX(130%); opacity: 0; }
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__track,
#bs-battle-container.blindspot-battle .arena-hype-bar__track {
  position: relative;
  overflow: hidden;
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__track::after,
#bs-battle-container.blindspot-battle .arena-hype-bar__track::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(110deg,
    transparent 30%,
    rgba(216, 169, 255, 0.22) 48%,
    rgba(216, 169, 255, 0.4) 50%,
    rgba(216, 169, 255, 0.22) 52%,
    transparent 70%);
  animation: bs-hype-empty-sheen 3.6s ease-in-out infinite;
  z-index: 1;
}
/* Hide the sheen as soon as any real fill exists. The fill
   element gets inline width:%; we key on width != "0%" via
   a sibling selector. */
#bs-screen-battle.blindspot-battle .arena-hype-bar__track:has(.arena-hype-bar__fill[style*="width: 0"])::after,
#bs-battle-container.blindspot-battle .arena-hype-bar__track:has(.arena-hype-bar__fill[style*="width: 0"])::after {
  /* Only animate when fill is at 0% */
}
#bs-screen-battle.blindspot-battle .arena-hype-bar__track:not(:has(.arena-hype-bar__fill[style*="width: 0%"]))::after,
#bs-battle-container.blindspot-battle .arena-hype-bar__track:not(:has(.arena-hype-bar__fill[style*="width: 0%"]))::after {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  #bs-screen-battle.blindspot-battle .arena-hype-bar__track::after,
  #bs-battle-container.blindspot-battle .arena-hype-bar__track::after {
    animation: none;
    opacity: 0.18;
  }
}

/* #9 — HP/stamina rails read as floating dark slabs decoupled
   from the gold-bordered card frame. Match the rail border to
   the frame's gold-border color (lighter than border-2) so
   the rails feel like part of the same chrome. Keeps the
   dynamic HP-tier panel border (red/amber/green) on the
   panel itself untouched; just polishes the rail container. */
#bs-screen-battle.blindspot-battle .arena-hp-bar,
#bs-battle-container.blindspot-battle .arena-hp-bar,
#bs-screen-battle.blindspot-battle .arena-stamina-bar,
#bs-battle-container.blindspot-battle .arena-stamina-bar {
  border-color: rgba(245, 192, 120, 0.32);
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(0, 0, 0, 0.4);
}

/* #10 (revised) — Active buff chips (`+5 XP`, `+3 CRIT`, `+3 AP`)
   live below the player card. Boss card has trait chips
   (`Fortified Start`, `First Blood`) inside the rendered card.
   They're both "passive effects active during fight" but read
   as different UI categories. Restyle the buff chips to match
   the boss trait chip family — same bordered pill, same gold
   tint, same mono-caps treatment — so the player reads both
   sides as one system. */
#bs-screen-battle.blindspot-battle .arena-buff-chip,
#bs-battle-container.blindspot-battle .arena-buff-chip {
  font-family: var(--blindspot-font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
  background: rgba(245, 192, 120, 0.08);
  border: 1px solid rgba(245, 192, 120, 0.32);
  color: var(--blindspot-accent-gold, #F5C078);
  line-height: 1;
  white-space: nowrap;
}
#bs-screen-battle.blindspot-battle .arena-buff-chip i,
#bs-battle-container.blindspot-battle .arena-buff-chip i {
  font-size: 0.7rem;
  color: var(--blindspot-accent-gold, #F5C078);
  opacity: 0.85;
}
#bs-screen-battle.blindspot-battle .arena-player-buffs,
#bs-battle-container.blindspot-battle .arena-player-buffs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: center;
  margin: 0.5rem 0 0.25rem;
  padding: 0 0.5rem;
}
#bs-screen-battle.blindspot-battle .arena-player-buffs:empty,
#bs-battle-container.blindspot-battle .arena-player-buffs:empty {
  display: none;
}

/* #3 — Boss-card stat values get a subtle "/10" suffix so the
   player reads them as tier values, not direct comparisons to
   their own 0-100 stats. The renderer in bs-boss-card.js wraps
   the suffix in `.bs-rc-stat__val-max`. */
#bs-screen-battle.blindspot-battle .bs-rc-stat__val-max,
#bs-battle-container.blindspot-battle .bs-rc-stat__val-max {
  font-size: 0.7em;
  opacity: 0.5;
  margin-left: 0.05em;
  font-weight: 400;
}

/* #11 — Player trait chips (sketch). bs-card-renderer renders two
   trait pills inside the player card: signature ability + play
   pattern. Mirrors the boss-card .bs-rc-traits pattern but
   gold-tinted to harmonize with the player card's gold chrome
   (boss uses red — same shape, side-appropriate color). The
   panel-level buff chip strip stays gold-outlined too but is
   content-distinguished by the leading `+N` numeric prefix. */
#bs-screen-battle.blindspot-battle .bs-rc-traits--player,
#bs-battle-container.blindspot-battle .bs-rc-traits--player {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  padding: 0.3rem 0.5rem 0.5rem;
  margin: 0;
  border-top: 1px solid var(--blindspot-border, #3A1F1A);
  background: rgba(0, 0, 0, 0.25);
}
#bs-screen-battle.blindspot-battle .bs-rc-traits--player:empty,
#bs-battle-container.blindspot-battle .bs-rc-traits--player:empty {
  display: none;
}
#bs-screen-battle.blindspot-battle .bs-rc-trait--player,
#bs-battle-container.blindspot-battle .bs-rc-trait--player {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  font-family: var(--blindspot-font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  padding: 0.18rem 0.5rem;
  border-radius: var(--blindspot-radius-pill, 999px);
  border: 1px solid rgba(245, 192, 120, 0.5);
  background: rgba(13, 8, 7, 0.55);
  color: var(--blindspot-accent-gold, #F5C078);
  white-space: nowrap;
}
#bs-screen-battle.blindspot-battle .bs-rc-trait--player i,
#bs-battle-container.blindspot-battle .bs-rc-trait--player i {
  color: var(--blindspot-accent-gold, #F5C078);
  opacity: 0.85;
  font-size: 0.7em;
}

/* ──────────────────────────────────────────────────────────────────
   MOVE-CARD CLICK FEEDBACK
   When a player presses a move, JS adds .arena-move-btn--pressed for
   ~320ms, triggering this one-shot burst on the card's art panel so
   every move has tactile feedback. Combo trigger flash still handled
   separately by .bs-move-card__dots--combo-triggered.
   ────────────────────────────────────────────────────────────────── */
/* Hold-and-release tactile press. Mouse down triggers :active
   which holds the card in a depressed state (quick transition
   into it). Mouse up: JS adds .arena-move-btn--pressed which
   plays the spring-pop release animation, then commits the move. */

/* Held state — depressed while mouse button (or finger) is down.
   Quick ease-in transition so the button feels like it's getting
   pushed; no spring on the way down. Selector matches the production
   hover rule's ID-prefix specificity (1,3,0) so this wins the cascade
   against .arena-move-btn:hover when both apply. */
#bs-screen-battle.blindspot-battle .arena-move-btn:active:not(:disabled):not(.arena-move-btn--no-stamina):not(.arena-move-btn--exhausted),
#bs-battle-container.blindspot-battle .arena-move-btn:active:not(:disabled):not(.arena-move-btn--no-stamina):not(.arena-move-btn--exhausted),
.bs-screen.blindspot-battle .arena-move-btn:active:not(:disabled):not(.arena-move-btn--no-stamina):not(.arena-move-btn--exhausted) {
  transform: scale(0.94) translateY(3px);
  transition: transform 140ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Release pop. Starts from the depressed state (matching :active),
   springs up with overshoot, settles to rest. Snappy curve gives
   the satisfying "snap" of a real mechanical key bouncing back. */
.bs-page .arena-move-btn--pressed {
  animation: bs-move-card-press-physical 320ms cubic-bezier(0.34, 1.7, 0.64, 1);
}
@keyframes bs-move-card-press-physical {
  0%   { transform: scale(0.94) translateY(3px); }
  35%  { transform: scale(1.05) translateY(-3px); }
  65%  { transform: scale(0.99) translateY(0); }
  100% { transform: scale(1)    translateY(0); }
}

/* Art panel: brightness pump + inset accent-glow burst. The
   --bs-move-color custom prop is per-move (orange Strike, cyan
   Guard, violet Ability, mint Heal, gold Counter), so the press
   feedback is color-coded to which move ignited. The whole-button
   animation above handles the physical depression, so this rule
   no longer animates transform — we just do the visual energy. */
.bs-page .bs-move-card.arena-move-btn--pressed .bs-move-card__art {
  animation: bs-move-card-press-burst 320ms ease-out;
}
@keyframes bs-move-card-press-burst {
  0%   { filter: brightness(1)    saturate(1);
         box-shadow: inset 0 0 0 0 transparent; }
  18%  { filter: brightness(1.55) saturate(1.5);
         box-shadow: inset 0 0 36px 6px var(--bs-move-color, rgba(255,255,255,0.7)); }
  55%  { filter: brightness(1.18) saturate(1.18);
         box-shadow: inset 0 0 18px 3px var(--bs-move-color, rgba(255,255,255,0.4)); }
  100% { filter: brightness(1)    saturate(1);
         box-shadow: inset 0 0 0 0 transparent; }
}

/* ──────────────────────────────────────────────────────────────────
   MOVE-CARD CSS-DRIVEN ART SLOTS (replacing broken VP9 WebM videos)
   Each move gets a distinct motion grammar; all use distributed
   transparent/outlined elements (no single dominant shape):
     heal    — drifting bubbles (vertical drift, 7 hollow bubbles)
     strike  — speed lines (L→R sweep, 5 thin gradient streaks)
     guard   — concentric ripples (center-out scale, 5 rings)
     ability — scattered twinkles (fade in/out at varied positions)
     counter — pendulum arcs (L↔R swing at 3 vertical positions)
   ────────────────────────────────────────────────────────────────── */

/* Heal — drifting bubbles */
.bs-page .bs-move-card__art--heal {
  background:
    radial-gradient(ellipse at center,
      rgba(74, 222, 128, 0.22) 0%,
      rgba(34, 100, 60, 0.32) 45%,
      rgba(8, 28, 14, 0.95) 100%);
  background-color: #051410;
  overflow: hidden;
  isolation: isolate;
}
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble {
  position: absolute;
  bottom: -12%;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid rgba(190, 255, 210, 0.7);
  box-shadow:
    inset 1px 1px 1.5px rgba(255, 255, 255, 0.55),
    inset -1px -1px 1.5px rgba(74, 222, 128, 0.18),
    0 0 6px rgba(74, 222, 128, 0.45);
  animation: bs-fx-heal-bubble-drift 4.5s ease-in infinite;
  pointer-events: none;
  z-index: 2;
}
/* Pulse element is span 1; bubbles occupy spans 2-8 */
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(2) { left:  8%; width: 10px; height: 10px; animation-delay: 0s;    animation-duration: 4.4s; --bs-drift-x: -5px; }
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(3) { left: 22%; width:  6px; height:  6px; animation-delay: 0.8s;  animation-duration: 3.6s; --bs-drift-x:  4px; }
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(4) { left: 36%; width: 12px; height: 12px; animation-delay: 1.6s;  animation-duration: 5.0s; --bs-drift-x: -3px; }
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(5) { left: 50%; width:  7px; height:  7px; animation-delay: 2.4s;  animation-duration: 4.0s; --bs-drift-x:  6px; }
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(6) { left: 64%; width: 11px; height: 11px; animation-delay: 0.4s;  animation-duration: 4.8s; --bs-drift-x: -4px; }
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(7) { left: 78%; width:  8px; height:  8px; animation-delay: 1.2s;  animation-duration: 3.8s; --bs-drift-x:  5px; }
.bs-page .bs-move-card__art--heal .bs-fx-heal__bubble:nth-of-type(8) { left: 92%; width: 10px; height: 10px; animation-delay: 2.0s;  animation-duration: 4.6s; --bs-drift-x: -6px; }

/* Heal infusion pulse — periodic center glow surge every ~5s. The
   bubbles already drift continuously; this adds a "moment of
   gravity" peak so Heal feels like a decision, not a passive. */
.bs-page .bs-move-card__art--heal .bs-fx-heal__pulse {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 60%;
  aspect-ratio: 2 / 1;
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
    rgba(150, 255, 190, 0.4) 0%,
    rgba(74, 222, 128, 0.2) 35%,
    transparent 70%);
  transform: translate(-50%, -50%) scale(0.7);
  opacity: 0;
  pointer-events: none;
  z-index: 1;
  mix-blend-mode: screen;
  animation: bs-fx-heal-pulse 5s ease-in-out infinite;
}
@keyframes bs-fx-heal-pulse {
  0%, 70%, 100% { opacity: 0;   transform: translate(-50%, -50%) scale(0.7); }
  82%           { opacity: 0.9; transform: translate(-50%, -50%) scale(1.1); }
  92%           { opacity: 0.4; transform: translate(-50%, -50%) scale(1.25); }
}

@keyframes bs-fx-heal-bubble-drift {
  0%   { bottom: -12%; opacity: 0;    transform: translateX(0); }
  15%  {                opacity: 0.9; }
  85%  {                opacity: 0.8; }
  100% { bottom: 112%; opacity: 0;    transform: translateX(var(--bs-drift-x, 0)); }
}

/* Hover — bubbles rise faster (~half duration), pulse cycle tightens too */
.bs-page .bs-move-card.arena-move-btn--heal:hover:not(:disabled) .bs-fx-heal__bubble {
  animation-duration: 2.4s;
}
.bs-page .bs-move-card.arena-move-btn--heal:hover:not(:disabled) .bs-fx-heal__pulse {
  animation-duration: 2.6s;
}

/* Reduced motion — freeze bubbles in mid-rise as a static composition */
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--heal .bs-fx-heal__bubble { animation: none; opacity: 0.75; bottom: 50%; }
  .bs-page .bs-move-card__art--heal .bs-fx-heal__pulse  { animation: none; opacity: 0; }
}

/* Strike — kinetic speed lines (5 sharp red streaks sweeping L→R).
   Tightened timing + sharper gradient edges so the motion reads
   punchy, not lens-flare-soft. The middle streak (nth 3) is the
   lead — thicker, brighter, stronger glow — to give the eye an
   anchor rather than five equally-faint streaks. */
.bs-page .bs-move-card__art--strike {
  background:
    radial-gradient(ellipse at center,
      rgba(220, 60, 60, 0.18) 0%,
      rgba(80, 20, 20, 0.32) 45%,
      rgba(28, 8, 8, 0.95) 100%);
  background-color: #1a0808;
  overflow: hidden;
  isolation: isolate;
}
.bs-page .bs-move-card__art--strike .bs-fx-strike__streak {
  position: absolute;
  left: -60%;
  width: 65%;
  height: 1.5px;
  /* Sharper gradient — narrow fade at the edges, hard-bright core */
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 110, 110, 0) 14%,
    rgba(255, 130, 130, 1) 32%,
    rgba(255, 90, 90, 1) 50%,
    rgba(255, 130, 130, 1) 68%,
    rgba(255, 110, 110, 0) 86%,
    transparent 100%);
  box-shadow: 0 0 4px rgba(255, 80, 80, 0.65);
  transform: rotate(-10deg);
  transform-origin: left center;
  animation: bs-fx-strike-streak 1.5s linear infinite;
  pointer-events: none;
  z-index: 2;
}
.bs-page .bs-move-card__art--strike .bs-fx-strike__streak:nth-of-type(1) { top: 18%; height: 1.5px; animation-delay: 0s;    animation-duration: 1.5s; }
.bs-page .bs-move-card__art--strike .bs-fx-strike__streak:nth-of-type(2) { top: 36%; height:   1px; animation-delay: 0.35s; animation-duration: 1.3s; opacity: 0.7; }
/* Lead streak — thicker, brighter, longer reach, strongest glow */
.bs-page .bs-move-card__art--strike .bs-fx-strike__streak:nth-of-type(3) {
  top: 54%;
  height: 2.5px;
  width: 72%;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 200, 200, 0) 10%,
    rgba(255, 240, 220, 1) 28%,
    rgba(255, 80, 80, 1) 50%,
    rgba(255, 240, 220, 1) 72%,
    rgba(255, 200, 200, 0) 90%,
    transparent 100%);
  box-shadow: 0 0 8px rgba(255, 90, 90, 0.85), 0 0 16px rgba(255, 60, 60, 0.4);
  animation-delay: 0.7s;
  animation-duration: 1.2s;
}
.bs-page .bs-move-card__art--strike .bs-fx-strike__streak:nth-of-type(4) { top: 72%; height: 1.5px; animation-delay: 1.0s;  animation-duration: 1.4s; }
.bs-page .bs-move-card__art--strike .bs-fx-strike__streak:nth-of-type(5) { top: 88%; height:   1px; animation-delay: 0.55s; animation-duration: 1.5s; opacity: 0.7; }

@keyframes bs-fx-strike-streak {
  0%   { left: -60%; opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { left: 110%; opacity: 0; }
}
.bs-page .bs-move-card.arena-move-btn--strike:hover:not(:disabled) .bs-fx-strike__streak {
  animation-duration: 0.65s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--strike .bs-fx-strike__streak { animation: none; left: 30%; opacity: 0.6; }
}

/* Guard — concentric ripples (5 blue rings expanding from center) */
.bs-page .bs-move-card__art--guard {
  background:
    radial-gradient(ellipse at center,
      rgba(60, 140, 220, 0.20) 0%,
      rgba(20, 60, 100, 0.32) 45%,
      rgba(8, 14, 28, 0.95) 100%);
  background-color: #050b18;
  overflow: hidden;
  isolation: isolate;
}
.bs-page .bs-move-card__art--guard .bs-fx-guard__ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid rgba(140, 200, 255, 0.85);
  box-shadow:
    0 0 8px rgba(80, 160, 255, 0.5),
    inset 0 0 4px rgba(180, 220, 255, 0.3);
  transform: translate(-50%, -50%) scale(0.3);
  animation: bs-fx-guard-ring 3.2s ease-out infinite;
  pointer-events: none;
  z-index: 2;
}
.bs-page .bs-move-card__art--guard .bs-fx-guard__ring:nth-of-type(1) { animation-delay: 0s;    }
.bs-page .bs-move-card__art--guard .bs-fx-guard__ring:nth-of-type(2) { animation-delay: 0.65s; }
.bs-page .bs-move-card__art--guard .bs-fx-guard__ring:nth-of-type(3) { animation-delay: 1.3s;  }
.bs-page .bs-move-card__art--guard .bs-fx-guard__ring:nth-of-type(4) { animation-delay: 1.95s; }
.bs-page .bs-move-card__art--guard .bs-fx-guard__ring:nth-of-type(5) { animation-delay: 2.6s;  }

@keyframes bs-fx-guard-ring {
  0%   { transform: translate(-50%, -50%) scale(0.3); opacity: 0; border-width: 2px; }
  15%  { opacity: 0.95; }
  100% { transform: translate(-50%, -50%) scale(8); opacity: 0; border-width: 0.5px; }
}
.bs-page .bs-move-card.arena-move-btn--guard:hover:not(:disabled) .bs-fx-guard__ring {
  animation-duration: 1.6s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--guard .bs-fx-guard__ring { animation: none; opacity: 0.5; transform: translate(-50%, -50%) scale(2.5); }
}

/* Ability — scattered twinkles (7 hollow purple dots fading in/out) */
.bs-page .bs-move-card__art--ability {
  background:
    radial-gradient(ellipse at center,
      rgba(140, 80, 220, 0.22) 0%,
      rgba(60, 30, 100, 0.32) 45%,
      rgba(18, 8, 30, 0.95) 100%);
  background-color: #100618;
  overflow: hidden;
  isolation: isolate;
}

/* Default-ability core — small purple orb, breathes. The "no class
   chosen" state. Variant treatments (powerstrike/arcaneblast/etc)
   replace this whole panel via JS innerHTML swap. */
.bs-page .bs-move-card__art--ability .bs-fx-ability__core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    rgba(230, 200, 255, 0.95) 0%,
    rgba(180, 100, 255, 0.8) 35%,
    rgba(110, 60, 180, 0.4) 70%,
    transparent 100%);
  box-shadow:
    0 0 12px rgba(180, 100, 255, 0.7),
    0 0 24px rgba(140, 70, 220, 0.4);
  transform: translate(-50%, -50%) scale(0.85);
  animation: bs-fx-ability-core 2.4s ease-in-out infinite;
  pointer-events: none;
  z-index: 1;
}
@keyframes bs-fx-ability-core {
  0%, 100% { transform: translate(-50%, -50%) scale(0.85); filter: brightness(0.95); }
  50%      { transform: translate(-50%, -50%) scale(1.1);  filter: brightness(1.3); }
}

.bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid rgba(210, 160, 255, 0.85);
  box-shadow:
    0 0 6px rgba(180, 100, 255, 0.65),
    inset 0 0 2px rgba(220, 180, 255, 0.45);
  opacity: 0;
  animation: bs-fx-ability-twinkle 3.6s ease-in-out infinite;
  pointer-events: none;
  z-index: 2;
}
/* Core is span 1; twinkles are spans 2-6 (5 of them, scattered around the core) */
.bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle:nth-of-type(2) { left: 14%; top: 28%; width: 5px; height: 5px; animation-delay: 0s;   animation-duration: 3.4s; }
.bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle:nth-of-type(3) { left: 28%; top: 72%; width: 4px; height: 4px; animation-delay: 0.7s; animation-duration: 4.0s; }
.bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle:nth-of-type(4) { left: 72%; top: 20%; width: 6px; height: 6px; animation-delay: 1.4s; animation-duration: 3.6s; }
.bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle:nth-of-type(5) { left: 86%; top: 68%; width: 5px; height: 5px; animation-delay: 0.4s; animation-duration: 4.2s; }
.bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle:nth-of-type(6) { left: 92%; top: 38%; width: 4px; height: 4px; animation-delay: 2.0s; animation-duration: 3.8s; }

@keyframes bs-fx-ability-twinkle {
  0%, 100% { opacity: 0;   transform: scale(0.6); }
  30%      { opacity: 1;   transform: scale(1.2); }
  60%      { opacity: 0.6; transform: scale(1);   }
}
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__twinkle {
  animation-duration: 1.8s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--ability .bs-fx-ability__core    { animation: none; transform: translate(-50%, -50%) scale(1); }
  .bs-page .bs-move-card__art--ability .bs-fx-ability__twinkle { animation: none; opacity: 0.7; transform: scale(1); }
}

/* Counter — Catch-and-throw. The animation IS the rules text:
   incoming amber dot glides from the right edge toward center →
   center spark ignites on impact (the "Flash") → an outgoing trail
   accelerates from center back out the right edge (the deflection).
   Full cycle runs continuously on a 4.5s loop in idle so a player
   sitting in hand for 30s still sees the mechanic teach itself. On
   hover the cycle halves to 2.2s — same motion grammar, just more
   urgent. Color: #ffd040 (warm yellow). All CSS, no JS. */
.bs-page .bs-move-card__art--counter {
  background: radial-gradient(ellipse at center, #4d2e10 0%, #2c1d0a 100%);
  background-color: #2c1d0a;
  overflow: hidden;
  isolation: isolate;
}

/* EMBER — always-on small amber glow at the parry point. Base
   opacity 0.3 (never invisible), brightens to 0.85 on impact, settles
   back. This guarantees the panel is never fully blank — even between
   the outgoing exit and the next incoming, the ember holds the eye. */
.bs-page .bs-move-card__art--counter .bs-fx-counter__ember {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(255, 220, 130, 0.55);
  box-shadow:
    0 0 6px rgba(255, 208, 64, 0.5),
    0 0 12px rgba(255, 208, 64, 0.25);
  transform: translate(-50%, -50%) scale(0.85);
  opacity: 0.35;
  pointer-events: none;
  z-index: 1;
  animation: bs-fx-counter-ember 4.5s ease-in-out infinite;
}
@keyframes bs-fx-counter-ember {
  0%, 100% { opacity: 0.35; transform: translate(-50%, -50%) scale(0.85); }
  44%      { opacity: 0.85; transform: translate(-50%, -50%) scale(1.2);  }
  60%      { opacity: 0.5;  transform: translate(-50%, -50%) scale(1);    }
}

/* INCOMING — bigger amber dot fades in at RIGHT edge, glides to
   center, then fades to 0 (absorbed by the parry). */
.bs-page .bs-move-card__art--counter .bs-fx-counter__incoming {
  position: absolute;
  top: 50%;
  left: 105%;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(255, 220, 130, 0.9);
  box-shadow: 0 0 10px rgba(255, 208, 64, 0.8);
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  animation: bs-fx-counter-incoming 4.5s ease-in-out infinite;
}
@keyframes bs-fx-counter-incoming {
  0%   { left: 105%; opacity: 0; }
  8%   { left:  96%; opacity: 0.7; }
  35%  { left:  50%; opacity: 1;   }
  42%  { left:  50%; opacity: 0;   }
  100% { left: 105%; opacity: 0;   }
}

/* SPARK — bigger center pip ignites at impact moment (≈40% of cycle).
   Bright burst, quick fade — the literal "Flash". */
.bs-page .bs-move-card__art--counter .bs-fx-counter__spark {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: rgba(255, 245, 200, 0.95);
  box-shadow:
    0 0 20px rgba(255, 220, 130, 0.95),
    0 0 40px rgba(255, 208, 64, 0.6);
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
  pointer-events: none;
  z-index: 3;
  animation: bs-fx-counter-spark 4.5s ease-in-out infinite;
}
@keyframes bs-fx-counter-spark {
  0%, 36%, 50%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(0); }
  40%                { opacity: 1; transform: translate(-50%, -50%) scale(1.6); }
  46%                { opacity: 0; transform: translate(-50%, -50%) scale(2.6); }
}

/* OUTGOING — longer bright trail fires from center toward and past
   the RIGHT edge — the deflection. Tail is brighter at the leading
   (right) edge so it reads as a projectile flying away. */
.bs-page .bs-move-card__art--counter .bs-fx-counter__outgoing {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 50px;
  height: 3.5px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 220, 130, 0) 5%,
    rgba(255, 230, 160, 0.85) 40%,
    rgba(255, 245, 200, 1) 95%,
    transparent 100%);
  box-shadow: 0 0 12px rgba(255, 208, 64, 0.85);
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  animation: bs-fx-counter-outgoing 4.5s ease-out infinite;
}
@keyframes bs-fx-counter-outgoing {
  0%, 42%, 100% { left:  50%; opacity: 0; }
  46%           { left:  52%; opacity: 1; }
  60%           { left:  75%; opacity: 1; }
  88%           { left: 108%; opacity: 0; }
}

/* SHARDS — 4 small ember particles radiate from center on impact and
   drift outward in different directions, fading as they go. They keep
   the panel alive between the outgoing exit and the next incoming —
   the "scatter of energy from the parry". Each shard reads its
   direction from CSS variables so one keyframe handles all 4. */
.bs-page .bs-move-card__art--counter .bs-fx-counter__shard {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(255, 235, 170, 0.95);
  box-shadow:
    0 0 6px rgba(255, 220, 130, 0.85),
    0 0 12px rgba(255, 208, 64, 0.4);
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  animation: bs-fx-counter-shard 4.5s ease-out infinite;
}
/* Four directions: up-right, down-right, up-left, down-left. The
   first three spans in the panel are ember/incoming/spark/outgoing,
   so shards are nth-of-type 5-8. Up-left/down-left are slightly
   delayed for a layered scatter feel. */
.bs-page .bs-move-card__art--counter .bs-fx-counter__shard:nth-of-type(5) { --shard-x:  44px; --shard-y: -22px; animation-delay: 0s;    }
.bs-page .bs-move-card__art--counter .bs-fx-counter__shard:nth-of-type(6) { --shard-x:  38px; --shard-y:  24px; animation-delay: 0s;    }
.bs-page .bs-move-card__art--counter .bs-fx-counter__shard:nth-of-type(7) { --shard-x: -32px; --shard-y: -20px; animation-delay: 0.1s;  width: 3px; height: 3px; }
.bs-page .bs-move-card__art--counter .bs-fx-counter__shard:nth-of-type(8) { --shard-x: -28px; --shard-y:  18px; animation-delay: 0.15s; width: 3px; height: 3px; }

@keyframes bs-fx-counter-shard {
  0%, 38%, 100% { opacity: 0; transform: translate(-50%, -50%) translate(0, 0)                                               scale(0.5); }
  44%           { opacity: 1; transform: translate(-50%, -50%) translate(calc(var(--shard-x, 0px) * 0.25), calc(var(--shard-y, 0px) * 0.25)) scale(1); }
  78%           { opacity: 0.7; transform: translate(-50%, -50%) translate(calc(var(--shard-x, 0px) * 0.75), calc(var(--shard-y, 0px) * 0.75)) scale(0.85); }
  98%           { opacity: 0.15; transform: translate(-50%, -50%) translate(var(--shard-x, 0px), var(--shard-y, 0px))        scale(0.5); }
}

/* Hover — same motion grammar, halved duration (more urgent feel) */
.bs-page .bs-move-card.arena-move-btn--counter:hover:not(:disabled) .bs-fx-counter__ember,
.bs-page .bs-move-card.arena-move-btn--counter:hover:not(:disabled) .bs-fx-counter__incoming,
.bs-page .bs-move-card.arena-move-btn--counter:hover:not(:disabled) .bs-fx-counter__spark,
.bs-page .bs-move-card.arena-move-btn--counter:hover:not(:disabled) .bs-fx-counter__outgoing,
.bs-page .bs-move-card.arena-move-btn--counter:hover:not(:disabled) .bs-fx-counter__shard {
  animation-duration: 2.2s;
}

/* Reduced motion — show the deflection mid-frame as a static tableau:
   ember at full glow, incoming dot near the right edge, outgoing
   trail mid-flight back out, shards mid-scatter. */
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--counter .bs-fx-counter__ember    { animation: none; opacity: 0.6; transform: translate(-50%, -50%) scale(1); }
  .bs-page .bs-move-card__art--counter .bs-fx-counter__incoming { animation: none; opacity: 0.7; left: 80%; }
  .bs-page .bs-move-card__art--counter .bs-fx-counter__spark    { animation: none; opacity: 0; }
  .bs-page .bs-move-card__art--counter .bs-fx-counter__outgoing { animation: none; opacity: 0.7; left: 65%; }
  .bs-page .bs-move-card__art--counter .bs-fx-counter__shard    { animation: none; opacity: 0.5; }
}

/* ──────────────────────────────────────────────────────────────────
   ABILITY VARIANTS — per-class signature move art
   The base ability slot (purple twinkles) is the no-class default.
   When a card class is picked, JS swaps in one of these variants:
     powerstrike  — red impact pulses (Fighter/Enforcer/Berserker)
     arcaneblast  — violet lightning forks (Caster/Scholar/Hacker)
     shadowstrike — dark cyan dashes (Scout/Rogue/Pilot)
     fortify      — gold shield facets (Guardian/Medic)
     wildcard     — chaotic multi-color flashes (Trickster/Wildcard)
   ────────────────────────────────────────────────────────────────── */

/* Power Strike — Heavy Slam. Central red core pulses + thick
   shockwave ring expands outward + 5 short impact spikes punch
   radially. Heavier visual weight than Spellburst's lightning bolts
   — feels like a fist impact, not a spell. */
.bs-page .bs-move-card__art--ability-powerstrike {
  background:
    radial-gradient(ellipse at center,
      rgba(255, 90, 60, 0.26) 0%,
      rgba(140, 35, 20, 0.36) 45%,
      rgba(40, 10, 6, 0.85) 100%);
  background-color: #1f0805;
  overflow: hidden;
  isolation: isolate;
}

/* Central red core */
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    rgba(255, 235, 200, 0.95) 0%,
    rgba(255, 110, 70, 0.9) 35%,
    rgba(180, 50, 30, 0.45) 70%,
    transparent 100%);
  box-shadow:
    0 0 16px rgba(255, 90, 50, 0.85),
    0 0 32px rgba(200, 50, 30, 0.5);
  transform: translate(-50%, -50%) scale(0.85);
  animation: bs-fx-powerstrike-core 1.6s ease-in-out infinite;
  pointer-events: none;
  z-index: 1;
}
@keyframes bs-fx-powerstrike-core {
  0%, 100% { transform: translate(-50%, -50%) scale(0.85); filter: brightness(0.9); }
  35%      { transform: translate(-50%, -50%) scale(1.25); filter: brightness(1.5); }
  60%      { transform: translate(-50%, -50%) scale(1);    filter: brightness(1.1); }
}

/* Shockwave ring — thick red ring expands outward at impact */
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__shockwave {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: transparent;
  border: 3px solid rgba(255, 130, 90, 0.95);
  box-shadow:
    0 0 12px rgba(255, 80, 50, 0.85),
    inset 0 0 6px rgba(255, 200, 170, 0.4);
  transform: translate(-50%, -50%) scale(0.3);
  opacity: 0;
  animation: bs-fx-powerstrike-shockwave 1.6s ease-out infinite;
  pointer-events: none;
  z-index: 2;
}
@keyframes bs-fx-powerstrike-shockwave {
  0%, 100% { transform: translate(-50%, -50%) scale(0.3); opacity: 0;   border-width: 3.5px; }
  30%      { transform: translate(-50%, -50%) scale(0.5); opacity: 1;   border-width: 3px; }
  85%      { transform: translate(-50%, -50%) scale(5.5); opacity: 0;   border-width: 0.5px; }
}

/* Impact spikes — 5 short thick red lines punch outward radially.
   Brief, percussive. CSS variable carries each spike's angle so a
   single keyframe handles all 5. Thicker + shorter than Spellburst
   bolts so they read as fist-impacts not lightning. */
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 28%;
  height: 4px;
  background: linear-gradient(90deg,
    rgba(255, 200, 160, 1) 0%,
    rgba(255, 110, 60, 0.95) 40%,
    rgba(200, 50, 30, 0.6) 80%,
    transparent 100%);
  box-shadow: 0 0 8px rgba(255, 90, 50, 0.85);
  border-radius: 2px;
  transform-origin: 0% 50%;
  opacity: 0;
  pointer-events: none;
  z-index: 3;
  animation: bs-fx-powerstrike-impact 1.6s ease-out infinite;
}
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact:nth-of-type(3) { --impact-angle:   0deg; animation-delay: 0s;    }
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact:nth-of-type(4) { --impact-angle:  72deg; animation-delay: 0.05s; }
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact:nth-of-type(5) { --impact-angle: 144deg; animation-delay: 0.1s;  }
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact:nth-of-type(6) { --impact-angle: 216deg; animation-delay: 0.15s; }
.bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact:nth-of-type(7) { --impact-angle: 288deg; animation-delay: 0.2s;  }

@keyframes bs-fx-powerstrike-impact {
  0%, 100% { opacity: 0;   transform: translateY(-50%) rotate(var(--impact-angle, 0deg)) scaleX(0); }
  25%      { opacity: 1;   transform: translateY(-50%) rotate(var(--impact-angle, 0deg)) scaleX(1); }
  55%      { opacity: 0.5; transform: translateY(-50%) rotate(var(--impact-angle, 0deg)) scaleX(1); }
  80%      { opacity: 0;   transform: translateY(-50%) rotate(var(--impact-angle, 0deg)) scaleX(1); }
}

.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__core,
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__shockwave,
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__impact {
  animation-duration: 0.8s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__core      { animation: none; transform: translate(-50%, -50%) scale(1); }
  .bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__shockwave { animation: none; opacity: 0.4; transform: translate(-50%, -50%) scale(2.5); }
  .bs-page .bs-move-card__art--ability-powerstrike .bs-fx-ability__impact    { animation: none; opacity: 0.6; transform: translateY(-50%) rotate(var(--impact-angle, 0deg)) scaleX(1); }
}

/* Arcane Blast — Spellburst. Central violet core pulses + 6 lightning
   bolts radiate outward from center to panel edge in sequence (60°
   apart, staggered 0.3s) so the cycle reads as a 360° starburst.
   Each bolt grows from the core via scaleX. CSS variable carries the
   per-bolt rotation angle so a single keyframe handles all 6. */
.bs-page .bs-move-card__art--ability-arcaneblast {
  background:
    radial-gradient(ellipse at center,
      rgba(180, 100, 255, 0.28) 0%,
      rgba(80, 40, 150, 0.36) 45%,
      rgba(28, 12, 50, 0.85) 100%);
  background-color: #18092a;
  overflow: hidden;
  isolation: isolate;
}

/* Central pulsing violet core */
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    rgba(245, 220, 255, 0.95) 0%,
    rgba(200, 130, 255, 0.85) 35%,
    rgba(140, 70, 220, 0.4) 70%,
    transparent 100%);
  box-shadow:
    0 0 16px rgba(200, 130, 255, 0.85),
    0 0 32px rgba(160, 80, 240, 0.45);
  transform: translate(-50%, -50%) scale(0.85);
  animation: bs-fx-arcaneblast-core 1.8s ease-in-out infinite;
  pointer-events: none;
  z-index: 1;
}
@keyframes bs-fx-arcaneblast-core {
  0%, 100% { transform: translate(-50%, -50%) scale(0.85); filter: brightness(0.95); }
  50%      { transform: translate(-50%, -50%) scale(1.2);  filter: brightness(1.4); }
}

/* Radiating bolts — anchored at center via transform-origin: 0% 50%,
   each rotates to its angle and scales-out from 0 to full panel-edge
   length in a quick crackle. */
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 50%;
  height: 2.5px;
  background: linear-gradient(90deg,
    rgba(245, 220, 255, 1) 0%,
    rgba(200, 130, 255, 0.9) 30%,
    rgba(160, 80, 240, 0.5) 70%,
    transparent 100%);
  box-shadow: 0 0 8px rgba(180, 100, 255, 0.85);
  transform-origin: 0% 50%;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  animation: bs-fx-arcaneblast-bolt 1.8s ease-out infinite;
}
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt:nth-of-type(2) { --bolt-angle:   0deg; animation-delay: 0s;   }
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt:nth-of-type(3) { --bolt-angle:  60deg; animation-delay: 0.3s; }
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt:nth-of-type(4) { --bolt-angle: 120deg; animation-delay: 0.6s; }
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt:nth-of-type(5) { --bolt-angle: 180deg; animation-delay: 0.9s; }
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt:nth-of-type(6) { --bolt-angle: 240deg; animation-delay: 1.2s; }
.bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt:nth-of-type(7) { --bolt-angle: 300deg; animation-delay: 1.5s; }

@keyframes bs-fx-arcaneblast-bolt {
  0%   { opacity: 0;   transform: translateY(-50%) rotate(var(--bolt-angle, 0deg)) scaleX(0); }
  18%  { opacity: 1;   transform: translateY(-50%) rotate(var(--bolt-angle, 0deg)) scaleX(1); }
  45%  { opacity: 0.5; transform: translateY(-50%) rotate(var(--bolt-angle, 0deg)) scaleX(1); }
  70%  { opacity: 0;   transform: translateY(-50%) rotate(var(--bolt-angle, 0deg)) scaleX(1); }
  100% { opacity: 0;   transform: translateY(-50%) rotate(var(--bolt-angle, 0deg)) scaleX(0); }
}

.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__core,
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__bolt {
  animation-duration: 0.9s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__core { animation: none; transform: translate(-50%, -50%) scale(1); }
  .bs-page .bs-move-card__art--ability-arcaneblast .bs-fx-ability__bolt { animation: none; opacity: 0.5; transform: translateY(-50%) rotate(var(--bolt-angle, 0deg)) scaleX(1); }
}

/* Shadow Strike — dark cyan dashes */
.bs-page .bs-move-card__art--ability-shadowstrike {
  background:
    radial-gradient(ellipse at center,
      rgba(80, 220, 220, 0.16) 0%,
      rgba(20, 50, 60, 0.40) 45%,
      rgba(4, 10, 14, 0.95) 100%);
  background-color: #04080c;
  overflow: hidden;
  isolation: isolate;
}
.bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash {
  position: absolute;
  left: -50%;
  width: 30%;
  height: 1.5px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(180, 250, 250, 0) 10%,
    rgba(200, 255, 255, 0.95) 50%,
    rgba(180, 250, 250, 0) 90%,
    transparent 100%);
  box-shadow: 0 0 5px rgba(100, 220, 220, 0.6);
  pointer-events: none;
  z-index: 2;
  animation: bs-fx-ability-dash 1.4s linear infinite;
}
.bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash:nth-of-type(1) { top: 15%; height: 1.5px; animation-delay: 0s;   animation-duration: 1.4s; }
.bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash:nth-of-type(2) { top: 32%; height:   1px; animation-delay: 0.2s; animation-duration: 1.1s; }
.bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash:nth-of-type(3) { top: 52%; height:   2px; animation-delay: 0.5s; animation-duration: 1.3s; }
.bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash:nth-of-type(4) { top: 72%; height: 1.5px; animation-delay: 0.8s; animation-duration: 1.0s; }
.bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash:nth-of-type(5) { top: 88%; height:   1px; animation-delay: 1.0s; animation-duration: 1.2s; }

@keyframes bs-fx-ability-dash {
  0%   { left: -50%; opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { left: 110%; opacity: 0; }
}
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__dash {
  animation-duration: 0.6s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--ability-shadowstrike .bs-fx-ability__dash { animation: none; left: 30%; opacity: 0.6; }
}

/* Fortify — Shield Wall. Central gold core pulses + 3 expanding gold
   rings (Guard-style ripple but warmer) + 4 perimeter hex shields
   that flash in sequence around the corners (like sequential blocks
   absorbing incoming hits). Three layered timings give it the most
   "active defensive system" energy of any Ability variant. */
.bs-page .bs-move-card__art--ability-fortify {
  background:
    radial-gradient(ellipse at center,
      rgba(255, 200, 100, 0.26) 0%,
      rgba(140, 90, 35, 0.34) 45%,
      rgba(40, 25, 10, 0.85) 100%);
  background-color: #2a1a08;
  overflow: hidden;
  isolation: isolate;
}

/* Central gold core — always-on pulse */
.bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    rgba(255, 245, 200, 0.95) 0%,
    rgba(255, 200, 100, 0.85) 35%,
    rgba(180, 130, 50, 0.4) 70%,
    transparent 100%);
  box-shadow:
    0 0 16px rgba(255, 200, 100, 0.85),
    0 0 32px rgba(245, 192, 120, 0.45);
  transform: translate(-50%, -50%) scale(0.85);
  animation: bs-fx-fortify-core 2.0s ease-in-out infinite;
  pointer-events: none;
  z-index: 1;
}
@keyframes bs-fx-fortify-core {
  0%, 100% { transform: translate(-50%, -50%) scale(0.85); filter: brightness(0.95); }
  50%      { transform: translate(-50%, -50%) scale(1.2);  filter: brightness(1.4); }
}

/* Expanding gold rings — radiate outward from center */
.bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid rgba(255, 220, 160, 0.85);
  box-shadow: 0 0 8px rgba(255, 200, 100, 0.55);
  background: transparent;
  transform: translate(-50%, -50%) scale(0.3);
  opacity: 0;
  animation: bs-fx-fortify-ring 2.4s ease-out infinite;
  pointer-events: none;
  z-index: 2;
}
.bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__ring:nth-of-type(2) { animation-delay: 0s;    }
.bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__ring:nth-of-type(3) { animation-delay: 0.8s;  }
.bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__ring:nth-of-type(4) { animation-delay: 1.6s;  }
@keyframes bs-fx-fortify-ring {
  0%   { transform: translate(-50%, -50%) scale(0.3); opacity: 0;   border-width: 2.5px; }
  15%  {                                              opacity: 0.9; }
  100% { transform: translate(-50%, -50%) scale(6);   opacity: 0;   border-width: 0.5px; }
}

.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__core,
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__ring {
  animation-duration: 1.0s;
}
@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__core { animation: none; transform: translate(-50%, -50%) scale(1); }
  .bs-page .bs-move-card__art--ability-fortify .bs-fx-ability__ring { animation: none; opacity: 0.4; transform: translate(-50%, -50%) scale(2.5); }
}

/* Wild Card — glowing color-shifting core + 5 orbital moons.
   This is the Ultimate variant; deliberately higher visual energy
   than the other variants. The core breathes + cycles hue while
   moons orbit at varied radii, directions and speeds.
   Gradient kept gentle (no aggressive vignette) so the panel edges
   read as uniformly active rather than dark padding around a center
   spotlight — fixes the "narrower window" perception caused by the
   center-clustered orbit cluster. */
.bs-page .bs-move-card__art--ability-wildcard {
  /* Nearly-flat gradient so the panel reads at full width even when
     the disabled-state filter (opacity 0.45 + grayscale + brightness)
     is stacked on top. Previously the edges faded toward dark indigo
     and disappeared into the card bg under the dim filter, creating
     the illusion of horizontal margin. */
  background: radial-gradient(ellipse at center, #4a2070 0%, #2a1240 100%);
  background-color: #2a1240;
  overflow: hidden;
  isolation: isolate;
}

/* Central core — pulsing magenta orb that hue-shifts through full spectrum */
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    rgba(255, 240, 220, 0.95) 0%,
    rgba(255, 100, 200, 0.85) 30%,
    rgba(140, 60, 200, 0.45) 65%,
    transparent 100%);
  box-shadow:
    0 0 18px rgba(255, 100, 200, 0.75),
    0 0 32px rgba(180, 80, 220, 0.45);
  transform: translate(-50%, -50%) scale(0.85);
  animation: bs-fx-wildcard-core 2.4s ease-in-out infinite;
  pointer-events: none;
  z-index: 1;
}
@keyframes bs-fx-wildcard-core {
  0%, 100% { transform: translate(-50%, -50%) scale(0.85); filter: hue-rotate(0deg);   }
  25%      { transform: translate(-50%, -50%) scale(1.15); filter: hue-rotate(90deg);  }
  50%      { transform: translate(-50%, -50%) scale(0.95); filter: hue-rotate(180deg); }
  75%      { transform: translate(-50%, -50%) scale(1.2);  filter: hue-rotate(270deg); }
}

/* Orbit wrapper — width = orbit diameter. Rotates around its own
   center which sits at the panel's middle (translate -50% -50%). */
/* Orbit sizes are tuned per aspect-ratio tier so the moons fill most
   of the panel area without clipping at the edges. Defaults below are
   for 2:1 (lush, 900p+); media queries shrink them for 3:1 / 4:1. */
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 88px;
  height: 88px;
  pointer-events: none;
  z-index: 2;
  transform: translate(-50%, -50%) rotate(0deg);
  animation: bs-fx-wildcard-orbit 4.2s linear infinite;
}
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(2) { width:  60px; height:  60px; animation-duration: 3.0s; animation-direction: reverse; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(3) { width: 116px; height: 116px; animation-duration: 5.4s; animation-delay: -0.6s; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(4) { width:  74px; height:  74px; animation-duration: 3.6s; animation-direction: reverse; animation-delay: -1.2s; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(5) { width: 100px; height: 100px; animation-duration: 4.8s; animation-delay: -1.8s; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(6) { width:  48px; height:  48px; animation-duration: 2.6s; animation-direction: reverse; animation-delay: -0.3s; }

/* 3:1 panel (laptop ~900p) — orbits ~25% smaller so the largest
   (now 84px / radius 42) stays inside the ~93px panel height. */
@media (max-height: 949px) {
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit                  { width: 68px; height: 68px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(2)   { width: 46px; height: 46px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(3)   { width: 84px; height: 84px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(4)   { width: 56px; height: 56px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(5)   { width: 76px; height: 76px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(6)   { width: 38px; height: 38px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__core                   { width: 20px; height: 20px; }
}

/* 4:1 panel (~768p) — most aggressive shrink; largest orbit 60px
   (radius 30) fits in the ~70px panel height. */
@media (max-height: 800px) {
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit                  { width: 50px; height: 50px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(2)   { width: 36px; height: 36px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(3)   { width: 60px; height: 60px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(4)   { width: 42px; height: 42px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(5)   { width: 54px; height: 54px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(6)   { width: 30px; height: 30px; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__core                   { width: 16px; height: 16px; }
}
@keyframes bs-fx-wildcard-orbit {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* Moon — sits at the right edge of its orbit wrapper, traces the orbit as parent rotates */
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__moon {
  position: absolute;
  left: 100%;
  top: 50%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid currentColor;
  box-shadow:
    0 0 8px currentColor,
    inset 0 0 3px rgba(255, 255, 255, 0.45);
  color: rgba(255, 100, 200, 0.95);
  transform: translate(-50%, -50%);
}
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(2) .bs-fx-ability__moon { color: rgba(100, 220, 255, 0.95); width: 6px; height: 6px; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(3) .bs-fx-ability__moon { color: rgba(255, 230, 100, 0.95); width: 8px; height: 8px; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(4) .bs-fx-ability__moon { color: rgba(180, 100, 255, 0.95); width: 6px; height: 6px; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(5) .bs-fx-ability__moon { color: rgba(100, 255, 180, 0.95); width: 7px; height: 7px; }
.bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit:nth-of-type(6) .bs-fx-ability__moon { color: rgba(255, 150, 100, 0.95); width: 5px; height: 5px; }

.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__core { animation-duration: 1.2s; }
.bs-page .bs-move-card.arena-move-btn--ability:hover:not(:disabled) .bs-fx-ability__orbit { animation-duration: 1.8s; }

@media (prefers-reduced-motion: reduce) {
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__core,
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__orbit { animation: none; }
  .bs-page .bs-move-card__art--ability-wildcard .bs-fx-ability__core { transform: translate(-50%, -50%) scale(1); }
}

/* ============================================================
   MOBILE BATTLE POLISH (≤600px) — Phase 1: stage geometry + center reflow
   ============================================================
   At 375px the desktop 3-col stage (`minmax(320px, 1fr) minmax(220px, 300px)
   minmax(320px, 1fr)`) cannot fit. The 1100px breakpoint shifts the center
   column to span full width via `grid-column: 1 / -1; order: -1` (placing it
   ABOVE the field). At 375 we want the opposite: keep player + opponent
   side-by-side (~170px each), float the center BELOW the field as a
   horizontal strip. That preserves matchup framing without crushing the
   card columns to thumbnail width.

   This block is intentionally placed at end-of-file so it overrides both
   the height-based 949/800px rules (which fire at 812h) and the 1100px
   width rule (which fires alongside this one). Source order matters more
   than specificity for same-selector @media rules. Dual ID prefix mirrors
   the rest of the file (#bs-screen-battle for play.html, #bs-battle-container
   for index.html / Stranger fight).
   ============================================================ */
@media (max-width: 600px) {
  #bs-screen-battle.blindspot-battle .arena-battle__field,
  #bs-battle-container.blindspot-battle .arena-battle__field {
    grid-template-columns: 1fr 1fr;
    gap: 0.4rem;
    margin-top: 8px;
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center,
  #bs-battle-container.blindspot-battle .blindspot-battle__center {
    grid-column: 1 / -1;
    order: 1;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.4rem;
    padding: 0.5rem 0;
  }
  /* Top zone: round counter + VS glyph inline (was column-stacked). */
  #bs-screen-battle.blindspot-battle .bs-vs-zone--top,
  #bs-battle-container.blindspot-battle .bs-vs-zone--top {
    display: flex;
    flex-direction: row;
    gap: 0.5rem;
    align-items: center;
    width: 100%;
    justify-content: center;
  }
  /* Mid zone: intent + matchup + flavor + hype span full width of the strip. */
  #bs-screen-battle.blindspot-battle .bs-vs-zone--mid,
  #bs-battle-container.blindspot-battle .bs-vs-zone--mid {
    width: 100%;
    padding: 0.25rem 0;
  }
  /* Bottom zone: stance row + utils stay stacked but centered, full-width. */
  #bs-screen-battle.blindspot-battle .bs-vs-zone--bottom,
  #bs-battle-container.blindspot-battle .bs-vs-zone--bottom {
    width: 100%;
  }
  #bs-screen-battle.blindspot-battle .arena-stance-row,
  #bs-battle-container.blindspot-battle .arena-stance-row {
    gap: 0.25rem;
  }
  #bs-screen-battle.blindspot-battle .bs-vs-utils,
  #bs-battle-container.blindspot-battle .bs-vs-utils {
    gap: 0.5rem;
  }

  /* ---------- Combatant frame + backdrop perf ----------
     At 812h the existing max-height: 800px rule fires (frame -> 250).
     With the 2-col field above, each column is ~170px wide; a 250px
     frame is still a touch tall and the 22px backdrop blur composes
     twice (once per side) on every scroll frame. Tighten frame to
     200, match backdrop, drop blur 22 -> 12 for ~70% less compositing
     cost when both backdrops paint together.

     Frame side-padding 32px -> 24px frees 16px total horizontal space
     for the card render. The HP/stamina rails inset 18px from frame
     edge (line 1531-37) stay legible inside the smaller chrome.

     `padding: ... !important` matches the load-bearing !important at
     line 1523 — without it the cascade loses to the desktop value. */
  #bs-screen-battle.blindspot-battle .arena-combatant__frame,
  #bs-battle-container.blindspot-battle .arena-combatant__frame {
    height: 200px;
    padding: 0.25rem 24px !important;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant__backdrop,
  #bs-battle-container.blindspot-battle .arena-combatant__backdrop {
    height: 200px;
    filter: blur(12px) saturate(1.2) brightness(0.95);
  }
  /* Smaller frame -> rails need less reserved space top/bottom. Bumps
     bar-readout offset to 24px each side (was 32) so the visible bar
     length scales with the new frame. */
  #bs-screen-battle.blindspot-battle .arena-hp-bar,
  #bs-battle-container.blindspot-battle .arena-hp-bar,
  #bs-screen-battle.blindspot-battle .arena-stamina-bar,
  #bs-battle-container.blindspot-battle .arena-stamina-bar {
    height: calc(100% - 48px);
  }
  /* Free vertical on the column itself so HP rail + buffs + status
     fit beneath the shrunken frame without clipping. */
  #bs-screen-battle.blindspot-battle .arena-combatant,
  #bs-battle-container.blindspot-battle .arena-combatant {
    padding: 0.25rem;
    gap: 0.1rem;
    max-height: none;
  }

  /* ---------- Tap target normalization ----------
     Item tray icons (charm + activated items) render as 32x32 squares
     in a horizontal strip. At a 44x44 floor each would either grow
     visually (crowding the tray when 4+ items are equipped) or get an
     invisible-inset hit area extension via ::before. Going with ::before
     — same pattern proven for the lobby bell, keeps the visual rhythm.

     Stance buttons measure ~48-52px tall via padding-math today; an
     explicit min-height:44 makes that resilient to font/line-height
     tweaks. Help/Forfeit utils (.bs-vs-utils .arena-btn) are already
     52x48 — above the floor, no change needed. */
  #bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn,
  #bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn {
    /* `position: relative` is already set at line 2398, so ::before
       anchors correctly. */
  }
  #bs-screen-battle.blindspot-battle .arena-combatant__item-tray .arena-move-btn::before,
  #bs-battle-container.blindspot-battle .arena-combatant__item-tray .arena-move-btn::before {
    content: '';
    position: absolute;
    inset: -6px;
    /* invisible — extends hit area to 44x44 */
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn {
    min-height: 44px;
  }

  /* ---------- Tiny-text floor ----------
     Five labels render under 10px on mobile in the battle scope. The
     worst case is `.arena-btn::after` at 0.46rem (~7.4px) on the help
     and forfeit utility buttons — barely legible even at high DPI.
     Bump every leaf label to >=10.4px (0.65rem) or >=11.2px (0.7rem)
     for the chip/trait family which has more breathing room and
     letter-spacing. */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::after,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::after {
    font-size: 0.65rem;                   /* 0.46 -> 0.65 */
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn::after,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn::after {
    font-size: 0.65rem;                   /* 0.55 -> 0.65 */
  }
  #bs-screen-battle.blindspot-battle .arena-hype-bar__hint,
  #bs-battle-container.blindspot-battle .arena-hype-bar__hint {
    font-size: 0.65rem;                   /* 0.55 -> 0.65 */
  }
  #bs-screen-battle.blindspot-battle .arena-buff-chip,
  #bs-battle-container.blindspot-battle .arena-buff-chip {
    font-size: 0.7rem;                    /* 0.6 -> 0.7 — chip has letter-spacing room */
  }
  #bs-screen-battle.blindspot-battle .bs-rc-trait--player,
  #bs-battle-container.blindspot-battle .bs-rc-trait--player {
    font-size: 0.7rem;                    /* 0.6 -> 0.7 — trait pill */
  }

  /* ---------- Results overlay (post-battle) at 375px ----------
     The .arena-results-overlay base now has overflow-y: auto so the
     modal scrolls when content exceeds viewport. On mobile, tighten
     the inner modal padding, scale the title down, stack the action
     CTAs full-width, and bump CTA min-height to the 44px floor. */
  .arena-results-overlay .arena-results {
    padding: 1.5rem 1rem 1rem;            /* 2.25rem 1.75rem -> 1.5rem 1rem */
  }
  .arena-results-overlay .arena-results__banner h2,
  .arena-results-overlay .arena-results__banner h1 {
    font-size: 1.5rem;                    /* 2rem -> 1.5rem */
  }
  .arena-results-overlay .arena-results__actions {
    flex-direction: column;
    gap: 0.5rem;
  }
  .arena-results-overlay .arena-results__actions .arena-btn--primary,
  .arena-results-overlay .arena-results__actions .arena-btn--ghost,
  .arena-results-overlay #arena-results-again,
  .arena-results-overlay #arena-results-lobby {
    min-height: 44px;
    padding: 0.85rem 1.4rem;
    width: 100%;
  }

  /* ---------- Battle viewport budget at 375x812 ----------
     User reported: in real-device test the move buttons sit below the
     fold even with .bs-play scroll enabled (a follow-up commit added
     scroll as safety net). Combat needs HP + intent + moves all
     visible at once — scrolling during a turn is wrong UX.

     Vertical budget at 375x812: 812 - 56 (topbar) = 756 usable.
     Allocation:
       - Field (cards + bars + buffs row):        ~250
       - Center strip (round/intent/hype/stance): ~180
       - Move grid (5-col horizontal):             ~90
       - Battle log:                               ~50
       - Margins/gaps/padding:                     ~50
       Total: ~620, comfortably under 756.

     Aggressive compression vs the previous commits' 200px frame +
     1-col stacked moves. Frame shrinks 200 -> 160, move grid goes
     5-col horizontal with trimmed card content (icon + label only),
     boss flavor + stance indicator hidden, buffs row collapses to
     horizontal flex-wrap. */
  /* Frame + backdrop tighter still */
  #bs-screen-battle.blindspot-battle .arena-combatant__frame,
  #bs-battle-container.blindspot-battle .arena-combatant__frame {
    height: 160px;
    padding: 0.25rem 20px !important;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant__backdrop,
  #bs-battle-container.blindspot-battle .arena-combatant__backdrop {
    height: 160px;
  }
  #bs-screen-battle.blindspot-battle .arena-hp-bar,
  #bs-battle-container.blindspot-battle .arena-hp-bar,
  #bs-screen-battle.blindspot-battle .arena-stamina-bar,
  #bs-battle-container.blindspot-battle .arena-stamina-bar {
    height: calc(100% - 32px);
  }

  /* Buffs row goes horizontal-flex with wrap, capped height. The
     +SPEED / +CRIT / +CRIT DMG chips stack vertically by default —
     in a 170px-wide column at 375 they eat ~80-100px vertically.
     Wrap horizontally + max-height clips at 2 lines. */
  #bs-screen-battle.blindspot-battle .arena-player-buffs,
  #bs-battle-container.blindspot-battle .arena-player-buffs {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.2rem;
    max-height: 56px;
    overflow: hidden;
  }

  /* Hide boss flavor ("Your data is already mine.") and the explicit
     boss stance indicator — both are nice-to-have but eat ~70px combined.
     Boss stance is already conveyed by the opponent card's border tint
     (commit 0b4036ad9 stance-tinted borders). */
  #bs-screen-battle.blindspot-battle .bs-vs-flavor,
  #bs-battle-container.blindspot-battle .bs-vs-flavor,
  #bs-screen-battle.blindspot-battle .bs-boss-stance-indicator,
  #bs-battle-container.blindspot-battle .bs-boss-stance-indicator {
    display: none;
  }

  /* Hype meter slimmer — track 14 -> 8px, label inline */
  #bs-screen-battle.blindspot-battle .arena-hype-bar__track,
  #bs-battle-container.blindspot-battle .arena-hype-bar__track {
    flex: 0 0 8px;
    height: 8px;
  }

  /* ---------- Move cards: art + full name + cost ----------
     User feedback: previous "icon-letter only" treatment (S/G/W/H/F)
     was unreadable. Combat is the most-interacted surface — needs
     full names + visual identity (move art) at a glance.

     Card vertical stack at 5-col: ART (small icon ~28px) + NAME (full
     word, single line, 0.75rem display font) + ENERGY chip (cost num
     with bolt icon, no "ENERGY" label). Type-label, desc, tags, footer
     all hidden on mobile (they're descriptive metadata for desktop).

     min-height 88 keeps each card ≥44 tap-floor with breathing room.
     The 5 in a row at 343px viewport-padded = ~64px each, which fits
     5-char "Strike" / "Guard" / "Counter" at 0.75rem display font. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves,
  #bs-battle-container.blindspot-battle .arena-battle__moves {
    grid-template-columns: repeat(5, 1fr);
    gap: 0.3rem;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card {
    flex-direction: column;
    padding: 0.4rem 0.2rem 0.35rem !important;
    gap: 0.25rem;
    min-height: 88px;
    aspect-ratio: auto;
    align-items: stretch;
    justify-content: flex-start;
  }
  /* Header is currently row (titles + energy). On mobile we want
     just the name — hide the type-label inside titles, drop the row
     direction so name + energy stack via card flex column instead. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__header,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__header {
    display: contents;          /* let titles + energy participate in
                                   the card's flex column directly */
  }
  /* !important on all the move-card-content hides — the legacy
     desktop rules at line 934 (.bs-move-card__desc) etc. set their
     own font/color but no display, so a plain `display: none` should
     win... but real-device test showed desc still visible (likely a
     cascade race against an inherited `display: -webkit-box` or
     similar). Force the hide. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__type-label,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__type-label,
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy-label,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy-label,
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__desc,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__desc,
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__tags,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__tags,
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__footer,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__footer {
    display: none !important;
  }
  /* Re-show art (Commit 9 hid it). Sized as a thin band at the top
     of the card. Aspect-ratio 2/1 from the desktop rule keeps the
     animation pixels intact at ~32px height in a 64px column. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__art,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__art {
    display: block;
    order: 1;
    width: 100%;
    aspect-ratio: 2 / 1;
    margin: 0;
  }
  /* Titles wraps the name. On mobile flatten to just the name. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__titles,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__titles {
    order: 2;
    width: 100%;
    text-align: center;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__name,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__name {
    font-size: 0.65rem;
    letter-spacing: 0;            /* tighter — was 0.02em */
    line-height: 1.05;
    /* Allow 2-line wrap so high-level upgraded names ("Heavy Strike",
       "Power Strike", "Flash Counter", "Fortified Heal") render in
       full instead of truncating mid-word. word-break: break-word
       handles edge cases; max 2 lines via -webkit-line-clamp keeps
       card heights consistent. */
    white-space: normal;
    word-break: keep-all;
    overflow-wrap: break-word;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-align: center;
  }
  /* Energy chip becomes a compact bolt + number row at the bottom. */
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy {
    order: 3;
    align-self: center;
    padding: 0.1rem 0.4rem;
    font-size: 0.7rem;
  }
  #bs-screen-battle.blindspot-battle .arena-battle__moves .bs-move-card__energy-num,
  #bs-battle-container.blindspot-battle .arena-battle__moves .bs-move-card__energy-num {
    font-size: 0.7rem;
  }

  /* Battle log expanded — was max-height: 80 (~2 entries) with a dead
     ~15% void between moves and log. Bump to 140 (~4-5 entries) so
     the log absorbs the void as visible combat history. margin-top
     auto + the .bs-play stretch (commit f7d6f4b0 / 5aa178e4) keep
     the log anchored to viewport bottom. */
  #bs-screen-battle.blindspot-battle .arena-battle__log,
  #bs-battle-container.blindspot-battle .arena-battle__log {
    max-height: 140px;
    height: auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    margin-top: auto;
  }
  /* Header chip clearance — without explicit padding-top the log's
     internal scroll could let the first .arena-log-entry slide under
     the inline-flex .arena-battle__log-head ("BATTLE LOG" chip),
     clipping the leading characters. Padding holds entries clear of
     the header even when scrolled. */
  #bs-screen-battle.blindspot-battle .arena-battle__log,
  #bs-battle-container.blindspot-battle .arena-battle__log {
    padding-top: 0.55rem;
  }

  /* Center column padding tighter so utils row fits without pushing
     the move grid off-screen */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center,
  #bs-battle-container.blindspot-battle .blindspot-battle__center {
    padding: 0.25rem 0;
    gap: 0.25rem;
  }

  /* ---------- Iteration: stance row + utils row compressed ----------
     Real-device follow-up showed stance buttons rendering at ~80px
     tall and the GUIDE/FORFEIT utils row another ~70px below — that
     150px eats the room the move grid needed. Compress both rows to
     the 44px tap floor so the moves grid renders fully on-screen.

     Stance buttons: drop the 1.1rem icon + 0.65rem label stack to a
     0.9rem icon + tighter padding, keeping min-height 44. Total ~44px
     instead of ~80, while still meeting the tap-target floor.

     Utils buttons: existing 52x48 from line 3187. Keep width but
     shrink height + padding so the row settles at 44px tall. */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn {
    padding: 0.35rem 0.25rem;
    font-size: 0.9rem;        /* icon shrinks 1.1 -> 0.9rem */
    gap: 0.1rem;              /* was 0.2 between icon and label */
    min-height: 44px;
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn::after,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn::after {
    font-size: 0.55rem;       /* below 0.65 floor here is fine — chip
                                 context with strong contrast + brand
                                 mono spacing keeps it legible */
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn {
    height: 44px;
    width: 56px;
    min-width: 44px;
    padding: 0.2rem 0;
    font-size: 0.85rem;       /* was 1.05rem default */
    gap: 0.1rem;
  }
  /* Iteration: drop the GUIDE / FORFEIT labels on mobile so the
     utils row collapses to two compact icon-only buttons. The labels
     were taking a dedicated row of vertical real estate; icons alone
     read clearly enough at the 56x44 button size and reclaim ~20px. */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::after,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::after {
    display: none;
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn {
    height: 36px;
    width: 36px;
    min-width: 36px;
    /* Hit area extended to 44 via ::before invisible inset — same
       pattern as the lobby bell (visual stays compact, taps are 44). */
    position: relative;
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::before,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-utils .arena-btn::before {
    content: '';
    position: absolute;
    inset: -4px;
  }

  /* Buffs row hidden on mobile (was max-height 28). The +15 XP /
     buff chips were the only content under the LEFT card that the
     OPPONENT side didn't mirror — created left/right asymmetry that
     read as a layout bug. Buffs are informational (XP totals are in
     the lobby HUD; prefight picker is where adventure buffs are
     surfaced); losing them mid-battle on mobile is acceptable trade
     for a symmetric layout.

     Item tray (charms/items the player tapped to bring) hidden for
     the same reason — three unlabeled thumbnails under the left
     card with no opponent equivalent. Items came in via the prefight
     picker; mid-battle activation moves to a future iteration with
     proper labeling + shared positioning. */
  #bs-screen-battle.blindspot-battle .arena-player-buffs,
  #bs-battle-container.blindspot-battle .arena-player-buffs,
  #bs-screen-battle.blindspot-battle .arena-combatant__item-tray,
  #bs-battle-container.blindspot-battle .arena-combatant__item-tray {
    display: none;
  }

  /* ---------- HP / ST stat labels on bar readouts ----------
     Without labels the bare numbers (e.g. "32 / 114" + "0 / 0") were
     unreadable for first-time players — no way to know which is HP,
     which is stamina, or what the gold vs red bar means. ::before
     pseudo prepends a 2-letter tag inline with the number. Inherits
     the readout's color (red for HP, gold for stamina), so the label
     visually links to its corresponding bar. */
  #bs-screen-battle.blindspot-battle .arena-bar-readout,
  #bs-battle-container.blindspot-battle .arena-bar-readout {
    font-size: 0.7rem;          /* 0.55 -> 0.7rem — was 8.8px, now 11.2 */
  }
  #bs-screen-battle.blindspot-battle .arena-bar-readout--hp::before,
  #bs-battle-container.blindspot-battle .arena-bar-readout--hp::before {
    content: 'HP ';
    opacity: 0.7;
    margin-right: 1px;
  }
  #bs-screen-battle.blindspot-battle .arena-bar-readout--stam::before,
  #bs-battle-container.blindspot-battle .arena-bar-readout--stam::before {
    content: 'ST ';
    opacity: 0.7;
    margin-right: 1px;
  }
  /* Hide in-bar readouts entirely on mobile. They can't escape the
     bar's positioning context via CSS alone — the bars are absolute
     children of the frame, anchored on adjacent inner edges of the
     two combatant frames, so any readout centered on them collides
     at the gutter regardless of vertical position. JS now writes
     HP/ST text to data-hp / data-stam attributes on each combatant
     column; ::before / ::after pseudos below render those values
     as proper per-column chips that can't bridge the seam. */
  #bs-screen-battle.blindspot-battle .arena-bar-readout,
  #bs-battle-container.blindspot-battle .arena-bar-readout {
    display: none;
  }
  /* Per-frame stat chips. Anchor to the FRAME (not the column) so
     chips sit at the bottom of the visible card frame, not below it
     on top of buffs/status rows. Bars sit on INNER edges of the two
     frames (HP-red next to gutter, ST-gold on outer edges); chips
     mirror that so each chip sits directly UNDER its corresponding
     bar — HP chip under HP rail, ST chip under ST rail. */
  #bs-screen-battle.blindspot-battle .arena-combatant__frame::before,
  #bs-battle-container.blindspot-battle .arena-combatant__frame::before,
  #bs-screen-battle.blindspot-battle .arena-combatant__frame::after,
  #bs-battle-container.blindspot-battle .arena-combatant__frame::after {
    position: absolute;
    bottom: 4px;
    background: rgba(13, 8, 7, 0.88);
    padding: 2px 6px;
    border-radius: 3px;
    font-family: var(--blindspot-font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.04em;
    white-space: nowrap;
    pointer-events: none;
    z-index: 5;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
  }
  /* HP chip: ::before, content from data-hp on frame, red text */
  #bs-screen-battle.blindspot-battle .arena-combatant__frame::before,
  #bs-battle-container.blindspot-battle .arena-combatant__frame::before {
    content: attr(data-hp);
    color: #ef4444;
    border: 1px solid rgba(239, 68, 68, 0.3);
  }
  /* ST chip: ::after, content from data-stam on frame, gold text */
  #bs-screen-battle.blindspot-battle .arena-combatant__frame::after,
  #bs-battle-container.blindspot-battle .arena-combatant__frame::after {
    content: attr(data-stam);
    color: var(--blindspot-accent-gold, #F5C078);
    border: 1px solid rgba(245, 192, 120, 0.3);
  }
  /* Player frame: HP rail on RIGHT (inner) -> HP chip right.
                   ST rail on LEFT (outer) -> ST chip left. */
  #bs-screen-battle.blindspot-battle .arena-combatant--player .arena-combatant__frame::before,
  #bs-battle-container.blindspot-battle .arena-combatant--player .arena-combatant__frame::before {
    right: 4px;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant--player .arena-combatant__frame::after,
  #bs-battle-container.blindspot-battle .arena-combatant--player .arena-combatant__frame::after {
    left: 4px;
  }
  /* Opponent frame: mirror — HP rail on LEFT (inner) -> HP chip left.
                              ST rail on RIGHT (outer) -> ST chip right. */
  #bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-combatant__frame::before,
  #bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-combatant__frame::before {
    left: 4px;
  }
  #bs-screen-battle.blindspot-battle .arena-combatant--opponent .arena-combatant__frame::after,
  #bs-battle-container.blindspot-battle .arena-combatant--opponent .arena-combatant__frame::after {
    right: 4px;
  }

  /* ---------- Center strip de-duplication + tightening ----------
     The "VS · EVEN MATCHUP" matchup chip restated information already
     conveyed by the giant VS glyph above + the round counter. On
     mobile that's three competing affordances saying the same thing.
     Hide the chip; matchup is inferable from the boss's element badge
     on its rendered card.

     Compress center-strip vertical rhythm by ~25% beyond Commit 9:
     gap 0.25 -> 0.18, padding 0.25rem 0 -> 0.15rem 0. Round counter
     pill + boss intent + hype bar tightened proportionally so the
     band reads as a single horizontal strip, not stacked sections. */
  /* Match existing rule's specificity (`.blindspot-battle__center
     .bs-vs-matchup` = 3 classes) and add !important so the hide
     wins regardless of source-order races. */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .bs-vs-matchup,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .bs-vs-matchup {
    display: none !important;
  }
  #bs-screen-battle.blindspot-battle .blindspot-battle__center,
  #bs-battle-container.blindspot-battle .blindspot-battle__center {
    padding: 0.15rem 0;
    gap: 0.18rem;
  }
  #bs-screen-battle.blindspot-battle .bs-vs-round,
  #bs-battle-container.blindspot-battle .bs-vs-round {
    padding: 0.2rem 0.7rem;
    font-size: 0.7rem;
  }
  #bs-screen-battle.blindspot-battle .arena-boss-intent,
  #bs-battle-container.blindspot-battle .arena-boss-intent {
    font-size: 0.78rem;
    padding: 0.3rem 0.6rem;
  }

  /* ---------- Combat log: backing panel + better contrast ----------
     Combat feedback was reading like debug text — italic + low contrast
     against the arena image background. Add a translucent dark backing
     strip with a faint gold inset border so combat events have visual
     authority and read instantly. */
  #bs-screen-battle.blindspot-battle .arena-battle__log,
  #bs-battle-container.blindspot-battle .arena-battle__log {
    background: linear-gradient(180deg,
      rgba(13, 8, 7, 0.7) 0%,
      rgba(13, 8, 7, 0.55) 100%);
    border-top: 1px solid rgba(245, 192, 120, 0.18);
    border-bottom: 1px solid rgba(245, 192, 120, 0.08);
    padding: 0.4rem 0.6rem;
    border-radius: 2px;
  }
  #bs-screen-battle.blindspot-battle .arena-log-entry,
  #bs-battle-container.blindspot-battle .arena-log-entry {
    color: var(--blindspot-text, #F5F0E8);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
  }

  /* ---------- Active stance: subtle pulse ----------
     Mobile combat feedback. The selected stance gets a subtle scale
     + glow pulse so the player gets instant tactile confirmation that
     their tap registered. ~1.4s loop, low amplitude — atmospheric, not
     attention-grabbing. Respects prefers-reduced-motion. */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn--active,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn--active {
    animation: bs-stance-pulse 1.6s ease-in-out infinite;
  }

  /* ---------- Reduce secondary-element glow ----------
     Round pill, hype label, matchup chip glow at full strength was
     competing with the cards + active stance for focus. Tone the
     secondary chrome glow down on mobile so the eye flows: cards ->
     HP/intent -> stance -> moves. */
  #bs-screen-battle.blindspot-battle .bs-vs-round,
  #bs-battle-container.blindspot-battle .bs-vs-round {
    box-shadow: none;
  }
  #bs-screen-battle.blindspot-battle .arena-hype-bar__label,
  #bs-battle-container.blindspot-battle .arena-hype-bar__label {
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
  }

  /* ---------- VS glyph: 15% smaller + softer glow on mobile ----------
     ChatGPT visual-hierarchy recommendation #4: VS was eating focal
     attention with clamp(3rem, 6vw, 4rem) (-> 48px at 375 width) plus
     a 40px-blur red glow. Cards should be the primary focal point;
     VS is connective tissue. Drop ~17% (3rem -> 2.4rem floor) and
     halve the glow intensity. */
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-battle__vs-text,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-battle__vs-text {
    font-size: clamp(2.4rem, 7vw, 3.2rem);
    text-shadow: 0 0 24px rgba(200, 48, 44, 0.35);
  }
}

@keyframes bs-stance-pulse {
  0%, 100% { transform: scale(1); box-shadow: inset 0 0 0 0 currentColor; }
  50% { transform: scale(1.04); box-shadow: inset 0 0 0 1px currentColor; }
}
@media (prefers-reduced-motion: reduce) {
  #bs-screen-battle.blindspot-battle .blindspot-battle__center .arena-stance-btn--active,
  #bs-battle-container.blindspot-battle .blindspot-battle__center .arena-stance-btn--active {
    animation: none;
  }
}
