/* Qualia v2 components, shared by every v2 screen. Built only from tokens.css. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100dvh;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--text-m) / var(--leading) var(--font-ui);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
img { display: block; max-width: 100%; }
button, input, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }

.display {
  font-family: var(--font-display);
  font-weight: 600;
  font-variation-settings: "SOFT" 100, "WONK" 1;
  letter-spacing: -0.02em;
  line-height: var(--leading-tight);
}
.muted { color: var(--ink-2); }
.tiny { font-size: var(--text-xs); color: var(--ink-3); letter-spacing: 0.02em; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* --- Buttons -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: var(--tap);
  padding: 0 var(--s5);
  border: 0;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: var(--text-m);
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease-out), background var(--dur-1), opacity var(--dur-2);
  touch-action: manipulation;
  user-select: none;
  text-decoration: none;
}
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.45; pointer-events: none; }
.btn-primary {
  min-height: 58px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: var(--text-l);
  box-shadow: 0 6px 18px rgba(212, 69, 27, 0.35);
}
.btn-primary:active { background: var(--accent-press); }
.btn-dark { background: var(--ink); color: var(--paper); }
.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--line); }
.btn-block { width: 100%; }
.btn-icon {
  width: var(--tap); padding: 0; flex: none;
  background: var(--paper-2); color: var(--ink);
}
.btn .price { font-weight: 500; opacity: 0.85; }

/* a picture that failed twice (lib/ui.js): a blank face, not the browser's "?" icon */
img.img-failed { visibility: hidden; }

/* A quiet line to reach a person, under a bought deck and its order page. Not a button. */
.help-line { text-align: center; margin: var(--s8) 0 var(--s4); font-size: var(--text-xs); color: var(--ink-3); }
.help-line a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.help-line a:hover { color: var(--ink); }

/* --- Chips ---------------------------------------------------------------------------- */
.chips {
  display: flex; gap: var(--s2);
  overflow-x: auto; scrollbar-width: none;
  margin: 0 calc(-1 * var(--s5)); padding: 2px var(--s5);
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--s5);
}
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex: none;
  min-height: 38px;
  padding: 0 var(--s4);
  border: 0; border-radius: var(--radius-pill);
  background: var(--card);
  box-shadow: var(--shadow-1);
  font-size: var(--text-s); font-weight: 500;
  white-space: nowrap; cursor: pointer;
  scroll-snap-align: start;
  transition: transform var(--dur-1) var(--ease-out);
}
.chip:active { transform: scale(0.95); }
.chip .emoji { margin-right: 6px; }
/* the idea conveyor (lib/ideas.js): one row drifting left, fading out at both edges; ideas.js
   moves .chips-track with a transform. Room above and below for the chips' shadows. */
.chips.is-conveyor {
  --fade: 28px;
  display: block; overflow: hidden; scroll-snap-type: none;
  padding-block: 6px 10px; margin-block: -6px -10px;
  touch-action: pan-y;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--fade), #000 calc(100% - var(--fade)), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 var(--fade), #000 calc(100% - var(--fade)), transparent);
}
.chips-track { display: flex; gap: var(--s2); width: max-content; will-change: transform; }
.chips.is-conveyor .chip { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* --- Fields --------------------------------------------------------------------------- */
.field {
  width: 100%;
  border: 0; outline: 0; resize: none;
  background: transparent;
  font-size: var(--text-l);
  line-height: 1.35;
  color: var(--ink);
}
.field::placeholder { color: var(--ink-3); }

/* --- Panels and sheets ---------------------------------------------------------------- */
.panel {
  background: var(--card);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-card);
}
.scrim {
  position: fixed; inset: 0; z-index: var(--z-scrim);
  background: var(--scrim);
  opacity: 0; transition: opacity var(--dur-2) var(--ease-out);
}
.scrim.is-open { opacity: 1; }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sheet);
  max-width: 560px; margin: 0 auto;
  padding: var(--s3) var(--s5) calc(var(--s5) + var(--safe-bottom));
  background: var(--paper);
  border-radius: var(--radius-l) var(--radius-l) 0 0;
  box-shadow: var(--shadow-lift);
  transform: translateY(105%);
  transition: transform var(--dur-2) var(--ease-out);
}
.sheet.is-open { transform: translateY(0); }
.sheet-grip { width: 40px; height: 5px; border-radius: 3px; background: var(--paper-3); margin: 0 auto var(--s4); }
.sheet h2 { margin: 0 0 var(--s2); font-size: var(--text-xl); }

/* Toggle rows (extras) */
.row {
  display: flex; align-items: center; gap: var(--s3);
  min-height: 60px; padding: var(--s2) 0;
  border-bottom: 1px solid var(--line);
}
.row:last-of-type { border-bottom: 0; }
.row-text { flex: 1; }
.row-text strong { display: block; font-weight: 600; }
.row-text span { font-size: var(--text-s); color: var(--ink-2); }
.switch { position: relative; width: 52px; height: 32px; flex: none; }
.switch input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.switch span {
  position: absolute; inset: 0; border-radius: 16px; background: var(--paper-3);
  transition: background var(--dur-2);
}
.switch span::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 26px; height: 26px;
  border-radius: 50%; background: #fff; box-shadow: var(--shadow-1);
  transition: transform var(--dur-2) var(--ease-spring);
}
.switch input:checked + span { background: var(--ink); }
.switch input:checked + span::after { transform: translateX(20px); }

.segmented {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  padding: 4px; gap: 4px; border-radius: var(--radius-pill); background: var(--paper-2);
}
.segmented button {
  min-height: 40px; border: 0; border-radius: var(--radius-pill); background: transparent;
  font-size: var(--text-s); font-weight: 600; color: var(--ink-2); cursor: pointer;
}
.segmented button[aria-pressed="true"] { background: var(--card); color: var(--ink); box-shadow: var(--shadow-1); }

/* Number stepper (how many decks) */
.stepper { display: flex; align-items: center; gap: 6px; }
.stepper .btn-icon { width: 40px; min-height: 40px; height: 40px; font-size: 20px; }
.stepper .field { width: 64px; text-align: center; padding: 10px 4px; -moz-appearance: textfield; }
.stepper .field::-webkit-inner-spin-button, .stepper .field::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* --- Playing card --------------------------------------------------------------------- */
/* <div class="pcard"><div class="pcard-inner"><div class="pcard-face pcard-back"></div>
   <div class="pcard-face pcard-front"><img></div></div></div>
   Add .is-up to flip it face up. */
.pcard {
  position: relative;
  aspect-ratio: var(--card-ratio);
  perspective: 1200px;
}
.pcard-inner {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transition: transform var(--dur-3) var(--ease-spring);
}
.pcard.is-up .pcard-inner { transform: rotateY(180deg); }
.pcard-face {
  position: absolute; inset: 0;
  border-radius: var(--card-radius) / calc(var(--card-radius) * 816 / 1110);
  overflow: hidden;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  box-shadow: var(--shadow-card);
  background: var(--card);
}
.pcard-front { transform: rotateY(180deg); }
.pcard-front img, .pcard-back img { width: 100%; height: 100%; object-fit: cover; }
/* The face-down card before the deck's own back exists: a woven paper pattern that breathes. */
.pcard-back {
  background:
    radial-gradient(circle at 50% 50%, rgba(255,255,255,0.0) 0 30%, rgba(255,255,255,0.08) 31% 32%, transparent 33%) 0 0 / 22px 22px,
    repeating-linear-gradient(45deg, rgba(255,255,255,0.07) 0 2px, transparent 2px 9px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.07) 0 2px, transparent 2px 9px),
    linear-gradient(160deg, #2a2723, #121110);
  border: 6px solid #fff;
}
.pcard-back::after {
  /* the skeleton shimmer: a light band that sweeps across the face-down card. It moves with
     transform only, so the compositor runs it without repainting the card. */
  content: ""; position: absolute; top: 0; bottom: 0; left: -100%; width: 300%;
  background: linear-gradient(105deg, transparent 40%, rgba(255,255,255,0.2) 50%, transparent 60%);
  transform: translateX(-34%);
  animation: shimmer 1.8s var(--ease-out) infinite;
  pointer-events: none;
}
.pcard.is-up .pcard-back::after { animation: none; opacity: 0; }
/* a small gold monogram ring in the middle of the plain back */
.pcard-back:not(.has-art)::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 34%; aspect-ratio: 1;
  transform: translate(-50%, -50%) rotate(45deg);
  border: 2px solid rgba(232, 176, 75, 0.75); border-radius: 18%;
  box-shadow: 0 0 0 6px rgba(232, 176, 75, 0.12), inset 0 0 0 6px rgba(232, 176, 75, 0.12);
}
.pcard-back.has-art { border: 0; }
.pcard-back.has-art::after { opacity: 0.6; }
@keyframes shimmer { to { transform: translateX(34%); } }
/* while a card turns, hint the compositor; ui.js removes the class when the turn ends */
.pcard.is-turning .pcard-inner { will-change: transform; }

/* --- The shuffle: what the table does while cards draw (lib/shuffler.js) ----------------- */
/* A deck riffles in the middle of the table: the two halves split, bend and drop back in one
   card at a time, square up, then fan a little. Transform only, one loop per 2.4 s. Each
   screen sizes and places it (create.css, deck.css). */
.shuffler {
  position: absolute; left: 50%; top: 50%; z-index: 0;
  width: calc(var(--cw, 180px) * 0.5); aspect-ratio: var(--card-ratio);
  translate: -50% -50%;
  opacity: 0; scale: 0.8;
  transition: opacity 360ms var(--ease-out), scale 360ms var(--ease-out);
  pointer-events: none;
}
.shuffler.is-on { opacity: 1; scale: 1; }
.shuffler.is-done { opacity: 0; scale: 0.6; }
.sh-card {
  position: absolute; inset: 0;
  transform: translateY(calc(var(--i) * -1px));
}
.shuffler.is-on .sh-card {
  animation: riffle 2.4s cubic-bezier(0.45, 0, 0.25, 1) infinite;
  animation-delay: calc(var(--k) * 42ms);
}
.sh-face {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: 7px / 9.5px;
  border: 3px solid #fff;
  box-shadow: 0 1px 2px rgba(40, 30, 10, 0.18), 0 6px 14px rgba(40, 30, 10, 0.12);
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,0.09) 0 2px, transparent 2px 8px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.09) 0 2px, transparent 2px 8px),
    linear-gradient(160deg, var(--sh-a, #2a2723), var(--sh-b, #121110));
}
.shuffler.has-palette .sh-face { animation: sh-tint 520ms var(--ease-spring) both; animation-delay: calc(var(--i) * 40ms); }
.shuffler.has-art .sh-face { border: 0; background: var(--card); }
.sh-face img { width: 100%; height: 100%; object-fit: cover; }
@keyframes sh-tint { from { opacity: 0.2; } }
@keyframes riffle {
  0%, 6% { transform: translate(0, calc(var(--i) * -1px)) rotate(0deg); }
  22% { transform: translate(calc(var(--side) * 62%), calc(var(--k) * -1px)) rotate(calc(var(--side) * 8deg)); }
  36% { transform: translate(calc(var(--side) * 54%), calc(var(--k) * -1px - 8px)) rotate(calc(var(--side) * 17deg)); }
  54% { transform: translate(calc(var(--side) * 6%), calc(var(--i) * -1px - 6px)) rotate(calc(var(--side) * 3deg)); }
  64%, 70% { transform: translate(0, calc(var(--i) * -1px)) rotate(0deg); }
  82% { transform: translate(calc((var(--i) - 4.5) * 3%), calc(var(--i) * -1px - 12px)) rotate(calc((var(--i) - 4.5) * 3deg)); }
  94%, 100% { transform: translate(0, calc(var(--i) * -1px)) rotate(0deg); }
}
/* a card still drawing is not on the table at all: it arrives from the deck when it is ready */
.pcard.is-waiting .pcard-inner, .pcard.is-waiting .card-caption { opacity: 0; }

/* --- Toast ---------------------------------------------------------------------------- */
.toast {
  position: fixed; left: 50%; bottom: calc(var(--s6) + var(--safe-bottom)); z-index: var(--z-toast);
  pointer-events: none;
  max-width: calc(100% - 32px);
  padding: var(--s3) var(--s5);
  border-radius: var(--radius-pill);
  background: var(--ink); color: var(--paper);
  font-size: var(--text-s); font-weight: 500;
  transform: translate(-50%, 140%); opacity: 0;
  transition: transform var(--dur-2) var(--ease-spring), opacity var(--dur-2);
}
.toast.is-on { transform: translate(-50%, 0); opacity: 1; }
/* over the viewer the toast rises above the card's name and arrows */
body:has(.viewer) .toast { bottom: calc(var(--s6) + var(--safe-bottom) + 118px); }

/* --- Page frame: every v2 screen ----------------------------------------------------- */
.screen {
  max-width: var(--page, 560px);
  margin: 0 auto;
  min-height: 100dvh;
  padding: calc(var(--s3) + var(--safe-top)) var(--gutter, var(--s5)) 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  min-height: var(--tap);
}
/* The mark: the original Qualia logo, cleaned to one flat colour (scripts/build_brand.py), shown
   as a mask so it stays a single crisp shape at any size. The wordmark is set in the display face. */
.brand { display: flex; align-items: center; gap: 9px; color: var(--ink); text-decoration: none; }
.brand-mark {
  flex: none; display: block; width: 20px; height: 30px; background: #0e1526;   /* the logo's navy */
  -webkit-mask: url(/v2/assets/brand/mark.png) center / contain no-repeat;
  mask: url(/v2/assets/brand/mark.png) center / contain no-repeat;
}
.brand-word {
  font-family: var(--font-display); font-size: 1.25rem; font-weight: 600; line-height: 1;
  letter-spacing: -0.015em; font-variation-settings: "SOFT" 100, "WONK" 1; white-space: nowrap;
}
.topnav { display: none; }
.topnav a { color: var(--ink-2); text-decoration: none; font-size: var(--text-s); font-weight: 500; padding: var(--s3) 0; }
.topnav a:hover { color: var(--ink); }
.topnav a[aria-current="page"] { color: var(--ink); }
.topbar-link { color: var(--ink-2); text-decoration: none; font-size: var(--text-s); font-weight: 500; padding: var(--s3) 0; }
.topbar-title { margin: 0; font-size: var(--text-l); font-weight: 600; }


/* --- Close-up viewer (lib/ui.js openViewer): the carousel, large, over a blurred scrim ----- */
/* The front card flies out of its place on the page (.viewer-face, moved by the Web Animations
   API: face, corners and shadow travel together); its neighbours fade in on both sides once it
   lands (.is-settled). carousel.js writes each card's transform. */
.viewer {
  position: fixed; inset: 0; z-index: var(--z-viewer);
  --vcw: min(74vw, 440px, calc((100dvh - 200px) * 816 / 1110));
}
.viewer-scrim {
  position: absolute; inset: 0;
  background: rgba(24, 19, 12, 0.5);
  -webkit-backdrop-filter: blur(12px) saturate(1.05); backdrop-filter: blur(12px) saturate(1.05);
  opacity: 0; transition: opacity 320ms var(--ease-out);
}
.viewer.is-open .viewer-scrim, .viewer.is-settled .viewer-scrim { opacity: 1; }
.viewer.is-closing .viewer-scrim { opacity: 0; transition-duration: 380ms; }
.viewer-stage, .viewer-stage.cz { position: absolute; inset: 0; touch-action: none; }
.viewer-stage.cz:focus-visible { outline: none; }
.viewer-card, .viewer-card.cz-item {
  width: var(--vcw); aspect-ratio: var(--card-ratio);
  top: calc(50% - var(--vcw) * 1110 / 816 / 2 - 34px);
  border-radius: 14px;
}
.viewer-face {
  position: absolute; inset: 0; overflow: hidden; border-radius: inherit; background: var(--card);
  box-shadow: 0 30px 60px -20px rgba(10, 6, 2, 0.6), 0 10px 24px rgba(10, 6, 2, 0.25);
  transform-origin: 50% 50%;
  transition: opacity var(--dur-2) var(--ease-out);
}
.viewer-face img { display: block; width: 100%; height: 100%; object-fit: cover; }
.viewer-face picture { display: contents; }
.viewer-card .cz-lift { display: none; }
/* until the front card has landed (and while it flies back), only the front card shows */
.viewer:not(.is-settled) .viewer-card:not(.cz-mid) .viewer-face { opacity: 0; }
.viewer .cz-arrow { display: none; }
.viewer-foot {
  position: absolute; left: 0; right: 0; bottom: calc(var(--s6) + var(--safe-bottom));
  display: flex; flex-direction: column; align-items: center; gap: var(--s3); pointer-events: none;
}
.viewer-foot > * { pointer-events: auto; }
.viewer-label, .viewer-nav, .viewer-close, .viewer-share {
  opacity: 0; transition: opacity 220ms var(--ease-out);
}
.viewer.is-open .viewer-label, .viewer.is-open .viewer-nav, .viewer.is-open .viewer-close, .viewer.is-open .viewer-share {
  opacity: 1; transition-delay: 160ms;
}
.viewer-label { margin: 0; color: #f5efe4; font-weight: 600; text-shadow: 0 1px 8px rgba(0,0,0,0.3); }
.viewer-close { position: absolute; top: calc(var(--s4) + var(--safe-top)); right: var(--s4); background: rgba(255,255,255,0.16); color: #fff; }
.viewer-share {
  position: absolute; top: calc(var(--s4) + var(--safe-top)); left: var(--s4);
  min-height: 44px; padding: 0 var(--s4); border-radius: var(--radius-pill);
  background: rgba(255,255,255,0.16); color: #fff; font-weight: 600;
}
.viewer-nav { display: flex; align-items: center; gap: var(--s4); }
.viewer-nav .btn-icon { background: rgba(255,255,255,0.16); color: #fff; }
.viewer-count { color: rgba(245,239,228,0.78); font-size: var(--text-s); font-variant-numeric: tabular-nums; min-width: 5ch; text-align: center; }
/* the card on the page while its copy is in the viewer */
.is-viewing { visibility: hidden; }

/* --- Desktop (1024 px and up) ------------------------------------------------------------- */
@media (min-width: 1024px) {
  .phone-only { display: none; }
  .topbar { min-height: 64px; }
  .brand-mark { width: 23px; height: 34px; }
  .brand-word { font-size: 1.4375rem; }
  .topnav { display: flex; gap: var(--s6); margin-left: auto; margin-right: var(--s4); }
  .chips { flex-wrap: wrap; overflow: visible; margin: 0; padding: 2px 0; }
  .chips.is-conveyor { --fade: 64px; overflow: hidden; padding: 6px 0 10px; margin: -6px 0 -10px; }
  .chip { min-height: 42px; }
  .btn-primary { min-height: 60px; }
  .btn-icon:hover, .chip:hover { transform: translateY(-1px); }
  .btn-primary:hover { background: var(--accent-press); }
  /* sheets become centered dialogs */
  .sheet {
    left: 50%; right: auto; top: 50%; bottom: auto; width: 520px; max-width: calc(100vw - 48px);
    padding: var(--s8);
    border-radius: var(--radius-l);
    opacity: 0; transform: translate(-50%, -46%);
    transition: transform var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out);
  }
  .sheet.is-open { opacity: 1; transform: translate(-50%, -50%); }
  .sheet-grip { display: none; }
  .viewer-close { top: var(--s6); right: var(--s6); }
  .viewer-share { top: var(--s6); left: var(--s6); }
}

/* Reduced motion: no shimmer, no idle movement. State still changes; it just doesn't travel. */
@media (prefers-reduced-motion: reduce) {
  .pcard-back::after { animation: none; opacity: 0; }
  .shuffler.is-on .sh-card, .shuffler.has-palette .sh-face { animation: none; }
  .viewer, .viewer img { animation: none; }
  .viewer-face { transition: none; }
}

/* --- Waiting: narration --------------------------------------------------------------------- */
.narrate {
  margin: var(--s2) 0 0; min-height: 1.45em;
  font-size: var(--text-s); color: var(--ink-2); font-style: italic;
  transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.narrate.is-out { opacity: 0; transform: translateY(4px); }

/* --- Carousel (lib/carousel.js): cover flow, the middle card always on top ---------------- */
/* carousel.js writes each rendered card's transform, opacity and z-index, and the opacity of
   its .cz-dim (darkens a side card) and .cz-lift (the middle card's deeper shadow). Cards
   more than six from the middle are .cz-off: not rendered at all. */
.cz {
  position: relative; touch-action: pan-y; -webkit-user-select: none; user-select: none;
  outline: none; -webkit-tap-highlight-color: transparent;
  isolation: isolate;   /* the cards' z-index stays inside: the viewer and sheets open over them */
}
.cz:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; border-radius: var(--radius-m); }
.cz-item {
  position: absolute; left: 50%; top: 0; transform-origin: 50% 50%; cursor: grab;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.cz-item:not(.cz-off) { will-change: transform, opacity; }
/* the dimming, the shadow and the parallax drift get their own layers, so moving them never
   repaints the card */
.cz-item:not(.cz-off) .cz-dim, .cz-item:not(.cz-off) .cz-lift { will-change: opacity; }
.cz-item:not(.cz-off) .cz-art { will-change: transform; }
.cz-off { display: none; }
/* the restack crossfade's copy of a card (lib/carousel.js): seen, never touched */
.cz-ghost { pointer-events: none; }
.cz:active .cz-item { cursor: grabbing; }
.cz-item img { -webkit-user-drag: none; pointer-events: none; }
.cz-item .cz-art { scale: 1.08; }          /* room for the parallax drift */
.cz-dim {
  position: absolute; inset: 0; z-index: 3; pointer-events: none; opacity: 0;
  border-radius: inherit; background: #17130d;
}
.cz-lift {
  position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0;
  border-radius: var(--card-radius) / calc(var(--card-radius) * 816 / 1110);
  box-shadow: 0 30px 50px -18px rgba(28, 20, 8, 0.55), 0 12px 22px -6px rgba(28, 20, 8, 0.22);
}
.cz-arrow {
  position: absolute; top: 50%; z-index: 200; translate: 0 -50%;
  width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  display: none; place-items: center; cursor: pointer;
  background: var(--card); color: var(--ink); box-shadow: var(--shadow-1);
  transition: transform var(--dur-1) var(--ease-out);
}
.cz-arrow:hover { transform: scale(1.06); }
.cz-arrow:active { transform: scale(0.94); }
.cz-prev { left: 4px; }
.cz-next { right: 4px; }
@media (hover: hover) and (pointer: fine) { .cz-arrow { display: grid; } }
/* the fan layout: a hand of cards pivoting on a point well below them */
.cz-fan .cz-item { transform-origin: 50% 190%; }
.cz-fan .cz-arrow { display: none; }   /* a hand turns by drag, a click on a side card, or the keys */

/* --- Card art is not a loose image: no dragging it out, no "Save Image" ------------------ */
/* lib/protect.js adds draggable="false" and blocks the context menu on card art. */
img { -webkit-user-drag: none; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.pcard, .fc, .viewer, .gal-card, .d-grid button, .sh-card, .sh-cell, .sp-card, .sp-rc, .fc-card { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }

/* --- Tiers (lib/tiers.js): three ways to make a deck ------------------------------------- */
.tier-grid {
  display: flex; gap: var(--s3); overflow-x: auto; scrollbar-width: none; scroll-snap-type: x mandatory;
  margin: 0 calc(-1 * var(--gutter, var(--s5))); padding: var(--s2) var(--gutter, var(--s5)) var(--s4);
  scroll-padding-inline: var(--gutter, var(--s5));
}
.tier-grid::-webkit-scrollbar { display: none; }
.tier {
  flex: none; width: min(78vw, 300px); scroll-snap-align: start;
  display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s5); border-radius: var(--radius-l);
  background: var(--card); box-shadow: var(--shadow-1);
}
.tier.is-here { box-shadow: inset 0 0 0 2px var(--ink), var(--shadow-1); }
.tier-commissioned { background: linear-gradient(165deg, #22262e, #14161b); color: #f5efe4; }
.tier-commissioned .tier-kicker, .tier-commissioned .tier-points { color: rgba(245, 239, 228, 0.72); }
.tier-commissioned .btn-ghost { color: #f5efe4; box-shadow: inset 0 0 0 1.5px rgba(245, 239, 228, 0.4); }
.tier-kicker { margin: 0; font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.tier-name { margin: 0; font-family: var(--font-display); font-size: var(--text-xl); font-weight: 600; letter-spacing: -0.01em; }
.tier-price { margin: 0; font-size: var(--text-m); }
.tier-price strong { font-size: var(--text-l); }
.tier-price span { opacity: 0.7; }
.tier-low { margin: -4px 0 0; font-size: var(--text-xs); font-weight: 600; color: var(--ink-2); }
.tier-summary { margin: var(--s1) 0 0; font-size: var(--text-s); font-weight: 600; }
.tier-commissioned .tier-low { color: rgba(245, 239, 228, 0.8); }
.tier-points { margin: var(--s1) 0 var(--s2); padding: 0 0 0 1.1em; font-size: var(--text-s); color: var(--ink-2); display: grid; gap: 6px; }
.tier-cta { margin-top: auto; min-height: 46px; font-size: var(--text-s); text-decoration: none; }
.tier-cta.btn-primary { min-height: 46px; font-size: var(--text-s); box-shadow: none; }
.tier-here { margin-top: auto; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-2); padding: var(--s2) 0; }
.tiers-compact .tier { width: min(56vw, 220px); padding: var(--s4); gap: 4px; }
.tiers-compact .tier-name { font-size: var(--text-l); }
@media (min-width: 1024px) {
  .tier-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); overflow: visible; margin: 0; padding: var(--s2) 0 var(--s4); }
  .tier { width: auto; padding: var(--s6); }
  .tiers-compact .tier { width: auto; }
}

/* --- Spread (lib/spread.js): the whole deck laid out like cards -------------------------- */
/* Table: each suit a tight fan on felt; hover (or a finger dragged across) opens it to a full
   fan and lifts the card under the pointer. Jokers and the back lie to the side. Fan: every
   card in one ring that turns slowly. Only transform and opacity move. */
.sp-switch { width: max-content; margin: 0 0 var(--s4); }
.sp-switch button { padding: 0 var(--s5); }
.sp-felt {
  --cw: 76px;
  display: flex; flex-direction: column; gap: var(--s4);
  padding: var(--s5) var(--s4) var(--s6); margin: 0 calc(-1 * var(--s5));
  /* a warm tan baize, the page's paper family a few shades deeper (no green: nothing else on
     the site is green). A faint fractal noise is the felt's nap. */
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255, 250, 240, 0.28), transparent 62%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .3 0 0 0 0 .2 0 0 0 0 .08 0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.35'/%3E%3C/svg%3E"),
    linear-gradient(170deg, #d6c19b, #c4a97d);
  box-shadow: inset 0 2px 16px rgba(90, 64, 28, 0.22), inset 0 0 0 1px rgba(90, 64, 28, 0.08);
}
.sp-suits { display: grid; gap: var(--s3); }
.sp-name {
  margin: 0 0 var(--s1); display: flex; align-items: center; gap: 8px;
  font-size: var(--text-s); font-weight: 600; color: rgba(29, 27, 24, 0.78);
}
.sp-name i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; box-shadow: 0 0 0 1.5px rgba(255, 250, 240, 0.8); }
.sp-fan {
  position: relative; container-type: inline-size; touch-action: pan-y;
  height: calc(var(--cw) * 1110 / 816 + 34px);
  --dx: calc(var(--cw) * 0.16);
  --a: 1.4deg;
}
/* open: swept out to the right across the suit's whole row, the way a hand spreads a deck */
.sp-fan:hover, .sp-fan.is-open {
  --dx: calc((100cqw - var(--cw) - 56px) / (var(--n) - 1));
  --a: 0.8deg;
}
.sp-card, .sp-rc {
  position: absolute; padding: 0; border: 0; cursor: pointer; background: var(--card);
  aspect-ratio: var(--card-ratio);
  border-radius: var(--card-radius) / calc(var(--card-radius) * 816 / 1110);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 4px 10px rgba(0, 0, 0, 0.22);
}
.sp-card img, .sp-rc img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; pointer-events: none; }
.sp-fan .sp-card {
  width: var(--cw); left: 28px; bottom: 10px;
  transform-origin: 50% 220%;
  transform: translateX(calc(var(--i) * var(--dx))) rotate(calc(var(--o) * var(--a))) translateY(var(--ly, 0px));
  transition: transform 460ms var(--ease-spring);
  transition-delay: calc(var(--i) * 12ms);
}
.sp-fan:hover .sp-card { transition-delay: 0ms; }
.sp-fan .sp-card:hover, .sp-fan .sp-card.is-lift, .sp-fan .sp-card:focus-visible { --ly: -16px; transition-delay: 0ms; }
.sp-aside { display: flex; justify-content: center; padding: var(--s2) 0 0; }
.sp-aside .sp-card {
  position: relative; width: var(--cw); margin-left: calc(var(--cw) * -0.35);
  transform: rotate(var(--r)); transition: transform 320ms var(--ease-spring);
}
.sp-aside .sp-card:first-child { margin-left: 0; }
.sp-aside .sp-card:hover { transform: rotate(0deg) translateY(-12px); z-index: 1; }

.sp-ring {
  --r: min(44vw, 190px); --w: calc(var(--r) * 0.42);
  position: relative; height: calc(var(--r) * 2 + 36px); overflow: hidden;
  margin: 0 calc(-1 * var(--s5));
}
.sp-ring-in { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }
.sp-ring.is-open .sp-ring-in { animation: sp-turn 160s linear infinite; }
@keyframes sp-turn { to { rotate: 360deg; } }
.sp-rc {
  left: calc(var(--w) / -2); top: calc(var(--r) * -1); width: var(--w);
  transform-origin: 50% var(--r);
  transform: rotate(var(--rest, 0deg)) translateY(var(--pile, 0px));
  transition: transform 900ms var(--ease-spring); transition-delay: calc(var(--i) * 9ms);
}
.sp-ring:not(.is-open) .sp-rc { --rest: calc(var(--j) * 1deg); --pile: calc(var(--r) - var(--w) * 1110 / 816 / 2); transition-delay: 0ms; }
.sp-ring.is-open .sp-rc { --rest: var(--a); }
.sp-rc img { transition: translate 260ms var(--ease-spring); }
.sp-rc:hover img, .sp-rc:focus-visible img { translate: 0 -14px; }
.sp-ring:has(.sp-rc:hover) .sp-ring-in { animation-play-state: paused; }
.sp-hub {
  position: absolute; left: 50%; top: 50%; width: 92px; height: 92px; margin: -46px 0 0 -46px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--paper); box-shadow: var(--shadow-1); pointer-events: none;
}
.sp-hub strong { font-family: var(--font-display); font-size: 32px; line-height: 1; }
.sp-hub span { font-size: 11px; color: var(--ink-3); font-weight: 600; }
@media (min-width: 1024px) {
  .sp-felt {
    --cw: 100px; margin: 0; border-radius: var(--radius-l);
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: var(--s8);
    padding: var(--s8) var(--s8) var(--s8);
  }
  .sp-suits { gap: var(--s2); }
  .sp-aside { flex-direction: column; padding: 0; }
  .sp-aside .sp-card { margin: calc(var(--cw) * -0.9) 0 0; }
  .sp-aside .sp-card:first-child { margin-top: 0; }
  .sp-ring { --r: 300px; margin: 0; }
  .sp-hub { width: 140px; height: 140px; margin: -70px 0 0 -70px; }
  .sp-hub strong { font-size: 52px; }
}
@media (prefers-reduced-motion: reduce) {
  .sp-fan .sp-card, .sp-aside .sp-card, .sp-rc, .sp-rc img { transition: none; }
  .sp-ring.is-open .sp-ring-in { animation: none; }
}


/* --- Site footer and newsletter signup (lib/newsletter.js posts to /api/newsletter) ------- */
.site-foot { display: flex; flex-direction: column; align-items: center; gap: var(--s4); padding: var(--s6) 0 var(--s4); border-top: 1px solid var(--line); }
.site-foot-links { display: flex; flex-wrap: wrap; gap: var(--s4); justify-content: center; }
.site-foot-links a { color: var(--ink-3); }
.foot-brand { display: flex; align-items: center; gap: 7px; color: var(--ink-3); text-decoration: none;
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-s); }
.foot-brand .brand-mark { width: 13px; height: 20px; background: currentColor; }
.nl { width: 100%; max-width: 420px; }
.nl-label { display: block; margin: 0 0 var(--s2); font-size: var(--text-s); font-weight: 600; color: var(--ink-2); text-align: center; }
.nl-row { display: flex; gap: var(--s2); }
.nl-row .field {
  flex: 1; min-width: 0; min-height: var(--tap); padding: 0 var(--s4);
  background: var(--card); border-radius: var(--radius-pill); box-shadow: inset 0 0 0 1.5px var(--line);
  font-size: var(--text-m);
}
.nl-row .field:focus-visible { box-shadow: inset 0 0 0 2px var(--ink); }
.nl-row .btn { flex: none; padding: 0 var(--s5); }
.nl-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.nl-msg { min-height: 1.4em; margin: var(--s2) 0 0; font-size: var(--text-s); color: var(--ink-2); text-align: center; }
.nl.is-done .nl-row { display: none; }
.nl.is-done .nl-msg { color: var(--good); font-weight: 600; }
