.board,
.board * {
  box-sizing: border-box;
}

.board {
  --board-brass: #d4a64c;
  --board-ink: #24170d;
  --board-parchment: #ead7ad;
  --board-shadow: rgba(16, 8, 3, 0.68);
  --board-wood: #6e3d1d;

  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  position: relative;
  z-index: 2200;
}

/* Let the expanded graveyard escape the board's stacking context so it can
   paint above the owner hand without lifting the rest of the board over it. */
.board:has(.board__graveyard-zone.is-open) {
  z-index: auto;
}

body:has(.board) .current-player-area,
body:has(.board) .other-player-area {
  grid-template-columns: 1fr;
  padding-left: 154px;
  padding-right: 248px;
}

/* Slice 9C gated reachability: the fixed gated chrome (graveyard toggle at
   2218, rail at 2220, hero zones at 2220, ledger at 2240, popover at 2250)
   used to paint over the risen owner hand (z-index 1000), making the hand's
   per-card spawn `+` and its modal unusable. Only the gated board lifts the
   hand above every chrome layer while keeping it below the deck picker
   (2300) and the card-move chrome (2340/2400); the default board's own
   hand rule is untouched, so default geometry is unchanged. */
body:has(.board) .hand-current-player {
  z-index: 2260;
}

body:has(.board) .current-player-playground,
body:has(.board) .other-player-playground {
  grid-column: 1;
}

.board button {
  font-family: inherit;
}

.board__hero-area {
  align-items: center;
  background: linear-gradient(100deg, rgba(49, 24, 11, 0.96), rgba(110, 62, 27, 0.97));
  border: 3px solid #29140a;
  border-radius: 24px 50px 50px 24px;
  box-shadow: inset 0 0 0 2px rgba(244, 197, 102, 0.26), 0 9px 20px var(--board-shadow);
  color: #ffeac0;
  display: grid;
  gap: 8px;
  grid-template-columns: minmax(0, 1fr) 78px;
  height: 96px;
  padding: 9px 12px 9px 16px;
  position: fixed;
  right: 22px;
  width: 260px;
  z-index: 2220;
}

.board__hero-area--opponent {
  top: 18px;
}

.board__hero-area--current {
  bottom: 18px;
}

.board__hero-identity {
  min-width: 0;
  padding-right: 5px;
  text-align: right;
  text-shadow: 0 2px 2px #1c0d06;
}

.board__hero-identity strong,
.board__hero-identity span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.board__hero-identity strong {
  font: 700 13px/1.2 Georgia, serif;
}

.board__hero-identity span {
  color: #d8b97d;
  font-size: 9px;
  margin-top: 4px;
}

/* The recipient's own deck name is the single actionable control in the
   hero, so only it becomes a real button: same typography and right-aligned
   ellipsis discipline as the inert span above, plus pointer cursor, visible
   focus, and a min-height 44px hit target that fills the identity column's
   remaining height without altering the fixed 96px hero card. The inert
   spans stay compact — only the actionable control carries the touch
   target. */
.board__hero-identity .board__hero-deck-opener {
  appearance: none;
  background: none;
  border: 0;
  border-radius: 6px;
  color: #d8b97d;
  cursor: pointer;
  display: block;
  font-size: 9px;
  line-height: 44px;
  margin-top: 4px;
  min-height: 44px;
  min-width: 44px;
  overflow: hidden;
  padding: 0;
  text-align: right;
  text-overflow: ellipsis;
  touch-action: manipulation;
  white-space: nowrap;
  width: 100%;
}

.board__hero-identity .board__hero-deck-opener:hover {
  color: #ffe9c2;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.board__hero-identity .board__hero-deck-opener:focus-visible {
  border-radius: 6px;
  outline: 3px solid #ffc866;
  outline-offset: -3px;
}

.board__hero-portrait {
  align-items: center;
  background: radial-gradient(circle at 40% 30%, #9cc2bc, #315153 58%, #132a2e);
  border: 4px solid #d9ad55;
  border-radius: 50%;
  box-shadow: inset 0 0 0 3px #4b2712, 0 4px 10px #180b05;
  display: flex;
  font: 800 22px/1 Georgia, serif;
  height: 78px;
  justify-content: center;
  overflow: hidden;
  position: relative;
  padding: 0;
  text-shadow: 0 2px 3px #132426;
  width: 78px;
}

button.board__hero-portrait {
  cursor: pointer;
  touch-action: manipulation;
}

button.board__hero-portrait:focus-visible {
  outline: 3px solid #ffefaa;
  outline-offset: 3px;
}

/* Legendary Reveal: decorative WebGPU overlay centered on the portrait by
   the avatar-reveal controller. Purely ornamental — never interactive, and
   the board must function identically without it. It deliberately overflows
   the fixed panel so the ray band can breathe past the frame edge. */
.board__avatar-reveal {
  pointer-events: none;
  position: absolute;
  z-index: 1;
}

.board__hero-portrait img {
  height: 115%;
  object-fit: cover;
  object-position: center 24%;
  width: 115%;
}

/* Real hero art layers above the decorative portrait, which stays visible
   underneath whenever the art is absent or fails to load. */
.board__hero-portrait-art {
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
}

.board__hero-portrait-art[hidden] {
  display: none;
}

.board__hero-portrait img.board__hero-portrait-avatar {
  height: 100%;
  object-position: center;
  width: 100%;
}

/* The life orb sits against the hero plate's left edge, clear of the portrait
   and identity copy. Editable controls straddle the orb — each glyph circle
   centered exactly on the rim, half in and half out, per the marked mockup.
   The painted circle is 22px, only slightly larger than the +/− marks
   (13px), while the button keeps an invisible 44px touch target. Offsets
   anchor to the padding box, whose edge sits 3px inside the visible rim, so
   centering on the rim needs left: -25px / 21px at the 46px orb and
   -25px / 12px at the 37px compact orb (the decrement rule is shared). */
.board__life {
  align-items: center;
  background: radial-gradient(circle at 42% 32%, #ff745e, #b51f26 58%, #5c0d16);
  border: 3px solid #f0c36a;
  border-radius: 50% 50% 52% 48%;
  bottom: -9px;
  box-shadow: inset 0 0 0 2px #6d1017, 0 3px 7px #1a0907;
  color: #fff3d1;
  display: flex;
  height: 46px;
  justify-content: center;
  left: 0;
  position: absolute;
  text-shadow: 0 2px 2px #5a0b12;
  width: 46px;
  z-index: 2;
}

.board__life strong {
  font: 900 15px/1 Georgia, serif;
  position: relative;
  z-index: 3;
}

.board__life button {
  align-items: center;
  background: none;
  border: 0;
  color: #ffe8ae;
  cursor: pointer;
  display: flex;
  font-size: 13px;
  height: 44px;
  justify-content: center;
  opacity: 0.2;
  padding: 0;
  position: absolute;
  top: -2px;
  transition: opacity 150ms ease;
  width: 44px;
  z-index: 2;
}

.board__life button span {
  align-items: center;
  background: #3e1a0c;
  border: 1px solid #d9ad55;
  border-radius: 50%;
  display: flex;
  height: 22px;
  justify-content: center;
  width: 22px;
}

.board__life button:first-child {
  left: -25px;
}

.board__life button:last-child {
  left: 21px;
}

.board__life button:hover,
.board__life button:focus-visible {
  filter: brightness(1.25);
  outline: 2px solid #ffefaa;
}

/* At rest the glyphs sit 80% transparent so the digits stay dominant. They
   fully reveal while the pointer or keyboard focus is anywhere on the orb,
   or when the user taps the orb to pin them (life-counter#toggleReveal
   manages the is-revealed class across Turbo morphs). Declared BEFORE the
   busy/disabled dim below so an in-flight request still dims the controls. */
.board__life:hover button,
.board__life:focus-within button,
.board__life.is-revealed button {
  opacity: 1;
}

/* Slice 4: while an authoritative life request is in flight the orb marks
   itself busy and disables both buttons; dimming is feedback only, the
   button geometry never changes. */
.board__life[aria-busy="true"] button,
.board__life button:disabled {
  cursor: default;
  filter: grayscale(0.4);
  opacity: 0.6;
}

.board__avatar-preview {
  background: linear-gradient(160deg, #4e2b16, #241108);
  border: 3px solid #d9ad55;
  border-radius: 22px;
  box-shadow: 0 24px 70px var(--board-shadow), inset 0 0 0 2px rgba(255, 231, 160, 0.22);
  color: #ffeac0;
  max-height: min(90dvh, 520px);
  max-width: min(420px, calc(100vw - 32px));
  padding: 18px;
  width: min(420px, calc(100vw - 32px));
}

.board__avatar-preview[open] {
  display: grid;
  gap: 16px;
  margin: auto;
}

.board__avatar-preview::backdrop {
  background: rgba(18, 9, 4, 0.78);
  backdrop-filter: blur(3px);
}

.board__avatar-preview-header {
  align-items: center;
  display: flex;
  gap: 12px;
  justify-content: space-between;
  width: 100%;
}

.board__avatar-preview-header h2 {
  color: #ffeac0;
  font: 700 20px/1.2 Georgia, serif;
  margin: 0;
}

.board__avatar-preview-close {
  align-items: center;
  background: #5f3519;
  border: 2px solid #d9ad55;
  border-radius: 50%;
  color: #ffeac0;
  cursor: pointer;
  display: flex;
  font-size: 24px;
  height: 44px;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 0;
  width: 44px;
}

.board__avatar-preview-close:hover,
.board__avatar-preview-close:focus-visible {
  background: #7b4924;
  outline: 3px solid #ffefaa;
  outline-offset: 2px;
}

.board__avatar-preview-image {
  aspect-ratio: 1;
  border: 5px solid #d9ad55;
  border-radius: 50%;
  box-shadow: inset 0 0 0 3px #4b2712, 0 12px 32px #180b05;
  justify-self: center;
  max-height: calc(100dvh - 160px);
  max-width: 100%;
  object-fit: cover;
  width: min(320px, calc(100vw - 80px));
}

.board__deck-zone {
  height: 106px;
  position: fixed;
  right: 34px;
  width: 86px;
  z-index: 2212;
}

.board__deck-zone--opponent {
  top: 146px;
}

.board__deck-zone--current {
  bottom: 146px;
  right: 50px;
}

/* The gated zone shells are viewport-pinned, but the shared drag-drop
   controller toggles .drop-zone-hover and legacy table.css declares that
   hook position: relative. Two-class specificity keeps the zones pinned
   no matter which stylesheet order the cascade resolves to. */
.board__deck-zone.drop-zone-hover,
.board__graveyard-zone.drop-zone-hover {
  position: fixed;
}

.board__deck-holster {
  appearance: none;
  background: linear-gradient(90deg, #2b160b, #70401f 50%, #2a140a);
  border: 3px solid #1c0d06;
  border-radius: 9px 9px 18px 18px;
  box-shadow: inset 0 0 0 2px rgba(231, 181, 88, 0.32), 0 8px 15px var(--board-shadow);
  cursor: pointer;
  height: 106px;
  overflow: visible;
  padding: 0;
  position: relative;
  width: 86px;
}

.board__deck-holster::after {
  background: linear-gradient(#b17437, #5b2f16);
  border: 2px solid #241108;
  border-radius: 0 0 13px 13px;
  bottom: -1px;
  content: "";
  height: 26px;
  left: 3px;
  position: absolute;
  right: 3px;
  z-index: 5;
}

.board__deck-card {
  appearance: none;
  background: linear-gradient(135deg, #38226e, #15102f 48%, #71442a 49%, #2e160d 53%, #14102c);
  border: 2px solid #d1ad68;
  border-radius: 5px;
  box-shadow: 0 4px 7px rgba(14, 6, 3, 0.7);
  height: 87px;
  left: 13px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  top: -15px;
  transform-origin: bottom center;
  transition: transform 150ms ease;
  width: 60px;
}

button.board__deck-card {
  cursor: grab;
}

button.board__deck-card:active {
  cursor: grabbing;
}

button.board__deck-card:focus-visible {
  outline: 3px solid #fff0a1;
  outline-offset: 2px;
}

.board__deck-draw-tooltip {
  background: linear-gradient(100deg, #f4e2b8, #dfc28a);
  border: 2px solid #6b3d1d;
  border-radius: 7px;
  box-shadow: 0 6px 14px var(--board-shadow);
  color: var(--board-ink);
  font: 700 11px/1.2 Georgia, serif;
  opacity: 0;
  padding: 7px 9px;
  pointer-events: none;
  position: absolute;
  right: -20px;
  top: -56px;
  transform: translateX(5px);
  transition: opacity 120ms ease, transform 120ms ease;
  white-space: nowrap;
  z-index: 12;
}

button.board__deck-card:hover + .board__deck-draw-tooltip,
button.board__deck-card:focus-visible + .board__deck-draw-tooltip,
button.board__deck-card[aria-expanded="true"] + .board__deck-draw-tooltip {
  opacity: 1;
  transform: none;
}

.board__deck-card img {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
}

.board__deck-card.is-back {
  background-position: center;
  background-size: cover;
  transform: rotate(-5deg) translateX(-5px);
  z-index: 1;
}

.board__deck-card.is-middle {
  transform: rotate(1deg);
  z-index: 2;
}

.board__deck-card.is-front {
  transform: rotate(6deg) translateX(5px);
  z-index: 3;
}

/* Each owner card keeps a full 44px exposed edge even before hover, so all
   three physical draw rules are independently reachable by mouse or touch. */
button.board__deck-card.is-back {
  transform: rotate(-8deg) translateX(-44px);
}

button.board__deck-card.is-middle {
  transform: rotate(1deg);
}

button.board__deck-card.is-front {
  transform: rotate(8deg) translateX(44px);
}

.board__deck-count {
  background: #f0d28d;
  border: 2px solid #4e2a13;
  border-radius: 12px;
  bottom: 3px;
  color: #2a160b;
  font: 800 10px/1 Georgia, serif;
  left: 50%;
  opacity: 0;
  padding: 4px 8px;
  pointer-events: none;
  position: absolute;
  transform: translate(-50%, 5px);
  transition: opacity 130ms ease, transform 130ms ease;
  white-space: nowrap;
  z-index: 7;
}

.board__deck-zone:hover .board__deck-card.is-back,
.board__deck-zone.is-open .board__deck-card.is-back {
  transform: rotate(-10deg) translate(-9px, -8px);
}

.board__deck-zone:hover .board__deck-card.is-front,
.board__deck-zone.is-open .board__deck-card.is-front {
  transform: rotate(11deg) translate(9px, -8px);
}

.board__deck-zone:hover button.board__deck-card.is-back,
.board__deck-zone:focus-within button.board__deck-card.is-back {
  transform: rotate(-8deg) translateX(-44px);
}

.board__deck-zone:hover button.board__deck-card.is-front,
.board__deck-zone:focus-within button.board__deck-card.is-front {
  transform: rotate(8deg) translateX(44px);
}

.board__deck-zone:hover .board__deck-count,
.board__deck-zone:focus-within .board__deck-count,
.board__deck-zone.is-open .board__deck-count {
  opacity: 1;
  transform: translate(-50%, 0);
}

.board__deck-holster:focus-visible {
  outline: 3px solid #fff0a1;
  outline-offset: 3px;
}

.board__graveyard-zone {
  height: 112px;
  left: 18px;
  position: fixed;
  width: 126px;
  z-index: 2218;
}

/* The compact owner hand overlaps the expanded pile. Lift only the open
   graveyard above the hand; the closed toggle keeps its reserved gutter. */
.board__graveyard-zone.is-open {
  z-index: 2270;
}

.board__graveyard-zone--opponent {
  top: 18px;
}

.board__graveyard-zone--current {
  bottom: 18px;
}

.board__graveyard {
  appearance: none;
  background: linear-gradient(#34454c 0 43%, #1f2b2b 44% 58%, #3c2b20 59% 100%);
  border: 3px solid #1a0f0b;
  border-radius: 18px 18px 12px 12px;
  box-shadow: inset 0 0 0 2px rgba(180, 199, 183, 0.17), 0 8px 18px var(--board-shadow);
  color: #e6dec4;
  cursor: pointer;
  height: 112px;
  overflow: hidden;
  padding: 0;
  position: relative;
  width: 126px;
}

.board__graveyard::after {
  background: #27352f;
  border-radius: 50%;
  bottom: -19px;
  box-shadow: -38px 5px 0 #314036, 41px 5px 0 #354138;
  content: "";
  height: 48px;
  left: 38px;
  position: absolute;
  width: 54px;
}

.board__graveyard-moon {
  background: #d9d4a6;
  border-radius: 50%;
  box-shadow: -5px 1px 0 #34454c;
  height: 17px;
  position: absolute;
  right: 14px;
  top: 11px;
  width: 17px;
}

.board__graveyard-stone {
  background: linear-gradient(100deg, #8c9489, #4d5752);
  border: 2px solid #222c29;
  border-radius: 18px 18px 3px 3px;
  bottom: 17px;
  color: #27302d;
  font: 800 7px/1 Georgia, serif;
  height: 48px;
  left: 44px;
  padding-top: 16px;
  position: absolute;
  text-shadow: 0 1px rgba(255, 255, 255, 0.28);
  width: 39px;
  z-index: 2;
}

.board__graveyard-cross {
  background: #7b6955;
  position: absolute;
  width: 6px;
  z-index: 2;
}

.board__graveyard-cross::after {
  background: inherit;
  content: "";
  height: 5px;
  left: -6px;
  position: absolute;
  top: 7px;
  width: 18px;
}

.board__graveyard-cross.is-small {
  bottom: 20px;
  height: 30px;
  left: 20px;
  transform: rotate(-5deg);
}

.board__graveyard-cross.is-large {
  bottom: 14px;
  height: 38px;
  right: 18px;
  transform: rotate(5deg);
}

.board__graveyard > strong {
  align-items: center;
  background: #d2b066;
  border: 2px solid #4b2b16;
  border-radius: 50%;
  color: #2b170c;
  display: flex;
  font: 900 12px/1 Georgia, serif;
  height: 31px;
  justify-content: center;
  left: 8px;
  position: absolute;
  top: 8px;
  width: 31px;
  z-index: 4;
}

.board__graveyard > small {
  background: rgba(20, 13, 10, 0.77);
  bottom: 3px;
  color: #e9d4a5;
  font: 700 8px/1 Georgia, serif;
  left: 28px;
  letter-spacing: 0.05em;
  padding: 3px 8px;
  position: absolute;
  text-transform: uppercase;
  z-index: 4;
}

.board__graveyard:hover,
.board__graveyard:focus-visible,
.board__graveyard-zone.is-open .board__graveyard {
  filter: brightness(1.12);
  outline: 3px solid #d9ba72;
  outline-offset: 2px;
}

.board__graveyard-pile {
  background: linear-gradient(105deg, rgba(40, 25, 16, 0.98), rgba(91, 55, 27, 0.98));
  border: 2px solid #1d0f08;
  border-radius: 10px 20px 20px 10px;
  box-shadow: 0 12px 24px var(--board-shadow), inset 0 0 0 2px rgba(217, 180, 103, 0.2);
  color: #f2dfb5;
  height: 112px;
  left: 136px;
  opacity: 0;
  padding: 9px 12px;
  pointer-events: none;
  position: absolute;
  top: 0;
  transform: translateX(-8px);
  transition: opacity 130ms ease, transform 130ms ease;
  width: 242px;
}

/* The closed pile is display-none on top of transparent: never rely on
   opacity alone for unavailability. */
.board__graveyard-pile[hidden] {
  display: none;
}

.board__graveyard-pile::before {
  content: "";
  height: 100%;
  left: -12px;
  position: absolute;
  top: 0;
  width: 12px;
}

/* Visibility is owned by the controller's is-open state (set alongside
   hidden/inert/aria), never by raw hover or focus styles. */
.board__graveyard-zone.is-open .board__graveyard-pile {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}

.board__graveyard-pile p {
  margin: 0;
}

.board__graveyard-pile p strong,
.board__graveyard-pile p span {
  display: block;
}

.board__graveyard-pile p strong {
  font: 700 10px/1.2 Georgia, serif;
}

.board__graveyard-pile p span {
  color: #bca579;
  font-size: 7px;
  margin-top: 2px;
}

.board__graveyard-cards {
  height: 70px;
  margin-top: 4px;
  overflow-x: auto;
  overflow-y: hidden;
  position: relative;
  scrollbar-width: thin;
}

.board__graveyard-card {
  background: linear-gradient(135deg, rgba(31, 18, 51, 0.6), rgba(93, 55, 31, 0.28)), #2f253e;
  background-position: center;
  background-size: cover;
  border: 2px solid #cbb276;
  border-radius: 4px;
  box-shadow: 0 3px 6px rgba(12, 5, 2, 0.65);
  color: white;
  cursor: pointer;
  height: 65px;
  left: calc(var(--graveyard-index) * 39px);
  overflow: hidden;
  padding: 0;
  position: absolute;
  /* Resting flush at 5px keeps the 65px card inside the 70px scroll box, and
     the hover/focus lift (4px + 1.05 scale growth) still clears the top edge
     of the pile's overflow-y: hidden clipping. */
  top: 5px;
  transform: rotate(calc((var(--graveyard-index) - 1.5) * 2deg));
  transition: transform 130ms ease, left 130ms ease;
  width: 47px;
}

.board__graveyard-card::after {
  background: linear-gradient(transparent, rgba(15, 7, 4, 0.84));
  content: "";
  inset: 0;
  position: absolute;
}

.board__graveyard-card img {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
}

.board__graveyard-card-name {
  align-items: center;
  bottom: 0;
  display: flex;
  font: 700 8px/1.15 Georgia, serif;
  hyphens: auto;
  left: 0;
  padding: 4px;
  position: absolute;
  right: 0;
  text-align: center;
  top: 0;
  z-index: 1;
}

.board__graveyard-empty {
  color: #bca579;
  font: 400 9px/1.3 Georgia, serif;
  margin: 8px 0 0;
}

.board__graveyard-card:hover,
.board__graveyard-card:focus-visible,
.board__graveyard-card.is-selected {
  outline: 2px solid #fff0a1;
  /* The 3px lift plus 1.05 scale growth stays inside the headroom the resting
     top: 5px reserves, so the raised card is never clipped by the pile's
     overflow-y: hidden scroll box. */
  transform: translateY(-3px) rotate(0) scale(1.05);
  z-index: 10;
}

.event-log__rail {
  align-items: center;
  display: flex;
  flex-direction: column;
  gap: 6px;
  left: 48px;
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  width: 66px;
  z-index: 2220;
}

.event-log__rail::before {
  background: linear-gradient(90deg, #2c160b, #754323 24%, #9d6738 50%, #63361c 76%, #271207);
  border: 2px solid #2b160c;
  border-radius: 30px;
  box-shadow: 0 5px 13px var(--board-shadow), inset 0 0 0 2px rgba(255, 210, 112, 0.2);
  content: "";
  inset: -9px 3px -11px;
  position: absolute;
  z-index: -1;
}

.event-log__turn {
  align-items: center;
  background: linear-gradient(#f5da8a, #9c6428);
  border: 2px solid #4a270e;
  border-radius: 50%;
  box-shadow: inset 0 1px 0 #fff2b4, 0 3px 7px var(--board-shadow);
  color: #3d200b;
  display: flex;
  font: 800 10px/1 Georgia, serif;
  height: 44px;
  justify-content: center;
  letter-spacing: 0.04em;
  text-shadow: 0 1px #f5d585;
  width: 44px;
}

.event-log__recent-events {
  align-items: center;
  display: flex;
  flex-direction: column;
  gap: 5px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.event-log__action {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  display: block;
  height: 44px;
  padding: 0;
  position: relative;
  width: 44px;
}

.event-log__token {
  align-items: center;
  background: radial-gradient(circle at 42% 32%, #fcdea1 0 8%, #b97936 42%, #4a2512 72%);
  border: 3px solid #2b160d;
  border-radius: 12px 20px 12px 20px;
  box-shadow: inset 0 0 0 2px rgba(255, 230, 154, 0.48), 0 3px 7px var(--board-shadow);
  color: #fff2c5;
  display: flex;
  font: 700 19px/1 Georgia, serif;
  height: 44px;
  justify-content: center;
  overflow: hidden;
  text-shadow: 0 2px 2px #1f1009;
  transform: rotate(-1deg);
  transition: transform 140ms ease, filter 140ms ease;
  width: 44px;
}

.event-log__token-icon {
  display: block;
}

i.event-log__token-icon {
  font-size: 22px;
}

.event-log__resurrection-icon {
  display: block;
  filter: drop-shadow(0 1px 1px #1f1009);
  height: 27px;
  width: 27px;
}

.event-log__token.has-card-art {
  background-position: center;
  background-size: cover;
}

.event-log__token.has-card-art.has-loaded-art {
  color: transparent;
  text-shadow: none;
}

.event-log__token.is-tap {
  font-size: 24px;
}

.event-log__token.is-opponent {
  box-shadow: inset 0 0 0 2px rgba(255, 230, 154, 0.4), 0 4px 8px rgba(18, 8, 4, 0.7);
}

.event-log__token.is-boundary {
  background: radial-gradient(circle at 40% 35%, #f9dd8b, #8a5522 55%, #3b1e0e);
  border-radius: 50%;
  font-size: 18px;
  height: 40px;
  margin: 2px;
  width: 40px;
}

.event-log__action:hover .event-log__token,
.event-log__action:focus-visible .event-log__token,
.event-log__action[aria-expanded="true"] .event-log__token {
  box-shadow: inset 0 0 0 2px rgba(255, 230, 154, 0.35), 0 8px 12px rgba(18, 8, 4, 0.78);
  filter: brightness(1.17);
  transform: translateX(3px) rotate(1deg) scale(1.06);
}

.event-log__action:focus-visible {
  outline: 0;
}

.event-log__action:focus-visible .event-log__token {
  box-shadow: 0 0 0 3px #fff2a8, 0 4px 10px var(--board-shadow);
}

.event-log__popover {
  background: linear-gradient(100deg, #f4e2b8, #dfc28a);
  border: 2px solid #6b3d1d;
  border-radius: 7px;
  box-shadow: 0 8px 18px var(--board-shadow), inset 0 0 0 2px rgba(255, 248, 215, 0.55);
  color: var(--board-ink);
  left: 57px;
  min-width: 226px;
  opacity: 0;
  padding: 9px 12px;
  pointer-events: none;
  position: absolute;
  text-align: left;
  top: 50%;
  transform: translate(-7px, -50%);
  transition: opacity 120ms ease, transform 120ms ease;
  z-index: 2250;
}

.event-log__popover::before {
  border-bottom: 7px solid transparent;
  border-right: 9px solid #6b3d1d;
  border-top: 7px solid transparent;
  content: "";
  left: -10px;
  position: absolute;
  top: calc(50% - 7px);
}

.event-log__popover strong {
  color: var(--board-ink);
  display: block;
  font: 700 13px/1.25 Georgia, serif;
}

.event-log__popover span {
  color: #6e5136;
  display: block;
  font-size: 10px;
  margin-top: 3px;
}

.event-log__action:hover .event-log__popover,
.event-log__action:focus-visible .event-log__popover,
.event-log__action[aria-expanded="true"] .event-log__popover {
  opacity: 1;
  transform: translate(0, -50%);
}

.event-log__ledger-toggle {
  align-items: center;
  background: linear-gradient(#e9c56e, #8d5723);
  border: 2px solid #3d200f;
  border-radius: 50%;
  box-shadow: inset 0 1px 0 #fff0ac, 0 3px 7px var(--board-shadow);
  color: #351b0b;
  cursor: pointer;
  display: flex;
  font: 900 16px/1 Georgia, serif;
  height: 44px;
  justify-content: center;
  padding: 0;
  width: 44px;
}

.event-log__ledger-toggle:hover,
.event-log__ledger-toggle:focus-visible {
  filter: brightness(1.15);
  outline: 2px solid #ffed9b;
  outline-offset: 2px;
}

.event-log__ledger {
  background: linear-gradient(100deg, rgba(238, 216, 169, 0.98), rgba(207, 173, 112, 0.98));
  border: 3px solid #5c3218;
  border-radius: 7px 18px 18px 7px;
  box-shadow: 0 20px 45px var(--board-shadow), inset 0 0 0 2px rgba(255, 245, 211, 0.65);
  color: var(--board-ink);
  display: flex;
  flex-direction: column;
  left: 162px;
  max-height: calc(100vh - 72px);
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  position: fixed;
  top: 50%;
  transform: translate(-18px, -50%) scale(0.98);
  transition: opacity 160ms ease, transform 160ms ease;
  width: min(340px, calc(100vw - 450px));
  z-index: 2240;
}

/* Slice 14B portrait hit testing (720x960): the owner hand strip
   (body:has(.board) .hand-current-player, z-index 2260 from Slice
   9C) physically covered the open ledger's scrolled Load older control, so
   elementFromPoint returned the hand's drop-zone and real clicks sent zero
   requests. The controller root is itself a stacking context (position +
   z-index 2200), so no descendant z-index could ever reach past it while it
   stays capped below the hand. While the ledger is open the root releases
   its stacking context (z-index: auto) — nothing is raised, the closed
   board keeps its verified Slice 9C paint order — and the open ledger
   itself then competes directly with the hand at 2270, clearing it while
   staying below the deck picker (2300) and the card-move chrome
   (2340/2400). The release is scoped to the open state, so the rail, hero
   zones, and command center keep their below-hand order exactly as shipped
   whenever the ledger is closed. */
.board[data-board-ledger-open-value="true"] {
  z-index: auto;
}

.board[data-board-ledger-open-value="true"] .event-log__ledger {
  opacity: 1;
  pointer-events: auto;
  transform: translate(0, -50%) scale(1);
  z-index: 2270;
}

.event-log__ledger-header {
  align-items: center;
  background: linear-gradient(90deg, #71411f, #4a2814);
  border-bottom: 2px solid #32190d;
  color: #fff0c5;
  display: flex;
  justify-content: space-between;
  padding: 13px 14px;
  text-shadow: 0 1px 2px #1a0d07;
}

.event-log__ledger-header p {
  color: #d9bd86;
  font-size: 9px;
  letter-spacing: 0.16em;
  margin: 0 0 3px;
  text-transform: uppercase;
}

.event-log__ledger-header h2 {
  color: #fff0c5;
  font: 700 20px/1 Georgia, serif;
  margin: 0;
}

.event-log__ledger-close {
  background: #2f180d;
  border: 1px solid #b78945;
  border-radius: 50%;
  color: #ffe0a0;
  cursor: pointer;
  font-size: 17px;
  height: 44px;
  padding: 0;
  width: 44px;
}

.event-log__ledger-close:hover,
.event-log__ledger-close:focus-visible {
  background: #5a3219;
  outline: 2px solid #ffe0a0;
}

.event-log__ledger-status {
  align-items: center;
  border-bottom: 1px solid rgba(76, 43, 20, 0.35);
  display: flex;
  gap: 10px;
  padding: 10px 14px;
}

.event-log__ledger-status-badge {
  align-items: center;
  background: #72451f;
  border: 2px solid #3c210f;
  border-radius: 50%;
  color: #ffe3a3;
  display: flex;
  font: 800 10px/1 Georgia, serif;
  height: 34px;
  justify-content: center;
  width: 34px;
}

.event-log__ledger-status strong {
  display: block;
  font: 700 13px/1.2 Georgia, serif;
}

.event-log__ledger-status span {
  color: #73573b;
  font-size: 10px;
}

.event-log__ledger-scroll {
  overflow: auto;
  padding: 8px 14px 15px;
}

.event-log__ledger-turn {
  align-items: center;
  color: #795225;
  display: flex;
  font: 800 9px/1 Georgia, serif;
  gap: 8px;
  letter-spacing: 0.14em;
  margin: 11px 0 6px;
  text-transform: uppercase;
}

.event-log__ledger-turn::after {
  background: rgba(105, 70, 33, 0.35);
  content: "";
  flex: 1;
  height: 1px;
}

.event-log__ledger-event {
  align-items: flex-start;
  display: grid;
  gap: 9px;
  grid-template-columns: 25px 1fr;
  padding: 7px 0;
}

.event-log__ledger-event > span {
  align-items: center;
  background: #6b3e1d;
  border: 1px solid #3a1d0c;
  border-radius: 50%;
  color: #ffe5aa;
  display: flex;
  font: 700 14px/1 Georgia, serif;
  height: 25px;
  justify-content: center;
  margin-top: 1px;
  text-shadow: 0 1px #2a1308;
}

.event-log__ledger-event i.event-log__token-icon {
  font-size: 14px;
}

.event-log__ledger-event .event-log__resurrection-icon {
  filter: none;
  height: 17px;
  width: 17px;
}

.event-log__ledger-event strong {
  display: block;
  font-size: 11px;
  line-height: 1.25;
}

.event-log__ledger-event small {
  color: #74583e;
  display: block;
  font-size: 9px;
  margin-top: 2px;
}

/* Slice 14B: the ledger's honest empty state and the older-page control. */
.event-log__ledger-empty {
  color: #74583e;
  font-size: 11px;
  line-height: 1.4;
  margin: 12px 0;
  padding: 0 2px;
}

/* Slice 14B review: the load-older control is the ledger's one actionable
   link, so it carries the 44px touch minimum like every other gated control;
   its ~29px content height alone left the target well under the floor. The
   flex centering keeps the label vertically centered inside the taller box. */
.event-log__ledger-older {
  align-items: center;
  background: #6f401d;
  border: 1px solid #3a1d0c;
  border-radius: 10px;
  color: #ffe5aa;
  display: flex;
  font: 700 11px/1 Georgia, serif;
  justify-content: center;
  margin: 12px 0 2px;
  min-height: 44px;
  padding: 8px 10px;
  text-decoration: none;
}

.event-log__ledger-older:hover,
.event-log__ledger-older:focus-visible {
  background: #8a5522;
  outline: 2px solid #ffed9b;
  outline-offset: 2px;
}

.board__command-center {
  align-items: center;
  display: flex;
  filter: drop-shadow(0 9px 13px var(--board-shadow));
  position: fixed;
  right: 24px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2230;
}

.board__turn-status {
  background: linear-gradient(90deg, #4a2814, #7f4922);
  border: 2px solid #2e160a;
  border-radius: 18px 4px 4px 18px;
  color: #f4dca9;
  margin-right: -10px;
  min-width: 112px;
  padding: 8px 20px 8px 13px;
  text-align: right;
  text-shadow: 0 1px 2px #1a0d07;
}

.board__turn-status small {
  color: #d6b97d;
  display: block;
  font-size: 8px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.board__turn-status strong {
  display: block;
  font: 700 12px/1.2 Georgia, serif;
  margin-top: 2px;
}

.board__command-orbit {
  height: 168px;
  position: relative;
  width: 142px;
}

.board__pass-turn {
  align-items: center;
  background: radial-gradient(circle at 42% 32%, #ffe598 0 8%, #d79a32 40%, #754018 72%);
  border: 4px solid #3a1c0b;
  border-radius: 50%;
  box-shadow: inset 0 0 0 3px #f6d274, inset 0 -7px 12px rgba(52, 25, 9, 0.42), 0 0 0 3px rgba(217, 162, 65, 0.55);
  color: #351807;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  font: 900 12px/1.04 Georgia, serif;
  height: 88px;
  justify-content: center;
  letter-spacing: 0.05em;
  padding: 0;
  position: absolute;
  right: 0;
  text-shadow: 0 1px #ffe9a8;
  text-transform: uppercase;
  top: 40px;
  transition: filter 140ms ease, transform 140ms ease;
  width: 88px;
  z-index: 3;
}

.board__pass-turn b {
  font-size: 18px;
  line-height: 0.8;
  margin-top: 4px;
}

.board__pass-turn:hover,
.board__pass-turn:focus-visible {
  filter: brightness(1.16);
  outline: 3px solid #fff0a1;
  outline-offset: 3px;
  transform: scale(1.04);
}

.board__pass-turn.is-waiting,
.board__pass-turn:disabled {
  background: radial-gradient(circle at 40% 35%, #a9ddf2, #4e93b7 48%, #244b62 75%);
  box-shadow: inset 0 0 0 3px #9fd2e7, inset 0 -7px 12px rgba(17, 45, 61, 0.45), 0 0 0 3px rgba(91, 159, 193, 0.45);
  color: #102f40;
  cursor: default;
  filter: none;
  font-size: 10px;
  text-shadow: 0 1px #d8f3ff;
  transform: none;
}

.board__command-button {
  align-items: center;
  background: radial-gradient(circle at 42% 30%, #edcc80, #925b27 58%, #42200e);
  border: 3px solid #2a1409;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px rgba(255, 231, 160, 0.4), 0 4px 8px var(--board-shadow);
  color: #2b1509;
  cursor: pointer;
  display: flex;
  font: 900 16px/1 Georgia, serif;
  height: 44px;
  justify-content: center;
  padding: 0;
  position: absolute;
  width: 44px;
  z-index: 4;
}

.board__command-button:hover,
.board__command-button:focus-visible,
.board__command-button.is-active {
  filter: brightness(1.2);
  outline: 2px solid #ffefaa;
  outline-offset: 2px;
  transform: scale(1.08);
}

/* Slice 5: while an authoritative command is in flight the dock marks itself
   busy and disables every command button; an exhausted deck keeps its draw
   buttons disabled. Dimming is feedback only — geometry never changes. */
.board__command-center[aria-busy="true"] .board__command-button,
.board__command-button:disabled {
  cursor: default;
  filter: grayscale(0.4);
  opacity: 0.6;
  transform: none;
}

.board__command-button .icon {
  font-size: 24px;
}

/* Slice 6: the menu actions share the same busy/disabled feedback as the
   primary dock buttons, also without any geometry change. */
.board__command-menu button:disabled {
  cursor: default;
  filter: grayscale(0.4);
  opacity: 0.6;
}

.board__command-button.is-untap {
  left: 42px;
  top: 0;
}

.board__command-button.is-draw {
  left: 8px;
  top: 39px;
}

.board__command-button.is-draw-seven {
  bottom: 39px;
  left: 8px;
}

.board__command-button.is-menu {
  bottom: 0;
  font-size: 11px;
  left: 42px;
}

.board__command-menu {
  background: linear-gradient(100deg, #f0dba9, #c69b5d);
  border: 2px solid #4b2914;
  border-radius: 12px;
  box-shadow: 0 10px 20px var(--board-shadow);
  display: grid;
  gap: 5px;
  opacity: 0;
  padding: 7px;
  pointer-events: none;
  position: absolute;
  /* 260px keeps the open menu clear of the turn-status plate at wide
     viewports: the old 232px right edge (1280 at 1536x900) overlapped the
     plate's left edge (1261) by 19px and clipped its leading "T". Runtime
     measured 7.59px gap at 259px; 260px measures 8.59px clearance. */
  right: 260px;
  top: 50%;
  transform: translate(8px, -50%);
  transition: opacity 120ms ease, transform 120ms ease;
  width: 148px;
  z-index: 2;
}

/* The closed menu is display-none on top of transparent/inert: never rely on
   opacity alone for unavailability. */
.board__command-menu[hidden] {
  display: none;
}

.board__command-menu.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translate(0, -50%);
}

/* Every overflow row — commands, Help disclosure, and lobby navigation —
   shares one 44px touch target and visual language. */
.board__command-menu :is(button, a) {
  align-items: center;
  background: #5f3519;
  border: 1px solid #2f180b;
  border-radius: 7px;
  color: #ffe7b5;
  cursor: pointer;
  display: flex;
  font-size: 10px;
  justify-content: flex-start;
  line-height: 1.2;
  min-height: 44px;
  padding: 6px 8px;
  text-align: left;
  text-decoration: none;
}

.board__command-menu :is(button, a):hover,
.board__command-menu :is(button, a):focus-visible {
  background: #7b4924;
  outline: 2px solid #fff0a1;
}

.board__command-menu button.is-danger {
  background: #6b2720;
}

/* The Help disclosure is a navigation item, not a command: same chrome, but
   visually separated from the mutating actions above it. */
.board__command-menu button.is-disclosure {
  border-top: 1px solid rgba(79, 41, 20, 0.55);
  margin-top: 2px;
}

/* Slice 9B: gated Help dialog on the native top layer. The browser paints
   the top layer above every board chrome regardless of z-index, so the
   dialog itself needs no z-index at all. Geometry stays responsive: capped
   width/height with viewport fallbacks, no horizontal overflow. No display
   or margin here: the closed shell keeps its native display:none, and the
   [open] rule below owns the flex geometry and centering. */
.board__help-dialog {
  background: linear-gradient(160deg, #f4e3ba, #d9b57c);
  border: 3px solid #4b2914;
  border-radius: 14px;
  box-shadow: 0 24px 60px var(--board-shadow), inset 0 0 0 2px rgba(255, 231, 160, 0.35);
  color: var(--board-ink);
  max-height: min(80vh, 640px);
  max-width: min(420px, calc(100vw - 32px));
  padding: 0;
}

/* Open-state geometry only: Tailwind preflight resets margin on every
   element, which kills the UA dialog{margin:auto} centering showModal
   relies on — margin:auto here restores it. Flex column applies only while
   open, so the closed shell stays display:none (setting display:flex on the
   base rule would render a closed dialog). The header is flex-none and the
   body min-height:0/flex:1/overflow:auto below, so no header-height
   subtraction is ever needed. */
.board__help-dialog[open] {
  display: flex;
  flex-direction: column;
  margin: auto;
}

.board__help-dialog::backdrop {
  background: rgba(18, 9, 4, 0.62);
}

.board__help-header {
  align-items: center;
  border-bottom: 2px solid rgba(75, 41, 20, 0.45);
  display: flex;
  flex: none;
  gap: 12px;
  justify-content: space-between;
  padding: 14px 16px;
}

.board__help-title {
  font: 700 16px/1.2 Georgia, serif;
  margin: 0;
}

.board__help-close {
  background: #5f3519;
  border: 2px solid #2f180b;
  border-radius: 8px;
  color: #ffe7b5;
  cursor: pointer;
  font-size: 12px;
  min-height: 44px;
  min-width: 76px;
  padding: 6px 12px;
}

.board__help-close:hover,
.board__help-close:focus-visible {
  background: #7b4924;
  outline: 2px solid #fff0a1;
}

/* The body scrolls while the header stays pinned; the dialog's own
   max-height plus the flex column owns the geometry at any header height —
   no hard-coded subtraction to keep in sync. */
.board__help-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 16px 16px;
}

.board__help-table-name {
  font: 700 15px/1.3 Georgia, serif;
  margin: 0 0 4px;
}

.board__help-description {
  color: #5c4327;
  font-size: 12px;
  line-height: 1.45;
  margin: 0 0 10px;
}

.board__help-roster {
  border-top: 1px solid rgba(75, 41, 20, 0.35);
  display: grid;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 10px 0 0;
}

.board__help-roster li {
  display: grid;
  gap: 2px;
}

.board__help-player-name {
  font-weight: 600;
  font-size: 13px;
}

.board__help-deck-name {
  color: #6d4a26;
  font-size: 11px;
}

@media (max-width: 900px) {
  body:has(.board) .current-player-area,
  body:has(.board) .other-player-area {
    grid-template-columns: 1fr;
    padding-left: 112px;
    padding-right: 180px;
  }

  .board__hero-area {
    grid-template-columns: minmax(0, 1fr) 58px;
    height: 74px;
    padding: 7px 9px 7px 12px;
    right: 10px;
    width: 174px;
  }

  .board__hero-area--opponent {
    top: 10px;
  }

  .board__hero-area--current {
    bottom: 10px;
  }

  .board__hero-portrait {
    height: 58px;
    width: 58px;
  }

  .board__hero-identity strong {
    font-size: 10px;
  }

  .board__hero-identity span {
    font-size: 7px;
  }

  .board__hero-identity .board__hero-deck-opener {
    font-size: 7px;
  }

  .board__life {
    bottom: -7px;
    height: 37px;
    left: -17px;
    width: 37px;
  }


  .board__life strong {
    font-size: 12px;
  }

  .board__life button {
    height: 44px;
    top: -5px;
    width: 44px;
  }

  /* Compact orb is 37px: the increment tucks in so its glyph still centers
     on the right rim; the decrement inherits the base -25px rule unchanged. */
  .board__life button:last-child {
    left: 12px;
  }

  .board__deck-zone {
    height: 81px;
    right: 18px;
    transform: scale(0.78);
    transform-origin: top right;
  }

  .board__deck-zone--opponent {
    top: 110px;
  }

  .board__deck-zone--current {
    bottom: 110px;
    right: 50px;
    transform: none;
    transform-origin: bottom right;
  }

  .board__graveyard-zone {
    height: 80px;
    left: 10px;
    transform: scale(0.78);
    width: 96px;
  }

  .board__graveyard-zone--opponent {
    top: 10px;
    transform-origin: top left;
  }

  .board__graveyard-zone--current {
    bottom: 10px;
    transform-origin: bottom left;
  }

  .event-log__rail {
    left: 19px;
    transform: translateY(-50%);
  }

  .event-log__ledger {
    left: 96px;
    width: min(320px, calc(100vw - 300px));
  }

  .board__command-center {
    right: 4px;
    transform: translateY(-50%);
    transform-origin: right center;
  }

  .board__command-menu {
    /* The compact dock ends 4px from the viewport edge. A 230px inset keeps
       the 148px menu at least 8px inside a 390px viewport. */
    right: 230px;
  }

  .board__turn-status {
    display: none;
  }
}

@media (max-width: 600px) {
  .event-log__ledger {
    left: 16px;
    width: min(340px, calc(100vw - 32px));
  }
}

@media (max-height: 680px) {
  .event-log__recent-events li:nth-child(2),
  .event-log__recent-events li:nth-child(3) {
    display: none;
  }
}

/* Checkpoint B (D-NEW-1, re-cut): compact coexistence of the owner hand and
   the gated graveyard zone. Two failure modes were measured on the live
   board (evidence s2b-hand-grave-overlap-portrait.json; 0/25 zone points
   reachable at 720x960):

   1. The gated graveyard zone moves into its compact bottom-left corner at
      THIS 900px breakpoint (left 10px, width 96px, scale(0.78) -> rendered
      x=10..85) — not at 768. Any hand reservation bounded to <=768 left the
      769-900 window uncovered while the zone still sat in the corner.
   2. The strip's pointer-enabled content wrapper (.floating-hand > div,
      pointer-events:auto) fills the strip's content box and paints a
      full-width drop-zone hit surface over that corner; when its centered
      content (justify-content:center !important from the base rule) is
      wider than the wrapper, the overflow spills BOTH directions — left
      spill lands straight back on the graveyard.

   Fix, gated to the mock board only:
   - padding-left on the pointer-transparent strip reserves the keep-clear
     gutter. Tailwind preflight sets border-box sizing, so the 95vw strip
     keeps its outer box (no document overflow at <=768) while the wrapper's
     hit surface starts right of the zone. 122px = compact zone left 10 +
     width 96 (unscaled, the conservative bound over its scale(0.78) render)
     + 16px clearance.
   - flex-start !important on the wrapper pins content to the reservation
     edge: any overflow goes right, away from the zone. Exact selector
     specificity over the base `.floating-hand > div` center rule, and this
     stylesheet loads after table.css in the bundle.
   - The deepened card overlap (inline -60px becomes -95px) is needed for
     the 7-card hand to fit the narrowed content box at the smallest
     portrait widths; it is scoped to the compact block so the wide board
     keeps its verified -60px spread.
   No z-index, no transforms (the <=768 strip contract transform:none stays),
   no hiding — the reservation is purely spatial. The opponent strip sits at
   the top edge with no corner zone to clear and is untouched, as is the
   ungated default board. */
@media (max-width: 900px) {
  body:has(.board) .hand-current-player {
    padding-left: 122px;
    padding-right: 132px;
  }

  body:has(.board) .hand-current-player > div {
    justify-content: flex-start !important;
    width: 100%;
  }

  body:has(.board) .hand-current-player [data-hand-target="card"] + [data-hand-target="card"] {
    margin-left: -95px !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .event-log__action,
  .board__command-button,
  .board__command-menu,
  .board__deck-card,
  .board__deck-count,
  .board__graveyard-card,
  .board__graveyard-pile,
  .event-log__ledger,
  .board__pass-turn,
  .event-log__popover,
  .event-log__token {
    transition: none;
  }
}

.avatar-crop {
  background: #321b10;
  border: 3px solid #d9ad55;
  border-radius: 22px;
  box-shadow: 0 18px 60px #110905;
  color: #fff1ce;
  max-height: calc(100dvh - 24px);
  max-width: calc(100vw - 24px);
  overflow-y: auto;
  padding: 0;
  width: 430px;
}

.avatar-crop[open] {
  display: block;
  inset: 0;
  margin: auto;
}

.avatar-crop::backdrop {
  background: #120b08cf;
}

.avatar-crop__form {
  display: grid;
  gap: 14px;
  padding: 24px;
}

.avatar-crop__heading {
  align-items: flex-start;
  display: flex;
  justify-content: space-between;
}

.avatar-crop h2 {
  color: #ffe2a0;
  font: 700 25px/1.2 Georgia, serif;
}

.avatar-crop__heading p,
.avatar-crop__status {
  color: #e7c9a3;
  font-size: 13px;
}

.avatar-crop label {
  font-size: 14px;
  font-weight: 600;
}

.avatar-crop input[type="file"],
.avatar-crop input[type="text"] {
  max-width: 100%;
}

.avatar-crop input[type="text"] {
  background: #25100a;
  border: 1px solid #b9864e;
  border-radius: 9px;
  color: #fff1ce;
  min-height: 44px;
  padding: 9px 11px;
  width: 100%;
}

.avatar-crop input[type="text"]:focus-visible {
  outline: 3px solid #ffefaa;
  outline-offset: 2px;
}

.avatar-crop__frame {
  background: #25100a;
  border: 3px solid #e0b358;
  border-radius: 50%;
  height: 256px;
  margin: 0 auto;
  overflow: hidden;
  position: relative;
  touch-action: none;
  width: 256px;
}

.avatar-crop__frame[hidden] {
  display: none;
}

.avatar-crop__frame img {
  max-width: none;
  position: absolute;
  user-select: none;
}

.avatar-crop__zoom {
  margin-bottom: -12px;
}

.avatar-crop input[type="range"] {
  accent-color: #e0b358;
  width: 100%;
}

.avatar-crop__actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

.avatar-crop__actions button,
.avatar-crop__close {
  border: 1px solid #e0b358;
  border-radius: 10px;
  min-height: 44px;
  padding: 8px 14px;
}

.avatar-crop__save {
  background: #b56f30;
  color: #fff8e7;
  font-weight: 700;
}

.avatar-crop__actions button:focus-visible,
.avatar-crop__close:focus-visible {
  outline: 3px solid #ffefaa;
}

.avatar-crop__save:disabled {
  opacity: .6;
}

.avatar-crop__flash {
  animation: avatar-toast-fade 3s 300ms both;
  background: #321b10;
  border: 2px solid #e0b358;
  border-radius: 12px;
  color: #fff1ce;
  left: 50%;
  padding: 12px 20px;
  position: fixed;
  top: 12px;
  transform: translateX(-50%);
  z-index: 4000;
}

@keyframes avatar-toast-fade {
  0%, 100% { opacity: 0; }
  5%, 60% { opacity: 1; }
}