/* Wilder Cards — self-hosted so the app stays offline-capable and makes no
   third-party request on load. Zilla Slab carries the card faces (slab serifs
   are what printed card stock has always used); Space Grotesk runs the UI. */
@font-face {
  font-family: 'Space Grotesk';
  src: url('/assets/fonts/space-grotesk.woff2') format('woff2-variations'),
       url('/assets/fonts/space-grotesk.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Zilla Slab';
  src: url('/assets/fonts/zilla-slab-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Zilla Slab';
  src: url('/assets/fonts/zilla-slab-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Zilla Slab';
  src: url('/assets/fonts/zilla-slab-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
/* The two faces the cards are set in: a condensed display face for what a card
   says, and an inscriptional serif for the small labels around it. */
@font-face {
  font-family: 'Bebas Neue';
  src: url('/assets/fonts/bebas-neue-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cinzel';
  src: url('/assets/fonts/cinzel-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  /* The table the cards are read on: near-black, warmed by lamplight rather
     than the old green felt. Every colour here is taken from the card art —
     black stock, antique gold leaf, and the red of the W. */
  --table: #120f0d;
  --table-deep: #0a0807;
  --table-edge: #050403;
  --rail: #2a2018;

  /* surfaces */
  --panel: #1a1512;
  --panel-2: #12100e;
  --line: #43331f;
  --line-soft: #2b2117;

  /* ink */
  --ink: #f3ead8;
  --ink-dim: #b8a894;
  --ink-faint: #7d6e5d;

  /* leaf and lacquer */
  --gold: #d9ab52;
  --gold-bright: #f2d089;
  --gold-deep: #96702a;
  --gold-ink: #2a1d05;
  --accent: #c0202a;
  --accent-bright: #e03a35;
  --accent-deep: #7d1218;
  --good: #7fbf6a;

  /* cards */
  --face: #f0e4cb;
  --face-edge: #cbbb9a;
  --face-ink: #211a12;
  --prompt-face: #17130f;
  --prompt-edge: #4a3820;
  --prompt-ink: #f3ead8;

  --verdict-life: 9s;
  --radius: 14px;
  --card-radius: 12px;
  --pad: 16px;
  --safe-b: env(safe-area-inset-bottom, 0px);
  --font: 'Space Grotesk', ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-card: 'Zilla Slab', "Iowan Old Style", Palatino, Georgia, serif;
  /* What a card says, and the small labels printed around it. */
  --font-card-text: 'Bebas Neue', 'Zilla Slab', Impact, sans-serif;
  --font-card-label: 'Cinzel', 'Zilla Slab', Georgia, serif;

  /* One light source, high and slightly left, used by every raised surface. */
  --shadow-card:
    0 1px 1px rgba(0,0,0,.4),
    0 4px 10px -4px rgba(0,0,0,.7),
    0 14px 28px -14px rgba(0,0,0,.95);
  --shadow-lift:
    0 2px 3px rgba(0,0,0,.4),
    0 12px 20px -8px rgba(0,0,0,.7),
    0 30px 50px -22px rgba(0,0,0,1);
  --edge-light: inset 0 1px 0 rgba(255,255,255,.5);
  --edge-light-dark: inset 0 1px 0 rgba(217,171,82,.16);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.45;
  overscroll-behavior-y: none;
}

/* The table: a lit patch of dark wood, with a fine grain over the top. */
body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  /* Lamplight falling on a dark table, with the gold of the deck bleeding in
     at the very top where the cards are dealt from. */
  background:
    radial-gradient(80% 42% at 50% -6%, rgba(217,171,82,.13), transparent 62%),
    radial-gradient(120% 74% at 50% 0%, #241c14 0%, var(--table) 34%, var(--table-deep) 72%, var(--table-edge) 100%),
    var(--table-deep);
  background-attachment: fixed;
}
/* Grain over the table. The turbulence is desaturated on purpose: feTurbulence
   produces *coloured* noise, and blended over a near-black ground it tints the
   whole page — which is exactly what it was quietly doing. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: .16;
  mix-blend-mode: soft-light;
  background-image: 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='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

.app {
  position: relative;
  flex: 1;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: var(--pad) var(--pad) calc(var(--pad) + var(--safe-b));
}

.boot { color: var(--ink-faint); text-align: center; padding: 25vh 0; }

h1, h2, h3 { line-height: 1.1; margin: 0 0 .4em; font-weight: 700; letter-spacing: -.03em; }
h1 { font-family: var(--font-card); font-weight: 700; letter-spacing: -.02em; }
h1 { font-size: clamp(1.75rem, 7vw, 2.3rem); overflow-wrap: break-word; }
h2 { font-size: 1.2rem; }
h3 { font-size: .95rem; letter-spacing: .01em; }
p { margin: 0 0 1em; }
a { color: var(--ink); }
small, .small { font-size: .82rem; }
.dim { color: var(--ink-dim); }
.faint { color: var(--ink-faint); }
.center { text-align: center; }
.row { display: flex; gap: 10px; align-items: center; }
.row.wrap { flex-wrap: wrap; }
.spread { justify-content: space-between; }
.grow { flex: 1; min-width: 0; }
.stack > * + * { margin-top: 12px; }
.gap-lg > * + * { margin-top: 22px; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[hidden] { display: none !important; }

/* ---------- the front page ---------- */
.hero { text-align: center; }
.hero-logo {
  display: block;
  width: min(190px, 46vw);
  height: auto;
  margin: 4px auto 14px;
  filter: drop-shadow(0 8px 26px rgba(0,0,0,.8)) drop-shadow(0 0 30px rgba(217,171,82,.18));
}
.hero h1 { text-wrap: balance; }

/* ---------- brand ---------- */
/* The small caption above the winner's name on the endgame screen. Named apart
   from `.verdict`, the round-result overlay, which it used to collide with. */
.result-label {
  font-size: .72rem; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--gold);
}

.topbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; gap: 10px; }
/* The wordmark is the brand — it carries the emblem, the gold and the type, so
   nothing is redrawn in CSS beside it. */
.brand { display: flex; align-items: center; gap: 8px; text-decoration: none; min-width: 0; }
.brand-mark {
  height: 30px;
  width: auto;
  max-width: 46vw;
  object-fit: contain;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.7));
}
.brand-sub {
  font-size: .66rem; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--gold); opacity: .8;
}
@media (min-width: 480px) { .brand-mark { height: 36px; } }

/* ---------- buttons ---------- */
/* Milled from one block: a lit top edge, a graded face, a dark base that the
   press collapses. No glyphs — every button says what it does in words. */
button, .btn {
  position: relative;
  font: inherit;
  font-weight: 600;
  font-size: .93rem;
  letter-spacing: .01em;
  color: var(--ink);
  background-image: linear-gradient(180deg, #3a2c1c 0%, #241a10 52%, #17110a 100%);
  border: 1px solid #4a3820;
  border-radius: 11px;
  padding: 11px 18px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  text-decoration: none;
  box-shadow: var(--edge-light-dark), 0 2px 0 #0a0705, 0 6px 14px -8px rgba(0,0,0,.9);
  transition: transform .08s ease, box-shadow .12s ease, filter .12s ease;
}
button:hover, .btn:hover { filter: brightness(1.14); }
button:focus-visible, .btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
button:active, .btn:active {
  transform: translateY(2px);
  box-shadow: var(--edge-light-dark), 0 0 0 #0a0705, 0 3px 8px -6px rgba(0,0,0,.9);
}
button:disabled, .btn:disabled {
  opacity: .38; cursor: not-allowed; transform: none; filter: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
}

.btn-primary {
  background-image: linear-gradient(180deg, #d8353a 0%, #c0202a 48%, #7d1218 100%);
  border-color: #5e0f14;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0,0,0,.35);
  box-shadow: var(--edge-light), 0 2px 0 #4a0c10, 0 8px 18px -10px rgba(217,67,39,.9);
}
.btn-primary:active { box-shadow: var(--edge-light), 0 0 0 #4a0c10, 0 4px 10px -8px rgba(217,67,39,.9); }

.btn-gold {
  background-image: linear-gradient(180deg, #f2d089 0%, #d9ab52 46%, #96702a 100%);
  border-color: #7a5a20;
  color: #2a1d05;
  text-shadow: 0 1px 0 rgba(255,255,255,.35);
  box-shadow: var(--edge-light), 0 2px 0 #5e4416, 0 8px 18px -10px rgba(227,176,75,.85);
}
.btn-gold:active { box-shadow: var(--edge-light), 0 0 0 #5e4416, 0 4px 10px -8px rgba(227,176,75,.85); }

.btn-ghost {
  background-image: none;
  background-color: transparent;
  border-color: var(--line-soft);
  box-shadow: none;
  color: var(--ink-dim);
}
.btn-ghost:hover { color: var(--ink); border-color: var(--line); background-color: #ffffff08; }
.btn-ghost:active { transform: translateY(1px); box-shadow: none; }

.btn-block { width: 100%; }
.btn-sm {
  min-height: 36px; padding: 6px 13px; font-size: .82rem; border-radius: 9px;
  box-shadow: var(--edge-light-dark), 0 2px 0 #0a0705;
}
.btn-sm:active { box-shadow: var(--edge-light-dark), 0 0 0 #0a0705; }
.btn-danger { color: #ffa895; border-color: #58302a; }

input, select, textarea {
  font: inherit; color: var(--ink); background: #0e0b09;
  border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; width: 100%;
  min-height: 46px; box-shadow: inset 0 2px 6px -3px #000;
}
input::placeholder, textarea::placeholder { color: var(--ink-faint); }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--gold); outline-offset: 1px; }
/* A width:100% input is a flex item too: without min-width:0 it refuses to
   shrink and pushes the whole row wider than the screen. */
.row > input, .row > select, .row > textarea { flex: 1 1 auto; min-width: 0; }
label { display: block; font-size: .82rem; color: var(--ink-dim); margin-bottom: 6px; }
.field + .field { margin-top: 14px; }

/* ---------- panels: boards laid on the table ---------- */
.panel {
  background: linear-gradient(var(--panel), var(--panel-2));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--pad);
  box-shadow: inset 0 1px 0 #ffffff12, 0 10px 24px -18px #000;
}
.panel + .panel { margin-top: 14px; }
details.panel > summary { cursor: pointer; font-weight: 650; list-style: none; }
details.panel > summary::-webkit-details-marker { display: none; }
details.panel > summary::after { content: ' ▾'; color: var(--ink-faint); }
details.panel[open] > summary::after { content: ' ▴'; }

.pill {
  display: inline-flex; align-items: center; gap: 5px; font-size: .68rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .07em; padding: 4px 9px; border-radius: 99px;
  background: #ffffff12; color: var(--ink-dim); white-space: nowrap;
}
.pill-gold { background: #d9ab5226; color: var(--gold); }
.pill-accent { background: #c0202a26; color: #ff9f8b; }
.pill-good { background: #5ec98b22; color: var(--good); }

/* ---------- cards ---------- */
/*
 * An answer card is the printed card: the artwork is the card, and the text is
 * set into the parchment panel inside its frame. The frame's proportions come
 * from the art itself (940x1445), so nothing is ever stretched, and the text
 * box is positioned in percentages of the card so it stays inside the border at
 * every size.
 */
.card {
  position: relative;
  container-type: inline-size;
  border-radius: var(--card-radius);
  font-family: var(--font-card-text);
  font-weight: 400;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.18;
  display: block;
  text-align: left;
  box-shadow: var(--shadow-card);
  transition: transform .14s cubic-bezier(.2,.8,.3,1), box-shadow .14s ease, filter .14s ease;
}

.card-answer {
  aspect-ratio: 940 / 1445;
  background: url('/assets/card-face.webp') center / 100% 100% no-repeat;
  color: var(--face-ink);
  /* The art carries its own border and shadow line, so nothing is added here. */
}
/* The parchment panel inside the printed frame, below the moon and above the
   footer rule. Measured off the artwork rather than guessed, and the text is
   centred in it both ways so a one-word answer sits where a three-line one does. */
.card-answer .card-body {
  position: absolute;
  left: 12%;
  right: 12%;
  top: 29%;
  bottom: 16%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  font-size: clamp(.9rem, 11cqw, 1.5rem);
  line-height: 1.12;
  hyphens: auto;
}
.card-answer .card-foot { display: none; }   /* the art already signs itself */

/*
 * A prompt is not a printed card, it is the card that has been turned face up
 * on the table — so it keeps a box, but one cut from the same cloth: black
 * stock, a gold rule inset from the edge, and the corner diamonds off the deck.
 */
.card-prompt {
  aspect-ratio: auto;
  min-height: 116px;
  padding: 24px 24px 32px;
  display: flex;
  align-items: center;
  background-image:
    radial-gradient(120% 90% at 50% -30%, rgba(217,171,82,.13), transparent 60%),
    linear-gradient(168deg, #241d15 0%, var(--prompt-face) 58%, #0d0b09 100%);
  color: var(--prompt-ink);
  border: 1px solid var(--prompt-edge);
  border-radius: var(--card-radius);
  font-size: clamp(1.15rem, 5.4vw, 1.5rem);
  box-shadow: var(--shadow-card), var(--edge-light-dark), inset 0 -2px 6px rgba(0,0,0,.5);
}
/* The inset gold rule, and the four diamonds that hold its corners. */
.card-prompt::before {
  content: '';
  position: absolute;
  inset: 7px;
  border: 1px solid rgba(217,171,82,.30);
  border-radius: 7px;
  pointer-events: none;
}
.card-prompt::after {
  content: '';
  position: absolute;
  inset: 7px;
  pointer-events: none;
  background-image:
    radial-gradient(circle, var(--gold) 46%, transparent 52%),
    radial-gradient(circle, var(--gold) 46%, transparent 52%),
    radial-gradient(circle, var(--gold) 46%, transparent 52%),
    radial-gradient(circle, var(--gold) 46%, transparent 52%);
  background-size: 5px 5px;
  background-repeat: no-repeat;
  background-position: top left, top right, bottom left, bottom right;
  opacity: .8;
}
.card-prompt .card-body { position: relative; width: 100%; text-align: center; }

.card-flat { aspect-ratio: auto; }
.card-body { overflow-wrap: break-word; }
.card-foot {
  position: absolute; right: 20px; bottom: 11px;
  font-family: var(--font-card-label);
  font-weight: 600;
  font-size: .58rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gold); opacity: .6;
}
.card blank {
  display: inline-block; min-width: 78px;
  border-bottom: 2px solid currentColor; opacity: .45; margin-bottom: -2px;
}
.card answer {
  color: var(--gold-bright);
  text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px;
}
.card-answer answer { color: var(--accent-deep); }

.hand {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 11px;
}
.card-wrap { position: relative; }
.hand .card { cursor: pointer; width: 100%; }
.hand .card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lift); }
/* Chosen cards are lifted off the table and lit, rather than outlined — a ring
   would cut across the printed border. */
.hand .card.selected {
  transform: translateY(-10px) rotate(-1.2deg);
  box-shadow: var(--shadow-lift), 0 0 26px -2px rgba(217,171,82,.55);
  filter: brightness(1.06) saturate(1.05);
}
.pick-order {
  position: absolute; top: -8px; right: -8px; z-index: 2;
  background: linear-gradient(#eec164, var(--gold-deep)); color: #241a05;
  width: 26px; height: 26px; border-radius: 99px; display: grid; place-items: center;
  font-size: .8rem; font-weight: 800; box-shadow: 0 2px 6px -1px #000a;
}

/* ---------- rating ---------- */
.subs { display: grid; gap: 16px; grid-template-columns: 1fr; }
.sub { display: grid; gap: 9px; }
.sub .card { width: 100%; }
.sub.is-mine .card { outline: 2px dashed var(--line); outline-offset: 3px; }
.sub.placed-1 .card { box-shadow: var(--shadow-lift), 0 0 0 3px var(--gold); }

.stars { display: flex; gap: 4px; justify-content: center; }
.star {
  min-height: 46px; flex: 1; max-width: 60px; padding: 0;
  font-size: 1.35rem; line-height: 1;
  color: #6b5638;
  background-image: linear-gradient(180deg, #241a10 0%, #1a130c 60%, #120d08 100%);
  border: 1px solid #3d2e1c;
  border-radius: 10px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.07), 0 1px 2px rgba(0,0,0,.5);
  transition: color .12s ease, box-shadow .16s ease, transform .08s ease;
}
.star:hover { color: #b08f56; }
.star.on {
  color: #ffd473;
  background-image:
    radial-gradient(70% 90% at 50% 120%, rgba(227,176,75,.35), transparent 70%),
    linear-gradient(180deg, #3a2c14 0%, #2a1f0e 60%, #1d1509 100%);
  border-color: var(--gold-deep);
  text-shadow: 0 0 10px rgba(255,196,84,.75), 0 1px 0 rgba(0,0,0,.4);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 -6px 10px -6px rgba(227,176,75,.5),
    0 1px 3px rgba(0,0,0,.55);
}
.star:active { transform: translateY(1px); }
.star:disabled { opacity: .3; cursor: not-allowed; }
.star:disabled:hover { color: #6b5638; }
.rating-note { font-size: .78rem; color: var(--ink-faint); text-align: center; }

.result-line { display: flex; align-items: center; gap: 8px; font-size: .84rem; }
.place-badge {
  width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
  font-weight: 800; font-size: .78rem; background: #ffffff12; color: var(--ink-dim);
}
.place-1 { background: linear-gradient(#eec164, var(--gold-deep)); color: #241a05; }
.place-2 { background: #c9ccd4; color: #21222a; }
.place-3 { background: #c08552; color: #1d1206; }

/* ---------- dealing and flipping ---------- */
/* A card is two faces stacked on one hinge. Turning is done with scaleX rather
   than rotateY on purpose: the faces carry `overflow: hidden` and their own
   stacking context, which flattens a 3D context and leaves `backface-visibility`
   with nothing to hide — the face shows through mirrored. Squashing one face to
   nothing while the other opens out reads exactly the same and cannot break. */
.card-wrap { position: relative; }
.flipper { position: relative; }
.flipper > .card-back { position: absolute; inset: 0; }

/* The printed back of the deck. */
.card-back {
  border-radius: var(--card-radius);
  background: url('/assets/card-back.webp') center / 100% 100% no-repeat;
  box-shadow: var(--shadow-card);
}

/* Three parts to a deal, staggered per card by one inline delay: the card
   slides in from the deck, the back turns away, the face opens out. */
@keyframes deal-slide {
  0%   { transform: translate(26%, -44%) rotate(8deg) scale(.88); opacity: 0; }
  30%  { opacity: 1; }
  100% { transform: translate(0, 0) rotate(0) scale(1); opacity: 1; }
}
@keyframes turn-back { 0%, 45% { transform: scaleX(1); } 55%, 100% { transform: scaleX(0); } }
@keyframes turn-face { 0%, 55% { transform: scaleX(0); } 100% { transform: scaleX(1); } }

.flipper.dealing { animation: deal-slide .55s cubic-bezier(.25,.9,.3,1) backwards; }
.flipper.dealing > .card-answer { animation: turn-face .55s ease-in-out backwards; }
.flipper.dealing > .card-back { animation: turn-back .55s ease-in-out forwards; }
/* Once turned, the back is out of the way for good. */
.flipper:not(.dealing) > .card-back { display: none; }

/* The prompt turns over in place — it is put down, not dealt out. */
@keyframes prompt-turn {
  0%   { transform: scaleY(.04) translateY(-10px); opacity: .2; }
  60%  { opacity: 1; }
  100% { transform: scaleY(1) translateY(0); opacity: 1; }
}
.prompt-turn { transform-origin: top center; animation: prompt-turn .5s cubic-bezier(.2,.85,.3,1) backwards; }

/* Playing a card sends it to the table rather than having it vanish. */
@keyframes card-away { to { transform: translateY(-38%) scale(.82) rotate(-4deg); opacity: 0; } }
.card-wrap.leaving { animation: card-away .32s ease forwards; pointer-events: none; }

/* ---------- the round verdict ---------- */
/* Who took the round, in the middle, once — then out of the way. */
.verdict-layer {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 24px;
  pointer-events: none;
  background: radial-gradient(60% 45% at 50% 50%, rgba(3,10,8,.82), rgba(3,10,8,.35) 70%, transparent);
  /* Long enough to actually read: nine seconds up, then a slow fade. A tap
     ends it sooner, and the bar along the bottom shows how long is left. */
  animation: verdict-layer var(--verdict-life) ease forwards;
}
@keyframes verdict-layer { 0%, 86% { opacity: 1; } 100% { opacity: 0; } }

.verdict {
  pointer-events: auto;
  cursor: pointer;
  max-width: min(420px, 88vw);
  text-align: center;
  padding: 26px 24px 22px;
  border-radius: 20px;
  border: 1px solid var(--gold-deep);
  background-image:
    radial-gradient(120% 90% at 50% -20%, rgba(227,176,75,.20), transparent 60%),
    linear-gradient(180deg, #241c12 0%, #12100c 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.14),
    0 0 0 1px rgba(0,0,0,.4),
    0 30px 60px -24px rgba(0,0,0,.95),
    0 0 60px -18px rgba(227,176,75,.45);
  animation: verdict-in .5s cubic-bezier(.2,1.1,.35,1) backwards;
}
@keyframes verdict-in {
  from { transform: scale(.82) translateY(14px); opacity: 0; }
}
.verdict-round {
  font-size: .68rem; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-faint);
}
.verdict-name {
  font-family: var(--font-card);
  font-weight: 700;
  font-size: clamp(2rem, 11vw, 3.1rem);
  line-height: 1.05;
  letter-spacing: -.02em;
  margin: 6px 0 2px;
  color: var(--ink);
  text-shadow: 0 2px 0 rgba(0,0,0,.5), 0 0 28px rgba(227,176,75,.35);
}
.verdict-answer {
  font-family: var(--font-card);
  font-size: 1rem; line-height: 1.35;
  color: var(--gold);
  margin: 10px 0 0;
}
.verdict-points {
  display: inline-block;
  margin-top: 14px;
  font-weight: 800; font-size: 1.05rem;
  color: #2a1d05;
  background-image: linear-gradient(180deg, #f2d089, #cf9c2e);
  border-radius: 99px;
  padding: 5px 16px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.55), 0 3px 10px -3px rgba(0,0,0,.7);
}
.verdict-sub { margin-top: 10px; font-size: .82rem; color: var(--ink-dim); }

/* The rest of the table, so the whole round can be read at a glance. */
.verdict-rest {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--line-soft);
  display: grid;
  gap: 7px;
}
.verdict-row { display: flex; align-items: center; gap: 9px; font-size: .86rem; color: var(--ink-dim); }
.verdict-row-pts { font-weight: 700; color: var(--gold); font-variant-numeric: tabular-nums; }

.verdict-hint {
  margin-top: 14px;
  font-family: var(--font-card-label);
  font-size: .58rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-faint);
}

/* A depleting rule, so it is obvious the panel will leave on its own. */
.verdict-timer {
  margin-top: 12px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--gold-deep), var(--gold));
  transform-origin: left center;
  animation: verdict-timer var(--verdict-life) linear forwards;
}
@keyframes verdict-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* A score that changed should be seen to change. */
@keyframes chip-bump {
  40% { transform: scale(1.28); box-shadow: 0 0 0 6px rgba(227,176,75,.18); }
}
.chip.bumped { animation: chip-bump .55s cubic-bezier(.3,1.2,.4,1); }

/* ---------- switches ---------- */
/* A real control rather than a browser checkbox: a recessed track with a lit
   thumb that slides, so its state reads at a glance on a phone. The native
   input stays in the DOM for keyboard and screen readers, just not visible. */
.switch {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0;
  padding: 11px 12px;
  border-radius: 12px;
  background-image: linear-gradient(180deg, #1c1610 0%, #141009 100%);
  border: 1px solid var(--line-soft);
  cursor: pointer;
  transition: border-color .14s ease, background-color .14s ease;
}
.switch:hover { border-color: var(--line); }
.switch + .switch { margin-top: 8px; }

.switch-input {
  position: absolute;
  width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.switch-track {
  position: relative;
  flex: 0 0 auto;
  width: 46px; height: 27px;
  margin-top: 1px;
  border-radius: 99px;
  background-image: linear-gradient(180deg, #0d0906 0%, #161009 100%);
  border: 1px solid #3d2e1c;
  box-shadow: inset 0 2px 5px rgba(0,0,0,.7);
  transition: background-image .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.switch-thumb {
  position: absolute;
  top: 2px; left: 2px;
  width: 21px; height: 21px;
  border-radius: 50%;
  background-image: linear-gradient(180deg, #8a7458 0%, #4a3c2a 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 2px 4px rgba(0,0,0,.6);
  transition: transform .18s cubic-bezier(.3,.8,.3,1.2), background-image .18s ease;
}
.switch-input:checked + .switch-track {
  background-image: linear-gradient(180deg, #8a6a28 0%, #5c4418 100%);
  border-color: #b08a3a;
  box-shadow: inset 0 2px 5px rgba(0,0,0,.45), 0 0 12px -4px rgba(217,171,82,.6);
}
.switch-input:checked + .switch-track .switch-thumb {
  transform: translateX(19px);
  background-image: linear-gradient(180deg, #f6f3ea 0%, #cfd8d1 100%);
}
.switch-input:focus-visible + .switch-track { outline: 2px solid var(--gold); outline-offset: 2px; }
.switch-input:checked ~ .switch-text .switch-label { color: var(--ink); }

.switch-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.switch-label { font-weight: 600; font-size: .94rem; color: var(--ink-dim); }
.switch-hint { font-size: .78rem; color: var(--ink-faint); line-height: 1.35; }

/* ---------- grouped settings ---------- */
.setting-group {
  padding: 14px;
  border-radius: 13px;
  background: #ffffff06;
  border: 1px solid var(--line-soft);
}
.setting-group > h3 {
  margin: 0 0 10px;
  font-size: .72rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-faint);
}
.setting-group .field + .switch { margin-top: 10px; }
.setting-group .switch + .field { margin-top: 10px; }
.field-note {
  margin: 8px 0 0;
  font-size: .78rem; line-height: 1.4; color: var(--ink-faint);
}

/* A round somebody missed: shown at the reveal, greyed and struck from scoring. */
.sub.missed .card { opacity: .55; filter: saturate(.5); }
.missed-note {
  font-size: .78rem; color: var(--ink-faint);
  display: flex; align-items: center; gap: 6px;
}

/* ---------- the points on offer ---------- */
.points-strip {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  padding: 10px 14px; border-radius: 12px;
  background: #ffffff08; border: 1px dashed var(--line-soft);
}
.points-title {
  font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-faint);
}
.points-cell { display: inline-flex; align-items: baseline; gap: 5px; }
.points-label { font-size: .8rem; color: var(--ink-dim); }
.points-value { font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.points-value.zero { color: var(--ink-faint); }

/* What the round just paid, sat next to the running total. */
.gain {
  font-weight: 800; font-size: .82rem; color: var(--gold);
  background: #d9ab521f; border-radius: 99px; padding: 2px 8px;
  animation: gain-in .5s ease backwards;
}
@keyframes gain-in { from { opacity: 0; transform: translateY(-6px); } }

/* ---------- players ---------- */
.players { display: grid; gap: 8px; }
.player {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px;
  background: #17120e; border-radius: 12px; border: 1px solid var(--line-soft);
}
.player.is-you { border-color: var(--line); background: #1e1711; }
.player.gone { opacity: .4; }
.player .name { flex: 1; font-weight: 650; }
.avatar {
  width: 32px; height: 32px; border-radius: 99px; display: grid; place-items: center;
  font-weight: 800; font-size: .78rem; color: #10201b;
  box-shadow: inset 0 -2px 4px #00000030, 0 1px 2px #0006;
}
/* Scores are chips, because points in a board game are objects you can see:
   a lit top edge, a domed face, a cast shadow and a milled rim. */
.chip {
  position: relative;
  min-width: 38px; height: 38px; padding: 0 9px; border-radius: 99px;
  display: grid; place-items: center;
  font-weight: 700; font-size: .98rem; font-variant-numeric: tabular-nums;
  color: var(--ink);
  background-image:
    radial-gradient(80% 70% at 34% 24%, rgba(255,255,255,.22), transparent 62%),
    linear-gradient(180deg, #3d2f1c 0%, #241a10 55%, #14100b 100%);
  border: 1px solid #4a3820;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.18),
    inset 0 -2px 4px rgba(0,0,0,.45),
    0 2px 4px -1px rgba(0,0,0,.65);
}
/* The milled rim, drawn rather than dashed-bordered so it stays crisp. */
.chip::after {
  content: '';
  position: absolute; inset: 3px;
  border-radius: 99px;
  border: 1px dashed rgba(255,255,255,.14);
  pointer-events: none;
}
.chip-lead {
  color: #2a1d05;
  background-image:
    radial-gradient(80% 70% at 34% 24%, rgba(255,255,255,.5), transparent 62%),
    linear-gradient(180deg, #f4cd85 0%, #d9ab52 52%, #96702a 100%);
  border-color: #7a5a20;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.6),
    inset 0 -2px 4px rgba(120,84,14,.5),
    0 2px 6px -1px rgba(227,176,75,.55);
}
.chip-lead::after { border-color: rgba(90,62,10,.35); }

/* ---------- history + talk ---------- */
/* The one deliberately iconic control in the app: a corner disc that lifts the
   history over the table. It gets a dot when a round has been scored unseen. */
.fab {
  position: fixed;
  right: 14px;
  bottom: calc(var(--ad-bottom-h, 0px) + 16px + var(--safe-b));
  z-index: 30;
  width: 54px; height: 54px; min-height: 0; padding: 0;
  border-radius: 50%;
  font-family: var(--font-card); font-size: 1.05rem; font-weight: 700; line-height: 1;
  background-image: linear-gradient(180deg, #3a2c1c, #17110a);
  border: 1px solid #4a3820;
  box-shadow: var(--edge-light-dark), 0 3px 0 #0a0705, 0 12px 24px -10px rgba(0,0,0,.95);
}
.fab:active { transform: translateY(3px); box-shadow: var(--edge-light-dark), 0 0 0 #0a0705; }
.fab-dot::after {
  content: '';
  position: absolute; top: 6px; right: 6px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--gold);
  border: 2px solid #17110a;
  animation: dot-pulse 1.6s ease-in-out infinite;
}
@keyframes dot-pulse { 50% { transform: scale(1.25); } }

.history { display: grid; gap: 20px; }
.history-round { display: grid; gap: 9px; }
.history-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding-bottom: 6px; border-bottom: 1px solid var(--line-soft);
}
.history-no { font-family: var(--font-card); font-weight: 700; font-size: 1.02rem; }
.history-empty { color: var(--ink-faint); text-align: center; padding: 28px 0; }

.chat-log { max-height: 46dvh; overflow-y: auto; display: grid; gap: 9px; }
.chat-line { font-size: .9rem; color: var(--ink-dim); }
.chat-line b { color: var(--ink); font-weight: 600; }
.chat-line.event { color: var(--ink-faint); font-size: .82rem; }

/* ---------- misc ---------- */
.code-display {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1.7rem;
  letter-spacing: .28em; font-weight: 700; color: var(--gold);
}
.link-box { display: flex; gap: 8px; }
.link-box input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .78rem; }
.waiting-dots::after { content: '…'; animation: dots 1.4s steps(4, end) infinite; }
@keyframes dots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '…'; } }
.deal-in { animation: deal .28s cubic-bezier(.2, .8, .3, 1) backwards; }
@keyframes deal { from { opacity: 0; transform: translateY(14px) scale(.97); } }

/* The bottom ad banner is sticky as well; --ad-bottom-h (set by ads.js) keeps
   the primary action clear of it instead of underneath it. */
.powers { align-items: stretch; }
.powers > button { flex: 1; line-height: 1.15; }

.sticky-actions {
  position: sticky; bottom: var(--ad-bottom-h, 0px); z-index: 10;
  padding: 12px 0 calc(4px + var(--safe-b));
  background: linear-gradient(to top, var(--table-deep) 58%, transparent);
}
/* The action is centred on the page, not on the space left over beside the
   corner disc: equal gutters, and a width that stops short of the disc. */
.sticky-actions .btn-action {
  display: block;
  width: min(100%, 420px);
  margin-inline: auto;
}
body.has-fab .sticky-actions { padding-inline: 66px; }
body.has-fab .sticky-actions .btn-action { width: 100%; }
/* Let the last rows scroll clear of the corner disc instead of under it. */
body.has-fab .app { padding-bottom: calc(var(--pad) + 78px + var(--safe-b)); }

.toasts {
  position: fixed; left: 0; right: 0; bottom: calc(var(--ad-bottom-h, 0px) + 64px + var(--safe-b));
  display: grid; gap: 8px; justify-items: center; pointer-events: none; z-index: 50; padding: 0 12px;
}
.toast {
  background: #0a0806e6; border: 1px solid var(--line); color: var(--ink);
  padding: 10px 16px; border-radius: 99px; font-size: .88rem; max-width: 90vw;
  box-shadow: 0 8px 20px -10px #000;
}
.toast.bad { border-color: var(--accent); }

dialog {
  border: 1px solid var(--line); background: linear-gradient(var(--panel), var(--panel-2));
  color: var(--ink); border-radius: var(--radius); padding: var(--pad);
  width: min(560px, 94vw); max-height: 86dvh;
}
dialog::backdrop { background: #02090780; backdrop-filter: blur(2px); }
/* The card editor holds a table and a search bar; 560px squeezes it to the point
   of being unreadable on a desktop screen. Still capped so it never runs the
   full width of a large monitor, where long lines are their own problem. */
.dialog-wide { width: min(1100px, 94vw); }
.dialog-wide .scroll { max-height: 60dvh; }

.rules-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.rules-table td { padding: 6px 0; border-bottom: 1px solid var(--line-soft); }
.rules-table td:last-child { text-align: right; font-weight: 800; color: var(--gold); }

/* ---------- ads ---------- */
.ad-slot {
  display: flex; align-items: center; justify-content: center; min-height: 62px;
  background-image: linear-gradient(180deg, #100c0a 0%, #080605 100%);
  border-block: 1px solid var(--line-soft);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05), inset 0 -8px 18px -14px #000;
  overflow: hidden;
}
.ad-top { box-shadow: inset 0 -1px 0 rgba(0,0,0,.5), inset 0 8px 18px -14px #000; }
.ad-bottom {
  position: sticky; bottom: 0; padding-bottom: var(--safe-b); z-index: 20;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 -10px 24px -18px #000;
}
.ad-house {
  text-align: center; padding: 11px 16px; line-height: 1.35;
  font-size: .76rem; letter-spacing: .01em; color: var(--ink-faint);
}
.ad-house b {
  display: block;
  font-size: .82rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-dim);
  text-shadow: 0 1px 0 rgba(0,0,0,.6);
}

@media (min-width: 640px) {
  :root { --pad: 22px; }
  .hand { grid-template-columns: repeat(auto-fill, minmax(164px, 1fr)); }
  .subs { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  /* With animation off the card must still land face-up, not face-down. */
  .flipper.dealing { transform: none; }
  .flipper > .card-back { display: none; }
  /* With motion off the panel cannot fade itself out, so it waits for a tap. */
  .verdict-layer { opacity: 1; animation: none; }
  .verdict-timer { display: none; }
}
