/* ==========================================================================
   Third Base — blackjack trainer chrome.
   Materials (felt/wood/cards) live in assets/table.svg + assets/cards.js.
   Every colour here is either a var(--tb-*) token from assets/tokens.css or
   copied verbatim from thirdbase-design-package/reference/mockup.html — the
   authoritative reference this restyle implements. Nothing here is invented.
   ========================================================================== */

* { box-sizing: border-box; margin: 0; padding: 0; }

html { min-height: 100%; scroll-behavior: smooth; }

body {
  min-height: 100vh;
  background: var(--tb-backdrop);
  font-family: var(--tb-font-ui);
  color: var(--tb-cream);
  -webkit-font-smoothing: antialiased;
  line-height: 1.6;
}

button, select, input { font: inherit; }
a { color: inherit; }

/* ---------- public site shell ---------- */
.site-header {
  position: relative; z-index: 10;
  border-bottom: 1px solid rgba(238,213,150,.12);
  background: transparent;
}
.site-header__inner {
  width: min(1120px, calc(100% - 40px)); min-height: 68px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 28px;
}
.site-brand {
  display: inline-flex; flex: 0 0 auto; align-items: center; text-decoration: none;
}
.site-brand img { display: block; width: 52px; height: 52px; object-fit: contain; }
.site-nav { display: flex; align-items: center; gap: 26px; }
.site-nav a, .site-footer a {
  color: var(--tb-cream-2); text-decoration: none; font-size: .82rem; font-weight: 600;
}
.site-nav a:hover, .site-footer a:hover { color: var(--tb-gold-ink); }

.site-main { width: 100%; overflow: hidden; }
.site-hero {
  width: min(820px, calc(100% - 40px)); margin: 0 auto; padding: 78px 0 52px;
  text-align: center;
}
.site-eyebrow {
  margin-bottom: 10px; color: var(--tb-gold-ink); font-size: .72rem; font-weight: 700;
  letter-spacing: var(--tb-tracking-label); text-transform: uppercase;
}
.site-hero h1, .content-section h2 {
  font-family: var(--tb-font-felt); color: var(--tb-cream); line-height: 1.12;
}
.site-hero h1 { max-width: 790px; margin: 0 auto; font-size: clamp(2rem, 5vw, 3.65rem); }
.site-hero__lead {
  max-width: 720px; margin: 24px auto 0; color: var(--tb-cream-2); font-size: 1.05rem;
}
.site-hero__note { margin-top: 10px; color: var(--tb-muted); font-size: .86rem; }
.site-cta {
  display: inline-flex; margin-top: 28px; padding: 12px 22px;
  border: 1px solid var(--tb-gold-lo); border-radius: var(--tb-r-md);
  background: linear-gradient(180deg, var(--tb-gold-hi), var(--tb-gold));
  box-shadow: 0 14px 30px -18px rgba(216,180,92,.9);
  color: #2a1f06; font-size: .78rem; font-weight: 700; letter-spacing: .08em;
  text-decoration: none; text-transform: uppercase;
}
.site-cta:hover { filter: brightness(1.06); transform: translateY(-1px); }

.trainer-section {
  width: min(720px, calc(100% - 24px)); margin: 0 auto; padding: 12px 0 76px;
}

.content-section {
  width: min(1040px, calc(100% - 40px)); margin: 0 auto; padding: 78px 0;
  border-top: 1px solid rgba(238,213,150,.14);
}
.content-section h2 { max-width: 760px; margin-bottom: 20px; font-size: clamp(1.65rem, 3vw, 2.45rem); }
.content-section > p:not(.site-eyebrow):not(.content-disclaimer) {
  max-width: 780px; color: var(--tb-cream-2);
}
.content-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 34px; }
.content-cards article, .content-callout {
  padding: 24px; border: 1px solid rgba(238,213,150,.16); border-radius: var(--tb-r-lg);
  background: rgba(20,28,22,.56);
}
.content-cards article > span { color: var(--tb-gold); font-size: .72rem; font-weight: 700; letter-spacing: .12em; }
.content-cards h3 { margin: 12px 0 8px; color: var(--tb-cream); font-family: var(--tb-font-felt); font-size: 1.05rem; }
.content-cards p, .content-callout p { color: var(--tb-cream-2); font-size: .9rem; }
.content-section--split { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(260px, .8fr); gap: 56px; align-items: center; }
.content-section--split > div:first-child > p:last-child { color: var(--tb-cream-2); }
.content-callout strong { display: block; margin-bottom: 12px; color: var(--tb-gold-ink); font-family: var(--tb-font-felt); }
.content-callout p + p { margin-top: 10px; }
.rules-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px 28px; margin: 30px 0; }
.rules-grid p { padding-bottom: 10px; border-bottom: 1px solid rgba(238,213,150,.1); color: var(--tb-cream-2); font-size: .9rem; }
.rules-grid strong { color: var(--tb-cream); }
.content-disclaimer {
  max-width: 900px; padding: 18px 20px; border-left: 3px solid var(--tb-gold-lo);
  background: rgba(138,109,24,.08); color: var(--tb-muted); font-size: .86rem;
}
.site-footer {
  border-top: 1px solid rgba(238,213,150,.14); color: var(--tb-muted); font-size: .8rem;
}
.site-footer > div, .site-footer > p {
  width: min(1120px, calc(100% - 40px)); margin-left: auto; margin-right: auto;
}
.site-footer > div { display: flex; justify-content: space-between; gap: 24px; padding: 30px 0 14px; }
.site-footer nav { display: flex; flex-wrap: wrap; gap: 10px 20px; justify-content: flex-end; }
.site-footer > p { padding-bottom: 30px; }

.tb-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;
}

/* ---------- frame / stage ---------- */
.tb-frame {
  position: relative;
  width: 100%;
  max-width: 640px;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 40px 90px -30px #000, 0 0 0 1px #1c211d;
  background: #0b0f0c;
  margin: 0 auto;
}
/* The SVG viewBox stays 1180x760 (every internal coordinate is unchanged) —
   narrowing this box to 640/760 relies on preserveAspectRatio="xMidYMid slice"
   to crop the sides at 1:1 scale, centred on the felt, rather than shrinking
   everything down. That keeps text/cards/chips at the same rendered size. */
.tb-stage { position: relative; width: 100%; aspect-ratio: 640 / 760; }
.tb-stage svg.table { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.tb-layer { position: absolute; inset: 0; pointer-events: none; }
.tb-layer > * { pointer-events: auto; }

/* ---------- gear: the only permanent chrome ---------- */
.tb-gear {
  position: absolute; top: 2.4%; left: 1.6%;
  width: 38px; height: 38px; border-radius: 10px;
  background: var(--tb-glass); border: 1px solid var(--tb-glass-br);
  backdrop-filter: var(--tb-blur);
  display: grid; place-items: center; cursor: pointer;
  color: var(--tb-gold-ink); font-size: 16px;
  transition: background var(--tb-t-fast), border-color var(--tb-t-fast);
}
.tb-gear:hover, .tb-gear[aria-expanded="true"] { background: rgba(8,14,10,.8); border-color: rgba(238,213,150,.6); }

/* ---------- onboarding tooltip: points at the gear, dismissed on first click ---------- */
.tb-tooltip {
  position: absolute; top: 2.4%; left: 58px;
  max-width: 180px; z-index: 3;
  padding: 9px 13px; border-radius: 10px;
  background: #fff; border: 1px solid rgba(0,0,0,.08);
  box-shadow: var(--tb-shadow-pop);
  color: var(--tb-ink); font-size: 12.5px; line-height: 1.35;
  animation: tb-tooltip-in var(--tb-t-slow) var(--tb-ease);
}
.tb-tooltip[hidden] { display: none; }
.tb-tooltip::before {
  content: ""; position: absolute; top: 50%; left: -6px;
  width: 11px; height: 11px;
  background: #fff;
  border-left: 1px solid rgba(0,0,0,.08); border-bottom: 1px solid rgba(0,0,0,.08);
  transform: translateY(-50%) rotate(45deg);
}
@keyframes tb-tooltip-in {
  from { opacity: 0; transform: translateX(-6px); }
  to { opacity: 1; transform: translateX(0); }
}

/* ---------- count readout: hidden unless asked for. Stacked vertically and
   pushed further right, clear of the rail curve, so a wide fanned-out hand
   (splits, multiple hits) growing rightward from centre never reaches it —
   a horizontal row that wide would have. ---------- */
.tb-count {
  position: absolute; top: 66%; left: 84%;
  display: flex; flex-direction: column; gap: 1px; border-radius: 6px; overflow: hidden;
  border: 1px solid var(--tb-glass-br);
  background: var(--tb-glass-br);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity var(--tb-t-slow), transform var(--tb-t-slow);
}
body.show-count .tb-count { opacity: 1; transform: none; pointer-events: auto; }
.tb-count > div { background: var(--tb-glass-2); padding: 4px 9px; text-align: center; backdrop-filter: var(--tb-blur); }
.tb-count .k { font-size: 6px; letter-spacing: var(--tb-tracking-label); text-transform: uppercase; color: var(--tb-muted); }
.tb-count .v { font-size: 10px; font-weight: 600; color: var(--tb-cream); font-variant-numeric: tabular-nums; margin-top: 1px; }
.tb-count .v.pos { color: var(--tb-win); }

/* top:66%/left:84% is tuned for the tall desktop frame; .tb-frame is
   aspect-ratio-locked to its width, so on a narrow window the frame gets
   much shorter and that same fixed-px box both overlaps Split (which spans
   the full mobile .tb-actions row below it) and gets clipped by the frame's
   own right edge. Docking it by the gear instead — top-right mirroring
   top-left — keeps it clear of the actions row and the player's hand at any
   width, since that band is otherwise always empty. */
@media (max-width: 600px) {
  .tb-count { top: 2.4%; left: auto; right: 1.6%; }
}

/* ---------- board message: repurposes the spec's hint slot for general
   status (deal prompts, outcomes, errors) rather than misplay-only text. ---------- */
.tb-message {
  position: absolute; left: 50%; top: 54%; transform: translate(-50%, 0);
  max-width: min(600px, 90%);
  padding: 11px 20px; border-radius: 11px;
  background: var(--tb-glass-2); border: 1px solid var(--tb-glass-br);
  box-shadow: var(--tb-shadow-pop); backdrop-filter: var(--tb-blur);
  font-size: 13.5px; color: var(--tb-cream); text-align: center;
  transition: background var(--tb-t-slow), border-color var(--tb-t-slow);
}
.tb-message:empty { display: none; }
.tb-message.warn { background: var(--tb-warn-bg); border-color: var(--tb-warn-br); color: #f0ded9; }
.tb-message.correct { border-color: rgba(140, 224, 168, .5); }

/* Verdict text ("You stood on 16 vs T — basic strategy says hit. Dealer busts
   a T about 23% of the time.") routinely wraps to 3+ lines. The box only
   grows downward from its fixed top:54%, and that 54%→65.5% gap to the
   player's cards is a constant fraction of .tb-frame's height — but the
   frame itself gets much shorter in px on a phone (aspect-ratio-locked to
   its width) while the message's font/padding stay fixed px. So the same
   wrapped message that clears the gap on desktop eats through it on mobile.
   Moving the anchor up (more slack above, toward the mostly-empty gap under
   the dealer's total) and trimming type/padding restores that clearance. */
@media (max-width: 600px) {
  .tb-message {
    top: 40%;
    max-width: 94%;
    padding: 8px 14px;
    font-size: 11.5px;
    line-height: 1.32;
  }
}

/* ---------- actions ---------- */
.tb-actions {
  position: absolute; left: 50%; bottom: 8.4%; transform: translateX(-50%);
  display: flex; gap: 10px; align-items: center;
}
.tb-act {
  min-width: 104px; padding: 11px 20px; border-radius: 11px; cursor: pointer;
  background: linear-gradient(180deg, rgba(20,28,22,.86), rgba(6,12,8,.92));
  border: 1px solid var(--tb-glass-br);
  box-shadow: var(--tb-shadow-btn);
  backdrop-filter: var(--tb-blur);
  color: var(--tb-cream-2); font-size: 12.5px; font-weight: 600;
  letter-spacing: var(--tb-tracking-btn); text-transform: uppercase; text-align: center;
  white-space: nowrap;
  transition: color var(--tb-t-fast), border-color var(--tb-t-fast), transform var(--tb-t-fast), box-shadow var(--tb-t-fast);
}
.tb-act:hover:not(:disabled) { color: var(--tb-gold-hi); border-color: rgba(238,213,150,.6); transform: translateY(-1px); }
.tb-act:disabled { opacity: .3; cursor: not-allowed; }
/* Five buttons at desktop min-width (104px each + gaps) need ~585px — the
   row was spilling out both sides of the frame on any phone, since .tb-actions
   is centred and .tb-frame never gets that wide. Shrinking them down to fit
   (content-sized, cramped padding) got them on-screen but made them fiddly
   to tap — so instead .tb-actions now spans the frame width and each button
   is an equal flex share of it, filling the row edge-to-edge with a taller
   (not just narrower) touch target than the desktop button ever had. Scoped
   to .tb-actions specifically — .tb-act is also used by the unrelated
   highscores/streak-prompt buttons, which don't want any of this.
   "Deal hand"/"New hand" is the longest label and doesn't fit this width on
   one line even at a small font, so nowrap is dropped in favour of letting
   it wrap to two lines rather than spilling past its own button edge. */
@media (max-width: 600px) {
  .tb-actions { left: 3%; right: 3%; transform: none; gap: 4px; }
  .tb-actions .tb-act {
    flex: 1 1 0; min-width: 0; padding: 10px 2px;
    font-size: 9.5px; letter-spacing: .03em; border-radius: 8px;
    white-space: normal; line-height: 1.25;
  }
}
.tb-act--primary {
  background: linear-gradient(180deg, var(--tb-gold-hi), var(--tb-gold) 55%, #a8842f);
  color: #2a1f06; border-color: var(--tb-gold-lo);
  box-shadow: 0 12px 28px -12px rgba(216,180,92,.7), inset 0 1px 0 rgba(255,255,255,.6);
}
.tb-act--primary:hover { filter: brightness(1.06); transform: translateY(-1px); }
/* Subtle marking of the correct move — kept from the old design, restyled to
   the new palette, rather than the spec's post-hoc misplay-only hint. A soft
   glowing ring rather than a colour swap: the button keeps its normal fill
   and label colour, just gains a faint green outline that glows slightly. */
.tb-act--recommended:not(:disabled) {
  border-color: var(--tb-win);
  box-shadow: 0 0 0 1px var(--tb-win), 0 0 9px 1px rgba(140,224,168,.55);
}

/* ---------- status bar ---------- */
.tb-status {
  position: absolute; left: 0; right: 0; bottom: 0; height: 7.2%;
  display: flex; align-items: center; justify-content: center; gap: 22px;
  padding: 0 14px;
  background: linear-gradient(180deg, rgba(4,8,6,.72), rgba(2,4,3,.94));
  border-top: 1px solid var(--tb-glass-br);
  backdrop-filter: blur(10px);
}
.tb-status-field { display: flex; align-items: baseline; gap: 7px; white-space: nowrap; }
.tb-status-field .k { font-size: 9.5px; letter-spacing: var(--tb-tracking-label); text-transform: uppercase; color: var(--tb-muted); }
.tb-status-field .v { font-size: 16px; font-weight: 600; color: var(--tb-cream); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tb-status-field .v.gold { color: var(--tb-gold-ink); }
.tb-status-field .v.pos { color: var(--tb-win); }
.tb-status-field .v.neg { color: var(--tb-lose); }
.tb-status-field .k-short { display: none; }

/* Five fields at full desktop size overflow .tb-frame's width well before
   the frame itself shrinks to phone width (fluid up to 640px, but the status
   row needs ~460px) — that overflow, clipped by the frame's own
   overflow:hidden, was the "buggy" cut-off text on mobile. First cut to the
   bare minimum that fit a 320px phone with zero overflow, then sized back up
   25% (still well short of the ~460px desktop needs) once that turned out
   too small to read comfortably. That "bare minimum" turned out to mean
   gap:0 — labels and values across adjacent fields touch with nothing to
   separate them, which reads as broken even though nothing is actually
   clipped. There's no spare width left at these sizes to just add a gap
   back, so the labels swap to short forms (Bankroll -> Bank, Strategy ->
   Strat, ...) to buy the room a small gap needs instead. */
@media (max-width: 600px) {
  .tb-status { gap: 6px; padding: 0 4px; }
  .tb-status-field { gap: 1px; }
  .tb-status-field .k { font-size: 5.5px; }
  .tb-status-field .v { font-size: 10px; }
  .tb-status-field .k-full { display: none; }
  .tb-status-field .k-short { display: inline; }
}
@media (max-width: 340px) {
  .tb-status { gap: 4px; }
  .tb-status-field .k { font-size: 5px; }
  .tb-status-field .v { font-size: 9.3px; }
}

/* ---------- gear panel: settings, hidden until the gear is clicked ---------- */
.tb-gear-panel[hidden] { display: none; }
.tb-gear-panel {
  position: absolute; top: calc(2.4% + 46px); left: 1.6%;
  z-index: 2;
  display: grid; grid-template-columns: repeat(2, minmax(160px, 1fr)); gap: 12px 16px;
  width: min(480px, 90%);
  padding: 16px;
  border-radius: var(--tb-r-lg);
  background: var(--tb-glass-2); border: 1px solid var(--tb-glass-br);
  box-shadow: var(--tb-shadow-pop); backdrop-filter: var(--tb-blur);
}
.tb-setting label { display: block; margin-bottom: 6px; color: var(--tb-muted); font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.tb-setting select, .tb-setting input {
  width: 100%; min-height: 37px; padding: 7px 9px;
  border: 1px solid var(--tb-glass-br); border-radius: var(--tb-r-sm);
  color: var(--tb-cream); background: rgba(8,14,10,.7);
}
.tb-toggle { display: flex; align-items: center; gap: 9px; min-height: 33px; cursor: pointer; }
.tb-toggle input { width: 16px; height: 16px; accent-color: var(--tb-gold); }
.tb-toggle span { font-size: .82rem; color: var(--tb-cream-2); }

.tb-highscores-open {
  grid-column: 1 / -1;
  background: none; border: 1px solid var(--tb-glass-br); border-radius: var(--tb-r-sm);
  color: var(--tb-gold-ink); font-size: .82rem; font-weight: 600; text-align: left;
  padding: 8px 10px; cursor: pointer;
}
.tb-highscores-open:hover { border-color: rgba(238,213,150,.6); }

/* ---------- high scores: longest no-hint streak, shared across players ---------- */
.tb-highscores[hidden] { display: none; }
.tb-highscores {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
  z-index: 4; width: min(340px, 88%);
  padding: 16px; border-radius: var(--tb-r-lg);
  background: var(--tb-glass-2); border: 1px solid var(--tb-glass-br);
  box-shadow: var(--tb-shadow-pop); backdrop-filter: var(--tb-blur);
}
.tb-highscores-welcome {
  margin: 0 0 26px; font-size: .84rem; line-height: 1.5; color: var(--tb-cream-2); text-align: center;
}
.tb-highscores-welcome:last-of-type { margin-bottom: 0; }
.tb-highscores-start { display: block; width: fit-content; margin: 32px auto; }
.tb-highscores-label {
  margin: 0 0 10px; font-size: .78rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--tb-muted); text-align: center;
}
.tb-highscores-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.tb-highscores-list li {
  display: flex; align-items: baseline; gap: 10px;
  font-size: .86rem; color: var(--tb-cream);
}
.tb-highscores-list .rank { width: 1.4em; color: var(--tb-muted); font-variant-numeric: tabular-nums; }
.tb-highscores-list .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tb-highscores-list .streak { color: var(--tb-gold-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.tb-highscores-status { margin: 8px 0 0; font-size: .78rem; color: var(--tb-muted); text-align: center; }

/* ---------- streak prompt: only shown when a broken streak would actually
   place on the leaderboard — a real moment, styled a touch more deliberately
   than the plain settings/high-scores panels. ---------- */
.tb-streak-prompt[hidden] { display: none; }
.tb-streak-prompt {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
  z-index: 5; width: min(300px, 88%);
  padding: 20px; border-radius: var(--tb-r-lg);
  background: var(--tb-glass-2); border: 1px solid rgba(238,213,150,.5);
  box-shadow: 0 0 0 4px rgba(216,180,92,.12), var(--tb-shadow-pop); backdrop-filter: var(--tb-blur);
  text-align: center;
}
.tb-streak-prompt-title {
  margin: 0 0 6px; font-family: var(--tb-font-felt); font-size: 1.1rem; font-weight: 600;
  color: var(--tb-gold-ink); letter-spacing: .02em;
}
.tb-streak-prompt-body { margin: 0 0 14px; font-size: .84rem; color: var(--tb-cream-2); line-height: 1.5; }
.tb-streak-prompt-body #tb-streak-count { color: var(--tb-gold-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
#streak-initials {
  width: 100%; margin-bottom: 12px; padding: 10px; text-align: center;
  font-size: 1.2rem; font-weight: 700; letter-spacing: .3em; text-transform: uppercase;
  border: 1px solid var(--tb-glass-br); border-radius: var(--tb-r-sm);
  color: var(--tb-cream); background: rgba(8,14,10,.7);
}
.tb-streak-prompt .tb-act--primary { width: 100%; }

/* ---------- rules disclosure: below the frame, not on the felt ---------- */
.tb-help { width: 100%; max-width: 640px; margin: 14px auto 0; color: var(--tb-muted); font-size: .85rem; }
.tb-help summary { color: var(--tb-cream); cursor: pointer; }
.tb-help p { margin-top: 8px; }

@media (max-width: 760px) {
  .site-header__inner { min-height: 60px; width: min(1120px, calc(100% - 28px)); gap: 16px; }
  .site-brand img { width: 44px; height: 44px; }
  .site-nav { gap: 14px; overflow-x: auto; }
  .site-nav a { white-space: nowrap; font-size: .72rem; }
  .site-nav a:nth-child(2), .site-nav a:nth-child(3) { display: none; }
  .site-hero { width: min(820px, calc(100% - 32px)); padding: 56px 0 38px; }
  .site-hero__lead { font-size: .96rem; }
  .trainer-section { padding-bottom: 58px; }
  .content-section { width: min(1040px, calc(100% - 32px)); padding: 58px 0; }
  .content-cards, .rules-grid { grid-template-columns: 1fr; }
  .content-section--split { grid-template-columns: 1fr; gap: 28px; }
  .site-footer > div { flex-direction: column; }
  .site-footer nav { justify-content: flex-start; }
}

/* ---------- dealt cards: fly in from the shoe ---------- */
/* transform-origin matches CARD_W/2, CARD_H/2 from assets/cards.js (92x128). */
.tb-card-deal {
  animation: tb-deal-in var(--tb-t-slow) var(--tb-ease) both;
  transform: translate(var(--card-x), var(--card-y)) rotate(var(--card-rot));
  transform-origin: 46px 64px;
}
@keyframes tb-deal-in {
  from {
    transform: translate(calc(var(--card-x) + var(--card-from-dx)), calc(var(--card-y) + var(--card-from-dy)))
               rotate(var(--card-rot)) scale(.82);
    opacity: .85;
  }
  to {
    transform: translate(var(--card-x), var(--card-y)) rotate(var(--card-rot)) scale(1);
    opacity: 1;
  }
}

/* ---------- dealer hole card: flip face-up in place ---------- */
.tb-card-flip {
  animation: tb-flip-squeeze var(--tb-t-flip) var(--tb-ease);
  transform: translate(var(--card-x), var(--card-y)) rotate(var(--card-rot));
  transform-origin: 46px 64px;
}
@keyframes tb-flip-squeeze {
  0%   { transform: translate(var(--card-x), var(--card-y)) rotate(var(--card-rot)) scaleX(1); }
  50%  { transform: translate(var(--card-x), var(--card-y)) rotate(var(--card-rot)) scaleX(0); }
  100% { transform: translate(var(--card-x), var(--card-y)) rotate(var(--card-rot)) scaleX(1); }
}
.tb-card-flip-face--back  { animation: tb-flip-back  var(--tb-t-flip) var(--tb-ease); }
.tb-card-flip-face--front { animation: tb-flip-front var(--tb-t-flip) var(--tb-ease); }
@keyframes tb-flip-back  { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes tb-flip-front { 0%, 49% { opacity: 0; } 50%, 100% { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; }
}
