/* Seal theme — a blue field, a cinnabar card, white type, everything centred.
   Loads after base.css, level.css and deck.css, so every rule here wins on
   source order at equal specificity.

   The world is the exam desk: a bright 青花 field, a 朱砂 seal pressed on it,
   the 田字格 guide grid. The field is the exact blue Fred asked for, #007FFF.
   White is the only text colour on it; a tint toward blue or red costs more
   contrast than it buys, so hierarchy comes from size and weight instead. Red
   is the card and nothing else.

   Contrast, computed from these values:
     white on the field ..... 3.83   above the 3:1 bar for large type
     white on the seal ...... 6.45   every word on the card
     #0066CC on white ....... 5.57   the primary button label */

:root{
  color-scheme:light dark;
  --canvas:#007FFF;
  --surface:#AB342B;
  --surface-2:rgba(0,18,54,.14);
  --surface-3:rgba(0,18,54,.22);
  --ink:#FFFFFF;
  --ink-2:#FFFFFF;
  --rule:rgba(255,255,255,.34);
  --rule-strong:rgba(255,255,255,.58);
  --grid:rgba(255,255,255,.42);
  --accent:#FFFFFF;
  --accent-hover:#EAF4FF;
  --on-accent:#0066CC;
  --accent-soft:rgba(255,255,255,.16);
  --growth:#FFFFFF;
  --growth-soft:rgba(255,255,255,.22);
  --alert:#FFD9D3;
  --alert-soft:rgba(0,15,45,.34);
  --shadow:0 2px 4px rgba(0,20,60,.18),0 20px 44px rgba(0,20,60,.28);
  --seal:#AB342B;
  --seal-ink:#FFFFFF;
  --seal-line:rgba(255,255,255,.22);
  --seal-quiet:#F4E4E1;
  --ease:cubic-bezier(.2,.7,.3,1);
  /* Motion: one rhythm for every control. The halo is white so it reads on
     both the field and the seal; a pane inside a clipped grid takes its halo
     inward, because an outward shadow would be cut off by the grid edge. */
  --ease-soft:cubic-bezier(.22,.61,.36,1);
  /* The spring settles the press: it overshoots by about a tenth and eases
     back, so a released button pops rather than snapping to rest. */
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
  --motion-fast:.14s;
  --motion:.26s;
  --motion-bounce:.44s;
  /* The turn: slow off the hand, quick through the middle, then a small
     overshoot (about 8°) and a settle. Long enough to read as a card being
     turned, not a pane snapping over. */
  --flip-time:.85s;
  --flip-ease:cubic-bezier(.38,.08,.18,1.3);
  /* When the card stands edge-on, i.e. when the turn has covered 90°. This
     slower ease reaches it at about 29% of --flip-time (0.25s); swapping
     which face is shown anywhere else leaves a bare card mid-turn. */
  --flip-edge:.25s;
  --glow-soft:0 0 0 1px rgba(255,255,255,.42),0 0 20px rgba(198,226,255,.34);
  --glow-strong:0 0 0 1px rgba(255,255,255,.66),0 0 0 5px rgba(198,226,255,.16),
    0 0 34px rgba(198,226,255,.55);
  --glow-in:inset 0 0 0 1px rgba(255,255,255,.4),inset 0 0 32px rgba(255,255,255,.1);
  --glow-in-strong:inset 0 0 0 1px rgba(255,255,255,.66),inset 0 0 40px rgba(255,255,255,.18);
}

@media (prefers-color-scheme:dark){
  :root{
    color-scheme:dark;
    --canvas:#001E4D;
    --surface:#932C24;
    --surface-2:rgba(255,255,255,.12);
    --surface-3:rgba(255,255,255,.20);
    --rule:rgba(255,255,255,.26);
    --rule-strong:rgba(255,255,255,.46);
    --grid:rgba(255,255,255,.44);
    --alert-soft:rgba(0,0,0,.34);
    --shadow:0 2px 4px rgba(0,0,0,.35),0 20px 44px rgba(0,0,0,.45);
  }
}

/* ── Ground ───────────────────────────────────────────────── */
/* One flat field. The blue is the point; nothing is layered over it. */
html{scroll-behavior:smooth;}
body{background:var(--canvas);text-align:center;}
::selection{background:#FFFFFF;color:var(--on-accent);}
/* A short cross-dissolve between pages where the browser supports
   cross-document view transitions, and nothing at all where it does not. */
@view-transition{navigation:auto;}
::view-transition-old(root),::view-transition-new(root){
  animation-duration:.18s;animation-timing-function:var(--ease-soft);
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
}

/* ── Icons ────────────────────────────────────────────────── */
/* One set, one size, one stroke. They take the colour of the text beside them. */
.i{width:16px;height:16px;flex:none;stroke:currentColor;stroke-width:1.5;
   fill:none;stroke-linecap:round;stroke-linejoin:round;vertical-align:-3px;}

/* ── Chrome ───────────────────────────────────────────────── */
/* No wordmark: the level links are the whole masthead, centred. */
.masthead{justify-content:center;padding:24px 24px 8px;}
.nav{justify-content:center;gap:4px;}
.nav a{color:var(--ink);}
.nav a:hover{background:var(--surface-2);color:var(--ink);}

/* ── Buttons ──────────────────────────────────────────────── */
/* Cut out of the field: white face, blue label. */
.btn-primary{background:var(--accent);color:var(--on-accent);}
.btn-primary:hover{background:var(--accent-hover);}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--rule-strong);}
.btn-ghost:hover{background:var(--surface-2);}

/* ── Type ─────────────────────────────────────────────────── */
h1{font-weight:500;letter-spacing:-.02em;line-height:1.06;}
h2,h3{font-weight:500;}
.lede{font-weight:400;}

/* ── Landing hero ─────────────────────────────────────────── */
.hero{display:block;text-align:center;padding:56px 0 64px;}
.hero-copy{max-width:none;margin:0 auto;}
.hero h1{font-size:clamp(36px,5.2vw,56px);margin:0 auto 18px;max-width:18ch;}
.hero .lede{font-size:18px;line-height:1.6;max-width:46ch;margin:0 auto 28px;}
.hero-actions{display:flex;align-items:center;justify-content:center;gap:20px;flex-wrap:wrap;}
.hero-quiet{color:var(--ink);font-size:15px;text-decoration:none;
  border-bottom:1px solid var(--rule-strong);padding-bottom:2px;}
.hero-quiet:hover{border-color:var(--ink);}

/* ── Levels ───────────────────────────────────────────────── */
/* Four levels, four pigments: 朱砂 cinnabar, 石绿 malachite, 花青 indigo,
   赭石 ochre. The 2px grid gap lets the field show between the panes, so the
   line separation stays and each level gains a colour of its own. The block
   is a 田字格 at page scale, the same grid that sits behind the character on
   a card. White is the only text colour on a pane; the lightest of the four
   is 5.7:1, the cinnabar 6.45:1. */
.levels{padding:0 0 24px;text-align:center;}
.levels-head{display:flex;align-items:baseline;justify-content:center;gap:16px;
  padding:0 0 12px;margin:0 0 20px;}
.levels-head h2{margin:0;font-size:15px;font-weight:500;}
.levels-head span{font-family:var(--mono);font-size:12px;color:var(--ink);}
.level-grid{
  display:grid;grid-template-columns:1fr 1fr;gap:2px;
  border-radius:20px;overflow:hidden;text-align:left;
}
.level-row{
  --lv:#AB342B;
  display:flex;flex-direction:column;
  min-height:184px;padding:20px 22px 18px;
  border:0;border-radius:0;box-shadow:none;
  background:var(--lv);color:#FFFFFF;text-decoration:none;text-align:left;
  transition:filter .15s var(--ease);
}
.level-row[data-level="1"]{--lv:#AB342B;}
.level-row[data-level="2"]{--lv:#1F5C46;}
.level-row[data-level="3"]{--lv:#24356E;}
.level-row[data-level="4"]{--lv:#8A4B1E;}
.level-row:hover{filter:brightness(1.12);}
.level-row:focus-visible{outline:3px solid #FFFFFF;outline-offset:-4px;}
.level-row .level-name{margin:0;font-family:var(--mono);font-size:12px;
  font-weight:400;letter-spacing:.1em;color:#FFFFFF;}
.level-row .level-count{margin:22px 0 0;font-family:var(--font);
  font-size:clamp(34px,4.6vw,46px);font-weight:500;letter-spacing:-.02em;
  line-height:1;font-variant-numeric:tabular-nums;}
.level-unit{margin-left:9px;font-family:var(--mono);font-size:12px;
  font-weight:400;letter-spacing:.06em;vertical-align:.55em;}
.level-row .level-meta{margin:9px 0 0;font-size:13.5px;line-height:1.4;color:#FFFFFF;}
.level-row .go{display:inline-flex;align-items:center;gap:7px;margin-top:auto;padding-top:14px;
  font-size:13.5px;font-weight:600;color:#FFFFFF;}
.level-row .go .i{transition:transform .15s var(--ease);}
.level-row:hover .go .i{transform:translateX(2px);}
.level-row .progress{margin:18px 0 0;}
.level-row .progress[hidden]{display:none;}
.level-row .progress .rail-head{margin:0 0 7px;justify-content:flex-start;gap:10px;}
.levels-note{margin:16px 0 0;font-size:13px;color:var(--ink);}

/* Two panes have to hold the same sentence a full-width row held, so the
   pane gives up padding and type size before it gives up the grid. */
@media (max-width:560px){
  .level-row{min-height:0;padding:16px 15px 14px;}
  .level-row .level-count{font-size:clamp(30px,8.4vw,40px);}
  .level-unit{margin-left:7px;font-size:11px;}
  .level-row .level-meta{margin-top:7px;font-size:12.5px;}
  .level-row .go{margin-top:auto;padding-top:12px;font-size:12.5px;}
  .level-row .progress{margin-top:14px;}
  .level-row .progress .rail-head{gap:0;}
  .level-row .progress .rail-title{display:none;}
}
@media (max-width:380px){
  .level-row{padding:13px 12px 12px;}
  .level-row .level-count{font-size:30px;}
  .level-row .level-meta{font-size:12px;}
  .levels-note{font-size:12px;}
}

/* Dark field, slightly lifted panes: same four pigments, still 5.6:1 or more
   against white. */
@media (prefers-color-scheme:dark){
  .level-row[data-level="1"]{--lv:#B23A30;}
  .level-row[data-level="2"]{--lv:#24654F;}
  .level-row[data-level="3"]{--lv:#2E4488;}
  .level-row[data-level="4"]{--lv:#9A5524;}
}

/* ── Page head ────────────────────────────────────────────── */
.page-head{text-align:center;padding:44px 0 8px;}
.page-head h1{margin:0 auto 12px;max-width:22ch;}
.page-head .lede{margin-inline:auto;max-width:52ch;}
.actions{justify-content:center;margin:24px 0 32px;}

/* ── Progress line (landing page) ─────────────────────────── */
.rail-head{justify-content:center;gap:12px;margin:0 0 10px;}
.rail-title{letter-spacing:.01em;text-transform:none;font-size:12px;color:var(--ink);}
.rail-count{font-size:12px;color:var(--ink);}

/* ── Bands and rows ───────────────────────────────────────── */
.band{margin:0 0 40px;}
.band-head{display:flex;flex-wrap:wrap;justify-content:center;align-items:baseline;
  gap:4px 12px;margin:0 0 4px;padding:0 0 10px;}
.band-name{font-family:var(--font);font-size:15px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--ink);}
.band-meta{font-family:var(--mono);font-size:12px;color:var(--ink);letter-spacing:0;}
/* One deck: the words on their own line, then number, range, state and arrow
   as a quiet centred line beneath. */
.row{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:3px 10px;min-height:0;padding:14px 8px;text-align:center;border-radius:0;
}
.row-pair{order:1;flex-basis:100%;justify-content:center;font-size:24px;gap:10px;}
.row-num{order:2;font-family:var(--mono);font-size:12px;
  color:var(--ink);font-variant-numeric:tabular-nums;}
.row-range{order:3;font-family:var(--mono);font-size:13px;
  color:var(--ink);font-variant-numeric:tabular-nums;}
.row-state{order:4;font-size:13px;color:var(--ink);display:inline-flex;
  align-items:center;gap:6px;}
.row-sep{height:18px;background:var(--rule-strong);}
.tick{display:inline-flex;color:var(--ink);}
.row-go{order:5;color:var(--ink);display:inline-flex;}
.row:hover{background:var(--surface-2);}
.row:hover .row-go{color:var(--ink);transform:none;}
.ladder-row .row-pair{font-size:20px;}
.ladder-row .row-range{font-size:12px;}

/* ── Prose pages ──────────────────────────────────────────── */
/* Centred, with a measure at the widest a line of 17px text can run before
   the eye loses the return. Bullets sit inside the box so the marker travels
   with the centred line. */
.band p{margin:0 auto 16px;max-width:64ch;}
.band p:last-child{margin-bottom:0;}
.band ul{margin:0 auto 16px;padding-left:0;max-width:64ch;list-style-position:inside;}
.band li{margin:0 0 6px;}
.band a{color:var(--ink);text-decoration-color:rgba(255,255,255,.55);
  text-underline-offset:2px;}
.band a:hover{text-decoration-color:var(--ink);}
.footnote{max-width:64ch;margin-inline:auto;}
.review{background:transparent;border-color:var(--rule-strong);border-radius:14px;}
/* The labels sit in the middle; Show and Hide hold the right edge, where a
   disclosure control is looked for. */
.review > summary{position:relative;justify-content:center;gap:12px;text-align:center;}
.review > summary::after{position:absolute;right:18px;top:50%;transform:translateY(-50%);
  margin-left:0;color:var(--ink);}
.review > summary:hover::after{color:var(--ink);}
/* On a phone the review label and its counts cannot share the line with Show
   without running under it, so they stack inside a box that keeps clear. */
@media (max-width:560px){
  .review > summary{flex-wrap:wrap;padding-inline:72px;row-gap:2px;}
  .review > summary::after{right:16px;}
}
/* At 320 the counts would break in the middle ("20 / decks"), so the box
   gives back padding and a point of type instead. */
@media (max-width:380px){
  .review > summary{padding-inline:56px;}
  .review > summary .band-meta{font-size:11px;}
}
.review .band{padding:0 18px;margin:22px 0;text-align:center;}

/* ── Deck ─────────────────────────────────────────────────── */
.deck-head{text-align:center;padding:32px 0 0;}
.deck-head h1{font-size:clamp(40px,7vw,64px);font-weight:500;letter-spacing:-.02em;}
.counter{justify-content:center;gap:16px;margin:8px auto 24px;max-width:440px;}
.counter-track{height:3px;border-radius:2px;background:var(--surface-2);}
.counter-fill{background:var(--ink);border-radius:2px;}
/* The card is the one filled shape on the deck page: seal paste, white type. */
.face{background:var(--seal);border-color:var(--seal-line);box-shadow:var(--shadow);}
.face-top{color:var(--seal-quiet);font-size:12px;letter-spacing:.02em;}
.stamp{color:var(--seal-ink);border-color:var(--seal-line);border-radius:5px;}
.hanzi-big{color:var(--seal-ink);}
.front .face-center::before{
  border-color:var(--seal-line);opacity:1;
  background-image:linear-gradient(var(--seal-line),var(--seal-line)),
                   linear-gradient(var(--seal-line),var(--seal-line));
}
.tap-hint{text-transform:none;letter-spacing:.02em;font-size:13px;
  font-weight:400;color:var(--seal-quiet);}
.back .face-top{padding-bottom:10px;border-bottom:1px solid var(--seal-line);}
.back-body{align-items:center;text-align:center;}
.back-meta{flex-direction:column;align-items:center;gap:4px;}
.back-hanzi,.meaning{color:var(--seal-ink);}
.pinyin,.pos,.trad{color:var(--seal-quiet);}
.trad .zh{color:var(--seal-ink);}
.meaning{max-width:26ch;margin-inline:auto;}
/* Everything below the meaning is still on seal red, so it stays white and the
   small furniture sinks into a darker wash instead of gaining a new colour. */
.pairs .pair{background:rgba(0,0,0,.14);border-color:var(--seal-line);color:var(--seal-ink);}
.pair-label,.pair-py,.sentence-en,.sentence-structure{color:var(--seal-quiet);}
.sentence{border-top-color:var(--seal-line);}
.say,.icon-btn{background:rgba(0,0,0,.14);border-color:var(--seal-line);color:var(--seal-ink);}
.say:hover:not(:disabled),.icon-btn:hover{border-color:var(--seal-ink);color:var(--seal-ink);}
.controls{justify-content:center;gap:8px;}
.controls button{min-height:44px;padding:0 16px;border-radius:10px;font-size:15px;
  font-weight:500;background:transparent;border:1px solid var(--rule-strong);
  color:var(--ink);display:inline-flex;align-items:center;gap:8px;}
.controls button:hover:not(:disabled){background:var(--surface-2);}
.controls button:disabled{opacity:.45;}
.controls .speak{background:var(--surface-2);}
.key-hint{text-align:center;color:var(--ink);font-size:13px;}
/* Keycaps stay on the field, never on the card red. */
.key-hint kbd{font-family:var(--mono);font-size:12px;border:1px solid var(--rule-strong);
  border-bottom-width:2px;border-radius:5px;padding:1px 5px;
  background:var(--surface-2);color:var(--ink);}

/* ── Game ─────────────────────────────────────────────────── */
/* The dialog is a seal too, so every word on it sits on red. Nothing inside
   needs a second surface. */
dialog.game{background:var(--seal);color:var(--seal-ink);border:0;
  border-radius:16px;box-shadow:0 24px 64px rgba(0,20,60,.4);}
dialog.game::backdrop{background:rgba(0,18,54,.45);}
.game-bar{position:relative;justify-content:center;border-bottom:1px solid var(--seal-line);
  padding:16px 20px 12px;}
.game-title{font-size:16px;font-weight:500;}
.game-close{position:absolute;right:12px;top:50%;transform:translateY(-50%);
  min-height:36px;border-radius:8px;background:transparent;
  border:1px solid var(--seal-line);color:var(--seal-quiet);font-size:13px;
  font-weight:500;padding:0 12px;}
.game-close:hover{background:rgba(0,0,0,.14);color:var(--seal-ink);}
.game-status{justify-content:center;gap:18px;font-size:12px;
  color:var(--seal-quiet);letter-spacing:0;}
.game-prompt{font-size:20px;font-weight:500;text-align:center;}
.feedback{color:var(--seal-quiet);font-size:14px;text-align:center;min-height:20px;}
.game-actions{justify-content:center;}
.opt{background:rgba(0,0,0,.14);border:1px solid rgba(255,255,255,.26);border-radius:12px;
  color:var(--seal-ink);font-weight:400;display:flex;align-items:center;
  justify-content:center;gap:10px;}
.opt:hover:not(:disabled){background:rgba(0,0,0,.24);border-color:rgba(255,255,255,.42);}
/* The one you got right inverts to white; the one you missed sinks under a
   wash and carries a cross, so colour is never the whole message. */
.opt.is-correct{background:#FFFFFF;border-color:#FFFFFF;color:var(--seal);}
.opt.is-wrong{background:rgba(0,0,0,.28);border-color:rgba(255,255,255,.3);
  color:rgba(255,255,255,.9);}
.opt-mark{display:inline-flex;}
.opt .i{width:20px;height:20px;}
.picker-band h3{font-size:13px;font-weight:500;color:var(--seal-quiet);
  text-align:center;letter-spacing:0;text-transform:none;font-family:var(--font);}
.picker-deck{border-radius:10px;background:rgba(0,0,0,.14);
  border-color:rgba(255,255,255,.26);color:var(--seal-ink);text-align:center;
  align-items:center;}
.picker-deck:hover{border-color:rgba(255,255,255,.42);}
.picker-deck .pp{color:var(--seal-quiet);}
.picker-deck.is-open{border-color:#FFFFFF;}
.picker-deck .pc{color:#FFFFFF;margin-left:6px;}
.picker-deck.is-open .pc{display:inline-flex;}
.score{font-weight:500;font-variant-numeric:tabular-nums;}

/* The question's shape arrives before its words do. A pale sweep on the seal,
   never a spinner: the layout is already the thing being waited for. */
.sk{
  display:block;border-radius:8px;
  background:linear-gradient(90deg,rgba(255,255,255,.1) 0%,rgba(255,255,255,.26) 50%,rgba(255,255,255,.1) 100%);
  background-size:220% 100%;
  animation:sk-sweep 1.15s linear infinite;
}
.sk-prompt{height:22px;width:min(240px,58%);margin:2px auto 24px;border-radius:6px;}
.sk-opt{min-height:76px;border-radius:12px;border:1px solid rgba(255,255,255,.12);}
@keyframes sk-sweep{from{background-position:100% 0;}to{background-position:-130% 0;}}
@media (prefers-reduced-motion:reduce){
  .sk{animation:none;background:rgba(255,255,255,.16);}
}

/* ── Footer ───────────────────────────────────────────────── */
.site-footer{text-align:center;}
.site-footer .site-links{justify-content:center;}
.site-footer p,.site-footer a{color:var(--ink);}

/* ── Small screens ────────────────────────────────────────── */
@media (max-width:560px){
  .masthead{padding:16px 16px 4px;}
  .page-head{padding:32px 0 4px;}
  .hero{padding:40px 0 48px;}
  .hero h1{max-width:16ch;}
  .hero .lede{font-size:17px;}
  .level-row{padding:22px 8px;}
  .band-head{flex-direction:column;align-items:center;gap:2px;}
  .row{padding:12px 8px;}
  .row-pair{font-size:20px;}
  .ladder-row .row-pair{font-size:17px;}
}

/* ── Motion ───────────────────────────────────────────────── */
/* One rhythm across the site. Hover lifts a control and lights its edge;
   pressing pops it back under the pointer and brightens the halo. Panes that
   sit inside a clipped grid take the halo inward, because an outward shadow
   would be cut off by the grid. Every value comes from the tokens at the top
   of this file, and base.css's reduced-motion switch stops all of it. */
.btn,.nav a,.icon-btn,.say,.controls button,.game-close,.picker-deck,.opt,
.option,.listen-play,.tile,.choice-face,.level-row,.deck-card,.review > summary,
.hero-quiet,.site-footer a,.card{
  transition:background-color var(--motion) var(--ease-soft),
    border-color var(--motion) var(--ease-soft),
    color var(--motion) var(--ease-soft),
    box-shadow var(--motion-bounce) var(--ease-soft),
    filter var(--motion) var(--ease-soft),
    translate var(--motion-bounce) var(--ease-spring),
    scale var(--motion-bounce) var(--ease-spring);
}

@media (hover:hover){
  .btn:hover,.nav a:hover,.icon-btn:hover,.say:hover:not(:disabled),
  .controls button:hover:not(:disabled),.game-close:hover,.picker-deck:hover,
  .opt:hover:not(:disabled),.option:hover:not(:disabled),
  .listen-play:hover:not(:disabled),.tile:hover,.choice:hover .choice-face,
  .review > summary:hover{
    translate:0 -1px;
    box-shadow:var(--glow-soft);
  }
  .deck-card:hover,.level-row:hover{box-shadow:var(--glow-in);}
  .card:hover .face{
    box-shadow:var(--shadow),0 0 0 1px rgba(255,255,255,.28),
      0 0 44px rgba(255,204,184,.26);
  }
}

/* The press is quicker than the rest, so it reads as contact, not motion. The
   button goes down under the finger and the halo blooms; on release the spring
   curve brings it back past rest and settles it, a soft pop rather than a snap. */
.btn:is(:active,.is-pressed),.nav a:is(:active,.is-pressed),
.icon-btn:is(:active,.is-pressed),.say:is(:active,.is-pressed):not(:disabled),
.controls button:is(:active,.is-pressed):not(:disabled),
.game-close:is(:active,.is-pressed),.picker-deck:is(:active,.is-pressed),
.opt:is(:active,.is-pressed):not(:disabled),.option:is(:active,.is-pressed):not(:disabled),
.listen-play:is(:active,.is-pressed):not(:disabled),.tile:is(:active,.is-pressed),
.choice:active .choice-face,.choice-face:is(:active,.is-pressed),
.review > summary:is(:active,.is-pressed){
  transform:none;translate:0 1px;scale:.96;
  box-shadow:var(--glow-strong);
  transition-duration:var(--motion-fast);
  transition-timing-function:var(--ease-soft);
}
/* Pressing the card is what starts the turn, so its own pop has to stay
   shallow: the face glow and the pressed edge do the work. */
.card:is(:active,.is-pressed){
  translate:0 1px;scale:.988;
  transition-duration:var(--motion-fast);
  transition-timing-function:var(--ease-soft);
}
.deck-card:is(:active,.is-pressed),.level-row:is(:active,.is-pressed){
  filter:brightness(.96);box-shadow:var(--glow-in-strong);
  transition-duration:var(--motion-fast);
}
.card:is(:active,.is-pressed) .face{
  box-shadow:var(--shadow),0 0 0 1px rgba(255,255,255,.46),
    0 0 0 4px rgba(255,255,255,.12),0 0 34px rgba(255,204,184,.42);
}

/* The practice dialog arrives with the same weight as a button press. */
dialog.game[open]{animation:game-pop var(--motion) var(--ease-soft);}
dialog.game::backdrop{animation:backdrop-in var(--motion) ease-out;}
@keyframes game-pop{
  from{opacity:0;translate:0 10px;scale:.98;}
  to{opacity:1;translate:0 0;scale:1;}
}
@keyframes backdrop-in{from{opacity:0;}to{opacity:1;}}

@media (prefers-reduced-motion:reduce){
  dialog.game[open],dialog.game::backdrop{animation:none;}
  ::view-transition-old(root),::view-transition-new(root){animation:none;}
  /* The turn is instant, so the face swap must be instant with it. */
  .face{transition-delay:0s!important;}
}
