/* ================================================================
   TAROT — Main Stylesheet
   Architecture: CSS Variables → Base → Layout → Components → Spreads → Responsive
   ================================================================ */

/* ── 1. Local aliases over the shared Lunaris tokens ── */
/* assets/css/lunaris.css must be loaded first — it owns the palette. */
:root {
  /* Colors — all resolved from the shared design system */
  --color-bg:          var(--ink);
  --color-bg-2:        var(--deep);
  --color-surface:     var(--surface);
  --color-surface-2:   var(--surface-2);
  --color-border:      var(--line-soft);
  --color-border-2:    var(--line);
  --color-gold:        var(--gold);
  --color-gold-dim:    var(--line-strong);
  --color-gold-glow:   rgba(201, 169, 110, 0.15);
  --color-text:        var(--text);
  --color-text-muted:  var(--text-muted);
  --color-text-faint:  var(--text-faint);
  --color-accent:      var(--violet);

  /* Card */
  /* Deck aspect — Sola Busca scans are 474x877 (h/w = 1.85) */
  --card-aspect: 474 / 877;
  --card-radius: 11px;


  /* Stage — the room a spread actually gets inside the board panel. The page
     scrolls like the other tabs, so the board takes a fixed slice of the
     viewport rather than whatever is left over. */
  /* Shell width, minus the 288px picker column, the 16px gap and the board
     panel's own 18px padding either side. */
  --stage-w: calc(min(1500px, 100vw - 48px) - 340px);
  /* 224px = shell padding (40) + topbar (68) + board padding & stage gutter
     (64) + footer (52). Everything else is sized from this, so the page fits
     one screen and never scrolls. */
  --stage-h: clamp(320px, calc(100dvh - 224px), 940px);
  /* Slot captions hang below the frame, so the frame itself gets a little
     less than the stage — otherwise the board sprouts a scrollbar. 30px is
     the tallest caption block any spread uses (the 3x3 grid's). */
  --stage-fit: calc(var(--stage-h) - 30px);

  /* The 3x3 grid is the ceiling: no spread draws a card wider than it does.
     0.1456 = its --cw (22.2%) x its --ar (0.656); 173px = 22.2% of its
     --max-w (780px). Sparse spreads divide this by their own --cw. */
  --card-cap: min(calc(var(--stage-fit) * 0.1456), 173px);

  /* Shadows */
  --shadow-card:
    0 12px 38px rgba(14, 6, 34, 0.58),
    0 3px 12px rgba(14, 6, 34, 0.40),
    0 0 26px rgba(107, 63, 160, 0.18);
  --shadow-card-hover: 0 12px 40px rgba(0, 0, 0, 0.7), 0 0 20px rgba(201, 169, 110, 0.18);
  --shadow-panel: var(--shadow-lift);

  /* Card flip — slow start, long soft landing */
  --tr-flip: 0.72s cubic-bezier(0.45, 0.05, 0.15, 1);

  /* Fonts */
  --font-heading: var(--font-display);
}

/* ── 2. Reset & Base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  min-height: 100%;
  font-size: 14px;
}

button {
  font-family: var(--font-body);
  cursor: pointer;
  border: none;
  background: none;
  color: inherit;
}

img {
  display: block;
  max-width: 100%;
  height: 100%;
  width: 100%;
  object-fit: cover;
}

/* ── 4. Page shell ── */
/* Same skeleton as the tử vi page: a centred scrolling column with the shared
   .topbar / .panel / .site-footer chrome, and a .workspace grid under it. */
.app-shell {
  position: relative;
  z-index: 1;
  width: min(1500px, calc(100% - 32px));
  margin: 0 auto;
  padding: 20px 0 20px;
  opacity: 0;
  transition: opacity 0.6s var(--ease-out);
}
.app-shell.app--ready { opacity: 1; }
.app-shell.app--ready .modes,
.app-shell.app--ready .board { animation: lun-rise 0.7s var(--ease-out) backwards; }
.app-shell.app--ready .board { animation-delay: 90ms; }

.topbar { margin-bottom: 16px; }

.workspace {
  display: grid;
  grid-template-columns: 288px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

/* ── 5. Section headings (mirrors horoscope/css/style.css) ── */
.section-title { margin-bottom: 14px; }

.modes h1 {
  font-family: var(--font-heading);
  font-size: 25px;
  line-height: 1.06;
  background: linear-gradient(160deg, var(--gold-pale) 18%, var(--gold) 56%, var(--gold-light) 86%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ── 6. Left panel: spread picker + deck actions ── */
.modes {
  position: sticky;
  top: 16px;
  padding: 18px;
}

.mode-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.mode-btn {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  text-align: left;
  transition: background var(--tr-base), border-color var(--tr-base), transform var(--tr-fast);
}
/* The active gradient sits on a layer that fades in — a gradient
   background itself cannot transition, so it used to snap. */
.mode-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(135deg, rgba(201, 169, 110, 0.18), rgba(107, 63, 160, 0.12));
  opacity: 0;
  transition: opacity var(--tr-base);
}
.mode-btn:hover {
  background: var(--color-surface-2);
  border-color: var(--color-border-2);
}
.mode-btn:active { transform: scale(0.985); transition-duration: 0.08s; }
.mode-btn.active { border-color: var(--line-strong); }
.mode-btn.active::before { opacity: 1; }
.mode-name { transition: color var(--tr-base); }
.mode-btn.active .mode-name { color: var(--color-gold); }

.mode-icon {
  flex: 0 0 auto;
  width: 56px;
  height: 46px;
  object-fit: contain;
  filter: brightness(1.9) drop-shadow(0 0 5px rgba(201, 169, 110, 0.55));
  transition: opacity var(--tr-base), transform var(--tr-slow);
}
.mode-btn:hover .mode-icon,
.mode-btn.active .mode-icon { filter: brightness(2.2) drop-shadow(0 0 8px rgba(232, 213, 163, 0.8)); }
.mode-btn:hover .mode-icon { transform: scale(1.12); }

.mode-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.mode-name {
  font-size: 13px;
  color: var(--color-text);
}
.mode-count {
  font-size: 11px;
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deck-actions { margin-top: 16px; }
.deck-actions .primary-button { width: 100%; }
.btn-icon { filter: brightness(1.9) drop-shadow(0 0 4px rgba(201, 169, 110, 0.6)); width: 20px; height: 20px; margin-right: 6px; vertical-align: -3px; }
.modal-card-symbol { width: 72px; height: 72px; opacity: 0.85; }
.suit-icon { width: 20px; height: 20px; margin-right: 6px; vertical-align: -5px; }
.ex-group h3 .suit-icon { width: 24px; height: 24px; }
.deck-actions .ask-ai-button {
  width: 100%;
  justify-content: center;
  min-height: 40px;
  margin-top: 10px;
}

.deck-hint {
  margin-top: 12px;
  color: var(--color-text-faint);
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}

/* Tighter than the shared default — the page has one screen to live in. */
.site-footer { margin-top: 16px; padding-top: 16px; }

.primary-button.btn-active { animation: btn-pulse 0.32s var(--ease-out); }
@keyframes btn-pulse {
  0%   { transform: scale(1); }
  50%  { transform: scale(0.96); }
  100% { transform: scale(1); }
}

/* ── 7. Right panel: the board ── */
.board {
  padding: 18px;
  min-width: 0;
}

/* ── 8. Spread stage ── */
#spread-area {
  display: flex;
  align-items: center;
  align-items: safe center;
  justify-content: center;
  justify-content: safe center;
  /* +28px so the bottom row's captions, which hang below the frame,
     have somewhere to land instead of being clipped. */
  height: calc(var(--stage-h) + 28px);
  padding: 14px;
  overflow: auto;
  border: 1px solid rgba(201, 169, 110, 0.07);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(120% 86% at 50% 6%, rgba(107, 63, 160, 0.26), transparent 64%),
    radial-gradient(90% 70% at 50% 104%, rgba(201, 169, 110, 0.075), transparent 72%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008));
  box-shadow: inset 0 0 90px rgba(9, 5, 22, 0.5);
}

/* ── 10. Spread Container (base) ── */
/* Each spread only declares its shape (--ar = width/height), how wide a card
   is inside it (--cw) and sane caps. The frame then grows to whichever of the
   available width / height runs out first, so nothing is left unused. */
.spread {
  position: relative;
  z-index: 1;
  aspect-ratio: var(--ar);
  width: clamp(
    var(--min-w, 260px),
    min(var(--stage-w), calc(var(--stage-fit) * var(--ar))),
    var(--max-w, 1400px)
  );
}

/* Switching spreads (see gatherAndShuffle in app.js): while the old cards
   are swept into a pile, nothing on the table takes input or shows labels. */
.spread--gathering .card-slot { pointer-events: none; }
.spread--gathering .card-label { opacity: 0; }

#spread-area { position: relative; }

/* Sparks flung out as a spread is dealt (spawned by sparkle() in app.js). */
.deal-spark {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  width: var(--s, 5px);
  height: var(--s, 5px);
  margin: calc(var(--s, 5px) / -2) 0 0 calc(var(--s, 5px) / -2);
  border-radius: 50%;
  background: #fff4d6;
  box-shadow: 0 0 8px 2px rgba(232, 197, 124, 0.9), 0 0 18px 4px rgba(201, 169, 110, 0.45);
  pointer-events: none;
}

/* ── 11. Card Slot (base) ── */
/* No dragging and no text selection on the board: a native drag started by a
   fast click never finishes here and leaves the tab deaf to all input. */
.card-slot,
.card-slot img,
#spread-area {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}

.card-slot {
  position: absolute;
  /* width set per spread via --cw; height via aspect-ratio */
  width: var(--cw, 10%);
  aspect-ratio: var(--card-aspect);
  transform: translate(-50%, -50%);
  cursor: pointer;
  /* perspective for 3D flip */
  perspective: 900px;
  perspective-origin: 50% 50%;
  /* Hover lift uses the standalone `translate` property so it composes with
     the positioning / deal `transform` instead of fighting it. */
  transition: translate 0.4s var(--ease-out);
}

/* Hover glow — via box-shadow on the faces, not filter on the slot. A filter
   forces the browser to flatten and re-rasterise the card's 3D subtree. */
.card-slot:hover,
.card-slot:focus-visible { z-index: 5; }
.card-slot:focus-visible { outline: none; }
.card-slot:focus-visible .card-face {
  box-shadow: var(--shadow-card), 0 0 0 2px var(--gold);
}
@media (hover: hover) {
  .card-slot:hover { translate: 0 -5px; }
}

.card-slot:hover .card-face {
  box-shadow:
    var(--shadow-card),
    0 0 0 1px rgba(232, 213, 163, 0.34),
    0 0 34px 6px rgba(201, 169, 110, 0.34);
}

/* Cross card (Celtic Cross card #2) — rotated 90° */
.card-slot--cross {
  transform: translate(-50%, -50%) rotate(90deg);
  z-index: 2;
}

/* ── 12. Card Inner (3D flip container) ── */
.card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform var(--tr-flip);
  border-radius: var(--card-radius);
  will-change: transform;
}

/* Flipped state — the card also lifts off the table mid-turn and settles
   back, which reads far more like a real card than a flat spin. */
.card-inner.flipped {
  transform: rotateY(180deg);
  animation: card-flip-lift 0.72s var(--ease-in-out);
}
@keyframes card-flip-lift {
  45% { scale: 1.09; }
}

/* lunaris.css zeroes every transition under prefers-reduced-motion (e.g.
   Windows "Animation effects" off), which made the flip snap instantly. The
   flip is user-triggered and is the page's core interaction, so keep it. */
@media (prefers-reduced-motion: reduce) {
  .card-slot .card-inner {
    transition-duration: 0.72s !important;
  }
}

/* ── 13. Card Faces ── */
.card-face {
  position: absolute;
  inset: 0;
  border-radius: var(--card-radius);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--tr-slow);
}

.card-back {
  background: var(--ink);
}
.card-back img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-front {
  transform: rotateY(180deg);
  background: var(--deep);
  /* lets .card-name size itself from the card width via cq units */
  container-type: inline-size;
}
.card-front img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* Card name caption — only visible once the card is face-up, since it
   lives on the front face (the back hides it via backface-visibility). */
.card-name {
  position: absolute;
  inset: auto 0 0 0;
  padding: 26% 7% 7%;
  font-family: var(--font-heading);
  font-size: 10px; /* fallback where container units are unsupported */
  font-size: clamp(9px, 10.5cqw, 24px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.05em;
  text-align: center;
  /* Opaque right behind the text so the name stays readable, then a long
     warm fade upward — a hard-edged black slab read cold and harsh. */
  color: var(--gold-light);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95), 0 0 16px rgba(201, 169, 110, 0.3);
  background: linear-gradient(
    to top,
    rgba(13, 7, 26, 0.95) 0%,
    rgba(13, 7, 26, 0.90) 32%,
    rgba(13, 7, 26, 0.62) 58%,
    rgba(13, 7, 26, 0.24) 80%,
    rgba(13, 7, 26, 0) 100%
  );
  pointer-events: none;
}

.card-name-rev {
  display: block;
  margin-top: 0.15em;
  font-family: var(--font-body);
  font-size: 0.78em;
  letter-spacing: 0.1em;
  color: var(--color-accent);
}

/* Revealed glow */
.card-revealed .card-inner {
  box-shadow: 0 0 0 1px var(--color-gold-dim);
}

/* Card name placeholder (when no image) */
.card-name-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 8px;
  font-family: var(--font-heading);
  font-size: 11px;
  text-align: center;
  color: var(--color-gold);
  line-height: 1.4;
  background: linear-gradient(160deg, var(--plum), var(--ink));
  white-space: pre-wrap;
}

/* ── 14. Card Label ── */
.card-label {
  position: absolute;
  bottom: calc(-1 * var(--label-gap, 18px));
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 170px;
  font-size: var(--label-fs, 10px);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(216, 207, 240, 0.5);
  text-align: center;
  white-space: nowrap;
  text-shadow: 0 0 12px rgba(107, 63, 160, 0.5);
  pointer-events: none;
  transition: color var(--tr-base), opacity var(--tr-fast);
}
.card-slot:hover .card-label,
.card-revealed .card-label {
  color: var(--color-gold);
}

/* Cross card: the label keeps the base placement and turns with the card, so
   it runs parallel to .card-name just past the card's bottom edge. */

/* ── 15. Card Dealing Animations ── */
/* Each card flies out of the pile at the table's centre (--fx/--fy, set per
   slot in dealCards) along an arc: it rises and spins at the apex, then
   drops into place with a small settle. Only the standalone translate /
   rotate / scale properties move, so the slot's positioning transform — and
   the Celtic cross card's 90deg turn — stay untouched.
   Fill is `backwards`, not `both`: once landed the card must hand
   `translate` back to the hover lift. */
@keyframes card-fly {
  0% {
    opacity: 0;
    translate: var(--fx, 0px) var(--fy, 0px);
    rotate: var(--fr, 0deg);
    scale: 0.5;
    animation-timing-function: cubic-bezier(0.3, 0, 0.45, 1);
  }
  10% { opacity: 1; }
  55% {
    translate: calc(var(--fx, 0px) * 0.3) calc(var(--fy, 0px) * 0.3 - 34px);
    rotate: calc(var(--fr, 0deg) * -0.35);
    scale: 1.1;
    animation-timing-function: cubic-bezier(0.25, 0.8, 0.3, 1);
  }
  85% { scale: 0.98; }
  100% {
    opacity: 1;
    translate: 0px 0px;
    rotate: 0deg;
    scale: 1;
  }
}

.card-slot.card-dealing {
  animation: card-fly 0.64s backwards;
  animation-delay: var(--deal-delay, 0ms);
}
/* Its glow flares while it is in the air. */
.card-slot.card-dealing .card-face {
  animation: card-fly-glow 0.64s var(--ease-out) backwards;
  animation-delay: var(--deal-delay, 0ms);
}
@keyframes card-fly-glow {
  0%, 40% {
    box-shadow:
      var(--shadow-card),
      0 0 0 1px rgba(232, 213, 163, 0.5),
      0 0 38px 8px rgba(201, 169, 110, 0.45);
  }
}

/* ── 16. Spread Mode Sizes ── */
/* --ar  frame width / height          --cw  card width, % of frame width
   --min-w  below this the stage scrolls instead of shrinking further
   Cards are 474x877 scans (h = 1.85 x w), which is what drives every ratio. */

/* 1 Card — the frame is the card, so the cap applies directly */
.spread-1card {
  --ar: 0.46;
  --cw: 100%;
  --min-w: 110px;
  --max-w: var(--card-cap);
  --label-gap: 16px;
  --label-fs: 11px;
}

/* 3 Card */
.spread-3card {
  --ar: 1.80;
  --cw: 24%;
  --max-w: calc(var(--card-cap) / 0.24);
  --label-gap: 18px;
  --label-fs: 11px;
}

/* Horseshoe (7 cards in an arc) */
.spread-horseshoe {
  --ar: 1.62;
  --cw: 12%;
  --max-w: calc(var(--card-cap) / 0.12);
  --label-gap: 14px;
  --label-fs: 9px;   /* neighbours are close — keep captions inside the card */
}

/* 9 Card (3x3) */
.spread-9card {
  --ar: 0.656;
  --cw: 22.2%;
  --max-w: 780px;
  --label-gap: 16px;
}

/* Celtic Cross — the staff wraps into 2x2 (see config.js), which turns the
   spread landscape: 3 cards deep instead of 4, so the cards get bigger and
   the whole thing clears the stage height. */
.spread-celtic {
  --ar: 1.10;
  --cw: 13%;
  --max-w: 1160px;
  --label-gap: 8px;
  --label-fs: 9px;
}

/* 12 Houses — a wide ellipse with the 3- and 9-o'clock cards pushed further
   out (see config.js); that sideways room is what frees the cards to grow. */
.spread-12houses {
  --ar: 1.50;
  --cw: 11.6%;
  --max-w: 1160px;
  --label-gap: 6px;
  --label-fs: 9.5px;
}

/* ── 17. Loading State ── */
.spread-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--color-text-muted);
  font-size: 12px;
  letter-spacing: 0.1em;
}

/* Slot placeholder (before deal) */
.card-slot::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--card-radius);
  border: 1px solid rgba(201, 169, 110, 0.10);
  background: rgba(255, 255, 255, 0.022);
  pointer-events: none;
  transition: border-color var(--tr-base);
}
.card-slot:hover::before { border-color: var(--color-gold-dim); }
.card-slot.card-dealing::before,
.card-slot.card-revealed::before { border: none; }

/* Slot number badge */
.card-slot::after {
  content: attr(data-number);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: var(--color-border-2);
  pointer-events: none;
  transition: opacity var(--tr-base);
}
.card-slot.card-dealing::after,
.card-slot.card-revealed::after { opacity: 0; }

/* ── 18. Modal ── */
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s var(--ease-out), visibility 0s linear 0.28s;
}

.modal.modal--open {
  pointer-events: auto;
  opacity: 1;
  visibility: visible;
  transition: opacity 0.28s var(--ease-out), visibility 0s;
}

.modal-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(4px);
}

.modal-content {
  position: relative;
  z-index: 1;
  display: flex;
  gap: var(--gap-lg);
  background: var(--panel-solid);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  backdrop-filter: blur(18px);
  padding: var(--gap-lg);
  max-width: 520px;
  width: calc(100% - 40px);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.7);
  /* Driven by .modal--open so it plays on every open (and reverses on
     close). The old keyframe animation only ever ran once, at page load,
     while the modal was still hidden. */
  transform: translateY(18px) scale(0.94);
  transition: transform 0.3s var(--ease-out);
}
.modal--open .modal-content {
  transform: none;
  transition: transform 0.46s var(--ease-spring);
}

.modal-card-image,
.modal-card-info { transition: opacity 0.4s var(--ease-out), transform 0.5s var(--ease-out); }
.modal:not(.modal--open) .modal-card-image { opacity: 0; transform: translateX(-10px); }
.modal:not(.modal--open) .modal-card-info  { opacity: 0; transform: translateX(10px); }
.modal--open .modal-card-info { transition-delay: 0.06s; }

.modal-close {
  position: absolute;
  top: 12px; right: 12px;
  width: 40px; height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  color: var(--color-text-muted);
  transition: background var(--tr-fast), color var(--tr-fast);
}
.modal-close:hover { background: var(--color-surface-2); color: var(--color-text); }

.modal-card-image {
  flex-shrink: 0;
  width: 120px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  background: var(--deep);
  aspect-ratio: var(--card-aspect);
}
.modal-card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}
.modal-no-image {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  color: var(--color-gold-dim);
}

.modal-card-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  padding-right: 24px;
}
.modal-reversed-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.modal-reversed-badge.is-reversed {
  color: var(--red);
}
#modal-card-name {
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: 500;
  color: var(--color-gold);
  line-height: 1.3;
}
.modal-position {
  font-size: 12px;
  color: var(--color-text-muted);
  letter-spacing: 0.06em;
}

/* ── 21. Responsive ── */

/* Not enough room for two columns — stack, and lay the picker out as a grid */
@media (max-width: 980px) {
  .workspace { grid-template-columns: minmax(0, 1fr); }
  .modes { position: static; }
  .modes h1 { font-size: 22px; }
  .mode-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(176px, 1fr));
    gap: var(--gap-sm);
  }
  .deck-actions .primary-button { width: auto; min-width: 220px; }
  .deck-actions .ask-ai-button { width: auto; margin: 0 0 0 10px; }

  :root { --stage-w: calc(min(1500px, 100vw - 48px) - 36px); }
}

@media (max-width: 640px) {
  .app-shell { width: calc(100% - 20px); padding: 16px 0 24px; }
  .topbar { flex-wrap: wrap; gap: var(--gap-sm); }
  .topbar-actions { gap: 6px; }
  .status-chip, .home-button { padding: 7px 11px; font-size: 12px; }

  .modes, .board { padding: var(--gap-md); }
  .modes h1 { font-size: 19px; }
  .mode-count { display: none; }
  .deck-actions .primary-button { width: 100%; }

  /* The board grows to fit here rather than scrolling inside itself, so the
     stage can be far taller than the viewport — that buys card size, and the
     page just scrolls the way any phone page does. */
  :root {
    --stage-w: calc(100vw - 58px);
    --stage-h: clamp(420px, calc(100dvh - 150px), 1000px);
  }

  /* A phone cannot show ten or twelve cards at a readable size, so here the
     dense spreads do get a floor and the stage pans sideways. The single card
     gets one too — matching the 3x3 grid's card size makes no sense when
     there is only one card on the table. */
  .spread-1card     { --min-w: 170px; }
  .spread-3card     { --min-w: 320px; }
  .spread-horseshoe { --min-w: 620px; }
  .spread-9card     { --min-w: 380px; }
  .spread-celtic    { --min-w: 600px; }
  .spread-12houses  { --min-w: 760px; }

  /* Let the panel grow instead of scrolling inside itself — one scroll
     context reads far better on a phone than a box within a page. */
  #spread-area {
    height: auto;
    min-height: calc(var(--stage-h) + 28px);
  }

  /* Modal */
  .modal-content {
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--gap-md);
  }
  .modal-card-image { width: 90px; }
  .modal-card-info { padding-right: 0; align-items: center; }
  #modal-card-name { font-size: 15px; }
}

/* ── 22. View tabs + Explore ── */
.view-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--color-border);
}
.view-tab {
  padding: 11px 18px;
  min-height: 44px;
  font-size: 14px;
  color: var(--color-text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--tr-fast), border-color var(--tr-fast);
}
.view-tab:hover { color: var(--color-text); }
.view-tab.active { color: var(--color-gold); border-bottom-color: var(--color-gold); }

.explore { padding: 22px; }
.explore[hidden], .workspace[hidden] { display: none; }

.explore-head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 22px;
}
.explore-head h2 {
  font-family: var(--font-heading);
  font-size: 25px;
  line-height: 1.1;
  color: var(--color-gold);
}
.explore-head p { margin-top: 6px; max-width: 52ch; color: var(--color-text-muted); line-height: 1.55; }
.explore-filters { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  min-height: 34px;
  padding: 6px 13px;
  font-size: 12.5px;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border-2);
  border-radius: var(--radius-pill);
  transition: color var(--tr-fast), border-color var(--tr-fast), background var(--tr-fast);
}
.chip:hover { color: var(--color-text); border-color: var(--line-strong); }
.chip.active { color: var(--ink); background: var(--color-gold); border-color: var(--color-gold); }

.ex-group + .ex-group { margin-top: 28px; }
.ex-group h3 {
  margin-bottom: 12px;
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 600;
  color: var(--color-text);
}
.ex-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 14px 12px;
}
.ex-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  text-align: left;
  font-size: 12px;
  line-height: 1.3;
  color: var(--color-text-muted);
  transition: color var(--tr-fast);
}
.ex-card img {
  width: 100%;
  aspect-ratio: var(--card-aspect);
  object-fit: cover;
  border-radius: 6px;
  background: var(--deep);
  border: 1px solid var(--color-border);
  transition: transform var(--tr-base), border-color var(--tr-fast);
}
.ex-card:hover { color: var(--color-gold); }
.ex-card:hover img { transform: translateY(-3px); border-color: var(--line-strong); }
.ex-card:active img { transform: scale(0.97); transition-duration: 0.08s; }

/* Detail dialog */
.detail-content { max-width: 720px; max-height: calc(100dvh - 40px); }
.detail-content .modal-card-image { width: 170px; align-self: flex-start; }
.detail-body {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  padding-right: 28px;
  line-height: 1.65;
  color: var(--color-text-muted);
}
.detail-suit { font-size: 12px; color: var(--color-text-faint); }
.detail-body h3 {
  margin: 2px 0 12px;
  font-family: var(--font-heading);
  font-size: 22px;
  font-weight: 500;
  color: var(--color-gold);
}
.detail-body h4 { margin: 16px 0 4px; font-size: 13px; font-weight: 600; color: var(--color-text); }
.detail-body h4.is-reversed { color: var(--red); }
.detail-keywords { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; }
.detail-keywords li {
  padding: 3px 11px;
  font-size: 12px;
  color: var(--gold-light);
  background: var(--color-gold-glow);
  border-radius: var(--radius-pill);
}
.detail-related { display: flex; flex-wrap: wrap; gap: 6px; }

@media (max-width: 640px) {
  .explore { padding: var(--gap-md); }
  .explore-head h2 { font-size: 20px; }
  .ex-cards { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
  .detail-content { flex-direction: column; align-items: center; overflow-y: auto; }
  .detail-content .modal-card-image { width: 110px; align-self: center; }
  .detail-body { overflow: visible; padding-right: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ex-card img { transition: none; }
}

/* Touch: chips and filters reach the 44px target. */
@media (pointer: coarse) {
  .chip { min-height: 44px; padding-inline: 16px; }
  .explore-filters, .detail-related { gap: 8px; }
}

/* Heading face (Cormorant SC) runs small and light: size/weight tuned per use. */
:root { --heading-weight: 700; }
.modes h1, .explore-head h2 { font-size: 31px; font-weight: var(--heading-weight); letter-spacing: 0.04em; }
.ex-group h3 { font-size: 19px; font-weight: var(--heading-weight); letter-spacing: 0.05em; color: var(--color-gold-light, var(--gold-light)); }
.detail-body h3 { font-size: 28px; font-weight: var(--heading-weight); letter-spacing: 0.04em; }
#modal-card-name { font-size: 22px; font-weight: var(--heading-weight); letter-spacing: 0.04em; }

/* Chips: icon beside label; active = gold outline on a tinted fill so the gold icon stays visible. */
.chip { display: inline-flex; align-items: center; gap: 7px; }
.chip.active { color: var(--gold-light); background: rgba(201, 169, 110, 0.16); border-color: var(--color-gold); }
.chip .suit-icon { width: 26px; height: 26px; margin: 0; flex: none; filter: brightness(1.9) drop-shadow(0 0 4px rgba(201, 169, 110, 0.6)); }
.ex-group h3 { display: flex; align-items: center; gap: 10px; }
.ex-group h3 .suit-icon { width: 34px; height: 34px; margin: 0; filter: brightness(1.9) drop-shadow(0 0 6px rgba(201, 169, 110, 0.7)); }
