/* ═══════════════════════════════════════════════════════════════════════════
   Vocabuapp — design system
   The iOS look: Apple's system colours and materials, San Francisco (the
   system font; Inter where a system has none), inset grouped lists, Liquid
   Glass bars and buttons that float over the content. One tint (--tint, the
   system blue) marks what can be tapped. The training round is a stage:
   always dark, the word big in the middle, the microphone as a glowing orb.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Inter stands in for SF Pro where the system has none (Windows, Android).
   Apple devices use their own San Francisco and never download it. */
/* Nunito (OFL, fonts/Nunito-OFL.txt) is the rounded face for titles and big
   numbers where the system has no SF Pro Rounded (Android, Windows) — round
   like the mascot. Weights 600–900, variable. */
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 600 900; font-display: fallback;
  src: url(/fonts/nunito-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 600 900; font-display: fallback;
  src: url(/fonts/nunito-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 600 900; font-display: fallback;
  src: url(/fonts/nunito-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: fallback;
  src: url(/fonts/inter-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: fallback;
  src: url(/fonts/inter-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: fallback;
  src: url(/fonts/inter-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: fallback;
  src: url(/fonts/inter-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}

/* ─── Tokens ──────────────────────────────────────────────────────────────── */
:root {
  --font: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI Variable Text', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-rounded: ui-rounded, 'SF Pro Rounded', 'Nunito', -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;

  /* UIKit system colours */
  --blue: #007AFF; --green: #34C759; --indigo: #5856D6; --orange: #FF9500; --pink: #FF2D55;
  --purple: #AF52DE; --red: #FF3B30; --teal: #30B0C7; --yellow: #FFCC00; --mint: #00C7BE;
  --cyan: #32ADE6; --brown: #A2845E; --gray: #8E8E93;
  --gray2: #AEAEB2; --gray3: #C7C7CC; --gray4: #D1D1D6; --gray5: #E5E5EA; --gray6: #F2F2F7;
  /* the same hues dark enough for text on a tinted background */
  --red-text: #D70015; --green-text: #248A3D; --orange-text: #C93400;

  --tint: var(--blue);
  --tint-soft: color-mix(in srgb, var(--tint) 12%, transparent);

  --label: #000;
  --label-2: rgba(60, 60, 67, .6);
  --label-3: rgba(60, 60, 67, .3);
  --label-4: rgba(60, 60, 67, .18);
  --fill: rgba(120, 120, 128, .2);
  --fill-2: rgba(120, 120, 128, .16);
  --fill-3: rgba(118, 118, 128, .12);
  --fill-4: rgba(116, 116, 128, .08);
  --bg: #F2F2F7;          /* systemGroupedBackground */
  --bg-2: #FFF;           /* cells and cards */
  --bg-3: #F2F2F7;        /* something inside a cell */
  --press: #D1D1D6;       /* a row while it is pressed */
  --sep: rgba(60, 60, 67, .29);
  --seg-on: #FFF;         /* the selected segment */
  --backdrop: #DADADF;    /* beside the phone column in a wide window */

  /* Liquid Glass: bars, floating buttons, menus, alerts */
  --glass: rgba(255, 255, 255, .72);
  --glass-thick: rgba(246, 246, 248, .93);
  --glass-rim: inset 0 .5px 0 rgba(255, 255, 255, .95), inset 0 0 0 .5px rgba(0, 0, 0, .07);
  --glass-lift: 0 10px 30px rgba(0, 0, 0, .1), 0 1px 4px rgba(0, 0, 0, .06);
  --glass-lift-s: 0 2px 10px rgba(0, 0, 0, .07), 0 .5px 2px rgba(0, 0, 0, .08);
  --blur: blur(24px) saturate(1.9);
  --dim: rgba(0, 0, 0, .22);

  --r-s: 12px;
  --r: 16px;
  --r-card: 24px;
  --r-xl: 32px;
  --ease: cubic-bezier(.32, .72, 0, 1);
  --ease-swipe: cubic-bezier(.22, .78, .24, 1);   /* goes on at the finger's pace, then settles */
  --spring: cubic-bezier(.34, 1.4, .64, 1);
  /* Soft 3D — the mascot's material (matte, lit from the top left) for the
     app's small solid things: icon badges, little illustrations. The light
     and shadow here; a badge's fill is its colour --c lit the same way (the
     gradient sits on the badge rules: a var() inside a custom property is
     resolved where that is declared, and --c is not set on :root). */
  --soft-3d: inset 0 1.5px 1px rgba(255, 255, 255, .55), inset 0 -2.5px 4px rgba(0, 20, 70, .22), 0 5px 12px -5px rgba(20, 50, 120, .45), 0 1.5px 3px rgba(20, 50, 120, .16);

  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
  --tabbar-h: 62px;
  --tabbar-b: max(12px, calc(var(--safe-b) - 8px));   /* floats just above the home indicator */

  /* The app is as wide as a phone everywhere (see "Phone column"): sizes that
     follow the screen width use --vw, 1 % of the app's width, never vw.
     --app-x is the column's left edge, for elements fixed to the window. */
  --app-w: 400px;
  --app-x: 0px;
  --vw: 1vw;

  /* Glyphs drawn by CSS (masks: only their shape counts) */
  --i-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 14'%3E%3Cpath d='M1.5 1.5 6.5 7l-5 5.5' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='24' height='24' fill='%23fff'/%3E%3Cpath d='m7.4 12.4 3 3 6.2-6.6' fill='none' stroke='%23000' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/mask%3E%3C/defs%3E%3Ccircle cx='12' cy='12' r='10.5' mask='url(%23m)'/%3E%3C/svg%3E");
  --i-bad: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='24' height='24' fill='%23fff'/%3E%3Cpath d='m8.5 8.5 7 7m0-7-7 7' fill='none' stroke='%23000' stroke-width='2.3' stroke-linecap='round'/%3E%3C/mask%3E%3C/defs%3E%3Ccircle cx='12' cy='12' r='10.5' mask='url(%23m)'/%3E%3C/svg%3E");
  --i-spinner: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M12 2.6v4.6'/%3E%3Cpath d='M12 2.6v4.6' opacity='.22' transform='rotate(45 12 12)'/%3E%3Cpath d='M12 2.6v4.6' opacity='.32' transform='rotate(90 12 12)'/%3E%3Cpath d='M12 2.6v4.6' opacity='.42' transform='rotate(135 12 12)'/%3E%3Cpath d='M12 2.6v4.6' opacity='.52' transform='rotate(180 12 12)'/%3E%3Cpath d='M12 2.6v4.6' opacity='.64' transform='rotate(225 12 12)'/%3E%3Cpath d='M12 2.6v4.6' opacity='.76' transform='rotate(270 12 12)'/%3E%3Cpath d='M12 2.6v4.6' opacity='.88' transform='rotate(315 12 12)'/%3E%3C/svg%3E");


  /* The training round's stage (TrainView; light or dark with the theme since
     2026-09-29 — before it was always dark). Also used by the reward layer
     and badges, which sit on <body>. */
  --s-bg: #F2F2F7;
  --s-glow-a: rgba(0, 122, 255, .16); --s-glow-b: rgba(88, 86, 214, .09);
  --s-text: #000;
  --s-label-2: rgba(60, 60, 67, .6); --s-label-3: rgba(60, 60, 67, .3);
  --s-glass: rgba(255, 255, 255, .8); --s-glass-2: #FFF;
  --s-rim: inset 0 .5px 0 rgba(255, 255, 255, .9), inset 0 0 0 .5px rgba(0, 0, 0, .07), 0 2px 8px rgba(0, 0, 0, .06);
  --s-press: rgba(0, 0, 0, .06);
  --s-tint: #007AFF; --s-green: #34C759; --s-red: #FF3B30; --s-yellow: #F5B800; --s-yellow-text: #A15C00;
  --s-link: #007AFF; --s-round: rgba(0, 0, 0, .7); --s-track: rgba(60, 60, 67, .12);
  --s-cta: #000; --s-cta-text: #FFF;
  --s-orb: #FFF; --s-mc-key: rgba(0, 0, 0, .06);
  --s-menu: rgba(255, 255, 255, .94); --s-menu-shadow: 0 20px 50px rgba(0, 0, 0, .18);
  --s-hit: #1F9E45; --s-combo: #C93400;
  --s-card-shadow: 0 20px 50px rgba(0, 0, 0, .14), inset 0 -1px 0 rgba(0, 0, 0, .06);
  --s-badge: rgba(255, 255, 255, .92); --s-badge-shadow: 0 12px 34px rgba(0, 0, 0, .16);
  --s-glow-blend: multiply;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --blue: #0A84FF; --green: #30D158; --indigo: #5E5CE6; --orange: #FF9F0A; --pink: #FF375F;
    --purple: #BF5AF2; --red: #FF453A; --teal: #40CBE0; --yellow: #FFD60A; --mint: #63E6E2;
    --cyan: #64D2FF; --brown: #AC8E68;
    --gray2: #636366; --gray3: #48484A; --gray4: #3A3A3C; --gray5: #2C2C2E; --gray6: #1C1C1E;
    --red-text: #FF6961; --green-text: #30DB5B; --orange-text: #FFB340;
    --tint-soft: color-mix(in srgb, var(--tint) 20%, transparent);
    --label: #FFF; --label-2: rgba(235, 235, 245, .6); --label-3: rgba(235, 235, 245, .3); --label-4: rgba(235, 235, 245, .16);
    --fill: rgba(120, 120, 128, .36); --fill-2: rgba(120, 120, 128, .32); --fill-3: rgba(118, 118, 128, .24); --fill-4: rgba(118, 118, 128, .18);
    --bg: #000; --bg-2: #1C1C1E; --bg-3: #2C2C2E; --press: #3A3A3C;
    --sep: rgba(84, 84, 88, .65); --seg-on: #636366; --backdrop: #151517;
    --glass: rgba(44, 44, 46, .66);
    --glass-thick: rgba(36, 36, 38, .9);
    --glass-rim: inset 0 .5px 0 rgba(255, 255, 255, .2), inset 0 0 0 .5px rgba(255, 255, 255, .09);
    --glass-lift: 0 10px 34px rgba(0, 0, 0, .6), 0 1px 3px rgba(0, 0, 0, .35);
    --glass-lift-s: 0 2px 10px rgba(0, 0, 0, .4);
    --dim: rgba(0, 0, 0, .48);
    --s-bg: #000;
    --s-glow-a: rgba(10, 132, 255, .34); --s-glow-b: rgba(94, 92, 230, .2);
    --s-text: #FFF;
    --s-label-2: rgba(235, 235, 245, .6); --s-label-3: rgba(235, 235, 245, .3);
    --s-glass: rgba(255, 255, 255, .1); --s-glass-2: rgba(255, 255, 255, .17);
    --s-rim: inset 0 .5px 0 rgba(255, 255, 255, .25), inset 0 0 0 .5px rgba(255, 255, 255, .1);
    --s-press: rgba(255, 255, 255, .1);
    --s-tint: #0A84FF; --s-green: #30D158; --s-red: #FF453A; --s-yellow: #FFD60A; --s-yellow-text: #FFD60A;
    --s-link: #409CFF; --s-round: rgba(255, 255, 255, .85); --s-track: rgba(255, 255, 255, .15);
    --s-cta: #FFF; --s-cta-text: #000;
    --s-orb: rgba(255, 255, 255, .12); --s-mc-key: rgba(255, 255, 255, .14);
    --s-menu: rgba(44, 44, 46, .84); --s-menu-shadow: 0 20px 50px rgba(0, 0, 0, .6);
    --s-hit: #7EF29A; --s-combo: #FF9F0A;
    --s-card-shadow: 0 30px 70px rgba(0, 0, 0, .55), inset 0 -1px 0 rgba(0, 0, 0, .06);
    --s-badge: rgba(44, 44, 46, .84); --s-badge-shadow: inset 0 .5px 0 rgba(255, 255, 255, .25), 0 12px 34px rgba(0, 0, 0, .5);
    --s-glow-blend: screen;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --blue: #0A84FF; --green: #30D158; --indigo: #5E5CE6; --orange: #FF9F0A; --pink: #FF375F;
  --purple: #BF5AF2; --red: #FF453A; --teal: #40CBE0; --yellow: #FFD60A; --mint: #63E6E2;
  --cyan: #64D2FF; --brown: #AC8E68;
  --gray2: #636366; --gray3: #48484A; --gray4: #3A3A3C; --gray5: #2C2C2E; --gray6: #1C1C1E;
  --red-text: #FF6961; --green-text: #30DB5B; --orange-text: #FFB340;
  --tint-soft: color-mix(in srgb, var(--tint) 20%, transparent);
  --label: #FFF; --label-2: rgba(235, 235, 245, .6); --label-3: rgba(235, 235, 245, .3); --label-4: rgba(235, 235, 245, .16);
  --fill: rgba(120, 120, 128, .36); --fill-2: rgba(120, 120, 128, .32); --fill-3: rgba(118, 118, 128, .24); --fill-4: rgba(118, 118, 128, .18);
  --bg: #000; --bg-2: #1C1C1E; --bg-3: #2C2C2E; --press: #3A3A3C;
  --sep: rgba(84, 84, 88, .65); --seg-on: #636366; --backdrop: #151517;
  --glass: rgba(44, 44, 46, .66);
  --glass-thick: rgba(36, 36, 38, .9);
  --glass-rim: inset 0 .5px 0 rgba(255, 255, 255, .2), inset 0 0 0 .5px rgba(255, 255, 255, .09);
  --glass-lift: 0 10px 34px rgba(0, 0, 0, .6), 0 1px 3px rgba(0, 0, 0, .35);
  --glass-lift-s: 0 2px 10px rgba(0, 0, 0, .4);
  --dim: rgba(0, 0, 0, .48);
  --s-bg: #000;
  --s-glow-a: rgba(10, 132, 255, .34); --s-glow-b: rgba(94, 92, 230, .2);
  --s-text: #FFF;
  --s-label-2: rgba(235, 235, 245, .6); --s-label-3: rgba(235, 235, 245, .3);
  --s-glass: rgba(255, 255, 255, .1); --s-glass-2: rgba(255, 255, 255, .17);
  --s-rim: inset 0 .5px 0 rgba(255, 255, 255, .25), inset 0 0 0 .5px rgba(255, 255, 255, .1);
  --s-press: rgba(255, 255, 255, .1);
  --s-tint: #0A84FF; --s-green: #30D158; --s-red: #FF453A; --s-yellow: #FFD60A; --s-yellow-text: #FFD60A;
  --s-link: #409CFF; --s-round: rgba(255, 255, 255, .85); --s-track: rgba(255, 255, 255, .15);
  --s-cta: #FFF; --s-cta-text: #000;
  --s-orb: rgba(255, 255, 255, .12); --s-mc-key: rgba(255, 255, 255, .14);
  --s-menu: rgba(44, 44, 46, .84); --s-menu-shadow: 0 20px 50px rgba(0, 0, 0, .6);
  --s-hit: #7EF29A; --s-combo: #FF9F0A;
  --s-card-shadow: 0 30px 70px rgba(0, 0, 0, .55), inset 0 -1px 0 rgba(0, 0, 0, .06);
  --s-badge: rgba(44, 44, 46, .84); --s-badge-shadow: inset 0 .5px 0 rgba(255, 255, 255, .25), 0 12px 34px rgba(0, 0, 0, .5);
  --s-glow-blend: screen;
  color-scheme: dark;
}

/* ─── Base ────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overscroll-behavior-y: none; background: var(--bg); }
html, body { min-height: 100%; }
body {
  overflow-x: clip;   /* the mascot flies past the edges (mascot.js) — never a sideways scroll */
  margin: 0;
  background: var(--bg);
  color: var(--label);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.3;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
button:disabled { cursor: default; }
a { color: var(--tint); text-decoration: none; }
img { max-width: 100%; }
[hidden] { display: none !important; }
::selection { background: color-mix(in srgb, var(--tint) 28%, transparent); }
:focus-visible { outline: 3px solid color-mix(in srgb, var(--tint) 55%, transparent); outline-offset: 2px; }
input:focus-visible, textarea:focus-visible { outline: none; }

.ic { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.ic-fill { fill: currentColor; stroke: none; }
.ic-play { fill: currentColor; }

/* The page itself scrolls. #view used to be a fixed full-screen box with its
   own scrollbar: on iOS a swipe right after reaching its end went to the page
   behind it and nothing moved until the bounce settled, and a swipe that
   started on the tab bar scrolled nothing at all. Full-screen layouts use
   --view-fill (the screen minus the view's bottom padding) instead of 100%. */
.view {
  --view-pb: calc(var(--tabbar-h) + var(--tabbar-b) + 28px);
  --view-fill: calc(100vh - var(--view-pb));
  min-height: 100vh;
  padding-bottom: var(--view-pb);
  overflow-x: clip;
}
body.no-tabbar .view { --view-pb: calc(var(--safe-b) + 16px); }
@supports (height: 100svh) {
  .view { --view-fill: calc(100svh - var(--view-pb)); min-height: 100svh; }
}

/* Navigation as on iOS (app.js sets data-nav): a pushed page slides in from
   the right, going back from the left, a round rises like a full-screen
   sheet, everything else fades. */
.view.enter > * { animation: nav-fade .26s ease both; }
.view.enter[data-nav="push"] > * { animation: nav-push .44s var(--ease) both; }
.view.enter[data-nav="pop"] > * { animation: nav-pop .44s var(--ease) both; }
.view.enter[data-nav="modal"] > * { animation: nav-modal .5s var(--ease) both; }
@keyframes nav-fade { from { opacity: 0; } }
@keyframes nav-push { from { opacity: 0; transform: translateX(26%); } }
@keyframes nav-pop { from { opacity: 0; transform: translateX(-18%); } }
@keyframes nav-modal { from { opacity: 0; transform: translateY(14%); } }

/* Swiping between the tabs (tabSwipe.js): the page follows the finger, the
   browser scrolls it up and down only. Turned, the old page leaves as a
   still copy (.tab-ghost, fixed over the view's place) and the new one comes
   in right beside it — both the same way in the same time; its cards are
   there already, they do not rise in again. */
.view-home, .view-sets { touch-action: pan-y pinch-zoom; }
/* the page carries its own transform (tabSwipe.js shift) on a layer of its
   own while dragged; the Vokis on it go on moving (2026-10-02, the owner) */
.view.tab-drag > * { animation: none; will-change: transform; }
.view.tab-back > * { transition: transform .3s var(--ease); }
.view.enter[data-nav="swipe"] > * { animation: nav-swipe .34s var(--ease-swipe) both; }
.view.enter[data-nav="swipe"] .set-card { animation: none; }
@keyframes nav-swipe { from { transform: translateX(var(--swipe-from, 100%)); } }
.tab-ghost { position: fixed; top: 0; z-index: 19; height: 100%; overflow: hidden; pointer-events: none; }
.tab-ghost > .view > * { animation: tab-out .34s var(--ease-swipe) both; }
.tab-ghost > .view > * * { animation: none !important; transition: none !important; }
@keyframes tab-out { from { transform: translateX(var(--tab-at)); } to { transform: translateX(var(--tab-to)); } }

.splash { min-height: var(--view-fill); display: grid; place-items: center; }
.splash svg { animation: breathe 1.6s ease-in-out infinite; filter: drop-shadow(0 12px 28px rgba(0, 90, 255, .28)); }
@keyframes breathe { 50% { transform: scale(.95); opacity: .85; } }
.noscript { text-align: center; padding: 40px 20px; }

/* ─── Layout ──────────────────────────────────────────────────────────────── */
.page {
  max-width: 760px;
  margin: 0 auto;
  padding: calc(var(--safe-t) + 10px) 16px 12px;
}
.page-narrow { max-width: 600px; }
.h1 { font-size: 34px; line-height: 41px; font-weight: 700; margin: 0; }
.h2 { font-size: 28px; line-height: 34px; font-weight: 700; margin: 0; }
/* Titles in the rounded face, like the mascot (and like Apple's own SF Rounded titles) */
:is(.h1, .h2, .hero-title, .res-title, .onb-title, .empty h2, .dlg-title) { font-family: var(--font-rounded); }
.eyebrow { font-size: 13px; line-height: 18px; font-weight: 600; text-transform: uppercase; color: var(--label-2); }
.sub { margin: 2px 0 0; color: var(--label-2); font-size: 15px; }
.lead { color: var(--label-2); font-size: 15px; line-height: 1.4; margin: 6px 4px 20px; }
.muted { color: var(--label-2); }
.small { font-size: 13px; }
.fine { font-size: 13px; line-height: 1.4; color: var(--label-2); text-align: center; margin: 4px 0 0; }
.center { display: flex; margin: 2px auto 0; }
.text-bad { color: var(--red) !important; }

.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 0 0 10px; }
.section-head h2 { font-size: 22px; line-height: 28px; font-weight: 700; margin: 0; }
.pill { font-size: 15px; font-weight: 400; color: var(--label-2); }

.card { background: var(--bg-2); border-radius: var(--r-card); padding: 16px; }

/* Navigation bar. Its buttons are glass circles; the bar itself has no
   background until content scrolls under it (html.scrolled, app.js) — then
   a soft blurred edge, as on iOS 26. */
.topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 8px;
  min-height: calc(var(--safe-t) + 58px);
  margin: calc(-1 * var(--safe-t) - 10px) -16px 6px;
  padding: calc(var(--safe-t) + 7px) 16px 7px;
  isolation: isolate;
}
.topbar::before {
  content: ''; position: absolute; z-index: -1; inset: 0 0 -26px; pointer-events: none;
  background: linear-gradient(to bottom, var(--bg) 50%, color-mix(in srgb, var(--bg) 82%, transparent) 72%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, transparent);
  mask-image: linear-gradient(to bottom, #000 62%, transparent);
  opacity: 0; transition: opacity .2s;
}
.scrolled .topbar::before { opacity: 1; }
.topbar-title { flex: 1; min-width: 0; text-align: center; font-weight: 600; font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.icon-btn {
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--label);
  transition: background-color .15s, transform .25s var(--spring);
}
.icon-btn:active { transform: scale(.9); }
.icon-btn .ic { width: 22px; height: 22px; }
.icon-btn-spacer { width: 44px; flex: none; }
.topbar .icon-btn, .glass-btn {
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--glass-rim), var(--glass-lift-s);
}
.topbar .icon-btn .ic { width: 21px; height: 21px; stroke-width: 2.1; }
.topbar .btn-sm { min-height: 44px; padding: 0 18px; font-size: 17px; }

.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 14px 0 16px; }
.head-actions { display: flex; align-items: center; gap: 10px; margin-top: -1px; }
.head-actions .btn-soft {
  min-height: 40px; background: var(--glass); color: var(--label);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--glass-rim), var(--glass-lift-s);
}

/* ─── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 50px; padding: 0 22px;
  border-radius: 999px;
  font-weight: 600; font-size: 17px; line-height: 1.2;
  white-space: nowrap;
  transition: transform .25s var(--spring), background-color .2s, opacity .2s, filter .2s;
  user-select: none; -webkit-user-select: none;
  overflow: hidden;
}
.btn:active:not(:disabled) { transform: scale(.97); }
.btn:disabled { opacity: .45; }
.btn .ic { width: 20px; height: 20px; stroke-width: 2.1; }
.btn-sm { min-height: 34px; padding: 0 14px; font-size: 15px; gap: 5px; }
.btn-sm .ic { width: 17px; height: 17px; }
.btn-lg { min-height: 54px; }
.btn-block { display: flex; width: 100%; }
.btn-block + .btn-block { margin-top: 10px; }
.btn-primary { background: var(--tint); color: #fff; }
.btn-primary:active:not(:disabled) { filter: brightness(.9); }
.btn-primary:disabled { opacity: 1; background: var(--fill-3); color: var(--label-3); }
.btn-soft { background: var(--fill-3); color: var(--tint); }
.btn-soft:active:not(:disabled) { background: var(--fill); }
.btn-ghost { color: var(--tint); }
.btn-ghost:active:not(:disabled) { opacity: .5; }
.btn-danger { background: var(--red); color: #fff; }
@media (hover: hover) {
  .btn-primary:hover:not(:disabled), .btn-danger:hover:not(:disabled) { filter: brightness(1.08); }
  .btn-soft:hover:not(:disabled) { background: var(--fill-2); }
  .btn-ghost:hover:not(:disabled) { background: var(--fill-4); }
}
.link-btn {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--tint); font-weight: 400; font-size: 17px;
  padding: 6px 2px; border-radius: 8px;
  transition: opacity .15s;
}
.link-btn .ic { width: 17px; height: 17px; stroke-width: 2.2; }
.link-btn .ic-chevron { width: 15px; height: 15px; stroke-width: 2.6; margin-left: -2px; }
.link-btn:active { opacity: .4; }
.link-btn:disabled { color: var(--label-2); }

/* Avatar: a glass circle, the account's monogram in Contacts grey */
.avatar-btn {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--glass-rim), var(--glass-lift-s);
  color: var(--label-2); font-weight: 600; font-size: 17px;
  transition: transform .25s var(--spring);
}
.avatar-btn .ic { width: 22px; height: 22px; }
.avatar-btn:active { transform: scale(.9); }
.avatar-btn.has-initial { background: linear-gradient(180deg, #A5ABB8, #858994); color: #fff; box-shadow: var(--glass-lift-s); }

/* ─── Tab bar ─────────────────────────────────────────────────────────────── */
/* iOS 26: a floating glass capsule with the tabs, the scan button as a
   separate circle beside it (where iOS puts the search tab). */
.tabbar {
  position: fixed; z-index: 20;
  left: calc(var(--app-x) + 20px); right: calc(var(--app-x) + 20px); bottom: var(--tabbar-b);
  display: flex; align-items: center; gap: 12px;
  pointer-events: none;
}
.tab-group {
  flex: 1; min-width: 0;
  display: flex; gap: 2px;
  height: var(--tabbar-h); padding: 5px;
  border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--glass-rim), var(--glass-lift);
  pointer-events: auto;
}
.tab {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  border-radius: 999px;
  color: var(--label); font-size: 10.5px; font-weight: 600; letter-spacing: .01em;
  transition: color .2s, background-color .25s;
}
.tab .ic { width: 25px; height: 25px; }
.tab.on { color: var(--tint); background: var(--fill-3); }
.tab:active { background: var(--fill-2); }
.tab-scan {
  flex: none; width: var(--tabbar-h); height: var(--tabbar-h);
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--tint); color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), inset 0 0 0 .5px rgba(255, 255, 255, .15), 0 10px 26px color-mix(in srgb, var(--tint) 38%, transparent);
  pointer-events: auto;
  transition: transform .3s var(--spring);
}
.tab-scan .ic { width: 27px; height: 27px; stroke-width: 2; }
.tab-scan:active { transform: scale(.9); }

/* ─── Home ────────────────────────────────────────────────────────────────── */
.home-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; margin: 14px 0 18px; }
.home-head .avatar-btn { margin-bottom: 1px; }

/* The card for what to do now — like a featured card in the App Store */
.hero, .quiz-card {
  position: relative; overflow: hidden; isolation: isolate;
  color: #fff;
  background:
    radial-gradient(90% 70% at 100% 0%, rgba(130, 200, 255, .55), transparent 60%),
    radial-gradient(80% 90% at 0% 100%, rgba(94, 70, 240, .75), transparent 70%),
    linear-gradient(160deg, #2E8FFF 0%, #0A63FF 50%, #3D3AD8 100%);
  border-radius: var(--r-card);
  box-shadow: 0 16px 34px -14px rgba(10, 80, 255, .6);
}
.hero { padding: 20px; }
.hero-eyebrow { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 600; text-transform: uppercase; color: rgba(255, 255, 255, .8); }
.hero-eyebrow .ic { width: 15px; height: 15px; stroke-width: 2.4; }
.hero-big { display: flex; align-items: baseline; gap: 10px; margin: 4px 0 0; flex-wrap: wrap; }
.hero-big b { font-family: var(--font-rounded); font-size: 64px; line-height: 1.05; font-weight: 700; font-variant-numeric: tabular-nums; }
.hero-big span { font-size: 20px; font-weight: 600; line-height: 1.25; }
.hero-title { font-size: 24px; line-height: 1.2; font-weight: 700; margin: 10px 0 4px; }
.hero-text { margin: 6px 0 18px; color: rgba(255, 255, 255, .85); font-size: 15px; line-height: 1.4; max-width: 44ch; }
.hero-actions { display: flex; flex-direction: column; gap: 2px; }
/* the empty Today's starter set (HomeView): a glass row under the two ways to make a set */
.hero-starter { display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 12px; padding: 12px 14px; border-radius: 18px; text-align: left; color: #FFF;
  background: rgba(255, 255, 255, .16); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22); transition: transform .2s var(--spring), background-color .2s; }
.hero-starter:active { transform: scale(.98); background: rgba(255, 255, 255, .24); }
.hero-starter-ic { width: 38px; height: 38px; flex: none; border-radius: 50%; display: grid; place-items: center; background: #FFF; color: var(--tint); }
.hero-starter-ic .ic { width: 16px; height: 16px; margin-left: 2px; }
.hero-starter-t { flex: 1; min-width: 0; }
.hero-starter-t b { display: block; font-size: 16px; font-weight: 700; }
.hero-starter-t small { display: block; margin-top: 1px; font-size: 14px; opacity: .85; }
.hero-starter > .ic { width: 16px; height: 16px; opacity: .7; }
.btn-hero { width: 100%; background: #fff; color: #0A5CFF; box-shadow: 0 6px 18px rgba(0, 30, 120, .22); }
.btn-hero:active:not(:disabled) { filter: brightness(.94); }
/* No voice quiz while the month's spoken answers are used up (limitHints.js spokenSpent): its
   start button is a sunk well with a gold lock — a tap opens the gold sheet (Today, the practise panel) */
.btn-hero.locked { background: rgba(0, 20, 90, .3); color: #fff; box-shadow: inset 0 1px 3px rgba(0, 10, 60, .4), inset 0 0 0 1px rgba(255, 255, 255, .16); }
.btn-hero.locked .ic { color: #FFD66B; stroke-width: 2.4; }
.btn-hero-ghost { width: 100%; min-height: 44px; color: #fff; font-weight: 600; }
.btn-hero-ghost:active { opacity: .6; }
.hero-note { margin-top: 10px; font-size: 13px; text-align: center; color: rgba(255, 255, 255, .72); }
.hero-art {
  width: 58px; height: 58px; border-radius: 16px;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .2); color: #fff;
  box-shadow: inset 0 .5px 0 rgba(255, 255, 255, .45);
  margin-bottom: 6px;
}
.hero-art .ic { width: 30px; height: 30px; }

/* Numbers in tiles, the way Fitness and Health show them */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 12px 0; }
.stat {
  background: var(--bg-2); border-radius: 20px;
  padding: 14px 8px 13px;
  display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center;
}
.stat b { font-family: var(--font-rounded); font-size: 26px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stat small { font-size: 12px; color: var(--label-2); font-weight: 500; line-height: 1.25; }
.stat-of { font-size: 15px; color: var(--label-2); font-weight: 600; }
.stat-ic { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; margin-bottom: 3px; }
.stat-ic .ic { width: 18px; height: 18px; stroke-width: 2.2; }
.stat-ic.flame { background: var(--fill-3); color: var(--label-3); }
.stat.lit .stat-ic.flame { background: color-mix(in srgb, var(--orange) 16%, transparent); color: var(--orange); }
.stat.lit .stat-ic.flame .ic { fill: currentColor; }
.stat-ic.known { background: color-mix(in srgb, var(--green) 16%, transparent); color: var(--green); }
.stat-ic.goal { background: var(--tint-soft); color: var(--tint); }
.stat-ic.mic { background: color-mix(in srgb, var(--purple) 15%, transparent); color: var(--purple); }
.goal-ring { width: 32px; height: 32px; margin-bottom: 3px; transform: rotate(-90deg); }
.ring-bg { fill: none; stroke: color-mix(in srgb, var(--tint) 18%, transparent); stroke-width: 5.5; }
.ring-fg { fill: none; stroke: var(--tint); stroke-width: 5.5; stroke-linecap: round; transition: stroke-dashoffset 1s var(--ease); }
.goal-ring.done .ring-bg { stroke: color-mix(in srgb, var(--green) 20%, transparent); }
.goal-ring.done .ring-fg { stroke: var(--green); }

/* The week as a Health chart: bars on a baseline, the daily goal dashed */
.week { margin-bottom: 26px; padding-bottom: 12px; }
.week .section-head { margin-bottom: 14px; }
.week .section-head h2 { font-size: 17px; line-height: 22px; font-weight: 600; }
.week .section-head .muted { font-size: 15px; }
.week-bars { --plot: 92px; position: relative; display: grid; grid-template-columns: repeat(7, 1fr); align-items: end; padding-right: 24px; }
.week-bars::before {
  content: ''; position: absolute; left: 0; right: 22px; bottom: calc(24px + var(--plot) * var(--goal, 2));
  border-top: 1.5px dashed color-mix(in srgb, var(--green) 70%, transparent);
  pointer-events: none;
}
.week-bars::after {
  content: attr(data-goal); position: absolute; right: 0; bottom: calc(24px + var(--plot) * var(--goal, 2) - 8px);
  font-size: 11px; font-weight: 600; color: var(--green); font-variant-numeric: tabular-nums;
}
.wb { display: flex; flex-direction: column; align-items: stretch; gap: 6px; }
.wb-track { position: relative; height: var(--plot); border-bottom: .5px solid var(--sep); }
.wb-track i {
  position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  width: min(62%, 22px);
  border-radius: 6px 6px 2px 2px;
  background: var(--gray4);
  transition: height .8s var(--ease);
}
.wb.hit .wb-track i { background: var(--green); }
.wb.today .wb-track i { background: var(--tint); }
.wb.today.hit .wb-track i { background: var(--green); }
.wb-day { font-size: 12px; line-height: 18px; font-weight: 500; color: var(--label-2); text-align: center; }
.wb.today .wb-day { color: var(--label); font-weight: 700; }

/* ─── Set lists ───────────────────────────────────────────────────────────── */
/* Every set a card of its own, one below the other (setCardHTML; the owner's
   pick A of tools/drafts/library-designs2.html): its face on the language's colour,
   name, words and last practice, on the right what is to do (due · done ·
   new), below the language pair, the share known and the mastery bar. */
.set-grid, .set-list { display: flex; flex-direction: column; gap: 10px; }
.set-list:has(> .empty) { background: var(--bg-2); border-radius: var(--r-card); }
.set-card {
  position: relative;
  display: grid; align-items: center;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "ic name state" "ic sub state" "meta meta meta" "bar bar bar";
  column-gap: 12px; row-gap: 1px;
  width: 100%; text-align: left;
  padding: 14px 14px 13px; border-radius: 22px;
  background: var(--bg-2); box-shadow: 0 10px 22px -16px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .04);
  transition: transform .2s var(--spring), background-color .25s;
}
.set-card:active { transform: scale(.98); transition: transform .1s; }
@media (hover: hover) { .set-card:hover { background: color-mix(in srgb, var(--bg-2) 94%, var(--label)); } }
.set-card-name { grid-area: name; align-self: end; font: 800 17px / 1.2 var(--font-rounded); overflow-wrap: anywhere; }
.set-card-sub { grid-area: sub; align-self: start; font-size: 13.5px; line-height: 18px; color: var(--label-2); }
.set-card-state { grid-area: state; align-self: center; }
.set-card-due { display: grid; place-items: center; min-width: 30px; height: 30px; padding: 0 8px; border-radius: 99px; background: #FF453A; color: #fff;
  font: 800 14px var(--font-rounded); box-shadow: 0 6px 12px -6px rgba(255, 69, 58, .9); }
.set-card-done { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; background: rgba(48, 209, 88, .16); color: var(--green); }
.set-card-done .ic { width: 16px; height: 16px; stroke-width: 3; }
.set-card-new { display: inline-flex; padding: 3px 10px; border-radius: 99px; background: var(--tint-soft); color: var(--tint); font: 800 12.5px var(--font-rounded); }
.set-card-meta { grid-area: meta; display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 10px; font-size: 12.5px; font-weight: 600; color: var(--label-2); }
.set-card .mbar { grid-area: bar; height: 7px; margin-top: 8px; }
.set-card .set-ic { position: relative; width: 56px; height: 56px; border-radius: 30%; }
.set-card .set-ic .ic { width: 26px; height: 26px; }
/* coming in: the cards rise one after the other */
.view.enter .set-card { animation: set-rise .5s var(--spring) both; }
.view.enter .set-card:nth-child(2) { animation-delay: .04s; } .view.enter .set-card:nth-child(3) { animation-delay: .08s; }
.view.enter .set-card:nth-child(4) { animation-delay: .12s; } .view.enter .set-card:nth-child(n + 5) { animation-delay: .16s; }
.view.enter .set-card:nth-child(n + 9) { animation: none; }
@keyframes set-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.set-ic {
  grid-area: ic; align-self: center;
  width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--c, var(--gray)); color: #fff;
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .08), inset 0 1px 0 rgba(255, 255, 255, .22);
}
.set-ic .ic { width: 19px; height: 19px; stroke-width: 2.1; }
.set-ic[data-lang="en"] { --c: var(--blue); }
.set-ic[data-lang="fr"] { --c: var(--indigo); }
.set-ic[data-lang="es"] { --c: var(--red); }
.set-ic[data-lang="it"] { --c: var(--green); }
.set-ic[data-lang="la"] { --c: var(--brown); }
.set-ic[data-lang="pt"] { --c: var(--mint); }
.set-ic[data-lang="nl"] { --c: var(--orange); }
.set-ic[data-lang="pl"] { --c: var(--pink); }
.set-ic[data-lang="ru"] { --c: var(--purple); }
.set-ic[data-lang="tr"] { --c: var(--cyan); }
.set-ic[data-lang="de"] { --c: var(--teal); }
.set-ic[data-lang="uk"] { --c: color-mix(in srgb, var(--yellow) 70%, var(--orange)); }
.set-ic[data-lang="ar"] { --c: color-mix(in srgb, var(--green) 62%, #0B3D2E); }
.set-ic[data-lang="fa"] { --c: color-mix(in srgb, var(--red) 55%, var(--brown)); }

.lang-pair {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 11px; font-weight: 600; letter-spacing: .03em; line-height: 16px;
  padding: 0 6px; border-radius: 5px;
  background: var(--fill-3); color: var(--label-2);
}
.lang-pair i { font-style: normal; opacity: .7; }
.badge { flex: none; font-size: 13px; font-weight: 600; line-height: 18px; padding: 2px 9px; border-radius: 999px; white-space: nowrap; }
.badge.due { background: var(--tint-soft); color: var(--tint); }

.mbar { display: flex; height: 4px; border-radius: 99px; background: var(--fill-3); overflow: hidden; }
.mbar.big { height: 8px; }
.mbar i { display: block; height: 100%; transition: width .8s var(--ease); }
.mb-known { background: var(--green); }
.mb-learning { background: var(--orange); }
.mlegend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 10px; font-size: 13px; color: var(--label-2); }
.mlegend span { display: inline-flex; align-items: center; gap: 6px; }
.mlegend b { color: var(--label); font-weight: 600; }
.dot { width: 10px; height: 10px; border-radius: 50%; flex: none; display: inline-block; }
.dot.known { background: var(--green); }
.dot.learning { background: var(--orange); }
.dot.fresh, .dot.new { background: var(--gray3); }
.dot.due { box-shadow: 0 0 0 3px color-mix(in srgb, var(--tint) 30%, transparent); }

.search {
  display: flex; align-items: center; gap: 7px;
  height: 40px; padding: 0 14px; margin-bottom: 16px;
  border-radius: 999px;
  background: var(--fill-3); color: var(--label-2);
}
.search .ic { width: 18px; height: 18px; stroke-width: 2.2; }
.search input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--label); height: 100%; font-size: 17px; caret-color: var(--tint); }
.search input::placeholder { color: var(--label-2); }
.no-hits { text-align: center; color: var(--label-2); margin: 28px 0; }

/* Library: groups (setGroups.js); "Practise several" and "New group" in a
   quiet line over the list, the sort a round button beside the plus */
.lib-line { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: -6px 4px 12px; }
.lib-line .link-btn { display: inline-flex; align-items: center; gap: 5px; min-height: 36px; font-size: 15px; font-weight: 600; }
.lib-line .link-btn .ic { width: 16px; height: 16px; stroke-width: 2.3; }
.set-group + .set-group { margin-top: 26px; }
.group-head { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; padding-left: 4px; }
.group-toggle { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; padding: 4px 0; text-align: left; }
.group-toggle:active { opacity: .5; }
.group-name { min-width: 0; font-weight: 700; font-size: 22px; line-height: 28px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-count { flex: none; font-size: 17px; color: var(--label-2); }
.group-chev { order: 3; width: 16px; height: 16px; color: var(--tint); stroke-width: 2.8; transform: rotate(90deg); transition: transform .3s var(--ease); }
.set-group.shut .group-chev { transform: none; }
.group-head .icon-btn { width: 32px; height: 32px; background: var(--tint-soft); color: var(--tint); }
.group-head .icon-btn .ic { width: 17px; height: 17px; stroke-width: 2.4; }
.group-head .group-play .ic { width: 15px; height: 15px; margin-left: 2px; }
.set-group.shut .set-list { display: none; }
.searching .set-group.shut .set-list { display: block; }
.set-group-tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 10px 2px 8px; border-radius: 999px;
  background: var(--tint-soft); color: var(--tint);
  font-size: 13px; font-weight: 600; line-height: 20px;
}
.set-group-tag .ic { width: 15px; height: 15px; }
button.set-group-tag:active { opacity: .6; }

/* Library: practising several sets — a group's play button, the picker and
   its bar above the tab bar (LibraryView → MixView). Picking works like
   "Select" in Photos or Mail: a circle in front of every row. */
.pick-box {
  flex: none; width: 24px; height: 24px; display: grid; place-items: center;
  border: 1.5px solid var(--gray3); border-radius: 50%;
  color: transparent; transition: background-color .15s, border-color .15s, color .15s;
}
.pick-box .ic { width: 14px; height: 14px; stroke-width: 3; }
.set-card.pickable { grid-template-columns: auto auto minmax(0, 1fr) auto; grid-template-areas: "pick ic name state" "pick ic sub state" "pick meta meta meta" "pick bar bar bar"; }
.set-card.pickable .pick-box { grid-area: pick; }
.set-card[aria-pressed="true"] .pick-box,
.group-pick[aria-checked="true"] .pick-box,
.group-pick[aria-checked="mixed"] .pick-box { background: var(--tint); border-color: var(--tint); color: #fff; }
.group-pick { flex: none; width: 44px; height: 36px; display: grid; place-items: center; border-radius: 12px; }
.library.picking { padding-bottom: 84px; }
.pick-bar {
  position: fixed; z-index: 21;
  left: calc(var(--app-x) + 16px); right: calc(var(--app-x) + 16px);
  bottom: calc(var(--tabbar-b) + var(--tabbar-h) + 12px);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 7px 7px 7px 22px; border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--glass-rim), var(--glass-lift);
  animation: pick-in .4s var(--spring);
}
@keyframes pick-in { from { opacity: 0; transform: translateY(16px) scale(.96); } }
.pick-sum { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.pick-sum b { font-weight: 600; font-size: 15px; }
.pick-sum small { font-size: 13px; color: var(--label-2); }
.pick-bar .btn { flex: none; min-height: 46px; }
body.picking .toast { bottom: calc(var(--tabbar-b) + var(--tabbar-h) + 86px); }
.mix-sets .check-list { margin: 0; background: var(--bg-2); border-radius: var(--r-card); }

.empty { text-align: center; padding: 30px 12px 10px; }
.empty-mascot .mascot { margin: 0 auto 4px; }
.empty h2 { font-size: 22px; line-height: 28px; font-weight: 700; margin: 20px 0 6px; }
.empty p { color: var(--label-2); font-size: 15px; line-height: 1.4; margin: 0 auto 22px; max-width: 32ch; }
.empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }

/* ─── Set page ────────────────────────────────────────────────────────────── */
.set-hero { margin-bottom: 20px; }
.set-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; font-size: 15px; color: var(--label-2); margin-bottom: 4px; }
.set-meta .lang-pair { font-size: 12px; line-height: 20px; padding: 0 7px; border-radius: 6px; }
.set-title { margin-bottom: 16px; overflow-wrap: anywhere; }
.set-last { margin-top: 8px; font-size: 13px; color: var(--label-2); }

/* What reading aloud can and cannot do for a set's language (Latin: not
   perfect; Ancient Greek: none) — components.js bindPractisePanel. */
.lang-note { display: flex; gap: 8px; align-items: flex-start; margin: 0 4px 12px; font-size: 13px; line-height: 1.4; color: var(--label-2); }
.lang-note .ic { flex: none; width: 16px; height: 16px; margin-top: 1px; color: var(--label-3); }

/* Getting the pronunciation ready before a round (components.js
   bindPractisePanel): progress, a changing line, the start buttons wait. */
.prep-card { padding: 14px 16px; margin-bottom: 12px; overflow: hidden; animation: prep-in .4s var(--spring) both; transition: opacity .35s, transform .35s var(--ease), max-height .45s var(--ease), margin .45s var(--ease), padding .45s var(--ease); max-height: 160px; }
@keyframes prep-in { from { opacity: 0; transform: translateY(-6px) scale(.98); } }
.prep-card.gone { opacity: 0; transform: scale(.98); max-height: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; }
.prep-row { display: flex; align-items: center; gap: 12px; }
.prep-ic { flex: none; width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; background: var(--tint-soft); color: var(--tint); }
.prep-card.running .prep-ic { animation: prep-pulse 1.4s ease-in-out infinite; }
@keyframes prep-pulse { 50% { transform: scale(1.08); background: color-mix(in srgb, var(--tint) 24%, transparent); } }
.prep-card.done .prep-ic { background: color-mix(in srgb, var(--green) 18%, transparent); color: var(--green); animation: pop-in .4s var(--spring); }
@keyframes pop-in { from { opacity: 0; scale: .6; } }
.prep-card.error .prep-ic { background: color-mix(in srgb, var(--orange) 18%, transparent); color: var(--orange); }
.prep-ic .ic { width: 20px; height: 20px; stroke-width: 2.2; }
.prep-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.prep-txt b { font-size: 16px; line-height: 21px; font-weight: 600; }
.prep-line { font-size: 14px; line-height: 19px; color: var(--label-2); animation: prep-line .35s var(--ease); }
@keyframes prep-line { from { opacity: 0; transform: translateY(4px); } }
.prep-count { flex: none; font-size: 15px; font-weight: 600; color: var(--label-2); font-variant-numeric: tabular-nums; }
.prep-bar { height: 6px; margin-top: 12px; border-radius: 99px; background: var(--fill-3); overflow: hidden; }
.prep-bar i { display: block; height: 100%; border-radius: 99px; background: var(--tint); transition: width .4s var(--ease); }
.prep-card.done .prep-bar i { background: var(--green); }
.wait { opacity: .45; }

.quiz-card { display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: center; padding: 18px; }
.quiz-ic {
  width: 54px; height: 54px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .22); color: #fff;
  box-shadow: inset 0 .5px 0 rgba(255, 255, 255, .5), 0 0 0 7px rgba(255, 255, 255, .08);
}
.quiz-ic .ic { width: 27px; height: 27px; stroke-width: 2; }
.quiz-txt h2 { font-size: 22px; line-height: 28px; font-weight: 700; margin: 0 0 2px; }
.quiz-txt p { margin: 0; font-size: 15px; line-height: 1.35; color: rgba(255, 255, 255, .85); }
.quiz-card .btn-hero { grid-column: 1 / -1; margin-top: 4px; }
/* locked (the spoken answers are used up): the microphone wears the round's gold lock */
.quiz-ic { position: relative; }
.quiz-card.locked .quiz-ic > .ic { opacity: .7; }
.quiz-ic .vx-lock { right: -5px; bottom: -5px; width: 25px; height: 25px; box-shadow: 0 0 0 2.5px #2A80FF, 0 0 12px rgba(245, 188, 58, .55); }
.quiz-ic .vx-lock .ic { width: 13px; height: 13px; stroke-width: 2.6; }

.modes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 12px 0; }
.mode {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  min-height: 86px; padding: 12px 6px; border-radius: 20px;
  background: var(--bg-2);
  font-size: 13px; font-weight: 600; text-align: center; line-height: 1.2;
  transition: background-color .2s, transform .25s var(--spring);
}
.mode .ic { width: 27px; height: 27px; color: var(--tint); stroke-width: 1.9; }
.mode:active { transform: scale(.96); background: var(--press); }

.dir-row { display: flex; flex-direction: column; gap: 8px; margin: 22px 0 6px; }
.dir-label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; text-transform: uppercase; color: var(--label-2); padding: 0 16px; }
.dir-label .ic { width: 15px; height: 15px; stroke-width: 2.2; }
.dir-row .seg { display: flex; }
.dir-row .seg button { flex: 1; }

/* Segmented control, capsule-shaped as in iOS 26 */
.seg { display: inline-flex; padding: 2px; gap: 0; border-radius: 999px; background: var(--fill-3); }
.seg button {
  min-height: 32px; padding: 0 12px; border-radius: 999px;
  font-size: 13px; font-weight: 500; color: var(--label); white-space: nowrap;
  transition: background-color .25s, box-shadow .25s;
}
.seg button.on { background: var(--seg-on); font-weight: 600; box-shadow: 0 3px 8px rgba(0, 0, 0, .12), 0 3px 1px rgba(0, 0, 0, .04); }
.seg-sm button { min-height: 30px; padding: 0 11px; font-size: 13px; }
.seg-block { display: flex; width: 100%; }
/* A settings row whose options sit on a line of their own (ProfileView segRow stack). */
.row.row-stack { flex-direction: column; align-items: stretch; gap: 9px; }
.seg-block button { flex: 1; min-height: 34px; font-size: 15px; }
.due-only {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 10px 0 0; min-height: 36px; padding: 0 14px;
  border-radius: 999px; background: var(--tint-soft); color: var(--tint);
  font-weight: 600; font-size: 15px;
}
.due-only .ic { width: 16px; height: 16px; stroke-width: 2.3; }
.due-only:active { opacity: .6; }

/* Word lists: grouped rows, the word above its meaning */
.card.words { background: none; border-radius: 0; padding: 0; margin-top: 28px; }
.words .section-head, .res-missed .section-head { padding: 0 4px; }
.word-list { list-style: none; margin: 0; padding: 0; background: var(--bg-2); border-radius: var(--r-card); overflow: hidden; }
.word-list li { position: relative; }
.word-list li + li::before { content: ''; position: absolute; top: 0; left: 16px; right: 0; border-top: .5px solid var(--sep); z-index: 1; }
.word-list.tappable li + li::before { left: 40px; }
.word-row {
  display: grid; grid-template-columns: 10px minmax(0, 1fr); grid-template-areas: "dot q" "dot a";
  column-gap: 14px; row-gap: 1px; align-items: center;
  width: 100%; text-align: left; padding: 10px 16px 11px;
}
.word-row .dot { grid-area: dot; }
.res-missed .word-row, .compact .word-row { grid-template-columns: minmax(0, 1fr); grid-template-areas: "q" "a"; }
.word-list.tappable .word-row { transition: background-color .25s; }
.word-list.tappable .word-row:active { background: var(--press); transition: none; }
@media (hover: hover) { .word-list.tappable .word-row:hover { background: var(--fill-4); } }
.w-q { grid-area: q; font-size: 17px; line-height: 22px; overflow-wrap: anywhere; }
.w-a { grid-area: a; font-size: 15px; line-height: 20px; color: var(--label-2); overflow-wrap: anywhere; }
.compact .word-row { padding: 8px 16px 9px; }
/* The speaker beside a word on the set page: reads it (pulses while it does). */
.word-list li.has-say .word-row { padding-right: 60px; }
.w-say {
  position: absolute; top: 50%; right: 10px; transform: translateY(-50%); z-index: 2;
  width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  color: var(--tint); transition: transform .25s var(--spring), background-color .2s;
}
.w-say .ic { width: 20px; height: 20px; stroke-width: 2; }
.w-say:active { transform: translateY(-50%) scale(.88); background: var(--tint-soft); }
.w-say.busy { animation: w-say-pulse 1s ease-in-out infinite; }
@keyframes w-say-pulse { 50% { background: var(--tint-soft); } }
.empty-set { text-align: center; }
.empty-set .mascot { margin: 0 auto; }
.empty-set p { color: var(--label-2); margin: 4px 0 16px; }

/* ─── Forms ───────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 7px; margin-bottom: 20px; }
.field-label { font-size: 13px; line-height: 18px; text-transform: uppercase; color: var(--label-2); padding: 0 16px; }
.input {
  width: 100%;
  background: var(--bg-2); color: var(--label);
  border: 0; border-radius: 12px;
  padding: 12px 16px; font-size: 17px; line-height: 22px;
  outline: none; caret-color: var(--tint);
  transition: box-shadow .15s;
}
.input::placeholder { color: var(--label-3); }
.input:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--tint) 55%, transparent); }
.input-lg { padding: 14px 16px; border-radius: 14px; }
textarea.input { resize: vertical; min-height: 200px; border-radius: 16px; font-family: var(--font-mono); font-size: 15px; line-height: 1.5; }
.shake { animation: shake .36s; }
@keyframes shake { 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }

/* UISwitch */
.switch { position: relative; flex: none; width: 51px; height: 31px; }
.switch input { position: absolute; inset: 0; z-index: 1; opacity: 0; margin: 0; cursor: pointer; }
.switch i { position: absolute; inset: 0; border-radius: 99px; background: var(--fill); transition: background-color .25s; pointer-events: none; }
.switch i::after {
  content: ''; position: absolute; left: 2px; top: 2px; width: 27px; height: 27px; border-radius: 99px;
  background: #fff; box-shadow: 0 3px 8px rgba(0, 0, 0, .15), 0 3px 1px rgba(0, 0, 0, .06);
  transition: transform .3s var(--spring), width .2s var(--ease);
}
.switch input:checked + i { background: var(--green); }
.switch input:checked + i::after { transform: translateX(20px); }
.switch input:active + i::after { width: 33px; }
.switch input:checked:active + i::after { transform: translateX(14px); }
.switch input:focus-visible + i { outline: 3px solid color-mix(in srgb, var(--tint) 55%, transparent); outline-offset: 2px; }

.alert { margin-top: 12px; padding: 12px 14px; border-radius: 14px; background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red-text); font-size: 15px; line-height: 1.35; font-weight: 500; }
.alert.info { background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green-text); }
.alert.soft { background: var(--fill-3); color: var(--label-2); font-weight: 400; }
.notice { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: 16px; background: var(--tint-soft); color: var(--label); font-size: 15px; line-height: 1.35; margin-bottom: 20px; }
.notice .ic { color: var(--tint); margin-top: 0; stroke-width: 2.2; }

/* ─── Editor ──────────────────────────────────────────────────────────────── */
/* As in the book (the owner's pick C of tools/drafts/words-check-design.html,
   2026-09-29): Voki, the set's head, the words in two columns by page, one
   save button at the bottom. */
.ed-say { display: flex; align-items: center; gap: 10px; margin: 4px 2px 14px; }
.ed-voki { width: 58px; height: 58px; flex: none; }
.ed-voki .mascot { width: 100%; height: 100%; }
.ed-bubble { position: relative; padding: 10px 14px; border-radius: 18px; background: var(--bg-2); font-size: 15px; line-height: 1.35; box-shadow: 0 6px 16px -10px rgba(0, 0, 0, .35); }
.ed-bubble::before { content: ''; position: absolute; left: -6px; top: 50%; width: 14px; height: 14px; margin-top: -7px; background: inherit; transform: rotate(45deg); border-radius: 3px; }
.ed-bubble b { color: var(--red-text); font-weight: 700; }
/* the set: its face, the name as the title, the language pair and the group */
.ed-head { display: grid; grid-template-columns: 52px minmax(0, 1fr); align-items: center; gap: 12px; padding: 14px; border-radius: 20px; background: var(--bg-2); margin-bottom: 22px; }
.ed-head .set-ic { grid-area: auto; width: 52px; height: 52px; }
.ed-head .set-ic .m-glyph { width: 40px; height: 40px; }
.ed-head .set-ic .ic { width: 26px; height: 26px; }
.ed-head-main { min-width: 0; }
.ed-name { display: flex; align-items: center; gap: 6px; min-width: 0; cursor: text; }
.ed-name input { flex: 1; min-width: 0; border: 0; padding: 0; background: none; font: 800 21px/1.25 var(--font-rounded); color: var(--label); outline: none; caret-color: var(--tint); text-overflow: ellipsis; }
.ed-name input::placeholder { color: var(--label-3); }
.ed-name.has-default input::placeholder { color: var(--label); }   /* what the set will be called */
.ed-name .ic { flex: none; width: 17px; height: 17px; color: var(--label-3); stroke-width: 2.2; }
.ed-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ed-chip { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; height: 28px; padding: 0 11px; border-radius: 99px; background: var(--fill-3); font-size: 13px; font-weight: 600; color: var(--label-2); }
.ed-chip[hidden] { display: none; }
.ed-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ed-chip .ic { flex: none; width: 14px; height: 14px; stroke-width: 2.3; }
.ed-group { color: var(--tint); background: var(--tint-soft); }
.ed-group.on { color: #fff; background: var(--tint); }
/* over the words: how many, swap the sides */
.ed-listhead { display: flex; align-items: center; justify-content: space-between; margin: 0 4px 6px; }
.ed-count { font: 800 17px var(--font-rounded); }
.ed-listhead .link-btn { font-size: 14px; }
/* a section: a scanned page (its picture; "View page" shows it big) */
.ed-sec { display: flex; align-items: center; gap: 10px; margin: 18px 4px 8px; }
.ed-lists > .ed-sec:first-child { margin-top: 8px; }
.ed-thumb { width: 30px; height: 40px; flex: none; border-radius: 6px; overflow: hidden; background: #fff; box-shadow: 0 3px 8px -3px rgba(0, 0, 0, .45), 0 0 0 .5px rgba(0, 0, 0, .12); }
.ed-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ed-sec-label { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: .02em; color: var(--label-2); }
.ed-sec .link-btn { font-size: 13.5px; }
.ed-sec .link-btn .ic { width: 15px; height: 15px; }
.ed-cols { display: grid; grid-template-columns: 1fr 1fr; margin: 6px 0 6px; }
.ed-cols span { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--label-3); padding: 0 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ed-cols span + span { padding-left: 14px; }
/* the words: two columns in one rounded list, a hairline between the rows */
.ed-list { list-style: none; margin: 0; padding: 0; border-radius: 16px; overflow: hidden; background: var(--bg-2); }
.ed-row { position: relative; overflow: hidden; touch-action: pan-y; animation: row-in .25s var(--ease) both; }
.ed-lists.settled .ed-row:not(.added):not(.going) { animation: none; }   /* drawn anew after a delete / swap: no flicker */
@keyframes row-in { from { opacity: 0; transform: translateY(-4px); } }
.ed-row + .ed-row::before { content: ''; position: absolute; z-index: 2; top: 0; left: 12px; right: 0; border-top: .5px solid var(--sep); }
.ed-pair { position: relative; z-index: 1; display: grid; grid-template-columns: 1fr 1fr; background: var(--bg-2);
  transform: translateX(var(--sx, 0)); transition: transform .3s var(--ease), background-color .2s; }
.ed-pair::after { content: ''; position: absolute; left: 50%; top: 9px; bottom: 9px; border-left: .5px solid var(--sep); pointer-events: none; }
.ed-row.dragging .ed-pair { transition: none; }
.ed-in {
  display: block; width: 100%; min-width: 0; resize: none; overflow: hidden;
  border: 0; outline: none; background: transparent; color: var(--label);
  padding: 11px 12px; font: inherit; font-size: 16px; line-height: 21px;
  overflow-wrap: anywhere; caret-color: var(--tint);
}
.ed-a { padding-left: 14px; }
.ed-in::placeholder { color: var(--label-3); }
.ed-q { font-weight: 600; }
.ed-row:focus-within .ed-pair { background: color-mix(in srgb, var(--tint) 7%, var(--bg-2)); }
.ed-row.warn .ed-pair { background: color-mix(in srgb, var(--red) 7%, var(--bg-2)); }
.ed-row.warn .ed-in:placeholder-shown::placeholder { color: var(--red-text); font-weight: 600; }
.ed-gone { position: absolute; top: 0; right: 0; bottom: 0; width: 84px; display: grid; place-items: center; background: var(--red); color: #fff; font-size: 14px; font-weight: 600; }
.ed-row:not(.open):not(.dragging) .ed-gone { visibility: hidden; }
.ed-row.going { animation: row-out .2s ease-in both; }
@keyframes row-out { to { opacity: 0; transform: translateX(-30%); } }
.ed-add { display: flex; align-items: center; justify-content: center; gap: 7px; width: 100%; min-height: 48px; margin-top: 14px; border-radius: 16px;
  border: 2px dashed color-mix(in srgb, var(--tint) 40%, transparent); color: var(--tint); font-weight: 600; font-size: 15px; }
.ed-add .ic { width: 18px; height: 18px; stroke-width: 2.3; }
.ed-add:active { background: var(--tint-soft); }
.ed-tip { font-size: 13px; line-height: 1.4; color: var(--label-2); margin: 12px 8px 0; text-align: center; }
.ed-foot {
  position: sticky; bottom: 0; z-index: 3;
  margin: 8px -16px 0; padding: 22px 16px calc(var(--safe-b) + 12px);
  background: linear-gradient(to top, var(--bg) 72%, transparent);
}
.ed-note { margin: 10px 4px 0; text-align: center; font-size: 13px; color: var(--label-2); }
.ed-note.bad { color: var(--red-text); font-weight: 600; }
/* "View page" (ui.js photoViewer): the page big over the words */
.layer-photo { padding: calc(var(--safe-t) + 12px) 16px calc(var(--safe-b) + 16px); }
.layer.layer-photo.open { background: rgba(0, 0, 0, .82); }
.layer-photo .layer-panel { width: 100%; height: 100%; max-height: none; display: flex; flex-direction: column; gap: 12px; padding: 0; border-radius: 0; background: none; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none; overflow: visible; }
.photo-head { display: flex; align-items: center; justify-content: space-between; color: #fff; font-size: 17px; font-weight: 600; }
.photo-sheet { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.photo-sheet img { display: block; max-width: 100%; max-height: 100%; border-radius: 14px; background: #fff; box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .7); }

.paste-area { margin-bottom: 14px; }
.paste-preview { margin-bottom: 18px; }
.paste-preview .muted.small { padding: 8px 16px 0; }

/* ─── Scan ────────────────────────────────────────────────────────────────── */
.scan-hero { text-align: center; }
.scan-hero .h2 { margin-top: 4px; }
.scan-hero .lead { max-width: 36ch; margin: 8px auto 24px; font-size: 17px; line-height: 1.35; }
.scan-hero .lead:has(+ .scan-left) { margin-bottom: 10px; }
.scan-left { display: table; margin: 0 auto 20px; padding: 5px 12px; border-radius: 99px; background: var(--fill-3); color: var(--label-2); font-size: 13px; font-weight: 600; }
/* none left this month: the line in gold, the photo buttons with a lock (ScanView: a tap opens the gold sheet) */
.scan-left.none { background: color-mix(in srgb, #F5BC3A 24%, transparent); color: var(--label); }
.scan-hero .btn.is-locked { background: var(--fill-2); color: var(--label-2); box-shadow: none; }
.scan-hero .btn.is-locked .ic { color: #E0A100; }
/* The scene (scanScene.js; the owner, 2026-09-29): Voki photographs a
   textbook page, the beam reads it, cards fly out — phases on data-phase:
   in → aim → shot → scan → cards → out, again; still = no motion. The page
   and the cards are paper: white in both themes. */
.scan-scene { position: relative; width: 300px; max-width: 100%; height: 200px; margin: 0 auto 16px; }
.scs-page {
  position: absolute; right: 14px; top: 8px; width: 150px; height: 180px; overflow: hidden;
  padding: 12px 11px; border-radius: 10px; transform: rotate(3deg);
  background: linear-gradient(160deg, #FFF 0%, #F1F5FC 100%); color: #1C1C1E; text-align: left;
  box-shadow: inset 0 1px 0 #FFF, inset 0 -3px 5px rgba(20, 50, 120, .08), 0 12px 30px rgba(0, 0, 0, .16), 0 1px 3px rgba(0, 0, 0, .1);
}
.scs-h { display: block; margin-bottom: 7px; font: 800 9.5px / 1.2 var(--font-rounded); color: #0A84FF; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scs-row { display: flex; justify-content: space-between; gap: 6px; margin: 0 -5px 3px; padding: 4px 5px; border-radius: 6px; font-size: 10px; line-height: 1.25; }
.scs-row span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scs-row span:first-child { font-weight: 700; }
.scs-row span:last-child { color: #6B6B70; text-align: right; }
.scs-beam { position: absolute; left: 6px; right: 6px; top: 8px; height: 3px; border-radius: 3px; opacity: 0; background: #0A84FF; box-shadow: 0 0 16px 4px rgba(10, 132, 255, .5); }
.scs-flash { position: absolute; inset: 0; background: #FFF; opacity: 0; }
.scs-frame { position: absolute; right: 4px; top: -2px; width: 170px; height: 204px; opacity: 0; transform: scale(1.16); transition: opacity .35s, transform .55s var(--spring); }
.scs-frame i { position: absolute; width: 26px; height: 26px; border: 3.5px solid var(--tint); }
.scs-frame .tl { left: 0; top: 0; border-right: 0; border-bottom: 0; border-radius: 12px 0 0 0; }
.scs-frame .tr { right: 0; top: 0; border-left: 0; border-bottom: 0; border-radius: 0 12px 0 0; }
.scs-frame .bl { left: 0; bottom: 0; border-right: 0; border-top: 0; border-radius: 0 0 0 12px; }
.scs-frame .br { right: 0; bottom: 0; border-left: 0; border-top: 0; border-radius: 0 0 12px 0; }
.scan-scene .scs-voki { position: absolute; left: 2px; bottom: 2px; width: 104px; height: 104px; z-index: 2; }   /* over .m-host's own position */
.scs-voki .mascot { width: 100%; height: 100%; }
.scs-cam { position: absolute; left: 90px; top: 124px; width: 42px; height: 30px; z-index: 3; opacity: 0; transform: translateY(14px) scale(.5) rotate(-10deg); transform-origin: 20% 70%; transition: opacity .25s, transform .45s var(--spring); }
.scs-cam svg { display: block; width: 100%; height: 100%; overflow: visible; }
.scs-cam::after { content: ''; position: absolute; right: -14px; top: 50%; width: 34px; height: 34px; margin-top: -17px; border-radius: 50%; opacity: 0; background: radial-gradient(circle, #FFF 0%, rgba(255, 255, 255, .75) 35%, transparent 70%); }
.scs-cards { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.scs-card {
  --dx: calc(34px + var(--i) * 18px); --dy: calc(96px - var(--i) * 22px); --r: calc(-12deg + var(--i) * 12deg);
  position: absolute; left: 150px; top: calc(38px + var(--i) * 25px); width: 82px; height: 42px; padding: 0 6px;
  display: grid; place-items: center; border-radius: 9px; border-left: 4px solid #0A84FF;
  background: #FFF; color: #1C1C1E; font: 800 11px / 1.15 var(--font-rounded); text-align: center;
  box-shadow: 0 8px 18px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .1); opacity: 0;
}
/* aim: the camera comes up, Voki looks at the page, the viewfinder closes in */
.scan-scene:is([data-phase="aim"], [data-phase="shot"], [data-phase="still"]) .scs-voki .mascot .m-arm-r { transform: rotate(-58deg); }
.scan-scene:is([data-phase="aim"], [data-phase="shot"], [data-phase="still"]) .scs-voki .mascot .m-gaze { transform: translateX(4px); }
.scan-scene:is([data-phase="aim"], [data-phase="shot"], [data-phase="scan"], [data-phase="cards"], [data-phase="still"]) .scs-frame { opacity: 1; transform: none; }
.scan-scene:is([data-phase="aim"], [data-phase="shot"], [data-phase="still"]) .scs-cam { opacity: 1; transform: none; }
.scan-scene[data-phase="aim"] .scs-cam { animation: scs-aim 1.1s ease-in-out .4s both; }
@keyframes scs-aim { 0%, 100% { transform: none; } 30% { transform: translate(1px, -2px) rotate(-3deg); } 65% { transform: translate(-1px, 1px) rotate(2deg); } }
/* shot: a flash on the page and at the lens, the camera kicks */
.scan-scene[data-phase="shot"] .scs-cam { animation: scs-kick .45s var(--spring) both; }
@keyframes scs-kick { 0% { transform: none; } 25% { transform: translateX(-3px) rotate(-7deg) scale(.94); } 100% { transform: none; } }
.scan-scene[data-phase="shot"] .scs-cam::after { animation: scs-glint .4s ease-out both; }
@keyframes scs-glint { 0% { opacity: 0; transform: scale(.4); } 20% { opacity: 1; transform: scale(1.1); } 100% { opacity: 0; transform: scale(1.4); } }
.scan-scene[data-phase="shot"] .scs-flash { animation: scs-flash .55s ease-out both; }
@keyframes scs-flash { 0% { opacity: 0; } 12% { opacity: .92; } 100% { opacity: 0; } }
/* scan: the beam runs down the page, each line lights up as it passes */
.scan-scene[data-phase="scan"] .scs-beam { animation: scs-beam 2.3s ease-in-out .15s both; }
@keyframes scs-beam { 0% { opacity: 0; top: 8px; } 8% { opacity: 1; } 90% { opacity: 1; } 100% { opacity: 0; top: calc(100% - 12px); } }
.scan-scene:is([data-phase="scan"], [data-phase="cards"]) .scs-row { animation: scs-row .45s ease-out both; animation-delay: calc(.5s + var(--i) * .36s); }
@keyframes scs-row { from { background: rgba(10, 132, 255, 0); } to { background: rgba(10, 132, 255, .14); } }
.scan-scene:is([data-phase="scan"], [data-phase="cards"]) .scs-row span:last-child { animation: scs-meaning .45s ease-out both; animation-delay: calc(.5s + var(--i) * .36s); }
@keyframes scs-meaning { from { color: #6B6B70; } to { color: #0A6CFF; } }
.scan-scene[data-phase="still"] .scs-row { background: rgba(10, 132, 255, .14); }
.scan-scene[data-phase="still"] .scs-row span:last-child { color: #0A6CFF; }
/* cards: three cards fly out of the page into a little fan */
.scan-scene[data-phase="cards"] .scs-card { animation: scs-card .7s var(--spring) both; animation-delay: calc(var(--i) * .2s); }
@keyframes scs-card {
  0% { opacity: 0; transform: scale(.5); }
  35% { opacity: 1; transform: translate(calc(var(--dx) * .4), calc(var(--dy) * .3 - 20px)) rotate(calc(var(--r) * .5)) scale(1.06); }
  100% { opacity: 1; transform: translate(var(--dx), var(--dy)) rotate(var(--r)); }
}
/* out: all of it settles back — the lines, the cards, the viewfinder */
.scan-scene[data-phase="out"] .scs-row { animation: scs-row-off .6s ease-out both; }
@keyframes scs-row-off { from { background: rgba(10, 132, 255, .14); } to { background: rgba(10, 132, 255, 0); } }
.scan-scene[data-phase="out"] .scs-row span:last-child { animation: scs-meaning-off .6s ease-out both; }
@keyframes scs-meaning-off { from { color: #0A6CFF; } to { color: #6B6B70; } }
.scan-scene[data-phase="out"] .scs-card { animation: scs-card-off .6s ease-in both; }
@keyframes scs-card-off {
  from { opacity: 1; transform: translate(var(--dx), var(--dy)) rotate(var(--r)); }
  to { opacity: 0; transform: translate(var(--dx), calc(var(--dy) + 12px)) rotate(var(--r)) scale(.9); }
}
.tips { list-style: none; padding: 0; margin: 24px 0 0; text-align: left; background: var(--bg-2); border-radius: var(--r-card); overflow: hidden; }
.tips li { position: relative; display: flex; align-items: center; gap: 14px; min-height: 52px; padding: 10px 16px; font-size: 15px; line-height: 1.35; }
.tips li + li::before { content: ''; position: absolute; top: 0; left: 60px; right: 0; border-top: .5px solid var(--sep); }
.tips .ic { width: 30px; height: 30px; padding: 6px; border-radius: 8px; color: #fff; background: var(--orange); stroke-width: 2.3; }
.tips li:nth-child(2) .ic { background: var(--red); }
.tips li:nth-child(3) .ic { background: var(--blue); }

/* The pages taken (ScanView photosHTML; the owner's pick of
   tools/drafts/scan-review-design.html, 2026-09-29): Voki says what is going on, each
   page a white card as it is sent (number, remove, state, "Adjust corners"),
   a dashed card to add one, the button at the bottom fills while reading. */
.scan-photos { display: flex; flex-direction: column; min-height: calc(var(--view-fill) - var(--safe-t) - 80px); }   /* the button at the bottom of the screen */
.scan-say { display: flex; align-items: center; gap: 10px; margin: 6px 2px 16px; }
.scan-voki { width: 58px; height: 58px; flex: none; }
.scan-voki .mascot { width: 100%; height: 100%; }
.scan-bubble { position: relative; padding: 10px 14px; border-radius: 18px; background: var(--bg-2); font-size: 15px; line-height: 1.35; box-shadow: 0 6px 16px -10px rgba(0, 0, 0, .35); }
.scan-bubble::before { content: ''; position: absolute; left: -6px; top: 50%; width: 14px; height: 14px; margin-top: -7px; background: inherit; transform: rotate(45deg); border-radius: 3px; }
.scan-bubble.bad { background: color-mix(in srgb, var(--red) 12%, var(--bg-2)); }
.scan-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }   /* two equal columns: a button's width must not widen one */
.scan-page { position: relative; margin: 0; }
.scan-sheet { position: relative; aspect-ratio: 3 / 4; border-radius: 16px; overflow: hidden; background: #fff; box-shadow: 0 14px 28px -16px rgba(0, 0, 0, .55), 0 1px 3px rgba(0, 0, 0, .1); transition: box-shadow .3s, opacity .3s; }
.scan-sheet img { display: block; width: 100%; height: 100%; object-fit: contain; }
.scan-num { position: absolute; left: 8px; top: 8px; min-width: 26px; height: 26px; padding: 0 8px; border-radius: 99px; display: grid; place-items: center;
  background: var(--glass-thick); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); box-shadow: var(--glass-rim), var(--glass-lift-s); font: 800 13px var(--font-rounded); color: var(--label); }
.scan-rm { position: absolute; right: 8px; top: 8px; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  background: var(--glass-thick); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); box-shadow: var(--glass-rim), var(--glass-lift-s); color: var(--label); }
.scan-rm .ic { width: 14px; height: 14px; stroke-width: 2.8; }
.scan-edit { display: flex; align-items: center; justify-content: center; gap: 5px; width: 100%; min-height: 36px; margin-top: 4px; color: var(--tint); font-size: 14px; font-weight: 600; cursor: pointer; }
.scan-edit .ic { width: 15px; height: 15px; stroke-width: 2.2; }
.scan-edit.bad { color: var(--red-text); }
.scan-add { aspect-ratio: 3 / 4; border-radius: 16px; border: 2px dashed color-mix(in srgb, var(--tint) 45%, transparent); background: color-mix(in srgb, var(--tint) 5%, transparent);
  display: flex; flex-direction: column; align-items: stretch; justify-content: center; gap: 10px; padding: 12px 10px; min-width: 0; }
.scan-add b { text-align: center; font: 800 15px var(--font-rounded); color: var(--tint); margin-bottom: 2px; }
.scan-add .btn { min-height: 40px; min-width: 0; font-size: 14px; padding: 0 8px; gap: 6px; }
.scan-add .btn span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.scan-add .btn .ic { width: 17px; height: 17px; }
/* reading: a beam over the page being read, the others wait; then a state pill */
.scan-beam { position: absolute; left: 0; right: 0; top: 0; height: 3px; background: var(--tint); box-shadow: 0 0 16px 4px color-mix(in srgb, var(--tint) 60%, transparent); opacity: 0; }
.scan-page.reading .scan-beam { opacity: 1; animation: scan-beam 1.6s ease-in-out infinite; }
@keyframes scan-beam { 0%, 100% { top: 4%; } 50% { top: 94%; } }
.scan-page.reading .scan-sheet::after { content: ''; position: absolute; inset: 0; background: color-mix(in srgb, var(--tint) 10%, transparent); }
.scan-page.waiting .scan-sheet { opacity: .5; }
.scan-state { position: absolute; left: 8px; right: 8px; bottom: 8px; display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 30px; border-radius: 99px;
  background: var(--glass-thick); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); box-shadow: var(--glass-rim), var(--glass-lift-s); font-size: 13px; font-weight: 700;
  animation: scan-pop .35s var(--spring) both; }
@keyframes scan-pop { from { opacity: 0; transform: translateY(6px) scale(.9); } }
.scan-state .ic { width: 15px; height: 15px; stroke-width: 2.6; }
.scan-state.ok { color: var(--green-text); }
.scan-state.bad { color: var(--red-text); }
.scan-state.now { color: var(--tint); }
.scan-page.done .scan-sheet { box-shadow: 0 0 0 3px var(--green), 0 14px 28px -16px rgba(0, 0, 0, .55); }
.scan-page.failed .scan-sheet { box-shadow: 0 0 0 3px var(--red), 0 14px 28px -16px rgba(0, 0, 0, .55); }
/* the button stays at the bottom of the screen; it reaches into the view's
   bottom padding so it sits flush whether stuck or at the end of the page */
.scan-foot { position: sticky; bottom: 0; z-index: 2; margin: auto -16px calc(-1 * var(--view-pb)); padding: 18px 16px var(--view-pb); background: linear-gradient(to top, var(--bg) 72%, transparent); }
.scan-go { position: relative; overflow: hidden; }
.scan-go .scan-fill { position: absolute; inset: 0; right: auto; width: 0; background: rgba(255, 255, 255, .28); transition: width 7s cubic-bezier(.15, .6, .3, 1); }
.scan-go.is-busy { pointer-events: none; }
.scan-go > :not(.scan-fill) { position: relative; }
.scan-note { margin: 10px 4px 0; text-align: center; font-size: 13px; color: var(--label-2); }

/* ─── Result ────────────────────────────────────────────────────────────────
   After a round: first the celebration, then the page (ResultView; the
   owner's pick A of tools/drafts/result-design.html, 2026-09-30). Three states
   (data-st): "stage" — only Voki, where he stood on the round's stage —,
   "party" — he has grown and stands in the middle, rays turn behind him, the
   headline and three numbers come —, "page" — everything has moved up and
   the rest of the page comes in. Every piece appears by a transition from a
   hidden state (.in), never by a keyframe animation: a skipped celebration
   (res-still: no transitions for a frame) simply stands there. */
.result {
  position: relative; min-height: var(--view-fill); display: flex; flex-direction: column; padding-bottom: 0;
  /* where Voki and the headline stand on the page … */
  --vy-page: calc(var(--safe-t) + 52px); --h0: calc(var(--safe-t) + 152px);
  /* … and in the celebration: a little above the screen's middle; --gap: from Voki's top to the headline */
  --vy-party: max(calc(var(--safe-t) + 84px), calc(50vh - 228px)); --gap: 190px;
  --hy-party: calc(var(--vy-party) + var(--gap) - var(--h0));
}
.result[data-st="stage"] { --vx: var(--vx0, 0px); --vy: var(--vy0, var(--vy-party)); --vs: var(--vs0, .6); --hy: var(--hy-party); }
.result[data-st="party"] { --vy: var(--vy-party); --vs: 1.14; --hy: var(--hy-party); --ro: 1; --rs: 1; --ry: calc(var(--vy-party) + 86px); }
.result[data-st="party"][data-party="0"] { --ro: .45; }   /* a weak round: the light stays low */
.result[data-st="page"] { --vy: var(--vy-page); --vs: .62; --hy: 0px; --ro: 0; --rs: .5; --ry: calc(var(--vy-page) + 46px); }
html[data-mascot="off"] .result { --h0: calc(var(--safe-t) + 84px); --gap: 50px; }
.res-still, .res-still *, .res-still *::before, .res-still *::after { transition: none !important; animation: none !important; }
/* the celebration starts on the round's last frame: this page does not fade in over it */
.view.enter > .result.live { animation: res-hold .02s both; }
@keyframes res-hold { from { opacity: 1; } }
/* … and the stage's glow does not snap off under Voki: it is here for the first frame, then fades */
.result.live::before {
  content: ''; position: fixed; z-index: 0; top: 0; bottom: 0; left: var(--app-x); right: var(--app-x); pointer-events: none;
  background: radial-gradient(120% 52% at 50% 112%, var(--s-glow-a), transparent 62%), radial-gradient(90% 40% at 50% -8%, var(--s-glow-b), transparent 70%);
  opacity: 0; transition: opacity .7s ease;
}
.result.live[data-st="stage"]::before { opacity: 1; transition: none; }
.res-bump { animation: res-bump .38s var(--spring); }
@keyframes res-bump { 40% { transform: scale(1.24); } }
.result .topbar { opacity: 0; pointer-events: none; transition: opacity .45s .15s; }
.result[data-st="page"] .topbar { opacity: 1; pointer-events: auto; }

/* Voki — the one from the stage — and the rays behind him */
.res-voki {
  position: absolute; z-index: 3; left: 50%; top: 0; width: 150px; height: 150px; margin-left: -75px; pointer-events: none;
  transform-origin: 50% 0; transform: translate(var(--vx, 0px), var(--vy)) scale(var(--vs, 1)); transition: transform .8s var(--spring);
}
.res-voki > div { width: 100%; height: 100%; }
.res-rays {
  position: absolute; z-index: 0; left: 50%; top: 0; width: 640px; height: 640px; margin: -320px 0 0 -320px; pointer-events: none;
  transform: translateY(var(--ry, 200px)) scale(var(--rs, .3)); opacity: var(--ro, 0); transition: transform .9s var(--spring), opacity .6s;
}
.res-rays i {
  position: absolute; inset: 0; border-radius: 50%; animation: res-spin 34s linear infinite;
  background: repeating-conic-gradient(from 0deg, color-mix(in srgb, var(--tint) 15%, transparent) 0 8deg, transparent 8deg 20deg);
  -webkit-mask: radial-gradient(closest-side, #000 18%, transparent 80%); mask: radial-gradient(closest-side, #000 18%, transparent 80%);
}
.result[data-st="page"] .res-rays i { animation-play-state: paused; }
@keyframes res-spin { to { transform: rotate(360deg); } }

/* the headline, letter by letter, and the three numbers of the round */
.res-hero { position: relative; z-index: 2; margin-top: calc(var(--h0) - var(--safe-t) - 64px); text-align: center; transform: translateY(var(--hy, 0px)); transition: transform .8s var(--spring); }
.res-title { margin: 0; font-size: 31px; line-height: 1.12; font-weight: 800; letter-spacing: -.01em; }
.res-title.flawless { color: var(--green-text); }
.res-w { display: inline-block; white-space: nowrap; }
.res-title i { display: inline-block; font-style: normal; opacity: 0; transform: translateY(18px) scale(.5) rotate(-10deg); transition: opacity .22s, transform .5s var(--spring); transition-delay: calc(var(--i) * 28ms); }
.res-title.in i { opacity: 1; transform: none; }
.res-sub { margin: 5px 0 0; color: var(--label-2); font-size: 15.5px; opacity: 0; transform: translateY(10px); transition: opacity .4s, transform .5s var(--spring); }
.res-sub.in { opacity: 1; transform: none; }
.result [data-c="green"] { --c: var(--green); --ct: var(--green-text); }
.result [data-c="yellow"] { --c: #F5B800; --ct: var(--s-yellow-text); }
.result [data-c="orange"] { --c: var(--orange); --ct: var(--orange-text); }
.result [data-c="blue"] { --c: var(--blue); --ct: var(--tint); }
.result [data-c="purple"] { --c: var(--purple); --ct: var(--purple); }
.res-badge { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; flex: none; }
.res-badge .ic { width: 18px; height: 18px; stroke-width: 2.3; }
.res-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 34px; }
.res-tile {
  position: relative; padding: 23px 4px 11px; border-radius: 20px; background: var(--bg-2); box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 12px 26px -16px rgba(0, 0, 0, .3);
  opacity: 0; transform: translateY(26px) scale(.6); transition: opacity .22s, transform .55s var(--spring);
}
.res-tile.in { opacity: 1; transform: none; }
.res-tile .res-badge { position: absolute; left: 50%; top: -17px; margin-left: -17px; }
.res-tile b { display: block; font: 800 26px / 1.1 var(--font-rounded); font-variant-numeric: tabular-nums; color: var(--ct); }
.res-tile small { display: block; margin-top: 2px; font-size: 12.5px; font-weight: 600; color: var(--label-2); }

/* the rest of the page comes in from below */
.res-sec { opacity: 0; transform: translateY(36px); pointer-events: none; transition: opacity .45s, transform .65s var(--spring); }
.res-sec.in { opacity: 1; transform: none; pointer-events: auto; }
/* the day: the streak with this week, the daily goal */
.res-day { display: grid; grid-template-columns: 1.22fr 1fr; gap: 10px; margin-top: 14px; }
.res-dt { min-width: 0; padding: 12px; border-radius: 20px; background: var(--bg-2); }
.res-dt-h { display: flex; align-items: center; gap: 7px; font-size: 12.5px; line-height: 1.2; font-weight: 600; color: var(--label-2); white-space: nowrap; }
.res-dt-h b { font: 800 25px / 1 var(--font-rounded); color: var(--label); font-variant-numeric: tabular-nums; }
.res-dt-h span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.res-dt .res-badge { width: 30px; height: 30px; }
.res-dt .res-badge .ic { width: 16px; height: 16px; }
.res-week { display: flex; justify-content: space-between; margin-top: 10px; }
.res-week i { width: 19px; height: 19px; border-radius: 50%; display: grid; place-items: center; font: 700 9.5px var(--font); color: var(--label-3); box-shadow: inset 0 0 0 1.5px var(--fill); transition: background-color .3s, color .3s, box-shadow .3s; }
.res-week i.on { background: var(--orange); color: #fff; box-shadow: none; }
.res-week i.today:not(.on) { box-shadow: inset 0 0 0 2px var(--orange); color: var(--orange-text); }
.res-goal { display: flex; align-items: center; gap: 10px; }
.res-goal b { display: block; font: 800 21px / 1.1 var(--font-rounded); font-variant-numeric: tabular-nums; }
.res-goal em, .res-set-n em { font-style: normal; }
.res-goal small { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.2; font-weight: 600; color: var(--label-2); }
.res-ring { position: relative; width: 46px; height: 46px; flex: none; --rc: var(--tint); }
.res-ring > svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.res-ring circle { fill: none; stroke-width: 5; stroke-linecap: round; }
.res-ring .t { stroke: color-mix(in srgb, var(--rc) 20%, transparent); }
.res-ring .f { stroke: var(--rc); stroke-dasharray: 100; stroke-dashoffset: calc(100 - var(--p, 0)); transition: stroke-dashoffset 1s var(--ease), stroke .3s; }
.res-ring.done { --rc: var(--green); }
.res-ring .ck { position: absolute; inset: 0; display: grid; place-items: center; color: var(--green); transform: scale(0); transition: transform .5s var(--spring); }
.res-ring .ck .ic { width: 20px; height: 20px; stroke-width: 3.2; }
.res-ring.done .ck { transform: none; }
.res-limit .lm-card { margin: 14px 0 0; }
/* the words to practise; "no mistakes" with the sets' progress */
.card.res-missed { background: none; padding: 0; border-radius: 0; margin: 22px 0 0; }
.res-missed .word-row { opacity: 0; transform: translateX(-14px); transition: opacity .35s, transform .5s var(--spring); transition-delay: calc(var(--i) * 70ms + 120ms); }
.res-missed.in .word-row { opacity: 1; transform: none; }
.res-missed .link-btn { margin: 8px 12px 0; }
.res-clean { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding: 14px; border-radius: 20px; background: var(--bg-2); }
.res-clean b { display: block; font: 800 17px var(--font-rounded); }
.res-clean div span { display: block; font-size: 14px; line-height: 1.3; color: var(--label-2); }
.res-set { position: relative; margin-top: 14px; padding: 14px 14px 13px; border-radius: 20px; background: var(--bg-2); }
.res-set-h { padding-right: 58px; font-size: 12.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--label-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res-set-n { display: block; margin: 3px 0 10px; font: 800 19px / 1.2 var(--font-rounded); font-variant-numeric: tabular-nums; }
.res-plus {
  position: absolute; right: 12px; top: 12px; padding: 3px 10px; border-radius: 99px; font: 800 14px var(--font-rounded); font-style: normal; color: #fff; background: var(--green);
  box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--green) 80%, #000); transform: scale(0) rotate(-14deg); transition: transform .55s var(--spring);
}
.res-plus.in { transform: none; }
/* What to do next stays at the bottom of the screen, as the stage's buttons
   do: over content that scrolls under it, a bar of the page's colour that
   fades out upwards and reaches down through the view's bottom padding. */
.res-actions {
  position: sticky; bottom: 0; z-index: 5;
  margin: auto -16px calc(-1 * var(--view-pb)); padding: 26px 16px calc(var(--view-pb) + 4px);
  background: linear-gradient(to top, var(--bg) 78%, transparent);
  transform: translateY(104%); pointer-events: none; transition: transform .65s var(--spring);
}
.res-actions.in { transform: none; pointer-events: auto; }
.res-act2 { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 10px; margin-top: 8px; }
.res-act2 .btn { min-height: 44px; padding: 0 8px; font-size: 16px; }

/* ─── Profile ─────────────────────────────────────────────────────────────── */
/* Laid out like Settings (ProfileView; the owner's pick A of
   tools/drafts/profile-design.html): you — the account and the four totals as a
   strip —, this month's allowances as meters with Plus as the card's last
   row, then the settings in groups, every row with its icon on its colour
   ([data-c]) and one short line. */
.pf-you { margin-top: 4px; background: var(--bg-2); border-radius: var(--r-card); overflow: hidden; }
.pf-acc { display: flex; align-items: center; gap: 12px; padding: 14px 16px; }
.pf-acc .avatar-lg { width: 52px; height: 52px; font-size: 22px; }
.pf-acc .avatar-lg .ic { width: 26px; height: 26px; }
.pf-acc .profile-id { flex: 1; }
.pf-acc .profile-id b { font-size: 17px; line-height: 22px; }
.pf-acc .profile-id small { font-size: 13.5px; }
.pf-nums { display: grid; grid-template-columns: repeat(4, 1fr); padding: 10px 6px 12px; border-top: .5px solid var(--sep); }
.pf-nums div { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 0; text-align: center; }
.pf-nums .ic { width: 17px; height: 17px; stroke-width: 2.3; color: var(--c); margin-bottom: 2px; }
.pf-nums b { font: 800 18px / 1.15 var(--font-rounded); font-variant-numeric: tabular-nums; }
.pf-nums small { font-size: 11.5px; line-height: 14px; color: var(--label-2); }
.pf-month { margin-top: 12px; background: var(--bg-2); border-radius: var(--r-card); overflow: hidden; }
.pf-month-in { padding: 14px 16px; }
.pf-month-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.pf-month-head b { font: 800 17px var(--font-rounded); }
.pf-chip { padding: 2px 10px; border-radius: 99px; background: var(--fill-3); color: var(--label-2); font: 800 12.5px var(--font-rounded); }
/* two meters side by side; a value too long for its half (Plus: 1,200 / 3,000) goes under its label, the bars stay level */
.pf-meters { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 16px; align-items: end; }
.pf-meter-l { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 6px; font-size: 14px; margin-bottom: 5px; white-space: nowrap; }
.pf-meter-l span:last-child { color: var(--label-2); font-variant-numeric: tabular-nums; font-size: 13px; }
.pf-bar { height: 7px; border-radius: 99px; background: var(--fill-3); overflow: hidden; }
.pf-bar i { display: block; height: 100%; border-radius: 99px; background: var(--tint); }
.pf-plus { display: flex; align-items: center; gap: 12px; width: 100%; padding: 11px 16px; text-align: left; transition: background-color .25s; }
.pf-month-in + .pf-plus { border-top: .5px solid var(--sep); }
.pf-plus:active { background: var(--press); transition: none; }
.pf-plus-txt { flex: 1; min-width: 0; }
.pf-plus-txt b { display: block; font-weight: 600; font-size: 16px; line-height: 21px; color: var(--tint); }
.pf-plus-txt small { display: block; font-size: 13px; line-height: 17px; color: var(--label-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.profile [data-c="blue"] { --c: var(--blue); } .profile [data-c="orange"] { --c: var(--orange); }
.profile [data-c="green"] { --c: var(--green); } .profile [data-c="indigo"] { --c: var(--indigo); }
.profile [data-c="purple"] { --c: var(--purple); } .profile [data-c="pink"] { --c: var(--pink); }
.profile [data-c="teal"] { --c: var(--teal); } .profile [data-c="cyan"] { --c: var(--cyan); }
.profile [data-c="red"] { --c: var(--red); } .profile [data-c="tint"] { --c: var(--tint); }
.profile [data-c="gray"] { --c: var(--gray); }
.profile [data-c="yellow"] { --c: color-mix(in srgb, var(--yellow) 70%, var(--orange)); }
.profile .group { margin-top: 26px; }
.profile .list .row + .row::before { left: 60px; }
.row-ic .m-glyph { width: 22px; height: 22px; margin-top: 1px; }
.row-ic-gap { width: 30px; flex: none; }
.row-stack .row-top { display: flex; align-items: center; gap: 14px; }
.row-stack > small { font-size: 13px; line-height: 17px; color: var(--label-2); }
.pf-foot { margin: 7px 16px 0; font-size: 13px; line-height: 17px; color: var(--label-2); }
.pf-danger { display: block; margin: 14px auto 0; padding: 8px 12px; font-size: 15px; color: var(--red); }
.pf-danger:active { opacity: .5; }
.avatar-lg {
  width: 60px; height: 60px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: linear-gradient(180deg, #A5ABB8, #858994); color: #fff;
  font-size: 26px; font-weight: 600;
}
.avatar-lg .ic { width: 30px; height: 30px; }
.profile-id { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.profile-id b { font-size: 20px; line-height: 25px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-id small { color: var(--label-2); font-size: 15px; }
.group { margin-top: 30px; }
.group > h2 { font-size: 13px; line-height: 18px; font-weight: 400; text-transform: uppercase; color: var(--label-2); margin: 0 16px 7px; }
.card.list { padding: 0; overflow: hidden; }
.row { position: relative; display: flex; align-items: center; gap: 14px; width: 100%; min-height: 52px; padding: 10px 16px; text-align: left; }
.list .row + .row::before { content: ''; position: absolute; top: 0; left: 16px; right: 0; border-top: .5px solid var(--sep); }
.list .row-link + .row-link::before { left: 60px; }
.row-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row-txt b { font-weight: 400; font-size: 17px; line-height: 22px; }
.row-txt small { font-size: 13px; line-height: 17px; color: var(--label-2); }
.row-note { flex: none; font-size: 17px; line-height: 22px; color: var(--label-2); font-variant-numeric: tabular-nums; }
.group-foot { margin: 7px 16px 0; font-size: 13px; line-height: 17px; color: var(--label-2); }
.row-link { transition: background-color .25s; }
.row-link:active:not(:disabled) { background: var(--press); transition: none; }
@media (hover: hover) { .row-link:hover:not(:disabled) { background: var(--fill-4); } }
.row-ic { width: 30px; height: 30px; flex: none; border-radius: 8px; display: grid; place-items: center; background: var(--c, var(--gray)); color: #fff; }
.row-ic .ic { width: 18px; height: 18px; stroke-width: 2.1; }

/* ─── Plus: the paywall (PlusView) ──────────────────────────────────────────
   Black and gold, the same in light and dark mode — the owner's pick of
   tools/drafts/paywall-design.html (2026-09-30): a world of its own, dark and
   glowing, with a moving background. ONE full screen that stays while the
   pages turn:
     .pw-decor   the background in three depths (light from above, soft
                 discs, rising gold dust, a sheen) — they shift as pages turn
     .pw-top     close · where you are
     .pw-stage   the page (.pw-page): its parts come in one after the other,
                 the old page leaves the other way
     .pw-voki    Voki, who flies from his place on a page ([data-slot]) to
                 his place on the next
     .pw-foot    the button (its label turns over, a light travels across
                 it) and the quiet way out
   All text is cream or gold on near-black with a dark shadow under it (the
   dust passes behind): every pair is 4.9 : 1 or more. */
@property --pw-a { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.pw { position: fixed; top: 0; bottom: 0; left: var(--app-x); right: var(--app-x); display: flex; flex-direction: column; overflow: hidden;
  background: radial-gradient(95% 52% at 50% 16%, #4A3509 0%, #1E1606 46%, #0B0804 100%);
  --gold: linear-gradient(135deg, #FFF0B0 0%, #F5BC3A 48%, #C9861A 100%); --on-gold: #2A1B00; --glow: rgba(245, 188, 58, .6);
  --text: #FFF8E6; --text-2: rgba(255, 248, 230, .84); --text-3: rgba(255, 248, 230, .68);
  --card: rgba(255, 225, 150, .1); --line: rgba(255, 225, 150, .22);
  color: var(--text); }
.pw i { font-style: normal; }
.pw-decor i, .pw-voki i, .pw-fx i, .pw-you .bar i { display: block; }

/* the background: three depths that shift a little as the pages turn (--p: the page) */
.pw-decor { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.pw-decor > div { position: absolute; inset: 0 -40px; transition: transform 1s var(--ease); }
.pw-decor i { position: absolute; }
.pw-far { transform: translateX(calc((var(--p) - 2) * -8px)); }
.pw-mid { transform: translateX(calc((var(--p) - 2) * -18px)); }
.pw-near { transform: translateX(calc((var(--p) - 2) * -34px)); }
.pw .beam { top: -14%; left: 50%; width: 130px; height: 92%; margin-left: -65px; transform-origin: 50% 0; filter: blur(14px); mix-blend-mode: screen;
  background: linear-gradient(180deg, rgba(255, 214, 120, .34), rgba(255, 214, 120, 0) 76%); animation: pw-beam 11s ease-in-out infinite alternate; }
.pw .beam:nth-child(1) { --r: -24deg; } .pw .beam:nth-child(2) { --r: 2deg; width: 170px; margin-left: -85px; animation-duration: 14s; animation-delay: -5s; } .pw .beam:nth-child(3) { --r: 25deg; animation-duration: 9s; animation-delay: -3s; }
@keyframes pw-beam { from { transform: rotate(calc(var(--r) - 4deg)); opacity: .5; } to { transform: rotate(calc(var(--r) + 4deg)); opacity: 1; } }
.pw .bokeh { border-radius: 50%; background: radial-gradient(circle at 40% 35%, rgba(255, 224, 140, .2), rgba(255, 200, 90, .05) 60%, transparent 72%); filter: blur(3px); animation: pw-drift ease-in-out infinite alternate; }
@keyframes pw-drift { from { transform: translate(0, 0) scale(1); } to { transform: translate(var(--dx), var(--dy)) scale(1.15); } }
.pw .dust { bottom: -10px; border-radius: 50%; background: #FFE08A; box-shadow: 0 0 6px 1px rgba(255, 200, 80, .6); animation: pw-dust linear infinite; }
@keyframes pw-dust { 0% { transform: translate(0, 0); opacity: 0; } 12% { opacity: var(--o); } 50% { transform: translate(var(--dx), calc(var(--h, 100vh) * -.5)); } 80% { opacity: var(--o); } 100% { transform: translate(calc(var(--dx) * -.6), calc(var(--h, 100vh) * -1)); opacity: 0; } }
.pw .sheen { left: -60%; top: -20%; width: 46%; height: 140%; transform: rotate(18deg); background: linear-gradient(90deg, transparent, rgba(255, 225, 150, .12), transparent); animation: pw-sheen 8s ease-in-out infinite; }
@keyframes pw-sheen { 0% { transform: translateX(0) rotate(18deg); } 45%, 100% { transform: translateX(413.043%) rotate(18deg); } }   /* left −60 % → 130 %, by a transform */
.pw .floor { left: 0; right: 0; bottom: 0; height: 34%; background: radial-gradient(70% 100% at 50% 100%, rgba(245, 188, 58, .2), transparent 70%); }

.pw-top { position: relative; z-index: 3; display: flex; align-items: center; gap: 12px; padding: calc(var(--safe-t) + 14px) 14px 0; }
.pw-x { width: 36px; height: 36px; flex: none; display: grid; place-items: center; border-radius: 50%; background: var(--card); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--line); }
.pw-x .ic { width: 17px; height: 17px; stroke-width: 2.6; }
.pw-x:active { opacity: .5; }
.pw-dots { flex: 1; display: flex; justify-content: center; gap: 6px; margin-right: 36px; }
.pw-dots button { width: 7px; height: 7px; padding: 0; border-radius: 99px; background: rgba(255, 225, 150, .34); transition: width .45s var(--spring), background-color .3s; }
.pw-dots button.on { width: 24px; background: #F5BC3A; box-shadow: 0 0 10px var(--glow); }
.pw-dots button.done { background: rgba(245, 188, 58, .75); }

/* the page: it comes in from the side it is turned from, part by part; the old one leaves the other way */
.pw-stage { position: relative; flex: 1; min-height: 0; }
.pw-page { position: absolute; inset: 0; display: flex; flex-direction: column; padding: 8px 22px 0; overflow-y: auto; scrollbar-width: none; text-shadow: 0 1px 10px rgba(0, 0, 0, .6); }
.pw-page::-webkit-scrollbar { display: none; }
.pw-page.in > * { animation: pw-in .55s var(--spring) both; animation-delay: calc(.1s + var(--i, 0) * .07s); }
.pw-page.in.back > * { animation-name: pw-in-back; }
.pw-page.in.first > * { animation-name: pw-rise; }
.pw-page.out { animation: pw-out .3s cubic-bezier(.5, 0, .9, .4) both; pointer-events: none; }
.pw-page.out.back { animation-name: pw-out-back; }
@keyframes pw-in { from { opacity: 0; transform: translateX(46px); } }
@keyframes pw-in-back { from { opacity: 0; transform: translateX(-46px); } }
@keyframes pw-rise { from { opacity: 0; transform: translateY(18px); } }
@keyframes pw-out { to { opacity: 0; transform: translateX(-60px) scale(.97); } }
@keyframes pw-out-back { to { opacity: 0; transform: translateX(60px) scale(.97); } }
.pw h1 { margin: 10px 0 0; text-align: center; font: 800 27px / 1.17 var(--font-rounded); text-wrap: balance; }
/* the words that matter: gold with a light running over them */
.pw h1 mark, .pw-gold { color: transparent; text-shadow: none; -webkit-background-clip: text; background-clip: text;
  background-image: linear-gradient(100deg, #FFD15C 0%, #FFE9A8 22%, #FFD15C 40%, #FFFBE6 50%, #FFD15C 60%, #FFE9A8 80%, #FFD15C 100%); background-size: 240% 100%; animation: pw-shimmer 4.2s linear infinite; }
@keyframes pw-shimmer { from { background-position: 120% 0; } to { background-position: -120% 0; } }
.pw .pw-lead { margin: 10px 0 0; text-align: center; font-size: 16px; line-height: 1.42; color: var(--text-2); text-wrap: pretty; }
.pw-eyebrow { align-self: center; padding: 3px 12px; border-radius: 99px; background: var(--gold); color: var(--on-gold); text-shadow: none; font: 900 12.5px var(--font-rounded); letter-spacing: .1em; }

/* Voki: one, who flies from his place on a page ([data-slot]) to his place on the next. Drawn 200 px, scaled to the place. */
.pw-voki { position: absolute; left: 0; top: 0; z-index: 2; width: 200px; height: 200px; transform-origin: 0 0; pointer-events: none; transition: transform .85s cubic-bezier(.3, 1.28, .45, 1); }
.pw-voki-in { position: absolute; inset: 0; transform-origin: 50% 62%; }
.pw-voki-in.pop { animation: pw-pop .7s var(--spring) both; }
@keyframes pw-pop { from { opacity: 0; transform: scale(.4); } }
.pw-voki-m { position: absolute; inset: 0; }
.pw-star { display: grid; place-items: center; position: absolute; right: -8px; top: 12px; width: 46px; height: 46px; border-radius: 14px; margin: 0; z-index: 3; color: #FFF;
  background: linear-gradient(145deg, #FFE27A, #F2A516); box-shadow: inset 0 1.5px 1px rgba(255, 255, 255, .7), inset 0 -3px 5px rgba(120, 60, 0, .3), 0 0 22px var(--glow); animation: pw-float 3.8s ease-in-out -1s infinite; }
.pw-star .ic { width: 25px; height: 25px; }
/* behind him: turning rays, a breathing halo, rings that widen, two sparks on an orbit — strongest on page 1 */
.pw-voki .burst { position: absolute; inset: -42%; border-radius: 50%; opacity: var(--burst, 1); transition: opacity .6s;
  background: repeating-conic-gradient(from 0deg, rgba(255, 214, 110, .26) 0 7deg, transparent 7deg 20deg);
  -webkit-mask-image: radial-gradient(closest-side, #000 22%, rgba(0, 0, 0, .5) 48%, transparent 78%); mask-image: radial-gradient(closest-side, #000 22%, rgba(0, 0, 0, .5) 48%, transparent 78%);
  animation: pw-turn 36s linear infinite; }
@keyframes pw-turn { to { transform: rotate(360deg); } }
.pw-voki .halo { position: absolute; inset: 4%; border-radius: 50%; background: var(--glow); filter: blur(30px); animation: pw-halo 4.4s ease-in-out infinite; }
@keyframes pw-halo { 0%, 100% { transform: scale(.9); opacity: .7; } 50% { transform: scale(1.1); opacity: 1; } }
.pw-voki .ring { position: absolute; inset: 10%; border-radius: 50%; box-shadow: inset 0 0 0 2px rgba(255, 214, 110, .7); opacity: 0; animation: pw-ring 3.4s ease-out infinite; }
.pw-voki .ring + .ring { animation-delay: 1.7s; }
.pw[data-page="2"] .pw-voki .ring { animation: none; }
@keyframes pw-ring { 0% { transform: scale(.7); opacity: 0; } 12% { opacity: .8; } 100% { transform: scale(1.75); opacity: 0; } }
.pw-voki .orbit { position: absolute; inset: -14%; transform: rotate(-18deg) scaleY(.4); opacity: var(--burst, 1); transition: opacity .6s; }
.pw-voki .orbit i { position: absolute; inset: 0; border-radius: 50%; animation: pw-turn 7s linear infinite; }
.pw-voki .orbit i + i { animation-duration: 11s; animation-direction: reverse; inset: 8%; }
.pw-voki .orbit b { position: absolute; left: 50%; top: -5px; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%; background: #FFF3C0; box-shadow: 0 0 12px 4px rgba(255, 210, 100, .9); }
.pw[data-page="1"] { --burst: 1; } .pw[data-page="2"] { --burst: 0; } .pw[data-page="3"] { --burst: .7; }
/* gold flakes thrown as he arrives on the last page */
.pw-fx { position: absolute; left: 0; top: 0; z-index: 4; pointer-events: none; }
.pw-fx i { position: absolute; width: 8px; height: 5px; border-radius: 1.5px; background: var(--c, #F5BC3A); animation: pw-flake 1.25s cubic-bezier(.15, .7, .4, 1) both; }
@keyframes pw-flake { 0% { transform: translate(0, 0) rotate(0); opacity: 1; } 70% { opacity: 1; } 100% { transform: translate(var(--x), var(--y)) rotate(var(--r)); opacity: 0; } }

/* the foot: the button breathes on the last page, a light travels over it, its label turns over */
.pw-foot { position: relative; z-index: 3; padding: 12px 20px calc(var(--safe-b) + 14px); }
.pw-cta { position: relative; overflow: hidden; display: grid; place-items: center; width: 100%; min-height: 56px; border-radius: 99px; color: var(--on-gold);
  background: linear-gradient(135deg, #FFEFA8 0%, #F5BC3A 52%, #D4921F 100%); font: 800 17.5px var(--font-rounded); letter-spacing: .01em;
  box-shadow: 0 0 36px -6px rgba(245, 188, 58, .85), inset 0 1.5px 0 rgba(255, 255, 255, .6); transition: transform .2s var(--spring); }
.pw[data-page="3"] .pw-cta { animation: pw-breathe 2.4s ease-in-out infinite; }
@keyframes pw-breathe { 0%, 100% { transform: scale(1); box-shadow: 0 0 36px -6px rgba(245, 188, 58, .85), inset 0 1.5px 0 rgba(255, 255, 255, .6); } 50% { transform: scale(1.025); box-shadow: 0 0 46px 0 rgba(245, 188, 58, .95), inset 0 1.5px 0 rgba(255, 255, 255, .6); } }
.pw-cta::after { content: ''; position: absolute; top: -20%; bottom: -20%; left: -40%; width: 34%; transform: skewX(-20deg); background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .75), transparent); animation: pw-shine 3.6s ease-in-out 1.2s infinite; }
@keyframes pw-shine { 0% { transform: translateX(0) skewX(-20deg); } 38%, 100% { transform: translateX(470.588%) skewX(-20deg); } }   /* left −40 % → 120 %, by a transform */
.pw-cta:active { transform: scale(.97); animation: none; }
.pw-cta:disabled { filter: saturate(.7) brightness(.92); }
.pw-cta .spin { vertical-align: -3px; margin-right: 4px; }
.pw-cta span { grid-area: 1 / 1; transition: transform .38s var(--spring), opacity .25s; }
.pw-cta span.from { transform: translateY(110%); opacity: 0; }
.pw-cta span.gone { transform: translateY(-110%); opacity: 0; }
.pw-no { display: block; margin: 4px auto 0; padding: 10px 16px; font: 800 14.5px var(--font-rounded); letter-spacing: .04em; text-transform: uppercase; color: var(--text-3); }
.pw-no:active { opacity: .5; }

/* 1 · the core value: Voki big, what Plus multiplies floating round him */
.pw-hero { position: relative; align-self: center; width: 290px; height: 214px; margin: auto 0 0; }
.pw-hero [data-slot] { position: absolute; left: 45px; top: 8px; width: 200px; height: 200px; }
.pw-chip { position: absolute; z-index: 3; display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; color: #FFF; background: rgba(255, 225, 150, .16);
  box-shadow: inset 0 0 0 1px rgba(255, 225, 150, .45), inset 0 8px 10px -6px rgba(255, 255, 255, .35), 0 10px 18px -10px rgba(0, 0, 0, .7);
  animation: pw-chip-in .6s var(--spring) both, pw-float 4.2s ease-in-out infinite; animation-delay: calc(.45s + var(--n) * .16s), calc(1.05s + var(--n) * .16s); }
.pw-chip .ic { width: 22px; height: 22px; stroke-width: 2.2; }
.pw-chip b { position: absolute; right: -9px; top: -7px; padding: 0 6px; border-radius: 99px; background: var(--gold); color: var(--on-gold); text-shadow: none; font: 900 12.5px / 19px var(--font-rounded); }
.pw-chip:nth-of-type(1) { left: 0; top: 20px; --n: 0; } .pw-chip:nth-of-type(2) { left: -4px; bottom: -8px; --n: 1; width: 42px; height: 42px; } .pw-chip:nth-of-type(3) { right: 0; bottom: 44px; --n: 2; }
@keyframes pw-chip-in { from { opacity: 0; transform: scale(0); } }
@keyframes pw-float { 0%, 100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-9px) rotate(3deg); } }
.pw-p-value h1 { font-size: 29px; }
.pw-p-value .pw-lead { margin-bottom: auto; }

/* 2 · what more there is: Voki says it, the month's use fills, the rows come one by one, the Plus column is drawn and counts up */
.pw-say { display: flex; align-items: center; gap: 10px; margin-top: 2px; }
.pw-say [data-slot] { width: 76px; height: 76px; flex: none; }
.pw-bubble { position: relative; flex: 1; padding: 11px 14px; border-radius: 18px; background: var(--card); box-shadow: inset 0 0 0 1px var(--line); }
.pw-bubble::before { content: ''; position: absolute; left: -6px; top: 50%; width: 13px; height: 13px; margin-top: -6px; border-radius: 3px; transform: rotate(45deg); background: #2B2109; box-shadow: inset 1px -1px 0 var(--line); clip-path: polygon(0 0, 0 100%, 100% 100%); }
.pw-bubble h1 { margin: 0; text-align: left; font-size: 20px; line-height: 1.22; }
.pw-you { margin-top: 12px; padding: 9px 14px 11px; border-radius: 16px; background: var(--card); box-shadow: inset 0 0 0 1px var(--line); font-size: 14px; color: var(--text-2); }
.pw-you b { color: var(--text); font-weight: 700; }
.pw-you .bar { height: 7px; margin-top: 7px; border-radius: 99px; background: rgba(255, 225, 150, .16); overflow: hidden; }
.pw-you .bar i { width: var(--w); height: 100%; border-radius: 99px; background: linear-gradient(90deg, #F5BC3A, #FF7A3D); animation: pw-fill 1s cubic-bezier(.2, .8, .3, 1) .5s both; }
@keyframes pw-fill { from { width: 0; } }
.pw-tab { position: relative; margin: 12px -6px 0; }
.pw-tab-col { position: absolute; top: 0; bottom: 0; right: 0; width: 76px; border-radius: 18px; background: rgba(245, 188, 58, .14); animation: pw-draw .8s cubic-bezier(.3, .8, .3, 1) .35s both, pw-colglow 3.4s ease-in-out 1.2s infinite; }
.pw-tab-col::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 2px; background: var(--gold);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
@keyframes pw-draw { from { clip-path: inset(0 0 100% 0 round 18px); } to { clip-path: inset(0 0 0 0 round 18px); } }
@keyframes pw-colglow { 0%, 100% { box-shadow: 0 0 18px -6px var(--glow); } 50% { box-shadow: 0 0 34px -2px var(--glow); } }
.pw-tr { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 64px 76px; align-items: center; min-height: 44px; padding-left: 6px; animation: pw-row .5s var(--spring) both; animation-delay: calc(.35s + var(--n) * .07s); }
@keyframes pw-row { from { opacity: 0; transform: translateX(-18px); } }
.pw-tr + .pw-tr { border-top: .5px solid var(--line); }
.pw-tr.head { min-height: 36px; border: 0; }
.pw-tr.head span { font: 800 12.5px var(--font-rounded); letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); text-align: center; }
.pw-tr.head .p { color: #FFD15C; }
.pw-tr b { font-weight: 600; font-size: 15px; line-height: 1.2; }
.pw-tr small { display: block; font-size: 12.5px; color: var(--text-3); }
.pw-tr .f { text-align: center; font-size: 15px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.pw-tr .p { text-align: center; font: 800 17.5px var(--font-rounded); font-variant-numeric: tabular-nums; }
.pw-tr .p.hit { animation: pw-hit .45s var(--spring); }
@keyframes pw-hit { 40% { transform: scale(1.3); color: #FFE9A8; } }
.pw-tr .ic { width: 18px; height: 18px; stroke-width: 3; vertical-align: -3px; }
.pw-tr .p .ic { color: #FFD15C; }

/* 3 · the plans: the cards come from both sides, a light runs round the chosen one, the saving is stamped on */
.pw-p-plans [data-slot] { align-self: center; width: 92px; height: 92px; flex: none; margin: 2px 0 -2px; }
.pw-p-plans h1 { font-size: 25px; }
.pw-plans { display: grid; gap: 12px; margin-top: 20px; }
.pw-page.in .pw-plans { animation: none; }
.pw-plan { position: relative; display: flex; align-items: center; gap: 12px; width: 100%; padding: 15px 16px; border-radius: 20px; text-align: left; background: var(--card); color: inherit; text-shadow: inherit;
  box-shadow: inset 0 0 0 1.5px var(--line); transition: transform .2s var(--spring), background-color .3s; animation: pw-plan-l .6s var(--spring) .3s both; }
.pw-plan + .pw-plan { animation-name: pw-plan-r; animation-delay: .4s; }
@keyframes pw-plan-l { from { opacity: 0; transform: translateX(-70px) rotate(-3deg); } }
@keyframes pw-plan-r { from { opacity: 0; transform: translateX(70px) rotate(3deg); } }
.pw-plan:active { transform: scale(.98); }
.pw-plan.on { background: rgba(245, 188, 58, .15); box-shadow: 0 0 30px -6px var(--glow); }
.pw-plan.on::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 2.5px;
  background: conic-gradient(from var(--pw-a), #C9861A 0deg, #FFF6CF 40deg, #F5BC3A 90deg, #C9861A 170deg, #8A5A10 250deg, #C9861A 360deg); animation: pw-spin 3.6s linear infinite;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
@keyframes pw-spin { to { --pw-a: 360deg; } }
.pw-radio { width: 24px; height: 24px; flex: none; border-radius: 50%; box-shadow: inset 0 0 0 2px rgba(255, 225, 150, .45); display: grid; place-items: center; transition: background-color .2s; }
.pw-plan.on .pw-radio { background: var(--gold); box-shadow: none; }
.pw-radio .ic { width: 14px; height: 14px; stroke-width: 3.4; color: var(--on-gold); transform: scale(0); transition: transform .35s var(--spring); }
.pw-plan.on .pw-radio .ic { transform: none; }
.pw-plan-t { flex: 1; min-width: 0; }
.pw-plan-t b { display: block; font: 800 18px / 1.2 var(--font-rounded); }
.pw-plan-t small { display: block; margin-top: 1px; font-size: 13.5px; color: var(--text-2); }
.pw-plan-p { text-align: right; white-space: nowrap; }
.pw-plan-p b { display: block; font: 800 18px / 1.2 var(--font-rounded); font-variant-numeric: tabular-nums; }
.pw-plan-p small { font-size: 13px; color: var(--text-2); }
.pw-save { position: absolute; top: -11px; right: 16px; z-index: 1; padding: 2px 10px; border-radius: 99px; background: var(--gold); color: var(--on-gold); text-shadow: none; font: 900 12px var(--font-rounded); letter-spacing: .06em; text-transform: uppercase;
  animation: pw-stamp .5s cubic-bezier(.3, 1.6, .5, 1) 1s both; }
@keyframes pw-stamp { from { opacity: 0; transform: scale(2.2) rotate(-14deg); } }
/* redrawn in place (after a purchase that did not happen): nothing comes in again */
.pw-page.still :is(.pw-plan, .pw-save, .pw-tr, .pw-tab-col) { animation: none; }
.pw-fine { margin: 14px 2px 0; text-align: center; font-size: 13px; line-height: 1.42; color: var(--text-3); transition: opacity .2s; }
.pw-fine.swap { opacity: 0; }
.pw-link { padding: 4px 0; font: inherit; font-weight: 600; color: var(--text-2); text-shadow: inherit; }
.pw-link:active { opacity: .5; }
/* the offer still loading: the plan cards' shape, gold bars shimmering where the words come */
.pw-sk-plan { display: flex; align-items: center; gap: 12px; padding: 15px 16px; border-radius: 20px; background: var(--card); box-shadow: inset 0 0 0 1.5px var(--line); }
.pw-sk i { display: inline-block; vertical-align: middle; width: var(--w); height: .7em; border-radius: 99px;
  background: linear-gradient(100deg, rgba(255, 225, 150, .09) 35%, rgba(255, 225, 150, .3) 50%, rgba(255, 225, 150, .09) 65%) 0 0 / 300% 100%; animation: pw-sk 1.5s linear infinite; }
.pw-sk-plan + .pw-sk-plan i { animation-delay: .15s; }
@keyframes pw-sk { from { background-position: 100% 0; } to { background-position: 0 0; } }
/* the last page where nothing can be bought */
.pw-note { margin: 22px 0 0; padding: 14px 16px; border-radius: 18px; background: var(--card); box-shadow: inset 0 0 0 1px var(--line); text-align: center; font-size: 15.5px; line-height: 1.4; color: var(--text-2); }
.pw-note .spin { vertical-align: -3px; margin-right: 4px; }
/* Mascot off (Profile): the Plus star stands in his place */
html[data-mascot="off"] .pw-star { right: 50%; top: 50%; width: 92px; height: 92px; margin: -46px -46px 0 0; border-radius: 28px; }
html[data-mascot="off"] .pw-star .ic { width: 50px; height: 50px; }

/* The paywall as a layer over a page (limitHints.js openPaywall): above the
   page and its tab bar, under dialogs and toasts. Nothing behind it scrolls. */
.pw { touch-action: none; overscroll-behavior: contain; }
.pw-page { touch-action: pan-y; overscroll-behavior: contain; }
.pw-over .pw { z-index: 90; animation: pw-over-in .4s var(--ease) both; }
.pw-over.closing .pw { animation: pw-over-out .24s ease-in both; pointer-events: none; }
@keyframes pw-over-in { from { opacity: 0; transform: translateY(7%); } }
@keyframes pw-over-out { to { opacity: 0; transform: translateY(5%); } }

/* ─── Hints at a free allowance (limitHints.js) ───────────────────────────────
   Gold is Plus: what the learner sees when an allowance runs low or out wears
   the paywall's black and gold — the owner's pick of tools/drafts/limit-design.html
   (2026-09-30). .lm holds the tokens; the pieces:
     .lm-warn   1 the warning, where the toasts are: Voki, a line, a gold chip
     .lm-sheet  2 the limit reached: a sheet from below (a layer), Voki looking
                  over its edge, free → Plus counting up, the button, the
                  quiet way on
     .lm-bar    3 in a spoken round: a slim bar over the answer field
     .lm-card   3 the result page's card · 4 .lm-today: the small one on Today */
.lm { --gold: linear-gradient(135deg, #FFF0B0 0%, #F5BC3A 48%, #C9861A 100%); --on-gold: #2A1B00; --glow: rgba(245, 188, 58, .6);
  --g-text: #FFF8E6; --g-text-2: rgba(255, 248, 230, .84); --g-text-3: rgba(255, 248, 230, .68); --g-card: rgba(255, 225, 150, .1); --g-line: rgba(255, 225, 150, .22); }
.lm-sheet, .lm-card, .lm-bar { color: var(--g-text); background: radial-gradient(110% 70% at 50% 0%, #4A3509 0%, #1E1606 50%, #0B0804 100%); }
.lm mark { color: transparent; -webkit-background-clip: text; background-clip: text;
  background-image: linear-gradient(100deg, #FFD15C 0%, #FFE9A8 22%, #FFD15C 40%, #FFFBE6 50%, #FFD15C 60%, #FFE9A8 80%, #FFD15C 100%); background-size: 240% 100%; animation: pw-shimmer 4.2s linear infinite; }
.lm-dust { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; pointer-events: none; }
.lm-dust i { position: absolute; bottom: -8px; display: block; border-radius: 50%; background: #FFE08A; box-shadow: 0 0 6px 1px rgba(255, 200, 80, .6); animation: lm-dust linear infinite; }
@keyframes lm-dust { 0% { transform: translateY(0); opacity: 0; } 15% { opacity: var(--o); } 80% { opacity: var(--o); } 100% { transform: translate(var(--dx), calc(var(--up) * -1)); opacity: 0; } }
.lm-cta { position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 54px; padding: 0 16px; border-radius: 99px; color: var(--on-gold);
  background: linear-gradient(135deg, #FFEFA8 0%, #F5BC3A 52%, #D4921F 100%); font: 800 17px var(--font-rounded); box-shadow: 0 0 30px -8px rgba(245, 188, 58, .85), inset 0 1.5px 0 rgba(255, 255, 255, .6); transition: transform .2s var(--spring); }
.lm-cta::after { content: ''; position: absolute; top: -20%; bottom: -20%; left: -40%; width: 34%; transform: skewX(-20deg); background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .75), transparent); animation: pw-shine 3.6s ease-in-out 1s infinite; }
.lm-cta:active { transform: scale(.97); }
.lm-cta .ic { position: relative; width: 17px; height: 17px; stroke-width: 2.6; }
.lm-no { display: block; margin: 4px auto 0; padding: 10px 14px; font: 700 15px var(--font); color: var(--g-text-3); }
.lm-no:active { opacity: .5; }
.lm-star { position: absolute; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 10px; color: #FFF; background: linear-gradient(145deg, #FFE27A, #F2A516); box-shadow: inset 0 1.5px 1px rgba(255, 255, 255, .7), 0 0 16px var(--glow); }
.lm-star .ic { width: 17px; height: 17px; }
.lm-star.flat { position: relative; flex: none; }
.lm-voki { display: block; }
.lm-voki .mascot { width: 100%; height: 100%; }
.lm-eyebrow { display: inline-block; padding: 3px 12px; border-radius: 99px; background: var(--gold); color: var(--on-gold); font: 900 12.5px var(--font-rounded); letter-spacing: .08em; text-transform: uppercase; }
.lm-chip { flex: none; display: inline-flex; align-items: center; gap: 4px; height: 32px; padding: 0 12px; border-radius: 99px; background: var(--gold); color: var(--on-gold); font: 800 13.5px var(--font-rounded); box-shadow: 0 6px 14px -8px rgba(200, 140, 20, .9); white-space: nowrap; }
.lm-chip:active { opacity: .7; }
.lm-chip .ic { width: 14px; height: 14px; stroke-width: 2.6; }
/* free → Plus: the two numbers, the Plus one counting up */
.lm-cmp { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 14px 0 0; }
.lm-cmp div { min-width: 86px; padding: 8px 12px 9px; border-radius: 16px; background: var(--g-card); box-shadow: inset 0 0 0 1px var(--g-line); text-align: center; }
.lm-cmp small { display: block; font: 800 11.5px var(--font-rounded); letter-spacing: .08em; text-transform: uppercase; color: var(--g-text-3); }
.lm-cmp b { display: block; font: 800 24px / 1.15 var(--font-rounded); font-variant-numeric: tabular-nums; }
.lm-cmp .p { background: rgba(245, 188, 58, .16); box-shadow: inset 0 0 0 2px #F5BC3A, 0 0 24px -6px var(--glow); }
.lm-cmp .p small { color: #FFD15C; }
.lm-cmp > .ic { width: 20px; height: 20px; color: #F5BC3A; stroke-width: 2.6; }
.lm-unit { margin: 6px 0 0; text-align: center; font-size: 13px; color: var(--g-text-3); }

/* 1 · the warning — where the toasts are, a little wider, a gold rim */
.lm-warn { position: fixed; z-index: 190; left: calc(var(--app-x) + 12px); right: calc(var(--app-x) + 12px); bottom: calc(var(--tabbar-b) + var(--tabbar-h) + 14px);
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 8px 10px; padding: 10px 10px 10px 8px; border-radius: 24px;
  background: var(--glass-thick); color: var(--label); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: 0 14px 34px -12px rgba(0, 0, 0, .45), inset 0 0 0 1.5px rgba(245, 188, 58, .75);
  opacity: 0; transform: translateY(40px) scale(.96); pointer-events: none; transition: opacity .25s, transform .5s var(--spring); }
body.no-tabbar .lm-warn { bottom: calc(var(--safe-b) + 20px); }
.lm-warn.show { opacity: 1; transform: none; pointer-events: auto; }
.lm-warn .lm-voki { width: 46px; height: 46px; }
.lm-warn-t b { display: block; font: 800 15.5px / 1.2 var(--font-rounded); }
.lm-warn-t small { display: block; font-size: 13px; color: var(--label-2); }
.lm-warn .lm-chip { grid-column: 1 / -1; justify-content: center; height: 38px; font-size: 14.5px; }

/* 2 · the sheet: a layer that sits on the screen's lower edge, the column wide */
.layer.layer-limit { align-items: flex-end; padding: 0 var(--app-x); }
.layer.layer-limit .layer-panel { width: 100%; max-height: none; overflow: visible; padding: 0; border-radius: 0; background: none; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none; animation: sheet-in .5s var(--ease) both; }
.layer.layer-limit.closing .layer-panel { animation: sheet-out .24s ease-in both; }
.lm-sheet { position: relative; padding: 56px 20px calc(var(--safe-b) + 14px); border-radius: 30px 30px 0 0; text-align: center; box-shadow: 0 -1px 0 rgba(255, 225, 150, .35), 0 -20px 50px rgba(0, 0, 0, .4); }
.lm-sheet .lm-voki { position: absolute; left: 50%; top: -58px; width: 108px; height: 108px; margin-left: -54px; }
.lm-sheet .lm-star { left: 50%; top: -46px; margin-left: 26px; z-index: 1; }
html[data-mascot="off"] .lm-sheet .lm-star { top: -15px; margin-left: -15px; }
.lm-sheet h2 { position: relative; margin: 8px 0 0; font: 800 23px / 1.18 var(--font-rounded); text-wrap: balance; }
.lm-sheet .lm-eyebrow, .lm-sheet .lm-cmp, .lm-sheet .lm-unit, .lm-sheet .lm-cta, .lm-sheet .lm-no { position: relative; }
.lm-sheet .lm-no { margin-left: auto; margin-right: auto; }
.lm-text { position: relative; margin: 10px 4px 16px; font-size: 15px; line-height: 1.4; color: var(--g-text-2); text-wrap: pretty; }

/* 3 · a spoken round: the bar over the answer field, a lock on the microphone */
.ss-limit { width: 100%; }
.ss-limit:empty { display: none; }
.lm-bar { position: relative; display: flex; align-items: center; gap: 10px; padding: 9px 9px 9px 14px; border-radius: 18px; text-align: left; box-shadow: inset 0 0 0 1px rgba(255, 225, 150, .3); animation: lm-pop .5s var(--spring) both; }
.lm-bar > .ic { width: 18px; height: 18px; color: #F5BC3A; flex: none; }
.lm-bar p { flex: 1; min-width: 0; margin: 0; font-size: 13.5px; line-height: 1.3; color: var(--g-text-2); }
.lm-bar p b { color: var(--g-text); font-weight: 700; }
@keyframes lm-pop { from { opacity: 0; transform: scale(.94); } }
.vx-lock { position: absolute; z-index: 2; right: 0; bottom: 0; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; color: #FFF;
  background: linear-gradient(145deg, #FFE27A, #F2A516); box-shadow: 0 0 0 3px var(--s-bg), 0 0 14px rgba(245, 188, 58, .6); }
.orb .vx-lock .ic { width: 16px; height: 16px; stroke-width: 2.4; }
/* at rest it is smaller: the bar takes the room (nothing may run under the buttons on a 680 px screen) */
.orb.locked { width: 64px; height: 64px; color: var(--s-label-2); }
.orb.locked > .ic { width: 28px; height: 28px; }
.orb.locked .vx-lock { right: -5px; bottom: -5px; width: 27px; height: 27px; }
.orb.locked .vx-lock .ic { width: 14px; height: 14px; }
.ss-inwrap .vx-mic .vx-lock { right: -3px; bottom: -3px; width: 18px; height: 18px; box-shadow: 0 0 0 2px var(--s-bg); }
.ss-inwrap .vx-mic .vx-lock .ic { width: 10px; height: 10px; stroke-width: 3; }

/* 3 · the card on the result page · 4 · the small one on Today */
.lm-card { position: relative; display: block; width: 100%; overflow: hidden; margin: 14px 0; padding: 16px; border-radius: 24px; text-align: left; box-shadow: 0 16px 34px -18px rgba(0, 0, 0, .7), inset 0 0 0 1px rgba(255, 225, 150, .3); }
.lm-card-h { position: relative; display: flex; align-items: center; gap: 12px; }
.lm-card-h .lm-voki { width: 60px; height: 60px; flex: none; margin: -6px 0 -6px -6px; }
.lm-card-h b { display: block; font: 800 18px / 1.2 var(--font-rounded); }
.lm-card-h small { display: block; margin-top: 2px; font-size: 13.5px; line-height: 1.35; color: var(--g-text-2); }
.lm-card .lm-cta { min-height: 46px; margin-top: 14px; font-size: 16px; }
.lm-today { display: flex; align-items: center; gap: 12px; margin: 12px 0 0; padding: 12px 14px; transition: transform .2s var(--spring); }
.lm-today:active { transform: scale(.98); }
.lm-today-t { position: relative; flex: 1; min-width: 0; }
.lm-today-t b { display: block; font: 800 16px / 1.2 var(--font-rounded); }
.lm-today-t small { display: block; margin-top: 1px; font-size: 13px; color: var(--g-text-2); }
.lm-today .lm-chip { position: relative; }
.row-chev { color: var(--label-3); width: 15px; height: 15px; stroke-width: 2.8; margin-right: -3px; }
.row .spin { vertical-align: -3px; margin-right: 4px; }
.row .seg { flex: none; }
/* UIStepper: the value, then − and + in one capsule */
.stepper { display: inline-flex; align-items: center; }
.stepper output { order: -1; min-width: 2.5ch; margin-right: 12px; text-align: right; font-size: 17px; color: var(--label-2); font-variant-numeric: tabular-nums; }
.stepper button { position: relative; width: 47px; height: 32px; display: grid; place-items: center; background: var(--fill-3); font-size: 22px; line-height: 1; font-weight: 400; color: var(--label); }
.stepper button:first-of-type { border-radius: 999px 0 0 999px; }
.stepper button:last-of-type { border-radius: 0 999px 999px 0; }
.stepper button:last-of-type::before { content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; border-left: 1px solid var(--sep); }
.stepper button:active { background: var(--fill); }
.version { text-align: center; color: var(--label-2); font-size: 13px; margin: 18px 0 8px; }

/* ─── Auth: signing in again (LoginView), in the onboarding's look ────────── */
.lg { gap: 0; }
.lg-mascot { display: flex; justify-content: center; flex: none; height: 150px; margin: 20px 0 6px; }
.lg-mascot .mascot { height: 100%; width: auto; }
.lg[data-tab="code"] .lg-mascot { height: 120px; }
.lg-body { flex: 1; display: flex; flex-direction: column; }
.lg-or { display: flex; align-items: center; gap: 12px; margin: 14px 0; color: var(--label-3); font-size: 14px; }
.lg-or::before, .lg-or::after { content: ''; flex: 1; height: 1px; background: var(--sep); }
.lg-forgot { margin-top: 2px; }
.lg-new { margin: 2px 0 0; text-align: center; color: var(--label-2); font-size: 15px; }
.lg .auth-legal { margin-top: 18px; }
.auth-legal { display: flex; justify-content: center; gap: 8px; font-size: 13px; color: var(--label-3); }
.auth-legal a { color: var(--label-2); }

/* ─── Onboarding & sign-in: the page frame (.onb); the steps: "Onboarding" under Mascot ─── */
.onb {
  min-height: var(--view-fill);
  max-width: 480px; margin: 0 auto;
  padding: calc(var(--safe-t) + 10px) 24px calc(var(--safe-b) + 18px);
  display: flex; flex-direction: column;
}
.onb-title { font-weight: 700; font-size: clamp(28px, calc(var(--vw) * 8.4), 34px); line-height: 1.18; margin: 0 0 12px; }
.onb-text { color: var(--label-2); font-size: 17px; line-height: 1.4; margin: 0 auto; max-width: 34ch; }

/* ─── Legal ───────────────────────────────────────────────────────────────── */
.prose { font-size: 17px; line-height: 1.45; padding: 0 4px; }
.prose h2 { font-size: 20px; line-height: 25px; font-weight: 600; margin: 26px 0 6px; }
.prose p { margin: 0 0 12px; }
.prose ul { padding-left: 22px; }
.prose li { margin-bottom: 8px; }
.prose strong { font-weight: 600; }
.legal-meta { color: var(--label-2); font-size: 13px; margin-top: 24px; }

/* ═══════════════════════════════════════════════════════════════════════════
   Training round — the stage (light or dark with the theme; --s-* tokens)
   ═══════════════════════════════════════════════════════════════════════════ */
.view-train {
  background:
    radial-gradient(120% 52% at 50% 112%, var(--s-glow-a), transparent 62%),
    radial-gradient(90% 40% at 50% -8%, var(--s-glow-b), transparent 70%),
    var(--s-bg);
  color: var(--s-text);
}
body:has(.view-train) { background: var(--s-bg); }
.ss {
  min-height: var(--view-fill);
  max-width: 620px; margin: 0 auto;
  padding: calc(var(--safe-t) + 8px) 16px 0;
  display: flex; flex-direction: column;
}
/* Four round buttons, the run counter and the progress bar share the column's width (the flag came on
   2026-09-30): compact everywhere — the column is never wider than a phone, and the 420 px rule did not
   reach the desktop's 400 px column, where a run of 11 squeezed the bar to 10 px (the test report). */
.ss-top { display: flex; align-items: center; gap: 8px; min-height: 52px; }
.ss-top .icon-btn { width: 40px; height: 40px; }
.ss-top .ss-count { min-width: 34px; }
@media (max-width: 380px) { .ss-top { gap: 6px; } }
.ss-btn {
  color: var(--s-text); background: var(--s-glass); box-shadow: var(--s-rim);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
}
.ss-btn .ic { width: 20px; height: 20px; stroke-width: 2.1; }
.ss-bar { flex: 1; min-width: 44px; height: 6px; border-radius: 99px; background: var(--s-track); overflow: hidden; }
.ss-bar i { display: block; height: 100%; width: 0; border-radius: 99px; background: var(--s-tint); transition: width .5s var(--ease); }
.ss-count { min-width: 40px; text-align: right; font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--s-label-2); }

.ss-mascot { display: flex; justify-content: center; height: clamp(130px, 24vh, 210px); margin: 0 0 -18px; pointer-events: none; }
.ss-mascot .mascot { width: auto; height: 100%; }
@media (max-height: 640px) { .ss-mascot { display: none; } }   /* a small phone, or the keyboard is up */
html[data-mascot="off"] .ss-mascot { display: none; }   /* Voki switched off: no empty room over the word (the test report) */
.ss-body { flex: 1; display: flex; flex-direction: column; padding: 8px 0 0; }
.ss-card {
  flex: 1; min-height: 190px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  text-align: center; padding: 20px 4px;
  animation: card-in .42s var(--ease) both;
}
@keyframes card-in { from { opacity: 0; transform: translateY(16px) scale(.98); } }
.ss-prompt { font-size: 13px; font-weight: 600; text-transform: uppercase; color: var(--s-label-2); }
.ss-tag { display: inline-flex; align-items: center; gap: 5px; padding: 4px 11px; border-radius: 99px; background: rgba(255, 159, 10, .2); color: var(--orange-text); font-size: 13px; font-weight: 600; text-transform: none; }
.ss-tag .ic { width: 14px; height: 14px; stroke-width: 2.4; }
.ss-word { font-weight: 700; font-size: clamp(36px, calc(var(--vw) * 11), 56px); line-height: 1.1; max-width: 100%; }
/* Long words and phrases (TrainView sizeClass) come smaller, lines balanced,
   compounds hyphenated in the card's language (lang) where it can. */
.ss-word, .fc-text { overflow-wrap: anywhere; -webkit-hyphens: auto; hyphens: auto; text-wrap: balance; }
.ss-word.long { font-size: clamp(28px, calc(var(--vw) * 8.2), 42px); line-height: 1.15; }
.ss-word.longer { font-size: clamp(24px, calc(var(--vw) * 6.6), 34px); line-height: 1.2; }

.ss-answer { display: flex; flex-direction: column; align-items: center; gap: 8px; }
/* A textarea that grows with its text (TrainView growWithText): a long answer
   wraps instead of running out of the field. */
.ss-input {
  display: block; width: 100%;
  resize: none; overflow-y: auto; max-height: 32vh;
  background: var(--fill-3); color: var(--s-text);
  border: 0; border-radius: 16px;
  padding: 15px 18px; font-size: 19px; font-weight: 500; line-height: 24px; text-align: center;
  overflow-wrap: anywhere;
  outline: none; caret-color: var(--s-tint);
  box-shadow: inset 0 0 0 1.5px transparent;
  transition: box-shadow .15s, background-color .15s;
}
.ss-input::placeholder { color: var(--s-label-3); font-weight: 400; }
.ss-input:focus { box-shadow: inset 0 0 0 2px var(--s-tint); }
.ss-input:disabled { opacity: .9; }
.ss-input.is-interim { color: var(--s-label-2); }
.ss-heard { background: transparent; font-size: 24px; font-weight: 600; line-height: 30px; min-height: 60px; }
.ss-heard:focus { box-shadow: inset 0 0 0 1.5px var(--s-label-3); }
.vx-status { font-size: 15px; font-weight: 500; color: var(--s-label-2); text-align: center; min-height: 1.35em; }
.vx-status:empty { visibility: hidden; }
.vx-status.err { color: var(--red-text); }
.vx-status.ok { color: var(--green-text); }

/* Speak: the orb. Glass while it waits; blue with rings that follow the
   voice while it listens. */
.ss-voice { position: relative; display: flex; align-items: center; justify-content: center; gap: 28px; margin: 16px 0 8px; }
.orb {
  --lvl: 0;
  position: relative;
  width: 92px; height: 92px; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--s-tint);
  background: var(--s-orb);
  box-shadow: var(--s-rim);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  transition: background-color .25s, color .25s, transform .25s var(--spring), box-shadow .25s;
}
.orb .ic { position: relative; z-index: 1; width: 38px; height: 38px; stroke-width: 2; }
.orb:active { transform: scale(.94); }
.orb.listening { background: var(--s-tint); color: #fff; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 10px 40px rgba(10, 132, 255, .6); }
.vx-ring { position: absolute; inset: 0; border-radius: 50%; pointer-events: none; opacity: 0; }
.orb.listening .vx-ring {
  opacity: 1;
  box-shadow: 0 0 0 calc(6px + var(--lvl) * 22px) rgba(10, 132, 255, .26), 0 0 0 calc(14px + var(--lvl) * 40px) rgba(10, 132, 255, .1);
  transition: box-shadow .09s linear;
  animation: orb-breathe 1.8s ease-in-out infinite;
}
.orb.hearing .vx-ring { animation: none; }
@keyframes orb-breathe { 50% { box-shadow: 0 0 0 14px rgba(10, 132, 255, .18), 0 0 0 30px rgba(10, 132, 255, .06); } }
.orb.busy { background: rgba(10, 132, 255, .3); color: #fff; }
.orb.busy .vx-ring { opacity: 1; inset: -7px; border: 3px solid transparent; border-top-color: var(--s-tint); border-right-color: rgba(10, 132, 255, .4); animation: spin .8s linear infinite; }
.vx-lang, .ss-round-btn {
  width: 50px; height: 50px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--s-glass); box-shadow: var(--s-rim);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  color: var(--s-round); font-size: 13px; font-weight: 700; letter-spacing: .03em;
  transition: background-color .2s, transform .25s var(--spring);
}
.vx-lang:active, .ss-round-btn:active { background: var(--s-glass-2); transform: scale(.92); }
.ss-round-btn .ic { width: 22px; height: 22px; }

/* Type: mic inside the field */
.ss-inwrap { position: relative; width: 100%; }
.ss-inwrap.has-voice .ss-input { padding-right: 104px; text-align: left; }
/* Mic and language chip sit at the bottom right, where they stay when a long
   answer makes the field grow. */
.ss-inwrap .vx-mic, .ss-inwrap .vx-lang { position: absolute; }
.ss-inwrap .vx-mic { right: 8px; bottom: 6px; width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center; color: var(--s-label-2); transition: background-color .2s, color .2s; }
.ss-inwrap .vx-mic .ic { position: relative; z-index: 1; }
.ss-inwrap .vx-mic.on { color: var(--s-tint); }
.ss-inwrap .vx-mic.listening { background: var(--s-tint); color: #fff; }
.ss-inwrap .vx-mic.listening .vx-ring { opacity: 1; inset: 0; box-shadow: 0 0 0 calc(3px + var(--lvl, 0) * 9px) rgba(10, 132, 255, .32); transition: box-shadow .09s linear; }
.ss-inwrap .vx-mic.busy .vx-ring { opacity: 1; inset: -3px; border: 2.5px solid transparent; border-top-color: var(--s-tint); animation: spin .8s linear infinite; }
.ss-inwrap .vx-lang { right: 56px; bottom: 11px; width: 40px; height: 32px; border-radius: 10px; display: none; font-size: 12px; background: var(--s-glass); box-shadow: none; }
.ss-inwrap.voice-on .vx-lang { display: grid; }
.ss-inwrap .vx-lang:active { transform: scale(.94); }
.ss-type .vx-status { margin-top: 2px; }

.lang-menu {
  position: absolute; z-index: 30; left: 50%; bottom: calc(100% + 12px); transform: translateX(-50%);
  width: min(330px, calc(var(--vw) * 92));
  background: var(--s-menu);
  -webkit-backdrop-filter: blur(30px) saturate(1.8); backdrop-filter: blur(30px) saturate(1.8);
  border-radius: 24px;
  box-shadow: var(--s-rim), var(--s-menu-shadow);
  padding: 10px;
  transform-origin: 50% 100%;
  animation: lang-in .32s var(--spring) both;
}
@keyframes lang-in { from { opacity: 0; scale: .8; } }
.ss-inwrap .lang-menu { left: auto; right: 0; transform: none; bottom: auto; top: calc(100% + 8px); transform-origin: 100% 0; }
.lang-menu-title { font-size: 13px; font-weight: 600; color: var(--s-label-2); padding: 4px 8px 8px; }
.lang-menu-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px; }
.lang-menu-grid button { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 14px; color: var(--s-text); text-align: left; font-size: 15px; }
.lang-menu-grid button b { font-size: 12px; width: 26px; color: var(--s-label-2); font-weight: 600; }
.lang-menu-grid button:active { background: var(--s-press); }
.lang-menu-grid button.on { background: color-mix(in srgb, var(--s-tint) 22%, transparent); }
.lang-menu-grid button.on b { color: var(--s-tint); }

/* Hint, feedback, mnemonic */
.ss-hintslot { display: flex; justify-content: center; min-height: 8px; }
.ss .link-btn { color: var(--s-link); font-size: 15px; }
.hint-box { display: inline-flex; align-items: center; gap: 10px; padding: 10px 16px; border-radius: 16px; background: var(--s-glass); box-shadow: var(--s-rim); font-family: var(--font-mono); font-size: 17px; letter-spacing: .08em; }
.hint-box .ic { color: var(--s-yellow); }
.ss-feedback { display: none; margin: 12px 0 4px; padding: 14px 16px; border-radius: 22px; background: var(--s-glass); box-shadow: var(--s-rim); animation: fb-in .34s var(--spring) both; }
@keyframes fb-in { from { opacity: 0; transform: translateY(8px) scale(.97); } }
.ss-feedback.show { display: block; }
.ss-feedback.ok { background: rgba(48, 209, 88, .14); box-shadow: inset 0 0 0 .5px rgba(48, 209, 88, .45); }
.ss-feedback.bad { background: rgba(255, 69, 58, .14); box-shadow: inset 0 0 0 .5px rgba(255, 69, 58, .45); }
.fb-head { display: flex; align-items: center; gap: 7px; font-weight: 700; font-size: 17px; }
.fb-head::before { content: ''; flex: none; width: 21px; height: 21px; background: currentColor; -webkit-mask: var(--m) center / contain no-repeat; mask: var(--m) center / contain no-repeat; }
.fb-head.ok { color: var(--green-text); --m: var(--i-ok); }
.fb-head.bad { color: var(--red-text); --m: var(--i-bad); }
.fb-row { display: grid; grid-template-columns: 96px 1fr; gap: 10px; margin-top: 9px; font-size: 16px; line-height: 1.35; }
.fb-lbl { color: var(--s-label-2); font-weight: 500; font-size: 13px; padding-top: 2px; }
.fb-val { overflow-wrap: anywhere; }
.fb-val b { font-weight: 600; }
.fb-val s { color: var(--s-label-2); text-decoration-color: rgba(255, 69, 58, .8); }
.chip { display: inline-block; margin: 0 6px 6px 0; padding: 3px 10px; border-radius: 99px; font-size: 14px; font-weight: 600; }
.chip.miss { background: rgba(255, 159, 10, .2); color: var(--orange-text); }
.chip.extra { background: rgba(255, 69, 58, .2); color: var(--red-text); }
.chip.also { background: rgba(48, 209, 88, .18); color: var(--green-text); }
.fb-override { margin-top: 10px; }
.fb-note { display: flex; gap: 8px; align-items: flex-start; margin-top: 10px; font-size: 14px; line-height: 1.4; color: var(--s-label-2); }
.fb-note .ic { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--s-yellow); }
.ss-mnemo { display: flex; justify-content: center; }
.mnemo-btn {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 10px; min-height: 40px; padding: 0 16px; border-radius: 99px;
  background: var(--s-glass); box-shadow: var(--s-rim);
  color: var(--s-yellow-text); font-weight: 600; font-size: 15px;
}
.mnemo-btn .ic { width: 17px; height: 17px; }
.mnemo-btn:active { background: var(--s-glass-2); }
.mnemo-box { display: flex; gap: 10px; margin-top: 10px; padding: 12px 14px; border-radius: 18px; background: rgba(255, 214, 10, .12); box-shadow: inset 0 0 0 .5px rgba(255, 214, 10, .3); font-size: 16px; line-height: 1.45; animation: fb-in .34s var(--spring) both; }
.mnemo-box .ic { color: var(--s-yellow); margin-top: 2px; }

/* The buttons stay at the bottom of the screen; over content that scrolls
   under them they are a bar of the stage's colour, fading out upwards —
   without it "Next" lay right across the lower answers of a multiple choice. */
.ss-actions {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; gap: 10px;
  /* Down to the screen's edge, through the view's bottom padding, and with
     the stage's glow of its own: ending 16 px above the edge, the flat bar
     left the view's glow showing under it as a light-blue line (the owner,
     2026-09-30). */
  margin: auto -16px calc(-1 * var(--view-pb)); padding: 22px 16px calc(var(--safe-b) + 14px + var(--view-pb));
  background:
    radial-gradient(130% 120% at 50% 125%, var(--s-glow-a), transparent 62%),
    linear-gradient(to top, var(--s-bg) 76%, transparent);
}
.ss-actions:empty { display: none; }
.ss-actions .btn { flex: 1; min-height: 54px; }
/* Typing on a touch screen (TrainView `typing`): the keyboard takes half the
   screen. The mascot, the mic row (language · mic · keyboard — not needed
   while typing) and its status make room; the word sits over a plain answer
   field right above the buttons, which sit right above the keyboard. */
.ss.typing .ss-mascot, .ss.typing .ss-voice, .ss.typing .vx-status { display: none; }
.ss.typing .ss-card { min-height: 0; padding: 6px 4px 14px; gap: 6px; }
.ss.typing .ss-heard { background: var(--fill-3); font-size: 19px; font-weight: 500; line-height: 24px; min-height: 0; }
.ss.typing .ss-heard:focus { box-shadow: inset 0 0 0 2px var(--s-tint); }
.ss.typing .ss-actions { padding: 12px 16px calc(12px + var(--view-pb)); }
.btn-stage { background: var(--s-cta); color: var(--s-cta-text); }
.btn-stage:disabled { opacity: .85; }
.btn-stage .spin { width: 17px; height: 17px; }
.btn-stage-ghost {
  flex: 0 1 auto !important; padding: 0 20px;
  background: var(--s-glass); color: var(--s-text); box-shadow: var(--s-rim);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
}
/* "Next" fills up while an automatic step is pending. */
.btn.auto::before { content: ''; position: absolute; inset: 0; z-index: -1; background: rgba(10, 132, 255, .3); transform-origin: left; animation: fill var(--auto-ms, 600ms) linear forwards; }
@keyframes fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Flashcards */
/* An index card, wider than high (3 : 2), in the middle of the free room
   (the owner's pick A of tools/drafts/flashcards-design.html, 2026-09-30). */
.fc-scene { flex: 1; display: flex; align-items: center; justify-content: center; perspective: 1400px; padding: 6px 0; }
.fc-swipe { position: relative; width: min(100%, 440px); aspect-ratio: 3 / 2; touch-action: pan-y; transition: transform .1s; }
.fc-swipe.dragging { transition: none; cursor: grabbing; }
.fc-swipe.spring { transition: transform .3s var(--spring); }
.fc-swipe.fly { transition: transform .32s ease-in, opacity .32s; }
.fc-flip { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform .6s var(--ease); cursor: pointer; }
.fc-flip.flipped { transform: rotateY(180deg); }
.fc-face {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 22px; text-align: center;
  border-radius: 28px;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: #fff; color: #000;
  box-shadow: var(--s-card-shadow);
}
.fc-face.back { transform: rotateY(180deg); background: linear-gradient(180deg, #F5F9FF, #E4EFFF); }
.fc-face .ss-tag { position: absolute; top: 12px; right: 14px; background: rgba(255, 149, 0, .14); color: #C93400; }
.fc-lang { position: absolute; top: 17px; left: 20px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: rgba(60, 60, 67, .55); }
.fc-small { max-width: 100%; font-size: 15px; font-weight: 600; color: rgba(60, 60, 67, .6); overflow-wrap: anywhere; }
.fc-text { font-weight: 700; font-size: clamp(26px, calc(var(--vw) * 8.4), 34px); line-height: 1.14; max-width: 100%; }
.fc-text.long { font-size: clamp(21px, calc(var(--vw) * 6.6), 27px); line-height: 1.15; }
.fc-text.longer { font-size: clamp(17px, calc(var(--vw) * 5), 21px); line-height: 1.2; }
.fc-hint { position: absolute; bottom: 12px; left: 16px; right: 16px; font-size: 12px; color: rgba(60, 60, 67, .5); font-weight: 500; }
.fc-stamp { position: absolute; top: 18px; width: 58px; height: 58px; border-radius: 50%; display: grid; place-items: center; opacity: 0; pointer-events: none; color: #fff; box-shadow: 0 8px 20px rgba(0, 0, 0, .25); }
.fc-stamp .ic { width: 30px; height: 30px; stroke-width: 3; }
.fc-stamp.yes { right: 18px; background: #34C759; }
.fc-stamp.no { left: 18px; background: #FF3B30; }
/* The bar: "Turn over", then the two verdict buttons in its place; under it
   the mnemonic, whose room is kept from the start — nothing moves. */
.fc-bar { flex-direction: column; align-items: stretch; gap: 8px; padding-top: 14px; }
.fc-mn { display: flex; justify-content: center; height: 40px; }
.fc-mn .mnemo-btn { margin: 0; visibility: hidden; opacity: 0; transition: opacity .25s; }
.fc-mn.on .mnemo-btn { visibility: visible; opacity: 1; }
.fc-grade { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.fc-grade .btn { min-height: 54px; padding: 0 12px; }
.ss-sheet .fc-grade { margin-top: 16px; }
.fc-grade .ic { stroke-width: 2.6; }
.fc-bad { background: rgba(255, 69, 58, .2); color: var(--red-text); }
.fc-good { background: rgba(48, 209, 88, .2); color: var(--green-text); }

/* Multiple choice */
.mc-options { display: grid; gap: 10px; margin-top: 4px; }
/* Multiple choice on a small phone (the LG: 360 × 680): the card only grows
   into room there is and the mascot is smaller, so the word and all four
   answers fit; after a wrong pick the right answer is scrolled above the
   buttons (TrainView, scroll-margin). */
.ss-choice .ss-mascot { height: clamp(110px, 16vh, 170px); }
.ss-choice .ss-card { flex: 1 0 auto; min-height: 0; padding: 10px 4px 16px; }
.ss-choice .mc-opt { scroll-margin-bottom: calc(var(--safe-b) + 100px); }
/* The bar is there from the start: "I don't know", then "Next" (+ the bulb). */
.ss-choice .ss-actions { padding-top: 12px; }
.ss-choice .mc-go { flex: 1 1 auto !important; }
.mc-bulb { flex: none; width: 54px; height: 54px; border-radius: 50%; display: grid; place-items: center; background: var(--s-glass); box-shadow: var(--s-rim); color: var(--orange-text); }
.mc-bulb[hidden] { display: none; }
.mc-bulb .ic { width: 22px; height: 22px; }
.mc-bulb:active { transform: scale(.94); }
/* Type / Speak: the word stays right under Voki, the free room is above the
   buttons — the result sheet covers only that, word and answer stay in view. */
.ss-type .ss-card, .ss-speak .ss-card { flex: 0 0 auto; min-height: 0; padding: 14px 4px 18px; }
/* The read-aloud switch in the top bar (every mode), tinted while on. */
.ss-top .say-top.on { background: var(--s-tint); color: #fff; box-shadow: 0 6px 18px rgba(10, 132, 255, .35); }
.ss-top .say-top.on.busy { animation: say-pulse-on 1s ease-in-out infinite; }
/* The result sheet (TrainView newSheet / openSheet): up from the bottom over
   the page — red / green with the result, yellow with the mnemonic. It sits
   40 px lower than it looks, so the spring's overshoot shows no gap. */
.ss-sheet {
  position: fixed; left: var(--app-x); right: var(--app-x); bottom: -40px; z-index: 40;
  max-width: 620px; margin: 0 auto;
  padding: 18px 18px calc(var(--safe-b) + 56px);
  border-radius: 26px 26px 0 0;
  background: var(--s-bg); box-shadow: 0 -12px 34px -14px rgba(0, 0, 0, .35);
  transform: translateY(105%); visibility: hidden;
  transition: transform .42s var(--spring), visibility 0s linear .42s;
}
.ss-sheet.on { transform: none; visibility: visible; transition: transform .42s var(--spring); }
/* The round is over (TrainView finish): its last card leaves — the bar, the
   word, the sheet —, only the mascot stays where it stands; the result page
   takes it over there and celebrates around it. */
.ss.leaving .ss-top, .ss.leaving .ss-body { opacity: 0; pointer-events: none; transition: opacity .26s ease; }
.ss.leaving .ss-sheet { transform: translateY(105%); pointer-events: none; transition: transform .3s var(--ease); }
.ss-sheet:has(.ss-feedback.bad) { background: color-mix(in srgb, var(--s-bg) 84%, var(--red)); }
.ss-sheet:has(.ss-feedback.ok) { background: color-mix(in srgb, var(--s-bg) 82%, var(--green)); }
.ss-sheet[data-kind="tip"] { background: color-mix(in srgb, var(--s-bg) 84%, #FFD60A); }
.ss-sheet .ss-feedback { margin: 0; padding: 0; background: none; box-shadow: none; animation: none; }
.ss-sheet .vx-status { margin-top: 10px; text-align: left; }
.ss-sheet .vx-status:empty { display: none; }
.ss-sheet-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 14px; }
.ss-sheet-tools:empty { display: none; }
.ss-sheet .mnemo-btn { margin-top: 0; min-height: 36px; }
.ss-sheet-tools .ss-mnemo:has(.mnemo-box) { flex-basis: 100%; }
.ss-sheet .mnemo-box { margin-top: 2px; }
.ss-sheet > .ss-mnemo { margin-top: 12px; }
.ss-sheet-next { margin-top: 16px; }
.ss-sheet-next .btn { width: 100%; min-height: 54px; }
.ss-sheet .fb-head.tip { color: var(--orange-text); gap: 8px; }
.ss-sheet .fb-head.tip::before { content: none; }
.ss-sheet .fb-head.tip .ic { width: 20px; height: 20px; }
.mc-opt {
  display: flex; align-items: center; gap: 14px;
  width: 100%; min-height: 60px; padding: 12px 16px;
  border-radius: 20px; text-align: left;
  background: var(--s-glass); box-shadow: var(--s-rim); color: var(--s-text);
  font-size: 17px; font-weight: 500;
  transition: background-color .2s, box-shadow .2s, transform .25s var(--spring);
  animation: card-in .36s var(--ease) both;
}
.mc-opt:nth-child(2) { animation-delay: .04s; }
.mc-opt:nth-child(3) { animation-delay: .08s; }
.mc-opt:nth-child(4) { animation-delay: .12s; }
.mc-opt:active:not(:disabled) { transform: scale(.98); background: var(--s-glass-2); }
@media (hover: hover) { .mc-opt:hover:not(:disabled) { background: var(--s-glass-2); } }
.mc-opt > span:last-child { min-width: 0; overflow-wrap: anywhere; -webkit-hyphens: auto; hyphens: auto; }
.mc-key { flex: none; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--s-mc-key); font-size: 14px; font-weight: 700; color: var(--s-label-2); font-variant-numeric: tabular-nums; }
.mc-opt.right { background: rgba(48, 209, 88, .2); box-shadow: inset 0 0 0 1.5px rgba(48, 209, 88, .85); }
.mc-opt.right .mc-key { background: var(--s-green); color: #fff; }
.mc-opt.wrong { background: rgba(255, 69, 58, .18); box-shadow: inset 0 0 0 1.5px rgba(255, 69, 58, .8); animation: shake .36s; }
.mc-opt.wrong .mc-key { background: var(--s-red); color: #fff; }
.mc-opt:disabled:not(.right):not(.wrong) { opacity: .45; }

/* Reading aloud (tts.js): a round speaker button under the word, a labelled
   one under a wrong answer's solution, one in the corner of each flashcard
   face. It pulses while the clip loads and plays. */
.say-btn {
  flex: none; width: 44px; height: 44px; border-radius: 50%;
  display: inline-grid; place-items: center;
  color: var(--s-link); background: var(--s-glass); box-shadow: var(--s-rim);
  transition: transform .25s var(--spring), background-color .2s;
}
.say-btn .ic { width: 22px; height: 22px; stroke-width: 2; }
.say-btn:active { transform: scale(.9); }
.say-btn.busy { animation: say-pulse 1s ease-in-out infinite; }
@keyframes say-pulse { 50% { background: rgba(10, 132, 255, .3); } }
.say-btn.labeled { width: auto; height: 36px; padding: 0 14px 0 10px; gap: 6px; display: inline-flex; align-items: center; border-radius: 99px; font-size: 15px; font-weight: 600; }
.say-btn.labeled .ic { width: 19px; height: 19px; }
.ss-again.on { background: var(--tint); color: #FFF; }   /* the round's microphone listens for the repeat */
.fb-say { margin-top: 10px; }
/* The switch on the card: tinted while on, a struck-through speaker while off. */
.say-btn.toggle { color: var(--s-label-2); }
.say-btn.toggle.on { background: var(--s-tint); color: #fff; box-shadow: 0 6px 18px rgba(10, 132, 255, .4); }
.say-btn.toggle.on.busy { animation: say-pulse-on 1s ease-in-out infinite; }
@keyframes say-pulse-on { 50% { box-shadow: 0 0 0 8px rgba(10, 132, 255, .25), 0 6px 18px rgba(10, 132, 255, .4); } }
.fc-face .say-btn { position: absolute; top: 14px; right: 14px; background: rgba(0, 0, 0, .06); box-shadow: none; color: #0A84FF; }
.fc-face .say-btn.toggle { color: rgba(60, 60, 67, .5); }
.fc-face .say-btn.toggle.on { background: #0A84FF; color: #fff; box-shadow: none; }
.fc-face .say-btn.busy { animation-name: say-pulse-light; }
@keyframes say-pulse-light { 50% { background: rgba(10, 132, 255, .18); } }

/* Rewards (cheer.js decides, cheerFx.js draws): the word or option springs
   and flashes green, a check mark draws itself, the run counter in the top
   bar bumps, particles and a glow play on a layer over the column, a badge
   under the top bar for the big moments. */
.fb-head.ok::before { content: none; }
.fx-check { flex: none; width: 21px; height: 21px; overflow: visible; }
.fx-check circle { fill: currentColor; transform-box: fill-box; transform-origin: center; animation: check-pop .42s var(--spring) both; }
.fx-check path { fill: none; stroke: #0B2913; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 14; stroke-dashoffset: 14; animation: check-draw .26s .16s ease-out forwards; }
@keyframes check-pop { from { opacity: 0; transform: scale(.2); } }
@keyframes check-draw { to { stroke-dashoffset: 0; } }
.mc-key .fx-check { width: 30px; height: 30px; }
.mc-key .fx-check circle { fill: var(--s-green); }
.mc-key .fx-check path { stroke: #fff; }

.ss-word.hit { animation: word-hit .6s var(--spring); }
@keyframes word-hit { 35% { transform: scale(1.08); color: var(--s-hit); text-shadow: 0 0 26px rgba(48, 209, 88, .55); } }
.mc-opt.right.hit { animation: opt-hit .5s var(--spring); }
@keyframes opt-hit { 35% { transform: scale(1.04); box-shadow: inset 0 0 0 1.5px rgba(48, 209, 88, .85), 0 0 28px rgba(48, 209, 88, .45); } }
.fc-stamp.pop { animation: stamp-pop .35s var(--spring); }
@keyframes stamp-pop { from { transform: scale(.4); } }

.ss-combo {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  height: 28px; padding: 0 8px 0 6px; border-radius: 99px;
  background: rgba(255, 159, 10, .18); box-shadow: inset 0 0 0 .5px rgba(255, 159, 10, .4);
  color: var(--s-combo); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
  transition: background-color .3s, color .3s, box-shadow .3s;
}
.ss-combo .ic { width: 14px; height: 14px; }
.ss-combo.bump { animation: combo-bump .45s var(--spring); }
@keyframes combo-bump { 30% { transform: scale(1.22); } }
.ss-combo.hot { background: linear-gradient(135deg, #FF9F0A, #FF375F); color: #fff; box-shadow: 0 0 18px rgba(255, 69, 58, .45); }
.ss-combo.lost { animation: combo-lost .6s ease-in forwards; }
@keyframes combo-lost {
  20%, 60% { transform: translateX(-4px); }
  40%, 80% { transform: translateX(4px); }
  100% { transform: scale(.7); opacity: 0; filter: grayscale(1); }
}

.fx-layer { position: fixed; top: 0; bottom: 0; left: var(--app-x); right: var(--app-x); z-index: 60; pointer-events: none; overflow: hidden; }
.fx-layer.out { opacity: 0; transition: opacity .24s ease; }   /* the round's stage leaves (cheerFx leave) */
.fx-confetti { display: block; width: 100%; height: 100%; }   /* confetti.js: the result page's canvas */
.fx-tick { display: none; }
.fx-p {
  position: absolute; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%;
  background: var(--c);
  animation: fx-spark var(--ms) cubic-bezier(.15, .7, .3, 1) forwards;
}
.fx-p.spark { box-shadow: 0 0 8px var(--c); }
@keyframes fx-spark {
  from { transform: translate(0, 0) scale(var(--s)); }
  to { transform: translate(var(--dx), var(--dy)) scale(0); opacity: 0; }
}
/* Confetti flies out fast, then tumbles down. */
.fx-p.confetti { width: 9px; height: 5px; margin: -2.5px 0 0 -4.5px; border-radius: 1.5px; animation-name: fx-confetti; animation-timing-function: linear; }
@keyframes fx-confetti {
  0% { transform: translate(0, 0) rotate(0) scale(var(--s)); animation-timing-function: cubic-bezier(.1, .7, .3, 1); }
  45% { transform: translate(var(--dx), var(--dy)) rotate(calc(var(--r) * .5)) scale(var(--s)); animation-timing-function: ease-in; }
  100% { transform: translate(calc(var(--dx) * 1.15), calc(var(--dy) + 150px)) rotate(var(--r)) scale(var(--s)); opacity: 0; }
}
.fx-p.star {
  width: 15px; height: 15px; margin: -7.5px 0 0 -7.5px; border-radius: 0;
  clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  animation-name: fx-star;
}
@keyframes fx-star {
  from { transform: translate(0, 0) scale(.2) rotate(0); }
  60% { opacity: 1; }
  to { transform: translate(var(--dx), var(--dy)) scale(var(--s)) rotate(calc(var(--r) * .4)); opacity: 0; }
}
.fx-ring { position: absolute; width: 60px; height: 60px; margin: -30px 0 0 -30px; border-radius: 50%; box-shadow: 0 0 0 2px rgba(48, 209, 88, .8); animation: fx-ring .55s ease-out forwards; }
@keyframes fx-ring { from { transform: scale(.6); opacity: 1; } to { transform: scale(3.2); opacity: 0; } }
/* The stage's floor lights up green (gold for a mastered word). */
.fx-glow {
  position: absolute; inset: 0; opacity: 0; mix-blend-mode: var(--s-glow-blend);
  background: radial-gradient(110% 50% at 50% 108%, rgba(48, 209, 88, .55), transparent 66%);
  animation: fx-glow .9s ease-out forwards;
}
.fx-glow.soft { --peak: .6; animation-duration: .7s; }
.fx-glow.gold { background: radial-gradient(120% 60% at 50% 108%, rgba(255, 214, 10, .6), transparent 68%); }
@keyframes fx-glow { 25% { opacity: var(--peak, 1); } }
.fx-badge {
  position: absolute; left: 50%; top: calc(var(--safe-t) + 68px);
  display: flex; align-items: center; gap: 10px;
  max-width: calc(100% - 32px); padding: 9px 18px 9px 10px; border-radius: 99px;
  background: var(--s-badge); color: var(--s-text);
  -webkit-backdrop-filter: blur(24px) saturate(1.8); backdrop-filter: blur(24px) saturate(1.8);
  box-shadow: var(--s-badge-shadow);
  transform: translateX(-50%);
  animation: badge-in .5s var(--spring) backwards;
  transition: opacity .3s, transform .35s var(--ease);
}
@keyframes badge-in { from { opacity: 0; transform: translateX(-50%) translateY(-18px) scale(.8); } }
.fx-badge.out { opacity: 0; transform: translateX(-50%) translateY(-10px) scale(.96); }
.fx-badge .ic { flex: none; width: 32px; height: 32px; padding: 7px; border-radius: 50%; background: #30D158; color: #fff; stroke-width: 2.4; }
.fx-badge > span { display: flex; flex-direction: column; min-width: 0; }
.fx-badge b { font-size: 17px; line-height: 21px; font-weight: 700; white-space: nowrap; }
.fx-badge small { font-size: 13px; line-height: 17px; color: var(--s-label-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-badge.surprise .ic { background: linear-gradient(135deg, #BF5AF2, #0A84FF); }
.fx-badge.milestone .ic { background: linear-gradient(135deg, #FF9F0A, #FF375F); }
.fx-badge.mastered .ic { background: linear-gradient(135deg, #FFD60A, #FF9F0A); }
.fx-badge.mastered { box-shadow: inset 0 0 0 1px rgba(255, 214, 10, .45), 0 0 34px rgba(255, 214, 10, .28), var(--s-badge-shadow); }
.fx-badge.goal .ic { background: #0A84FF; }

/* ─── Statistics (AdminView, the owner's page) ──────────────────────────────── */
.admin .adm-range { display: flex; width: 100%; margin: 4px 0 16px; }
.admin .adm-range button { flex: 1; }
.adm-hero { padding: 18px 20px; margin-bottom: 12px; display: flex; flex-direction: column; gap: 2px; }
.adm-hero small { font-size: 13px; font-weight: 600; color: var(--label-2); text-transform: uppercase; letter-spacing: .02em; }
.adm-hero b { font-size: 44px; line-height: 50px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.adm-hero span { font-size: 15px; color: var(--label-2); }
.adm-stats { margin-bottom: 8px; }
.adm-stats .stat b { font-size: 22px; font-variant-numeric: tabular-nums; }
.adm-feat .row-txt { gap: 6px; }
.adm-bar { display: block; height: 6px; border-radius: 99px; background: var(--fill-3); overflow: hidden; }
.adm-bar i { display: block; height: 100%; border-radius: 99px; background: var(--tint); }
.adm-val { flex: none; margin-left: 12px; font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.adm-count { font-weight: 400; color: var(--label-2); }
/* Cost per day: one series in the accent colour; bars sit on the baseline
   with rounded tops and a 2 px gap; the line above names the tapped bar. */
.adm-chart { padding: 14px 14px 10px; }
.adm-tip { min-height: 20px; margin-bottom: 8px; font-size: 14px; font-weight: 600; color: var(--label-2); font-variant-numeric: tabular-nums; }
.adm-bars { display: flex; align-items: flex-end; gap: 2px; height: 120px; border-bottom: 1px solid var(--sep); }
.adm-day { flex: 1; min-width: 0; height: 100%; display: flex; align-items: flex-end; padding: 0; cursor: pointer; }
.adm-day i { display: block; width: 100%; border-radius: 4px 4px 0 0; background: var(--tint); opacity: .85; transition: opacity .15s; }
.adm-day.on i, .adm-day:hover i { opacity: 1; box-shadow: 0 0 0 2px color-mix(in srgb, var(--tint) 30%, transparent); }
.adm-axis { display: flex; justify-content: space-between; margin-top: 6px; font-size: 12px; color: var(--label-3); font-variant-numeric: tabular-nums; }
.adm-user summary { list-style: none; cursor: pointer; }
.adm-user summary::-webkit-details-marker { display: none; }
.adm-user[open] summary .row-txt b { color: var(--tint); }
.adm-detail { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; padding: 4px 16px 14px; }
.adm-detail div { display: flex; flex-direction: column; min-width: 0; }
.adm-detail span { font-size: 12px; color: var(--label-2); }
.adm-detail b { font-size: 16px; font-variant-numeric: tabular-nums; }
.adm-detail small { font-size: 12px; color: var(--label-3); }
.adm-empty { padding: 24px 8px; text-align: center; color: var(--label-2); }
/* The statistics' building blocks (2026-09-26): notes under a section, empty lists, facts */
.adm-sub { margin: 6px 16px 0; font-size: 12px; line-height: 16px; color: var(--label-3); }
.adm-none { color: var(--label-3); font-size: 15px; }
.adm-fact .row-txt small { white-space: normal; }
.adm-feat .row-txt small { font-size: 12px; color: var(--label-3); }
.admin .adm-stats + .adm-stats { margin-top: -2px; }
.adm-note { margin: 18px 8px 0; font-size: 12px; color: var(--label-3); }

/* ─── Alerts, menus & sheets ──────────────────────────────────────────────── */
/* The page scrolls underneath, so a swipe on the backdrop must not reach it
   and the panel keeps its own scrolling to itself. */
.layer {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: transparent;
  transition: background-color .25s;
  touch-action: none;
  overscroll-behavior: contain;
}
.layer.open { background: var(--dim); }
.layer.closing { background: transparent; }
.layer-panel {
  width: min(100%, 300px);
  max-height: calc(100% - 20px); overflow-y: auto;
  touch-action: pan-y; overscroll-behavior: contain;
  background: var(--glass-thick); color: var(--label);
  -webkit-backdrop-filter: blur(40px) saturate(1.8); backdrop-filter: blur(40px) saturate(1.8);
  border-radius: 34px;
  padding: 22px 16px 16px;
  box-shadow: var(--glass-rim), 0 24px 70px rgba(0, 0, 0, .28);
  animation: dlg-in .4s var(--spring) both;
}
.layer.closing .layer-panel { animation: dlg-out .2s ease-in both; }
@keyframes dlg-in { from { opacity: 0; transform: scale(1.12); } }
@keyframes dlg-out { to { opacity: 0; transform: scale(.96); } }
.dlg-art .mascot { margin: -4px auto 2px; }
.dlg-title { font-size: 17px; line-height: 22px; font-weight: 600; text-align: center; margin: 0 6px 4px; overflow-wrap: anywhere; }
.dlg-msg { font-size: 15px; line-height: 1.35; text-align: center; margin: 0 6px 2px; }
.dlg-form { margin-top: 16px; }
.layer .field { margin-bottom: 12px; }
.layer .field-label { text-transform: none; padding: 0 8px; font-size: 13px; }
.layer .input { background: var(--bg-2); }
/* "Report a problem" (ui.js reportDialog): the usual cases as a list to pick
   one from, a field for one's own words. A little wider than a dialog. */
.layer-report, .layer-word { padding: 16px 12px; }
.layer-report .layer-panel, .layer-word .layer-panel { width: min(100%, 350px); padding: 20px 14px 14px; }
.layer-report .dlg-actions, .layer-word .dlg-actions { margin-top: 14px; }
/* "Edit word" (ui.js wordDialog): the two sides in one card, each under its
   language, as in the editor — long ones wrap. */
.ew-group { border-radius: 16px; background: var(--bg-2); overflow: hidden; }
.ew-row { position: relative; display: block; padding: 9px 14px 8px; cursor: text; }
.ew-row + .ew-row::before { content: ''; position: absolute; top: 0; left: 14px; right: 0; border-top: .5px solid var(--sep); }
.ew-row:focus-within { background: color-mix(in srgb, var(--tint) 7%, var(--bg-2)); }
.ew-lbl { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--label-3); }
.ew-in { display: block; width: 100%; margin-top: 1px; padding: 0; border: 0; outline: none; resize: none; overflow: hidden; background: none; color: var(--label);
  font: inherit; font-size: 17px; line-height: 23px; overflow-wrap: anywhere; caret-color: var(--tint); }
.ew-row:first-child .ew-in { font-weight: 600; }
.rep-context { margin: 2px 6px 0; text-align: center; font-size: 14px; color: var(--label-2); overflow-wrap: anywhere; }
.rep-form { margin-top: 12px; }
.rep-list { display: flex; flex-direction: column; border-radius: 16px; background: var(--bg-2); overflow: hidden; }
.rep-opt { position: relative; display: flex; align-items: center; gap: 11px; min-height: 42px; padding: 7px 14px; font-size: 15px; line-height: 1.3; cursor: pointer; }
.rep-opt + .rep-opt::before { content: ''; position: absolute; top: 0; left: 46px; right: 0; border-top: .5px solid var(--sep); }
.rep-opt input { position: absolute; opacity: 0; pointer-events: none; }
.rep-dot { flex: none; width: 21px; height: 21px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--label-3); transition: box-shadow .2s; }
.rep-opt input:checked + .rep-dot { box-shadow: inset 0 0 0 6.5px var(--tint); }
.rep-opt:has(input:focus-visible) { background: var(--fill-3); }
.layer-report textarea.rep-note { display: block; width: 100%; margin-top: 10px; min-height: 64px; height: 64px; padding: 10px 14px; resize: none; border-radius: 14px; font: inherit; font-size: 16px; line-height: 1.35; }   /* over textarea.input (the paste field: 200 px, monospace) */
.rep-hint { margin: 8px 6px 0; font-size: 12.5px; line-height: 1.35; color: var(--label-2); }
.adm-report { display: block; }
.adm-report > div { display: grid; grid-template-columns: 96px 1fr; gap: 10px; padding: 3px 0; font-size: 14.5px; }
.adm-report > div span { color: var(--label-2); }
.adm-report > div b { font-weight: 500; overflow-wrap: anywhere; }
.dlg-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
/* each button at least as wide as its words: two long ones stack instead of being cut ("Weiter bearbeiten", "Endgültig löschen" — the test report) */
.dlg-actions .btn { flex: 1 1 0; min-width: max-content; max-width: 100%; min-height: 48px; padding: 0 16px; }
.dlg-actions .btn-ghost { background: var(--fill-3); color: var(--label); }
.dlg-actions .btn-ghost:active:not(:disabled) { opacity: 1; background: var(--fill); }
.dlg-actions .btn-danger { background: var(--fill-3); color: var(--red); }
.dlg-actions .btn-danger:active:not(:disabled) { background: var(--fill); }
.dlg-actions .dlg-extra { order: 3; flex-basis: 100%; min-height: 40px; background: none; }
/* keep (confirmDialog): staying is the main button, on the right */
.dlg-actions.keep [data-no] { order: 2; flex-grow: 1.45; }

/* A menu next to the button that opened it (actionSheet with an anchor):
   no dimming, it grows out of the button. */
.layer-menu { display: block; padding: 0; }
.layer-menu.open { background: transparent; }
.layer-menu .layer-panel {
  position: absolute; width: 270px; max-width: calc(100% - 24px); max-height: calc(100% - 24px);
  padding: 6px 0; border-radius: 24px;
  box-shadow: var(--glass-rim), 0 14px 50px rgba(0, 0, 0, .18), 0 2px 8px rgba(0, 0, 0, .08);
  animation: menu-in .38s var(--spring) both;
}
.layer-menu.closing .layer-panel { animation: menu-out .18s ease-in both; }
@keyframes menu-in { from { opacity: 0; transform: scale(.35); } }
@keyframes menu-out { to { opacity: 0; transform: scale(.8); } }
.layer-menu .sheet-title { padding: 8px 18px 8px; font-size: 13px; font-weight: 400; color: var(--label-2); text-align: left; white-space: normal; border-bottom: .5px solid var(--sep); }
.layer-menu .sheet-list { gap: 0; }
.layer-menu .sheet-item { gap: 12px; min-height: 46px; padding: 11px 18px; border-radius: 0; }
.layer-menu .sheet-item + .sheet-item { border-top: .5px solid var(--sep); }
.layer-menu .sheet-item:active { background: var(--fill-3); }
.layer-menu .sheet-ic { order: 2; width: 22px; height: 22px; background: none; color: var(--label); }
.layer-menu .sheet-ic .ic { width: 20px; height: 20px; }
.layer-menu .sheet-txt { flex: 1; }
.layer-menu .sheet-txt b { font-weight: 400; font-size: 17px; line-height: 22px; }
.layer-menu .sheet-txt small { font-size: 13px; line-height: 17px; margin-top: 1px; }
.layer-menu .sheet-item.danger .sheet-ic { background: none; color: var(--red); }

/* Without an anchor: a floating sheet from the bottom */
.layer-sheet { align-items: flex-end; padding: 0 8px calc(var(--safe-b) + 8px); }
.layer-sheet .layer-panel {
  width: min(100%, 520px);
  border-radius: 34px;
  padding: 8px 8px 8px;
  animation: sheet-in .45s var(--ease) both;
}
.layer-sheet.closing .layer-panel { animation: sheet-out .24s ease-in both; }
@keyframes sheet-in { from { transform: translateY(110%); } }
@keyframes sheet-out { to { transform: translateY(110%); } }
.sheet-grip { width: 36px; height: 5px; border-radius: 99px; background: var(--label-4); margin: 0 auto 6px; }
.sheet-title { font-weight: 600; font-size: 15px; color: var(--label-2); text-align: center; padding: 4px 12px 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-list { display: flex; flex-direction: column; gap: 2px; }
.sheet-item { display: flex; align-items: center; gap: 14px; width: 100%; padding: 10px 12px; border-radius: 22px; text-align: left; transition: background-color .2s; }
.sheet-item:active { background: var(--fill-3); }
.sheet-ic { width: 40px; height: 40px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--tint-soft); color: var(--tint); }
.sheet-ic .ic { width: 21px; height: 21px; }
.sheet-txt { display: flex; flex-direction: column; min-width: 0; }
.sheet-txt b { font-weight: 600; font-size: 17px; }
.sheet-txt small { font-size: 13px; color: var(--label-2); }
.sheet-item.danger .sheet-ic { background: color-mix(in srgb, var(--red) 14%, transparent); color: var(--red); }
.sheet-item.danger b { color: var(--red); }
.sheet-cancel { margin-top: 6px; background: var(--fill-3); color: var(--label); }

/* checklistDialog: selection circles, as in a list in edit mode */
.check-list { display: flex; flex-direction: column; margin: 16px 0 0; background: var(--bg-2); border-radius: 20px; overflow: hidden; }
.check-row { position: relative; display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 10px 16px; cursor: pointer; transition: background-color .2s; }
.check-row + .check-row::before { content: ''; position: absolute; top: 0; left: 52px; right: 0; border-top: .5px solid var(--sep); }
.check-row:active { background: var(--press); transition: none; }
.check-row input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.check-box {
  flex: none; width: 24px; height: 24px; display: grid; place-items: center;
  border: 1.5px solid var(--gray3); border-radius: 50%;
  color: transparent; transition: background-color .15s, border-color .15s, color .15s;
}
.check-box .ic { width: 14px; height: 14px; stroke-width: 3; }
.check-row input:checked + .check-box { background: var(--tint); border-color: var(--tint); color: #fff; }
.check-row input:focus-visible + .check-box { outline: 3px solid color-mix(in srgb, var(--tint) 55%, transparent); outline-offset: 2px; }
.check-txt { display: flex; flex-direction: column; min-width: 0; }
.check-txt b { font-weight: 400; font-size: 17px; line-height: 22px; overflow-wrap: anywhere; }
.check-txt small { font-size: 13px; color: var(--label-2); }

/* ─── Toast ───────────────────────────────────────────────────────────────── */
/* A glass capsule above the tab bar, like the undo banners in Mail */
.toast {
  position: fixed; left: 50%; z-index: 200;
  bottom: calc(var(--tabbar-b) + var(--tabbar-h) + 14px);
  transform: translate(-50%, 14px) scale(.96);
  display: flex; align-items: center; gap: 14px;
  width: max-content; max-width: min(calc(var(--vw) * 92), 440px);
  min-height: 48px; padding: 12px 20px;
  border-radius: 24px;
  background: var(--glass-thick); color: var(--label);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--glass-rim), var(--glass-lift);
  font-size: 15px; font-weight: 500; line-height: 1.35;
  opacity: 0; pointer-events: none;
  transition: opacity .22s, transform .4s var(--spring);
}
body.no-tabbar .toast { bottom: calc(var(--safe-b) + 96px); }
.toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast.error { color: var(--red-text); }
.toast-action { flex: none; min-height: 40px; margin: -6px -10px -6px 0; padding: 0 14px; border-radius: 99px; color: var(--tint); font-weight: 600; background: color-mix(in srgb, var(--tint) 14%, transparent); }   /* a capsule big enough to hit (the test report: a click on the small "Plus" missed) */
.toast-action:active { opacity: .5; }

/* The iOS activity indicator: eight spokes turning in steps */
.spin {
  display: inline-block; flex: none; width: 20px; height: 20px;
  background: currentColor;
  -webkit-mask: var(--i-spinner) center / contain no-repeat; mask: var(--i-spinner) center / contain no-repeat;
  animation: spin .9s steps(8) infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ─── Page scanner (cropImage.js) ───────────────────────────────────────────
   In the app's look, light or dark (the owner's pick of tools/drafts/crop-design.html,
   2026-09-29): a glass close button and a title, Voki saying what to do, the
   photo as a rounded card with a veil of the background outside the corners,
   the frame and the corners in the tint, capsules under it and "Apply". */
.crop-overlay { position: fixed; inset: 0; z-index: 9999; display: flex; flex-direction: column; padding: calc(var(--safe-t) + 8px) 16px 0; background: var(--bg); color: var(--label); touch-action: none; user-select: none; -webkit-user-select: none; }
.crop-overlay .is-hidden { display: none !important; }
.crop-topbar { display: flex; align-items: center; gap: 12px; min-height: 48px; }
.crop-topbar .icon-btn { flex: none; }
.crop-title { flex: 1; min-width: 0; margin-right: 56px; text-align: center; font-size: 17px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crop-say { display: flex; align-items: center; gap: 10px; margin: 8px 2px 4px; }
.crop-voki { width: 54px; height: 54px; flex: none; }
.crop-voki .mascot { width: 100%; height: 100%; }
.crop-bubble { position: relative; padding: 10px 14px; border-radius: 18px; background: var(--bg-2); font-size: 15px; line-height: 1.35; box-shadow: 0 6px 16px -10px rgba(0, 0, 0, .35); }
.crop-bubble::before { content: ''; position: absolute; left: -6px; top: 50%; width: 14px; height: 14px; margin-top: -7px; background: inherit; transform: rotate(45deg); border-radius: 3px; }
.crop-stage { position: relative; flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; padding: 16px 6px; }
.crop-image-wrap { position: relative; flex: none; border-radius: 18px; touch-action: none; box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .55), 0 1px 3px rgba(0, 0, 0, .12); }   /* sized by layout(); never squeezed */
.crop-image { display: block; width: 100%; height: 100%; border-radius: inherit; pointer-events: none; -webkit-user-drag: none; }
.crop-mask { position: absolute; inset: 0; border-radius: inherit; background: color-mix(in srgb, var(--bg) 74%, transparent); pointer-events: none; }
.crop-quad { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.crop-quad polygon { fill: none; stroke: var(--tint); stroke-width: 2.5; stroke-linejoin: round; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .35)); }
.crop-handle { position: absolute; width: 26px; height: 26px; margin: -13px 0 0 -13px; border-radius: 50%; background: #fff; touch-action: none; cursor: grab;
  box-shadow: 0 0 0 3.5px var(--tint), 0 4px 12px rgba(0, 0, 0, .35); transition: transform .2s var(--spring); }
.crop-handle::before { content: ''; position: absolute; inset: -13px; border-radius: 50%; }   /* a finger-sized grip */
.crop-handle.on { transform: scale(1.18); cursor: grabbing; }
.crop-foot { padding: 4px 0 calc(var(--safe-b) + 20px); }
.crop-tools { display: flex; gap: 10px; margin-bottom: 12px; }
.crop-tools .btn { flex: 1; }

/* ─── Phone column ────────────────────────────────────────────────────────────
   Vocabuapp is a phone app. In a wider window — a desktop browser, a tablet,
   a phone on its side — it stays a phone-wide column in the middle with the
   same layout, line breaks and type sizes as on an iPhone (--vw is 1 % of the
   column there, not of the window). Everything fixed to the window keeps to
   the column: the tab bar, dialogs and sheets, the scanner, the pick bar; the
   toasts are narrower than it anyway. A dialog's dimming still covers the
   whole window, so a click beside the column closes it as before. */
@media (min-width: 501px) {
  :root {
    --vw: calc(var(--app-w) / 100);
    --app-x: calc(50% - var(--app-w) / 2);   /* column edge, for fixed elements */
  }
  html {
    background: var(--backdrop);
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--label-3) 60%, transparent) transparent;
  }
  body {
    width: var(--app-w);
    margin: 0 auto;
    box-shadow: 0 0 0 .5px var(--sep), 0 30px 90px rgba(0, 0, 0, .14);
  }
  .layer { padding-left: calc(var(--app-x) + 24px); padding-right: calc(var(--app-x) + 24px); }
  .layer-sheet { padding-left: calc(var(--app-x) + 8px); padding-right: calc(var(--app-x) + 8px); }
  .layer-menu { padding: 0; }
  .crop-overlay { left: var(--app-x); right: var(--app-x); }
}

/* ─── Motion ──────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ─── Mascot ──────────────────────────────────────────────────────────────────
   The speech bubble of the icon with a face (js/mascot/mascot.js). Flat colours of
   its own — it looks the same in light and dark mode and on the stage. The
   root's data-mood shows the parts of that mood ([data-show] lists them);
   transforms are in the drawing's 200 × 200 units (transform-box: view-box).
   How it moves, as in hand-drawn animation:
   · a mood is a POSE — a transform on the outer group of a part, eased by
     a transition, so the body, the arms and the hat glide from one mood
     into the next — and a MOTION on the inner group: transform keyframes,
     most of them an entrance once and then a loop (never the CSS rotate /
     scale properties: Chrome does not apply them to SVG elements);
   · the arms, the thing in the hand and the hat move on their own, a little
     behind the body (overlap, follow-through); a jump crouches first
     (anticipation), stretches in the air and squashes on landing;
   · new parts of the face pop in; the eyes glance about and blink at
     uneven times, sometimes twice;
   · --m-lvl (0…1, mountMascot level()) — the learner's voice — makes the
     ear pulse while it listens. */
.mascot {
  --m-ink: #0B2A6B; --m-fill: #FFF; --m-shade: #DCE8FF; --m-cheek: #FF8FB0;
  --m-tongue: #FF6F91; --m-wave: #4AA8FF; --m-spark: #FFC43D;
  --m-sine: cubic-bezier(.37, 0, .63, 1);      /* breathing, swaying */
  --m-back: cubic-bezier(.34, 1.56, .64, 1);   /* pops, arms: a little past, then back */
  --m-soft: cubic-bezier(.3, 1.25, .5, 1);     /* poses: settle with a hint of overshoot */
  --m-lvl: 0;
  display: block; flex: none; overflow: visible;
}
.mascot * { transform-box: view-box; }

/* What each mood shows; a part that appears pops in. */
.mascot [data-show] { display: none; transform-box: fill-box; transform-origin: center; animation: m-pop .3s var(--m-back) both; }
.mascot[data-mood="idle"] [data-show~="idle"], .mascot[data-mood="happy"] [data-show~="happy"],
.mascot[data-mood="wave"] [data-show~="wave"], .mascot[data-mood="speak"] [data-show~="speak"],
.mascot[data-mood="listen"] [data-show~="listen"], .mascot[data-mood="think"] [data-show~="think"],
.mascot[data-mood="cheer"] [data-show~="cheer"], .mascot[data-mood="sad"] [data-show~="sad"],
.mascot[data-mood="sleep"] [data-show~="sleep"], .mascot[data-mood="fly"] [data-show~="fly"] { display: inline; }

/* Paint */
.mascot .m-fill { fill: var(--m-fill); }
.mascot .m-shade { fill: var(--m-shade); }
.mascot .m-line { fill: none; stroke: var(--m-ink); stroke-width: 5; stroke-linejoin: round; }
.mascot .m-shadow { fill: rgba(0, 0, 0, .13); }
.mascot .m-glint { fill: #FFF; }
.mascot .m-stroke { fill: none; stroke: var(--m-ink); stroke-width: 4.5; stroke-linecap: round; stroke-linejoin: round; }
.mascot .m-thin { stroke-width: 3.5; }
.mascot .m-ink { fill: var(--m-ink); }
.mascot .m-tongue { fill: var(--m-tongue); }
.mascot .m-cheeks { fill: var(--m-cheek); opacity: .55; transition: opacity .35s ease, transform .45s var(--m-soft); }
.mascot .m-arm-o { stroke: var(--m-ink); stroke-width: 15; stroke-linecap: round; }
.mascot .m-arm-f { stroke: var(--m-fill); stroke-width: 6; stroke-linecap: round; }
.mascot .m-hand { fill: var(--m-fill); stroke: var(--m-ink); stroke-width: 4.5; }
.mascot .m-acc :is(path, circle, ellipse) { stroke: var(--m-ink); stroke-width: 3.5; stroke-linejoin: round; stroke-linecap: round; }
.mascot .m-acc ellipse, .mascot .m-acc .m-acc-thin { stroke-width: 2.2; }
.mascot .m-held :is(path, circle, ellipse, rect) { stroke: var(--m-ink); stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
.mascot .m-held .m-acc-thin { stroke-width: 1.6; }
.mascot .m-held .m-held-o { fill: none; stroke-width: 7.5; }
.mascot .m-held .m-held-f { fill: none; stroke-width: 3.6; }
.mascot .m-acc .m-acc-flat, .mascot .m-held .m-acc-flat { stroke: none; }
.mascot .m-sparks { fill: var(--m-spark); }
.mascot .m-think { fill: var(--m-fill); stroke: var(--m-ink); stroke-width: 3; }
.mascot .m-zzz { fill: var(--m-wave); font: 800 18px var(--font-rounded); }
.mascot .m-drop { fill: #7CC4FF; stroke: var(--m-ink); stroke-width: 2; }
/* A woman's voice: eyelashes, rosier cheeks. */
.mascot .m-lashes { fill: none; stroke: var(--m-ink); stroke-width: 3; stroke-linecap: round; }
.mascot:not([data-voice="f"]) .m-lashes { display: none !important; }
.mascot[data-voice="f"] .m-cheeks { opacity: .8; }
.mascot:is([data-mood="happy"], [data-mood="cheer"]) .m-cheeks { opacity: .9; }

/* ── The body: a pose, and a motion on top ─────────────────────────────── */
.mascot .m-pose { transform-origin: 100px 166px; transition: transform .55s var(--m-soft); }
.mascot .m-body { transform-origin: 100px 166px; animation: m-bob 3.2s var(--m-sine) infinite; }
.mascot[data-mood="listen"] .m-pose { transform: rotate(6deg); }
.mascot[data-mood="think"] .m-pose { transform: rotate(-3deg); }
.mascot[data-mood="sad"] .m-pose { transform: translateY(4px) scale(1.02, .95); }
.mascot[data-mood="sleep"] .m-pose { transform: translateY(3px) rotate(3deg); }
.mascot .m-shadow { transform-origin: 100px 188px; animation: m-shadow-bob 3.2s var(--m-sine) infinite; }
.mascot[data-mood="happy"] .m-body { animation: m-hop .62s both, m-bob 3.2s .62s var(--m-sine) infinite; }
.mascot[data-mood="happy"] .m-shadow { animation: m-hop-shadow .62s both, m-shadow-bob 3.2s .62s var(--m-sine) infinite; }
/* after a cheer (which ends with its own landing) happy only bobs — a second hop looked like a stumble */
:is(.mascot[data-from="cheer"], .mascot[data-from="fly"])[data-mood="happy"] .m-body { animation: m-bob 3.2s var(--m-sine) infinite; }
:is(.mascot[data-from="cheer"], .mascot[data-from="fly"])[data-mood="happy"] .m-shadow { animation: m-shadow-bob 3.2s var(--m-sine) infinite; }
.mascot[data-mood="wave"] .m-body { animation: m-sway 1.12s var(--m-sine) infinite; }
.mascot[data-mood="speak"] .m-body { animation: m-speak-body 1.4s var(--m-sine) infinite; }
.mascot[data-mood="listen"] .m-body { animation: m-nod 2.2s var(--m-sine) .3s infinite; }
.mascot[data-mood="think"] .m-body { animation: m-ponder 4.2s var(--m-sine) infinite; }
.mascot[data-mood="cheer"] .m-body { animation: m-cheer 1.5s both, m-hop-loop 1.1s 1.5s infinite; }
.mascot[data-mood="cheer"] .m-shadow { animation: m-cheer-shadow 1.5s both, m-hop-shadow 1.1s 1.5s infinite; }
.mascot[data-mood="sad"] .m-body { animation: m-flinch .5s both, m-sigh 3.6s .5s var(--m-sine) infinite; }
.mascot[data-mood="sleep"] .m-body { animation: m-breathe 4.2s var(--m-sine) infinite; }

/* ── The hat: rides on the head, a beat behind it ──────────────────────── */
.mascot .m-hat { transform-origin: 100px 40px; transition: transform .6s var(--m-soft); }
.mascot .m-hat-move { transform-origin: 100px 40px; animation: m-hat-lag 3.2s var(--m-sine) -2.85s infinite; }
.mascot[data-mood="wave"] .m-hat-move { animation: m-hat-sway 1.12s var(--m-sine) -.95s infinite; }
.mascot[data-mood="speak"] .m-hat-move { animation: m-hat-talk 1.4s var(--m-sine) -1.3s infinite; }
.mascot[data-mood="cheer"] .m-hat-move { animation: m-hat-cheer 1.5s both, m-hat-hop 1.1s 1.58s infinite; }
.mascot[data-mood="listen"] .m-hat { transform: rotate(-2deg); }
.mascot[data-mood="sad"] .m-hat { transform: translateY(2.5px) rotate(-5deg); }
.mascot[data-mood="sleep"] .m-hat { transform: translate(2px, 3px) rotate(7deg); }
.mascot .m-feather { animation: m-flutter 2.2s var(--m-sine) infinite; }
.mascot .m-ribbon { animation: m-flutter 1.7s var(--m-sine) -.5s infinite; }
.mascot .m-sway { animation: m-sway-flower 3s var(--m-sine) infinite; }
.mascot .m-flap-l { animation: m-flap-l 3.2s var(--m-sine) -.2s infinite; }
.mascot .m-flap-r { animation: m-flap-r 3.2s var(--m-sine) -.2s infinite; }
.mascot[data-mood="cheer"] :is(.m-feather, .m-ribbon) { animation-duration: .5s; }
.mascot[data-mood="cheer"] .m-flap-l { animation: m-flap-l .36s var(--m-sine) infinite; }
.mascot[data-mood="cheer"] .m-flap-r { animation: m-flap-r .36s var(--m-sine) -.12s infinite; }

/* ── The arms: a pose (outer) with its own swing (inner) ───────────────── */
.mascot .m-arm { transition: transform .55s var(--m-back); }
.mascot .m-arm-l, .mascot .m-arm-l .m-swing { transform-origin: 34px 112px; }
.mascot .m-arm-r, .mascot .m-arm-r .m-swing { transform-origin: 166px 112px; }
.mascot .m-arm-l .m-swing { animation: m-swing-l 3.2s var(--m-sine) -.3s infinite; }
.mascot .m-arm-r .m-swing { animation: m-swing-r 3.2s var(--m-sine) -.1s infinite; }
.mascot[data-mood="wave"] .m-arm-r { transform: rotate(-86deg); }
.mascot[data-mood="wave"] .m-arm-r .m-swing { animation: m-wave .56s cubic-bezier(.45, 0, .55, 1) infinite alternate; }
.mascot[data-mood="speak"] .m-arm-r { transform: rotate(-22deg); }
.mascot[data-mood="speak"] .m-arm-r .m-swing { animation: m-gesture 1.4s var(--m-sine) infinite; }
.mascot[data-mood="listen"] .m-arm-r { transform: rotate(-84deg); }
.mascot[data-mood="listen"] .m-arm-r .m-swing { animation: m-cup 1.8s var(--m-sine) infinite; }
.mascot[data-mood="think"] .m-arm-r { transform: rotate(-100deg); }
.mascot[data-mood="think"] .m-arm-r .m-swing { animation: m-scratch 2.6s var(--m-sine) .4s infinite; }
.mascot[data-mood="cheer"] .m-arm-l { transform: rotate(84deg); }
.mascot[data-mood="cheer"] .m-arm-r { transform: rotate(-84deg); }
.mascot[data-mood="cheer"] .m-arm-l .m-swing { animation: m-shake-l .34s var(--m-sine) .1s infinite alternate; }
.mascot[data-mood="cheer"] .m-arm-r .m-swing { animation: m-shake-r .34s var(--m-sine) infinite alternate; }
.mascot[data-mood="sad"] .m-arm-l { transform: rotate(-26deg); }
.mascot[data-mood="sad"] .m-arm-r { transform: rotate(26deg); }
.mascot[data-mood="sad"] .m-arm-l .m-swing { animation: m-dangle-l 3.6s var(--m-sine) .5s infinite; }
.mascot[data-mood="sad"] .m-arm-r .m-swing { animation: m-dangle-r 3.6s var(--m-sine) .3s infinite; }
.mascot[data-mood="sleep"] .m-arm-l { transform: rotate(-12deg); }
.mascot[data-mood="sleep"] .m-arm-r { transform: rotate(12deg); }
.mascot[data-mood="sleep"] .m-arm-l .m-swing { animation: m-dangle-l 4.2s var(--m-sine) infinite; }
.mascot[data-mood="sleep"] .m-arm-r .m-swing { animation: m-dangle-r 4.2s var(--m-sine) -.4s infinite; }

/* The thing in the hand: turned against the arm (it stays upright), swinging
   a little later than the arm. */
.mascot .m-held, .mascot .m-dangle { transform-origin: 14px 130px; }
.mascot .m-held { transition: transform .6s var(--m-back); }
.mascot .m-dangle { animation: m-dangle 3.2s var(--m-sine) -.02s infinite; }
.mascot[data-mood="cheer"] .m-held { transform: rotate(-84deg); }
.mascot[data-mood="cheer"] .m-dangle { animation: m-shake-item .34s var(--m-sine) .22s infinite alternate; }
.mascot[data-mood="sad"] .m-held { transform: rotate(14deg); }
.mascot[data-mood="sleep"] .m-held { transform: rotate(20deg); }
.mascot .m-steam { opacity: 0; animation: m-steam 2.4s var(--m-sine) infinite; }
.mascot .m-steam + .m-steam { animation-delay: 1.2s; }

/* ── The face ──────────────────────────────────────────────────────────── */
.mascot .m-face { transition: transform .45s var(--m-soft); }
.mascot[data-mood="listen"] :is(.m-face, .m-cheeks) { transform: translateX(-10px); }
.mascot .m-gaze { transition: transform .4s var(--m-soft); }
.mascot[data-mood="listen"] .m-gaze { transform: translateX(-2px); }
.mascot[data-mood="think"] .m-gaze { transform: translate(3px, -3px); }
.mascot .m-eyes {
  fill: var(--m-ink); transform-box: view-box; transform-origin: 100px 82px;
  animation: m-pop .3s var(--m-back) both, m-look 7.3s var(--m-sine) .3s infinite;
}
.mascot[data-mood="think"] .m-brows-up { animation: m-pop .3s var(--m-back) both, m-brow 4.2s var(--m-sine) .3s infinite; }
.mascot .m-talk { transform-box: view-box; transform-origin: 100px 101px; animation: m-talk 1.4s var(--m-sine) infinite; }
.mascot .m-drop { transform-box: view-box; transform-origin: 150px 58px; animation: m-drop 2.6s .35s infinite both; }

/* The ear, while it listens: grows out, wiggles, pulses with the voice. */
.mascot :is(.m-ear, .m-ear-lvl, .m-ear-in) { transform-origin: 170px 86px; }
.mascot .m-ear { transform: scale(0); transition: transform .3s cubic-bezier(.5, 0, .75, 0); }
.mascot[data-mood="listen"] .m-ear { transform: none; transition: transform .5s var(--m-back) .08s; }
.mascot .m-ear-lvl { transform: scale(calc(1 + var(--m-lvl) * .22)); transition: transform .09s linear; }
.mascot[data-mood="listen"] .m-ear-in { animation: m-ear 1.8s var(--m-sine) infinite; }   /* only while it listens: hidden, it moved too */

/* ── Around it: sparks, thoughts, sleep ────────────────────────────────── */
.mascot .m-sparks { transform-box: view-box; transform-origin: 100px 90px; animation: m-burst .55s var(--m-back) both; }
.mascot .m-sparks path { transform-box: fill-box; transform-origin: center; animation: m-twinkle 1.1s var(--m-sine) infinite alternate; }
.mascot .m-sparks g:nth-child(2) path { animation-delay: -.35s; }
.mascot .m-sparks g:nth-child(3) path { animation-delay: -.7s; }
.mascot .m-sparks g:nth-child(4) path { animation-delay: -.5s; }
.mascot .m-think { animation: none; }
.mascot .m-think circle { transform-box: fill-box; transform-origin: center; animation: m-dot-in .35s var(--m-back) both, m-dot 2.4s var(--m-sine) .35s infinite; }
.mascot .m-think circle:nth-child(2) { animation-delay: .14s, .6s; }
.mascot .m-think circle:nth-child(3) { animation-delay: .28s, .85s; }
.mascot .m-zzz text { transform-box: fill-box; transform-origin: center; opacity: 0; animation: m-z 3s var(--m-sine) infinite; }
.mascot .m-zzz text:nth-child(2) { animation-delay: 1s; }
.mascot .m-zzz text:nth-child(3) { animation-delay: 2s; }

/* ── Keyframes ─────────────────────────────────────────────────────────── */
@keyframes m-pop { 0% { transform: scale(.4); opacity: 0; } 55% { transform: scale(1.12); opacity: 1; } 100% { transform: none; opacity: 1; } }
/* body */
@keyframes m-bob { 0%, 100% { transform: none; } 50% { transform: translateY(-3px) scale(.995, 1.012); } }
@keyframes m-shadow-bob { 0%, 100% { transform: none; } 50% { transform: scale(.94); opacity: .8; } }
@keyframes m-hop {
  0% { transform: none; animation-timing-function: cubic-bezier(.3, 0, .5, 1); }
  18% { transform: translateY(1px) scale(1.07, .92); animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  50% { transform: translateY(-13px) scale(.96, 1.05); animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  78% { transform: scale(1.05, .95); animation-timing-function: cubic-bezier(.3, .6, .4, 1); }
  100% { transform: none; }
}
@keyframes m-hop-shadow { 0%, 100% { transform: none; } 18% { transform: scale(1.06); } 50% { transform: scale(.72); opacity: .55; } 78% { transform: scale(1.05); opacity: 1; } }
@keyframes m-sway { 0%, 100% { transform: rotate(-1.6deg); } 50% { transform: translateY(-2px) rotate(2deg); } }
@keyframes m-speak-body {
  0%, 20%, 100% { transform: none; }
  9% { transform: translateY(-1.6px) scale(.99, 1.012); }
  29% { transform: translateY(-2px) scale(.99, 1.014) rotate(-.9deg); }
  45% { transform: rotate(.6deg); }
  66% { transform: translateY(-2px) scale(.99, 1.014) rotate(1deg); }
  82% { transform: translateY(-1px); }
}
@keyframes m-nod { 0%, 38%, 72%, 100% { transform: none; } 20% { transform: translateY(1.2px) rotate(2deg); } 55% { transform: translateY(.7px) rotate(1.2deg); } }
@keyframes m-ponder { 0%, 100% { transform: none; } 50% { transform: translateY(-1.5px) rotate(-2deg); } }
@keyframes m-cheer {
  0% { transform: none; animation-timing-function: cubic-bezier(.3, 0, .6, 1); }
  12% { transform: translateY(2px) scale(1.1, .88); animation-timing-function: cubic-bezier(.15, .8, .3, 1); }
  38% { transform: translateY(-24px) scale(.94, 1.08) rotate(-3deg); animation-timing-function: linear; }
  45% { transform: translateY(-25px) scale(.97, 1.03) rotate(-2deg); animation-timing-function: cubic-bezier(.55, 0, .85, .35); }
  60% { transform: scale(1.1, .88); animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  72% { transform: translateY(-9px) scale(.97, 1.04) rotate(2deg); animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  84% { transform: scale(1.05, .95); animation-timing-function: cubic-bezier(.3, .6, .4, 1); }
  100% { transform: none; }
}
@keyframes m-cheer-shadow {
  0%, 100% { transform: none; } 12% { transform: scale(1.08); } 38%, 45% { transform: scale(.6); opacity: .45; }
  60% { transform: scale(1.1); opacity: 1; } 72% { transform: scale(.82); opacity: .75; } 84% { transform: scale(1.04); opacity: 1; }
}
@keyframes m-hop-loop {
  0% { transform: none; animation-timing-function: cubic-bezier(.3, 0, .5, 1); }
  15% { transform: scale(1.06, .93); animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  45% { transform: translateY(-10px) scale(.97, 1.04); animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  70% { transform: scale(1.05, .95); animation-timing-function: cubic-bezier(.3, .6, .4, 1); }
  100% { transform: none; }
}
@keyframes m-flinch { 0% { transform: none; animation-timing-function: cubic-bezier(.2, .8, .3, 1); } 30% { transform: translateY(3px) scale(1.06, .9); } 65% { transform: translateY(-1px) scale(.98, 1.02); } 100% { transform: none; } }
@keyframes m-sigh { 0%, 100% { transform: none; } 35% { transform: translateY(-2px) scale(.99, 1.02); } 62% { transform: translateY(1px) scale(1.015, .98); } }
@keyframes m-breathe { 0%, 100% { transform: none; } 50% { transform: translateY(-1px) scale(1.025, 1.035); } }
/* hat */
@keyframes m-hat-lag { 0%, 100% { transform: rotate(-1deg); } 50% { transform: translateY(.8px) rotate(1.2deg); } }
@keyframes m-hat-sway { 0%, 100% { transform: rotate(1.2deg); } 50% { transform: rotate(-2deg); } }
@keyframes m-hat-talk { 0%, 20%, 100% { transform: none; } 12% { transform: translateY(.8px); } 34% { transform: translateY(1px) rotate(1deg); } 70% { transform: translateY(1px) rotate(-1deg); } }
@keyframes m-hat-cheer {
  0%, 100% { transform: none; }
  12% { transform: translateY(1px) scale(1.04, .96); }
  38% { transform: translateY(-6px) rotate(-6deg); }
  50% { transform: translateY(-10px) rotate(-8deg); }
  62% { transform: translateY(-2px) rotate(4deg); }
  70% { transform: translateY(1.5px) rotate(3deg) scale(1.04, .95); }
  82% { transform: translateY(-1.5px) rotate(-2deg); }
}
@keyframes m-hat-hop { 0%, 100% { transform: none; } 45% { transform: translateY(-2.5px) rotate(-2deg); } 72% { transform: translateY(1px) rotate(1.5deg); } }
@keyframes m-flutter { 0%, 100% { transform: rotate(-4deg); } 50% { transform: rotate(7deg); } }
@keyframes m-sway-flower { 0%, 100% { transform: rotate(-5deg); } 50% { transform: rotate(6deg); } }
@keyframes m-flap-l { 0%, 100% { transform: rotate(3deg); } 50% { transform: rotate(-9deg); } }
@keyframes m-flap-r { 0%, 100% { transform: rotate(-3deg); } 50% { transform: rotate(9deg); } }
/* arms and hand */
@keyframes m-swing-l { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(5deg); } }
@keyframes m-swing-r { 0%, 100% { transform: rotate(2deg); } 50% { transform: rotate(-5deg); } }
@keyframes m-wave { from { transform: rotate(12deg); } to { transform: rotate(-15deg); } }
@keyframes m-gesture { 0%, 100% { transform: none; } 22% { transform: rotate(-22deg); } 40% { transform: rotate(-8deg); } 60% { transform: rotate(-30deg); } 80% { transform: rotate(4deg); } }
@keyframes m-cup { 0%, 100% { transform: none; } 50% { transform: rotate(-5deg); } }
@keyframes m-scratch { 0%, 36%, 100% { transform: none; } 6%, 18%, 30% { transform: rotate(-7deg); } 12%, 24% { transform: rotate(3deg); } }
@keyframes m-shake-l { from { transform: rotate(-10deg); } to { transform: rotate(8deg); } }
@keyframes m-shake-r { from { transform: rotate(10deg); } to { transform: rotate(-8deg); } }
@keyframes m-dangle-l { 0%, 100% { transform: none; } 50% { transform: rotate(3deg); } }
@keyframes m-dangle-r { 0%, 100% { transform: none; } 50% { transform: rotate(-3deg); } }
@keyframes m-dangle { 0%, 100% { transform: rotate(2.5deg); } 50% { transform: rotate(-4.5deg); } }
@keyframes m-shake-item { from { transform: rotate(14deg); } to { transform: rotate(-12deg); } }
@keyframes m-steam { 0% { transform: translateY(3px); opacity: 0; } 40% { opacity: .9; } 100% { transform: translateY(-6px); opacity: 0; } }
/* face */
@keyframes m-look {
  0%, 14%, 33%, 46%, 49%, 77%, 88%, 90.6%, 93.3%, 100% { transform: none; }
  17%, 30% { transform: translateX(-1.6px); }
  47.5% { transform: scaleY(.08); }
  64%, 74% { transform: translate(1.4px, -.6px); }
  89.3%, 92% { transform: scaleY(.08); }
}
@keyframes m-brow { 0%, 100% { transform: none; } 50% { transform: translateY(-2px); } }
@keyframes m-talk {
  0%, 100% { transform: scale(.9, .25); } 9% { transform: scale(1, .95); } 17% { transform: scale(.94, .4); }
  29% { transform: scale(1.04, 1); } 38% { transform: scale(.9, .3); } 47% { transform: scale(.98, .75); }
  55% { transform: scale(.92, .35); } 66% { transform: scale(1.05, 1.05); } 76% { transform: scale(.94, .45); }
  85% { transform: scale(1, .85); } 93% { transform: scale(.9, .3); }
}
@keyframes m-drop {
  0% { transform: translateY(-3px) scale(.4); opacity: 0; animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
  18% { transform: none; opacity: 1; animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  70%, 100% { transform: translateY(16px); opacity: 0; }
}
@keyframes m-ear { 0%, 100% { transform: none; } 50% { transform: rotate(5deg); } }
/* around */
@keyframes m-burst { 0% { transform: scale(.3); opacity: 0; } 55% { opacity: 1; } 100% { transform: none; opacity: 1; } }
@keyframes m-twinkle { from { transform: scale(.72) rotate(-8deg); opacity: .8; } to { transform: scale(1.15) rotate(18deg); opacity: 1; } }
@keyframes m-dot-in { from { transform: scale(0); } to { transform: none; } }
@keyframes m-dot { 0%, 100% { transform: none; } 50% { transform: translateY(-2.5px) scale(1.08); } }
@keyframes m-z { 0% { transform: translate(-4px, 8px) scale(.5); opacity: 0; } 25% { opacity: 1; } 100% { transform: translate(6px, -14px) scale(1.15); opacity: 0; } }

/* ── Flying (mood "fly"): leans into the flight, flaps its arms like wings;
   svg data-heading (mascot.js flight) says which way — flying left the whole
   drawing turns round (a short squeeze through the middle, not a snap), so
   its tail and the speed lines trail behind ─ */
.mascot .m-speed { fill: none; stroke: var(--m-wave); stroke-width: 5; stroke-linecap: round; }
.mascot .m-speed path { animation: m-speed .42s linear infinite; }
.mascot .m-speed path:nth-child(2) { animation-delay: -.14s; }
.mascot .m-speed path:nth-child(3) { animation-delay: -.28s; }
.mascot[data-mood="fly"] .m-pose { transform: rotate(8deg); }
.m-host > .mascot { transition: transform .3s cubic-bezier(.4, 0, .3, 1); }
.m-host > .mascot[data-heading="left"] { transform: scaleX(-1); }
.mascot[data-mood="fly"] .m-body { animation: m-fly-bob .52s var(--m-sine) infinite; }
.mascot[data-mood="fly"] .m-arm-l { transform: rotate(40deg); }
.mascot[data-mood="fly"] .m-arm-r { transform: rotate(-40deg); }
.mascot[data-mood="fly"] .m-arm-l .m-swing { animation: m-wing-l .26s var(--m-sine) infinite alternate; }
.mascot[data-mood="fly"] .m-arm-r .m-swing { animation: m-wing-r .26s var(--m-sine) infinite alternate; }
.mascot[data-mood="fly"] .m-held { transform: rotate(-40deg); }
.mascot[data-mood="fly"] .m-dangle { animation: m-shake-item .22s var(--m-sine) .05s infinite alternate; }
.mascot[data-mood="fly"] .m-hat { transform: translate(-2px, 1px) rotate(-6deg); }
.mascot[data-mood="fly"] .m-hat-move { animation: m-hat-hop .5s var(--m-sine) -.1s infinite; }
.mascot[data-mood="fly"] :is(.m-feather, .m-ribbon) { animation-duration: .35s; }
.mascot[data-mood="fly"] .m-shadow { opacity: 0; animation: none; }   /* no ground under it: its bob would fade it back in */
@keyframes m-fly-bob { 0%, 100% { transform: none; } 50% { transform: translateY(-3px); } }
@keyframes m-wing-l { from { transform: rotate(-35deg); } to { transform: rotate(42deg); } }
@keyframes m-wing-r { from { transform: rotate(35deg); } to { transform: rotate(-42deg); } }
@keyframes m-speed { 0% { transform: translateX(10px); opacity: 0; } 30% { opacity: 1; } 100% { transform: translateX(-18px); opacity: 0; } }

/* The element that holds a mounted mascot (mountMascot adds .m-host). */
.m-host { position: relative; }
.m-host > .mascot { width: 100%; height: 100%; }
.m-flying { z-index: 50; pointer-events: none; }
.m-tappable { cursor: pointer; pointer-events: auto; -webkit-tap-highlight-color: transparent; }
/* the dust it kicks up as it lands (mascot.js puffsAt) */
.m-puff { position: fixed; z-index: 49; width: 26px; height: 16px; margin: -8px 0 0 -13px; border-radius: 50%; pointer-events: none; filter: blur(1.5px);
  background: radial-gradient(closest-side, color-mix(in srgb, var(--label) 34%, transparent), color-mix(in srgb, var(--label) 12%, transparent) 65%, transparent);
  animation: m-puff .7s cubic-bezier(.2, .7, .3, 1) forwards; }
@keyframes m-puff { from { transform: translate(0, 0) scale(calc(var(--s) * .35)); opacity: 1; } to { transform: translate(var(--dx), -10px) scale(calc(var(--s) * 1.7)); opacity: 0; } }

/* ── Scenes on the spot (mascot.js `scene`; the start page — the owner,
   2026-09-29: no flying about there, more life instead; picked in
   tools/labs/mascot-antics.html). data-act on the drawing for the scene's length.
   Only the outer groups move (.m-pose, .m-arm-*, .m-held, .m-hat, .m-gaze):
   the loops inside them (bob, swing, dangle, glance) run on. Every scene
   starts and ends in the resting pose, so it glides in and out of the mood
   (scene() first eases a mood with a pose of its own back to rest). */
.mascot .m-x { opacity: 0; pointer-events: none; }
.mascot .m-x-yawn { transform-origin: 100px 107px; }
.mascot .m-x-yawn .m-x-in { fill: var(--m-ink); }
.mascot .m-x-yawn .m-x-tg { fill: var(--m-tongue); }
.mascot .m-x-oh { fill: var(--m-ink); transform-origin: 100px 106px; }
.mascot .m-x-gum { transform-origin: 100px 108px; }
.mascot .m-x-gum .m-x-ball { fill: #FF9CC6; }
.mascot .m-x-gum .m-x-hi { fill: #FFF; opacity: .75; }
.mascot .m-x-bits circle { fill: #FF9CC6; }
.mascot .m-x-drops circle { fill: #8FD3FF; }
.mascot .m-x-bang path { fill: none; stroke: #FF9F0A; stroke-width: 6; stroke-linecap: round; }
.mascot .m-x-bang circle { fill: #FF9F0A; }
.mascot .m-x-bang { transform-origin: 168px 40px; }
.mascot .m-x-note ellipse { fill: #FFF; stroke: var(--m-ink); stroke-width: 2.2; }
.mascot .m-x-note path { fill: none; stroke: var(--m-ink); stroke-width: 3.2; stroke-linecap: round; }
.mascot .m-x-z { fill: #FFF; stroke: var(--m-ink); stroke-width: 2.4; paint-order: stroke; stroke-linejoin: round; font: 900 24px var(--font-rounded, sans-serif); }
.mascot .m-x-bfly .m-x-w { fill: #FF9F43; } .mascot .m-x-bfly .m-x-w2 { fill: #FFC857; }
.mascot .m-x-bfly .m-x-bd { fill: #3B2A1A; } .mascot .m-x-bfly .m-x-sp { fill: #fff; opacity: .8; }
.mascot .m-x-wings { transform-origin: 0 0; }
.mascot[data-act="bfly"] .m-x-wings { animation: m-x-flap .16s ease-in-out infinite alternate; }
@keyframes m-x-flap { from { transform: scaleX(1); } to { transform: scaleX(.28); } }
.mascot[data-act] .m-gaze { transform-origin: 100px 82px; }
.mascot[data-act] .m-hat { transform-origin: 100px 30px; }

/* the mouth of the mood gives way to the scene's own */
@keyframes m-x-mouth-off { 0% { opacity: 1; } 6%, 100% { opacity: 0; } }
.mascot:is([data-act="yawn"], [data-act="gum"], [data-act="whistle"], [data-act="sneeze"], [data-act="hatslip"]) .m-face > path.m-stroke[data-show~="idle"] { animation: m-x-mouth-off var(--m-x-ms) both; }

/* 1 · Hut fällt runter: a hiccup throws the hat up; it falls edge-on past
   his face and lands upside down beside him, rocks; he bends down, picks
   it up with his hand and tosses it back onto his head. */
.mascot[data-act="hatfall"] { --m-x-ms: 5.4s; }
.mascot[data-act="hatfall"] .m-pose { animation: m-x-hf-body var(--m-x-ms) both; }
@keyframes m-x-hf-body {
  0% { transform: none; animation-timing-function: cubic-bezier(.3, 0, .5, 1); }
  4% { transform: translateY(2px) scale(1.06, .94); animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  9% { transform: translateY(-9px) scale(.97, 1.04); animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  14% { transform: scale(1.03, .97); } 18%, 38% { transform: none; }
  44% { transform: rotate(2deg); } 50%, 56% { transform: translate(3px, 3px) rotate(7deg); }
  64% { transform: rotate(-1deg); } 76% { transform: translateY(-2px) rotate(-3deg); }
  83% { transform: translateY(2px) scale(1.04, .96); } 90%, 100% { transform: none; }
}
.mascot[data-act="hatfall"] .m-hat { animation: m-x-hf-hat var(--m-x-ms) both; }
@keyframes m-x-hf-hat {
  0%, 8% { transform: none; animation-timing-function: cubic-bezier(.2, .7, .4, 1); }
  17% { transform: translate(24px, -52px) rotate(24deg); animation-timing-function: cubic-bezier(.5, 0, .75, .4); }
  23% { transform: translate(64px, -4px) rotate(90deg); animation-timing-function: cubic-bezier(.4, 0, .85, .55); }
  30% { transform: translate(70px, 133px) rotate(178deg); animation-timing-function: cubic-bezier(.2, .8, .4, 1); }
  34% { transform: translate(70px, 127px) rotate(166deg); animation-timing-function: cubic-bezier(.5, 0, .7, .5); }
  38% { transform: translate(70px, 133px) rotate(188deg); }
  42% { transform: translate(70px, 133px) rotate(175deg); }
  46%, 55% { transform: translate(70px, 133px) rotate(180deg); animation-timing-function: cubic-bezier(.4, 0, .2, 1); }
  64% { transform: translate(84px, 44px) rotate(24deg); animation-timing-function: cubic-bezier(.3, 0, .6, 1); }
  68% { transform: translate(84px, 42px) rotate(18deg); animation-timing-function: cubic-bezier(.4, 0, .9, .6); }
  76% { transform: translate(30px, -46px) rotate(-14deg); animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  83% { transform: translate(0, 4px) rotate(3deg); animation-timing-function: cubic-bezier(.3, .6, .4, 1); }
  88% { transform: translate(0, -3px) rotate(-2deg); } 93%, 100% { transform: none; }
}
.mascot[data-act="hatfall"] .m-arm-r { animation: m-x-hf-arm var(--m-x-ms) both; }
@keyframes m-x-hf-arm { 0%, 40% { transform: none; } 48%, 55% { transform: rotate(48deg); } 64% { transform: rotate(-70deg); } 68% { transform: rotate(-58deg); } 76% { transform: rotate(-98deg); } 86%, 100% { transform: none; } }
.mascot[data-act="hatfall"] .m-gaze { animation: m-x-hf-eyes var(--m-x-ms) both; }
@keyframes m-x-hf-eyes {
  0%, 8% { transform: none; } 14% { transform: translate(2px, -7px) scale(1.15); } 20% { transform: translate(5px, -2px); }
  30%, 56% { transform: translate(6px, 7px); } 64% { transform: translate(5px, -2px); } 76% { transform: translate(1px, -8px); }
  83% { transform: translate(0, -3px) scaleY(.12); } 88%, 100% { transform: none; }
}
.mascot[data-act="hatfall"] .m-x-bang { animation: m-x-bang var(--m-x-ms) both; }
@keyframes m-x-bang { 0%, 10% { opacity: 0; transform: scale(.3); } 13% { opacity: 1; transform: scale(1.15); } 16%, 26% { opacity: 1; transform: none; } 31%, 100% { opacity: 0; transform: none; } }

/* 1b · Hut rutscht über die Augen: a hiccup, the hat slips down over his
   eyes; he sways about blind, pushes it back up with his hand — there you are. */
.mascot[data-act="hatslip"] { --m-x-ms: 4.4s; }
.mascot[data-act="hatslip"] .m-hat { animation: m-x-hs-hat var(--m-x-ms) both; }
@keyframes m-x-hs-hat {
  0%, 6% { transform: none; animation-timing-function: cubic-bezier(.2, .7, .4, 1); }
  12% { transform: translate(0, -16px) rotate(-6deg); animation-timing-function: cubic-bezier(.55, 0, .85, .5); }
  20% { transform: translate(-2px, 44px) rotate(-7deg); animation-timing-function: cubic-bezier(.2, .8, .4, 1); }
  24% { transform: translate(-2px, 38px) rotate(-5deg); }
  28% { transform: translate(-2px, 42px) rotate(-6deg); }
  36% { transform: translate(-1px, 42px) rotate(-3deg); } 46% { transform: translate(-3px, 43px) rotate(-8deg); }
  54% { transform: translate(-2px, 42px) rotate(-6deg); animation-timing-function: cubic-bezier(.4, 0, .9, .6); }
  59% { transform: translate(5px, 36px) rotate(9deg); animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  65% { transform: translate(2px, -14px) rotate(-4deg); animation-timing-function: cubic-bezier(.5, 0, .8, .5); }
  72% { transform: translate(0, 2px) rotate(2deg); } 77% { transform: translate(0, -1px); } 82%, 100% { transform: none; }
}
.mascot[data-act="hatslip"] .m-gaze { animation: m-x-hs-eyes var(--m-x-ms) both; }
@keyframes m-x-hs-eyes {
  0%, 6% { opacity: 1; transform: none; } 12% { opacity: 1; transform: translate(0, -6px) scale(1.12); }
  17% { opacity: 1; transform: translateY(-4px) scaleY(.2); } 18%, 62% { opacity: 0; transform: none; }
  65% { opacity: 1; transform: scale(1.28); } 71% { opacity: 1; transform: scale(1.2); } 74% { opacity: 1; transform: scaleY(.1); } 78%, 100% { opacity: 1; transform: none; }
}
.mascot[data-act="hatslip"] .m-pose { animation: m-x-hs-body var(--m-x-ms) both; }
@keyframes m-x-hs-body {
  0% { transform: none; } 5% { transform: translateY(2px) scale(1.05, .95); } 10% { transform: translateY(-7px) scale(.97, 1.03); } 16% { transform: none; }
  22% { transform: translateY(1px) scale(1.02, .98); }
  30% { transform: translateX(-3px) rotate(-5deg); } 40% { transform: translateX(3px) rotate(5deg); } 50% { transform: translateX(-2px) rotate(-3deg); }
  58% { transform: rotate(2deg); } 65% { transform: translateY(-3px) scale(.98, 1.02); } 72%, 100% { transform: none; }
}
.mascot[data-act="hatslip"] .m-arm-l { animation: m-x-hs-armL var(--m-x-ms) both; }
@keyframes m-x-hs-armL { 0%, 22% { transform: none; } 30% { transform: rotate(24deg); } 40% { transform: rotate(-8deg); } 50% { transform: rotate(18deg); } 60%, 100% { transform: none; } }
.mascot[data-act="hatslip"] .m-arm-r { animation: m-x-hs-armR var(--m-x-ms) both; }
@keyframes m-x-hs-armR { 0%, 24% { transform: none; } 32% { transform: rotate(-20deg); } 42% { transform: rotate(10deg); } 50% { transform: none; } 57% { transform: rotate(-82deg); } 63% { transform: rotate(-104deg); } 72% { transform: rotate(-60deg); } 82%, 100% { transform: none; } }
.mascot[data-act="hatslip"] .m-x-oh { animation: m-x-hs-mouth var(--m-x-ms) both; }
@keyframes m-x-hs-mouth { 0%, 16% { opacity: 0; transform: scale(.3); } 22% { opacity: 1; transform: scale(1); } 40% { opacity: 1; transform: scale(.8); } 60% { opacity: 1; transform: scale(1); } 66%, 100% { opacity: 0; transform: scale(.3); } }

/* 2 · Hatschi: breathes in, eyes squeeze, sneezes forward, the hat jumps. */
.mascot[data-act="sneeze"] { --m-x-ms: 2.9s; }
.mascot[data-act="sneeze"] .m-pose { animation: m-x-sneeze var(--m-x-ms) both; }
@keyframes m-x-sneeze {
  0% { transform: none; }
  20% { transform: translateY(-2px) rotate(-3deg); }
  30% { transform: translateY(-3px) rotate(-5deg); } 36% { transform: translateY(-4px) rotate(-7deg) scale(.98, 1.03); animation-timing-function: cubic-bezier(.7, 0, 1, .6); }
  42% { transform: translateY(5px) rotate(9deg) scale(1.06, .93); animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  52% { transform: translateY(-1px) rotate(-2deg); } 62%, 100% { transform: none; }
}
.mascot[data-act="sneeze"] .m-gaze { animation: m-x-sneeze-eyes var(--m-x-ms) both; }
@keyframes m-x-sneeze-eyes { 0% { transform: none; } 22% { transform: scaleY(.62); } 32% { transform: scaleY(.4); } 36% { transform: scaleY(.25); } 40%, 50% { transform: scaleY(.08); } 58% { transform: scaleY(1.15); } 66%, 100% { transform: none; } }
.mascot[data-act="sneeze"] .m-hat { animation: m-x-sneeze-hat var(--m-x-ms) both; }
@keyframes m-x-sneeze-hat { 0%, 41% { transform: none; } 49% { transform: translate(-3px, -22px) rotate(-16deg); animation-timing-function: cubic-bezier(.5, 0, .8, .5); } 58% { transform: translate(0, 3px) rotate(4deg); } 64% { transform: translate(0, -2px) rotate(-1deg); } 70%, 100% { transform: none; } }
.mascot[data-act="sneeze"] .m-x-oh { animation: m-x-sneeze-oh var(--m-x-ms) both; }
@keyframes m-x-sneeze-oh { 0%, 12% { opacity: 0; transform: scale(.3); } 18% { opacity: 1; transform: scale(.8); } 30% { opacity: 1; transform: scale(1.1); } 38% { opacity: 1; transform: scale(1.35); } 41%, 100% { opacity: 0; } }
.mascot[data-act="sneeze"] .m-x-yawn { animation: m-x-sneeze-open var(--m-x-ms) both; }
@keyframes m-x-sneeze-open { 0%, 40% { opacity: 0; transform: scale(.5); } 42% { opacity: 1; transform: scale(1.1, .7); } 54% { opacity: 1; transform: scale(.8, .5); } 60%, 100% { opacity: 0; transform: scale(.3); } }
.mascot[data-act="sneeze"] .m-x-drops circle { transform-origin: 100px 110px; animation: m-x-drop var(--m-x-ms) both; }
.mascot[data-act="sneeze"] .m-x-drops circle:nth-child(1) { --m-dx: -34px; --m-dy: 22px; }
.mascot[data-act="sneeze"] .m-x-drops circle:nth-child(2) { --m-dx: -14px; --m-dy: 36px; }
.mascot[data-act="sneeze"] .m-x-drops circle:nth-child(3) { --m-dx: 14px; --m-dy: 38px; }
.mascot[data-act="sneeze"] .m-x-drops circle:nth-child(4) { --m-dx: 34px; --m-dy: 24px; }
.mascot[data-act="sneeze"] .m-x-drops circle:nth-child(5) { --m-dx: 0px; --m-dy: 44px; }
@keyframes m-x-drop { 0%, 41% { opacity: 0; transform: none; } 44% { opacity: 1; } 62% { opacity: 0; transform: translate(var(--m-dx), var(--m-dy)) scale(.6); } 100% { opacity: 0; } }

/* 3 · Gähnen & Strecken: arms up, tall and thin, a big yawn, eyes shut. */
.mascot[data-act="yawn"] { --m-x-ms: 3.9s; }
.mascot[data-act="yawn"] .m-pose { animation: m-x-yawn-body var(--m-x-ms) both; }
@keyframes m-x-yawn-body {
  0% { transform: none; } 12% { transform: translateY(1px) scale(1.02, .98); }
  32% { transform: translateY(-6px) scale(.95, 1.08); } 44% { transform: translateY(-7px) scale(.94, 1.09) rotate(-1.5deg); }
  52% { transform: translateY(-7px) scale(.95, 1.08) rotate(1.5deg); } 60% { transform: translateY(-6px) scale(.95, 1.08); }
  70% { transform: translateY(2px) scale(1.05, .95); } 78% { transform: translateY(-1px); } 86%, 100% { transform: none; }
}
.mascot[data-act="yawn"] .m-arm-l { animation: m-x-yawn-l var(--m-x-ms) both; }
.mascot[data-act="yawn"] .m-arm-r { animation: m-x-yawn-r var(--m-x-ms) both; }
@keyframes m-x-yawn-l { 0%, 10% { transform: none; } 30% { transform: rotate(92deg); } 44% { transform: rotate(99deg); } 52% { transform: rotate(92deg); } 60% { transform: rotate(98deg); } 72%, 100% { transform: none; } }
@keyframes m-x-yawn-r { 0%, 10% { transform: none; } 30% { transform: rotate(-92deg); } 44% { transform: rotate(-99deg); } 52% { transform: rotate(-92deg); } 60% { transform: rotate(-98deg); } 72%, 100% { transform: none; } }
.mascot[data-act="yawn"] .m-held { animation: m-x-yawn-held var(--m-x-ms) both; }
@keyframes m-x-yawn-held { 0%, 10% { transform: none; } 30%, 60% { transform: rotate(-95deg); } 72%, 100% { transform: none; } }
.mascot[data-act="yawn"] .m-gaze { animation: m-x-yawn-eyes var(--m-x-ms) both; }
@keyframes m-x-yawn-eyes { 0% { transform: none; } 16% { transform: scaleY(.5); } 26%, 62% { transform: scaleY(.07); } 70% { transform: scaleY(.6); } 76% { transform: scaleY(.9); } 80% { transform: scaleY(.1); } 84%, 100% { transform: none; } }
.mascot[data-act="yawn"] .m-x-yawn { animation: m-x-yawn-mouth var(--m-x-ms) both; }
@keyframes m-x-yawn-mouth { 0%, 10% { opacity: 0; transform: scale(.2); } 16% { opacity: 1; transform: scale(.4, .3); } 34% { opacity: 1; transform: scale(1.05, 1.1); } 56% { opacity: 1; transform: scale(1.1, 1.25); } 66% { opacity: 1; transform: scale(.5, .3); } 70%, 100% { opacity: 0; transform: scale(.2); } }

/* 5 · Kaugummiblase: a pink bubble grows, wobbles — and pops in his face. */
.mascot[data-act="gum"] { --m-x-ms: 3.7s; }
.mascot[data-act="gum"] .m-x-gum { animation: m-x-gum var(--m-x-ms) both; }
@keyframes m-x-gum {
  0%, 6% { opacity: 0; transform: scale(.05); } 9% { opacity: 1; transform: scale(.14); }
  22% { transform: scale(.42); opacity: 1; } 27% { transform: scale(.38); opacity: 1; } 40% { transform: scale(.74); opacity: 1; }
  45% { transform: scale(.7, .74); opacity: 1; } 56% { transform: scale(1, 1.02); opacity: 1; } 61% { transform: scale(1.1, 1.06); opacity: 1; }
  62.5% { transform: scale(1.5); opacity: 0; } 100% { transform: scale(.1); opacity: 0; }
}
.mascot[data-act="gum"] .m-x-bits circle { transform-origin: 100px 108px; animation: m-x-bit var(--m-x-ms) both; }
.mascot[data-act="gum"] .m-x-bits circle:nth-child(1) { --m-dx: -36px; --m-dy: -14px; }
.mascot[data-act="gum"] .m-x-bits circle:nth-child(2) { --m-dx: 38px; --m-dy: -10px; }
.mascot[data-act="gum"] .m-x-bits circle:nth-child(3) { --m-dx: -24px; --m-dy: 22px; }
.mascot[data-act="gum"] .m-x-bits circle:nth-child(4) { --m-dx: 26px; --m-dy: 24px; }
.mascot[data-act="gum"] .m-x-bits circle:nth-child(5) { --m-dx: 2px; --m-dy: -30px; }
@keyframes m-x-bit { 0%, 61% { opacity: 0; transform: none; } 63% { opacity: 1; } 76% { opacity: 0; transform: translate(var(--m-dx), var(--m-dy)) scale(.5); } 100% { opacity: 0; } }
.mascot[data-act="gum"] .m-gaze { animation: m-x-gum-eyes var(--m-x-ms) both; }
@keyframes m-x-gum-eyes { 0%, 8% { transform: none; } 16%, 58% { transform: translateY(3px); } 62% { transform: translateY(-2px) scale(1.28); } 70% { transform: translateY(-2px) scale(1.2); } 73% { transform: scaleY(.1); } 77%, 100% { transform: none; } }
.mascot[data-act="gum"] .m-pose { animation: m-x-gum-body var(--m-x-ms) both; }
@keyframes m-x-gum-body { 0%, 60% { transform: none; } 63% { transform: translateY(-5px) rotate(-4deg) scale(.97, 1.04); } 70% { transform: translateY(1px) rotate(1deg); } 78%, 100% { transform: none; } }

/* 6 · Schmetterling: one flutters in, lands on his head; he watches it, it flies off. */
.mascot[data-act="bfly"] { --m-x-ms: 5.4s; }
.mascot[data-act="bfly"] .m-x-bfly { animation: m-x-bfly var(--m-x-ms) both; }
@keyframes m-x-bfly {
  0% { opacity: 0; transform: translate(240px, 70px) rotate(-10deg); }
  4% { opacity: 1; }
  14% { transform: translate(196px, 22px) rotate(8deg); }
  24% { transform: translate(156px, 52px) rotate(-12deg); }
  33% { transform: translate(128px, -6px) rotate(10deg); }
  41%, 70% { opacity: 1; transform: translate(104px, var(--m-x-land, 2px)) rotate(-4deg); }
  78% { transform: translate(70px, -26px) rotate(-16deg); }
  88% { transform: translate(18px, 10px) rotate(10deg); }
  96% { opacity: 1; } 100% { opacity: 0; transform: translate(-40px, -30px) rotate(-12deg); }
}
.mascot[data-act="bfly"] .m-gaze { animation: m-x-bfly-eyes var(--m-x-ms) both; }
@keyframes m-x-bfly-eyes { 0% { transform: none; } 12% { transform: translate(6px, -3px); } 24% { transform: translate(5px, -1px); } 33% { transform: translate(3px, -6px); } 41%, 70% { transform: translate(0, -8px) scale(1.06); } 80% { transform: translate(-4px, -6px); } 90% { transform: translate(-6px, -2px); } 100% { transform: none; } }
.mascot[data-act="bfly"] .m-pose { animation: m-x-bfly-body var(--m-x-ms) both; }
@keyframes m-x-bfly-body { 0%, 34% { transform: none; } 42%, 70% { transform: rotate(-2deg) translateY(-1px); } 80%, 100% { transform: none; } }

/* 7 · Eindösen: the eyes fall shut, he nods off — and jerks awake. */
.mascot[data-act="doze"] { --m-x-ms: 4.6s; }
.mascot[data-act="doze"] .m-gaze { animation: m-x-doze-eyes var(--m-x-ms) both; }
@keyframes m-x-doze-eyes { 0% { transform: none; } 18% { transform: scaleY(.7); } 26% { transform: scaleY(.9); } 38% { transform: scaleY(.3); } 46%, 58% { transform: scaleY(.07); } 60% { transform: translateY(-2px) scale(1.3); } 68% { transform: translate(-6px, 0) scale(1.1); } 77% { transform: translate(6px, 0) scale(1.05); } 86%, 100% { transform: none; } }
.mascot[data-act="doze"] .m-pose { animation: m-x-doze-body var(--m-x-ms) both; }
@keyframes m-x-doze-body {
  0% { transform: none; } 30% { transform: translateY(2px) rotate(3deg); } 36% { transform: translateY(1px) rotate(1deg); }
  50% { transform: translateY(5px) rotate(7deg); } 58% { transform: translateY(6px) rotate(9deg); animation-timing-function: cubic-bezier(.2, .9, .3, 1); }
  61% { transform: translateY(-8px) rotate(-3deg) scale(.97, 1.05); } 68% { transform: translateY(1px) scale(1.02, .98); } 76%, 100% { transform: none; }
}
.mascot[data-act="doze"] .m-hat { animation: m-x-doze-hat var(--m-x-ms) both; }
@keyframes m-x-doze-hat { 0%, 30% { transform: none; } 56% { transform: translate(3px, 4px) rotate(8deg); } 61% { transform: translate(0, -12px) rotate(-8deg); } 68% { transform: translate(0, 2px) rotate(2deg); } 74%, 100% { transform: none; } }
.mascot[data-act="doze"] .m-x-z { transform-origin: 150px 44px; animation: m-x-z var(--m-x-ms) both; }
@keyframes m-x-z { 0%, 34% { opacity: 0; transform: translate(0, 6px) scale(.5); } 42% { opacity: 1; } 56% { opacity: .9; transform: translate(14px, -18px) scale(1.1); } 59%, 100% { opacity: 0; transform: translate(16px, -22px) scale(1.2); } }
.mascot[data-act="doze"] .m-x-bang { animation: m-x-doze-bang var(--m-x-ms) both; }
@keyframes m-x-doze-bang { 0%, 58% { opacity: 0; transform: scale(.3); } 62% { opacity: 1; transform: scale(1.15); } 66%, 78% { opacity: 1; transform: none; } 84%, 100% { opacity: 0; } }

/* 8 · Pfeifen: lips pursed, looking away innocently, notes rising, a sway. */
.mascot[data-act="whistle"] { --m-x-ms: 4.2s; }
.mascot[data-act="whistle"] .m-x-oh { animation: m-x-whistle-mouth var(--m-x-ms) both; }
@keyframes m-x-whistle-mouth { 0%, 5% { opacity: 0; transform: scale(.3); } 10% { opacity: 1; transform: scale(.9); } 30% { transform: scale(.75); opacity: 1; } 50% { transform: scale(.9); opacity: 1; } 70% { transform: scale(.75); opacity: 1; } 88% { opacity: 1; transform: scale(.85); } 93%, 100% { opacity: 0; transform: scale(.3); } }
.mascot[data-act="whistle"] .m-gaze { animation: m-x-whistle-eyes var(--m-x-ms) both; }
@keyframes m-x-whistle-eyes { 0% { transform: none; } 10%, 84% { transform: translate(4px, -5px); } 92%, 100% { transform: none; } }
.mascot[data-act="whistle"] .m-pose { animation: m-x-whistle-body var(--m-x-ms) both; }
@keyframes m-x-whistle-body { 0% { transform: none; } 20% { transform: rotate(-3deg); } 40% { transform: rotate(2.5deg) translateY(-1px); } 60% { transform: rotate(-2.5deg); } 80% { transform: rotate(2deg) translateY(-1px); } 100% { transform: none; } }
.mascot[data-act="whistle"] .m-x-note { transform-origin: 120px 100px; animation: m-x-note 1.7s ease-out both; }
.mascot[data-act="whistle"] .m-x-note:nth-child(2) { animation-delay: .9s; }
.mascot[data-act="whistle"] .m-x-note:nth-child(3) { animation-delay: 1.9s; }
@keyframes m-x-note { 0% { opacity: 0; transform: translate(0, 0) scale(.4) rotate(-10deg); } 15% { opacity: 1; } 50% { transform: translate(26px, -34px) scale(1) rotate(8deg); } 100% { opacity: 0; transform: translate(46px, -74px) scale(.9) rotate(-8deg); } }

/* ── Where it sits ─────────────────────────────────────────────────────── */
/* Today: on the card of what to do now, dressed for the language at hand */
.hero-wrap { position: relative; }
.hero-buddy { position: absolute; top: 8px; right: 8px; width: 96px; height: 96px; z-index: 2; }
html:not([data-mascot="off"]) .hero-wrap .hero :is(.hero-eyebrow, .hero-big, .hero-title) { margin-right: 92px; }
html:not([data-mascot="off"]) .hero-wrap .hero-art { display: none; }
/* A set's page: beside the title, dressed for the set's language */
.set-hero { position: relative; }
.set-buddy { position: absolute; top: -8px; right: -6px; width: 96px; height: 96px; }
html:not([data-mascot="off"]) .set-hero:has(.set-buddy) :is(.set-meta, .set-title, .mbar) { margin-right: 88px; }   /* the bar too: Voki stood on its end (the test report) */
/* The stage, the result, empty screens */
.empty-mascot.m-host { width: 180px; height: 180px; margin: 0 auto 4px; }
.empty-set .m-host { width: 130px; height: 130px; margin: 0 auto; }
/* Toasts: it says them */
.toast-buddy { flex: none; width: 36px; height: 36px; margin: -8px -8px -8px -10px; }
.toast-buddy .mascot { width: 36px; height: 36px; }
/* A set's card: the whole Voki in the badge, dressed for the set's language
   (js/mascot/setVokis.js; the owner's pick A of tools/drafts/set-voki-design.html). The
   drawing is a little bigger than the badge — its hat and what it holds
   reach over the edge. Out of sight its loops rest (.off); arriving, it hops
   into its card (.sv-in, --sv-d after the card's own rise); with the effects
   off nothing on it moves. */
.set-ic .sv { position: absolute; left: -6px; top: -4px; width: 68px; height: 68px; pointer-events: none; }
.sv .m-shadow { display: none; }
/* The cards' Vokis are small (68 px) and drawn without the SVG filters — the hat's and the held
   thing's bevel light, the body's lift, the soft cheeks: at that size they hardly show, and they
   cost a moving Voki most of its frame. On the LG with eight of them moving while the page
   scrolls (they no longer hold still then, 2026-10-02), 69 % of the frames came late with the
   filters, 17 % without (still Vokis: 6 %). */
.sv .mascot, .sv .mascot * { filter: none !important; }
/* out of sight (setVokis.js, buddy.js): at rest. While the page scrolls they go on (2026-10-02,
   the owner) — each a layer of its own, so its frames do not redraw the page under it. */
.m-host.off * { animation-play-state: paused !important; }
.m-host { will-change: transform; }
.sv.sv-in { animation: sv-in .6s var(--spring) var(--sv-d, 0s) both; }
@keyframes sv-in { 0% { opacity: 0; transform: translateY(16px) scale(.5); } 60% { opacity: 1; } 100% { opacity: 1; transform: none; } }
html[data-mascot-motion="off"] .sv * { animation: none !important; }
/* The editor's set icon: its face on the language's colour */
.set-ic .m-glyph { width: 27px; height: 27px; margin-top: 2px; filter: drop-shadow(0 1.5px 1.5px rgba(0, 20, 70, .3)); }
html:not([data-mascot="off"]) .set-ic .ic { display: none; }
html[data-mascot="off"] .set-ic .m-glyph { display: none; }

/* Profile → "Mascot" off: none anywhere. */
html[data-mascot="off"] :is(.mascot, .m-host, .toast-buddy, .dlg-art) { display: none !important; }

/* ── Solid styles (mascot.js `style`; compare: tools/labs/mascot-styles.html) ─── */
.mascot :is(.m-spec, .m-spec2, .m-sclera, .m-inner) { display: none; }
.mascot:not([data-style="flat"]) .m-fill { fill: var(--m-g-body); }
.mascot:not([data-style="flat"]) .m-shade { fill: var(--m-g-shade); }
.mascot:not([data-style="flat"]) .m-spec { display: inline; fill: var(--m-g-spec); }
.mascot:not([data-style="flat"]) .m-shadow { fill: rgba(10, 40, 110, .24); filter: var(--m-g-soft); }
.mascot:not([data-style="flat"]) .m-cheeks { filter: var(--m-g-blur); }
.mascot:not([data-style="flat"]) .m-eyes ellipse:not(.m-sclera) { fill: var(--m-g-eye); }
.mascot:not([data-style="flat"]) :is(.m-acc, .m-held) { filter: var(--m-g-bevel); }
.mascot:not([data-style="flat"]) .m-acc :is(path, circle, ellipse),
.mascot:not([data-style="flat"]) .m-held :is(path, circle, ellipse, rect) { stroke: rgba(8, 24, 70, .3); stroke-width: 1.4; }
.mascot:not([data-style="flat"]) .m-held .m-held-o { stroke: #7A4515; stroke-width: 7.5; }
.mascot:not([data-style="flat"]) .m-ear .m-stroke { stroke: rgba(40, 70, 140, .45); }
/* Soft 3D: matte, lit from the top left, no outline */
.mascot:is([data-style="clay"], [data-style="glass"]) .m-body > .m-fill { filter: var(--m-g-lift); }
.mascot[data-style="clay"] .m-line { stroke: #9DB4E3; stroke-width: 1.8; opacity: .85; }
.mascot[data-style="clay"] .m-arm-o { stroke: #BDD0F2; }
.mascot[data-style="clay"] .m-arm-f { stroke: #FFF; stroke-width: 9; }
.mascot[data-style="clay"] .m-hand { fill: var(--m-g-body); stroke: #BDD0F2; stroke-width: 2; }
/* Liquid Glass: see-through, a bright rim, the glass's thickness inside */
.mascot[data-style="glass"] .m-line { stroke: var(--m-g-rim); stroke-width: 3; }
.mascot[data-style="glass"] .m-inner { display: inline; fill: none; stroke: rgba(255, 255, 255, .55); stroke-width: 12; clip-path: var(--m-g-clip); filter: var(--m-g-blur); }
.mascot[data-style="glass"] .m-arm-o { stroke: rgba(110, 160, 235, .55); }
.mascot[data-style="glass"] .m-arm-f { stroke: rgba(255, 255, 255, .92); stroke-width: 8; }
.mascot[data-style="glass"] .m-hand { fill: var(--m-g-body); stroke: rgba(255, 255, 255, .9); stroke-width: 2.5; }
.mascot[data-style="glass"] .m-spec2 { display: inline; fill: #FFF; opacity: .9; }
/* Vinyl: glossy, in the brand blue, big white eyes */
.mascot[data-style="gloss"] { --m-ink: #061A4F; }
.mascot[data-style="gloss"] .m-line { stroke: #03348C; stroke-width: 2.5; }
.mascot[data-style="gloss"] .m-arm-o { stroke: #03348C; }
.mascot[data-style="gloss"] .m-arm-f { stroke: #2F8FFF; stroke-width: 7; }
.mascot[data-style="gloss"] .m-hand { fill: var(--m-g-body); stroke: #03348C; stroke-width: 2.5; }
.mascot[data-style="gloss"] .m-sclera { display: inline; fill: #FFF; }
.mascot[data-style="gloss"] .m-spec2 { display: inline; fill: #FFF; opacity: .95; }
.mascot[data-style="gloss"] .m-cheeks { fill: #FF8FB8; opacity: .75; }
.mascot[data-style="gloss"] .m-ear .m-stroke { stroke: #03348C; }

/* ── Soft 3D across the app (the mascot’s material; token --soft-3d) ── */
.set-ic, .row-ic, .tips .ic, .stat-ic, .res-badge {
  /* !important: the older, more specific rules (.stat-ic.known, .stat.lit .stat-ic.flame …)
     set pale tints; here only --c differs between them */
  --cc: var(--c, var(--gray));
  background: radial-gradient(130% 130% at 32% 22%, color-mix(in srgb, var(--cc) 45%, #fff) 0%, var(--cc) 46%, color-mix(in srgb, var(--cc) 76%, #000) 100%) !important;
  box-shadow: var(--soft-3d) !important; color: #FFF !important;
}
.stat-ic { --c: #AEAEB2; }
.stat.lit .stat-ic.flame { --c: var(--orange); color: #FFF; }
.stat-ic.known { --c: var(--green); color: #FFF; }
.stat-ic.goal { --c: var(--blue); color: #FFF; }
.stat-ic.mic { --c: var(--purple); color: #FFF; }
.tips .ic { --c: var(--orange); }
.tips li:nth-child(2) .ic { --c: var(--red); }
.tips li:nth-child(3) .ic { --c: var(--blue); }
.fx-badge .ic { box-shadow: inset 0 1.5px 1px rgba(255, 255, 255, .5), inset 0 -2.5px 4px rgba(0, 20, 70, .25), 0 6px 16px -6px rgba(0, 0, 0, .5); }
/* the little illustrations: pages with a soft curve, the orb lit */
.si-page, .as-page { background: linear-gradient(160deg, #FFF 0%, #F1F5FC 100%); }
.si-page { box-shadow: inset 0 1px 0 #FFF, inset 0 -3px 5px rgba(20, 50, 120, .08), 0 12px 30px rgba(0, 0, 0, .14), 0 1px 3px rgba(0, 0, 0, .1); }
.ap-orb {
  background: radial-gradient(120% 120% at 32% 24%, #6BB6FF 0%, #0A84FF 50%, #0058D6 100%);
  box-shadow: inset 0 2px 1px rgba(255, 255, 255, .45), inset 0 -4px 8px rgba(0, 30, 110, .35), 0 8px 30px rgba(10, 132, 255, .6);
}

/* ─── Onboarding (OnboardingView): hello → languages → try it → goal → account ─── */
.ob { gap: 0; }
.ob-top { display: grid; grid-template-columns: 44px 1fr 44px; align-items: center; gap: 12px; min-height: 48px; }
.ob-top-gap { width: 44px; }
.ob-progress { height: 6px; border-radius: 99px; background: var(--fill-3); overflow: hidden; }
.ob-progress i { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--tint); transition: width .5s var(--ease); }
.ob[data-step="hello"] .ob-progress { visibility: hidden; }
/* one mascot through every step; it grows and shrinks with the room a step needs */
.ob-mascot { display: flex; justify-content: center; flex: none; height: 150px; margin: 6px 0 4px; transition: height .45s var(--ease); }
.ob-mascot .mascot { width: auto; height: 100%; }
.ob[data-step="hello"] .ob-mascot { height: min(300px, 36vh); margin-top: 40px; }
.ob[data-step="try"] .ob-mascot { height: 128px; }
.ob[data-step="account"] .ob-mascot { height: 136px; }
.ob-body { flex: 1; display: flex; flex-direction: column; animation: nav-fade .35s ease both; }
.ob-copy { text-align: center; margin-bottom: 18px; }
.ob-h { font: 700 clamp(24px, calc(var(--vw) * 7.2), 28px) / 1.2 var(--font-rounded); margin: 0 0 8px; }
.ob-sub { color: var(--label-2); font-size: 16px; line-height: 1.4; margin: 0 auto; max-width: 34ch; }
.ob-actions { margin-top: auto; padding-top: 18px; display: flex; flex-direction: column; gap: 10px; }
.ob-actions .fine { text-align: center; margin: 4px 0 0; }
/* the steps before the account (OnboardingView bar): the main button in one place on every
   step — a quiet second choice under it, or its room kept —, sticky at the bottom so a step
   taller than the screen (the LG's 680 px) scrolls under it. Its box reaches down to the
   screen's edge (the frame's and the view's bottom padding, given back by the margin): at rest
   it stands exactly where the sticky bar stands while scrolling. */
.ob:has(> .ob-body > .ob-bar) { padding-bottom: 0; }   /* the bar keeps the bottom room itself */
.ob-bar { --ob-under: var(--view-pb);
  position: sticky; z-index: 3; bottom: 0; gap: 2px; margin-bottom: calc(-1 * var(--ob-under)); padding-bottom: var(--ob-under);
  background: linear-gradient(to bottom, color-mix(in srgb, var(--bg) 0%, transparent), var(--bg) 18px); }
.ob-alt { min-height: 42px; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ob-alt .obt-skip { margin-top: 0; padding: 8px 18px; }
/* a small phone (the LG: 360 × 680): Voki smaller, so every step fits above the bar */
@media (max-height: 700px) {
  .ob-mascot { height: 112px; }
  .ob[data-step="try"] .ob-mascot { height: 100px; }
  .onb.ob[data-step="goal"] .ob-mascot { height: 92px; }   /* .onb: over the goal's own rule further down */
  .ob .obg-hero { height: 90px; }
  .ob-copy { margin-bottom: 12px; }
}
.ob[data-step="hello"] .ob-copy { margin-top: 18px; }

/* which languages */
.ob-chips { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ob-chip {
  display: flex; align-items: center; gap: 10px; min-height: 56px; padding: 0 14px; border-radius: 18px;
  background: var(--bg-2); font-size: 16px; font-weight: 600; text-align: left;
  box-shadow: inset 0 0 0 2px transparent; transition: box-shadow .2s, background-color .2s, transform .2s var(--spring);
}
.ob-chip:active { transform: scale(.97); }
.ob-chip.on { background: var(--tint-soft); box-shadow: inset 0 0 0 2px var(--tint); }
.ob-flag { font-size: 24px; line-height: 1; }

/* try it: the card, the mic, the choices */
.ob-eyebrow { text-align: center; font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--tint); margin: 0 0 10px; }
.ob-top-gap { position: relative; }
.obt-run { position: absolute; right: 0; top: 50%; margin-top: -15px; height: 30px; padding: 0 10px; border-radius: 99px; white-space: nowrap; pointer-events: none;
  background: rgba(255, 159, 10, .18); color: #FFB340; font: 800 15px var(--font-rounded); display: flex; align-items: center;
  opacity: 0; transform: scale(.4); transition: opacity .3s, transform .45s cubic-bezier(.34, 1.8, .64, 1); }
.ob[data-run] .obt-run { opacity: 1; transform: none; }
/* the card: it glows while it is read and turns over green when answered */
.obt-flip { position: relative; height: 168px; perspective: 900px; flex: none; }
.obt-card { position: absolute; inset: 0; transform-style: preserve-3d; transition: transform .7s cubic-bezier(.3, 1.3, .5, 1); }
.obt-flip.right .obt-card { transform: rotateY(180deg); }
.obt-face { position: absolute; inset: 0; padding: 0 16px; border-radius: 26px; color: var(--label); text-align: center; -webkit-backface-visibility: hidden; backface-visibility: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: linear-gradient(180deg, var(--bg-2), var(--bg)); border: 1px solid var(--fill-3);
  box-shadow: 0 20px 40px -18px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .12); transition: box-shadow .4s; }
.obt-flip.reading .obt-front { box-shadow: 0 20px 40px -18px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .12), 0 0 0 3px color-mix(in srgb, var(--tint) 50%, transparent), 0 0 40px color-mix(in srgb, var(--tint) 35%, transparent); }
.obt-q { font: 800 12.5px var(--font-rounded); letter-spacing: .08em; text-transform: uppercase; color: var(--label-2); }
.obt-word { font: 800 42px / 1.1 var(--font-rounded); margin: 6px 0 8px; overflow-wrap: anywhere; }
.obt-eq { display: flex; gap: 4px; height: 20px; align-items: center; }
.obt-eq i { width: 4px; height: 100%; border-radius: 2px; background: var(--tint); transform: scaleY(.25); }
.obt-flip.reading .obt-eq i { animation: obt-eq .5s ease-in-out infinite; }
.obt-flip.reading .obt-eq i:nth-child(2) { animation-delay: -.15s; }
.obt-flip.reading .obt-eq i:nth-child(3) { animation-delay: -.3s; }
.obt-flip.reading .obt-eq i:nth-child(4) { animation-delay: -.1s; }
.obt-flip.reading .obt-eq i:nth-child(5) { animation-delay: -.25s; }
@keyframes obt-eq { 0%, 100% { transform: scaleY(.3); } 50% { transform: scaleY(1); } }
.obt-say { position: absolute; right: 10px; top: 10px; color: var(--label); background: var(--fill-3); }
.obt-back { transform: rotateY(180deg); border-color: transparent; color: #fff; background: radial-gradient(130% 130% at 30% 18%, #7BE69A 0%, #30C455 48%, #1F9A40 100%); }
.obt-back b { display: flex; align-items: center; gap: 10px; font: 800 32px var(--font-rounded); }
.obt-back b .ic { width: 32px; height: 32px; stroke-width: 3.2; }
.obt-back span { margin-top: 4px; font-size: 15px; font-weight: 700; opacity: .9; }
.obt-sparks { position: absolute; left: 50%; top: 50%; width: 0; height: 0; z-index: 5; }
.obt-flip.right .obh-spark { animation: obh-spark .9s .25s cubic-bezier(.2, .7, .3, 1) forwards; }
/* the answer: shown in the field; what is heard is written over it */
.obt-field { width: 100%; margin-top: 16px; min-height: 58px; padding: 0 18px; border-radius: 18px; flex: none; color: var(--label); text-align: left;
  background: var(--fill-4); border: 1.5px solid var(--fill-3); display: flex; align-items: center; gap: 10px;
  transition: border-color .3s, background .3s, transform .2s var(--spring); }
.obt-field:active:not(:disabled) { transform: scale(.98); }
.obt-field small { flex: none; color: var(--label-2); font-weight: 700; font-size: 14px; }
.obt-ans { position: relative; min-width: 0; font: 800 22px var(--font-rounded); }
.obt-ghost { color: var(--label-3); transition: opacity .2s; }
.obt-heard { position: absolute; left: 0; top: 0; color: var(--label); white-space: nowrap; }
.obt-field.heard .obt-ghost { opacity: 0; }
.obt-ok { margin-left: auto; width: 30px; height: 30px; flex: none; border-radius: 50%; background: #30D158; color: #fff; display: grid; place-items: center;
  transform: scale(0); transition: transform .45s cubic-bezier(.34, 1.8, .64, 1); }
.obt-ok .ic { width: 18px; height: 18px; stroke-width: 3.2; }
.obt-field.listening { border-color: color-mix(in srgb, var(--tint) 80%, transparent); background: color-mix(in srgb, var(--tint) 10%, transparent); }
.obt-field.right { border-color: #30D158; background: rgba(48, 209, 88, .12); }
.obt-field.right .obt-ok { transform: none; }
.obt-field:disabled { opacity: 1; }
/* the mic: blue throughout; listening, one ring follows the voice, one breathes */
.obt-micwrap { flex: 1; min-height: 150px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; }
.obt-mic { --lvl: 0; position: relative; width: 88px; height: 88px; border-radius: 50%; display: grid; place-items: center; color: #fff;
  background: radial-gradient(130% 130% at 32% 22%, #6BB6FF 0%, #0A84FF 50%, #0058D6 100%);
  box-shadow: 0 10px 30px rgba(10, 132, 255, .55), inset 0 2px 1px rgba(255, 255, 255, .4); transition: box-shadow .3s; }
.obt-mic .ic { width: 36px; height: 36px; }
.obt-mic::before, .obt-mic::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 3px solid #0A84FF; opacity: 0; pointer-events: none; }
.obt-mic:not(.on):not(:disabled) { animation: ob-invite 1.8s ease-in-out .8s infinite; }
.obt-mic:not(.on):not(:disabled)::before { animation: obt-ring 1.8s ease-out .8s infinite; }
.obt-mic.on { box-shadow: 0 10px 30px rgba(10, 132, 255, .55), 0 0 44px rgba(10, 132, 255, .55), inset 0 2px 1px rgba(255, 255, 255, .4); }
.obt-mic.on::before { opacity: .6; transform: scale(calc(1.12 + var(--lvl) * .6)); transition: transform .08s; }
.obt-mic.on::after { animation: obt-breathe 1.4s ease-in-out infinite; }
.obt-mic:disabled { opacity: 1; }
@keyframes obt-ring { from { transform: scale(1); opacity: .6; } to { transform: scale(1.7); opacity: 0; } }
@keyframes obt-breathe { 0%, 100% { transform: scale(1.2); opacity: .28; } 50% { transform: scale(1.5); opacity: .1; } }
.obt-label { margin: 0; min-height: 20px; text-align: center; font-size: 15px; font-weight: 700; color: var(--label); }
.obt-tap { font-size: 14px; font-weight: 600; color: var(--label-2); text-decoration: underline; text-underline-offset: 3px; }
.obt-tap:disabled { visibility: hidden; }
.obt-skip { align-self: center; margin-top: 4px; padding: 10px 18px; font-size: 14px; font-weight: 600; color: var(--label-3); }
@media (max-height: 700px) { .obt-flip { height: 150px; } .obt-mic { width: 76px; height: 76px; } .obt-micwrap { gap: 8px; min-height: 0; } }
@media (prefers-reduced-motion: reduce) { .obt-card { transition: none; } .obt-mic:not(.on):not(:disabled), .obt-mic:not(.on):not(:disabled)::before { animation: none; } }
/* "That's how it works!" (OnboardingView howHTML / playHow): one scene on a loop —
   a page is photographed (viewfinder, flash), turns into cards, the top card is
   asked, answered out loud, turns green. The state classes s-* sit on the scene. */
.obh-scene { position: relative; width: min(330px, 100%); height: 290px; margin: 4px auto 0; flex: none; }
.ob-body > .obh-scene { margin-top: auto; }   /* the scene and its steps in the middle of the free room */
.obh-reset, .obh-reset * { transition: none !important; animation: none !important; }
.obh-scene { transition: opacity .5s ease, transform .55s ease; }
.obh-scene.s-out { opacity: 0; transform: scale(.94); }
.obh-ic { --cc: var(--blue); position: relative; display: grid; place-items: center; color: #fff; box-shadow: var(--soft-3d);
  background: radial-gradient(130% 130% at 32% 22%, color-mix(in srgb, var(--cc) 45%, #fff) 0%, var(--cc) 46%, color-mix(in srgb, var(--cc) 76%, #000) 100%); }
.obh-page { position: absolute; left: 50%; top: 22px; width: 178px; height: 224px; margin-left: -89px; padding: 14px 13px; border-radius: 10px; color: #1D2A44; overflow: hidden;
  background: linear-gradient(160deg, #FFF 0%, #EEF3FB 100%); box-shadow: inset 0 1px 0 #FFF, 0 14px 30px rgba(0, 0, 0, .28), 0 1px 3px rgba(0, 0, 0, .15);
  opacity: 0; transform: translateY(46px) rotate(-5deg); transition: opacity .5s, transform .7s var(--spring); }
.obh-pg-h { font: 800 10px var(--font-rounded); color: #0A6AE0; letter-spacing: .04em; text-transform: uppercase; margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.obh-pg-r { display: flex; justify-content: space-between; gap: 6px; font-size: 10.5px; line-height: 1.25; padding: 4.5px 0; border-bottom: 1px solid #DDE4F0; white-space: nowrap; }
.obh-pg-r b { font-weight: 700; }
.obh-pg-r span { color: #5B6B8C; }
.obh-vf { position: absolute; left: 50%; top: 4px; width: 214px; height: 262px; margin-left: -107px; pointer-events: none;
  opacity: 0; transform: scale(1.3); transition: opacity .3s, transform .4s cubic-bezier(.2, .9, .3, 1.25); }
.obh-vf i { position: absolute; width: 26px; height: 26px; border: 3.5px solid var(--tint); }
.obh-vf i:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0; border-top-left-radius: 10px; }
.obh-vf i:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0; border-top-right-radius: 10px; }
.obh-vf i:nth-child(3) { left: 0; bottom: 0; border-right: 0; border-top: 0; border-bottom-left-radius: 10px; }
.obh-vf i:nth-child(4) { right: 0; bottom: 0; border-left: 0; border-top: 0; border-bottom-right-radius: 10px; }
.obh-flash { position: absolute; inset: -10px; border-radius: 24px; background: #FFF; opacity: 0; pointer-events: none; }
.obh-card { position: absolute; left: 50%; top: 66px; width: 196px; height: 120px; margin-left: -98px; padding: 0 12px; border-radius: 18px; color: #fff;
  display: grid; place-items: center; text-align: center; font: 800 22px / 1.15 var(--font-rounded);
  background: radial-gradient(130% 130% at 30% 18%, #6CB4FF 0%, #0A84FF 48%, #0058D6 100%);
  box-shadow: inset 0 1.5px 1px rgba(255, 255, 255, .5), inset 0 -3px 6px rgba(0, 20, 80, .3), 0 12px 24px -8px rgba(0, 40, 120, .6);
  opacity: 0; transform: translateY(30px) scale(.3); transition: transform .6s var(--spring), opacity .35s, background .4s; }
.obh-card.k1 { z-index: 1; } .obh-card.k2 { z-index: 2; } .obh-card.k3 { z-index: 3; }
.obh-check { position: absolute; right: -10px; top: -10px; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; background: #FFF; color: var(--green);
  box-shadow: 0 6px 14px rgba(0, 0, 0, .35); transform: scale(0); transition: transform .45s cubic-bezier(.34, 1.8, .64, 1); }
.obh-check .ic { width: 22px; height: 22px; stroke-width: 3.4; }
.obh-mic { --cc: var(--green); position: absolute; left: calc(50% - 118px); top: 204px; width: 60px; height: 60px; border-radius: 50%;
  opacity: 0; transform: scale(.3); transition: transform .5s var(--spring), opacity .3s; }
.obh-mic .ic { width: 28px; height: 28px; }
.obh-mic::before, .obh-mic::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 2.5px solid var(--green); opacity: 0; }
.obh-said { position: absolute; left: calc(50% - 40px); top: 214px; padding: 9px 14px; border-radius: 18px; background: #FFF; color: #0B2A6B; white-space: nowrap;
  font: 800 17px var(--font-rounded); box-shadow: inset 0 -2.5px 4px rgba(20, 50, 120, .12), 0 8px 20px -6px rgba(0, 0, 0, .5);
  opacity: 0; transform: scale(.3); transform-origin: 0 50%; transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), opacity .25s; }
.obh-said::before { content: ''; position: absolute; left: -7px; top: 50%; width: 14px; height: 14px; margin-top: -7px; background: inherit; transform: rotate(45deg); border-radius: 3px; }
.obh-sparks { position: absolute; left: 50%; top: 96px; width: 0; height: 0; z-index: 5; }
.obh-spark { position: absolute; left: 50%; top: 50%; width: 9px; height: 9px; margin: -4.5px; border-radius: 3px; opacity: 0; background: var(--sc, #FFD60A); }
.obh-spark:nth-child(3n + 1) { border-radius: 50%; }
@keyframes obh-ring { from { transform: scale(1); opacity: .7; } to { transform: scale(1.9); opacity: 0; } }
@keyframes obh-spark { from { transform: rotate(var(--a)) translateY(0) scale(1); opacity: 1; } to { transform: rotate(var(--a)) translateY(-86px) scale(.3) rotate(90deg); opacity: 0; } }
@keyframes obh-flash { 0% { opacity: 0; } 12% { opacity: .95; } 100% { opacity: 0; } }
.obh-scene.s-page .obh-page { opacity: 1; transform: rotate(-5deg); }
.obh-scene.s-snap .obh-vf { opacity: 1; transform: scale(1); }
.obh-scene.s-flash .obh-flash { animation: obh-flash .6s ease-out; }
.obh-scene.s-cards .obh-page { opacity: 0; transform: scale(.45) rotate(-5deg); transition: opacity .4s, transform .5s ease-in; }
.obh-scene.s-cards .obh-vf { opacity: 0; transform: scale(.55); transition: opacity .3s, transform .4s ease-in; }
.obh-scene.s-cards .obh-card { opacity: 1; }
.obh-scene.s-cards .obh-card.k1 { transform: translate(-62px, 14px) rotate(-14deg) scale(.8); }
.obh-scene.s-cards .obh-card.k2 { transform: translate(62px, 14px) rotate(14deg) scale(.8); transition-delay: .1s; }
.obh-scene.s-cards .obh-card.k3 { transform: translate(0, -6px) scale(.92); transition-delay: .2s; }
.obh-scene.s-stack .obh-card.k1 { transform: translate(-10px, 16px) rotate(-7deg) scale(.9); transition-delay: 0s; }
.obh-scene.s-stack .obh-card.k2 { transform: translate(10px, 9px) rotate(6deg) scale(.94); transition-delay: 0s; }
.obh-scene.s-stack .obh-card.k3 { transform: none; transition-delay: 0s; }
.obh-scene.s-quiz .obh-card.k1, .obh-scene.s-quiz .obh-card.k2 { opacity: .35; transform: translate(0, -18px) scale(.84); }
.obh-scene.s-quiz .obh-card.k3 { transform: translateY(-34px) scale(1.08); }
.obh-scene.s-mic .obh-mic { opacity: 1; transform: none; }
.obh-scene.s-mic:not(.s-right) .obh-mic::before { animation: obh-ring 1.3s ease-out infinite; }
.obh-scene.s-mic:not(.s-right) .obh-mic::after { animation: obh-ring 1.3s ease-out .65s infinite; }
.obh-scene.s-said .obh-said { opacity: 1; transform: none; }
.obh-scene.s-right .obh-card.k3 { background: radial-gradient(130% 130% at 30% 18%, #7BE69A 0%, #30C455 48%, #1F9A40 100%); }
.obh-scene.s-right .obh-check { transform: none; }
.obh-scene.s-right .obh-spark { animation: obh-spark .9s cubic-bezier(.2, .7, .3, 1) forwards; }
/* the three steps under it: the one the scene shows lights up */
.obh-steps { list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0 0; padding: 0; }
.obh-step { display: flex; align-items: center; justify-content: center; gap: 7px; padding: 7px 6px; border-radius: 99px; background: var(--fill-4); color: var(--label-3);
  font-weight: 700; font-size: 13.5px; white-space: nowrap; transition: background .35s, color .35s, transform .45s var(--spring); }
.obh-step:nth-child(2) { --cc: var(--indigo); } .obh-step:nth-child(3) { --cc: var(--green); }
.obh-step .obh-ic { width: 24px; height: 24px; border-radius: 8px; box-shadow: none; filter: saturate(.2) opacity(.55); transition: filter .35s; }
.obh-step:nth-child(2) .obh-ic { --cc: var(--indigo); } .obh-step:nth-child(3) .obh-ic { --cc: var(--green); }
.obh-step .obh-ic .ic { width: 14px; height: 14px; }
.obh-step.on { --cc: var(--blue); background: color-mix(in srgb, var(--cc) 20%, transparent); color: var(--label); transform: scale(1.06); }
.obh-step:nth-child(2).on { --cc: var(--indigo); } .obh-step:nth-child(3).on { --cc: var(--green); }
.obh-step.on .obh-ic, .obh-step.done .obh-ic { filter: none; }
.obh-step.done { color: var(--label-2); }
/* a short screen: the scene a little smaller, so "Next" stays in view */
@media (max-height: 740px) { .obh-scene { zoom: .82; } }

/* the daily goal (OnboardingView goalHTML / bindGoal): a slider with three
   stops, a flame that grows with the goal, the number, the week it makes */
.ob[data-step="goal"] .ob-mascot { height: 124px; }
.obg { flex: none; }
.ob-body > .obg { margin-top: auto; }
.obg-hero { display: flex; align-items: flex-end; justify-content: center; gap: 12px; height: 104px; }
.obg-flame { position: relative; width: 70px; height: 96px; transform-origin: 50% 100%; transition: transform .7s var(--spring); }
.obg-flame svg { width: 100%; height: 100%; overflow: visible; transform-origin: 50% 100%; animation: obg-flicker 1.4s ease-in-out infinite; filter: drop-shadow(0 6px 16px rgba(255, 120, 20, .45)); }
@keyframes obg-flicker { 0%, 100% { transform: scale(1, 1) skewX(0); } 30% { transform: scale(.97, 1.05) skewX(-2deg); } 60% { transform: scale(1.03, .96) skewX(2deg); } }
.obg-flame[data-n="10"] { transform: scale(.62); }
.obg-flame[data-n="20"] { transform: scale(.86); }
.obg-flame[data-n="40"] { transform: scale(1.12); }
.obg-ember { position: absolute; left: 50%; bottom: 40%; width: 6px; height: 6px; margin-left: -3px; border-radius: 50%; background: #FFB340; opacity: 0; }
.obg-flame[data-n="40"] .obg-ember { animation: obg-ember 1.4s ease-out infinite; }
.obg-ember:nth-of-type(2) { animation-delay: .45s !important; --x: -18px; }
.obg-ember:nth-of-type(3) { animation-delay: .9s !important; --x: 16px; }
@keyframes obg-ember { from { transform: translate(0, 0) scale(1); opacity: 1; } to { transform: translate(var(--x, 6px), -70px) scale(.2); opacity: 0; } }
.obg-num { padding-bottom: 6px; }
.obg-num b { display: block; font: 800 64px / .95 var(--font-rounded); font-variant-numeric: tabular-nums; min-width: 2ch; }
.obg-num small { display: block; font-size: 15px; font-weight: 700; color: var(--label-2); margin-top: 4px; }
.obg-time { text-align: center; color: var(--label-2); font-size: 15px; font-weight: 600; margin: 8px 0 0; }
.obg-slider { position: relative; height: 46px; margin: 12px 4px 0; touch-action: none; cursor: pointer; border-radius: 99px; --p: .5; }
.obg-slider:focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; }
.obg-track, .obg-fill { position: absolute; top: 50%; height: 10px; margin-top: -5px; border-radius: 99px; }
.obg-track { left: 14px; right: 14px; background: var(--fill-3); }
.obg-fill { left: 14px; width: calc((100% - 28px) * var(--p)); background: linear-gradient(90deg, #FFD60A, #FF9F0A 55%, #FF453A); transition: width .55s var(--spring); }
.obg-stop { position: absolute; top: 50%; left: 14px; width: 6px; height: 6px; margin: -3px; border-radius: 50%; background: var(--label-3); }
.obg-stop:nth-of-type(4) { left: 50%; }
.obg-stop:nth-of-type(5) { left: calc(100% - 14px); }
.obg-thumb { position: absolute; top: 50%; left: calc(14px + (100% - 28px) * var(--p)); width: 34px; height: 34px; margin: -17px; border-radius: 50%; background: #FFF;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .35), 0 0 0 .5px rgba(0, 0, 0, .1); transition: left .55s var(--spring); display: grid; place-items: center; font-size: 17px; }
.obg-slider.drag .obg-thumb, .obg-slider.drag .obg-fill { transition-duration: .2s; }
.obg-labels { display: grid; grid-template-columns: repeat(3, 1fr); }
.obg-labels button { font-weight: 700; font-size: 14.5px; color: var(--label-3); padding: 4px 0; transition: color .3s, transform .4s var(--spring); }
.obg-labels button:first-child { text-align: left; }
.obg-labels button:last-child { text-align: right; }
.obg-labels button.on { color: var(--label); transform: scale(1.06); }
.obg-week { margin-top: 18px; padding: 14px 16px 16px; border-radius: 22px; background: var(--bg-2); }
.obg-week-h { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 12px; font-size: 14px; color: var(--label-2); font-weight: 600; }
.obg-week-h b { color: var(--label); font: 800 17px var(--font-rounded); font-variant-numeric: tabular-nums; }
.obg-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; text-align: center; }
.obg-day i { display: grid; place-items: center; width: 34px; height: 34px; margin: 0 auto 4px; border-radius: 50%; background: var(--fill-3); color: #fff; transition: background .3s; }
.obg-day i .ic { width: 16px; height: 16px; stroke-width: 3; opacity: 0; }
.obg-day.lit i { background: radial-gradient(130% 130% at 32% 22%, #FFD27A 0%, #FF9F0A 50%, #E0600A 100%); box-shadow: 0 4px 10px -4px rgba(255, 120, 20, .7); animation: obg-pop .45s var(--spring) both; }
.obg-day.lit i .ic { opacity: 1; }
.obg-day small { font-size: 11.5px; color: var(--label-3); font-weight: 600; }
@keyframes obg-pop { 0% { transform: scale(.4); opacity: 0; } 70% { transform: scale(1.12); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .obg-flame svg, .obg-flame .obg-ember { animation: none; } }
@media (max-height: 740px) { .obg { zoom: .86; } .ob[data-step="goal"] .ob-mascot { height: 100px; } }

/* the account */
/* the account's first view (OnboardingView accountHTML, "choose"): the learner's
   own start page builds itself behind glass, then a sheet with the sign-in
   slides up (.sheet) and Voki peeks over its edge; .intro plays it once */
.ob[data-acct="choose"] .ob-stage { display: none; }
.oba { position: relative; flex: 1; display: flex; flex-direction: column; margin: 0 -24px calc(-1 * (var(--safe-b) + 18px + var(--view-pb))); }   /* the sheet down to the screen's edge, past the page's and the view's bottom padding */
/* the real start page (HomeView homeHTML), fixed to the column under the step's
   top bar, as wide and padded as it is at home */
.oba-home { position: fixed; top: 48px; bottom: 0; left: var(--app-x); right: var(--app-x); z-index: 0; overflow: hidden; pointer-events: none;
  transform-origin: 50% 20%; transition: filter .8s, opacity .8s, transform .8s var(--ease); }
.ob[data-acct="choose"] .ob-top { position: relative; z-index: 3; }
.oba.sheet .oba-home { filter: blur(3px) saturate(.9); opacity: .55; transform: scale(.96); }
.oba-peek .mascot { height: 100%; width: auto; }
.oba.intro .oba-home .home > * { animation: oba-in .5s var(--spring) both; }
.oba.intro .oba-home .home > :nth-child(2) { animation-delay: .1s; }
.oba.intro .oba-home .home > :nth-child(3) { animation-delay: .2s; }
.oba.intro .oba-home .home > :nth-child(n + 4) { animation-delay: .3s; }
@keyframes oba-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.oba-sheet { position: relative; z-index: 2; margin-top: auto; padding: 26px 20px calc(var(--safe-b) + 22px); border-radius: 34px 34px 0 0;
  background: color-mix(in srgb, var(--bg-2) 92%, transparent); -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  box-shadow: 0 -20px 50px -10px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 255, 255, .08); }
.oba.intro .oba-sheet { transform: translateY(105%); }
.oba.intro.sheet .oba-sheet { transform: none; transition: transform .75s cubic-bezier(.2, 1.1, .3, 1); }
.oba-peek { position: absolute; left: 50%; top: -74px; z-index: -1; width: 110px; height: 110px; margin-left: -55px; display: flex; justify-content: center; }   /* sits on the edge and rides up with the sheet (a delayed rise of its own lagged behind it) */
.oba-h { margin: 14px 0 6px; text-align: center; font: 800 26px / 1.2 var(--font-rounded); }
.oba-sub { max-width: 30ch; margin: 0 auto; text-align: center; color: var(--label-2); font-size: 15.5px; line-height: 1.4; }
.oba-sheet .alert { margin-top: 12px; }
.oba-sheet .ob-actions { margin-top: 0; }
/* "Continue as tester" — only on the local test server (auth.testerReady); dashed, so it never passes for a real way in */
.btn-tester { background: transparent; color: var(--tint); box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--tint) 55%, transparent); border: 0; outline: 2px dashed color-mix(in srgb, var(--tint) 70%, transparent); outline-offset: -2px; }
.btn-tester .ic { width: 20px; height: 20px; }
.lg-tester { margin-bottom: 14px; }
/* "Shall I remind you?" (OnboardingView remindHTML): Voki beside an alarm clock whose hands
   turn to the time; − / + in quarter hours; it rings (shakes, "RRRING!") after a change */
.ob[data-step="remind"] .ob-stage { display: none; }
.ob[data-step="remind"] .ob-copy { margin-top: 22px; }
.obr-scene { display: flex; align-items: flex-end; justify-content: center; gap: 4px; height: 190px; margin: 4px 0; flex: none; }
.obr-voki { height: 150px; display: flex; }
.obr-voki .mascot { height: 100%; width: auto; }
.obr-clock { position: relative; width: 150px; height: 170px; transform-origin: 50% 85%; }
.obr-clock svg { width: 100%; height: 100%; overflow: visible; }
.obr-clock.ring { animation: obr-ring .12s linear 8; }
@keyframes obr-ring { 0%, 100% { transform: rotate(-7deg); } 50% { transform: rotate(7deg); } }
.obr-hand { transform-origin: 75px 95px; transition: transform .5s cubic-bezier(.3, 1.3, .5, 1); }
.obr-rrr { position: absolute; right: -16px; top: -8px; font: 900 15px var(--font-rounded); color: #FF9F0A; opacity: 0; transform: rotate(12deg); transition: opacity .2s; pointer-events: none; }
/* the page leaving in a swipe (OnboardingView ghostOf): a still copy over the new one,
   under a wrapper that carries the old step (its rules keep their spacing) */
.ob-ghost-frame { position: fixed; top: 0; bottom: 0; z-index: 1; overflow: hidden; pointer-events: none; }
.ob-ghost { position: absolute; z-index: 1; margin: 0; padding: 0; pointer-events: none; display: flex; flex-direction: column; }
.ob-ghost > .ob-body { flex: 1; }
.ob-ghost, .ob-ghost * { animation: none !important; transition: none !important; }
.obr-clock.ring .obr-rrr { opacity: 1; }
.obr-time { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 14px; }
.obr-time button { width: 56px; height: 56px; border-radius: 50%; background: var(--fill-3); color: var(--label); font: 700 28px var(--font-rounded); touch-action: none; user-select: none; transition: transform .15s; }
.obr-time button:active { transform: scale(.92); }
.obr-time b { min-width: 150px; text-align: center; font: 800 52px / 1 var(--font-rounded); font-variant-numeric: tabular-nums; }
.obr-hint { max-width: 30ch; margin: 12px auto 0; text-align: center; color: var(--label-2); font-size: 14.5px; line-height: 1.35; }
@media (prefers-reduced-motion: reduce) { .obr-clock.ring { animation: none; } .obr-hand { transition: none; } }
@media (max-height: 740px) { .obr-scene { height: 160px; } .obr-voki { height: 124px; } .obr-clock { width: 124px; height: 140px; } .obr-time b { font-size: 44px; } }
/* the reminder's time in the profile */
.time-pill { border: 0; border-radius: 10px; padding: 6px 10px; background: var(--fill-3); color: var(--label); font: 600 17px var(--font); font-variant-numeric: tabular-nums; }
.btn-google { background: #FFF; color: #1F1F1F; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14), 0 2px 6px rgba(0, 0, 0, .08); gap: 10px; }
.btn-google .g-logo { width: 22px; height: 22px; flex: none; }
.ob-form { display: flex; flex-direction: column; gap: 10px; }
.ob-wait { display: flex; align-items: center; justify-content: center; gap: 10px; color: var(--label-2); font-size: 15px; margin: 8px 0; min-height: 22px; }
/* the 6-digit code from the email (codeInput.js): six boxes over one input */
.code { position: relative; display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; width: 100%; max-width: 330px; margin: 16px auto 4px; }
.code-input { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; opacity: 0; font-size: 16px; caret-color: transparent; }
.code-box { height: 60px; border-radius: 14px; display: grid; place-items: center; background: var(--bg-2); box-shadow: inset 0 0 0 1.5px var(--fill-3);
  font: 800 28px var(--font-rounded); color: var(--label); transition: box-shadow .2s; }
.code-box.on { box-shadow: inset 0 0 0 2.5px var(--tint); }
.code-box.filled { animation: code-pop .22s var(--spring); }
.code.bad { animation: code-shake .42s cubic-bezier(.36, .07, .19, .97); }
.code.bad .code-box { box-shadow: inset 0 0 0 2px var(--red); }
@keyframes code-pop { from { transform: scale(.85); } }
@keyframes code-shake { 20%, 60% { transform: translateX(-8px); } 40%, 80% { transform: translateX(8px); } }
/* Voki's hello when a language is picked: it stands to the left, its speech bubble on the right */
.ob-stage { position: relative; }
.ob[data-step="lang"] .ob-mascot { justify-content: flex-start; padding-left: 4%; }
/* the try-out's Voki stands in the middle and steps left while its bubble shows */
.ob[data-step="try"] .ob-mascot { transition: height .45s var(--ease), padding-right .45s var(--ease); }
.ob[data-step="try"] .ob-stage.talking .ob-mascot { padding-right: 52%; }
.ob-bubble {
  position: absolute; right: 0; top: 4px; max-width: 54%; z-index: 3;
  padding: 10px 14px 11px; border-radius: 20px; background: #FFF; color: #0B2A6B;
  box-shadow: inset 0 1.5px 1px rgba(255, 255, 255, .6), inset 0 -2.5px 4px rgba(20, 50, 120, .12), 0 8px 20px -6px rgba(20, 50, 120, .4);
  transform-origin: 0 100%;
}
.ob-bubble::before { content: ''; position: absolute; left: -9px; bottom: 16px; width: 18px; height: 18px; background: inherit; transform: rotate(45deg); border-radius: 3px; }
.ob-bubble b { position: relative; display: block; font: 800 17px / 1.25 var(--font-rounded); }
.ob-bubble small { position: relative; display: block; margin-top: 3px; font-size: 13px; line-height: 1.3; color: #5B6B8C; }
.ob-bubble.pop { animation: ob-bubble-in .45s cubic-bezier(.34, 1.56, .64, 1) both; }
@keyframes ob-bubble-in { from { opacity: 0; transform: scale(.4) translateX(-12px); } to { opacity: 1; transform: none; } }
@keyframes ob-invite { 0%, 100% { transform: none; } 50% { transform: scale(1.04); } }
