/* Deck view and reveal (/v2/deck/). The whole deck as a hand of cards that fans out and
   turns face up as each card is drawn. */

.deck-screen { padding-bottom: calc(var(--s8) + var(--safe-bottom)); overflow-x: clip; }
.paid-pill {
  padding: 6px 12px; border-radius: var(--radius-pill);
  background: rgba(47, 143, 91, 0.12); color: var(--good);
  font-size: var(--text-xs); font-weight: 700;
  animation: pop-in var(--dur-3) var(--ease-spring) both;
}
@keyframes pop-in { from { transform: scale(0.6); opacity: 0; } }

.d-head { padding: var(--s2) 0 0; min-height: 112px; }
.status { margin: 0 0 var(--s1); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }
.status::before {
  content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 8px;
  border-radius: 50%; background: var(--accent); vertical-align: 1px;
  animation: pulse 1.1s ease-in-out infinite;
}
body.is-done .status::before { background: var(--good); animation: none; }
@keyframes pulse { 50% { opacity: 0.25; transform: scale(0.7); } }
.d-title { margin: 0; font-size: var(--text-2xl); }
.d-tagline { margin: var(--s2) 0 0; font-size: var(--text-m); }

/* --- The table: the whole deck opens into a ring ------------------------------------------- */
/* Every card hangs from the ring's center (transform-origin --r below its top edge). Stacked,
   they sit in a pile on the center; open, each turns to its own angle, so the deck bursts out
   into a full circle with every card's top-left index showing. */
.table {
  --r: 164px;                 /* ring radius to the cards' outer edge */
  --w: 80px;
  position: relative;
  height: calc(var(--r) * 2 + 28px);
  margin: var(--s1) calc(-1 * var(--s5)) 0;
  overflow: hidden;
  isolation: isolate;         /* the hub and sweep stack inside the table, under the viewer */
}
.fan { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }
.fan .fc {
  position: absolute; left: calc(var(--w) / -2); top: calc(var(--r) * -1);
  width: var(--w); aspect-ratio: var(--card-ratio);
  perspective: 700px;
  transform-origin: 50% var(--r);
  transform: rotate(var(--rest, 0deg)) translateY(var(--pile, 0px));
  transition: transform 900ms var(--ease-spring);
  transition-delay: var(--delay, 0ms);
  z-index: var(--z);
  cursor: pointer;
}
.fan:not(.is-open) .fc {
  --rest: calc(var(--jitter) * 1deg);
  --pile: calc(var(--r) - var(--w) * 1110 / 816 / 2);
  --delay: 0ms;
}
.fan.is-open .fc { --rest: var(--angle); }
.fan.is-bursting .fc { will-change: transform; }   /* only for the burst; deck.js removes it */
.fan:not(.is-open) .fc-face { box-shadow: 0 1px 1px rgba(40, 30, 10, 0.08); }
.fc-inner { position: absolute; inset: 0; transform-style: preserve-3d; }
.fc.is-up .fc-inner { transform: rotateY(180deg); }
.fc-face {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: 5px; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: var(--card);
  box-shadow: 0 1px 2px rgba(40, 30, 10, 0.14), 0 4px 10px rgba(40, 30, 10, 0.14);
}
.fc-face img { width: 100%; height: 100%; object-fit: cover; }
.fc-front { transform: rotateY(180deg); }
.fc-back {
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,0.07) 0 2px, transparent 2px 7px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.07) 0 2px, transparent 2px 7px),
    linear-gradient(160deg, #2a2723, #121110);
  border: 3px solid #fff;
}
.fc-back.has-art { border: 0; }
/* a card that just landed pops out of the ring, then settles */
.fc.is-landing .fc-inner { animation: fc-pop 640ms var(--ease-spring); }
@keyframes fc-pop { 35% { translate: 0 -14px; scale: 1.06; } }
/* the finished ring ripples once, all the way round */
.fan.is-wave .fc .fc-inner { animation: fc-wave 800ms var(--ease-out) both; animation-delay: calc(var(--i) * 16ms); }
@keyframes fc-wave { 40% { translate: 0 -12px; } }

/* The ring is the reveal only: a card that has landed opens on a tap (deck.js). */
.fan .fc { -webkit-touch-callout: none; }
.table { -webkit-user-select: none; user-select: none; }
.fc-inner { transition: transform 560ms var(--ease-spring); }

/* While the deck draws, a soft light sweeps round the ring, over the cards still face down:
   one layer that only rotates, so it costs the compositor nothing. */
.sweep {
  position: absolute; left: 50%; top: 50%; z-index: 90; pointer-events: none;
  width: calc(var(--r) * 2 + 20px); aspect-ratio: 1; margin: calc(var(--r) * -1 - 10px) 0 0 calc(var(--r) * -1 - 10px);
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 300deg, rgba(255, 250, 240, 0.0) 300deg, rgba(255, 250, 240, 0.28) 350deg, transparent 360deg);
  -webkit-mask: radial-gradient(circle, transparent 0 calc(var(--r) * 0.32), #000 calc(var(--r) * 0.36));
  mask: radial-gradient(circle, transparent 0 calc(var(--r) * 0.32), #000 calc(var(--r) * 0.36));
  opacity: 0; transition: opacity 600ms var(--ease-out);
  animation: sweep 2.6s linear infinite; animation-play-state: paused;
}
body.is-drawing .sweep { opacity: 1; animation-play-state: running; }
@keyframes sweep { to { transform: rotate(360deg); } }

/* Dealing (while the deck draws, and for gallery decks): a deck riffles in the middle, larger
   than a ring card; cards not yet drawn are not on the table; each flies out to its place and
   turns up as it lands (deck.js dealOut). The hub comes back when the last card is down. */
.table .shuffler { z-index: 95; width: calc(var(--w) * 1.1); }
.table.is-dealing .fc:not(.is-dealt) { opacity: 0; pointer-events: none; }
.table.is-dealing .hub { scale: 0; }
.table.is-dealing .sweep { opacity: 0; }

/* the hole in the middle of the ring: the count and the clock */
.hub {
  position: absolute; left: 50%; top: 50%; z-index: 100;
  width: 96px; height: 96px; margin: -48px 0 0 -48px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--paper); box-shadow: 0 0 0 6px rgba(245, 239, 228, 0.6), var(--shadow-1);
  font-variant-numeric: tabular-nums; text-align: center;
  transition: scale var(--dur-3) var(--ease-spring);
}
.hub strong { font-family: var(--font-display); font-size: 34px; line-height: 1; font-weight: 650; }
.hub span { font-size: 11px; color: var(--ink-3); font-weight: 600; letter-spacing: 0.02em; margin-top: 3px; }
.fan:not(.is-open) ~ .hub { scale: 0; }
body.is-done .hub { animation: hub-done 700ms var(--ease-spring); }
@keyframes hub-done { 40% { scale: 1.15; } }

/* --- Under the table: the turning verbs while it deals, then how long it took ---------------- */
.meter { padding: var(--s3) 0 var(--s5); text-align: center; }
.meter-note { margin: var(--s2) 0 0; text-align: center; }
.meter-note:empty { display: none; }
.d-spin {
  margin: 0; min-height: 1.5em; font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: var(--text-xl); color: var(--ink-2);
  opacity: 0; transition: opacity 170ms var(--ease-out), translate 170ms var(--ease-out);
}
.d-spin.is-on { opacity: 1; }
.d-spin.is-out { opacity: 0; translate: 0 6px; }

/* --- The carousel (lib/carousel.js): the deck to browse ----------------------------------- */
/* A drawn deck opens straight into it. While a deck is really drawing, the ring (.table) is
   shown instead, and gives way to the carousel when the last card is down. */
body:not(.is-ringing) .table { display: none; }
body.is-ringing .d-stage { display: none; }
.table.is-leaving { opacity: 0; scale: 0.92; transition: opacity 360ms var(--ease-out), scale 360ms var(--ease-out); }
.d-stage { overflow-x: clip; margin: var(--s2) calc(-1 * var(--s5)) 0; padding: 0 var(--s5); }
.d-cz { --dcw: min(60vw, 250px); height: calc(var(--dcw) * 1110 / 816 + 40px); }
.d-czc { width: var(--dcw); aspect-ratio: var(--card-ratio); top: 16px; border-radius: var(--card-radius) / calc(var(--card-radius) * 816 / 1110); }
/* until lib/carousel.js takes the cards (it adds .cz-item), keep them out of sight: their
   absolutely placed faces would otherwise fill the page for a frame while the first cards load */
.d-czc:not(.cz-item) { visibility: hidden; }
.d-czc-face {
  position: absolute; inset: 0; overflow: hidden; border-radius: inherit;
  background: var(--card); box-shadow: var(--shadow-card);
}
.d-czc-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.d-czc-face picture { display: contents; }
.d-stage .cz-label { text-align: center; margin: var(--s2) 0 0; min-height: 1.45em; font-weight: 600; font-size: var(--text-s); color: var(--ink-2); }

.d-actions { display: flex; flex-direction: column; gap: var(--s2); padding-bottom: var(--s6); animation: rise var(--dur-3) var(--ease-spring) both; }
.d-actions .btn { text-decoration: none; }
.d-actions .tiny { text-align: center; margin: 0; }
@keyframes rise { from { transform: translateY(24px); opacity: 0; } }

/* --- Every card, suit by suit -------------------------------------------------------------- */
.d-all { animation: rise var(--dur-3) var(--ease-spring) both; }
.d-h2 { margin: 0 0 var(--s3); font-size: var(--text-l); }
.d-suit { margin: 0 0 var(--s5); }
.d-suit h3 { margin: 0 0 var(--s2); font-size: var(--text-s); font-weight: 600; color: var(--ink-2); display: flex; align-items: center; gap: 8px; }
.d-suit h3 i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.d-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); }
.d-grid button {
  aspect-ratio: var(--card-ratio); padding: 0; border: 0; border-radius: 6px; overflow: hidden;
  background: var(--card); box-shadow: var(--shadow-1); cursor: pointer;
}
.d-grid img { width: 100%; height: 100%; object-fit: cover; }

/* once it's all there, the ring turns slowly, like a record */
body.is-done .fan.is-open { animation: spin 120s linear infinite; }
@keyframes spin { to { rotate: 360deg; } }
@media (prefers-reduced-motion: reduce) {
  body.is-done .fan.is-open { animation: none; }
  .sweep { display: none; }
  .fan .fc, .fc-inner { transition-duration: 0ms; }
  .fc.is-landing .fc-inner, .fan.is-wave .fc .fc-inner { animation: none; }
}

/* --- Desktop: the story on the left, the ring large on the right, every card below ---------- */
@media (min-width: 1024px) {
  .deck-screen {
    display: grid; grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
    grid-template-rows: auto auto auto auto 1fr auto; column-gap: 56px; align-content: start;
    min-height: 0;   /* the ring sets the height; a full-window grid would stretch the gap above "Every card" */
    padding-bottom: var(--s12);
  }
  .deck-screen > .topbar { grid-column: 1 / -1; }
  .d-head { grid-column: 1; grid-row: 2; padding-top: var(--s12); min-height: 0; }
  .d-title { font-size: var(--text-2xl); }
  .d-tagline { font-size: var(--text-l); }
  .meter { grid-column: 1; grid-row: 4; padding: var(--s6) 0; }
  .d-actions { grid-column: 1; grid-row: 5; align-self: start; }
  .table {
    grid-column: 2; grid-row: 2 / span 4;
    /* as large as the right column and the window height allow */
    --r: clamp(200px, min(calc((100dvh - 170px) / 2), calc((min(100vw, 1180px) - 536px) / 2 - 16px)), 330px);
    --w: calc(var(--r) * 0.49);
    margin: 0;
  }
  .fc-face { border-radius: 8px; }
  .hub { width: 150px; height: 150px; margin: -75px 0 0 -75px; }
  .hub strong { font-size: 56px; }
  .hub span { font-size: 13px; }
  .d-stage {
    grid-column: 2; grid-row: 2 / span 4; margin: 0; padding: var(--s8) 0 0; align-self: start;
    /* the stack fades out at the column's edges instead of being cut off */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  }
  .d-cz { --dcw: clamp(240px, calc((100dvh - 250px) * 816 / 1110), 340px); }
  .d-stage .cz-arrow { top: auto; bottom: -52px; translate: none; }
  .d-stage .cz-prev { left: calc(50% - 200px); }
  .d-stage .cz-next { right: calc(50% - 200px); }
  .d-stage .cz-label { line-height: 44px; margin-top: 6px; }
  .d-all { grid-column: 1 / -1; grid-row: 6; padding-top: var(--s10); }
  .d-h2 { font-size: var(--text-xl); font-family: var(--font-display); }
  .d-grid { grid-template-columns: repeat(13, 1fr); gap: var(--s3); }
  .d-grid button { transition: transform var(--dur-1) var(--ease-out); }
  .d-grid button:hover { transform: translateY(-4px); }
}
@media (min-width: 1024px) {
  .d-spin { font-size: var(--text-l); text-align: left; }
  .meter-note { text-align: left; }
}

/* --- The proof sheet button, under the carousel ---------------------------------------------- */
.d-sheet-btn { display: flex; align-items: center; gap: 8px; margin: var(--s3) auto 0; min-height: 44px; padding: 0 var(--s5); }
.d-sheet-btn[hidden] { display: none; }
.d-all { scroll-margin-top: var(--s6); }
@media (min-width: 1024px) { .d-stage .d-sheet-btn { margin-top: var(--s10); } }

/* --- A shared deck (/s/<token>): the buy panel -------------------------------------------------- */
.d-buy { padding: var(--s5); display: flex; flex-direction: column; gap: var(--s2); }
.d-buy p { margin: 0; }
.d-buy-line { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--s1) var(--s3); }
.d-buy-line strong { font-size: var(--text-l); }
.d-buy-sub { font-size: var(--text-s); margin-bottom: var(--s2) !important; }
.d-buy .tiny { text-align: center; }

/* Watermark on a shared deck's cards: a small, light "qualia" at the bottom edge of each card
   (in the white margin, clear of the corner indices): a text overlay on the carousel and the
   proof sheet; in the viewer, whose ground is dark, a CSS mask lets the ground show through the
   letters. It deters casual copying; it can't stop a screenshot. */
body.is-share .d-czc-face::after, body.is-share .sp-card::after, body.is-share .sp-rc::after {
  content: "qualia"; position: absolute; left: 50%; bottom: 1.4%; translate: -50% 0; z-index: 2;
  font: italic 500 clamp(6px, 4.2cqw, 13px)/1 var(--font-display); letter-spacing: 0.08em;
  color: #1d1b18; opacity: 0.32; pointer-events: none;
}
body.is-share .d-czc-face, body.is-share .sp-card, body.is-share .sp-rc { container-type: inline-size; }
body.is-share .d-czc-face { position: absolute; }
body.is-share .viewer-card img {
  -webkit-mask-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 816 1110" preserveAspectRatio="none"%3E%3Cmask id="m"%3E%3Crect width="816" height="1110" fill="%23fff"/%3E%3Ctext x="408" y="1086" text-anchor="middle" font-family="Georgia,serif" font-style="italic" font-size="30" letter-spacing="3" fill="%238c8c8c"%3Equalia%3C/text%3E%3C/mask%3E%3Crect width="816" height="1110" mask="url(%23m)"/%3E%3C/svg%3E');
  mask-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 816 1110" preserveAspectRatio="none"%3E%3Cmask id="m"%3E%3Crect width="816" height="1110" fill="%23fff"/%3E%3Ctext x="408" y="1086" text-anchor="middle" font-family="Georgia,serif" font-style="italic" font-size="30" letter-spacing="3" fill="%238c8c8c"%3Equalia%3C/text%3E%3C/mask%3E%3Crect width="816" height="1110" mask="url(%23m)"/%3E%3C/svg%3E');
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}

/* --- Every deck in its packaging: two product shots under the title (lib/productshot.js) ------ */
.d-product { margin: var(--s3) 0 var(--s2); }
.d-product[hidden], body.is-drawing .d-product { display: none; }   /* a live draw keeps the table */
.d-shots-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
.d-shot { margin: 0; aspect-ratio: 1; border-radius: 12px; overflow: hidden; background: #dcd3c6; }
.d-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.d-shots-cap { margin: var(--s2) 0 0; text-align: center; color: var(--ink-2); }
@media (min-width: 1024px) {
  .d-product { grid-column: 1; grid-row: 3; margin: var(--s6) 0 0; }
  .d-shots-cap { text-align: left; }
}
