/* Clay Toy Theme - CSS Design System */

:root {
  /* Bright porcelain palette - airy, premium, still toy-friendly. The hot
     pink lives on only as the DEFAULT board cosmetic (--clay-board below is
     what board skins overwrite at runtime); menus/panels use the neutral
     --clay-panel surfaces instead. */
  --clay-bg: #f3f1fa; /* bright porcelain desk */
  --clay-board: #ff9fd6; /* Bubblegum pink play mat (DEFAULT board skin - cosmetic, runtime-overridden) */
  --clay-board-dark: #ee5fb0; /* Bubblegum pink mat border */
  /* Play-mat TEXTURE for the equipped board. Declared here so the default mat
     paints on first render; SkinsSystem.applyEquippedBoard() overrides it from
     the catalog (boardImage), and sets `none` for boards that are just a
     flat colour pair. Colour above stays as the backdrop/fallback. */
  --clay-board-image: url("assets/art/board-default.webp");

  /* Menu/panel surfaces - deliberately NOT the board cosmetic color */
  --clay-panel: #f8f6fe;
  --clay-panel-dark: #d9d3ee;

  --clay-red: #ff6b6b;
  --clay-red-dark: #cc4b4b;
  --clay-red-light: #ff9e9e;

  --clay-blue: #4dabf7;
  --clay-blue-dark: #228be6;
  --clay-blue-light: #a5d8ff;

  --clay-green: #51cf66;
  --clay-green-dark: #37b24d;
  --clay-green-light: #b2f2bb;

  --clay-yellow: #fcc419;
  --clay-yellow-dark: #f59f00;
  --clay-yellow-light: #ffe066;

  --clay-pink: #ff6fb5;
  --clay-pink-dark: #e64980;
  --clay-pink-light: #ffc2dd;

  --clay-purple: #cc5de8;
  --clay-purple-dark: #9c36b5;
  --clay-purple-light: #eebefa;

  --clay-white: #fefdff;
  --clay-white-dark: #e2ddf0; /* neutral lavender-grey border (was candy pink) */
  --clay-white-light: #ffffff;

  --clay-dark: #4a4463; /* deep slate-plum - calmer than the old bright purple */

  /* Text and shadows */
  --font-main: 'Fredoka', system-ui, -apple-system, sans-serif;

  /* Claymorphic Shadows - softer/diffused for the premium bright look */
  --clay-shadow-out: 0 8px 18px rgba(84, 74, 133, 0.16);
  --clay-shadow-in: inset 2px 2px 5px rgba(255, 255, 255, 0.8), inset -4px -4px 8px rgba(84, 74, 133, 0.12);

  --clay-btn-shadow: 0 4px 0px rgba(84, 74, 133, 0.18), inset 2px 2px 4px rgba(255, 255, 255, 0.7), inset -3px -3px 6px rgba(0, 0, 0, 0.12);
  --clay-btn-active: 0 1px 0px rgba(84, 74, 133, 0.18), inset 2px 2px 4px rgba(255, 255, 255, 0.7), inset -3px -3px 6px rgba(0, 0, 0, 0.12);

  /* Card shadow. A drop-shadow FILTER, not a box-shadow: card faces are
     rounded PNGs on a transparent canvas, so only drop-shadow follows their
     real silhouette (see .clay-card-element). Card art ships shadow-free -
     every card shadow in the game comes from here. */
  --card-shadow: drop-shadow(0 6px 9px rgba(84, 74, 133, 0.32));
  --card-shadow-raised: drop-shadow(0 14px 15px rgba(84, 74, 133, 0.38));
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  user-select: none;
  -webkit-user-drag: none;
}

body, html {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: var(--clay-bg);
  font-family: var(--font-main);
  color: var(--clay-dark);
}

/* <button>/input controls don't inherit the page font by default - force it so
   EVERY tab/nav/control uses Fredoka like the currency + body text (was: the
   bottom-nav and some tabs fell back to the system font). */
button, input, select, textarea {
  font-family: inherit;
}

/* Landscape Wrapper */
.landscape-wrapper {
  position: relative;
  width: 100vw;
  /* Mobile browsers count 100vh as the address-bar-HIDDEN height, so with the
     bar showing the bottom of the app falls below the fold (the "missing
     bottom quarter"). 100dvh tracks the CURRENTLY visible viewport instead;
     100vh stays as a fallback for browsers without dvh support. */
  height: 100vh;
  height: 100dvh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  /* Full-bleed background art (assets/bg.webp). Solid colour is the fallback
     while it loads / if it's missing. */
  background: #6d93bd url("assets/bg.webp") center / cover no-repeat;
}

/* Orientation Warning Screen */
.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(8px);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
  opacity: 1;
  transition: opacity 0.3s ease;
}

/* ===== Dust Shop ===== */
/* Dust Shop panel texture (Dust tab only): the collection scrim panel swaps its
   flat translucent fill for a knocked-back clay-checkerboard tile. The pattern
   is high-contrast (std ~11.5) and shares the item text/border palette, so a
   cream scrim at 0.72 over it drops the visible std to ~3.2 (faint texture, NOT
   a visible checkerboard) while keeping the header text at ~7:1 contrast. The
   two item cards + "Other Goods" box stay opaque and cover it - the texture only
   shows in the margins and behind the header. :has() scopes it to the Dust tab,
   so In Progress / Completed keep the ordinary dark scrim. Tiling: half-native
   scale (768px wide, aspect kept) => ~48px squares, background-repeat: repeat
   (never stretched, so the squares aren't distorted). */
#screen-collection .shop-items-scroll-area:has(#collection-panel-dust:not(.hidden)) {
  background-color: #efe6d3;
  background-image:
    linear-gradient(rgba(250, 244, 232, 0.72), rgba(250, 244, 232, 0.72)),
    url("assets/bgs/dust-shop-tile.webp");
  background-repeat: no-repeat, repeat;
  background-size: auto, 768px auto;
  background-position: center, center;
}

.dust-shop-box { display: flex; gap: 12px; align-items: stretch; }
.dust-shop-left { flex: 0 0 40%; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.dust-shop-right {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 12px;
}
.dust-pull-card {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 12px;
  cursor: pointer;
  text-align: left;
  box-shadow: var(--clay-shadow-out);
  transition: transform 0.1s ease;
}
.dust-pull-card:hover { transform: translateY(-2px); }
.dust-pull-random { border-color: #0ca678; }
.dust-pull-selected { border-color: #e8590c; }
.dust-pull-ad { border-color: #1c7ed6; } /* blue: free "watch an ad" Dust */
/* Already claimed today - dimmed, not clickable. */
.dust-pull-card.dust-claimed {
  opacity: 0.5;
  cursor: default;
  filter: saturate(0.7);
}
.dust-pull-card.dust-claimed:hover { transform: none; }
.dust-pull-icon { font-size: 1.7rem; }
.dust-pull-text { flex: 1 1 auto; min-width: 0; }
.dust-pull-title { font-weight: 800; color: var(--clay-dark); font-size: 0.88rem; }
.dust-pull-desc { font-size: 0.7rem; opacity: 0.72; color: var(--clay-dark); }
.dust-pull-price { font-weight: 800; color: #b06bd6; white-space: nowrap; }
.dust-goods-title { font-weight: 800; color: var(--clay-dark); margin-bottom: 8px; }
.dust-goods-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 8px; }
.dust-goods-soon {
  grid-column: 1 / -1;
  text-align: center;
  opacity: 0.55;
  padding: 44px 12px;
  font-weight: 600;
  color: var(--clay-dark);
  line-height: 1.7;
}
.dust-sets-back { margin-bottom: 10px; }
.dust-sets-hint { font-size: 0.8rem; opacity: 0.75; margin-bottom: 10px; color: var(--clay-dark); }
.dust-sets-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(108px, 1fr)); gap: 10px; }
.dust-set-tile { cursor: pointer; }

/* Historical ECP tab: one row per ended event still holding unopened packs
   (kept forever - each opens against its own event's pool only). */
.history-packs-list { display: flex; flex-direction: column; gap: 10px; }
.history-packs-empty { text-align: center; padding: 24px 16px; color: var(--clay-dark); opacity: 0.7; font-weight: 600; }
.history-pack-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: #FDF8F0;
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 10px 14px;
  box-shadow: var(--clay-shadow-out);
}
.history-pack-circle .ecp-circle { width: 54px; height: 54px; border-width: 3px; gap: 0; }
.history-pack-circle .ecp-glyph { width: 24px; height: 24px; }
.history-pack-circle .ecp-circle-date { font-size: 0.5rem; }
.history-pack-info { flex: 1; min-width: 0; }
.history-pack-name { font-weight: 800; color: var(--clay-dark); font-size: 0.95rem; }
.history-pack-hint { font-size: 0.75rem; font-weight: 600; color: var(--clay-dark); opacity: 0.7; }
.history-pack-badge { flex-shrink: 0; }
.history-pack-open { flex-shrink: 0; padding: 8px 14px; font-size: 0.85rem; }

.dust-confirm-card { max-width: 320px; text-align: center; }
.dust-confirm-card h3 { margin: 0 0 8px; color: var(--clay-dark); }
.dust-confirm-card p { color: var(--clay-dark); opacity: 0.85; margin: 0 0 16px; }
.dust-confirm-actions { display: flex; gap: 12px; justify-content: center; }

/* Dust-reward info popup (shown once the collection is complete). */
.ecp-dust-info-card {
  max-width: 340px;
  text-align: center;
}
.ecp-dust-info-card h3 { margin: 0 0 8px; color: var(--clay-dark); }
.ecp-dust-info-card p { font-size: 0.85rem; color: var(--clay-dark); opacity: 0.85; margin: 0 0 12px; }
.ecp-dust-info-list {
  list-style: none;
  padding: 0;
  margin: 0 0 16px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.ecp-dust-info-list li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  background: var(--clay-white-light);
  border: 2px solid var(--clay-white-dark);
  border-radius: 12px;
  padding: 7px 12px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--clay-dark);
  text-align: left;
}
.ecp-dust-amt { color: #b06bd6; white-space: nowrap; }

/* ===== Batch ECP open (sealed pack -> cut -> spread -> flip) ===== */
.pack-batch-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  max-width: 94vw;
}
.pack-batch-count {
  position: absolute;
  top: 8%;
  right: calc(50% - 128px);
  background: var(--clay-yellow);
  color: var(--clay-dark);
  font-weight: 900;
  font-size: 1.15rem;
  padding: 4px 13px;
  border-radius: 999px;
  border: 3px solid var(--clay-yellow-dark);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
  z-index: 10;
}
/* Event circle (differentiates the event: gold month symbol + MM.YY on the
   event's colour). Rest of the pack is shared across all ECP. */
.ecp-circle {
  border-radius: 50%;
  border: 4px solid;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  width: 96px;
  height: 96px;
  box-shadow: inset 0 3px 8px rgba(255, 255, 255, 0.25), 0 4px 10px rgba(0, 0, 0, 0.3);
}
/* ECP identity = the royal-crown card back: the event circle wears its
   purple clay TEXTURE (ecp-texture.webp, cropped from card-back.webp below
   the medallion). Dust-shop circles keep their flat theme colours - this
   class is only added by eventCircleHtml. */
.ecp-circle-crown {
  background: #55457e url("assets/cards/ecp-texture.webp") center / cover no-repeat;
  border-color: #3d325b;
}
/* Circle + its MM.YY caption UNDERNEATH (the date moved out of the circle). */
.ecp-circle-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
/* On the cream Historical-ECP rows the white caption text has no contrast. */
.history-pack-row .ecp-circle-date { color: var(--clay-dark); text-shadow: none; }
.ecp-glyph {
  width: 42px;
  height: 42px;
  fill: #ffd24a;
  stroke: none;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
}
.ecp-circle-date {
  font-size: 0.72rem;
  font-weight: 800;
  color: #fff;
  letter-spacing: 0.06em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
/* Sealed pack */
.ecp-pack {
  width: 152px;
  height: 212px;
  border-radius: 20px;
  /* Royal-crown purple clay (the ECP identity); dust-shop themes override
     this with their own flat gradients below. */
  background: #55457e url("assets/cards/ecp-texture.webp") center / cover no-repeat;
  border: 4px solid rgba(255, 255, 255, 0.4);
  box-shadow: 0 12px 26px rgba(0, 0, 0, 0.38), inset 0 2px 8px rgba(255, 255, 255, 0.2);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.ecp-pack-lid {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 34px;
  /* Same crown clay, lightened so the tear-off lid still reads as a lid. */
  background: linear-gradient(rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0.28)), url("assets/cards/ecp-texture.webp") center / cover no-repeat;
  border-bottom: 2px dashed rgba(255, 255, 255, 0.55);
  transform-origin: top center;
  transition: transform 0.45s ease, opacity 0.45s ease;
  z-index: 3;
}
/* Dust Shop packs: permanent, distinct colours (vs ECP + each other). */
.ecp-pack.pack-theme-dust-random { background: linear-gradient(160deg, #38d9a9, #099268); }
.ecp-pack.pack-theme-dust-random .ecp-pack-lid { background: linear-gradient(160deg, #63e6be, #0ca678); }
.ecp-pack.pack-theme-dust-selected { background: linear-gradient(160deg, #ffa94d, #e8590c); }
.ecp-pack.pack-theme-dust-selected .ecp-pack-lid { background: linear-gradient(160deg, #ffc078, #f76707); }

.pack-batch-sealed.cut .ecp-pack-lid { transform: translateY(-46px) rotate(-9deg); opacity: 0; }
.pack-batch-sealed.cut .ecp-pack { animation: ecp-pack-pop 0.45s ease; }
@keyframes ecp-pack-pop { 50% { transform: translateY(-10px) scale(1.05); } }

/* Spread of revealed cards */
.pack-batch-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  align-content: center;
  max-width: 92vw;
  perspective: 1100px;
}
.reveal-card {
  position: relative;
  width: 74px;
  height: 104px;
  opacity: 0;
  transform: translateY(34px) scale(0.55);
  transition: opacity 0.35s ease, transform 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.35);
  transition-delay: calc(var(--i) * 55ms);
}
/* Rarity glow aura behind the card (revealed once flipped). */
.reveal-aura {
  position: absolute;
  inset: -13px;
  border-radius: 50%;
  z-index: -1;
  opacity: 0;
  filter: blur(8px);
  transition: opacity 0.45s ease;
}
.reveal-card.flipped .reveal-aura { opacity: 1; }
.rarity-number .reveal-aura { background: radial-gradient(circle, rgba(255, 255, 255, 0.35), transparent 70%); }
.rarity-special .reveal-aura { background: radial-gradient(circle, rgba(77, 171, 247, 0.95), transparent 70%); }
.rarity-attack .reveal-aura { background: radial-gradient(circle, rgba(160, 90, 235, 0.95), transparent 70%); }
.rarity-king .reveal-aura { background: radial-gradient(circle, rgba(255, 205, 70, 1), transparent 68%); }
.rarity-joker .reveal-aura {
  background: conic-gradient(from 0deg, #ff5f6d, #ffc371, #4dff88, #4dabf7, #b06bd6, #ff5f6d);
  border-radius: 50%;
  animation: joker-prism-spin 2.4s linear infinite;
}
.reveal-card.flipped.rarity-joker .reveal-aura { opacity: 0.95; }
@keyframes joker-prism-spin { to { transform: rotate(360deg); } }
.pack-batch-cards.spread .reveal-card { opacity: 1; transform: none; }
.reveal-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.55s ease;
}
.reveal-card.flipped .reveal-card-inner { transform: rotateY(180deg); }
.reveal-card-back,
.reveal-card-front {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.reveal-card-back {
  /* The royal-crown PLAIN CLAY texture (same tile as the sealed pack), NOT
     the full card art - the art's gold medallion ring peeked out from behind
     the overlaid month circle as a stray gold arc. */
  background: #55457e url("assets/cards/ecp-texture.webp") center / cover no-repeat;
  border: 3px solid rgba(255, 255, 255, 0.35);
}
.reveal-card-back .ecp-circle { width: 50px; height: 50px; border-width: 3px; gap: 0; }
.reveal-card-back .ecp-glyph { width: 22px; height: 22px; }
.reveal-card-back .ecp-circle-date { font-size: 0.48rem; }
/* No background here: the frame art is a rounded card inside a transparent
   600x840 canvas, so any face colour shows as cream bars above/below the art. */
.reveal-card-front { transform: rotateY(180deg); }
.reveal-card-front .clay-card-element { position: relative; width: 100%; height: 100%; }
.reveal-tag {
  position: absolute;
  bottom: 3px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.52rem;
  font-weight: 800;
  padding: 1px 7px;
  border-radius: 8px;
  white-space: nowrap;
  z-index: 5;
}
.reveal-tag.new { background: var(--clay-green); color: #fff; }
.reveal-tag.dust { background: rgba(0, 0, 0, 0.6); color: #ffe9a8; }
.pack-batch-hint {
  margin-top: 20px;
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  opacity: 0.9;
  animation: tap-hint-pulse 1.3s ease-in-out infinite;
}

/* The played card's symbol glyph shown as the title of an in-match effect
   pop-up (spawnTextAlert), in place of the player name. */
.alert-symbol {
  width: 58px;
  height: 58px;
  object-fit: contain;
  display: block;
  margin: 0 auto 2px;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25));
}

/* Joker cue (triggerJokerOverlay): the glyph alone over a dimmed board, no
   worded banner. Pointer-events off so it never eats a tap mid-animation. */
.joker-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 400;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity 0.25s ease;
}
.joker-overlay.visible { opacity: 1; }
.joker-overlay-glyph {
  width: min(42vw, 220px);
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.45));
  transform: scale(0.55);
  transition: transform 0.45s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.joker-overlay.visible .joker-overlay-glyph { transform: scale(1); }

/* Collection board: newly-collected tiles flip in after a batch open. */
@keyframes tile-reveal-flip {
  0% { transform: rotateY(88deg) scale(0.9); }
  55% { transform: rotateY(-14deg) scale(1.08); }
  100% { transform: rotateY(0) scale(1); }
}
.event-card-tile.tile-reveal,
.ccb-tile.tile-reveal {
  animation: tile-reveal-flip 0.55s ease;
  z-index: 2;
}

.overlay.hidden {
  display: none !important;
  opacity: 0;
  pointer-events: none;
}

.clay-card {
  background: var(--clay-white);
  border-radius: 24px;
  padding: 24px;
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  border: 4px solid var(--clay-white-dark);
  text-align: center;
}

.warning-content {
  width: 320px;
  background: var(--clay-yellow-light);
  border-color: var(--clay-yellow-dark);
}

.toy-icon {
  font-size: 3rem;
  margin-bottom: 12px;
  animation: wobble 2s infinite ease-in-out;
}

@keyframes wobble {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(10deg) scale(1.05); }
  75% { transform: rotate(-10deg) scale(0.95); }
}

/* Screen titles were previously unstyled h2s (browser defaults, oversized
   margins) - one consistent rule for every screen header. */
.section-title {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--clay-dark);
  margin: 0 0 10px;
}

/* Currency icons (assets/icons/*.webp) - inline PNG art replacing the old
   🪙/💎/✨ emojis. The source images have baked-in square backgrounds, so the
   circle crop (border-radius) turns them into clean round chips. Sized in em
   so they track whatever text they sit beside. */
.currency-icon {
  display: inline-block;
  width: 1.15em;
  height: 1.15em;
  border-radius: 50%;
  object-fit: cover;
  vertical-align: -0.2em;
}

/* Base Screen Style */
.screen {
  /* Each screen is its own stacking context: child z-indexes (e.g. the
     hand's paint-above-board rank) can never leak above a LATER screen
     (found live: the hand scroller blocked the game-over buttons). */
  isolation: isolate;
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.3s ease;
}

.screen.hidden {
  opacity: 0;
  pointer-events: none;
  transform: scale(0.9);
}

/* Per-screen background art. Uploaded PNGs were optimized to WebP in
   assets/art/; these opaque covers sit on top of the global
   .landscape-wrapper backdrop (assets/bg.webp) for their own screen only.
   Screens NOT listed here (lobby, settings, notifications, rules, match
   history, tutorial) intentionally keep the plain wrapper backdrop.

   These load lazily for free: .screen.hidden resolves to display:none, and a
   display:none element's background-image is never fetched - so only the
   visible screen's art is downloaded (home-bg is additionally preloaded in
   index.html, being the first screen seen).

   NOTE: the art is 1400x933 (3:2) while the app is landscape ~16:9, so `cover`
   fills the width and crops ~15.6% of the height (~7.8% off top and bottom).
   Accepted deliberately - the centres are quiet and only edge detail is lost.
   Revisit if the masters are ever re-exported at a true 16:9. */
#screen-home {
  background: url("assets/art/home-bg.webp") center / cover no-repeat;
}
#screen-shop {
  background: url("assets/art/shop-bg.webp") center / cover no-repeat;
}
/* Play-modes art is shared with the Select Players screen behind it, and with
   the online lobby / matchmaking screen that Multiplayer flows into - so the
   whole play path reads as one themed surface instead of the lobby dropping to
   the plain global backdrop. */
#screen-play-modes,
#screen-mode,
#screen-online-lobby {
  background: url("assets/art/play-modes-bg.webp") center / cover no-repeat;
}
#screen-event {
  background: url("assets/art/event-bg.webp") center / cover no-repeat;
}
#screen-inventory {
  background: url("assets/art/inventory-bg.webp") center / cover no-repeat;
}
/* (#screen-missions is a MODAL overlay now, not a screen - it shows the dim
   backdrop from .overlay and the screen behind it, so it takes no full-bleed
   art of its own. missions-bg.webp is used as the window's own surface below.) */
#screen-profile {
  background: url("assets/art/profile-bg.webp") center / cover no-repeat;
}
/* Collections art is shared with the Card Collection Board it opens into. */
#screen-collection,
#screen-ccb {
  background: url("assets/art/collections-bg.webp") center / cover no-repeat;
}
/* Match result: a dark night scene - a soft scrim keeps the title and
   standings readable, and the title/subtitle go light on top of it. */
#screen-game-over {
  background: linear-gradient(rgba(18, 22, 38, 0.35), rgba(18, 22, 38, 0.55)),
              url("assets/art/match-result.webp") center / cover no-repeat;
}
#screen-game-over .victory-title {
  color: #ffffff;
  text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35);
}
#screen-game-over .victory-subtitle {
  color: #f4f6ff;
  text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.55);
}

.clay-container {
  /* The outer "capsule" panel was removed by request - screens now sit
     directly on the full-bleed background (assets/bg.webp) with no frame, and
     fill the whole viewport so corner elements (back button, bottom nav) go
     to the true screen edges. Inner content boxes keep their own surfaces. */
  width: 100%;
  max-width: none;
  height: 100%;
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  /* base 30px, but never less than the device safe-area inset (notch / home
     indicator) so in-flow headers/currency aren't clipped on full-screen. */
  padding: max(30px, env(safe-area-inset-top)) max(30px, env(safe-area-inset-right)) max(30px, env(safe-area-inset-bottom)) max(30px, env(safe-area-inset-left));
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  position: relative;
}

/* Buttons (Claymorphism Style) */
.clay-btn {
  font-family: var(--font-main);
  font-weight: 700;
  font-size: 1.1rem;
  padding: 12px 24px;
  border: 4px solid rgba(0, 0, 0, 0.15);
  border-radius: 20px;
  cursor: pointer;
  outline: none;
  transition: transform 0.1s ease, box-shadow 0.1s ease;
  box-shadow: var(--clay-btn-shadow);
  color: white;
  text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.2);
}

/* (The old claymorphism :hover/:active elevation rules lived here. They were
   the "two-tone split" bug: the DESIGN REFRESH block at the end of this file
   gives every .clay-btn a solid coloured ledge (box-shadow 0 6px 0), but on
   hover these legacy rules swapped that for the pre-refresh soft inset
   elevation - so the ledge vanished and the old shadow layer showed through
   the face mid-interaction (worst on the home PLAY button and the mission
   CLAIM buttons, and :hover can stick after a tap on touch screens). The
   refresh block declares its own :hover/:active; these had to go. */

.btn-primary {
  background: var(--clay-blue);
  border-color: var(--clay-blue-dark);
}
.btn-secondary {
  background: var(--clay-white);
  color: var(--clay-dark);
  text-shadow: none;
  border-color: var(--clay-white-dark);
}
.btn-success {
  background: var(--clay-green);
  border-color: var(--clay-green-dark);
}
.btn-danger {
  background: var(--clay-red);
  border-color: var(--clay-red-dark);
}

.btn-large {
  font-size: 1.5rem;
  padding: 16px 40px;
  border-radius: 24px;
}

/* Home Screen Styling */
/* ===== Home Scene-Center + Icon-Edge Redesign (2026-07) =====
   The home screen is a centered diorama with all UI moved to compact buttons
   at the edges. Background is full-bleed; diorama centered with margins.
   All buttons are small, icon-forward clay tiles. Only PLAY has a text label. */

.home-scene {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #f5e6d3;
  background-image: url('assets/bgs/home-cat-diorama.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 0;
}

.home-edge-layout {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
  pointer-events: none;
}

.home-corner {
  position: absolute;
  display: flex;
  pointer-events: auto;
  z-index: 11;
}

.home-corner-tl {
  top: max(16px, env(safe-area-inset-top));
  left: max(24px, calc(env(safe-area-inset-left) + 12px));
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

/* The gap separates two different KINDS of control - the round utility icons
   above, the square nav tiles below - so it runs wider than the 6-8px used
   within each group, to read as a break rather than just more spacing. */
.home-corner-tr {
  top: max(16px, env(safe-area-inset-top));
  right: max(24px, calc(env(safe-area-inset-right) + 12px));
  flex-direction: column;
  align-items: flex-end;
  gap: 20px;
}

.home-icon-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.home-nav-menu-compact {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.home-nav-btn-compact {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 3px;
  width: 56px;
  height: 56px;
  border-radius: 15px;
  border: none;
  background: linear-gradient(180deg, #ffffff, #e2ddf0);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 4px 10px rgba(84, 74, 133, 0.2);
  padding: 0;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.home-nav-btn-compact:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 6px 13px rgba(84, 74, 133, 0.24);
}
.home-nav-btn-compact:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(84, 74, 133, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 5px rgba(84, 74, 133, 0.2);
}

.home-nav-btn-compact .nav-icon {
  width: 26px;
  height: 26px;
  object-fit: contain;
}

.home-nav-btn-compact .nav-label {
  font-size: 0.56rem;
  font-weight: 800;
  color: var(--clay-dark);
  opacity: 0.7;
}

.home-event-badge-compact {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 2px;
  width: 56px;
  height: 56px;
  border-radius: 15px;
  border: none;
  background: linear-gradient(180deg, #ffd24a, #f5c930);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(180, 140, 0, 0.16),
    0 4px 10px rgba(180, 140, 0, 0.2);
  padding: 0;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.home-event-badge-compact:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(180, 140, 0, 0.16),
    0 6px 13px rgba(180, 140, 0, 0.24);
}
.home-event-badge-compact:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(180, 140, 0, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 5px rgba(180, 140, 0, 0.2);
}

.home-event-badge-compact .event-icon {
  width: 24px;
  height: 24px;
  object-fit: contain;
}

.home-event-badge-compact .event-countdown {
  font-size: 0.56rem;
  font-weight: 800;
  color: rgba(0, 0, 0, 0.8);
  line-height: 1;
}

.home-corner-bl {
  bottom: max(20px, env(safe-area-inset-bottom));
  left: max(24px, calc(env(safe-area-inset-left) + 12px));
  flex-direction: row;
  align-items: flex-end;
  gap: 8px;
}

.home-nav-row {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}

.home-corner-br {
  bottom: max(20px, env(safe-area-inset-bottom));
  right: max(24px, calc(env(safe-area-inset-right) + 12px));
}

/* Top-center: currency pills (reverted from compact to full format). */
.home-currency-center {
  position: absolute;
  top: max(16px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: 11;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  pointer-events: auto;
}

.currency-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px;
  border-radius: 14px;
  background: linear-gradient(180deg, #ffffff, #e2ddf0);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 6px 13px rgba(84, 74, 133, 0.24);
}

.pill-icon {
  width: 18px;
  height: 18px;
  object-fit: contain;
}

.pill-value {
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--clay-dark);
}

.pill-plus {
  margin-left: 6px;
  border: none;
  background: none;
  color: var(--clay-dark);
  font-weight: 900;
  font-size: 1rem;
  cursor: pointer;
  padding: 0;
  opacity: 0.7;
  transition: opacity 0.15s;
}

.pill-plus:hover {
  opacity: 1;
}

.pill-plus:active {
  transform: scale(0.95);
}

/* ---- Top-left: Avatar tile + level below ---- */
.home-avatar-tile {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  border: none;
  background: linear-gradient(180deg, #ffffff, #e2ddf0);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 6px 13px rgba(84, 74, 133, 0.24);
  padding: 0;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.home-avatar-tile:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 9px 18px rgba(84, 74, 133, 0.28);
}
.home-avatar-tile:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(84, 74, 133, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 5px rgba(84, 74, 133, 0.2);
}
.home-avatar-img {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: 12px;
  object-fit: cover;
}

/* ---- Top-right: Utility icon buttons ---- */
/* Circular, unlike the rounded-square nav tiles - the round shape marks these
   as utility/chrome rather than a destination you navigate to. */
.home-icon-btn {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: linear-gradient(180deg, #ffffff, #e2ddf0);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 4px 10px rgba(84, 74, 133, 0.2);
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s ease;
}
.home-icon-btn:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 6px 15px rgba(84, 74, 133, 0.24);
}
.home-icon-btn:active {
  transform: translateY(1px);
  box-shadow:
    inset 0 3px 6px rgba(84, 74, 133, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 5px rgba(84, 74, 133, 0.2);
}
.home-icon-btn img {
  width: 22px;
  height: 22px;
  object-fit: contain;
}

/* ---- Bottom-left: Nav menu stack (Missions, Event, Inventory, Collection, Shop) ---- */
.home-nav-menu {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
}

.home-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 4px;
  width: 64px;
  min-width: 64px;
  border-radius: 16px;
  border: none;
  background: linear-gradient(180deg, #ffffff, #e2ddf0);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 6px 13px rgba(84, 74, 133, 0.24);
  padding: 8px 0;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.home-nav-btn:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 9px 18px rgba(84, 74, 133, 0.28);
}
.home-nav-btn:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(84, 74, 133, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 5px rgba(84, 74, 133, 0.2);
}

.home-nav-btn .nav-icon {
  width: 30px;
  height: 30px;
  object-fit: contain;
  display: block;
}

/* Tiny labels for all buttons in horizontal row. */
.home-nav-btn .nav-label {
  font-size: 0.62rem;
  font-weight: 900;
  color: var(--clay-dark);
  line-height: 1;
  text-align: center;
  opacity: 0.8;
}

/* ---- Event badge (in bottom-left nav stack) ---- */
.home-event-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 2px;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  border: none;
  background: linear-gradient(180deg, #ffd24a, #f5c930);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(180, 140, 0, 0.16),
    0 6px 13px rgba(180, 140, 0, 0.24);
  padding: 0;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.home-event-badge:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(180, 140, 0, 0.16),
    0 9px 18px rgba(180, 140, 0, 0.28);
}
.home-event-badge:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(180, 140, 0, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 5px rgba(180, 140, 0, 0.2);
}

.event-icon {
  width: 20px;
  height: 20px;
  object-fit: contain;
}

.event-countdown {
  font-size: 0.6rem;
  font-weight: 900;
  color: rgba(0, 0, 0, 0.8);
  line-height: 1;
  text-align: center;
}

/* ---- Top-left: Level indicator (below avatar) ---- */
.home-level-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: 12px;
  background: linear-gradient(180deg, #ffffff, #e2ddf0);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 7px rgba(84, 74, 133, 0.16),
    0 4px 10px rgba(84, 74, 133, 0.2);
  font-weight: 900;
  color: var(--clay-dark);
  font-size: 0.9rem;
}

.level-label {
  font-size: 0.7rem;
  opacity: 0.7;
  font-weight: 800;
}

.level-value {
  display: inline-block;
  width: 2ch;
  font-variant-numeric: tabular-nums;
}

/* ---- Bottom-right: PLAY button (large primary action) ---- */
.home-play-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px 32px;
  border-radius: 18px;
  border: none;
  background: linear-gradient(180deg, #ff6b9d, #ff3b7f);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.6),
    inset 0 -4px 7px rgba(128, 20, 60, 0.2),
    0 8px 16px rgba(128, 20, 60, 0.28);
  cursor: pointer;
  font-size: 1.05rem;
  font-weight: 900;
  color: #ffffff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.home-play-btn:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.6),
    inset 0 -4px 7px rgba(128, 20, 60, 0.2),
    0 12px 24px rgba(128, 20, 60, 0.32);
}
.home-play-btn:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(128, 20, 60, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    0 2px 8px rgba(128, 20, 60, 0.2);
}

/* Fixed-width currency count cells EVERYWHERE a balance is displayed (home,
   shop header, collection board, dust shop, profile) - each cell is sized for
   its currency's cap (coins 999,999,999 / gems 999,999 / dust 999), so no
   currency box ever resizes or shifts as balances change. Boxes that carry
   only some currencies just get those cells. */
#home-coin-count, #shop-coin-count, #ccb-coin-count, #profile-coin-count {
  display: inline-block;
  width: 9ch;
}
#home-gem-count, #shop-gem-count, #ccb-gem-count, #profile-gem-count {
  display: inline-block;
  width: 6ch;
}
#home-dust-count, #ccb-dust-count, #profile-dust-count, #collection-dust-count, #dust-shop-balance {
  display: inline-block;
  width: 3ch;
}
/* Equal-width digits in every currency container (no per-digit jitter). */
.shop-coin-badge,
.currency-badge-row,
.profile-currency-row {
  font-variant-numeric: tabular-nums;
}

.logo-area {
  text-align: center;
}

.clay-logo {
  font-size: 4.5rem;
  color: var(--clay-white);
  text-shadow: 4px 4px 0px var(--clay-purple-dark), 8px 8px 0px var(--clay-pink-dark), 8px 8px 18px rgba(0,0,0,0.15);
  letter-spacing: 2px;
  animation: popIn 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, sparkleGlow 2.4s ease-in-out infinite;
}

@keyframes sparkleGlow {
  0%, 100% { filter: drop-shadow(0 0 0px rgba(255, 255, 255, 0)); }
  50% { filter: drop-shadow(0 0 18px rgba(255, 220, 245, 0.9)); }
}

.logo-subtitle {
  font-size: 1.4rem;
  color: var(--clay-yellow-dark);
  font-weight: 700;
}

.logo-sparkle {
  display: inline-block;
  animation: wobble 1.8s infinite ease-in-out;
}

.home-buttons {
  display: flex;
  gap: 20px;
}

.clay-decorations {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 0;
}

.clay-ball {
  position: absolute;
  border-radius: 50%;
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  opacity: 0.85;
  animation: floatBob 4s ease-in-out infinite;
}

@keyframes floatBob {
  0%, 100% { transform: translateY(0) rotate(var(--ball-rot, 0deg)); }
  50% { transform: translateY(-14px) rotate(var(--ball-rot, 0deg)); }
}

.clay-ball.red {
  width: 60px;
  height: 60px;
  background: var(--clay-red);
  top: 15%;
  left: 10%;
  --ball-rot: 15deg;
  animation-delay: 0s;
}

.clay-ball.blue {
  width: 80px;
  height: 80px;
  background: var(--clay-blue);
  bottom: 15%;
  right: 8%;
  --ball-rot: -25deg;
  animation-delay: 0.6s;
}

.clay-ball.green {
  width: 50px;
  height: 50px;
  background: var(--clay-green);
  top: 20%;
  right: 15%;
  --ball-rot: 45deg;
  animation-delay: 1.2s;
}

.clay-ball.yellow {
  width: 70px;
  height: 70px;
  background: var(--clay-yellow);
  bottom: 10%;
  left: 15%;
  animation-delay: 1.8s;
}

.clay-ball.pink {
  width: 45px;
  height: 45px;
  background: var(--clay-pink);
  top: 42%;
  left: 4%;
  --ball-rot: -10deg;
  animation-delay: 0.3s;
}

.clay-ball.purple {
  width: 55px;
  height: 55px;
  background: var(--clay-purple);
  top: 8%;
  left: 45%;
  --ball-rot: 20deg;
  animation-delay: 0.9s;
}

/* Sparkly emoji decorations (stars, hearts) scattered around the home screen */
.clay-sparkle {
  position: absolute;
  font-size: 2rem;
  filter: drop-shadow(2px 2px 0px rgba(0,0,0,0.1));
  animation: floatBob 3.5s ease-in-out infinite, wobble 2.5s infinite ease-in-out;
  opacity: 0.9;
}

.clay-sparkle.s1 { top: 10%; left: 25%; font-size: 1.8rem; animation-delay: 0.2s; }
.clay-sparkle.s2 { top: 65%; left: 20%; font-size: 1.4rem; animation-delay: 0.8s; }
.clay-sparkle.s3 { top: 25%; right: 25%; font-size: 1.6rem; animation-delay: 1.4s; }
.clay-sparkle.s4 { bottom: 12%; right: 30%; font-size: 2rem; animation-delay: 0.5s; }

/* Mode Selection Screen */
.mode-options {
  display: flex;
  gap: 30px;
  margin: auto;
}

.mode-card {
  width: 220px;
  padding: 30px 20px;
  cursor: pointer;
  /* Positioned + clipped so the per-panel art layer (::before, added in the
     play-modes section) sits behind the content and respects the rounded
     corners. Content is lifted above it via `.mode-card > *` below - layout is
     unchanged. */
  position: relative;
  overflow: hidden;
  transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.2s ease;
  /* 3D clay card: top->bottom gradient fill + a bright inset lip + a soft
     inset floor + a deep contact shadow, matching the home pills/buttons.
     Replaces the flat white panel (solid fill + hard 5px border + subtle
     bevel), which read sticker-flat. */
  background: linear-gradient(180deg, #ffffff, #e7e2f4);
  border: none;
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.9),
    inset 0 -8px 14px rgba(84, 74, 133, 0.14),
    0 10px 22px rgba(84, 74, 133, 0.26);
}

.mode-card:hover {
  /* Lift only - no scale (the panel must not grow on hover). */
  transform: translateY(-4px);
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.9),
    inset 0 -8px 14px rgba(84, 74, 133, 0.14),
    0 18px 34px rgba(84, 74, 133, 0.3);
}

.mode-card:active {
  /* No scale - pressing the card (or the multiplier +/- buttons inside it) must
     not resize the panel. Held level with the hover lift so a tap on the
     multiplier control produces no card movement at all. */
  transform: translateY(-4px);
  box-shadow:
    inset 0 4px 9px rgba(84, 74, 133, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 4px 10px rgba(84, 74, 133, 0.2);
}

.mode-icon {
  font-size: 3.5rem;
  margin-bottom: 12px;
}

.mode-card h3 {
  font-size: 1.4rem;
  margin-bottom: 8px;
}

/* Game Board Layout */
/* The match screens' FULL surface is the equipped board (spec 6.1): the play
   mat art is a flat clay table designed edge-to-edge (calm across the whole
   frame, no border props - unlike home-bg/missions-bg), so it covers the
   screen and everything - cards, deck, seats - sits directly on it. Driven by
   the same --clay-board-image/-color pair SkinsSystem.applyEquippedBoard()
   already maintains, so board skins keep working; colour-only boards resolve
   the image to `none` and show their flat colour full-bleed. */
#screen-game,
#screen-online-game {
  background-color: var(--clay-board);
  background-image: var(--clay-board-image, none);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

.game-layout {
  width: 100vw;
  height: 100vh; /* fallback */
  height: 100dvh; /* visible viewport - see .landscape-wrapper note */
  display: grid;
  grid-template-rows: 110px 1fr 200px;
  /* keep the board off the notch/home-indicator on full-screen devices */
  padding: max(10px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
  gap: 8px;
}

/* Opponents Row */
.opponents-row {
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding: 5px 15px;
  gap: 15px;
}

/* Opponent clay card info */
.opponent-badge {
  display: flex;
  align-items: center;
  background: var(--clay-white);
  padding: 8px 16px;
  border-radius: 20px;
  border: 4px solid var(--clay-white-dark);
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  min-width: 160px;
  position: relative;
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.opponent-badge.active-turn {
  border-color: var(--clay-blue);
  transform: scale(1.05);
  animation: turnPulse 1.5s infinite alternate;
}

@keyframes turnPulse {
  0% { box-shadow: 0 0 10px rgba(77, 171, 247, 0.5), var(--clay-shadow-out), var(--clay-shadow-in); }
  100% { box-shadow: 0 0 20px rgba(77, 171, 247, 0.8), var(--clay-shadow-out), var(--clay-shadow-in); }
}

/* Matches the profile/topbar avatar look (raised outer shadow, 3px white
   frame, 13px radius) so avatars look identical everywhere - was a recessed
   inset-shadow tile with a grey backing. */
.avatar-holder {
  width: 44px;
  height: 44px;
  border-radius: 13px;
  border: 3px solid var(--clay-white);
  margin-right: 8px;
  overflow: hidden;
  box-shadow: var(--clay-shadow-out);
}

.opponent-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.opponent-name {
  font-weight: 700;
  font-size: 0.9rem;
  max-width: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* Opponent hand preview: a tiny face-down pile of the REAL card back (spec
   4.1), not abstract bars. 5:7 like every card slot; the stack offset makes
   2-3 of them read as a pile. */

.opponent-card-count {
  font-size: 0.8rem;
  font-weight: 700;
  margin-left: 12px;
}

.opponent-status-tag {
  position: absolute;
  bottom: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--clay-red);
  color: white;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 0.7rem;
  font-weight: 700;
  box-shadow: var(--clay-shadow-out);
  white-space: nowrap;
}

.opponent-status-tag.eliminated {
  background: #555;
}

.opponent-status-tag.reconnecting {
  background: var(--clay-yellow);
  color: #5c4400;
}

.opponent-badge.disconnected {
  opacity: 0.55;
}

.opponent-status-tag.reconnecting .status-spinner {
  display: inline-block;
  margin-right: 4px;
  animation: statusSpin 0.8s linear infinite;
}

@keyframes statusSpin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* Turn timer countdown ring (spec 4.2) - a conic-gradient arc that drains as
   --timer-pct falls from 100 to 0, with --timer-color shifting green -> red. */
.turn-indicator-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.turn-timer-ring {
  --timer-pct: 100;
  --timer-color: #51cf66;
  position: relative;
  width: 46px;
  height: 46px;
  min-width: 46px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: conic-gradient(var(--timer-color) calc(var(--timer-pct) * 1%), rgba(0, 0, 0, 0.15) 0);
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  transition: opacity 0.2s ease;
}

.turn-timer-ring.hidden {
  opacity: 0;
  pointer-events: none;
}

/* When relocated next to the active player's badge (spec: timer beside whoever's
   playing), sit it on the right with a little gap and shrink it to fit the badge. */
.opponent-badge > .turn-timer-ring,
.player-info-badge > .turn-timer-ring {
  width: 38px;
  height: 38px;
  min-width: 38px;
  margin-left: 10px;
  flex-shrink: 0;
}
.opponent-badge > .turn-timer-ring::before,
.player-info-badge > .turn-timer-ring::before {
  width: 29px;
  height: 29px;
}
.opponent-badge > .turn-timer-ring span,
.player-info-badge > .turn-timer-ring span {
  font-size: 0.72rem;
}

.turn-timer-ring::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--clay-white);
}

.turn-timer-ring span {
  position: relative;
  font-weight: 800;
  font-size: 0.85rem;
  z-index: 1;
}

/* Brief discard-pile pulse when a genuinely new card lands (spec 4.7) */
@keyframes cardJustPlayed {
  0% { scale: 1.35; filter: brightness(1.3); }
  100% { scale: 1; filter: brightness(1); }
}

.card-just-played {
  animation: cardJustPlayed 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

/* Online lobby */
.lobby-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 20px;
  width: 340px;
  max-width: 90vw;
}

/* The lobby's form/status panels sit on the themed play-modes backdrop now, so
   give them the same 3D clay treatment as the mode-picker cards (gradient fill
   + lip + inset floor + contact shadow) instead of the flat bordered white
   .clay-card, which read plain against the art. Scoped to the lobby so other
   base clay-cards (warning dialog, tutorial) are untouched. */
#screen-online-lobby .clay-card {
  background: linear-gradient(180deg, #ffffff, #e7e2f4);
  border: none;
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.9),
    inset 0 -8px 14px rgba(84, 74, 133, 0.14),
    0 10px 22px rgba(84, 74, 133, 0.26);
}

/* The collapsed room-making forms behind the lobby's Play-with-friends
   toggle - stacked like the rest of the lobby column when expanded. */
.lobby-options {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
}

.lobby-field-label {
  font-weight: 700;
  font-size: 0.85rem;
  margin-top: 6px;
}

.clay-input {
  font-family: inherit;
  font-size: 1rem;
  padding: 10px 14px;
  border-radius: 14px;
  border: 3px solid var(--clay-white-dark);
  background: var(--clay-white);
  box-shadow: inset 2px 2px 5px rgba(0,0,0,0.1);
  outline: none;
}

.clay-input:focus {
  border-color: var(--clay-blue);
}

.lobby-hint {
  font-size: 0.75rem;
  opacity: 0.7;
  margin: 0 0 6px;
}

.lobby-status {
  padding: 16px 24px;
  text-align: center;
  margin-top: 14px;
  /* Fixed footprint: the status line, seat fill-in, and rotating tips all
     change text constantly - the box must not resize with every change. */
  width: min(440px, 92vw);
  box-sizing: border-box;
}

/* task 13: the status line is empty while searching (we go straight to the
   matchmaking box); collapse it so it leaves no gap, and only take space when
   it actually carries an error/timeout message. */
#lobby-status-text { margin: 0; }
#lobby-status-text:empty { display: none; }

.lobby-waiting-details {
  margin-top: 8px;
  font-weight: 700;
}
/* No top margin when it's the first visible thing in the card (status line
   collapsed) - keeps the box tight to the card's padding. */
#lobby-status-text:empty + .lobby-waiting-details { margin-top: 0; }

/* Matchmaking lobby seat fill-in / timer / tips (spec section 14) */

.lobby-timer-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 10px 0;
}

.lobby-timer-ring {
  --timer-pct: 100;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: conic-gradient(var(--clay-green) calc(var(--timer-pct) * 1%), rgba(0, 0, 0, 0.15) 0);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.lobby-timer-ring::before {
  content: "";
  position: absolute;
}
.lobby-timer-ring span {
  background: var(--clay-white-light);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 800;
  color: var(--clay-dark);
}

.lobby-timer-label {
  font-size: 0.7rem;
  font-weight: 500;
  opacity: 0.75;
  max-width: 160px;
  text-align: left;
}

.lobby-seat-row {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin: 10px 0;
}

.lobby-seat-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 64px;
}
.lobby-seat-avatar {
  width: 48px;
  height: 48px;
  border-radius: 13px;
  border: 3px solid var(--clay-white-dark);
  background: var(--clay-white-light);
  overflow: hidden;
  box-shadow: var(--clay-shadow-out);
}
.lobby-seat-avatar svg {
  width: 100%;
  height: 100%;
}
.lobby-seat-slot.empty .lobby-seat-avatar {
  border-style: dashed;
  opacity: 0.4;
}
.lobby-seat-name {
  font-size: 0.65rem;
  font-weight: 700;
  color: var(--clay-dark);
  max-width: 64px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lobby-tip-card {
  margin-top: 10px;
  background: rgba(0, 0, 0, 0.08);
  border-radius: 14px;
  padding: 8px 14px;
  font-size: 0.75rem;
  font-style: italic;
  opacity: 0.85;
  /* Reserve enough for the longest rotating tip (2 lines at the card's fixed
     440px, plus headroom) so tips don't pump the card's height up and down. */
  min-height: 4.2em;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lobby-starting-message {
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--clay-green-dark);
}

/* Center Board (Main Playing Surface).
   The mat art is a real clay surface with its own moulded ring + corner
   detail, referenced through --clay-board-image so it follows the EQUIPPED
   board rather than a hardcoded path (see SkinsSystem.applyEquippedBoard).
   --clay-board stays underneath as the backdrop, and is the whole look for
   colour-only boards, which set the image to `none`.

   `contain`, not `cover`: the art is 16:9 but this mat renders ~2:1, so cover
   would scale to the width and slice the ring's top and bottom off. contain
   fits the whole 16:9 frame inside the mat, keeping the ring intact and
   concentric with the deck/discard cluster in the centre grid column; the
   --clay-board colour fills the slim letterbox either side of it. */
/* Layout grid ONLY - the old "mat" chrome is gone. This used to be a pink
   rounded rect (+magenta border) holding the board art via `contain`, which
   letterboxed: hard vertical seams where flat pink met textured art. The
   equipped-board art now covers the whole screen (see #screen-game above), so
   this element draws nothing itself. */
.center-board {
  display: grid;
  /* The CENTRE column sizes to its content (deck + gap + discard at full card
     size); the side panels split whatever is left, equally, and shrink to suit
     the viewport. Previously the sides were a hardcoded 168px and the centre
     took `1fr`, which meant the cards had to fit a fixed leftover - so the deck
     got quietly shrunk to 88px to squeeze in, and every breakpoint had to
     re-budget the pixels by hand. `auto` in the middle inverts that: the cards
     are never the thing that gives. The panels only need ~106px of content, and
     even the shortest supported layout leaves them ~142px. */
  grid-template-columns: 1fr auto 1fr;
  padding: 10px;
  align-items: center;
  justify-content: center;
  position: relative;
  /* Full width: with the mat gone there's no "capped board" to read as a
     shape - the table IS the screen, so the columns get all of it. */
  width: 100%;
}

/* The old central turn banners are hidden; active turn reads as a SEAT GLOW
   (.active-turn, ring block) - the "playing"/"next" .turn-tag system was
   deleted with it (2026-07). */
#turn-banner,
#online-turn-banner {
  display: none;
}

/* Playable cards lift out of the fan - a soft glow reinforces the raise. */
.player-hand-scroll .clay-card-element.playable-raised,
#online-player-hand .clay-card-element.playable-raised {
  filter: drop-shadow(0 6px 8px rgba(0, 0, 0, 0.28));
}

/* Board Panels */
.board-info-panel, .board-state-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  justify-content: center;
}

/* Turn banner - a clay pill that visibly changes state: golden pulsing glow
   on YOUR turn, quiet with animated waiting dots on anyone else's. */
.turn-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--clay-white);
  padding: 8px 16px;
  border-radius: 999px;
  border: 3px solid var(--clay-white-dark);
  font-weight: 800;
  font-size: 0.95rem;
  color: var(--clay-dark);
  box-shadow: var(--clay-shadow-out);
  transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}

.turn-indicator.my-turn {
  background: linear-gradient(135deg, var(--clay-yellow-light), var(--clay-yellow));
  border-color: var(--clay-yellow-dark);
  animation: turnGlowPulse 1.4s ease-in-out infinite;
}

.turn-indicator.other-turn {
  opacity: 0.85;
}

@keyframes turnGlowPulse {
  0%, 100% { box-shadow: var(--clay-shadow-out); transform: scale(1); }
  50% { box-shadow: 0 0 18px rgba(252, 196, 25, 0.8), var(--clay-shadow-out); transform: scale(1.04); }
}

/* "..." while waiting on another player - three softly blinking dots. */
.turn-wait-dots span {
  animation: turnDotBlink 1.2s infinite;
}
.turn-wait-dots span:nth-child(2) { animation-delay: 0.2s; }
.turn-wait-dots span:nth-child(3) { animation-delay: 0.4s; }

@keyframes turnDotBlink {
  0%, 60%, 100% { opacity: 0.25; }
  30% { opacity: 1; }
}

.game-status-card {
  font-size: 0.85rem;
  font-weight: 700;
  padding: 10px;
  border-radius: 16px;
  border-width: 3px;
}

/* Turn-order chip: a small pill with a glyph that actually rotates in the
   current play direction (mirrors the big dashed ring around the play area). */
.direction-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.5);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--clay-dark);
  margin-bottom: 4px;
}

.dir-spin {
  display: inline-block;
  font-size: 1rem;
  line-height: 1;
  animation: dirSpinCW 3s linear infinite;
}
.dir-spin.ccw {
  animation-name: dirSpinCCW;
}

@keyframes dirSpinCW {
  to { transform: rotate(360deg); }
}
@keyframes dirSpinCCW {
  to { transform: rotate(-360deg); }
}

/* UNO-style compact state chip: a color dot + current symbol in one small
   pill, replacing the old labeled "CURRENT COLOR" panel. */
.state-card {
  padding: 6px 14px;
  border-radius: 999px;
  border-width: 3px;
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  align-self: center;
}

.state-label {
  display: none; /* the dot + symbol speak for themselves */
}

.clay-color-wheel {
  width: 30px;
  height: 30px;
  min-width: 30px;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: 700;
  font-size: 0; /* hide the color-name text at chip size - the dot IS the info */
  text-shadow: 1px 1px 2px black;
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  border: 3px solid white;
  transition: background-color 0.3s ease;
}

.clay-color-wheel.red { background-color: var(--clay-red); }
.clay-color-wheel.blue { background-color: var(--clay-blue); }
.clay-color-wheel.green { background-color: var(--clay-green); }
.clay-color-wheel.yellow { background-color: var(--clay-yellow); }
.clay-color-wheel.none { background-color: #888; }

.state-symbol-label {
  font-size: 0.85rem;
  font-weight: 800;
  margin-top: 0;
  /* Dark pill so the white symbol glyph (kunai/crown/etc.) reads on the light
     state card - also fine for the plain number-card digits. */
  background: var(--clay-dark);
  color: #fff;
  border-radius: 9px;
  padding: 3px 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  min-height: 1.5em;
}
.state-symbol-label .card-glyph { height: 1.2em; }

#symbol-text {
  color: var(--clay-blue-dark);
}

/* Attack Active Card */
.attack-card {
  background: var(--clay-red-light);
  border-color: var(--clay-red);
  padding: 10px;
  border-radius: 16px;
  border-width: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  animation: attackShake 0.4s infinite alternate;
}

/* translateY(-50%) is REQUIRED in every frame: .attack-card centres itself with
   `top:50%; transform:translateY(-50%)`, and an animation's transform REPLACES
   the element's own. Without it the pill dropped half its height the instant a
   stack started - which read as the pill "moving" between the 0 and >0 states. */
@keyframes attackShake {
  0% { transform: translateY(-50%) rotate(-2deg) scale(1.02); }
  100% { transform: translateY(-50%) rotate(2deg) scale(1.02); }
}

.attack-icon {
  font-size: 1.5rem;
}

.attack-details {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.attack-title {
  font-size: 0.65rem;
  font-weight: 700;
  color: var(--clay-red-dark);
}

.attack-amount {
  font-size: 1.2rem;
  font-weight: 800;
  color: var(--clay-red-dark);
}

/* Play Area (Deck & Discard) */
.play-area {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 40px;
  position: relative;
}

/* Clay Deck Stack Style */
.deck-container {
  perspective: 600px;
}

/* Deck/discard render at the SAME 110x154 as hand cards (see
   .player-hand-scroll .clay-card-element) - a played card must not change
   size when it lands on the pile, and the deck must not look like a smaller
   card than the one sitting next to it.
   (The deck was stuck at 88px wide while the discard was 110 - a 25% mismatch
   that only became obvious once both showed real card art. Widening it needed
   28px more in the centre grid column, hence the narrower side panels on
   .center-board - they only need ~106px of content.) */
.clay-deck-stack {
  position: relative;
  width: 110px;
  height: 154px; /* 5:7, matching the card art - see .clay-card-element */
  cursor: pointer;
}

/* Each layer is a real card back (.card-back-face in index.html), so the stack
   is literally three cards offset behind each other. No fill/border of its own
   - the old red fill + white border would have framed the back art's
   transparent canvas with a coloured rectangle. */
.deck-card-layer {
  position: absolute;
  width: 100%;
  height: 100%;
  filter: drop-shadow(2px 3px 3px rgba(84, 74, 133, 0.3));
  transition: transform 0.1s ease;
}

.layer-3 {
  transform: translate3d(6px, 6px, -15px);
  filter: brightness(0.82) drop-shadow(2px 3px 3px rgba(84, 74, 133, 0.3));
}

.layer-2 {
  transform: translate3d(3px, 3px, -8px);
  filter: brightness(0.92) drop-shadow(2px 3px 3px rgba(84, 74, 133, 0.3));
}

.layer-1 {
  transform: translate3d(0, 0, 0);
}

.clay-deck-stack:hover .layer-1 {
  transform: translate3d(0, -5px, 0);
}

.clay-deck-stack:active .layer-1 {
  transform: translate3d(0, 2px, 0);
}

/* Discard Pile - same 110x160 footprint as a hand card (size-consistency
   rule above), so a played card lands with zero size change. */
.discard-container {
  width: 110px;
  height: 154px;
  position: relative;
}

.discard-pile {
  width: 100%;
  height: 100%;
  border-radius: 14px;
  background: rgba(0,0,0,0.1);
  border: 3px dashed rgba(255,255,255,0.4);
  position: relative;
}

/* The resting top card matches a hand card EXACTLY (110x160), overriding the
   base .clay-card-element 100x140. Explicit pixels, not 100% - the pile's
   3px dashed border would otherwise shrink a percentage-sized card.
   (Regression fix: this was shrunk to 88x128 at some point, which squeezed the
   fixed-size .card-center content - a visibly different card template than the
   hand. Discard cards must always render at hand-card size.) */
.discard-pile .clay-card-element {
  width: 110px;
  height: 154px;
}

/* ===== Clay Card Design - LAYERED, asset-driven (see ui.js cardFaceInner) =====
   .clay-card-element is a bare, fixed-size SLOT: it owns the size, the
   transform and the shadow, and nothing else. The visible card face is the
   .card-frame layer's PNG - a complete face including its own background - so
   the element itself carries no border or background of its own.

   SHADOWS ARE CSS-ONLY (the frame art ships with none baked in) and use
   `filter: drop-shadow` rather than box-shadow: each frame is a rounded card
   sitting inside a transparent 600x840 canvas, so a rectangular box-shadow -
   or any inset shadow - would paint a visible rectangle around/over the
   artwork. drop-shadow follows the artwork's real alpha silhouette instead.
   (.playable-raised already used this approach.)

   CARD SLOTS MUST BE 5:7 (100x140, 110x154, 88x123 ...). The frame art is a
   600x840 canvas drawn with `background-size: contain`, so a slot of any other
   ratio letterboxes the art within the slot - which both shrinks the card and
   slides it out from under the % offsets .card-corner/.card-center rely on.
   (The slots were 11:16 before the art landed, costing 3px of letterbox and
   pushing the corner symbol off the frame.) */
.clay-card-element {
  position: absolute;
  width: 100px;
  height: 140px;
  cursor: pointer;
  transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), filter 0.2s ease;
  transform-origin: center bottom;
  box-sizing: border-box;
  filter: var(--card-shadow);
}

/* Layer 1 - the FRAME: a complete card face. Every frame shares one 600x840
   canvas (card centred at 552x792), so `contain` renders them all at a
   matching size. Do NOT per-card tweak scale. */
.card-frame {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
  pointer-events: none;
}

/* Layer 2 - the big centred SYMBOL. One slot, identical for every symbol (all
   share a 512x512 canvas with a consistent safe inset), so there is no
   per-symbol special-casing. `contain` keeps each glyph's own aspect.
   Attack cards (symbols 7/8) render as a flex container with the paw image
   + numeric overlay (.attack-value span). */
.card-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 58%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  pointer-events: none;
  z-index: 1;
}

/* Layer 3 - the SAME symbol again, small, TOP-LEFT ONLY (no bottom-right).
   ~20px at hand size. For Attack cards: single paw for symbol 7, two stacked
   paws for symbol 8 (via sym-paw-stamp-2.webp) - verified distinguishable at 14/18/22px.

   The 12% inset is measured, not guessed: on the frame's 600x840 canvas the
   card edge starts at 36px, the raised rim runs to ~48px and the bevel groove
   to ~68px, with the flat inner face beginning at ~72px = 12%. Anything less
   and the glyph sits on the rim. The art is exactly 600:840, so the same 12%
   holds on both axes (top resolves against height, left against width). */
.card-corner {
  position: absolute;
  top: 12%;
  left: 12%;
  width: 18%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  pointer-events: none;
  z-index: 2;
}

/* Attack-2 corner (symbol 8): two paws stacked vertically. Rendered as a
   <div> with two <img> children positioned tightly. Each paw is ~0.48 * corner size
   (tighter stack than naive 50/50 split) so they remain visually distinct at hand size. */
.card-corner.attack-2-corner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 0;
  width: 18%;
  aspect-ratio: 1 / 1;
}
.card-corner.attack-2-corner img {
  width: 100%;
  height: 48%;
  object-fit: contain;
  display: block;
  flex-shrink: 0;
}

/* Attack card (symbol 7/8): centre paw stamp + the attack value ON the pad.
   Runs larger than the standard 58% centre symbol so the number has room.

   The 52%/55% offsets are MEASURED off the 1024x1024 art, not guessed: the
   large lower pad spans x 350-720, y 415-700, putting its centre at ~52%/55%.
   The number is centred on that point, so it sits wholly on the big pink blob
   and never straddles the toe-beans (which read unevenly, half pink half white).

   Colour #3D1119 is a dark rose measured against the sampled pad rgb(234,107,130)
   at 5.36:1 and the white disc at 9.66:1 - both past WCAG AA, so it stays legible
   even if a future re-cut shifts the number slightly off the pad. */
.card-center.attack-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 74%;
  aspect-ratio: 1 / 1;
  pointer-events: none;
  z-index: 1;
  /* Makes the stamp a query container so the number can size against IT rather
     than an inherited font-size. Card slots are fixed px per context (100x140
     hand, 110x154 discard, 88x123 tiles) and set no font-size, so an em/rem
     value would render at one fixed size on every card and overflow the pad on
     the small ones. */
  container-type: size;
}
.card-center.attack-center img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.attack-value {
  position: absolute;
  left: 52%;
  top: 55%;
  transform: translate(-50%, -50%);
  font-size: 0.8rem; /* fallback for engines without container query units */
  font-size: 30cqw;  /* 30% of the stamp's width - scales with every card size */
  font-weight: 900;
  line-height: 1;
  color: #3D1119;
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.3);
  pointer-events: none;
}

/* Arch 3 (premium skins): one whole baked card image, symbol layers disabled. */
.clay-card-element.card-full-art { overflow: hidden; }
.clay-card-element.card-full-art .card-full-art-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Card BACK: one complete baked face on the same canvas as the frames. Only
   the default back has art - the other back skins' legacy `background:`
   gradients override background-image and keep their old look (hence the
   border-radius here, so that fallback still reads as a card). */
.card-back-face {
  background-image: url("assets/cards/card-back-paw.webp");
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
  border-radius: 14px;
}

/* The symbol shown ALONE in the board's "CURRENT SYMBOL" state panel. */
.card-glyph {
  height: 1.35em;
  width: auto;
  display: block;
  object-fit: contain;
}
/* The attack panel's icon is the paw-stamp symbol (white+pink clay disc).
   Matches the card art where symbols 7 (+1 attack) and 8 (+2 attack) render
   as single paw with numeric overlay (center) + single/double paws (corner). */
.attack-icon-img {
  height: 1.6rem;
  width: auto;
  object-fit: contain;
  display: block;
}

/* Card blank state for Green King visual rule */
.clay-card-element.blank-visual .card-center {
  visibility: hidden;
}
.clay-card-element.blank-visual .card-corner {
  visibility: hidden;
}

.player-hand-scroll .clay-card-element {
  position: relative;
  width: 110px;
  height: 154px; /* 5:7 - see the card-slot note on .clay-card-element */
  flex-shrink: 0;
  margin-left: -50px; /* Spread cards horizontally with a nice overlap */
  margin-bottom: 5px;
}

.player-hand-scroll .clay-card-element:first-child {
  margin-left: 0;
}

/* Play card fly animations */
.clay-card-element.flying {
  transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), opacity 0.4s ease;
  z-index: 100;
}

/* Card interactive states inside human hand.
   These all use drop-shadow filters (never box-shadow) for the same reason the
   base card does - see .clay-card-element. Where a state also tints the card,
   the tint and the shadow must be composed in ONE filter chain, since `filter`
   replaces rather than merges. */
.player-hand-scroll .clay-card-element:hover {
  transform: translateY(-20px) scale(1.08) rotate(2deg) !important;
  z-index: 50 !important;
  filter: var(--card-shadow-raised);
}

.player-hand-scroll .clay-card-element.unplayable {
  filter: brightness(0.65) saturate(0.8) var(--card-shadow);
  cursor: not-allowed;
}

.player-hand-scroll .clay-card-element.unplayable:hover {
  transform: none !important;
  z-index: 1 !important;
  filter: brightness(0.65) saturate(0.8) var(--card-shadow);
}

.player-hand-scroll .clay-card-element.gk-selectable {
  filter: brightness(0.7) var(--card-shadow);
}

.player-hand-scroll .clay-card-element.gk-selected {
  filter: brightness(1.05) saturate(1.1) drop-shadow(0 0 9px var(--clay-yellow)) var(--card-shadow-raised);
  transform: translateY(-25px) scale(1.05) !important;
}

/* Bottom Player Panel */
.player-panel {
  display: grid;
  grid-template-columns: 190px 1fr 92px; /* compact square controls -> the hand gets the freed width */
  align-items: center;
  padding: 5px 15px;
  gap: 15px;
  /* The hand paints ABOVE the center board - fanned/lifted cards overlap the
     board's bottom edge like UNO, never slide behind it. */
  position: relative;
  z-index: 5;
}

.player-info-badge {
  display: flex;
  align-items: center;
  padding: 10px 15px;
  border-radius: 20px;
  border-width: 4px;
  position: relative;
}

.player-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.player-name {
  font-weight: 700;
  font-size: 1rem;
}

.player-card-count {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--clay-blue-dark);
}

.player-status-tag {
  position: absolute;
  top: -15px;
  right: 10px;
  background: var(--clay-red);
  color: white;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: 0.75rem;
  font-weight: 700;
  box-shadow: var(--clay-shadow-out);
  animation: wobble 1s infinite alternate;
}

/* Player Hand Container */
.player-hand-container {
  display: flex;
  align-items: center;
  width: 100%;
  overflow: visible; /* horizontal scrolling lives in .player-hand-scroll; hiding here also chopped lifted cards */
  min-width: 0; /* overflow:hidden used to grant this implicitly - without it the grid column expands instead of letting the hand scroll */
  height: 100%;
}

.player-hand-scroll {
  display: flex;
  align-items: flex-end;
  /* overflow-x:auto forces vertical clipping at the padding box, so lifted/
     fanned cards need HEADROOM: the box GROWS upward (taller + pulled up by
     the same amount) - its bottom edge, where cards anchor, stays put. */
  height: calc(100% + 60px);
  margin-top: -60px;
  width: 100%;
  overflow-x: auto;
  padding: 70px 28px 10px 28px;
  scrollbar-width: none; /* Hide default scrollbar */
}

.player-hand-scroll::-webkit-scrollbar {
  display: none;
}

.scroll-hand-btn {
  background: var(--clay-white);
  border: 3px solid var(--clay-white-dark);
  border-radius: 50%;
  width: 32px;
  height: 32px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  box-shadow: var(--clay-btn-shadow);
  font-weight: 700;
  font-size: 0.85rem;
  z-index: 10;
}

.scroll-hand-btn:active {
  box-shadow: var(--clay-btn-active);
  transform: scale(0.95);
}

/* Player Action Controls area */
.player-controls {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* Compact, roughly-square action buttons (was a wide pill that ate the hand's
   width). Fills the narrow controls column. */
.player-controls .clay-btn {
  width: 100%;
  padding: 16px 6px;
  font-size: 0.8rem;
  border-radius: 16px;
  line-height: 1.1;
}

/* The hand auto-fits its width now (fitHandToContainer in ui.js), so the manual
   scroll arrows are no longer needed. */
.scroll-hand-btn {
  display: none;
}

/* Color Picker modal content */
.color-selector {
  width: 360px;
  background: var(--clay-white);
  border-color: var(--clay-white-dark);
}

.color-selector h3 {
  font-size: 1.4rem;
  margin-bottom: 20px;
}

.color-options-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 15px;
}

.color-select-btn {
  font-family: var(--font-main);
  font-size: 1.2rem;
  font-weight: 700;
  color: white;
  border-radius: 16px;
  border: 4px solid rgba(0,0,0,0.15);
  padding: 20px;
  cursor: pointer;
  box-shadow: var(--clay-btn-shadow);
  text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
  transition: transform 0.1s ease;
}

.color-select-btn:active {
  transform: scale(0.95);
  box-shadow: var(--clay-btn-active);
}

.btn-red { background: var(--clay-red); border-color: var(--clay-red-dark); }
.btn-blue { background: var(--clay-blue); border-color: var(--clay-blue-dark); }
.btn-green { background: var(--clay-green); border-color: var(--clay-green-dark); }
.btn-yellow { background: var(--clay-yellow); border-color: var(--clay-yellow-dark); }

/* Standings Card - wide enough that each player row fits on ONE line
   (rank + name on the left, cards + reward chips on the right). */
.standings-card {
  width: min(640px, 94vw);
  margin: 8px auto;
  background: var(--clay-white-light);
}
.standings-card h3 {
  margin: 0 0 6px;
}
/* Keep the whole victory screen inside the (short, landscape) viewport so the
   PLAY AGAIN / MAIN MENU buttons are never pushed off the bottom edge. */
#screen-game-over .victory-title {
  font-size: clamp(1.5rem, 5vw, 2.3rem);
  margin: 0 0 2px;
}
#screen-game-over .game-over-buttons {
  margin-top: 2px;
}
#screen-game-over .game-over-buttons .clay-btn {
  padding-top: 9px;
  padding-bottom: 9px;
}

.standings-list {
  list-style: none;
  text-align: left;
  padding: 6px;
}

.standings-list li {
  padding: 5px 14px;
  margin-bottom: 4px;
  border-radius: 12px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* Left group: rank badge + player name. */
.standing-left {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.standing-rank {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5em;
  font-size: 1.15em;
  flex-shrink: 0;
}
.standing-rank-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5em;
  height: 1.5em;
  border-radius: 50%;
  background: var(--clay-white-dark);
  color: var(--clay-dark);
  font-size: 0.78em;
  font-weight: 800;
}
.standing-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Right group: card count + reward chips, kept on one line. */
.standing-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
.standing-cards {
  font-size: 0.78em;
  opacity: 0.75;
  white-space: nowrap;
}
.reward-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 800;
  font-size: 0.92em;
  white-space: nowrap;
}
.reward-icon {
  width: 1.2em;
  height: 1.2em;
  display: block;
  flex-shrink: 0;
}

.standings-list li.rank-1 { background: #ffe066; border: 2px solid #f59f00; font-size: 1.1em; transform: scale(1.04); }
.standings-list li.rank-2 { background: #f3d9ff; border: 2px solid #cc5de8; }
.standings-list li.rank-3 { background: #ffd8a8; border: 2px solid #f76707; }
.standings-list li.rank-4 { background: #f6f4fb; border: 1px dashed var(--clay-white-dark); opacity: 0.8; }

/* Podium-style staggered reveal (spec 4.11) - each row fades/slides in with
   an increasing delay set inline per row (index * 0.25s), 1st place first. */
@keyframes podiumReveal {
  0% { opacity: 0; transform: translateY(14px) scale(0.9); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

.podium-reveal {
  opacity: 0;
  animation: podiumReveal 0.45s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

.standings-list li.rank-1.podium-reveal {
  animation-name: podiumRevealRankOne;
}

@keyframes podiumRevealRankOne {
  0% { opacity: 0; transform: translateY(14px) scale(0.9); }
  100% { opacity: 1; transform: translateY(0) scale(1.04); }
}

/* Rules overlay sizing */
.rules-content {
  max-width: 600px;
  height: 85%;
}

.rules-scroll-area {
  flex: 1;
  width: 100%;
  overflow-y: auto;
  text-align: left;
  margin: 15px 0;
  background: var(--clay-white);
  padding: 15px;
  border-radius: 16px;
}

.rule-group {
  margin-bottom: 18px;
}

.rule-group h4 {
  font-size: 1.1rem;
  margin-bottom: 6px;
  color: var(--clay-blue-dark);
}

.rule-group ul {
  padding-left: 20px;
  margin-top: 4px;
}

.rule-group li {
  margin-bottom: 4px;
  font-size: 0.9rem;
}

.rule-group p {
  font-size: 0.9rem;
  line-height: 1.35;
}

/* Floating Log System (Clay Tablet) & Home Button */
.game-log-floating-container {
  position: absolute;
  top: 15px;
  right: 15px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 5px;
}

.game-home-floating-container {
  position: absolute;
  top: 15px;
  left: 15px;
  z-index: 100;
  display: flex;
  gap: 8px;
}

/* Small round icon buttons (Home / Log) - corner chrome kept minimal so the
   table itself is the focus, UNO-style. */
.log-toggle-btn {
  background: var(--clay-white);
  border: 3px solid var(--clay-white-dark);
  border-radius: 50%;
  width: 42px;
  height: 42px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.9;
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
}

.log-toggle-btn:active {
  transform: scale(0.95);
}

.log-panel {
  width: 250px;
  height: 250px;
  padding: 10px;
  display: flex;
  flex-direction: column;
  text-align: left;
  border-radius: 16px;
  border-width: 3px;
  background: rgba(245, 245, 240, 0.95);
}

.log-panel h3 {
  font-size: 0.9rem;
  margin-bottom: 6px;
  border-bottom: 1px solid #ccc;
  padding-bottom: 4px;
}

.log-entries {
  flex: 1;
  overflow-y: auto;
  font-size: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.log-entry {
  line-height: 1.2;
}

/* CSS Animations for deck, drawing, and custom events */
@keyframes popIn {
  0% { transform: scale(0.5); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

/* Utility visibility classes */
.hidden {
  display: none !important;
}

/* Custom avatars (SVG styling) */
.avatar-svg {
  width: 100%;
  height: 100%;
}

/* Custom animations for squash and stretch */
@keyframes claySquishStretch {
  0% {
    transform: scaleX(1) scaleY(1);
  }
  25% {
    transform: scaleX(0.7) scaleY(1.3); /* Stretch tall as it flies */
  }
  60% {
    transform: scaleX(0.7) scaleY(1.3);
  }
  85% {
    transform: scaleX(1.3) scaleY(0.7); /* Squash flat on impact */
  }
  100% {
    transform: scaleX(1) scaleY(1); /* Settle to normal */
  }
}

.inner-flyer {
  animation: claySquishStretch 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}

/* Screen Shake Animation */
@keyframes screenShake {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  10% { transform: translate(-3px, 2px) rotate(-0.5deg); }
  20% { transform: translate(2px, -3px) rotate(0.5deg); }
  30% { transform: translate(-2px, -2px) rotate(-0.5deg); }
  40% { transform: translate(3px, 2px) rotate(0.5deg); }
  50% { transform: translate(-1px, 3px) rotate(-0.5deg); }
  60% { transform: translate(2px, -2px) rotate(0.5deg); }
  70% { transform: translate(-3px, 1px) rotate(-0.5deg); }
  80% { transform: translate(1px, -3px) rotate(0.5deg); }
  90% { transform: translate(2px, 2px) rotate(-0.5deg); }
}

.game-layout.shake-active {
  animation: screenShake 0.45s ease-in-out;
}

/* Attack gauge design */
.attack-card {
  flex-direction: column !important;
  align-items: stretch !important;
}

.attack-header-row {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
}

.clay-gauge-track {
  width: 100%;
  height: 20px;
  background: #6b2158; /* Deep candy valley */
  border-radius: 10px;
  margin-top: 10px;
  position: relative;
  overflow: hidden;
  box-shadow: inset 3px 3px 6px rgba(0,0,0,0.3), inset -1px -1px 2px rgba(255,255,255,0.1);
  border: 2px solid rgba(0,0,0,0.15);
}

.clay-gauge-fill {
  height: 100%;
  width: 0%; /* Dynamic from JS */
  background: linear-gradient(90deg, #ff8787 0%, #ff4b4b 50%, #c92a2a 100%);
  box-shadow: inset 1px 1px 2px rgba(255,255,255,0.4);
  border-radius: 8px;
  transition: width 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.gauge-pip-markers {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-around;
  pointer-events: none;
}

.gauge-pip-markers span {
  width: 2px;
  height: 100%;
  background: rgba(255, 255, 255, 0.15);
}

/* ==================== CARD SKINS SYSTEM ====================

   Nothing here any more, deliberately.

   A card skin is defined by its ASSETS, not by CSS: register it in ui.js's
   CARD_SKINS with an arch + frame, e.g.
     neon:        { arch: 2, frame: "frame-neon" }        // needs frame-neon.webp
     classic:     { arch: 1 }                            // coloured frame + white symbol
     "ember-gala": { arch: 3, fullArt: c => ... }        // baked per-card art
   and the back art comes from .card-back-face's background-image.

   This block used to hold CSS re-tints (border/background/glow) of the old
   ivory-and-brass face the card drew itself, from before the art landed. The
   catalog has since been shrunk to the skins that actually have art (one
   front / back / board), so every rule here targeted a skin that no longer
   exists. They're gone with it - re-add per skin only as real art ships.
   ==================================================================== */


/* ==================== CLAY SHOP SCREEN ==================== */
.shop-content {
  /* Fill the width like the other content screens (event/inventory) so the tab
     rail hugs the LEFT edge instead of the whole panel being centered. */
  max-width: none !important;
  height: 88% !important;
}

.shop-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  margin-bottom: 12px;
  padding-left: 50px; /* clear the top-left back button */
}

/* Shop body: vertical tab rail on the LEFT + the item grid filling the rest. */
.shop-body {
  display: flex;
  gap: 14px;
  flex: 1;
  min-height: 0;
  width: 100%;
}
.shop-body .shop-tabs-vertical {
  flex-direction: column;
  width: auto;
  flex: 0 0 auto;
  gap: 8px;
  /* Start the top tab level with the FIRST CARD (the grid box's top padding),
     not the grey box's top edge. */
  margin-top: 18px;
  margin-bottom: 0;
  justify-content: flex-start;
  align-items: stretch;
}
.shop-body .shop-tabs-vertical .shop-tab-btn {
  white-space: nowrap;
  text-align: left;
  padding: 10px 18px;
  min-width: 118px;
}
.shop-body .shop-items-scroll-area {
  flex: 1 1 auto;
  min-width: 0;
}

.shop-coin-badge {
  background: var(--clay-yellow-light);
  border: 3px solid var(--clay-yellow-dark);
  padding: 8px 16px;
  border-radius: 18px;
  font-weight: 700;
  font-size: 1.1rem;
  box-shadow: var(--clay-btn-shadow);
  color: var(--clay-dark);
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Shop: balance shown as plain text, no yellow box (per product owner). */
/* Shop header currency: the clay currency box (was stripped to transparent
   floating icons+numbers - "missing the box"). Dark clay fill + white numerals,
   matching the home pills and the collection dust badge. */
#screen-shop .shop-header .shop-coin-badge {
  background: linear-gradient(180deg, #5b5273, #423a58);
  border: none;
  border-radius: 999px;
  color: #fff;
  padding: 5px 15px;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.2),
    inset 0 -3px 5px rgba(0, 0, 0, 0.26),
    0 5px 9px rgba(58, 46, 72, 0.35);
}
#screen-shop .shop-header .shop-coin-badge .currency-icon { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35)); }

/* Enlarge-and-confirm shop item modal */
.shop-item-modal-card {
  background: var(--clay-panel);
  border: 6px solid var(--clay-panel-dark);
  border-radius: 28px;
  padding: 22px 26px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  max-width: 320px;
  box-shadow: 10px 10px 24px rgba(0, 0, 0, 0.28);
}
.shop-item-modal-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 186px;
  margin-bottom: 4px;
}
.shop-item-modal-preview .clay-card-element { width: 130px; height: 182px; }
.shop-item-modal-preview .board-swatch-preview { width: 220px; height: 110px; }
.shop-item-modal-preview .avatar-shop-preview { width: 150px; height: 150px; border-radius: 24px; overflow: hidden; }
.shop-item-modal-preview .avatar-shop-preview img { width: 100%; height: 100%; object-fit: cover; }
.shop-item-modal-name { font-size: 1.3rem; font-weight: 800; color: var(--clay-dark); text-align: center; }
.shop-item-modal-price { font-size: 1.05rem; font-weight: 700; color: var(--clay-dark); }
.shop-item-modal-actions { display: flex; gap: 12px; margin-top: 10px; }

/* Owned/Equipped status text on the compact tiles */
.shop-item-status.owned { color: var(--clay-blue-dark); }
.shop-item-status.equipped { color: var(--clay-green-dark); }

/* Coins + Gems shown side by side (spec 9.2/10.1 - Gems is the hard,
   real-money-backed currency alongside soft-currency Coins). */
.currency-badge-row {
  gap: 14px;
}
.currency-badge-row > span {
  display: flex;
  align-items: center;
  gap: 4px;
}

.shop-tabs {
  display: flex;
  gap: 15px;
  margin-bottom: 15px;
  width: 100%;
  justify-content: center;
}

.shop-tab-btn {
  /* Borderless clay, matching the currency pills + buttons - the hard 3px
     stroke ("dark border throughout") is gone; a light lip + soft inner shadow
     + contact shadow does the shaping now. Padding bumped to offset the border
     removal (box-sizing:border-box, so the stroke used to eat into size). */
  background: linear-gradient(180deg, #f4f0fc, #ddd6ef);
  color: var(--clay-dark);
  border: none;
  border-radius: 15px;
  padding: 11px 22px;
  /* <button>s don't inherit the page font - match the currency/body font. */
  font-family: var(--font-main);
  font-weight: 800;
  cursor: pointer;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.6),
    inset 0 -3px 5px rgba(0, 0, 0, 0.1),
    0 4px 8px rgba(74, 68, 99, 0.2);
  transition: transform 0.1s, box-shadow 0.2s;
}

.shop-tab-btn.active {
  background: linear-gradient(180deg, #72c0fb, #228be6); /* blue clay pill, matching btn-primary */
  color: white;
  text-shadow: 1px 1px 0px rgba(0,0,0,0.15);
}

.shop-tab-btn:hover {
  transform: translateY(-2px);
}

.shop-tab-btn:active {
  transform: translateY(1px);
}

/* (The old .missions-tabs block here was from a FIVE-tab design
   (Daily/Weekly/Monthly/Challenges/Collection) and gave each tab `flex: 1 1 0`
   so they'd share the row. With only three tabs left that stretched each one to
   a full third of the window. The live rules are in the missions-window block
   further down.) */

.shop-items-scroll-area {
  flex: 1;
  width: 100%;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.12);
  border-radius: 24px;
  padding: 18px;
  margin-bottom: 15px;
  box-shadow: inset 3px 3px 6px rgba(0,0,0,0.2);
}

.shop-items-grid {
  display: grid;
  /* Compact tiles - ~6 per row, sized to the panel (shop / inventory /
     collection all share this grid + .shop-item-card). */
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 9px;
}

.shop-item-card {
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 14px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  transition: transform 0.2s ease;
}
.shop-item-name { font-size: 0.72rem; line-height: 1.15; text-align: center; }
.shop-item-price { font-size: 0.68rem; }

.shop-item-card:hover {
  transform: translateY(-4px);
}

.shop-item-preview-holder {
  /* Compact preview (see .shop-items-grid) - a 58x81 slot; each preview type
     is scaled to fit inside it below, so tiles pack ~6 per row. */
  width: 58px;
  height: 81px;
  position: relative;
  margin-bottom: 4px;
  /* centers non-absolute previews (the landscape board mat); absolutely
     positioned card fronts/backs are unaffected */
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Card front/back preview: full 100x140 card scaled down to the 66x92 slot. */
.shop-item-preview-holder .clay-card-element {
  position: absolute;
  left: 0;
  top: 0;
  width: 100px;
  height: 140px;
  transform: scale(0.58);
  transform-origin: top left;
}
/* Avatar + board previews scaled to the same compact slot (scoped to tiles so
   the equipped-showcase / profile-preview panels keep their full size). */
.shop-item-preview-holder .avatar-shop-preview {
  width: 56px;
  height: 56px;
  margin-top: 0;
  border-width: 3px;
}
.shop-item-preview-holder .board-swatch-preview {
  --board-preview-w: 56px;
  --board-preview-h: 28px;
}
/* Inventory only (task 14): the board tile matches the card front/back
   footprint - a portrait card-shaped swatch filling the 58x81 preview slot
   (100x140 * 0.58), instead of the compact 2:1 landscape mat used elsewhere. */
#screen-inventory .shop-item-preview-holder .board-swatch-preview {
  --board-preview-w: 58px;
  --board-preview-h: 81px;
}

/* Boards (spec 6.1) preview: ONE canonical proportion everywhere - a 2:1
   landscape mini play mat (matching the real in-match board's shape), not a
   card-shaped swatch. Every surface (shop, inventory, equipped rail) uses
   these same tokens so board previews are identical across the app. */
:root {
  --board-preview-w: 104px;
  --board-preview-h: 52px;
}
.board-swatch-preview {
  width: var(--board-preview-w);
  height: var(--board-preview-h);
  border-radius: 12px;
  border: 4px solid;
  box-shadow: inset 3px 3px 8px rgba(0,0,0,0.25), inset -3px -3px 8px rgba(255,255,255,0.15);
  flex-shrink: 0;
}

/* Tier badge (spec 6.2/10.3): Common = cheap frame-tint-only, Epic = the
   real-money-backed tier with custom art/typography/animation. */
.shop-tier-badge {
  font-size: 0.65rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 2px 10px;
  border-radius: 10px;
  margin-bottom: 4px;
}
.shop-tier-badge.tier-common {
  background: var(--clay-white-dark);
  color: var(--clay-dark);
}
.shop-tier-badge.tier-epic {
  background: linear-gradient(135deg, #a78bfa, #f472b6);
  color: white;
  text-shadow: 1px 1px 0px rgba(0,0,0,0.2);
}

.shop-item-name {
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: 6px;
  color: var(--clay-dark);
}

.shop-item-price {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--clay-yellow-dark);
  margin-bottom: 10px;
}

.shop-item-btn {
  width: 100%;
  font-size: 0.85rem !important;
  padding: 6px 12px !important;
  border-radius: 12px !important;
}

.btn-equipped {
  background: var(--clay-green) !important;
  border-color: var(--clay-green-dark) !important;
  cursor: default !important;
  pointer-events: none;
}

/* ------------------------------------------------------------------ */
/* Event system (spec section 5) - collection grid + missions list     */
/* ------------------------------------------------------------------ */

.event-countdown {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--clay-dark);
  opacity: 0.75;
}

.event-progress-text {
  text-align: center;
  font-weight: 700;
  font-size: 1rem;
  margin-bottom: 12px;
  color: var(--clay-dark);
}

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

.event-card-tile {
  aspect-ratio: 2 / 3;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.75rem;
  border: 3px solid var(--clay-white-dark);
  background: var(--clay-white-light);
  box-shadow: var(--clay-shadow-out);
  position: relative;
  text-align: center;
  padding: 2px;
}

/* Collected: NO green fill. The tile is taller than the 5:7 card art, so a
   coloured background showed as green bands above and below the card. The
   glow + check mark already say "owned". */
.event-card-tile.owned {
  background: var(--clay-white-light);
  color: var(--clay-dark);
}

.event-card-tile.owned::after {
  content: "✓";
  position: absolute;
  top: 2px;
  right: 4px;
  font-size: 0.7rem;
  color: var(--clay-green-dark);
}

.event-card-tile.missing {
  /* Deliberately no opacity/grayscale filter on the whole tile - the buy
     row below has real interactive buttons now (Dust/Coins/Gems, spec
     5.4/10.4), and a filter on this element would visually wash them out
     along with the label, making working buttons look disabled. */
  background: var(--clay-white-dark);
}

/* Open Pack button (spec 5.1 v5: ECP reward unit) - sits between the
   progress text and the collection grid. */
#btn-open-pack {
  align-self: center;
  margin: 0 auto 12px;
  display: block;
}

/* Mission cadence tag (Daily/Weekly/Monthly/Milestone/Achievement) */
.mission-cadence-tag {
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  background: var(--clay-white-dark);
  color: var(--clay-dark);
  border-radius: 8px;
  padding: 1px 7px;
  margin-left: 6px;
  vertical-align: middle;
  opacity: 0.8;
}

/* Vault per-card "pick a card" inline list (spec 5.4 v5 - 50 Dust choice) */
.vault-pick-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  justify-content: center;
  margin-top: 8px;
  max-height: 140px;
  overflow-y: auto;
}

.vault-pick-card-btn {
  font-size: 0.6rem !important;
  padding: 3px 6px !important;
  border-radius: 8px !important;
  background: var(--clay-white);
  color: var(--clay-dark);
}

/* ---------------------------------------------------------------------------
   Card Collection Board (spec 6.5) - per-skin 45-card progress grid.
   Collected tiles render as mini clay cards in the skin's real frame;
   uncollected ones are greyed silhouettes.
--------------------------------------------------------------------------- */

.ccb-actions-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.ccb-hint {
  font-size: 0.8rem;
  color: var(--clay-dark);
  opacity: 0.7;
  margin: 0;
  width: 100%;
  text-align: center;
}

/* Every collection board shows the whole set at a glance: 11 cards per row -
   the CCB popup (#ccb-card-grid), the missions Collection tab
   (#event-card-grid) and the Event nav screen (#collection-event-grid). */
#ccb-card-grid.ccb-grid,
#event-card-grid,
#collection-event-grid {
  grid-template-columns: repeat(11, 1fr);
  gap: 5px;
}

.ccb-grid .ccb-tile {
  aspect-ratio: 2 / 3;
  border-radius: 10px;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
}

/* At 11-wide the tiles are small - shrink the per-card buy buttons to match. */
/* Collected: a shrunken real clay card (the skin's frame class applies). */
.ccb-tile .clay-card-element {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 4px;
  border-width: 3px;
  cursor: default;
}
.ccb-tile .clay-card-element .card-corner { font-size: 0.55rem; }
.ccb-tile .clay-card-element .card-center {
  width: 60%;
  height: 55%;
  font-size: 1rem;
  border-radius: 8px;
}
/* The tile rule above sets an explicit non-square height, which would squash the
   paw stamp and hand container-type:size a non-square box for the number to size
   against. Attack cards keep their square stamp here. */
.ccb-tile .clay-card-element .card-center.attack-center {
  width: 74%;
  height: auto;
  aspect-ratio: 1 / 1;
}

/* Uncollected: greyed silhouette placeholder (spec 6.5). */
.ccb-tile.silhouette {
  background: rgba(0, 0, 0, 0.12);
  border: 3px dashed rgba(0, 0, 0, 0.25);
  color: rgba(0, 0, 0, 0.45);
  font-size: 0.7rem;
  font-weight: 700;
  text-align: center;
  padding: 4px;
}

/* Just-collected celebration on the slot (spec 6.6's landing moment). */
@keyframes ccbSlotPop {
  0% { transform: scale(0.6); box-shadow: 0 0 0 rgba(255, 215, 0, 0); }
  55% { transform: scale(1.15); box-shadow: 0 0 24px rgba(255, 215, 0, 0.9); }
  100% { transform: scale(1); box-shadow: 0 0 6px rgba(255, 215, 0, 0.3); }
}
.ccb-tile.just-collected,
.event-card-tile.just-collected {
  animation: ccbSlotPop 0.7s ease-out;
}

/* ---------------------------------------------------------------------------
   Pack-opening animation (spec 6.6) - pack appears -> shakes -> bursts ->
   card flips in. One sequence for every grant source; the pack visual class
   (pack-ecp / pack-vault-random / pack-vault-choice) is the only difference.
--------------------------------------------------------------------------- */

.pack-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  min-height: 320px;
}

.pack-visual {
  width: 150px;
  height: 210px;
  border-radius: 18px;
  border: 6px solid;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  box-shadow: var(--clay-shadow-out), inset 2px 2px 6px rgba(255, 255, 255, 0.35);
}
.pack-visual .pack-icon { font-size: 3.2rem; }
.pack-visual .pack-shine {
  position: absolute;
  top: -60%;
  left: -60%;
  width: 60%;
  height: 220%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.5), transparent);
  transform: rotate(20deg);
  animation: packShine 1.4s ease-in-out infinite;
}
@keyframes packShine {
  from { left: -60%; }
  to { left: 120%; }
}

/* Pack visual by source (spec 6.6) */
.pack-visual.pack-ecp { background: linear-gradient(160deg, #b7442e, #7a1f12); border-color: #f5c04e; } /* event-themed (Ember Gala) */
.pack-visual.pack-vault-random { background: linear-gradient(160deg, #8d97ab, #4d5668); border-color: #cfd6e2; }
.pack-visual.pack-vault-choice { background: linear-gradient(160deg, #7b5cd6, #45318a); border-color: #d9c9ff; }

@keyframes packShake {
  0%, 100% { transform: rotate(0deg); }
  20% { transform: rotate(-6deg) scale(1.02); }
  40% { transform: rotate(6deg) scale(1.04); }
  60% { transform: rotate(-5deg) scale(1.06); }
  80% { transform: rotate(5deg) scale(1.08); }
}
.pack-visual.pack-shake { animation: packShake 0.6s ease-in-out; }

@keyframes packBurst {
  from { transform: scale(1.1); opacity: 1; }
  to { transform: scale(1.9); opacity: 0; }
}
.pack-visual.pack-burst { animation: packBurst 0.32s ease-out forwards; }

.pack-card-reveal {
  perspective: 700px;
}
.pack-card-reveal .clay-card-element {
  position: relative;
  width: 140px;
  height: 196px;
  cursor: default;
  animation: packCardFlipIn 0.5s ease-out;
}
@keyframes packCardFlipIn {
  from { transform: rotateY(90deg) scale(0.7); opacity: 0; }
  to { transform: rotateY(0deg) scale(1); opacity: 1; }
}

.pack-result-label {
  font-size: 1.15rem;
  font-weight: 800;
  color: white;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
  min-height: 1.4em;
  text-align: center;
}

/* "Tap to continue" prompt shown under the reveal (pack now waits for a tap). */
.pack-tap-hint {
  display: block;
  margin-top: 10px;
  font-size: 0.8rem;
  font-weight: 600;
  opacity: 0.85;
  animation: tap-hint-pulse 1.3s ease-in-out infinite;
}
@keyframes tap-hint-pulse {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 0.95; }
}

/* spec 4.7: online Joker slide-behind - starts raised above the pile, slides
   down/under the top card (it paints beneath via DOM order), then fades,
   leaving the unchanged top card clearly still in charge of the table. */
@keyframes jokerSlideBehind {
  0% { transform: translate(-60px, -90px) rotate(-14deg) scale(1.05); opacity: 0; }
  25% { opacity: 1; }
  60% { transform: translate(8px, 5px) rotate(4deg) scale(0.96); opacity: 1; }
  85% { transform: translate(8px, 5px) rotate(4deg) scale(0.96); opacity: 1; }
  100% { transform: translate(8px, 5px) rotate(4deg) scale(0.96); opacity: 0; }
}
.joker-slide-behind {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%; /* matches the (hand-card-sized) discard container */
  height: 100%;
  cursor: default;
  pointer-events: none;
  animation: jokerSlideBehind 1.45s ease-in-out forwards;
}

/* Shop Event tab summary panel (spec 10.2 tab 3) */
.shop-event-stats-row {
  display: flex;
  justify-content: center;
  gap: 24px;
  font-weight: 700;
  color: var(--clay-dark);
  margin: 14px 0;
}

/* Section headers inside the Tasks panel (Daily / Weekly / Monthly, spec 12.1) */
.task-section-header {
  list-style: none;
  font-weight: 800;
  font-size: 0.95rem;
  color: var(--clay-dark);
  opacity: 0.75;
  margin-top: 6px;
  padding-left: 4px;
}

/* Profile inventory secondary tabs (spec 11.3 Owned / Not Owned) */
.profile-subtabs {
  margin-top: -6px;
}
.profile-subtabs .shop-tab-btn {
  font-size: 0.8rem;
  padding: 5px 14px;
}

.missions-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* A claimed mission stays on the list, visibly "spent": dimmed and
   desaturated, DONE button disabled (buildMissionRow renders it that way). */
.mission-row.mission-claimed { opacity: 0.5; filter: grayscale(0.55); }
.mission-row.mission-claimed .mission-claim-btn { pointer-events: none; }

.mission-row {
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 14px;
  padding: 4px 12px; /* shorter rows (was 7px) */
  /* Uniform panel size: min-height holds every row the same regardless of
     content, and titles clamp to one line so a longer label can't grow one row
     taller than the rest. (Previously the leading icon+rank column set this
     height; that column was removed and the rank moved beside the XP.) */
  min-height: 58px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  box-shadow: var(--clay-shadow-out);
}

.mission-row.eligible {
  border-color: var(--clay-green-dark);
}

.mission-row-title {
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--clay-dark);
  /* One line only, so a long label can't make its row taller than the others. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mission-row-desc {
  font-size: 0.68rem;
  opacity: 0.75;
  color: var(--clay-dark);
}

.mission-claim-btn {
  font-size: 0.72rem !important;
  padding: 5px 12px !important;
  border-radius: 11px !important;
  white-space: nowrap;
}

.missions-all-done {
  list-style: none;
  text-align: center;
  padding: 24px 12px;
  opacity: 0.75;
  color: var(--clay-dark);
  font-weight: 600;
}

.mission-claim-btn:disabled {
  /* spec 12.2 "enabled only once complete": visibly DEAD, not just dimmed -
     flat warm grey matching the clay-tile palette, no ledge, no drop shadow,
     muted label. (opacity alone read as "still green enough to look
     claimable" - caught via a live screenshot back when this rule was born.) */
  background: #ded7c9 !important;
  border-color: transparent !important;
  color: #a49b8d !important;
  text-shadow: none;
  box-shadow: none !important;
  transform: none;
  opacity: 1;
  cursor: default !important;
  pointer-events: none;
}

/* Difficulty tags on daily missions (Easy/Medium/Hard) + the Event tag. */
.mission-tier-tag {
  display: inline-block;
  font-size: 0.52rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 1px 8px;
  border-radius: 10px;
  vertical-align: middle;
  margin-left: 4px;
  color: #fff;
}
.mission-tier-tag.tier-easy { background: var(--clay-green); }
.mission-tier-tag.tier-medium { background: var(--clay-blue); }
.mission-tier-tag.tier-hard { background: #b06bd6; }
.mission-tier-tag.tier-event { background: #f0872e; }

.mission-row-main { min-width: 0; }

/* Event-daily capstone: its own coloured box, count sits right of CLAIM. */
.mission-row.event-daily-row {
  background: linear-gradient(180deg, #fff3e0, #ffe3c2);
  border-color: #f0a45a;
}
.event-daily-claim {
  display: flex;
  align-items: center;
  gap: 10px;
}
.event-daily-count {
  font-weight: 800;
  color: #c25e12;
  font-size: 0.82rem;
  white-space: nowrap;
}

/* AI opponent slot wrappers for vertical sidebar placement */
.opponent-slot {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 80px;
}
.opponent-slot:empty {
  display: none;
}

/* Human Active Turn Highlights */
.player-info-badge.active-turn {
  border-color: var(--clay-red);
  transform: scale(1.03);
  box-shadow: 0 0 20px rgba(255, 107, 107, 0.8), var(--clay-shadow-out), var(--clay-shadow-in);
  animation: turnPulseHuman 1.5s infinite alternate;
}

@keyframes turnPulseHuman {
  0% { box-shadow: 0 0 10px rgba(255, 107, 107, 0.5), var(--clay-shadow-out), var(--clay-shadow-in); }
  100% { box-shadow: 0 0 20px rgba(255, 107, 107, 0.85), var(--clay-shadow-out), var(--clay-shadow-in); }
}

/* Inactive Attack status card style (always present on right sidebar) */
.attack-card {
  background: var(--clay-white);
  border-color: var(--clay-white-dark);
  padding: 12px;
  border-radius: 16px;
  border-width: 3px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  animation: none; /* No shake when inactive */
  transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.attack-card.active-attack {
  background: var(--clay-red-light);
  border-color: var(--clay-red);
  animation: attackShake 0.4s infinite alternate;
}

/* The attack-stack bar is ALWAYS on screen (shows +0 in a neutral state, then
   turns red + shakes while an attack stacks) so players can always see it. */
.attack-card:not(.active-attack) {
  opacity: 0.9;
}

/* Deck count badge below the draw pile */
/* Hangs BELOW the deck, out of flow: in-flow it made .deck-container taller
   than the deck card itself, and .play-area centres its children - so the
   badge's height pushed the deck card ~16px above the discard card sitting
   next to it. Absolute keeps the container exactly one card tall, so deck and
   discard line up. */
.deck-count-badge {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 8px;
  white-space: nowrap;
  text-align: center;
  font-size: 0.85rem;
  font-weight: 800;
  color: white;
  /* Dark plum pill: white-on-20%-black was washing out against the pink
     board; this holds contrast on ANY board colour, art or flat. */
  background: rgba(58, 46, 72, 0.72);
  padding: 2px 10px;
  border-radius: 10px;
  display: inline-block;
  box-shadow: inset 1px 1px 2px rgba(0,0,0,0.15);
}

.deck-container {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Bouncing deck draw arrow hint */
.deck-draw-arrow {
  position: absolute;
  top: -45px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 2.2rem;
  z-index: 10;
  pointer-events: none;
  animation: arrowBounce 0.6s infinite alternate;
  filter: drop-shadow(2px 2px 0px rgba(0,0,0,0.15));
}

@keyframes arrowBounce {
  0% { transform: translate(-50%, 0); }
  100% { transform: translate(-50%, -10px); }
}

/* Turn-direction indicator: a stationary clay dish the cards sit on
   (.play-area::before) with soft chevrons orbiting its rim BEHIND the cards
   - replaces the old dashed ellipse whose line visibly cut across the deck
   and discard. */
.play-area::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 350px;
  height: 215px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.09);
  box-shadow: inset 4px 6px 14px rgba(0, 0, 0, 0.08), inset -3px -5px 12px rgba(255, 255, 255, 0.2);
  z-index: 0;
  pointer-events: none;
}

.direction-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 350px;
  height: 215px;
  border: none;
  z-index: 0; /* rim chevrons orbit BEHIND the cards, never across them */
  pointer-events: none;
  box-sizing: border-box;
  /* Semi-axes of the ELLIPTICAL orbit the chevrons travel - matching the
     visible dish (.play-area::before, 350x215) so the arrows ride exactly
     along its rim. The ring container itself never rotates. */
  --orbit-rx: 175px;
  --orbit-ry: 107px;
}

/* Cards sit above the dish and the orbiting chevrons */
.deck-container,
.discard-container {
  position: relative;
  z-index: 2;
}

/* Each chevron orbits the dish center on a fixed circle (staying ON the orbit,
   never rotating the whole ring). The four are spaced a quarter-turn apart via
   negative animation delays. Glyphs point along the direction of travel. */
.direction-arrow-fx {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1em;
  height: 1em;
  margin: -0.5em 0 0 -0.5em;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.8);
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1;
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.55), 0 1px 2px rgba(84, 74, 133, 0.15);
  animation: orbit-cw 15s linear infinite;
  animation-delay: var(--orbit-delay, 0s);
}
.direction-ring.counter-clockwise .direction-arrow-fx {
  animation-name: orbit-ccw;
}
.arrow-1 { --orbit-delay: 0s; }
.arrow-2 { --orbit-delay: -3.75s; }
.arrow-3 { --orbit-delay: -7.5s; }
.arrow-4 { --orbit-delay: -11.25s; }

/* Elliptical orbit sampled at 22.5-degree steps: position = (rx*cos, ry*sin),
   glyph rotated along the ellipse's local travel direction (tangent). A plain
   rotate/translate spin can only make a CIRCLE - these baked stops keep the
   chevrons on the dish's actual elliptical rim. */
@keyframes orbit-cw {
  0%     { transform: translate(calc(var(--orbit-rx) *  1.000), calc(var(--orbit-ry) *  0.000)) rotate(90deg); }
  6.25%  { transform: translate(calc(var(--orbit-rx) *  0.924), calc(var(--orbit-ry) *  0.383)) rotate(124deg); }
  12.5%  { transform: translate(calc(var(--orbit-rx) *  0.707), calc(var(--orbit-ry) *  0.707)) rotate(148deg); }
  18.75% { transform: translate(calc(var(--orbit-rx) *  0.383), calc(var(--orbit-ry) *  0.924)) rotate(166deg); }
  25%    { transform: translate(calc(var(--orbit-rx) *  0.000), calc(var(--orbit-ry) *  1.000)) rotate(180deg); }
  31.25% { transform: translate(calc(var(--orbit-rx) * -0.383), calc(var(--orbit-ry) *  0.924)) rotate(194deg); }
  37.5%  { transform: translate(calc(var(--orbit-rx) * -0.707), calc(var(--orbit-ry) *  0.707)) rotate(212deg); }
  43.75% { transform: translate(calc(var(--orbit-rx) * -0.924), calc(var(--orbit-ry) *  0.383)) rotate(236deg); }
  50%    { transform: translate(calc(var(--orbit-rx) * -1.000), calc(var(--orbit-ry) *  0.000)) rotate(270deg); }
  56.25% { transform: translate(calc(var(--orbit-rx) * -0.924), calc(var(--orbit-ry) * -0.383)) rotate(304deg); }
  62.5%  { transform: translate(calc(var(--orbit-rx) * -0.707), calc(var(--orbit-ry) * -0.707)) rotate(328deg); }
  68.75% { transform: translate(calc(var(--orbit-rx) * -0.383), calc(var(--orbit-ry) * -0.924)) rotate(346deg); }
  75%    { transform: translate(calc(var(--orbit-rx) *  0.000), calc(var(--orbit-ry) * -1.000)) rotate(360deg); }
  81.25% { transform: translate(calc(var(--orbit-rx) *  0.383), calc(var(--orbit-ry) * -0.924)) rotate(374deg); }
  87.5%  { transform: translate(calc(var(--orbit-rx) *  0.707), calc(var(--orbit-ry) * -0.707)) rotate(392deg); }
  93.75% { transform: translate(calc(var(--orbit-rx) *  0.924), calc(var(--orbit-ry) * -0.383)) rotate(416deg); }
  100%   { transform: translate(calc(var(--orbit-rx) *  1.000), calc(var(--orbit-ry) *  0.000)) rotate(450deg); }
}
@keyframes orbit-ccw {
  0%     { transform: translate(calc(var(--orbit-rx) *  1.000), calc(var(--orbit-ry) *  0.000)) rotate(-90deg); }
  6.25%  { transform: translate(calc(var(--orbit-rx) *  0.924), calc(var(--orbit-ry) * -0.383)) rotate(-124deg); }
  12.5%  { transform: translate(calc(var(--orbit-rx) *  0.707), calc(var(--orbit-ry) * -0.707)) rotate(-148deg); }
  18.75% { transform: translate(calc(var(--orbit-rx) *  0.383), calc(var(--orbit-ry) * -0.924)) rotate(-166deg); }
  25%    { transform: translate(calc(var(--orbit-rx) *  0.000), calc(var(--orbit-ry) * -1.000)) rotate(-180deg); }
  31.25% { transform: translate(calc(var(--orbit-rx) * -0.383), calc(var(--orbit-ry) * -0.924)) rotate(-194deg); }
  37.5%  { transform: translate(calc(var(--orbit-rx) * -0.707), calc(var(--orbit-ry) * -0.707)) rotate(-212deg); }
  43.75% { transform: translate(calc(var(--orbit-rx) * -0.924), calc(var(--orbit-ry) * -0.383)) rotate(-236deg); }
  50%    { transform: translate(calc(var(--orbit-rx) * -1.000), calc(var(--orbit-ry) *  0.000)) rotate(-270deg); }
  56.25% { transform: translate(calc(var(--orbit-rx) * -0.924), calc(var(--orbit-ry) *  0.383)) rotate(-304deg); }
  62.5%  { transform: translate(calc(var(--orbit-rx) * -0.707), calc(var(--orbit-ry) *  0.707)) rotate(-328deg); }
  68.75% { transform: translate(calc(var(--orbit-rx) * -0.383), calc(var(--orbit-ry) *  0.924)) rotate(-346deg); }
  75%    { transform: translate(calc(var(--orbit-rx) *  0.000), calc(var(--orbit-ry) *  1.000)) rotate(-360deg); }
  81.25% { transform: translate(calc(var(--orbit-rx) *  0.383), calc(var(--orbit-ry) *  0.924)) rotate(-374deg); }
  87.5%  { transform: translate(calc(var(--orbit-rx) *  0.707), calc(var(--orbit-ry) *  0.707)) rotate(-392deg); }
  93.75% { transform: translate(calc(var(--orbit-rx) *  0.924), calc(var(--orbit-ry) *  0.383)) rotate(-416deg); }
  100%   { transform: translate(calc(var(--orbit-rx) *  1.000), calc(var(--orbit-ry) *  0.000)) rotate(-450deg); }
}

/* ------------------------------------------------------------------ */
/* Tutorial (spec section 13) - guided lesson banner + card highlight  */
/* ------------------------------------------------------------------ */

.tutorial-lesson-banner {
  position: absolute;
  top: 12%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  width: min(520px, 88%);
  animation: tutorialBannerIn 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

@keyframes tutorialBannerIn {
  from { opacity: 0; transform: translate(-50%, -12px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

.tutorial-lesson-card {
  background: var(--clay-white-light);
  border: 4px solid var(--clay-blue);
  border-radius: 22px;
  padding: 18px 22px;
  box-shadow: var(--clay-shadow-out), 0 0 20px rgba(77, 171, 247, 0.35);
  text-align: center;
}

.tutorial-lesson-card h3 {
  margin: 0 0 8px;
  color: var(--clay-dark);
  font-size: 1.15rem;
}

.tutorial-lesson-card p {
  margin: 0 0 12px;
  color: var(--clay-dark);
  font-size: 0.9rem;
  line-height: 1.4;
}

.tutorial-skip-btn {
  /* Offset below the log toggle (.game-log-floating-container sits at the
     same top:15px/right:15px corner with z-index:100) so the two never
     overlap and steal each other's clicks. */
  position: absolute;
  top: 62px;
  right: 14px;
  z-index: 100;
  font-size: 0.7rem !important;
  padding: 6px 12px !important;
  opacity: 0.75;
}

/* The one card a guided step allows - a glowing highlight distinct from the
   ordinary "legal to play" state, so it reads as "play THIS one." Pulses
   box-shadow only (never transform) - the card's position/size must stay
   perfectly still so a mid-pulse tap always lands where the player expects,
   rather than chasing a bouncing target. */
.clay-card-element.tutorial-target {
  animation: tutorialTargetPulse 1.1s ease-in-out infinite;
  /* 300: above every static board element - fan neighbours (inline z 5+N),
     the player avatar badge, deck/discard - but under flyers/alerts (500+).
     The ring is a box-shadow spread (not `outline`): it scrolls, clips and
     stacks exactly like the card itself, so nothing can slice through it. */
  z-index: 300 !important;
  box-shadow: 0 0 0 3px rgba(77, 171, 247, 0.9);
  border-radius: 14px;
  position: relative;
}

/* The animation OWNS box-shadow while running, so the steady 3px ring must
   ride inside every keyframe or the pulse would erase it. */
@keyframes tutorialTargetPulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(77, 171, 247, 0.9), 0 0 0 rgba(77, 171, 247, 0); }
  50% { box-shadow: 0 0 0 3px rgba(77, 171, 247, 0.9), 0 0 22px 6px rgba(77, 171, 247, 0.7); }
}

/* ------------------------------------------------------------------ */
/* Tutorial completion screen                                          */
/* ------------------------------------------------------------------ */

.tutorial-complete-content {
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 14px;
}

.tutorial-complete-icon {
  font-size: 3.5rem;
  margin-bottom: 4px;
}

.tutorial-reward-text {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--clay-yellow-dark);
  margin: 8px 0 20px;
}

.tutorial-link-blurb {
  max-width: 420px;
  margin: 0 auto 16px;
  color: var(--clay-dark);
  opacity: 0.85;
  font-size: 0.9rem;
}

.tutorial-link-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 10px;
}

/* ------------------------------------------------------------------ */
/* Home screen top bar + bottom nav (spec section 9.2)                 */
/* ------------------------------------------------------------------ */

.home-topbar {
  position: absolute;
  top: max(16px, env(safe-area-inset-top));
  /* Extra breathing room from the screen edges (and always some gap BEYOND a
     notch inset on devices) so the avatar/currency aren't jammed to the edge. */
  left: max(30px, calc(env(safe-area-inset-left) + 16px));
  right: max(30px, calc(env(safe-area-inset-right) + 16px));
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 10;
}

.topbar-avatar-btn {
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 0;
}

.topbar-avatar-holder {
  width: 46px;
  height: 46px;
  border-radius: 13px;
  overflow: hidden;
  border: 3px solid var(--clay-white);
  box-shadow: var(--clay-shadow-out);
  display: block;
}
.topbar-avatar-holder svg {
  width: 100%;
  height: 100%;
}

.player-level-badge {
  background: var(--clay-purple, var(--clay-dark));
  color: white;
  font-size: 0.65rem;
  font-weight: 800;
  padding: 1px 8px;
  border-radius: 10px;
  white-space: nowrap;
}

.topbar-icon-buttons {
  display: flex;
  gap: 8px;
}

.topbar-icon-btn {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 3px solid var(--clay-white-dark);
  background: var(--clay-white-light);
  font-size: 1.1rem;
  cursor: pointer;
  box-shadow: var(--clay-shadow-out);
  transition: transform 0.15s ease;
}
.topbar-icon-btn:hover {
  transform: translateY(-2px);
}

.home-event-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* Bright premium banner - ivory card with a gold accent edge (the old
     dark-maroon version was the one dark blob on the bright home screen) */
  background: linear-gradient(135deg, #fffdf6, #fff6e0);
  border: 3px solid #e6c65c;
  border-radius: 18px;
  padding: 10px 18px;
  color: var(--clay-dark);
  width: min(420px, 90%);
  box-shadow: var(--clay-shadow-out);
}
.home-event-banner-name {
  font-weight: 800;
  font-size: 0.95rem;
}
.home-event-banner-progress {
  font-size: 0.75rem;
  opacity: 0.85;
}
.home-event-banner-countdown {
  font-size: 0.8rem;
  font-weight: 700;
  color: #b8860b; /* readable gold on the bright banner */
  white-space: nowrap;
}

.btn-huge {
  font-size: 1.6rem !important;
  padding: 22px 70px !important;
  border-radius: 30px !important;
}

/* Full-screen game-mode picker */
.play-modes-content {
  justify-content: center;
  gap: 34px;
}
.play-modes-help {
  position: absolute;
  top: 22px;
  right: 22px;
}
.play-modes-options {
  display: flex;
  gap: 2.2vw;
  justify-content: center;
  flex-wrap: nowrap; /* always one row - the cards shrink to fit the screen */
  width: 100%;
  /* 4 panels since online split into 1v1 + 4-player (was 3 at 760px). */
  max-width: 940px;
}
.play-modes-options .mode-card {
  flex: 1 1 0;
  min-width: 0;      /* allow shrink below content so 3 always fit one row */
  width: auto;
  max-width: 240px;
  padding: clamp(12px, 3vw, 28px) clamp(8px, 1.6vw, 18px);
}
/* Card content scales with the viewport so it stays legible when the cards
   shrink on smaller phones. */
.play-modes-options .mode-icon { font-size: clamp(1.9rem, 6vw, 3.4rem); margin-bottom: 6px; }
/* The 4-player icon is a WIDE 4-figure group (~2.15:1) - capped to the card's
   width so it can't overflow, and given a touch more height so the figures
   read at the same visual weight as the square single icons. */
.mode-icon-4p { height: 1.15em; max-width: 100%; object-fit: contain; }
/* The 1v1 pair icon is from the same clay-figure set as the 4-player art -
   sized to match their visual weight. */
.mode-icon-2p { height: 1.15em; max-width: 100%; object-fit: contain; }
.play-modes-options .mode-card h3 { font-size: clamp(0.9rem, 2.4vw, 1.4rem); margin-bottom: 4px; }
.play-modes-options .mode-card p { font-size: clamp(0.65rem, 1.6vw, 0.95rem); }
.play-modes-options .mode-coming-soon { font-size: clamp(0.55rem, 1.4vw, 0.7rem); }

/* ---- Per-panel mode art (surface pass hook) ---------------------------------
   Each mode card gets a full-bleed 2:3 clay illustration behind its content,
   cover-fit and centred so the art's calm centre band sits under the title/
   subtitle while the vivid edges crop away. Two layers behind the content:
     ::before = the art itself, knocked back to 62% so it reads as texture, not
                a competing illustration;
     ::after  = a soft cream veil (stronger through the vertical middle where the
                title/subtitle/multiplier/price text sits) so small light text
                stays legible over the ~189-luminance art.
   Content is lifted above both via z-index; the art never intercepts clicks. */
.mode-card > * { position: relative; z-index: 1; }
.mode-card::before,
.mode-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
}
.mode-card::before {
  background: center / cover no-repeat;
  opacity: 0.62;
}
.mode-card::after {
  background: linear-gradient(
    180deg,
    rgba(255, 250, 244, 0.30) 0%,
    rgba(255, 250, 244, 0.52) 58%,
    rgba(255, 250, 244, 0.36) 100%
  );
}
#mode-multiplayer::before    { background-image: url("assets/panel/panel-multiplayer.webp"); }
#mode-multiplayer-4p::before { background-image: url("assets/panel/panel-multiplayer.webp"); }
#mode-practice::before       { background-image: url("assets/panel/panel-practice.webp"); }
#mode-friends::before     { background-image: url("assets/panel/panel-friends.webp"); }

/* Friends is the LOCKED/"coming soon" mode, and its art is the softest/prettiest
   of the three - a lush backdrop would fight the disabled state. When disabled,
   suppress the art hard (extra desaturation + dimming) and swap the cream veil
   for a cooler grey one, so the locked reading wins over the decoration. This is
   ON TOP of the .mode-card-disabled { opacity: 0.6 } that dims the whole panel. */
.mode-card.mode-card-disabled::before {
  opacity: 0.22;
  filter: grayscale(0.9) brightness(0.92);
}
.mode-card.mode-card-disabled::after {
  background: linear-gradient(180deg, rgba(233, 231, 240, 0.55), rgba(233, 231, 240, 0.62));
}

/* Reward multiplier control inside the Multiplayer card. */
.mp-multiplier {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  margin-top: clamp(6px, 1.6vw, 12px);
  padding-top: clamp(6px, 1.6vw, 12px);
  border-top: 2px dashed var(--clay-white-dark);
  width: 100%;
  cursor: default;
}
.mp-mult-label {
  font-size: clamp(0.55rem, 1.4vw, 0.72rem);
  font-weight: 800;
  color: var(--clay-dark);
  opacity: 0.85;
}
.mp-mult-stepper {
  display: flex;
  align-items: center;
  gap: 8px;
}
.mp-mult-btn {
  width: clamp(24px, 5vw, 30px);
  height: clamp(24px, 5vw, 30px);
  border-radius: 50%;
  border: none;
  background: var(--clay-blue);
  color: #fff;
  font-family: var(--font-main);
  font-size: clamp(0.9rem, 2.4vw, 1.2rem);
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--clay-btn-shadow);
}
.mp-mult-btn:active { transform: translateY(1px); }
.mp-mult-btn:disabled { opacity: 0.4; cursor: default; box-shadow: none; }
/* "locked" + button (multiplier capped by level): dimmed like disabled, but
   still clickable so a tap can surface the "unlocks at Lv 5" toast. */
.mp-mult-btn.locked { opacity: 0.45; box-shadow: none; cursor: not-allowed; }
.mp-mult-value {
  min-width: 34px;
  text-align: center;
  font-size: clamp(1rem, 2.6vw, 1.4rem);
  font-weight: 800;
  color: var(--clay-blue-dark);
}
.mp-mult-hint {
  font-size: clamp(0.5rem, 1.2vw, 0.64rem);
  opacity: 0.7;
  color: var(--clay-dark);
  min-height: 0.7rem;
}
/* PLAY button on the Multiplayer card: big "PLAY" + a small live price line. */
.mp-play-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  line-height: 1.05;
  margin-top: clamp(6px, 1.4vw, 10px);
  padding: clamp(6px, 1.4vw, 10px) clamp(14px, 3vw, 26px);
  width: 100%;
  max-width: 200px;
}
.mp-play-label {
  font-size: clamp(0.9rem, 2.4vw, 1.2rem);
  font-weight: 800;
  letter-spacing: 0.03em;
}
.mp-play-price {
  font-size: clamp(0.52rem, 1.3vw, 0.68rem);
  font-weight: 700;
  opacity: 0.9;
}
.mode-card.mode-card-disabled {
  opacity: 0.6;
  cursor: default;
  position: relative;
}
.mode-card.mode-card-disabled:hover {
  transform: none;
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.9),
    inset 0 -8px 14px rgba(84, 74, 133, 0.14),
    0 10px 22px rgba(84, 74, 133, 0.26);
}
.mode-coming-soon {
  display: inline-block;
  margin-top: 8px;
  padding: 3px 12px;
  border-radius: 12px;
  background: var(--clay-panel-dark);
  color: var(--clay-white);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 1px;
}

.home-bottom-nav {
  position: absolute;
  bottom: max(14px, env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 24px;
  padding: 6px;
  box-shadow: var(--clay-shadow-out);
}

.bottom-nav-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 18px;
  border-radius: 18px;
  font-size: 0.65rem;
  font-weight: 700;
  color: var(--clay-dark);
  opacity: 0.6;
  transition: background 0.15s ease, opacity 0.15s ease;
}
.bottom-nav-btn.active {
  background: var(--clay-blue-light);
  opacity: 1;
}
.bottom-nav-icon {
  font-size: 1.1rem;
}

/* Settings + notifications live inside the bottom nav bar, after the
   destinations, separated by a thin divider. Slightly smaller circular
   icon buttons so they sit neatly in the bar. */
.nav-utility-divider {
  width: 2px;
  align-self: stretch;
  margin: 4px 2px;
  border-radius: 1px;
  background: var(--clay-white-dark);
}
.home-bottom-nav .nav-utility-btn {
  width: 40px;
  height: 40px;
  min-width: 40px;
  min-height: 40px;
  font-size: 1rem;
  border-width: 2px;
}

.daily-login-card {
  text-align: center;
}

/* ------------------------------------------------------------------ */
/* Level-up celebration overlay (spec 12.3)                            */
/* ------------------------------------------------------------------ */
.level-up-card {
  position: relative;
  overflow: hidden;
  padding: 30px 40px 26px;
  min-width: 320px;
  background:
    radial-gradient(circle at 50% 34%, rgba(252, 196, 25, 0.22), transparent 60%),
    var(--clay-white);
}
.level-up-card > *:not(.level-up-rays):not(.level-up-confetti) {
  position: relative;
  z-index: 1;
}

/* Rotating sunburst behind the badge */
.level-up-rays {
  position: absolute;
  z-index: 0;
  top: 96px;
  left: 50%;
  width: 320px;
  height: 320px;
  transform: translate(-50%, -50%);
  background: repeating-conic-gradient(
    from 0deg,
    rgba(252, 196, 25, 0.20) 0deg 10deg,
    transparent 10deg 20deg
  );
  border-radius: 50%;
  animation: levelUpRaysSpin 14s linear infinite;
  pointer-events: none;
}
@keyframes levelUpRaysSpin {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* The popping level badge (gold coin/medal) */
.level-up-badge {
  width: 118px;
  height: 118px;
  margin: 6px auto 10px;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 30%, var(--clay-yellow-light), var(--clay-yellow) 55%, var(--clay-yellow-dark));
  border: 6px solid #fff;
  box-shadow: 0 8px 0 var(--clay-yellow-dark), 0 12px 22px rgba(245, 159, 0, 0.4);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
  text-shadow: 0 2px 3px rgba(146, 84, 0, 0.55);
  animation: levelUpBadgePop 0.55s cubic-bezier(0.175, 0.885, 0.32, 1.5) both;
}
.level-up-badge-label {
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 2px;
  opacity: 0.9;
  margin-bottom: -4px;
}
.level-up-badge-num {
  font-size: 2.9rem;
  font-weight: 900;
  line-height: 1;
}
@keyframes levelUpBadgePop {
  0% { transform: scale(0) rotate(-25deg); }
  100% { transform: scale(1) rotate(0deg); }
}

.level-up-title {
  font-size: 2rem;
  font-weight: 900;
  letter-spacing: 1px;
  color: var(--clay-purple-dark);
  text-shadow: 2px 2px 0 var(--clay-yellow-light);
  margin: 2px 0 4px;
  animation: levelUpTitlePop 0.5s ease 0.15s both;
}
@keyframes levelUpTitlePop {
  0% { transform: scale(0.6); opacity: 0; }
  70% { transform: scale(1.08); }
  100% { transform: scale(1); opacity: 1; }
}
.level-up-sub {
  color: var(--clay-dark);
  opacity: 0.85;
  font-size: 0.95rem;
  margin: 0 0 14px;
}
.level-up-bonus {
  display: block;
  width: fit-content;
  font-weight: 800;
  color: var(--clay-yellow-dark);
  background: var(--clay-yellow-light);
  border: 2px solid var(--clay-yellow);
  border-radius: 999px;
  padding: 7px 18px;
  margin: 0 auto 18px;
  font-size: 1rem;
}
.level-up-coin { color: #a56800; }

/* Confetti burst */
.level-up-confetti {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
}
.confetti-piece {
  position: absolute;
  top: -20px;
  width: 9px;
  height: 14px;
  opacity: 0.95;
  animation-name: confettiFall;
  animation-timing-function: ease-in;
  animation-iteration-count: 1;
  animation-fill-mode: both;
}
@keyframes confettiFall {
  0% { transform: translateY(0) rotate(0deg); opacity: 1; }
  100% { transform: translateY(560px) rotate(540deg); opacity: 0; }
}

/* ------------------------------------------------------------------ */
/* Profile / Inventory screen (spec section 11)                        */
/* ------------------------------------------------------------------ */

.profile-content {
  gap: 12px;
}




/* The panel BELOW the header: lifetime stats + Player ID, a vertical stack that
   grows into whatever height is left. (Currency moved to the top-right corner;
   the equipped-cosmetics summary and Match History button were removed - the
   cosmetics live in Inventory.)
   (It was previously glued onto .profile-header's rule below, which handed it
   `display:flex; align-items:center` and so laid the sections out in one
   squashed horizontal ROW, plus a 50px left padding meant only for clearing
   the header's back button.) */
/* Same recessed grey box the Shop / Inventory / Collection panels use
   (.shop-items-scroll-area) so Profile reads as the same surface language. */
#profile-panel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  width: 100%;
  flex: 1;
  min-height: 0; /* lets it shrink so the responsive overflow-y can bite */
  background: rgba(0, 0, 0, 0.12);
  border-radius: 24px;
  padding: 18px;
  margin-bottom: 15px;
  box-shadow: inset 3px 3px 6px rgba(0, 0, 0, 0.2);
  overflow-y: auto;
}

/* Avatar + username + level badge + XP gauge sit together in one recessed box,
   same surface as #profile-panel below it. It HUGS its content (fit-content)
   rather than spanning the row, so it doesn't run under the absolutely
   positioned currency in the top-right; the 50px margin clears the back button
   (this was padding before, which would have put 50px of empty box on the left). */
.profile-header {
  display: flex;
  align-items: center;
  align-self: flex-start;
  gap: 14px;
  width: fit-content;
  /* Hard cap so the box can never reach the corner currency: 50px back-button
     margin + ~300px for the widest currency row (3 pills, event live). Without
     this the box overlapped the pills at 740w - a common landscape size. The XP
     bar shrinks to absorb the difference (see .profile-xp-bar). */
  max-width: calc(100% - 350px);
  flex-shrink: 0;
  margin-left: 50px;
  padding: 12px 18px;
  background: rgba(0, 0, 0, 0.12);
  border-radius: 20px;
  box-shadow: inset 3px 3px 6px rgba(0, 0, 0, 0.2);
}

.profile-avatar-btn {
  width: 64px;
  height: 64px;
  cursor: pointer;
}

/* min-width:0 down the chain: flex items default to min-width:auto, which would
   refuse to shrink below content size and let the header box blow past its
   max-width. This lets the compression reach .profile-xp-bar. */
.profile-header-text {
  flex: 1;
  min-width: 0;
}
.profile-level-row,
.profile-xp-wrap,
.profile-xp-line {
  min-width: 0;
}

.profile-username {
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--clay-dark);
}

/* Shared clay-tile surface for the Profile screen's panels (warm cream, soft
   shadow, top-lip highlight) - consistent with the Missions/event tiles. */
.profile-tile {
  background: #FDF8F0;
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 12px 16px;
  box-shadow: var(--clay-shadow-out);
  position: relative;
}
.profile-tile::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 15%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.4), transparent);
  border-radius: 13px 13px 0 0;
  pointer-events: none;
}

/* Equipped-loadout row: three DISPLAY-ONLY thumbnails (front/back/board),
   each a real render of the current equip; tapping opens the Inventory at
   that category. Buttons, so they get focus/tap semantics for free. */
.profile-loadout { display: flex; gap: 12px; }
.profile-loadout-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  cursor: pointer;
  font: inherit;
  color: var(--clay-dark);
}
.profile-loadout-cell:active { transform: scale(0.96); }
.profile-loadout-preview { position: relative; width: 62px; height: 87px; }
.profile-loadout-preview .clay-card-element {
  position: relative;
  width: 100%;
  height: 100%;
  cursor: pointer;
}
.profile-loadout-preview .board-swatch-preview { width: 62px; height: 87px; border-radius: 10px; }
.profile-loadout-label {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.6;
}

/* The avatar-corner edit bubble now holds a clay gear icon (no OS emoji). */
.avatar-edit-icon { width: 14px; height: 14px; }

/* Nickname row (Profile tab): name + EDIT, cooldown hint underneath. */
.profile-nickname-row { display: flex; align-items: center; gap: 10px; }
.profile-nick-edit { padding: 4px 12px; font-size: 0.75rem; }
.profile-nick-edit:disabled { opacity: 0.45; cursor: default; }
.profile-nick-hint { font-size: 0.75rem; font-weight: 600; color: var(--clay-dark); opacity: 0.7; margin-top: 2px; }

/* Profile tab panels: identity content stacks with air between rows. */
#profile-panel-main { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; padding: 6px 4px; }
#profile-panel-main .profile-uid-row { align-self: flex-start; }
#profile-panel-stats { display: flex; flex-direction: column; gap: 16px; padding: 8px 4px; }
#profile-panel-stats.hidden { display: none; }
#profile-panel-stats .profile-stats-row { justify-content: flex-start; }

/* Nickname editor modal. */
.nickname-edit-card { max-width: 340px; text-align: center; }
.nickname-edit-card h3 { margin: 0 0 12px; color: var(--clay-dark); }
.nickname-edit-card .clay-input { width: 100%; text-align: center; }
.nickname-edit-hint { font-size: 0.75rem; opacity: 0.7; color: var(--clay-dark); margin: 8px 0 0; }
.nickname-edit-error { font-size: 0.8rem; font-weight: 700; color: #d9480f; margin: 8px 0 0; }
.nickname-edit-actions { display: flex; gap: 12px; justify-content: center; margin-top: 14px; }

/* Daily login: CLAIM next to the ad-doubled claim. */
.daily-login-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.daily-login-actions .clay-btn { flex: 0 1 auto; }

/* Event Offers (shop Currency tab, live-event only). */
#event-offers-section { margin-bottom: 14px; }
.event-offer-tile { position: relative; }
.event-offer-icon { width: 44px; height: 44px; }
.event-offer-contents { font-size: 0.72rem; font-weight: 700; color: var(--clay-dark); opacity: 0.75; text-align: center; line-height: 1.25; }
.event-offer-limit {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--clay-dark);
  opacity: 0.55;
}

/* Stake-room select (public matchmaking): the 4-tile room ladder. */
.stake-room-modal { max-width: 460px; text-align: center; }
.stake-room-modal h3 { margin: 0 0 8px; color: var(--clay-dark); }
.stake-room-sub { font-size: 0.78rem; color: var(--clay-dark); opacity: 0.75; margin: 0 0 12px; line-height: 1.35; }
/* Reflects the match size chosen by the play-mode panel that opened this. */
.stake-size-note {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--clay-dark);
  background: #FDF8F0;
  border: 3px solid var(--clay-white-dark);
  border-radius: 12px;
  padding: 4px 14px;
  margin-bottom: 12px;
  box-shadow: var(--clay-shadow-out);
}
.stake-room-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 14px; }
.stake-room-tile {
  background: #FDF8F0;
  border: 3px solid var(--clay-white-dark);
  border-radius: 14px;
  padding: 10px 6px;
  box-shadow: var(--clay-shadow-out);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  font: inherit;
  color: var(--clay-dark);
}
.stake-room-tile:not(.locked):active { transform: scale(0.95); }
.stake-room-tile.locked { opacity: 0.45; filter: grayscale(0.6); cursor: default; }
/* Selected room - PLAY commits this one. */
.stake-room-tile.selected {
  border-color: var(--clay-blue);
  box-shadow: 0 0 0 3px var(--clay-blue), var(--clay-shadow-out);
}
.stake-room-actions { display: flex; gap: 12px; justify-content: center; }
.stake-room-mult { font-size: 1.4rem; font-weight: 900; }
.stake-room-fee { font-size: 0.68rem; font-weight: 800; }
.stake-room-min { font-size: 0.6rem; font-weight: 700; opacity: 0.65; }

/* Game-over stake settlement (server numbers only). */
.stake-chip.stake-win { color: #2b8a3e; }
.stake-chip.stake-loss { color: #c92a2a; }
.stake-math { font-size: 0.6rem; font-weight: 700; color: var(--clay-dark); opacity: 0.65; white-space: nowrap; }

/* Randomized-reward mechanic disclosure (pre-purchase, Google Play policy). */
.ecp-disclosure-card { max-width: 360px; text-align: center; }
.ecp-disclosure-card h3 { margin: 0 0 10px; color: var(--clay-dark); }
.ecp-disclosure-item { font-weight: 800; color: var(--clay-dark); margin: 0 0 8px; }
.ecp-disclosure-text { font-size: 0.85rem; color: var(--clay-dark); opacity: 0.85; margin: 0 0 14px; line-height: 1.4; }
.ecp-disclosure-actions { display: flex; gap: 12px; justify-content: center; }

.profile-level-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 5px;
}

/* Level widget: badge on the left, a small progress bar + exact XP numbers, and
   a milestone hint beneath (what leveling unlocks). Modest footprint - it sits
   inside the info card, not as a full-width hero banner. */
.profile-xp-wrap {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.profile-xp-line {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* 150px preferred, but allowed to shrink so the header box can honour its
   max-width on narrow screens instead of overflowing into the currency. */
.profile-xp-bar {
  width: 150px;
  flex: 0 1 150px;
  min-width: 64px;
  height: 12px;
  background: rgba(74, 68, 99, 0.22);
  border-radius: 7px;
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.18);
}
.profile-xp-bar-fill {
  height: 100%;
  background: linear-gradient(180deg, #8ce99a, #37b24d);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45);
  width: 0%;
  transition: width 0.3s ease;
}
.profile-xp-text {
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--clay-dark);
  opacity: 0.85;
  white-space: nowrap;
}
.profile-xp-hint {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--clay-dark);
  opacity: 0.7;
}
/* Below Lv 5 the hint renders empty (see renderProfileScreen). Drop it from the
   flex flow entirely so it doesn't leave the wrap's 3px gap hanging under the bar. */
.profile-xp-hint:empty {
  display: none;
}
.profile-xp-hint-icon {
  width: 13px;
  height: 13px;
  object-fit: contain;
}

.avatar-picker {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
  padding: 10px;
  background: rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  width: 100%;
}

.avatar-preset-btn {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  border: 3px solid var(--clay-white);
  overflow: hidden;
  cursor: pointer;
  padding: 0;
  box-shadow: var(--clay-shadow-out);
}
.avatar-preset-btn svg {
  width: 100%;
  height: 100%;
}

.avatar-preset-btn.avatar-selected {
  border-color: var(--clay-yellow);
  box-shadow: 0 0 10px var(--clay-yellow), var(--clay-shadow-out);
}

/* Level-locked avatar teaser: dimmed portrait with an "Lv X" badge. */
.avatar-preset-btn {
  position: relative;
}
.avatar-preset-btn.avatar-locked {
  cursor: default;
}
.avatar-preset-btn.avatar-locked .avatar-img {
  filter: grayscale(0.85) brightness(0.75);
}
.avatar-lock-badge {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.72rem;
  font-weight: 800;
  color: #fff;
  background: rgba(20, 22, 34, 0.42);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

/* Pencil "edit" badge on the profile avatar (tap the avatar to change it). */
.profile-avatar-btn { position: relative; overflow: visible; }
.profile-avatar-btn .avatar-img { border-radius: 10px; }
.avatar-edit-pencil {
  position: absolute;
  bottom: -4px;
  right: -4px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--clay-yellow);
  border: 2px solid #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.68rem;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.28);
  pointer-events: none;
}

/* Avatar picker MODAL (popup, no longer inline). */
.avatar-picker-modal { max-width: 340px; text-align: center; }
.avatar-picker-modal h3 { margin: 0 0 12px; color: var(--clay-dark); }
.avatar-picker-modal .avatar-picker {
  background: transparent;
  padding: 4px;
  margin-bottom: 16px;
  max-height: 260px;
  overflow-y: auto;
}

/* PNG portrait avatars (assets/avatars/<key>.webp) - fill whatever circular
   holder they're mounted in (top bar, profile header, picker, match badge). */
.avatar-img {
  width: 100%;
  height: 100%;
  border-radius: 13px;
  object-fit: cover;
  display: block;
}

/* Round the avatar image to the holder's INNER corner radius (holder radius
   13px minus the 3px frame = 10px). Matching it exactly means:
   - no corner gap (image radius isn't larger than the inner corner), and
   - no square poke on holders that don't clip (the profile button is
     overflow:visible so its pencil badge can stick out - the image has to
     round itself there since the button won't clip it). */
.topbar-avatar-holder .avatar-img,
.avatar-holder .avatar-img,
.lobby-seat-avatar .avatar-img {
  border-radius: 10px;
}

.avatar-img.eliminated {
  filter: grayscale(1) brightness(0.8);
}

/* Screen back button - a round arrow pinned to the top-left corner of the
   screen's container (was a "BACK"/"CLOSE" pill at the bottom). One shared
   class across every full-screen back button. */
.screen-back-btn {
  position: absolute;
  /* Geometry adopted from the Missions window's back chip (2026-07 device
     pass - the compact corner chip reads better than the old 46px one that
     crowded screen titles). Kept safe-area-aware, unlike the in-modal
     version: at screen level this sits against the real device edge, and in
     LANDSCAPE the camera cutout is on the left, so a fixed offset would slide
     the button under it. */
  top: max(8px, env(safe-area-inset-top));
  left: max(10px, env(safe-area-inset-left));
  z-index: 30;
  width: 36px;
  height: 36px;
  min-width: 36px;
  padding: 0 !important;
  /* A round cream chip, matching the util icon discs (bell/gear) from the
     design-refresh block - was a bare glyph, which floated oddly over the
     painted screen backgrounds. The arrow art sizes in `em` off font-size
     (see .back-arrow-img). */
  background: var(--clay-white) !important;
  border: none !important;
  border-radius: 50% !important; /* !: the design-refresh .clay-btn 22px radius is declared later */
  /* Extra hairline ring so the cream disc still reads as a BUTTON on light
     backgrounds (e.g. the profile art's pale top-left) rather than looking like
     a bare floating arrow. */
  box-shadow: 0 0 0 1.5px rgba(84, 74, 133, 0.12), 0 5px 0 #ddd8ee, 0 12px 18px rgba(74, 68, 99, 0.12), inset 0 3px 0 #fff !important;
  color: var(--clay-dark);
  /* Drives the arrow art's size (.back-arrow-img is height: 1em) - matched
     to the 36px chip. */
  font-size: 1.15rem;
  font-weight: 900;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.screen-back-btn:active {
  transform: translateY(3px);
  box-shadow: 0 2px 0 #ddd8ee, inset 0 3px 0 #fff !important;
}
.back-arrow-img {
  height: 1em;
  width: auto;
  object-fit: contain;
  display: block;
}
.screen-back-btn:hover { transform: translateX(-2px); }
@media (max-height: 520px) {
  /* font-size still drives the icon's `em` sizing (see .back-arrow-img).
     Safe-area floors kept - a landscape notch sits on the left edge. */
  .screen-back-btn {
    top: max(5px, env(safe-area-inset-top));
    left: max(6px, env(safe-area-inset-left));
    width: 32px; height: 32px; min-width: 32px; font-size: 1rem;
  }
  /* Match the top tab to the first card (grid box padding is 10px at this height). */
  .shop-body .shop-tabs-vertical { margin-top: 10px; }
}

/* Starter default avatar (inline SVG span instead of a PNG img). */
.avatar-img.starter-avatar { overflow: hidden; }
.starter-avatar-svg { display: block; width: 100%; height: 100%; }
.avatar-preset-btn .starter-avatar-svg { width: 100%; height: 100%; }

/* Shop tile preview for an avatar - centered circle in the same 100x140
   holder card/board previews use. */
.avatar-shop-preview {
  width: 100px;
  height: 100px;
  margin-top: 20px;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
  border: 4px solid var(--clay-white);
}

/* Top-right corner, matching the badge placement on the other screens. Absolute
   so it sits beside the header rather than pushing the panel down. */
.profile-currency-row {
  position: absolute;
  top: max(16px, env(safe-area-inset-top));
  right: max(20px, calc(env(safe-area-inset-right) + 10px));
  z-index: 5;
  display: flex;
  gap: 10px;
  align-items: center;
  color: var(--clay-dark);
}

.profile-stats-row {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}
.profile-stats-row.hidden { display: none; }

/* New-player empty state (Played == 0) - one friendly pill instead of 0/0/0%. */
.profile-stats-empty {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  background: linear-gradient(180deg, #ffffff, #e7e2f4);
  border-radius: 18px;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -4px 8px rgba(84, 74, 133, 0.12),
    0 6px 14px rgba(84, 74, 133, 0.2);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--clay-dark);
}
.profile-stats-empty.hidden { display: none; }

/* Player ID (Firebase uid / users/{uid} doc id). Deliberately quiet - it's a
   support identifier, not a stat. A uid is ~28 chars, so the value gets
   min-width:0 + ellipsis: without that it forces the row wider than the panel
   and drags the whole profile layout with it. user-select:all so a long-press
   selects the WHOLE id when the copy button can't run. */
.profile-uid-row {
  display: flex;
  align-items: center;
  gap: 8px;
  align-self: center;
  max-width: 100%;
  margin: 0;
  padding: 6px 12px;
  background: rgba(255, 255, 255, 0.45);
  border: 2px solid var(--clay-white-dark);
  border-radius: 12px;
  box-shadow: none;
  cursor: pointer;
  font-family: inherit;
  text-shadow: none;
  transition: background 0.15s ease;
}
.profile-uid-row:hover { background: rgba(255, 255, 255, 0.7); }
.profile-uid-row:active { transform: translateY(1px); }
.profile-uid-label {
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--clay-dark);
  opacity: 0.6;
  flex-shrink: 0;
}
.profile-uid-value {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--clay-dark);
  opacity: 0.85;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  user-select: all;
}
.profile-uid-copy {
  /* Text chip (was an OS glyph): reads as the action it performs. */
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  padding: 2px 8px;
  border: 2px solid var(--clay-white-dark);
  border-radius: 8px;
  color: var(--clay-dark);
  opacity: 0.7;
  flex-shrink: 0;
}
.profile-stats-empty .profile-stat-icon { width: 26px; height: 26px; }

.profile-inventory-section {
  grid-column: 1 / -1; /* a section is a full-width band, not one grid cell */
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: rgba(255, 255, 255, 0.55);
  border: 3px solid var(--clay-white-dark);
  border-radius: 18px;
  padding: 12px;
  box-shadow: var(--clay-shadow-out);
}

.profile-inventory-section-title {
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--clay-dark);
}

.profile-inventory-section-subtitle {
  font-size: 0.72rem;
  opacity: 0.7;
  color: var(--clay-dark);
}

.profile-inventory-section-items {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
}

.profile-inventory-section-items .shop-item-card {
  margin: 0;
}

/* Inventory hover/tap preview panel - shows the focused skin at card size
   next to its name/source/tier before the player commits to equipping. */
.profile-inventory-preview {
  width: 100%;
  background: rgba(255, 255, 255, 0.55);
  border: 3px solid var(--clay-white-dark);
  border-radius: 18px;
  padding: 10px 14px;
  box-shadow: var(--clay-shadow-out);
}

.profile-inventory-preview-body {
  display: flex;
  align-items: center;
  gap: 14px;
}

.profile-inventory-preview-swatch {
  position: relative;
  width: 74px;
  height: 104px;
  flex-shrink: 0;
}

/* The preview swatch reuses the real card/board elements (so skin CSS
   treatments render exactly as in-game) but scaled into the panel. */
.profile-inventory-preview-swatch .clay-card-element.large {
  position: absolute;
  left: 0;
  top: 0;
  transform: scale(0.74);
  transform-origin: top left;
  cursor: default;
}

.profile-inventory-preview-swatch .board-swatch-preview.large {
  width: 74px;
  height: 104px;
}

.profile-inventory-preview-title {
  font-weight: 800;
  font-size: 1rem;
  color: var(--clay-dark);
}

.profile-inventory-preview-meta {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--clay-dark);
  opacity: 0.65;
  margin-top: 2px;
}

/* All / Equipped / Available quick filters above the inventory grid. */
.profile-inventory-filters {
  display: flex;
  gap: 8px;
  width: 100%;
  justify-content: center;
}

.profile-filter-btn {
  min-height: 32px;
  border: 3px solid var(--clay-white-dark);
  border-radius: 999px;
  background: var(--clay-white-light);
  color: var(--clay-dark);
  font-weight: 800;
  font-size: 0.75rem;
  padding: 4px 14px;
  box-shadow: var(--clay-shadow-out);
  cursor: pointer;
}

.profile-filter-btn.active {
  background: var(--clay-yellow-light);
  border-color: var(--clay-yellow);
}

/* Source/rarity badge on each inventory tile (same visual family as the
   shop's .shop-tier-badge). */
.inventory-badge {
  font-size: 0.58rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 2px 8px;
  border-radius: 10px;
  flex-shrink: 0;
}
.inventory-badge.badge-event {
  background: linear-gradient(135deg, #60a5fa, #34d399);
  color: white;
  text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.2);
}
.inventory-badge.badge-epic {
  background: linear-gradient(135deg, #a78bfa, #f472b6);
  color: white;
  text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.2);
}
.inventory-badge.badge-rare {
  background: var(--clay-blue-light);
  color: var(--clay-dark);
}
.inventory-badge.badge-common {
  background: var(--clay-white-dark);
  color: var(--clay-dark);
}

/* Each real stat (spec 11.2) as an icon + value + label in a clay pill. */
/* Stat cells wear the same warm-cream clay-tile treatment as the Missions/
   event surfaces (see .profile-tile) - not flat white. */
.profile-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 92px;
  padding: 10px 16px 8px;
  background: #FDF8F0;
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  box-shadow: var(--clay-shadow-out);
  position: relative;
}
.profile-stat::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 15%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.4), transparent);
  border-radius: 13px 13px 0 0;
  pointer-events: none;
}
.profile-stat-icon {
  width: 30px;
  height: 30px;
  object-fit: contain;
  margin-bottom: 2px;
  filter: drop-shadow(0 2px 2px rgba(84, 74, 133, 0.25));
}
.profile-stat-value {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--clay-dark);
  line-height: 1.1;
}
.profile-stat-label {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.6;
}

/* ------------------------------------------------------------------ */
/* Settings screen (spec section 15)                                   */
/* ------------------------------------------------------------------ */

.settings-content {
  gap: 14px;
}

.settings-list {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
}

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 10px 16px;
}

.settings-row-title {
  font-weight: 700;
  color: var(--clay-dark);
}
.settings-row-desc {
  font-size: 0.75rem;
  opacity: 0.75;
  color: var(--clay-dark);
}

.settings-version {
  font-size: 0.7rem;
  opacity: 0.6;
  color: var(--clay-dark);
}

/* ------------------------------------------------------------------ */
/* Shop Currency tab (spec section 10.2 tab 5)                         */
/* ------------------------------------------------------------------ */

.currency-tab-content {
  width: 100%;
  padding-top: 20px;
}

.currency-section-title {
  color: var(--clay-dark);
  font-size: 1rem;
  margin: 0 0 10px;
}

.currency-dev-note {
  font-size: 0.75rem;
  background: rgba(255, 200, 0, 0.2);
  border: 2px dashed #f59f00;
  border-radius: 10px;
  padding: 6px 12px;
  color: var(--clay-dark);
  margin-bottom: 12px;
}

.currency-convert-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 12px 16px;
  margin-top: 8px;
}
.currency-convert-row .clay-input {
  max-width: 140px;
}
.currency-convert-preview {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--clay-dark);
  flex: 1;
}

/* ------------------------------------------------------------------ */
/* Compact density for short viewports (phones held landscape - the   */
/* game's primary target). Without this, screen chrome (title + tabs  */
/* + BACK) consumed nearly the whole 390px-tall viewport and content  */
/* rendered as a clipped sliver; Home overflowed outright.            */
/* ------------------------------------------------------------------ */
@media (max-height: 520px) {
  .clay-container {
    height: 94%;
    padding: 12px 18px;
    border-width: 6px;
    border-radius: 24px;
  }
  .shop-content {
    height: 94% !important;
  }

  /* --- Home: clear the absolute topbar above and bottom nav below --- */
  .home-content {
    justify-content: flex-start;
    gap: 7px;
    padding-top: 8px;
    padding-bottom: 64px; /* the absolute .home-bottom-nav floats here */
  }
  /* (home-topbar stays absolute/pinned to the corners even on short screens -
     the old static-flow override was for a home logo that no longer exists.) */
  .clay-logo {
    font-size: 1.9rem;
    line-height: 1.05;
    text-shadow: 2px 2px 0px var(--clay-purple-dark), 4px 4px 0px var(--clay-pink-dark);
  }
  .logo-subtitle {
    font-size: 0.75rem;
    line-height: 1;
  }
  .home-event-banner {
    padding: 5px 14px;
  }
  .home-event-banner-name {
    font-size: 0.8rem;
  }
  .home-event-banner-progress {
    font-size: 0.7rem;
  }
  .home-event-banner-countdown {
    font-size: 0.75rem;
  }
  .btn-huge {
    font-size: 1.1rem !important;
    padding: 12px 48px !important;
    border-radius: 22px !important;
  }
  .home-bottom-nav {
    bottom: 10px;
  }
  .topbar-avatar-holder {
    width: 38px;
    height: 38px;
  }
  .topbar-icon-btn {
    width: 34px;
    height: 34px;
    font-size: 0.9rem;
  }

  /* --- All content screens: shrink chrome so the scroll area wins --- */
  .section-title {
    font-size: 1.05rem;
    margin-bottom: 4px;
  }
  .clay-btn {
    font-size: 0.85rem;
    padding: 7px 16px;
    border-width: 3px;
    border-radius: 14px;
  }
  .btn-large {
    font-size: 0.95rem;
    padding: 9px 22px;
    border-radius: 16px;
  }
  .shop-header {
    margin-bottom: 4px;
  }
  .shop-coin-badge {
    padding: 4px 10px;
    font-size: 0.8rem;
    border-width: 2px;
  }
  .shop-tabs {
    gap: 6px;
    margin-bottom: 6px;
  }
  .shop-tab-btn {
    padding: 4px 12px;
    font-size: 0.75rem;
    border-width: 2px;
  }
  .shop-items-scroll-area {
    padding: 10px;
    margin-bottom: 6px;
    border-radius: 16px;
  }
  .shop-items-grid {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
  }

  /* --- Profile: everything above the fold, panel scrolls if not --- */
  .profile-content {
    gap: 6px;
  }
  /* #profile-panel was glued onto this rule and got sized to 44x44 - the whole
     panel collapsed to an avatar-sized box on exactly this (short landscape)
     viewport. It gets the scroll behaviour the section comment promises. */
  #profile-panel {
    gap: 8px;
    overflow-y: auto;
    min-height: 0;
    padding: 12px;      /* tighter grey box - 18px eats too much of a short screen */
    margin-bottom: 8px;
  }
  /* Compact pills too - at the narrowest landscape (568w) a 3-pill row with an
     event live still reached the header box even after it shrank. */
  .profile-currency-row { gap: 7px; top: max(10px, env(safe-area-inset-top)); }
  .profile-currency-row .currency-pill { padding: 6px 9px; gap: 4px; }
  .profile-currency-row .pill-icon { width: 14px; height: 14px; }
  .profile-currency-row .pill-value { font-size: 0.78rem; }
  /* Tighter box on a short screen. (No right-clearance rule needed: the header
     box is fit-content, so it never reaches the corner currency.) */
  .profile-header { margin-left: 46px; padding: 8px 14px; border-radius: 16px; }
  .profile-avatar-btn {
    width: 44px;
    height: 44px;
  }
  .profile-username {
    font-size: 0.95rem;
  }
  .profile-stat-value {
    font-size: 1rem;
  }
  .profile-stats-row {
    gap: 16px;
  }

  /* --- Lobby --- */
  .lobby-form {
    padding: 12px;
    gap: 6px;
  }

  /* --- Inventory: slim the preview panel so the item grid stays above
     the fold; the panel itself scrolls for anything below --- */
  .profile-inventory-preview {
    padding: 6px 12px;
  }
  .profile-inventory-preview-swatch {
    width: 48px;
    height: 68px;
  }
  .profile-inventory-preview-swatch .clay-card-element.large {
    transform: scale(0.48);
  }
  .profile-inventory-preview-swatch .board-swatch-preview.large {
    width: 48px;
    height: 68px;
  }
  .profile-inventory-preview-title {
    font-size: 0.85rem;
  }
  .profile-inventory-preview-meta {
    font-size: 0.65rem;
  }
  .profile-filter-btn {
    min-height: 26px;
    font-size: 0.65rem;
    padding: 3px 10px;
  }

  /* --- Settings: the list scrolls instead of clipping --- */
  .settings-list {
    overflow-y: auto;
    min-height: 0;
    flex: 1;
  }

  /* --- Game board: scale the whole card system down together (hand, deck,
     discard, resting top card) so the size-consistency rule holds; the fly
     animation measures live element sizes, so it follows along.
     84x118 keeps the 5:7 of the card art - see .clay-card-element. Only the
     card BOX is set here: the frame/centre/corner layers are all sized in %
     of it, so they scale on their own. (This block used to also re-declare
     border/padding/radius and a fixed 46x64 .card-center - leftovers from the
     pre-art card model, which drew its own face; they're gone with it.) --- */
  .clay-card-element {
    width: 84px;
    height: 118px;
  }
  .player-hand-scroll .clay-card-element {
    width: 84px;
    height: 118px;
    margin-left: -38px;
  }
  /* Deck matches the hand/discard card exactly - it was 68x99 here, the same
     mismatch the desktop rule had. */
  .clay-deck-stack {
    width: 84px;
    height: 118px;
  }
  .discard-container,
  .discard-pile .clay-card-element {
    width: 84px;
    height: 118px;
  }
  .direction-ring {
    width: 260px;
    height: 155px;
    /* rim of the small 260x155 dish */
    --orbit-rx: 130px;
    --orbit-ry: 77px;
  }
  .play-area::before {
    width: 260px;
    height: 155px;
  }
  .deck-count-badge {
    font-size: 0.7rem;
    margin-top: 4px;
  }
  .play-area {
    gap: 24px;
  }
  .turn-indicator {
    font-size: 0.8rem;
    padding: 6px 12px;
  }
  .direction-indicator {
    font-size: 0.7rem;
    padding: 3px 10px;
  }
  .opponent-badge .avatar-holder,
  .player-info-badge .avatar-holder {
    width: 34px;
    height: 34px;
  }
  .game-layout {
    grid-template-rows: 62px 1fr 132px;
    padding: 6px;
    gap: 6px;
  }
  .opponent-badge {
    padding: 4px 10px;
  }
  .opponent-name {
    font-size: 0.75rem;
  }
  .opponent-card-count {
    font-size: 0.65rem;
  }
  .player-info-badge {
    padding: 6px 12px;
  }
  .player-name {
    font-size: 0.8rem;
  }
  .player-card-count {
    font-size: 0.65rem;
  }
}

/* ------------------------------------------------------------------ */
/* Toasts - replaces every blocking browser alert() with stacked clay  */
/* pills that slide in top-center and dismiss themselves.              */
/* ------------------------------------------------------------------ */
#toast-container {
  position: fixed;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  width: min(480px, 92vw);
}

.clay-toast {
  background: var(--clay-white-light);
  color: var(--clay-dark);
  border: 3px solid var(--clay-white-dark);
  border-radius: 999px;
  padding: 10px 22px;
  font-weight: 700;
  font-size: 0.9rem;
  box-shadow: var(--clay-shadow-out);
  max-width: 100%;
  text-align: center;
  animation: toastIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.clay-toast.toast-success {
  background: var(--clay-green-light, #b2f2bb);
  border-color: var(--clay-green);
}

.clay-toast.toast-error {
  background: var(--clay-red-light, #ffc9c9);
  border-color: var(--clay-red);
}

.clay-toast.toast-leaving {
  transition: opacity 0.3s ease, transform 0.3s ease;
  opacity: 0;
  transform: translateY(-10px);
}

@keyframes toastIn {
  from { opacity: 0; transform: translateY(-14px) scale(0.9); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* ------------------------------------------------------------------ */
/* Opening deal (spec 3.1's 5-card deal, visualized): while a screen   */
/* carries .dealing, the already-dealt hand and starting discard stay  */
/* hidden; card backs fly from the deck to each seat, then the hand    */
/* pops in with a per-card stagger (.just-dealt).                      */
/* ------------------------------------------------------------------ */
.dealing .player-hand-scroll .clay-card-element,
.dealing .discard-pile .clay-card-element,
.dealing .deck-draw-arrow {
  visibility: hidden;
}

.player-hand-scroll.just-dealt .clay-card-element {
  animation: dealPopIn 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) backwards;
  animation-delay: calc(var(--deal-i, 0) * 70ms);
}

@keyframes dealPopIn {
  from { opacity: 0; transform: translateY(34px) scale(0.6); }
}

/* ------------------------------------------------------------------ */
/* Phone safety net: any menu whose content outgrows its container     */
/* scrolls instead of spilling out of the box (found live: the lobby's */
/* expanded friends form reached 945px on a 390px viewport).           */
/* ------------------------------------------------------------------ */
@media (max-height: 520px) {
  .clay-container {
    overflow-y: auto;
  }
}

/* Premium thin scrollbars everywhere (WebKit + Firefox) */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(84, 74, 133, 0.28) transparent;
}
*::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
*::-webkit-scrollbar-thumb {
  background: rgba(84, 74, 133, 0.28);
  border-radius: 999px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}

/* ------------------------------------------------------------------ */
/* Drawn SVG chrome icons (replace the emoji buttons)                  */
/* ------------------------------------------------------------------ */
/* ===== Drawn icon ART (assets/icons/*.webp - see iconHtml() in ui.js) =====
   These replaced the emoji that were still literally rendering. Each emoji was
   sized by its parent's font-size, so these size in `em` too and drop into the
   same slots without retuning anything.

   Distinct from .icon-svg below: that's CHROME_ICONS' inline SVG for the nav /
   util chrome, which stays because stroke="currentColor" makes it follow
   hover / active / disabled colour. Raster art can't do that - hence the two
   systems coexisting rather than one replacing the other. */
.ui-icon,
.inline-icon {
  height: 1em;
  width: auto;
  object-fit: contain;
  display: inline-block;
  vertical-align: -0.15em; /* sit on the text baseline, as the emoji did */
}
/* Icons that stood alone in their own box rather than inline with a label. */
.mode-icon-img,
.celebrate-icon-img,
.dust-pull-icon-img,
.pack-icon-img,
.deck-draw-arrow-img {
  height: 1em;
  width: auto;
  object-fit: contain;
  display: block;
  margin: 0 auto;
}
/* Orbit chevrons: .direction-arrow-fx is already a 1em box, so fill it. */
.chevron-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.icon-svg {
  width: 1em;
  height: 1em;
  display: block;
  margin: auto;
}
.topbar-icon-btn .icon-svg,
.log-toggle-btn .icon-svg {
  width: 19px;
  height: 19px;
}
.bottom-nav-icon .icon-svg {
  width: 18px;
  height: 18px;
}
.scroll-hand-btn .icon-svg {
  width: 16px;
  height: 16px;
}
/* Inventory controls: Owned/Not-Owned subtabs and the state filters share
   one row (was two stacked rows eating vertical space on phones). */
.profile-inventory-controls {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  width: 100%;
}
.profile-inventory-controls .shop-tabs,
.profile-inventory-controls .profile-inventory-filters {
  width: auto;
  margin-bottom: 0;
}

/* ------------------------------------------------------------------ */
/* Ergonomics + polish pass (thumb-reach design direction)             */
/* ------------------------------------------------------------------ */

/* Elevation scale: every clay element reads at one of three heights.
   rest = sitting on the table, raised = hover/lifted, pressed = pushed in. */
:root {
  --elev-rest: 0 6px 14px rgba(84, 74, 133, 0.14), inset 2px 2px 5px rgba(255, 255, 255, 0.8), inset -3px -3px 7px rgba(84, 74, 133, 0.1);
  --elev-raised: 0 10px 22px rgba(84, 74, 133, 0.2), inset 2px 2px 5px rgba(255, 255, 255, 0.8), inset -3px -3px 7px rgba(84, 74, 133, 0.1);
  --elev-pressed: 0 2px 5px rgba(84, 74, 133, 0.16), inset 3px 3px 7px rgba(84, 74, 133, 0.16), inset -2px -2px 4px rgba(255, 255, 255, 0.5);
  --tap-min: 44px; /* minimum reliable touch target */
}

/* Touch targets: everything interactive >= 44px (scroll chevrons were 32,
   log/home 42, topbar 42 - all under spec, worse under a turn timer). */
.scroll-hand-btn,
.log-toggle-btn,
.topbar-icon-btn {
  width: var(--tap-min);
  height: var(--tap-min);
  min-width: var(--tap-min);
  min-height: var(--tap-min);
}
.bottom-nav-btn {
  min-height: var(--tap-min);
  justify-content: center;
}
@media (max-height: 520px) {
  /* the compact layer must never undercut the tap minimum */
  .topbar-icon-btn,
  .scroll-hand-btn,
  .log-toggle-btn {
    width: var(--tap-min);
    height: var(--tap-min);
  }
}

/* Bottom nav: unmistakable active state - filled + pressed-in (was a subtle
   tint swap). */
.bottom-nav-btn.active {
  background: var(--clay-blue);
  color: white;
  opacity: 1;
  box-shadow: inset 2px 2px 6px rgba(0, 0, 0, 0.22);
}

/* Color picker: re-anchored from a center modal to a compact cluster rising
   from the bottom-right thumb zone (choice happens mid-turn, under time
   pressure). The dimmed backdrop stays, lighter, so the table remains
   readable while choosing. */
#color-picker-overlay,
#online-color-picker-overlay {
  justify-content: center; /* centered in the board (was bottom-right hug) */
  align-items: center;
  background: rgba(0, 0, 0, 0.32);
}
#color-picker-overlay .color-selector,
#online-color-picker-overlay .color-selector {
  width: auto;
  margin: 0; /* centered in the board (was offset up-right to clear the hand) */
  padding: 14px 18px;
}
#color-picker-overlay .color-selector h3,
#online-color-picker-overlay .color-selector h3 {
  font-size: 0.95rem;
  margin-bottom: 10px;
}
/* Colour buttons in a single row (1x4: Red, Blue, Green, Yellow). */
#color-picker-overlay .color-options-grid,
#online-color-picker-overlay .color-options-grid {
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
#color-picker-overlay .color-select-btn,
#online-color-picker-overlay .color-select-btn {
  padding: 0;
  width: 76px;
  height: 50px;
  font-size: 0.95rem;
}

/* ---- Colour palette (4 circles) + the color-change sweep animation ---- */
.color-palette {
  display: flex;
  justify-content: center;
  gap: 12px;
}
.color-picker-palette {
  margin-bottom: 14px;
}
.palette-circle {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--clay-white-dark);
  border: 3px solid rgba(0, 0, 0, 0.18);
  box-shadow: var(--clay-shadow-out), inset 0 2px 4px rgba(255, 255, 255, 0.4);
  /* the sweep recolours each circle; 0.35s ease keeps the change smooth */
  transition: background-color 0.35s ease;
}
.palette-circle.pc-red { background: var(--clay-red); }
.palette-circle.pc-blue { background: var(--clay-blue); }
.palette-circle.pc-green { background: var(--clay-green); }
.palette-circle.pc-yellow { background: var(--clay-yellow); }

/* Lighter dim for the watch/animation overlay ("dim the screen a little"). */
.overlay.overlay-light {
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(2px);
  pointer-events: none; /* purely a visual flourish - never blocks input */
}
.color-change-anim-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 22px 30px;
  background: var(--clay-white-light);
  border-radius: 22px;
  border: 3px solid var(--clay-white-dark);
  box-shadow: var(--clay-shadow-out), var(--clay-shadow-in);
}
#color-change-palette .palette-circle {
  width: 44px;
  height: 44px;
}
/* A little pop as each circle recolours during the sweep. */
.palette-circle.pc-pop {
  animation: palettePop 0.35s ease;
}
@keyframes palettePop {
  0% { transform: scale(1); }
  45% { transform: scale(1.28); }
  100% { transform: scale(1); }
}

/* ------------------------------------------------------------------ */
/* Colorblind / high-contrast mode (Settings toggle, body.colorblind):  */
/* red-green players (~8% of men) can't rely on suit color alone, and   */
/* the whole game is color matching. Every color surface gains a shape  */
/* mark - Red ▲  Blue ●  Green ■  Yellow ◆ - and green deepens for      */
/* luminance separation from red.                                       */
/* ------------------------------------------------------------------ */
body.colorblind {
  --clay-green: #2f9e44;
  --clay-green-dark: #237032;
}

body.colorblind .clay-card-element .card-center::before {
  position: absolute;
  top: 3px;
  left: 5px;
  font-size: 0.85rem;
  line-height: 1;
  color: rgba(255, 255, 255, 0.95);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  z-index: 2;
}
body.colorblind .clay-card-element.red .card-center::before { content: "▲"; }
body.colorblind .clay-card-element.blue .card-center::before { content: "●"; }
body.colorblind .clay-card-element.green .card-center::before { content: "■"; }
body.colorblind .clay-card-element.yellow .card-center::before { content: "◆"; }

body.colorblind .clay-color-wheel::after {
  font-size: 14px;
  color: white;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
body.colorblind .clay-color-wheel.red::after { content: "▲"; }
body.colorblind .clay-color-wheel.blue::after { content: "●"; }
body.colorblind .clay-color-wheel.green::after { content: "■"; }
body.colorblind .clay-color-wheel.yellow::after { content: "◆"; }

body.colorblind .color-select-btn.btn-red::after { content: " ▲"; }
body.colorblind .color-select-btn.btn-blue::after { content: " ●"; }
body.colorblind .color-select-btn.btn-green::after { content: " ■"; }
body.colorblind .color-select-btn.btn-yellow::after { content: " ◆"; }

/* Off-turn state for the thumb-zone DRAW buttons */
.clay-btn.btn-dimmed {
  opacity: 0.45;
}

/* (The picker is centered in the board now - no bottom-right offset.) */

/* ==========================================================================
   DESIGN REFRESH — ported from the Claude Design "One Card UI Kit" (2026-07).
   Chunky "pressable candy-block" 3D buttons + matching icon buttons, color
   picks, bottom-nav active state, and badge depth. Appended LAST so these
   override the base component rules above via source order.
   NOT touched: .clay-card-element (skin-driven frame — the design's flat cards
   would break the skin economy) and the colorblind shape marks (they stay
   behind body.colorblind, per choice — no always-on glyphs here).
   ========================================================================== */

/* Clay-pill buttons (2026-07): match the home currency wrappers' surface -
   a top-to-bottom gradient fill (light lip up top, darker toward the base) with
   a lip highlight, a soft inner shadow underneath, and a soft contact shadow so
   the button reads as a moulded clay object resting on the surface. Replaces
   the old flat fill + hard coloured ledge ("candy block"). Colours unchanged. */
.btn-primary   { background: linear-gradient(180deg, #72c0fb, #228be6); } /* blue  */
.btn-success   { background: linear-gradient(180deg, #71e085, #37b24d); } /* green */
.btn-danger    { background: linear-gradient(180deg, #ff9090, #cc4b4b); } /* red   */
.btn-secondary { background: linear-gradient(180deg, #ffffff, #ddd6ef); color: var(--clay-dark); }

.clay-btn {
  border: none;
  border-radius: 22px;
  font-weight: 700;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.12);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.5),    /* top lip catching light */
    inset 0 -5px 8px rgba(0, 0, 0, 0.18),        /* soft shadow underneath, inside */
    0 6px 12px rgba(74, 68, 99, 0.3);            /* contact shadow on the surface */
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.btn-secondary { text-shadow: none; }
.clay-btn:hover { transform: translateY(-1px); }
.clay-btn:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 3px 6px rgba(0, 0, 0, 0.28),         /* pressed in */
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 2px 5px rgba(74, 68, 99, 0.22);
}

/* Round icon buttons: white 3D discs */
.topbar-icon-btn, .log-toggle-btn {
  border: none;
  box-shadow: 0 5px 0 #ddd8ee, 0 12px 18px rgba(74, 68, 99, 0.12), inset 0 3px 0 #fff;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.topbar-icon-btn:active, .log-toggle-btn:active {
  transform: translateY(3px);
  box-shadow: 0 2px 0 #ddd8ee, inset 0 3px 0 #fff;
}

/* Color-pick buttons: chunky per-color ledge (shapes remain toggle-gated) */
.color-select-btn { border: none; text-shadow: 0 2px 0 rgba(0, 0, 0, 0.15); transition: transform 0.08s ease, box-shadow 0.08s ease; }
.color-select-btn.btn-red    { box-shadow: 0 6px 0 #e05252, 0 14px 20px rgba(255, 107, 107, 0.35), inset 0 4px 0 rgba(255, 255, 255, 0.45); }
.color-select-btn.btn-blue   { box-shadow: 0 6px 0 #2f8fdc, 0 14px 20px rgba(77, 171, 247, 0.35), inset 0 4px 0 rgba(255, 255, 255, 0.45); }
.color-select-btn.btn-green  { box-shadow: 0 6px 0 #3aad4f, 0 14px 20px rgba(81, 207, 102, 0.35), inset 0 4px 0 rgba(255, 255, 255, 0.45); }
.color-select-btn.btn-yellow { box-shadow: 0 6px 0 #d9a410, 0 14px 20px rgba(252, 196, 25, 0.40), inset 0 4px 0 rgba(255, 255, 255, 0.50); }
.color-select-btn:active { transform: translateY(4px); }

/* Bottom-nav active: raised blue pill */
.bottom-nav-btn.active {
  background: var(--clay-blue);
  color: #fff;
  box-shadow: 0 4px 0 #2f8fdc, 0 8px 14px rgba(77, 171, 247, 0.40), inset 0 2px 0 rgba(255, 255, 255, 0.40);
}

/* Currency / coin badge: match the new button depth */
.shop-coin-badge {
  box-shadow: 0 4px 0 var(--clay-yellow-dark), 0 10px 16px rgba(74, 68, 99, 0.12), inset 0 2px 0 rgba(255, 255, 255, 0.5);
}

/* Hero CTA = green (Quick Match), per the Claude Design mock */
#btn-quick-match {
  background: linear-gradient(180deg, #71e085, #37b24d); /* green clay pill, matching btn-success */
  color: #fff;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.12);
}

/* ------------------------------------------------------------------ */
/* Collection screen: two-face flipping box (Event <-> Collection)     */
/* ------------------------------------------------------------------ */
.collection-tabs {
  width: auto;
  margin-bottom: 0;
}

.collection-flip {
  flex: 1;
  width: 100%;
  min-height: 0;
  position: relative;
  perspective: 1400px;
}

.collection-flip-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.35, 0.9, 0.35, 1);
}

.collection-flip.flipped .collection-flip-inner {
  transform: rotateY(180deg);
}

.collection-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: rgba(0, 0, 0, 0.1);
  border-radius: 20px;
  padding: 12px;
  box-shadow: inset 3px 3px 6px rgba(0, 0, 0, 0.15);
}

.collection-face-back {
  transform: rotateY(180deg);
}

.collection-face-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.collection-face-title {
  font-weight: 800;
  color: var(--clay-dark);
  font-size: 0.95rem;
}

.collection-face-corner {
  display: flex;
  align-items: center;
  gap: 8px;
}

.collection-corner-badge {
  padding: 4px 13px;
  font-size: 0.85rem;
  /* Clay currency badge - dark fill so the icon + white numeral pop, matching
     the home currency pills instead of the old flat yellow-on-tan box. Wins
     over the .shop-coin-badge yellow by later source order (same specificity). */
  background: linear-gradient(180deg, #5b5273, #423a58);
  border: none;
  border-radius: 999px;
  color: #fff;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.2),   /* top lip */
    inset 0 -3px 5px rgba(0, 0, 0, 0.26),       /* inner shadow beneath */
    0 5px 9px rgba(58, 46, 72, 0.35);           /* contact shadow */
}
.collection-corner-badge .currency-icon { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35)); }

.collection-event-body {
  flex: 1;
  display: flex;
  gap: 12px;
  min-height: 0;
}

.collection-event-grid-wrap {
  flex: 1;
  overflow-y: auto;
  min-width: 0;
}

/* Reward rail: the skin you're collecting toward */
.collection-reward-rail {
  width: 172px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.55);
  border-radius: 16px;
  padding: 12px;
  text-align: center;
  overflow-y: auto;
}

.collection-reward-label {
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--clay-dark);
  opacity: 0.6;
}

.collection-reward-name {
  font-weight: 800;
  font-size: 0.9rem;
  color: var(--clay-dark);
}

.collection-reward-hint {
  font-size: 0.68rem;
  color: var(--clay-dark);
  opacity: 0.7;
}

.collection-reward-preview {
  position: relative;
  width: 100px;
  height: 140px;
}
.collection-reward-preview .clay-card-element {
  cursor: default;
}
/* Event Reward now uses the SAME two-card fan as the inventory/shop thumbnails
   (skinFanHtml), but the base .skin-fan is 64x74 - sized for grid thumbs - so
   it would sit small and off-centre in this 100x140 reward slot. Scale it to
   the slot, keeping the 5:7 card ratio and centring exactly:
   left = (100-72)/2 = 14, top = (140-100)/2 = 20. */
.collection-reward-preview .skin-fan {
  width: 100px;
  height: 140px;
}
.collection-reward-preview .skin-fan .fan-card {
  width: 72px;
  height: 100px;
  top: 20px;
  left: 14px;
}
/* Slightly wider spread than the thumbnail, proportional to the larger card. */
.collection-reward-preview .skin-fan .fan-0 { transform: rotate(-9deg) translateX(-8px); }
.collection-reward-preview .skin-fan .fan-1 { transform: rotate(9deg) translateX(8px); }

.collection-skins-scroll {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}


@media (max-height: 520px) {
  .collection-reward-rail {
    width: 128px;
    padding: 8px;
  }
  .collection-reward-preview {
    transform: scale(0.72);
    transform-origin: top center;
    margin-bottom: -34px;
  }
  .collection-face {
    padding: 8px;
    gap: 6px;
  }
}

/* A rotated-away face is invisible (backface-visibility) but would still
   swallow clicks - only the face currently shown accepts pointer events. */
.collection-flip .collection-face-back,
.collection-flip.flipped .collection-face-front {
  pointer-events: none;
}
.collection-flip.flipped .collection-face-back {
  pointer-events: auto;
}

/* ------------------------------------------------------------------ */
/* Currency tab: compact gem tiles with escalating-bonus badges        */
/* ------------------------------------------------------------------ */
#gems-catalog-grid {
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 10px;
}

.gem-tile {
  padding: 10px 8px;
}

.gem-tile-icon {
  font-size: 1.5rem;
  line-height: 1;
  margin-bottom: 4px;
}

.gem-tile .shop-item-name {
  font-size: 0.82rem;
  margin-bottom: 2px;
}

.gem-tile .shop-item-price {
  font-size: 0.78rem;
  margin-bottom: 6px;
}

.gem-tile .shop-item-btn {
  font-size: 0.7rem !important;
  padding: 5px 8px !important;
}

.gem-bonus-badge {
  display: inline-block;
  background: linear-gradient(135deg, #51cf66, #2f9e44);
  color: white;
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 8px;
  margin-bottom: 4px;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}

.gem-bonus-badge.gem-bonus-base {
  background: var(--clay-white-dark);
  color: var(--clay-dark);
  text-shadow: none;
}

/* ------------------------------------------------------------------ */
/* Event nav badge + card-face tiles (dimmed until owned)              */
/* ------------------------------------------------------------------ */
.bottom-nav-btn {
  position: relative;
}

.nav-event-days {
  position: absolute;
  top: -7px;
  right: 4px;
  background: var(--clay-red);
  color: white;
  font-size: 0.58rem;
  font-weight: 800;
  padding: 1px 7px;
  border-radius: 999px;
  border: 2px solid var(--clay-white-light);
  box-shadow: 0 2px 4px rgba(84, 74, 133, 0.25);
  pointer-events: none;
  z-index: 2;
}

/* Event screen: the content area to the right of the vertical tab rail holds
   whichever tab panel is active (On-going / Event Cards). Fills the row and
   lets its panel scroll internally. */
.event-content-area {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* On-going tab (task 12): cumulative EXP tile + placeholder event art and
   directions, in a scrolling grey panel that matches the Event Cards face. */
/* Event On-going tab: grid layout that fits one landscape-phone screen with
   no scroll. Four bands: identity strip (slim, themed), hero row (2 cells),
   support row (3 cells), open button (positioned absolutely). */
.event-ongoing-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 1fr;
  gap: 10px;
  padding: 2px 12px 12px;
  position: relative;
}
/* Tighten the gap between the top of the screen and the identity strip - the
   screen header only holds the "Event" title, so its default spacing is air. */
#screen-event .shop-header { margin-bottom: 0; }
#screen-event .section-title { margin-bottom: 0; }

/* 1. Identity strip: event name (left) + countdown pill (right) + confetti */
.event-grid-identity {
  position: relative;
  background: linear-gradient(135deg, rgba(239, 235, 220, 0.95), rgba(245, 240, 230, 0.95));
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 12px 16px;
  box-shadow: var(--clay-shadow-out);
  display: flex;
  align-items: center;
  justify-content: space-between;
  overflow: hidden;
  flex-shrink: 0;
}
.event-identity-left { flex: 1; min-width: 0; }
.event-name {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--clay-dark);
  background: rgba(255, 255, 255, 0.5);
  padding: 6px 12px;
  border-radius: 8px;
  display: inline-block;
  position: relative;
  z-index: 1;
}
.event-identity-right { flex-shrink: 0; margin-left: 12px; }
.event-countdown {
  display: flex;
  align-items: center;
  gap: 4px;
  background: rgba(255, 255, 255, 0.8);
  border: 2px solid var(--clay-white-dark);
  border-radius: 12px;
  padding: 6px 12px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--clay-dark);
  white-space: nowrap;
  position: relative;
  z-index: 2;
  flex-shrink: 0;
}
.event-countdown-icon { font-size: 0.9rem; margin-right: 2px; }

/* Confetti: positioned absolutely behind the left title, NOT overlapping countdown */
.event-identity-confetti {
  position: absolute;
  pointer-events: none;
  opacity: 0.55;
  z-index: 0;
}
/* Confetti positioned LEFT behind title, scattered behind "Cream Festival" */
.event-identity-confetti-1 { width: 24px; height: 24px; top: 6px; left: 12px; transform: rotate(-20deg); }
.event-identity-confetti-2 { width: 28px; height: 28px; top: 10px; left: 50px; transform: rotate(15deg); }
.event-identity-confetti-3 { width: 18px; height: 18px; top: 16px; left: 30px; transform: rotate(-35deg); }

/* 2. Hero row: combined In-progress panel (62% left) | ECP panel (38% right) */
.event-grid-hero {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 10px;
  align-items: stretch;
}
/* Clay tile surface — warm cream (#FDF8F0), soft shadow, top lip highlight ~15%.
   Shared by the combined panel, the ECP panel and the placement row. */
.event-hero-combined,
.event-hero-ecp,
.event-grid-placement {
  background: #FDF8F0;
  border: 3px solid var(--clay-white-dark);
  border-radius: 16px;
  padding: 14px;
  box-shadow: var(--clay-shadow-out);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  position: relative;
}
/* Top lip highlight (clay surface treatment) */
.event-hero-combined::before,
.event-hero-ecp::before,
.event-grid-placement::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 15%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.4), transparent);
  border-radius: 13px 13px 0 0;
  pointer-events: none;
}
/* Combined panel: a bigger fan on the left, ONE composed text column on the
   right (skin name headline -> status label -> big count), left-aligned so
   the three lines rag together instead of floating separately. */
.event-hero-combined { gap: 26px; }
.event-hero-reward-side {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.event-hero-progress-side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
.event-howto-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--clay-white-dark);
  background: rgba(255, 255, 255, 0.85);
  font-size: 0.95rem;
  font-weight: 900;
  color: var(--clay-dark);
  line-height: 1;
  cursor: pointer;
}
.event-howto-btn:active { transform: scale(0.92); }
.event-hero-title {
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--clay-dark);
  opacity: 0.55;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.event-hero-count {
  font-size: 2.5rem;
  font-weight: 900;
  color: var(--clay-dark);
  line-height: 1;
  display: flex;
  gap: 3px;
  align-items: baseline;
}
.event-hero-total { font-size: 1.05rem; font-weight: 700; opacity: 0.65; }
/* Reward preview: the same two-card fan as the Inventory thumbnails
   (skinFanHtml; base .skin-fan is 64x74 grid-thumb sized) scaled up, keeping
   the 5:7 card ratio and centring: left = (96-68)/2, top = (128-95)/2. */
.event-reward-preview { position: relative; width: 96px; height: 128px; flex-shrink: 0; }
.event-reward-preview .skin-fan { width: 96px; height: 128px; }
.event-reward-preview .skin-fan .fan-card {
  width: 68px;
  height: 95px;
  top: 16px;
  left: 14px;
}
.event-reward-preview .skin-fan .fan-0 { transform: rotate(-9deg) translateX(-8px); }
.event-reward-preview .skin-fan .fan-1 { transform: rotate(9deg) translateX(8px); }
/* The skin name is the panel's headline now (top of the text column). */
.event-reward-name { font-size: 1.15rem; font-weight: 800; color: var(--clay-dark); }

/* ECP panel: the crown-card icon at full glory + label-over-count on the
   left, the action stack (OPEN / daily ad) on the right, equal-width buttons.
   Unavailable actions grey out instead of hiding, so the panel's shape never
   jumps. */
.event-hero-ecp { flex-direction: row; padding: 12px 16px; gap: 14px; justify-content: space-between; }
.event-ecp-info { display: flex; flex-direction: row; align-items: center; gap: 10px; }
.event-ecp-icon { flex-shrink: 0; }
.event-ecp-icon img {
  height: 68px;
  width: auto;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.25));
}
.event-ecp-count-wrap { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.event-ecp-count-wrap .event-support-value { font-size: 1.9rem; }
.event-ecp-actions { display: flex; flex-direction: column; align-items: stretch; justify-content: center; gap: 8px; }
.event-ecp-actions .clay-btn { width: 100%; }
.event-hero-ecp .clay-btn { padding: 7px 14px; font-size: 0.85rem; white-space: nowrap; }
.event-ecp-ad-btn { padding: 5px 12px; font-size: 0.75rem; }
.event-ecp-actions .clay-btn:disabled { opacity: 0.45; cursor: default; filter: grayscale(0.6); }
.event-support-icon { width: 28px; height: 28px; flex-shrink: 0; }
.event-support-icon img { width: 100%; height: 100%; }
.event-support-title { font-size: 0.75rem; font-weight: 800; color: var(--clay-dark); opacity: 0.6; letter-spacing: 0.04em; text-transform: uppercase; }
.event-support-value { font-size: 1.5rem; font-weight: 900; color: var(--clay-dark); line-height: 1; }
.event-support-label { font-size: 0.7rem; font-weight: 600; color: var(--clay-dark); opacity: 0.75; line-height: 1.2; }

/* 3. Placement Points row: one full-width tile. Every full 500 available
   points arms CLAIM (+1 ECP each, points deducted on claim). */
.event-grid-placement { padding: 10px 16px; gap: 12px; justify-content: flex-start; }
.event-placement-text { flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; text-align: left; }
.event-placement-progress {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: stretch;
}
.event-placement-bar {
  height: 10px;
  background: rgba(74, 68, 99, 0.15);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.event-placement-bar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(180deg, #8ce99a, #37b24d);
  transition: width 0.3s ease;
}
.event-placement-bar-label {
  font-size: 0.85rem;
  font-weight: 900;
  color: var(--clay-dark);
  text-align: right;
  line-height: 1;
}
#event-placement-claim { flex-shrink: 0; padding: 7px 14px; font-size: 0.8rem; }
#event-placement-claim:disabled { opacity: 0.45; cursor: default; }

/* "How to Earn" popup (the ? on the combined panel). */
.event-howto-card { max-width: 320px; text-align: center; }
.event-howto-card h3 { margin: 0 0 12px; color: var(--clay-dark); }
.event-howto-list {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-weight: 700;
  color: var(--clay-dark);
}

/* Static (non-flipping) collection/event panel - same look as the old flip
   faces, but in normal flow */
.collection-face-static {
  position: relative;
  inset: auto;
  flex: 1;
  width: 100%;
  min-height: 0;
  backface-visibility: visible;
  transform: none;
  pointer-events: auto !important;
}

/* Event/collection grids: tiles are real mini card faces now. Dimmed =
   not yet collected; owned cards render at full color and glow. */
.card-face-tile {
  padding: 0;
  border: none;
  background: none;
  box-shadow: none;
  overflow: visible;
}

.card-face-tile .clay-card-element {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 4px;
  border-width: 3px;
  cursor: default;
}
.card-face-tile .clay-card-element .card-corner { font-size: 0.55rem; }
.card-face-tile .clay-card-element .card-center {
  width: 60%;
  height: 55%;
  font-size: 1rem;
  border-radius: 8px;
}
/* Square stamp for attack cards - see the matching .ccb-tile note. */
.card-face-tile .clay-card-element .card-center.attack-center {
  width: 74%;
  height: auto;
  aspect-ratio: 1 / 1;
}

.card-dimmed .clay-card-element {
  filter: grayscale(0.9) brightness(0.82) contrast(0.85);
  opacity: 0.55;
}

.event-card-tile.owned .clay-card-element,
.ccb-tile:not(.card-dimmed) .clay-card-element {
  box-shadow: 0 0 12px rgba(255, 214, 90, 0.55), var(--clay-shadow-out);
}

/* Buy buttons overlay the dimmed card's lower edge */
.card-dimmed {
  position: relative;
}

/* ------------------------------------------------------------------ */
/* Two-pane inventory: equipped showcase rail (left) + owned grid      */
/* ------------------------------------------------------------------ */

.inventory-equipped-rail {
  width: 186px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  justify-content: center; /* showcase sits centered in the rail */
  gap: 10px;
  overflow-y: auto;
  background: rgba(255, 255, 255, 0.55);
  border: 3px solid var(--clay-white-dark);
  border-radius: 18px;
  padding: 12px;
  box-shadow: var(--clay-shadow-out);
}

/* Tabs now sit in their own row right under the "Inventory" title (moved out of
   the right column) so the equipped rail (left) and the items box (right) start
   at the same Y. Compact margins keep the whole block high on the screen. */
#screen-inventory .shop-header {
  margin-bottom: 6px;
}
#screen-inventory.profile-content,
#screen-inventory .profile-content {
  gap: 6px;
}

/* One equipped item: image on top, texts below */
.equipped-showcase {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
}

.equipped-showcase-preview {
  position: relative;
  width: 100px;
  height: 140px;
  margin-bottom: 4px;
}
.equipped-showcase-preview .clay-card-element {
  width: 100px;
  height: 140px;
  cursor: default;
}
.equipped-showcase-preview {
  display: flex;
  align-items: center;
  justify-content: center;
}
.equipped-showcase-preview .board-swatch-preview {
  width: var(--board-preview-w);
  height: var(--board-preview-h);
}
.equipped-showcase-preview.is-avatar {
  height: 100px;
}
.equipped-showcase-preview.is-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 3px dashed var(--clay-white-dark);
  border-radius: 14px;
  font-size: 1.4rem;
  color: var(--clay-dark);
  opacity: 0.5;
}

.equipped-showcase-label {
  font-size: 0.6rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--clay-dark);
  opacity: 0.55;
}

.equipped-showcase-name {
  font-weight: 800;
  font-size: 0.88rem;
  color: var(--clay-dark);
  line-height: 1.15;
}

@media (max-height: 520px) {
  .inventory-equipped-rail {
    width: 132px;
    padding: 8px;
  }
  :root {
    --board-preview-w: 76px;
    --board-preview-h: 38px;
  }
  .equipped-showcase-preview,
  .equipped-showcase-preview .clay-card-element {
    width: 72px;
    height: 100px;
  }
  .equipped-showcase-preview .board-swatch-preview {
    width: var(--board-preview-w);
    height: var(--board-preview-h);
  }
  .equipped-showcase-preview.is-avatar {
    height: 72px;
  }
}

/* Yellow King shield pulse: soft golden ring + shield swelling from center */
.shield-pulse {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 40;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.shield-pulse-ring {
  position: absolute;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  border: 5px solid rgba(252, 196, 25, 0.85);
  box-shadow: 0 0 24px rgba(252, 196, 25, 0.6), inset 0 0 14px rgba(252, 196, 25, 0.35);
  animation: shieldRing 0.9s ease-out forwards;
}

.shield-pulse-icon {
  font-size: 2.6rem;
  animation: shieldIcon 0.9s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  filter: drop-shadow(0 0 10px rgba(252, 196, 25, 0.8));
}

@keyframes shieldRing {
  0% { transform: scale(0.4); opacity: 0; }
  30% { opacity: 1; }
  100% { transform: scale(3.4); opacity: 0; }
}

@keyframes shieldIcon {
  0% { transform: scale(0.2); opacity: 0; }
  35% { transform: scale(1.25); opacity: 1; }
  70% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 0; }
}

/* (While a played card flies in, only ITS pile copy is hidden - handled per
   card in renderDiscardPile via data-inflight-hidden, not a blanket rule; the
   old hide-everything rule here made the whole stack blink on every play.) */


/* Equipped rail: the default clay-face SVG fills its square frame */
.equipped-showcase-preview.is-avatar svg {
  width: 100%;
  height: 100%;
}
.equipped-showcase-preview.is-avatar {
  border-radius: 20px;
  overflow: hidden;
}

/* Home topbar currency: plain readout, no badge box */
.home-currency-plain {
  display: flex;
  align-items: center;
  font-weight: 800;
  color: var(--clay-dark);
  font-size: 1rem;
}

/* ------------------------------------------------------------------ */
/* Shop density: smaller tiles, shorter rows - 5+ per row instead of 3 */
/* (scoped to the SHOP grid; inventory/collection grids unaffected)    */
/* ------------------------------------------------------------------ */
/* Compact tiles - 5-6 per row. No inline buy button: the whole tile is
   tappable and opens the enlarge-and-confirm modal (#shop-item-modal). */
#shop-items-grid,
#profile-inventory-grid {
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: 8px;
}

#shop-items-grid .shop-item-card,
#profile-inventory-grid .shop-item-card {
  padding: 7px 5px;
  border-radius: 14px;
  border-width: 3px;
  cursor: pointer;
  position: relative;
}
/* Inventory tiles share the shop's compact preview/name/badge sizing so both
   grids pack ~6/row identically. */
#profile-inventory-grid .shop-item-preview-holder {
  width: 60px;
  height: 84px;
  margin-bottom: 5px;
}
#profile-inventory-grid .shop-item-preview-holder .clay-card-element {
  width: 100px;
  height: 140px;
  transform: scale(0.6);
  transform-origin: top left;
}
#profile-inventory-grid .board-swatch-preview {
  width: 66px;
  height: 33px;
}
#profile-inventory-grid .shop-item-name {
  font-size: 0.7rem;
  line-height: 1.12;
  margin-bottom: 2px;
}
#profile-inventory-grid .inventory-badge {
  font-size: 0.5rem;
  padding: 1px 7px;
  margin-bottom: 2px;
}
#profile-inventory-grid .shop-item-btn {
  font-size: 0.66rem !important;
  padding: 5px 8px !important;
  border-radius: 10px !important;
}
/* Event-limited item badge (top-left of the tile). */
.shop-limited-badge {
  position: absolute;
  top: 3px;
  left: 3px;
  background: #f76707;
  color: #fff;
  font-size: 0.48rem;
  font-weight: 800;
  padding: 1px 6px;
  border-radius: 8px;
  z-index: 3;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
}

/* Card previews scale down to 60x84 (same 5:7 proportion) */
#shop-items-grid .shop-item-preview-holder {
  width: 60px;
  height: 84px;
  margin-bottom: 5px;
}
#shop-items-grid .shop-item-preview-holder .clay-card-element {
  width: 100px;
  height: 140px;
  transform: scale(0.6);
  transform-origin: top left;
}

/* Boards keep the canonical 2:1 mat proportion, just smaller */
#shop-items-grid .board-swatch-preview {
  width: 66px;
  height: 33px;
}

/* Avatars: smaller rounded square */
#shop-items-grid .avatar-shop-preview {
  width: 54px;
  height: 54px;
  margin-top: 12px;
  border-radius: 14px;
}

#shop-items-grid .shop-item-name {
  font-size: 0.7rem;
  line-height: 1.12;
  margin-bottom: 2px;
}
#shop-items-grid .shop-item-price {
  font-size: 0.68rem;
  margin-bottom: 0;
}
#shop-items-grid .shop-tier-badge {
  font-size: 0.5rem;
  padding: 1px 7px;
  margin-bottom: 2px;
}
#shop-items-grid .shop-item-btn {
  font-size: 0.66rem !important;
  padding: 5px 8px !important;
  border-radius: 10px !important;
}

/* ------------------------------------------------------------------ */
/* Nav color identity: Play = green (matches the PLAY CTA), Shop = blue */
/* ------------------------------------------------------------------ */
.bottom-nav-btn.active {
  background: var(--clay-green);
  color: #fff;
  box-shadow: 0 4px 0 #3aad4f, 0 8px 14px rgba(81, 207, 102, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4);
}

#nav-btn-shop {
  /* Blue accent identity, but as a 3D clay pill (gradient + lip + inset floor
     + soft contact shadow) instead of the old flat hard-ledge block. Matches
     btn-primary / the active shop tab. */
  background: linear-gradient(180deg, #72c0fb, #228be6);
  color: #fff;
  opacity: 1;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.5),
    inset 0 -5px 8px rgba(0, 0, 0, 0.18),
    0 6px 13px rgba(34, 139, 230, 0.34);
}
#nav-btn-shop:hover {
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.5),
    inset 0 -5px 8px rgba(0, 0, 0, 0.18),
    0 9px 18px rgba(34, 139, 230, 0.4);
}
#nav-btn-shop:active {
  box-shadow:
    inset 0 3px 6px rgba(0, 0, 0, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 2px 5px rgba(34, 139, 230, 0.3);
}

/* Play = green solid accent (the primary bottom-nav action -> matchmaking),
   mirroring Shop's blue identity. */
#nav-btn-play {
  background: var(--clay-green);
  color: #fff;
  opacity: 1;
  box-shadow: 0 4px 0 #3aad4f, 0 8px 14px rgba(81, 207, 102, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4);
}

/* ==================== MISSIONS SCREEN (restructure 2026-07) ====================
   Rows sit DIRECTLY on missions-bg - the old translucent scrim panel is gone
   (scoped below; the scrim itself still exists for the other screens that
   share .shop-items-scroll-area). The art is 1600x900 with a flat, calm tan
   band in the middle (measured: centre 50% luminance std ~4.7 vs 31-35 in
   the prop-filled side margins), so ALL content lives in one centred column
   (.missions-band) and the margins stay clear for the artwork. */
/* Missions is a MODAL WINDOW centred on the .overlay dim, floating above
   whatever screen opened it. It carries missions-bg as its own surface, so the
   art reads inside the window frame instead of full-bleed behind the screen. */
.missions-window {
  position: relative; /* containing block for the back button + reset chip */
  display: flex;
  flex-direction: column;
  width: min(520px, 84vw);
  height: min(400px, 80vh);
  height: min(400px, 80dvh);
  min-height: 0;
  gap: 14px; /* breathing room between the tab row and the first mission */
  padding: 10px 14px 12px;
  /* Cream wash OVER the art: at window size `cover` crops the full-screen
     painting hard, and the raw props behind the rows hurt legibility. The wash
     keeps it as soft texture and guarantees contrast for the cream row tiles. */
  background:
    linear-gradient(rgba(253, 248, 240, 0.82), rgba(253, 248, 240, 0.82)),
    url("assets/art/missions-bg.webp") center / cover no-repeat,
    #f3ead9;
  border-radius: 28px;
  /* Lifted card, not a recessed panel - it's floating over the dim now. */
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.38), inset 0 0 0 2px rgba(255, 255, 255, 0.35);
  box-sizing: border-box;
  overflow: hidden; /* keep the art inside the rounded corners */
}
/* The back button is scoped INSIDE the window - .screen-back-btn positions
   against the nearest positioned ancestor, which is .missions-window, but its
   screen-level top offset (30px safe-area) would push it past the window's
   padding. Re-anchor to the window's own corner. */
/* This chip's geometry became the app-wide default (see .screen-back-btn),
   so only the position differs now: inside a modal window there is no device
   edge, so it uses flat offsets rather than safe-area insets. */
.missions-window-back {
  top: 8px !important;
  left: 10px !important;
}
/* Cadence tabs: a centred horizontal row ABOVE the list box (was a vertical
   left rail). Padded clear of the back button and the reset chip, which are
   absolutely positioned in the window's two top corners. */
.missions-tabs {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 5px;
  flex: 0 0 auto;
  min-height: 30px;
  padding: 0 clamp(46px, 10%, 90px);
}
/* All three tabs are the SAME size: a fixed width sized to the longest label
   ("Monthly"), not `flex: 1 1 0` - that is what a five-tab-era rule used to do
   here, and it stretched each tab to a full third of the window. Fixed width
   keeps them equal AND compact. */
.missions-tabs .shop-tab-btn {
  flex: 0 0 auto;
  width: 86px;
  padding: 6px 8px;
  font-size: 0.82rem;
  border-radius: 10px;
  text-align: center;
}
/* Legacy centred-band width (kept for any element still tagged .missions-band). */
.missions-band {
  width: clamp(520px, 54%, 880px);
}

/* The window supplies the recessed surface now, so the list area inside it goes
   transparent - two nested scrims read as muddy, and the mission rows are
   already opaque cream tiles that need a plain backdrop to sit on. */
#screen-missions .shop-items-scroll-area {
  background: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
  margin-bottom: 0;
}

/* spec-12.2 reset countdown: a compact clay chip in the window's top-right
   corner (it anchors to .missions-window, not the screen, so it uses plain
   offsets rather than safe-area insets). */
/* Quiet status text, not a heavy chip: dropped to the BOTTOM of the tab band so
   it sits just above the mission list, with a lighter weight and smaller size.
   The shadow was softened to match - a heavy drop shadow around small, light
   text read as a loud badge wrapping quiet content. */
.missions-reset {
  position: absolute;
  top: 30px;
  right: 12px;
  z-index: 20;
  font-size: 0.58rem;
  font-weight: 500;
  color: var(--clay-dark);
  opacity: 0.85;
  background: linear-gradient(180deg, #ffffff, #f0edf8);
  padding: 4px 10px;
  border-radius: 999px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 2px 5px rgba(84, 74, 133, 0.14);
  white-space: nowrap;
}
.missions-reset:empty { display: none; }

/* Tabs: centred horizontal pills (was a vertical rail covering the plant art
   in the left margin). Active = blue with a light top-inset; inactive =
   translucent cream. */

/* Mission rows as CLAY TILES resting on the table: opaque warm cream (never
   translucent, never flat white), a soft warm shadow dropped BELOW, and a
   light band across the top ~20% for the bevel read.
   Scoped to #screen-missions: .mission-row is shared markup with the match
   history and notifications lists, which keep their own look. */
/* Compact rows: the leading icon column was removed, so the row no longer has
   to be tall enough to hold it - min-height drops from 58px to 42px here. */
#screen-missions .mission-row {
  position: relative;
  overflow: hidden;
  background: #fdf8f0;
  border: none;
  border-radius: 16px;
  padding: 6px 12px;
  min-height: 42px;
  gap: 10px;
  box-shadow: 0 4px 10px rgba(96, 78, 58, 0.26);
}
#screen-missions .mission-row-title { font-size: 0.76rem; }
#screen-missions .mission-progress { margin-top: 3px; gap: 6px; }
/* No max-width here (the shared rule caps it at 230px): the capped bar left a
   dead gap between the mission text and the reward column, since .mission-row-main
   stretches but its content didn't. Letting the bar fill closes that gap at any
   window width. */
#screen-missions .mission-progress-track { height: 8px; max-width: none; }
#screen-missions .mission-xp-col { width: 62px; gap: 2px; }
#screen-missions .mission-xp { font-size: 0.58rem; }
#screen-missions .mission-tier-tag { font-size: 0.48rem; padding: 1px 6px; }

/* FIXED-WIDTH COLUMNS. Every section right of the mission text is a fixed
   width with tabular figures, so rows line up regardless of their values.
   Without this each column sized to its own content and a "1" reward vs a
   "1000" reward (or "0 / 5" vs "0 / 2000") shifted everything after it,
   leaving the reward/XP/CLAIM columns visibly ragged down the list. */
#screen-missions .mission-reward {
  width: 58px;
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
#screen-missions .mission-reward .currency-icon {
  width: 15px;
  height: 15px;
}
/* Progress readout: fixed width + right-aligned, so every bar ENDS at the same
   x instead of being shortened by a longer "0 / 2000". */
#screen-missions .event-daily-count {
  flex: 0 0 auto;
  width: 56px;
  text-align: right;
  font-size: 0.6rem;
  font-variant-numeric: tabular-nums;
}
#screen-missions .mission-claim-btn {
  font-size: 0.66rem !important;
  padding: 4px 10px !important;
  min-width: 58px;
  flex: 0 0 auto;
}
#screen-missions .mission-row::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 20%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0));
  pointer-events: none;
}

/* Row internals (spec 12.2 order): icon | title+tier / progress | reward | claim */
/* Left block: icon on top, difficulty rank tag below. Fixed width so every
   row's left column is identical and the rows line up. */
/* Difficulty rank stacked ABOVE the XP value. Replaces the old leading
   .mission-icon-col (icon with the rank beneath it) - the icon was removed and
   the rank moved here. Fixed width so every row's right block aligns. */
.mission-xp-col {
  flex: 0 0 auto;
  width: 76px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
}
.mission-xp-col .mission-tier-tag {
  margin-left: 0; /* was an inline margin next to the title */
}
#screen-missions .mission-row-main {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
}
.mission-progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 5px;
}
.mission-progress-track {
  flex: 1 1 auto;
  max-width: 230px;
  height: 10px;
  border-radius: 999px;
  background: #e7dfd3; /* warm grey */
  box-shadow: inset 0 1px 2px rgba(96, 78, 58, 0.28);
  overflow: hidden;
}
.mission-progress-fill {
  height: 100%;
  border-radius: inherit;
  background: #f0a63c; /* amber while in progress */
  transition: width 0.3s ease;
}
.mission-progress-fill.complete {
  background: var(--clay-green);
}
/* x/y readout: muted purple-grey. Was #c25e12 orange-red, which reads as an
   error state in a pastel UI. */
#screen-missions .event-daily-count {
  color: #8a84a3;
}
.mission-reward {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-weight: 800;
  color: var(--clay-dark);
  white-space: nowrap;
}
/* XP weight now sits as its own column BETWEEN the reward icon and the CLAIM
   button (was stacked under the reward icon). */
.mission-xp {
  flex: 0 0 auto;
  font-size: 0.64rem;
  font-weight: 700;
  opacity: 0.6;
  color: var(--clay-dark);
  white-space: nowrap;
  text-align: center;
}

/* (CLAIM's dead state lives on the canonical .mission-claim-btn:disabled rule
   up near the other mission-row styles - it already carried !important flags,
   so the new look was folded into it rather than fought from here.) */

@media (max-height: 520px) {
  .missions-band { width: clamp(460px, 62%, 800px); }
  #screen-missions .mission-row { border-radius: 14px; padding: 5px 10px; min-height: 38px; }
  /* Tighter window + tab row so the list keeps its height on a short screen -
     the fixed 440px height would otherwise overflow it. */
  .missions-window { padding: 8px 12px 10px; gap: 10px; border-radius: 20px; height: 88dvh; }
  .missions-tabs { min-height: 30px; padding: 0 clamp(44px, 10%, 84px); }
  /* Same equal-width treatment, one step down so the row still clears the
     reset chip at the narrowest landscape. */
  .missions-tabs .shop-tab-btn { width: 74px; padding: 5px 6px; font-size: 0.74rem; }
  .missions-window-back { top: 5px !important; left: 6px !important; }
  .missions-reset { top: 26px; right: 10px; font-size: 0.54rem; padding: 3px 9px; }
}

/* ==================== HOME PASS (2026-07): chip press feedback ====================
   Appended after the DESIGN REFRESH block so this wins: the refresh gives the
   round util chips a translateY ledge-press, and the PNG icons additionally
   need scale + brightness on the chip (the raster glyph can't colour-shift
   the way the old currentColor SVGs did). */
.topbar-icon-btn:active {
  transform: translateY(3px) scale(0.94);
  filter: brightness(0.92);
}

/* Short landscape viewports (phone with browser chrome visible). Rewritten for
   the 2026-07 scene-centre layout - the previous rules here targeted
   .home-right-cluster and .chip-icon, which that redesign removed, while their
   .home-nav-btn rule still landed on the NEW tiles and forced horizontal
   padding onto what are now fixed-width column tiles.

   The squeeze is top-anchored utility stack vs bottom-anchored PLAY. Measured
   at the smallest landscape target (iPhone SE, 320px minus ~44px chrome) the
   two clear each other by ~30px at the default sizes, so this only needs to
   claw back a little: tighten the group break and shave the tiles. PLAY and the
   diorama's clear centre are left alone. */
@media (max-height: 420px) {
  .home-corner-tr { gap: 12px; top: max(10px, env(safe-area-inset-top)); }
  .home-icon-btn { width: 38px; height: 38px; }
  .home-icon-btn img { width: 19px; height: 19px; }
  .home-nav-menu-compact { gap: 5px; }
  .home-nav-btn-compact,
  .home-event-badge-compact { width: 46px; height: 46px; border-radius: 13px; }
  .home-nav-btn-compact .nav-icon { width: 21px; height: 21px; }
  .home-event-badge-compact .event-icon { width: 19px; height: 19px; }
  .home-nav-menu { gap: 6px; }
  .home-nav-btn { width: 54px; min-width: 54px; padding: 6px 0; }
  .home-nav-btn .nav-icon { width: 25px; height: 25px; }
}

/* ==================== MATCH SCREEN (mats -> board, 2026-07) ====================
   Attack indicator: a compact pill floating just right of the discard pile -
   paw-stamp icon + the running total. ALWAYS on screen (departs from spec 4.3's
   "visible only while attack_active == true") so the gauge has a constant home
   and players can see it at rest; it sits quiet and white showing +0, then goes
   red and shakes once a stack builds. Mirrors the "Turn" chip's 185px offset on
   the other side of the pile, so the two cues frame the deck symmetrically.
   ui.js already keeps .attack-amount fresh (+0 when inactive) on BOTH boards,
   so this is presentation only. */
.attack-card {
  display: flex !important;
  flex-direction: row !important;
  align-items: center !important;
  position: absolute;
  left: calc(50% + 185px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 6;
  gap: 8px;
  padding: 10px 18px !important;
  border: none !important;
  border-radius: 999px !important;
  box-shadow: var(--clay-shadow-out);
  animation: none;
  transition: background 0.25s ease, box-shadow 0.25s ease;
}
/* Resting state (+0): GREY container with the paw desaturated, so "nothing
   stacked" reads as inert rather than as a live white chip. */
.attack-card:not(.active-attack) {
  background: #b8b3c6 !important;
}
.attack-card:not(.active-attack) .attack-amount { color: #4a4463; text-shadow: none; }
/* The paw stays FULLY VISIBLE at rest. It used to be dimmed to 45% opacity +
   70% grayscale, which on the old white pill washed a white-and-pink disc out
   to nothing - the icon looked absent rather than idle. The grey container is
   what signals "no stack"; the mark itself should always read. */
.attack-card:not(.active-attack) .attack-icon-img { opacity: 1; filter: none; }
.attack-card.active-attack {
  background: rgba(224, 82, 82, 0.94) !important;
  box-shadow: 0 4px 10px rgba(120, 30, 30, 0.35);
  animation: attackShake 0.4s infinite alternate;
}
/* The pill is icon + total only - the title and gauge belonged to the panel. */
.attack-card .attack-title,
.attack-card .clay-gauge-track {
  display: none;
}
.attack-card .attack-header-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Fixed width + tabular figures: the pill is anchored by its LEFT edge, so a
   number that changes width (+0 -> +10) would resize the pill and shift its
   apparent position. 2.6ch covers +0 through +99. */
.attack-card .attack-amount {
  font-size: 1.5rem;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
  min-width: 2.6ch;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.attack-card .attack-icon-img {
  height: 1.95rem;
}

/* ==================== SKIN GRID + DETAIL (Shop / Inventory, spec 9.1) ====================
   Two-panel selection: a compact thumbnail grid selects into a large detail
   panel. Thumbnails only need to be RECOGNISABLE (two fanned cards = "a deck
   of these"); the detail panel does the inspection with one big card. Shop's
   action buys; Inventory's equips - never unified. */

/* ---- Detail panel (left, both screens) ---- */
.skin-detail-panel {
  flex: 0 0 clamp(230px, 30%, 330px);
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px 14px;
  background: rgba(255, 255, 255, 0.6);
  border-radius: 18px;
  overflow-y: auto;
}
.skin-detail-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}
/* Big single card - inspection, no occlusion. 190x266 shop / a touch smaller
   in the narrower inventory pane (the .clay-card-element internals are all
   %-based, so setting the element size scales frame + symbol together). */
.skin-detail-preview .detail-card {
  position: relative;
  width: 190px;
  height: 266px;
}
#inventory-detail-panel .skin-detail-preview .detail-card { width: 165px; height: 231px; }
.skin-detail-preview.slot-board .board-swatch-preview { width: 210px; height: 130px; }
.skin-detail-preview.slot-avatar .avatar-shop-preview { width: 150px; height: 150px; }
.skin-detail-preview.slot-avatar .avatar-img { width: 100%; height: 100%; object-fit: cover; border-radius: 24px; }
.skin-detail-name { font-size: 1.15rem; font-weight: 800; color: var(--clay-dark); text-align: center; }
.skin-detail-desc { font-size: 0.78rem; color: var(--clay-dark); opacity: 0.8; text-align: center; line-height: 1.3; }
.skin-detail-source { font-size: 0.68rem; color: #8a84a3; text-align: center; }
.skin-detail-action { margin-top: 8px; min-width: 150px; }
.skin-detail-cantafford { font-size: 0.72rem; font-weight: 700; color: var(--clay-red-dark); }
.skin-detail-empty { font-size: 0.82rem; opacity: 0.65; text-align: center; margin: auto; padding: 20px; }
/* Can't-afford BUY: unmistakably inert (spec 9.1), matching the mission CLAIM
   dead state so "you can't do this yet" reads the same way app-wide. */
.btn-cantafford {
  background: #ded7c9 !important;
  color: #a49b8d !important;
  text-shadow: none;
  box-shadow: none !important;
  transform: none;
  cursor: default;
}

/* ---- Thumbnail grid (right) ---- */
.skin-thumb-grid {
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)) !important;
  align-content: start;
}
.skin-thumb {
  position: relative;
  background: var(--clay-white-light);
  border: 3px solid var(--clay-white-dark);
  border-radius: 14px;
  padding: 8px 6px 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  box-shadow: var(--clay-shadow-out);
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.skin-thumb:hover { transform: translateY(-2px); }
.skin-thumb.selected {
  border-color: var(--clay-blue);
  box-shadow: 0 0 0 2px var(--clay-blue), var(--clay-shadow-out);
}
.skin-thumb-preview {
  width: 100%;
  height: 74px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.skin-thumb-name { font-size: 0.66rem; font-weight: 700; color: var(--clay-dark); text-align: center; line-height: 1.1; }
.skin-thumb-lock {
  position: absolute;
  top: 5px; right: 5px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: rgba(58, 46, 72, 0.72);
  display: flex; align-items: center; justify-content: center;
}
.skin-lock-icon { width: 12px; height: 12px; display: block; }
.skin-thumb-inuse {
  position: absolute;
  top: 5px; left: 5px;
  font-size: 0.55rem;
  font-weight: 800;
  color: #fff;
  background: var(--clay-green);
  padding: 1px 6px;
  border-radius: 999px;
}
/* Single upright card thumbnail (matches the detail preview). 5:7 kept, and
   it stays inside .skin-thumb-preview's 74px box so nothing clips. */
.skin-thumb .thumb-card {
  position: relative;
  width: 52px;
  height: 73px;
}
.skin-thumb .board-swatch-preview { width: 62px; height: 40px; }
.skin-thumb .avatar-shop-preview { width: 54px; height: 54px; }
.skin-thumb .avatar-img { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; }

/* Two fanned cards in a thumbnail - recognition ("a deck"). Each is a real
   .clay-card-element (5:7), offset + rotated so the pair reads as a stack. */
.skin-fan { position: relative; width: 64px; height: 74px; }
.skin-fan .fan-card {
  position: absolute;
  width: 46px;
  height: 64px;
  top: 5px;
  left: 9px;
}
.skin-fan .fan-0 { transform: rotate(-9deg) translateX(-5px); z-index: 1; }
.skin-fan .fan-1 { transform: rotate(9deg) translateX(5px); z-index: 2; }

@media (max-height: 520px) {
  /* Short viewport: tighten the detail panel so the FULLEST card (preview +
     rank + name + description + source + BUY) still fits without the button
     dropping below the fold. Smaller card, tighter gaps + type. */
  .skin-detail-panel { flex-basis: clamp(190px, 28%, 260px); padding: 8px 10px; gap: 4px; }
  .skin-detail-preview .detail-card { width: 118px; height: 165px; }
  #inventory-detail-panel .skin-detail-preview .detail-card { width: 108px; height: 151px; }
  .skin-detail-preview { margin-bottom: 0; }
  .skin-detail-name { font-size: 0.95rem; }
  .skin-detail-desc { font-size: 0.68rem; line-height: 1.2; }
  .skin-detail-source { font-size: 0.6rem; }
  .skin-detail-action { margin-top: 4px; }
  .skin-thumb-grid { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)) !important; }
}

/* Board previews show the ACTUAL match-screen background image (cover-fit),
   not the flat placeholder colour - the colour swatch styling remains the
   fallback for legacy colour-only boards (see boardPreviewHtml). */
.board-image-preview {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  /* Image boards are self-contained art, so no visible frame - the old faint
     grey border read as a stray edge around the picture. Kept transparent
     (not removed) so the 4px border box size stays identical and the image,
     which paints under the border-box, simply fills to the edge. */
  border-color: transparent;
  /* Also drop the inset bevel shadow here: it's for defining the flat colour
     swatches' edges, but over real art it just darkens the picture's borders
     into a grey box. */
  box-shadow: none;
}

/* ==================== HOME CURRENCY PILLS (clay restyle, spec 9.1) ====================
   Was flat yellow-on-tan with a hard 2px stroke - low luminance separation, so
   the outline did all the work and the gold icons/numerals had the worst
   contrast on the screen. Now a dark clay capsule that reads as an OBJECT
   resting on the table (same clay-volume language as the nav chips - a light
   lip catching light on top, soft shadow beneath, a contact shadow under the
   whole pill), with the icon overlapping the left edge UNO-style and a gold
   "+" store-entry button at the right. Scoped to #home-currency so the shared
   .shop-coin-badge (shop header / CCB) is untouched. */
/* Profile currency pills reuse the Home treatment verbatim (dark clay capsule,
   overlapping icon, high-contrast numerals) so the two screens don't diverge -
   the only difference is Profile has no "+" store button. */
#home-currency .currency-pill,
#profile-currency-row .currency-pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 5px 4px 24px; /* left room for the overlapping icon */
  border: none;
  border-radius: 999px;
  background: linear-gradient(180deg, #5b5273, #423a58); /* dark clay, not yellow */
  color: #fff;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.22),   /* top lip catching light */
    inset 0 -3px 5px rgba(0, 0, 0, 0.28),       /* soft shadow underneath, inside */
    0 6px 11px rgba(58, 46, 72, 0.4);           /* contact shadow on the table */
}
/* Icon overlaps / breaks the left outline (its own silhouette, UNO-style).
   Source assets stay 96 square - only the on-screen size changes. */
#home-currency .pill-icon,
#profile-currency-row .pill-icon {
  position: absolute;
  left: -7px;
  top: 50%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.4));
  z-index: 2;
}
#home-currency .pill-value,
#profile-currency-row .pill-value {
  color: #fff;
  font-weight: 800;
  font-size: 1rem;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35); /* keep bright numerals crisp on the dark fill */
}
/* Profile pills have no "+" button, so they need their own right padding. */
#profile-currency-row .currency-pill { padding-right: 14px; }
/* Gold "+" store-entry button at the right end of each pill. */
#home-currency .pill-plus {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  background: var(--clay-yellow);
  color: #5a3a00;
  font-weight: 900;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 0 var(--clay-yellow-dark), inset 0 1px 0 rgba(255, 255, 255, 0.55);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
#home-currency .pill-plus:active {
  transform: translateY(2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}

@media (max-height: 520px) {
  #home-currency .currency-pill { padding: 3px 4px 3px 20px; }
  #home-currency .pill-icon { width: 24px; height: 24px; left: -6px; }
  #home-currency .pill-value { font-size: 0.85rem; }
  #home-currency .pill-plus { width: 17px; height: 17px; font-size: 0.85rem; }
}

/* ==================== MATCH SCREEN — RING SEATING (2026-07) ====================
   Full-bleed board with players seated around an implied ring (UNO-style),
   replacing the old 3-row grid + pink mat plates. Shared by the practice
   (#screen-game) and online (#screen-online-game) boards — both use the same
   class names, only ids differ (online- prefix). LAYOUT ONLY: rules, turn/timer
   logic, the hand-fan mechanic and card art are untouched. Appended last so it
   overrides the old board rules above. */

/* The board itself is already the full-bleed screen bg (--clay-board-image,
   cover). Make the layout a plain positioning context and DISSOLVE the old
   center-board + side-panel wrappers so their children can ring the table. */
.game-layout { display: block; position: relative; padding: 0; }
.center-board, .board-info-panel, .board-state-panel { display: contents; }

/* Removed cues: the value/state pill by the right seat, central turn banners,
   and the per-seat NEXT/PLAYING text tags (active turn is a seat GLOW now). */
.state-card { display: none !important; }

/* --- Seats around the ring ------------------------------------------------- */
/* Seats shrink to their content (fit-content) and are click-through so their
   boxes never blanket the deck/hand; the chips themselves don't need clicks. */
#top-opponent-container, #online-top-opponent-container {
  /* Top-CENTRE, lifted to 13% (was 20%) to sit higher on the table. This now
     rides slightly ABOVE the play-table art's toy horizon (~18% at 16:9) - a
     deliberate trade for the extra breathing room over the centre pile. The
     seat is a short [chip | compact card row] element, so centring it never
     covers the deck/discard (pile is at 50%). */
  position: absolute; top: 13%; left: 50%; right: auto; transform: translateX(-50%);
  z-index: 4; margin: 0; padding: 0; display: flex; gap: 20px; justify-content: center;
  width: fit-content; pointer-events: none;
}
#left-opponent-container, #online-left-opponent-container {
  position: absolute; left: max(24px, env(safe-area-inset-left)); top: 30%; z-index: 4;
  width: fit-content; pointer-events: none;
}
#right-opponent-container, #online-right-opponent-container {
  position: absolute; right: max(24px, env(safe-area-inset-right)); top: 30%; z-index: 4;
  width: fit-content; pointer-events: none;
}
/* Top seat lays chip + card row side by side, hand to the RIGHT of the avatar
   box; the container centres the pair. Side seats keep the column (row below
   the box). */
#top-opponent-container .opponent-badge,
#online-top-opponent-container .opponent-badge {
  flex-direction: row; align-items: center; gap: 8px;
}
/* Neutralise the legacy .opponent-slot sizing (min-height 80 / width 100%
   centring) - ring seats size to their content. */
#top-opponent-container, #left-opponent-container, #right-opponent-container,
#online-top-opponent-container, #online-left-opponent-container, #online-right-opponent-container {
  min-height: 0;
}
.opponents-row { padding: 0; }

/* Each opponent SEAT: a chip stacked over a fanned face-down hand. The old
   pill styling on .opponent-badge is replaced by this transparent column. */
.opponent-badge {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: none; border: none; box-shadow: none; padding: 0; min-width: 0;
  position: relative; transition: transform 0.2s ease;
}
.opponent-badge.active-turn { transform: none; animation: none; }
.seat-chip {
  display: flex; align-items: center; gap: 8px;
  background: var(--clay-white); border: 3px solid var(--clay-white-dark);
  border-radius: 16px; padding: 6px 12px; box-shadow: var(--clay-shadow-out);
}
/* Active seat = gold glow (mockup), not a text tag. */
.opponent-badge.active-turn .seat-chip {
  border-color: var(--clay-yellow);
  animation: seatGlowPulse 1.4s ease-in-out infinite;
}
@keyframes seatGlowPulse {
  0%,100% { box-shadow: 0 0 0 3px rgba(252,196,25,0.45), 0 0 12px rgba(252,196,25,0.6), var(--clay-shadow-out); }
  50%     { box-shadow: 0 0 0 3px rgba(252,196,25,0.6),  0 0 22px rgba(252,196,25,0.9), var(--clay-shadow-out); }
}
/* Bigger + decisively SQUARE. The radius has to stay a small FRACTION of the
   box or it reads as a circle at seat size - the old 34px/13px was 38% and
   looked round; 46px/12px (26%) was still soft. ~17% is unmistakably square. */
.opponent-badge .avatar-holder { width: 58px; height: 58px; margin: 0; border-radius: 10px; }
.opponent-badge .avatar-holder .avatar-img { border-radius: 7px; }
/* Player's own seat avatar, match screens only - same square look, a step
   larger so your own seat still reads as the primary one. */
#screen-game .player-info-badge .avatar-holder,
#screen-online-game .player-info-badge .avatar-holder {
  width: 66px; height: 66px; border-radius: 12px;
}
#screen-game .player-info-badge .avatar-holder .avatar-img,
#screen-online-game .player-info-badge .avatar-holder .avatar-img { border-radius: 9px; }
/* Fixed name slot: 12ch = the server-enforced 12-char username cap (game-room
   .slice(0,12), input maxlength 12) at this font - same convention as
   .home-username. The chip is therefore a CONSTANT width regardless of the
   name; anything wider (defensive: bot "🤖 " prefix, legacy long names)
   ellipsizes via the base .opponent-name overflow rules. */
.opponent-badge .opponent-name { font-size: 0.82rem; width: 12ch; max-width: none; }
.opponent-card-count {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.8rem; font-weight: 800; margin: 0; color: var(--clay-dark);
}
.seat-count-back {
  width: 12px; height: 16px; border-radius: 2px;
  background: url("assets/cards/card-back-paw.webp") center / contain no-repeat;
  filter: drop-shadow(1px 1px 1px rgba(0,0,0,0.25)); flex-shrink: 0;
}

/* Compact overlapping card row (replaced the fan, which collided with the
   centre pile on narrow phones): backs in a horizontal line, each overlapping
   the previous by ~58% - 7 cards ≈ a 3-card footprint (34 + 6x14 = 118px). */
.opponent-hand-row { display: flex; margin-top: 2px; }
.row-back {
  width: 34px; height: 48px; flex-shrink: 0;
  background: url("assets/cards/card-back-paw.webp") center / contain no-repeat;
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.3));
}
.row-back + .row-back { margin-left: -20px; } /* ~58% overlap */
.opponent-badge .opponent-status-tag { bottom: -8px; }

/* --- Center: deck + discard + direction cue -------------------------------- */
/* 50%: the play-table art's sculpted mat circle is centred at ~52% of the
   image, so the pile anchors mid-screen to sit inside the circle (45% rode up
   onto the circle's top rim). */
.play-area { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 3; }
/* Direction label ("Turn" + a glyph spinning in the play direction - the words
   Clockwise/Counter-Clockwise were redundant). Sits to the LEFT of the deck,
   vertically centred on it (was tucked under the pile). Anchored by `right`
   off the midline so it hangs outward from the deck: 185px clears both the
   deck's own half-width (~130px at the 110px card size + 40px gap) and the
   translucent dish behind it (.play-area::before, 350px wide = 175px half).
   The layout is landscape (~740px wide at the short-height floor), leaving
   ~185px of room to its left - it does not crowd the left seat, which is
   pinned to the viewport edge at top 30%. */
.direction-indicator {
  position: absolute; top: 50%; right: calc(50% + 185px); left: auto;
  transform: translateY(-50%);
  z-index: 3; margin: 0; background: var(--clay-white); box-shadow: var(--clay-shadow-out);
  color: var(--clay-red-dark); font-size: 0.78rem; white-space: nowrap;
}
.deck-count-badge { color: #fff; }

/* --- Timer promoted top-left (online only) --------------------------------- */
#online-turn-indicator-row {
  position: absolute; top: max(10px, env(safe-area-inset-top));
  left: calc(max(12px, env(safe-area-inset-left)) + 58px); /* clear the home chip */
  z-index: 12; margin: 0; flex-direction: row; align-items: center;
}
.turn-indicator-row .turn-indicator { display: none; }

/* --- Your seat (bottom): YOUR-TURN chip left, hand centre, DRAW right ------- */
.player-panel {
  position: absolute; left: 0; right: 0; bottom: max(6px, env(safe-area-inset-bottom));
  z-index: 5; display: grid; grid-template-columns: 1fr auto 1fr; align-items: end;
  padding: 0 12px; gap: 8px; height: auto;
}
.player-info-badge { align-self: end; justify-self: start; position: relative; }
.player-info-badge.active-turn::after {
  content: "YOUR TURN"; position: absolute; top: -13px; left: 50%; transform: translateX(-50%);
  background: var(--clay-green); color: #fff; font-size: 0.55rem; font-weight: 800;
  letter-spacing: 0.05em; padding: 2px 10px; border-radius: 9px; white-space: nowrap;
  box-shadow: 0 2px 5px rgba(0,0,0,0.22);
}
.player-controls { justify-self: end; align-self: end; }

/* Short landscape heights (real phones ~740x360 and shorter): the top-seat +
   center pile + bottom hand vertical stack overcrowds. Reclaim it by shrinking
   the CENTER PILE and OPPONENT FANS first (both are just face-down card-backs -
   legibility doesn't matter) and lifting the ring higher. The bottom hand (your
   own cards, what you read + tap) is deliberately NOT shrunk here. Side seats
   already clear the center horizontally, so they aren't thinned - only sized
   down a touch. */
@media (max-height: 430px) {
  /* Center deck + discard shrink FIRST + most (5:7 kept) - took a second cut
     (68->60px) when the top seat moved below the play-table art's horizon. */
  .clay-deck-stack, .discard-container { width: 60px; height: 84px; }
  .discard-pile .clay-card-element { width: 60px; height: 84px; }
  /* Height-adaptive pile anchor: the free band between the (now horizon-
     cleared) top seat and the protected hand shifts with viewport height -
     67.5vh-110px tracks its midpoint (=40% at 400h, ~37% at the 360 floor),
     splitting the unavoidable floor overlap evenly instead of sinking the
     pile into the hand. */
  .play-area { top: calc(67.5vh - 110px); gap: 22px; }
  .play-area::before, .direction-ring { width: 192px; height: 106px; }
  .direction-ring { --orbit-rx: 96px; --orbit-ry: 53px; }
  /* Tracks the pile's height-adaptive anchor (same calc as .play-area above)
     so it stays vertically centred on the deck; 105px clears the shrunken
     deck (60px cards + 22px gap = ~142 wide) and its 192px dish. */
  .direction-indicator {
    top: calc(67.5vh - 110px); right: calc(50% + 105px);
    font-size: 0.66rem; padding: 2px 8px;
  }
  /* Attack pill mirrors it on the far side of the pile, same anchor. */
  .attack-card {
    top: calc(67.5vh - 110px); left: calc(50% + 105px);
    padding: 6px 13px !important; gap: 6px;
  }
  .attack-card .attack-amount { font-size: 1.15rem; }
  .attack-card .attack-icon-img { height: 1.45rem; }
  .deck-count-badge { font-size: 0.68rem; margin-top: 3px; padding: 1px 8px; }

  /* Bottom hand: protected - shrunk LAST and LEAST (~15%), just enough to
     unstack it from the center. Kept the largest of the three card sizes. */
  .player-hand-scroll .clay-card-element,
  #online-player-hand .clay-card-element { width: 94px; height: 131px; margin-left: -44px; }

  /* Opponent card rows + seat chips compact (rows shrink with the pile to pay
     for the top seat sitting below the art's toy horizon). */
  .row-back { width: 24px; height: 34px; }
  .row-back + .row-back { margin-left: -14px; } /* keeps the ~58% overlap */
  .seat-chip { padding: 3px 8px; gap: 6px; border-radius: 13px; }
  .opponent-badge .opponent-name { font-size: 0.68rem; width: 12ch; }
  .opponent-card-count { font-size: 0.68rem; }
  .seat-count-back { width: 10px; height: 13px; }
  /* Below the horizon even at the floor: cover-fit crops the wide/short
     viewport's image top, so the horizon ends at ~13-14.5% here, not 18%.
     Stays top-centre (short seat, above the pile). Lifted with the base rule. */
  #top-opponent-container, #online-top-opponent-container { top: 9vh; }
  /* Compact-height avatars: bigger than before, still small enough to fit.
     Radius scales down with the box to hold the square read (~17%). */
  .opponent-badge .avatar-holder { width: 42px; height: 42px; border-radius: 8px; }
  .opponent-badge .avatar-holder .avatar-img { border-radius: 5px; }
  #screen-game .player-info-badge .avatar-holder,
  #screen-online-game .player-info-badge .avatar-holder { width: 50px; height: 50px; border-radius: 9px; }
  #screen-game .player-info-badge .avatar-holder .avatar-img,
  #screen-online-game .player-info-badge .avatar-holder .avatar-img { border-radius: 6px; }
  #left-opponent-container, #online-left-opponent-container,
  #right-opponent-container, #online-right-opponent-container { top: 25%; }
}
