﻿/* ============ Design tokens (COLOR-REDESIGN-SPEC v2 "Modern Felt", D1) ============
   Conflict record 2026-08-09: the spec's hex references (DESIGN-ROUND5/audit:
   `#265e51`) do NOT match the token literal's true render — oklch(0.34 0.055 165)
   renders #174131. Implemented the DOCUMENTED felt appearance; family re-derived
   from oklch(0.44 0.063 176) ≈ #265e51 keeping the sheet's L/C spacing/hue rules. */
:root {
  /* ---- surfaces — the felt, modernized (deeper + cooler than old #1f7a5c) ---- */
  --bg:        oklch(0.44 0.063 176);   /* deep calm green felt ≈ #265e51 */
  --surface:   oklch(0.52 0.073 176);   /* drop wells / valid target lighten */
  --surface-2: oklch(0.38 0.05 176);    /* recessed wells (stats) */
  --shade:      oklch(0 0 176);         /* darken mix target — SAME hue as felt; plain oklch(0 0 0) interpolates hue 176→0 through olive (C10) */
  --suit-ghost: oklch(0.514 0.033 155); /* empty-well suit glyph — documented render #596D5F (C9) */

  /* ---- ink on felt ---- */
  --fg:       oklch(0.94 0.015 100);    /* crisp cream-white on green */
  --muted:    oklch(0.85 0.02 100);
  --on-ink:   oklch(0.26 0.02 100);     /* dark text on card */

  /* ---- structure — soft modern depth ---- */
  --border:     oklch(1 0 0 / 0.14);      /* hairline on felt */
  --hairline:   oklch(1 0 0 / 0.09);
  --shadow-card: 0 1px 2px oklch(0.12 0.04 176 / 0.30),
                 0 6px var(--col-gap) oklch(0.12 0.04 176 / 0.38);

  /* ---- the one accent — amber, modernized (richer, fewer warm tones) ---- */
  --accent:       oklch(0.80 0.13 72);
  --accent-ink:   oklch(0.28 0.04 72);
  --accent-focus: oklch(0.87 0.07 80);    /* focus rings / back motif strokes */
  --accent-ghost: oklch(0.80 0.13 72 / 0.22);   /* ghost-well tint / valid drop */

  /* ---- semantics ---- */
  --success: oklch(0.74 0.13 155);
  --danger:  oklch(0.62 0.19 28);
  --settings-fg: oklch(0.97 0.005 100);
  --settings-muted: oklch(0.95 0.01 100);
  --settings-danger: oklch(0.97 0.04 28);

  /* ---- cards — crisp cool whites now (the cream is gone) ---- */
  --card-face:   oklch(0.97 0.005 100);   /* near-white, cool, never cream, never #fff */
  --card-back:   oklch(0.24 0.04 165);    /* deep green-charcoal back, motif in accent */
  --card-ink:    oklch(0.16 0.015 200);
  --type-red:    oklch(0.52 0.19 28);     /* hearts & diamonds */
  --type-black:  oklch(0.18 0.02 200);    /* spades & clubs */

  --ease: cubic-bezier(.22,.61,.36,1);
  --ease-reverse: cubic-bezier(.64,0,.78,.39);
  --ease-glide: cubic-bezier(.2,.7,.2,1);
  --ease-glide-reverse: cubic-bezier(.8,0,.8,.3);

  --font: 'Inter', 'Helvetica Neue', system-ui, sans-serif;

  --card-scale: 1;
  --card-w: calc(100px * var(--card-scale));
  --card-h: calc(140px * var(--card-scale));
  --card-r: 8px;
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 14px;

  --col-gap: 12px;
  --step-down: 30.8px;
  --step-up: 44.8px;
  --waste-shift: 22px;
  --zone-gap: 16px;
  --tableau-budget: 677.6px;
  --board-content-w: 772px;
  --topbar-h: 72px;
  --nudge-dur: 2.4s;

  /* Temporary animation-audit timing; js/timing.js keeps cleanup and locks aligned. */
  --dur-base: 2000ms;
  --dur-glide: 2000ms;
  --dur-draw: 2000ms;
  --dur-flip: 2000ms;
  --dur-flick: 2000ms;
  --dur-gather: 2000ms;
  --dur-deal: 2000ms;
  --dur-drop: 2000ms;
  --dur-banner: 2000ms;
  --dur-fade: 2000ms;
  --dur-fall: 2000ms;
  --dur-cascade: 30ms;          /* per-card cascade inside a pile run */
  --dur-run: 45ms;              /* per-card cascade for tableau runs */
  --dur-grace-ghost: 2000ms;
  --dur-grace-cleanup: 2000ms;
  --dur-grace-lock: 2000ms;
  --dur-lock-flip: 2000ms;
  --dur-deal-settle: 2000ms;
  --dur-aces-delay: 2000ms;
  --dur-lock-deal: 4000ms;
  --dur-tick: 1000ms;           /* hud timer */
  --dur-nudge: 6000ms;          /* includes 2s fade-in, hold, and fade-out */
  --dur-hint: 1200ms;           /* hint highlight stay */
  --dur-finish-bar: 8000ms;     /* finish-bar auto hide */
  --dur-finish-step: 90ms;      /* autoplay pacing */
  --dur-autoplay-poll: 40ms;    /* autoplay settled-check interval */
  --dur-autoplay-stall: 5000ms; /* autoplay settle timeout */
  --dur-release: 2000ms;

  --animate: full;
}

/* ---- size swatch F12 ---- */
html[data-size='s'] { --card-scale: 0.88; }
html[data-size='l'] { --card-scale: 1.12; }

/* ---- felt themes F12 (only these three) ---- */
html[data-felt='green'] {
  --bg: oklch(0.44 0.063 176);
  --surface: oklch(0.52 0.073 176);
  --surface-2: oklch(0.38 0.05 176);
  --shadow-card: 0 1px 2px oklch(0.12 0.04 176 / 0.30), 0 6px var(--col-gap) oklch(0.12 0.04 176 / 0.38);
}
html[data-felt='slate'] {
  --bg: oklch(0.40 0.035 250);
  --surface: oklch(0.48 0.045 250);
  --surface-2: oklch(0.34 0.03 250);
  --shade: oklch(0 0 250);
  --shadow-card: 0 1px 2px oklch(0.12 0.035 250 / 0.30), 0 6px var(--col-gap) oklch(0.12 0.035 250 / 0.38);
}
html[data-felt='charcoal'] {
  --bg: oklch(0.42 0.02 90);
  --surface: oklch(0.50 0.03 90);
  --surface-2: oklch(0.36 0.015 90);
  --shade: oklch(0 0 90);
  --shadow-card: 0 1px 2px oklch(0.12 0.02 90 / 0.30), 0 6px var(--col-gap) oklch(0.12 0.02 90 / 0.38);
}

/* ---- viewports: the 7 columns always fit, no horizontal scroll ---- */
@media (max-width: 1260px) {
  :root { --col-gap: 10px; --waste-shift: 18px; }
}
@media (max-width: 1000px) and (min-width: 721px) {
  :root {
    --col-gap: 8px;
    --waste-shift: 15px;
    --card-w: calc((min(88vw, 1280px) - 24px - 6 * var(--col-gap)) / 7 * var(--card-scale));
    --card-h: calc(var(--card-w) * 1.40);
  }
  /* foundations flow to a second row next to the stock (§5 breakpoints) */
  .toprow {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--col-gap);
    padding-bottom: 0;
  }
  .tablerow { padding-top: 8px; }
}
@media (max-width: 720px) {
  :root {
    --card-w: calc((100vw - 6 * var(--col-gap) - 8px) / 7 * var(--card-scale));
    --card-h: calc(var(--card-w) * 1.40);
    --step-down: 9px;
    --step-up: clamp(14px, calc(var(--card-h) * 0.22), 28px);
    --col-gap: 4px;
    --waste-shift: 13px;
    --topbar-h: 64px;
  }
  .topbar { flex-wrap: wrap; row-gap: 6px; padding: 8px 10px; }
  .brand { font-size: 15px; }
  .topbar .stats { display: none; }
  .topbar .btn-primary { width: 40px; height: 40px; padding: 0; min-height: 40px; }
  .topbar .btn-primary .lbl { display: none; }
  .topbar .btn-primary .ico { display: block; }
  .sheet-stats { display: grid; }
}
@media (max-width: 420px) {
  :root { --col-gap: 2px; --waste-shift: 10px; }
  .brand { font-size: 14px; }
  .seg button { padding: 9px 8px; }
  .sheet-stats .stat-score, .sheet-stats .stat-streak { display: none; }
}
@media (max-height: 840px) and (min-width: 721px) {
  :root {
    --card-w: calc(clamp(64px, 100vh - 470px, 96px) * var(--card-scale));
    --card-h: calc(var(--card-w) * 1.40);
    --step-up: clamp(16px, calc(var(--card-h) * 0.26), 28px);
  }
}
/* short landscape: keep a full 13-card column on screen without scroll */
@media (max-height: 620px) {
  :root {
    --step-down: 8px;
    --step-up: clamp(12px, calc(var(--card-h) * 0.2), 22px);
  }
}

*, *::before, *::after { box-sizing: border-box; }
* { touch-action: manipulation; }

html, body { margin: 0; min-height: 100%; }

body {
  font-family: var(--font);
  line-height: 1.5;
  color: var(--fg);
  background: var(--bg);
  user-select: none;
  -webkit-user-select: none;
  -webkit-font-smoothing: antialiased;
}

button { font-family: var(--font); }

/* ============ Top rail (72px, the field owns the screen) ============ */
#app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  height: 100dvh;
  position: relative;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: var(--topbar-h);
  padding: 0 16px;
  background: color-mix(in oklch, var(--bg), var(--shade) 18%);
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}

.brand {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.stats {
  display: flex;
  align-items: center;
  gap: 20px;
  background: var(--surface-2);
  border-radius: 8px;
  padding: 7px 16px;
}

.stat {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.stat b {
  margin-left: 5px;
  color: var(--fg);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* segmented control — neutral, never accent */
.seg {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.seg button {
  appearance: none;
  background: transparent;
  border: none;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  padding: 9px 12px;
  min-height: 40px;
  cursor: pointer;
}

.seg button:hover { color: var(--fg); }
.seg button.on { color: var(--fg); background: rgba(255, 255, 255, 0.1); }
.seg button:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: -2px; }

/* buttons — one primary per action, ghosts everywhere else */
.btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 8px 14px;
  min-height: 40px;
  cursor: pointer;
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease), transform 0.12s var(--ease);
}

.btn:hover { background: rgba(255, 255, 255, 0.1); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible,
.card:focus-visible,
.pad[data-board-control]:focus-visible,
.icon-btn:focus-visible {
  outline: 2px solid var(--accent-focus);
  outline-offset: 3px;
}

.btn-ghost { border-color: rgba(255, 255, 255, 0.28); }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.btn-primary:hover {
  background: color-mix(in oklch, var(--accent), oklch(0 0 72 / 14%));
}

.btn.ic, .icon-btn {
  width: 40px;
  height: 40px;
  padding: 0;
  min-height: 40px;
}

.btn:disabled { opacity: 0.55; }
.btn-small { min-height: 34px; padding: 4px 10px; font-size: 12px; }
.btn-block { width: 100%; }

.btn svg { flex: 0 0 auto; }

/* ============ Board ============ */
#board {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 8px;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--zone-gap);
  overflow: hidden;
}


.toprow, .tablerow {
  display: grid;
  gap: var(--col-gap);
  justify-content: center;
  margin: 0;
  position: relative;
  width: var(--board-content-w);
}

.toprow {
  grid-template-columns: repeat(2, var(--card-w)) 1fr repeat(4, var(--card-w));
}

.toprow > :nth-child(1) { grid-column: 1; }
.toprow > :nth-child(2) { grid-column: 2; }
.toprow > :nth-child(3) { grid-column: 4; }
.toprow > :nth-child(4) { grid-column: 5; }
.toprow > :nth-child(5) { grid-column: 6; }
.toprow > :nth-child(6) { grid-column: 7; }

.tablerow {
  grid-template-columns: repeat(7, var(--card-w));
  align-items: start;
  height: var(--tableau-budget);
}

.tablerow { padding-top: 0; }

.pad {
  position: relative;
  width: var(--card-w);
  height: var(--card-h);
  border-radius: var(--card-r);
  background: color-mix(in oklch, var(--surface), var(--shade) 14%);
  border: 1px dashed var(--border);
  grid-column: span 1;
}

.pad.waste { position: relative; isolation: isolate; }

.pad .wellmark {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: var(--card-h);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  opacity: 0.4;
  font-size: 22px;
  font-weight: 600;
  pointer-events: none;
  letter-spacing: 0.04em;
  pointer-events: none;
}

/* keep the empty-hint glyph beneath transient waste "keeper" cards */
.pad.waste .wellmark { z-index: -2; }

.pad .wellmark svg { width: 100%; height: 100%; display: block; }

/* foundation empty hint well */
.pad.foundation .wellmark { opacity: 0.45; }
.pad.foundation { border-style: solid; border-color: color-mix(in oklch, var(--border), transparent 30%); }
.pad.tableau { border: none; background: transparent; }
.pad.tableau::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: var(--card-h);
  border-radius: var(--card-r);
  background: color-mix(in oklch, var(--surface), var(--shade) 14%);
  border: 1px dashed var(--border);
}


/* the card (face & back live in js/cards.js) */
.card {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--card-w);
  height: var(--card-h);
  border-radius: var(--card-r);
  background: var(--card-face);
  box-shadow: var(--shadow-card);
  color: var(--card-ink);
  cursor: grab;
  touch-action: none;
  transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease);
  -webkit-tap-highlight-color: transparent;
  outline: none;
}

.card svg { width: 100%; height: 100%; display: block; }

.waste .card { left: min(calc(var(--shift) * var(--waste-shift)), calc(var(--card-w) - 8px)); }
.waste .card[data-role='waste-buried'] { pointer-events: none; cursor: default; }
.stock .card, .found .card { cursor: default; }

/* decorative deck kept on the stock while a draw is in flight — never a real
   game card, pointer-transparent so it can't be drawn/dragged mid-flight */
.stock-deck { pointer-events: none; }

/* hover — lifts 4px with a deeper shadow, cursor stays grab via .card.
   Exclude cards mid-flight (.glide) and mid-flip (.drawing): their animated
   transform would be overridden anyway, and the hover shadow would paint a
   full-card ghost behind the transparent rotating faces. */
@media (hover: hover) and (pointer: fine) {
  .card:hover:not(.face-down):not(.drawing):not(.glide) {
    transform: translateY(-4px);
    box-shadow: 0 10px var(--col-gap) oklch(0.15 0.04 176 / 0.45);
  }
}

/* interaction states (§7) — selection ring comes from keyboard focus (:focus-visible), never click/tap */
.card.selected { outline: none; }

.valid, .valid-target { box-shadow: inset 0 0 0 2px var(--accent); background: var(--surface); }
.drop-valid { box-shadow: inset 0 0 0 2px var(--accent); background: var(--surface); }

.hinted { outline: 2px solid var(--accent); outline-offset: 2px; }

.bump { animation: bump var(--dur-flick) var(--ease); }
@keyframes bump {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-1.5px); }
  75% { transform: translateX(1.5px); }
}

@media (prefers-reduced-motion: reduce), html[data-motion='off'] {
  .bump { animation-duration: 100ms; }
}

/* deal-in */
.deal .card { animation: deal var(--dur-deal) var(--ease) both; animation-delay: calc(var(--deal-delay, 0) * 1ms); }
@keyframes deal {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* draw: the card turns over while flying in — back face first, then the face.
   .flip-stage rotates 0→180 with only ONE face opaque at a time: the back is
   shown for the first half, the faces swap opacity at 90° (where the card is
   edge-on / invisible), then the front shows for the second half. No
   backface-visibility or preserve-3d needed, so stacking contexts can never
   make a mirrored ghost face leak through. The glide (translate) runs on the
   .card itself; the turn runs on the stage, so they never fight. */
.card.drawing {
  background: transparent;
  box-shadow: none;
  transition: none;
  perspective: 1000px;
}
.flip-stage {
  position: absolute;
  inset: 0;
  box-shadow: var(--shadow-card);
  animation: flipOver var(--flip-dur, var(--dur-flip)) cubic-bezier(.45, .2, .55, .9) var(--flip-delay, 0s) both;
}
.flip-face {
  position: absolute;
  inset: 0;
}
.flip-back { animation: backGone var(--flip-dur, var(--dur-flip)) linear var(--flip-delay, 0s) both; }
.flip-front { transform: rotateY(180deg); animation: frontGone var(--flip-dur, var(--dur-flip)) linear var(--flip-delay, 0s) both; }
.turn-reverse .flip-stage,
.turn-reverse .flip-back,
.turn-reverse .flip-front { animation-direction: reverse; }
@keyframes flipOver {
  from { transform: rotateY(0); }
  to { transform: rotateY(180deg); }
}
@keyframes backGone {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}
@keyframes frontGone {
  0%, 50% { opacity: 0; }
  50.01%, 100% { opacity: 1; }
}

/* outgoing waste cards on draw: behave like a real pile. Turn-1: the previous
   card stays in place until the new one lands on top of it. Turn-3: the old fan
   gathers into the stack (slides to the pile spot) while the new trio flips in. */
.waste-stay {
  z-index: -1;
  pointer-events: none;
}
.waste-arrival-stay {
  z-index: -1;
  pointer-events: none;
}
.waste-stay.waste-grouping {
  animation: wasteGroup var(--dur-gather) var(--ease) both;
}

/* while a card glides into a foundation, keep the previous top card (or the
   empty-well glyph) visible beneath the flight — same ghost pattern as waste.
   z 0 (not -1 like .waste-stay): the foundation pad is NOT isolated, so a
   negative z would paint under the pad's own felt surface and border */
.foundation-stay {
  z-index: 0;
  pointer-events: none;
}
@keyframes wasteGroup {
  to { transform: translateX(calc(var(--shift, 0) * var(--waste-shift) * -1)); }
}

/* undo of draw (turn 3): the buried group un-gathers from the stack back to
   its fan — the exact reverse of waste-grouping, opening at the same phase
   of the flow the gather did (t0) so the fan settles beneath the departing
   cards, mirroring how the old fan gathered beneath the arriving trio */
.waste-unfan { animation: wasteGroup var(--dur-gather) var(--ease) var(--unfan-delay, 0ms) reverse both; }

/* FLIP glide — the card rides from its previous spot (--fx/--fy set in JS) to rest. */
.glide {
  z-index: var(--glide-z, 300);
  animation: glide var(--glide-dur, var(--dur-glide)) var(--ease-glide) backwards;
}
.glide.glide-reverse { animation-timing-function: var(--ease-glide-reverse); }
@keyframes glide {
  from { transform: translate(var(--fx, 0px), var(--fy, 0px)); }
  to { transform: translate(0, 0); }
}

.draw-reverse,
.redeal-flyer {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  perspective: 1000px;
  width: var(--card-w);
  height: var(--card-h);
}

.draw-reverse {
  z-index: var(--glide-z, 300);
  animation: glide var(--fly-dur, var(--dur-glide)) var(--ease-glide) var(--fd, 0ms) reverse backwards;
}
.draw-reverse .flip-stage,
.draw-reverse .flip-back,
.draw-reverse .flip-front { animation-direction: reverse; }

.fly-hidden { opacity: 0; }
.drag-reverse-flyer {
  position: fixed;
  z-index: 350;
  pointer-events: none;
  box-shadow: 0 18px 34px oklch(0.15 0.04 176 / 0.55);
  transition: none !important;
}
.fold-stage { position: absolute; inset: 0; box-shadow: var(--shadow-card); }
.fold-face { position: absolute; inset: 0; }
.fold-front { transform: rotateY(180deg); }

/* redeal: the waste rallies to the stock under the empty stock well. Each card
   carries two nested transform layers: the .gather-stage slides the fan into
   the pile spot (480ms, all in sync), while the inner .fold-stage folds the
   card face-down and flies it to the stock — starting IMMEDIATELY, staggered
   one per (1500ms / pile size), TOP card first. The fold's translate starts at
   (0,0), so an early flight compounds smoothly with the still-running gather
   (no snap, no pause); late flights just take off from the pile spot. Whole
   run uses the draw timing budget. Waiting/settled wrappers and the first 10%
   of source-resident motion stay at z40. Departing faces keep waste-pile order;
   at the exact 50.01% face/back swap, zBump inverts to stock order. Undo
   reverses the same layer and face keyframes. */
.redeal-flyer {
  animation: zBump var(--fly-dur, var(--dur-glide)) var(--fd, 0ms);
}
.redeal-flyer .gather-stage {
  position: absolute;
  inset: 0;
  perspective: 1000px;
  animation: redealGather var(--dur-gather) var(--ease) var(--gather-delay, 0ms) both;
}
.redeal-flyer .fold-stage {
  animation: redealFly var(--fly-dur, var(--dur-glide)) cubic-bezier(.45, .2, .55, .9) var(--fd, 0ms) both;
}
.redeal-flyer .fold-front { animation: foldFront var(--fly-dur, var(--dur-glide)) linear var(--fd, 0ms) backwards; }
.redeal-flyer .fold-back { animation: foldBack var(--fly-dur, var(--dur-glide)) linear var(--fd, 0ms) backwards; }
.redeal-flyer.redeal-reverse,
.redeal-flyer.redeal-reverse .gather-stage,
.redeal-flyer.redeal-reverse .fold-stage,
.redeal-flyer.redeal-reverse .fold-front,
.redeal-flyer.redeal-reverse .fold-back { animation-direction: reverse; }
@keyframes zBump {
  from, 10% { z-index: 40; }
  10.01%, 50% { z-index: var(--redeal-face-z, 120); }
  50.01%, to { z-index: var(--redeal-back-z, 60); }
}
@keyframes redealGather {
  from { transform: translate(var(--gx, 0px), var(--gy, 0px)); }
  to { transform: translate(var(--sx, 0px), var(--sy, 0px)); }
}
@keyframes redealFly {
  from { transform: translate(0, 0) rotateY(180deg); }
  to { transform: translate(var(--tx, 0px), var(--ty, 0px)) rotateY(0deg); }
}

/* faces swap at the 90deg edge — each fold stage crosses it at ~50% of its easing window,
   matching the forward .flip-stage so the turn feels identical in both directions */
@keyframes foldFront { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
@keyframes foldBack { 0%, 50% { opacity: 0; } 50.01%, 100% { opacity: 1; } }

@media (prefers-reduced-motion: reduce), html[data-motion='off'] {
  .bump,
  .glide,
  .waste-grouping,
  .waste-unfan,
  .draw-reverse,
  .redeal-flyer,
  .fold-stage,
  .fold-front,
  .fold-back { animation: none !important; }
  .drawing .flip-stage,
  .drawing .flip-back,
  .drawing .flip-front { animation: none; }
  .drawing .flip-back { opacity: 0; }
  .drawing .flip-front { opacity: 1; }
  .deal .card,
  .banner,
  .sheet { animation: reducedFade 100ms linear both !important; }
}

@keyframes reducedFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* win banner */
.overlay {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100dvh;
  max-height: none;
  margin: 0;
  border: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: oklch(0.12 0.04 176 / 0.5);
  z-index: 400;
  padding: 20px;
}

.overlay[open] { display: flex; }
.overlay::backdrop { background: transparent; }

.banner {
  position: relative;
  width: min(420px, 92vw);
  background: var(--card-face);
  color: var(--card-ink);
  border-radius: var(--r-lg);
  padding: 36px 40px 32px;
  text-align: center;
  box-shadow: 0 22px 60px oklch(0.12 0.05 176 / 0.55);
  border: 2px solid var(--success);
  animation: banner var(--dur-banner) var(--ease);
}
@keyframes banner {
  from { opacity: 0; transform: translateY(10px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: color-mix(in oklch, var(--success), var(--card-ink) 40%);
}

.banner h3 {
  margin: 8px 0 20px;
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.1;
}

.banner-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 24px;
}

.banner-stats div {
  background: color-mix(in oklch, var(--card-ink), oklch(1 0 0 / 6%));
  border-radius: var(--r-md);
  padding: 10px 8px;
}

.banner-stats span {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.banner-stats b { font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }

.banner .btn { width: 100%; }

/* confetti — short, non-blocking, reduced-motion aware */
.confetti {
  position: fixed;
  top: -12px;
  left: 0;
  right: 0;
  height: 60vh;
  pointer-events: none;
  z-index: 401;
  overflow: hidden;
}

.confetti i {
  position: absolute;
  top: -14px;
  width: 8px;
  height: 8px;
  background: var(--accent);
  animation: fall var(--dur-fall) var(--ease) forwards;
}

.confetti i:nth-child(3n) { background: var(--success); }
.confetti i:nth-child(3n + 1) { background: var(--danger); }

@keyframes fall {
  from { opacity: 1; transform: translateY(0) rotate(0deg); }
  to {
    opacity: 0.6;
    transform: translateY(58vh) rotate(540deg);
  }
}

@media (prefers-reduced-motion: reduce), html[data-motion='off'] {
  .confetti i { animation: none; opacity: 0; }
}

/* settings sheet */
.sheet {
  width: min(460px, 94vw);
  max-height: 86vh;
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 22px 24px;
  animation: banner var(--dur-banner) var(--ease);
  color: var(--settings-fg);
  scrollbar-gutter: stable;
  overscroll-behavior: contain;
}

.sheet-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.sheet h3 { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }

/* session stats — shown inside the sheet on mobile (topbar collapses) */
.sheet-stats {
  display: none;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 4px 0 0;
}

.sheet-stats .stat {
  background: color-mix(in oklch, var(--surface-2), var(--shade) 20%);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 8px 4px;
  text-align: center;
}

.sheet-stats .stat span {
  display: block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--settings-muted);
}

.sheet-stats .stat b {
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 14px 0;
  border-top: 1px solid var(--border);
  font-size: 14px;
}

.row:first-of-type { border-top: none; }
.row .lbl { line-height: 1.35; }
.row .lbl small {
  display: block;
  color: var(--settings-muted);
  font-size: 12px;
  font-weight: 400;
}

.switches { display: flex; gap: 6px; flex-wrap: nowrap; justify-content: flex-end; }

.switches button {
  appearance: none;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--settings-fg);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 7px 12px;
  border-radius: var(--r-sm);
  cursor: pointer;
  min-height: 38px;
}

.switches button:hover { background: color-mix(in oklch, var(--surface), var(--shade) 12%); }
.switches button.on { background: color-mix(in oklch, var(--surface), var(--shade) 20%); color: var(--settings-fg); }
.switches button:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 2px; }

.btn-danger {
  color: var(--settings-danger);
  border-color: color-mix(in oklch, var(--settings-danger), transparent 35%);
}
.btn-danger:hover { background: color-mix(in oklch, var(--surface), var(--shade) 14%); }
.sheet .btn:not(.btn-danger) { color: var(--settings-fg); }

/* status nudge — muted chip, never a toast */
.nudge {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  border-radius: 999px;
  padding: 10px 18px;
  opacity: 0;
  pointer-events: none;
  z-index: 350;
  transition: opacity var(--dur-fade) var(--ease);
  text-align: center;
  max-width: 80vw;
  white-space: nowrap;
}

.nudge.show { opacity: 1; }

/* ============ Embed widget (?embed=1) — board only, credit strip ============ */
.embed-strip {
  display: none;
  position: fixed;
  left: 50%;
  bottom: 10px;
  transform: translateX(-50%);
  z-index: 200;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--muted);
  background: color-mix(in oklch, var(--surface-2), var(--shade) 10%);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 12px;
  text-decoration: none;
  white-space: nowrap;
}

.embed-strip:hover { color: var(--fg); }

body.embed .topbar,
body.embed .article,
body.embed .nudge { display: none; }

body.embed .embed-strip { display: block; }

body.embed #board { min-height: 100vh; }

body.embed .finish { bottom: 44px; }

/* auto-finish cue — quiet, ghost-level */
.finish {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 360;
  color: var(--fg);
  font-size: 13px;
  font-weight: 500;
  box-shadow: var(--shadow-card);
}

.finish[hidden] { display: none; }

/* sr-only for aria-live announcements */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* hide the deal animation after load */
#board.dealt .card { animation: none; }

/* real-card drag — the actual run follows the pointer, no clones */
.drag-run {
  position: fixed;
  margin: 0;
  z-index: 300;
  pointer-events: none;
  will-change: transform;
  box-shadow: 0 18px 34px oklch(0.15 0.04 176 / 0.55);
  transition: none;
}

.drag-run.drag-tween { transition: transform var(--dur-release) cubic-bezier(.2, .7,.2, 1); }

/* the run is position:fixed, but its z-index stays trapped inside the source
   pad's stacking context (.pad.waste isolates) — so the pad itself must rise
   above every auto-level pad while a run is lifted out of it */
.pad:has(.drag-run) { z-index: 800; }
.pad:has(.glide) { z-index: 300; }
.pad:has(.glide-flight) { z-index: 310; }

body.is-dragging { cursor: grabbing; }
body.is-dragging * { cursor: grabbing !important; }

@media (max-width: 1000px) {
  .topbar .stats { display: none; }
  .sheet-stats { display: grid; }
}

@media (max-width: 720px) {
  .topbar { flex-wrap: wrap; row-gap: 6px; padding: 8px 10px; }
  .brand { font-size: 15px; }
  .topbar .stats { display: none; }
  .topbar .btn-primary { width: 40px; height: 40px; padding: 0; min-height: 40px; }
  .topbar .btn-primary .lbl { display: none; }
  .topbar .btn-primary .ico { display: block; }
  .sheet-stats { display: grid; }
}

@media (max-width: 480px) {
  .sheet {
    width: calc(100vw - 16px);
    max-height: calc(100dvh - 16px);
    padding: 18px 18px 28px;
  }
  .row { flex-direction: column; align-items: stretch; gap: 8px; }
  .switches { width: 100%; justify-content: stretch; }
  .switches button { flex: 1 1 0; min-width: 0; padding-inline: 8px; }
}

@media (max-width: 420px) {
  .brand { flex-basis: 100%; text-align: center; font-size: 14px; }
  .controls { width: 100%; min-width: 0; justify-content: center; gap: 4px; }
  .seg button { padding-inline: 6px; font-size: 11px; }
  #btn-undo { padding-inline: 8px; }
  .sheet-stats .stat-score, .sheet-stats .stat-streak { display: none; }
}

/* touch: selection outlines & tap targets */
@media (pointer: coarse) {
  .btn, .seg button, .switches button { min-height: 44px; }
  .topbar .btn,
  .topbar .seg button,
  .topbar .btn-primary,
  .topbar .btn.ic,
  .topbar .icon-btn { min-height: 44px; height: 44px; }
  .topbar .btn-primary,
  .topbar .seg button,
  .topbar .btn.ic,
  .topbar .icon-btn { min-width: 44px; width: 44px; }
}

/* ============ Article / SEO (unchanged layout-wise) ============ */
.article {
  max-width: 760px;
  margin: 0 auto;
  padding: 40px 20px 60px;
  color: var(--fg);
  font-size: 16px;
}

.article h1 { font-size: 30px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.1; }
.article h2 { font-size: 26px; font-weight: 600; letter-spacing: -0.01em; margin: 2.4rem 0 0.8rem; }
.article p { line-height: 1.5; }
.article ul { line-height: 1.6; padding-left: 1.2em; }
.article details { margin: 1rem 0; }
.article summary { font-weight: 600; cursor: pointer; }

@media (forced-colors: active) {
  :root {
    --bg: Canvas;
    --surface: Canvas;
    --surface-2: Canvas;
    --fg: CanvasText;
    --muted: CanvasText;
    --settings-fg: CanvasText;
    --settings-muted: CanvasText;
    --settings-danger: CanvasText;
    --card-face: Canvas;
    --card-back: CanvasText;
    --card-ink: CanvasText;
    --type-red: CanvasText;
    --type-black: CanvasText;
    --suit-ghost: CanvasText;
    --accent: Highlight;
    --accent-focus: Highlight;
    --accent-ink: HighlightText;
    --border: CanvasText;
    --hairline: CanvasText;
  }
  .card,
  .pad,
  .sheet,
  .banner,
  .btn,
  .seg,
  .switches button { border-color: CanvasText; box-shadow: none; forced-color-adjust: auto; }
  .card { border: 1px solid CanvasText; }
  .card.face-up { background: Canvas; color: CanvasText; }
  .card.face-down { background: CanvasText; color: Canvas; }
  .card.face-up svg text,
  .wellmark svg text { fill: CanvasText !important; }
  .card.face-up svg path,
  .wellmark svg path { fill: CanvasText !important; stroke: CanvasText !important; }
  .pad .wellmark,
  .pad.foundation .wellmark { opacity: 1; }
  .card:focus-visible,
  .hinted,
  .valid,
  .valid-target,
  .drop-valid { outline: 3px solid Highlight; outline-offset: 2px; box-shadow: none; }
  .btn:focus-visible,
  .card:focus-visible,
  .pad[data-board-control]:focus-visible,
  .icon-btn:focus-visible { outline-color: Highlight; }
  .btn-primary { background: Highlight; color: HighlightText; }
  .btn-primary,
  .btn-primary .lbl { forced-color-adjust: none; }
}

.no-motion *, html[data-motion='off'] * {
  animation-duration: 0.12s !important;
  animation-delay: 0s !important;
}
.no-motion :is(.btn, .card, .nudge, .drag-run.drag-tween),
html[data-motion='off'] :is(.btn, .card, .nudge, .drag-run.drag-tween) {
  transition-duration: 0.12s !important;
}

@media (prefers-reduced-motion: no-preference) {
  html[data-motion='on'] *,
  html[data-motion='on'] *::before,
  html[data-motion='on'] *::after {
    animation-duration: 2000ms !important;
  }
  html[data-motion='on'] :is(.btn, .card, .nudge, .drag-run.drag-tween) {
    transition-duration: 2000ms !important;
  }
}
