/* Novara design system. Fonts (Bricolage Grotesque / Inter / Noto Sans Thai) are
   requested per page via <link rel=preconnect> + <link rel=stylesheet> in <head>
   (no render-blocking @import chain). Tokens + shared classes: "Novara tokens" below. */

/* Multilingual: only show active language, no mixing */
.lang-en { display: none !important; }
.lang-fr { display: none !important; }
.lang-es { display: none !important; }
.lang-th { display: none !important; }
.lang-nl { display: none !important; }
.lang-de { display: unset; }

[data-lang="en"] .lang-en { display: unset !important; }
[data-lang="en"] .lang-de { display: none !important; }
[data-lang="en"] .lang-fr { display: none !important; }

[data-lang="fr"] .lang-fr { display: unset !important; }
[data-lang="fr"] .lang-de { display: none !important; }
[data-lang="fr"] .lang-en { display: none !important; }

[data-lang="es"] .lang-es { display: unset !important; }
[data-lang="es"] .lang-de { display: none !important; }
[data-lang="es"] .lang-en { display: none !important; }
[data-lang="es"] .lang-fr { display: none !important; }

[data-lang="th"] .lang-th { display: unset !important; }
[data-lang="th"] .lang-de { display: none !important; }
[data-lang="th"] .lang-en { display: none !important; }
[data-lang="th"] .lang-fr { display: none !important; }
[data-lang="th"] .lang-es { display: none !important; }

/* Dutch (nl): new language, normal Latin font — no special font block needed. */
[data-lang="nl"] .lang-nl { display: unset !important; }
[data-lang="nl"] .lang-de { display: none !important; }
[data-lang="nl"] .lang-en { display: none !important; }
[data-lang="nl"] .lang-fr { display: none !important; }
[data-lang="nl"] .lang-es { display: none !important; }
[data-lang="nl"] .lang-th { display: none !important; }

/* Thai script: prefer a Thai-capable font and roomier line-height for legibility.
   Noto Sans Thai (Android/Chrome), Thonburi (iOS/macOS), Sarabun — falls back to
   the system stack, so no bundled webfont is required. The lang="th" attribute on
   each .lang-th span drives correct Thai line-breaking. */
[data-lang="th"] body, [lang="th"], [lang="th"] body {
    font-family: var(--nv-font-body);
    line-height: 1.65;
}

/* Jurisdiction (country) within the German language: default = Germany (DE);
   [data-country="at"] flips German-content facts to the Austrian variant.
   Used only inside German (.lang-de) content, so it never affects EN/FR. */
.ctry-at { display: none !important; }
.ctry-de { display: unset; }
[data-country="at"] .ctry-at { display: unset !important; }
[data-country="at"] .ctry-de { display: none !important; }
/* Hide a whole block ONLY for Austria. Safe on flex/grid rows because it only
   ever sets display:none (never restores a display value like the spans do). */
[data-country="at"] .at-hide { display: none !important; }

/* France (FR). France is a new LANGUAGE as well as a new jurisdiction, so
   virtually all French facts live in the French text itself (.lang-fr spans,
   *_fr quiz fields) — there is no general .ctry-fr content branch to maintain.
   These two rules exist only for the rare LANGUAGE-NEUTRAL element (a number in
   a shared table cell, a whole row) that still has to vary by jurisdiction.

   Note there is deliberately NO blanket `[data-country="fr"] .ctry-de { none }`:
   that would blank out every Austrian-style .ctry-de span in the GERMAN content
   for a French account whose owner flips the 🌐 toggle to German (language and
   jurisdiction are independent — see docs/COUNTRY_MODEL.md). Instead, opt in
   per element by putting `fr-hide` on the .ctry-de span that has a .ctry-fr
   sibling. */
.ctry-fr { display: none !important; }
[data-country="fr"] .ctry-fr { display: unset !important; }
/* Hide a single element or a whole block ONLY for France (e.g. the DE-only tax
   fields — Sparerpauschbetrag, Teilfreistellung — that don't exist in FR).
   Safe on flex/grid rows: it only ever sets display:none. */
[data-country="fr"] .fr-hide { display: none !important; }

/* Spain (ES). Like France, Spanish is a new LANGUAGE as well as a new
   jurisdiction, so almost all Spanish facts live in the Spanish text (.lang-es
   spans, *_es quiz fields). These rules exist only for the rare LANGUAGE-NEUTRAL
   element (a number in a shared table cell, a whole row) that must still vary by
   jurisdiction. Opt in per element by putting `es-hide` on the .ctry-de span that
   has a .ctry-es sibling. No blanket [data-country="es"] .ctry-de{none} (same
   reasoning as France — language and jurisdiction are independent). */
.ctry-es { display: none !important; }
[data-country="es"] .ctry-es { display: unset !important; }
[data-country="es"] .es-hide { display: none !important; }

/* England / United Kingdom (EN). English is a new LANGUAGE as well as a new
   jurisdiction, so almost all UK facts live in the English text (.lang-en spans,
   *_en quiz fields). These rules cover only the rare LANGUAGE-NEUTRAL element (a
   number in a shared table cell, e.g. a currency amount not wrapped in .lang-*)
   that must still vary by jurisdiction. Opt in per element by putting `en-hide` on
   the sibling that should disappear for the UK, next to a .ctry-en sibling. Same
   reasoning as FR/ES: no blanket [data-country="en"] .ctry-de{none}. */
.ctry-en { display: none !important; }
[data-country="en"] .ctry-en { display: unset !important; }
[data-country="en"] .en-hide { display: none !important; }

/* United States (US). The US shares the English LANGUAGE with the UK (both read
   .lang-en), but diverges on nearly every money FACT (£/$, ISA/Roth IRA, PAYE/W-2,
   HMRC/IRS, FTSE/S&P 500, NI/FICA, sort code/routing number, FSCS/FDIC). English
   content therefore branches by JURISDICTION exactly like German does for DE/AT:
   inside .lang-en, pair a .ctry-en (UK-only) span with a .ctry-us (US-only) span.
   Within VISIBLE English content the active country is either the UK (.ctry-en
   shows, .ctry-us hides) or the US (.ctry-us shows, .ctry-en hides), so exactly one
   appears. `us-hide` drops a shared element for the US only (mirror of at-hide) and
   is also how a language-neutral default cell — e.g. a bare £ amount that already
   has fr-hide/en-hide/th-hide — opts OUT for the US next to its new .ctry-us
   sibling. See docs/US_UK_DIVERGENCE.md. */
.ctry-us { display: none !important; }
[data-country="us"] .ctry-us { display: unset !important; }
[data-country="us"] .us-hide { display: none !important; }

/* Thailand (TH): same language-neutral currency/jurisdiction gating for the ฿ market. */
.ctry-th { display: none !important; }
[data-country="th"] .ctry-th { display: unset !important; }
[data-country="th"] .th-hide { display: none !important; }

/* Currency icon (brand logo + money emoji in content). The old 💰 money bag
   carries a "$", which is wrong for our Euro markets — and there is no euro
   money-bag emoji, so we use the banknote pair instead: same silhouette, only
   the currency mark differs. Euro markets (DE/AT/FR — and the unknown/default
   case, since every launched market is Euro) show 💶; dollar markets show 💵.
   Pure CSS off the same pre-paint data-country attribute as .ctry-*, so the
   right icon paints on first frame — no JS dependency, no flash. Usage:
   <span class="cur-eur">💶</span><span class="cur-usd">💵</span>
   (A future £ market would just add .cur-gbp + a [data-country="uk"] pair.) */
.cur-usd { display: none !important; }
.cur-gbp { display: none !important; }
.cur-thb { display: none !important; }
.cur-eur { display: unset; }
/* United Kingdom (data-country="en") shows the £ banknote 💷. */
[data-country="en"] .cur-gbp { display: unset !important; }
[data-country="en"] .cur-eur { display: none !important; }
/* United States (data-country="us") shows the $ banknote 💵. */
[data-country="us"] .cur-usd { display: unset !important; }
[data-country="us"] .cur-eur { display: none !important; }
/* Thailand (data-country="th"): no ฿ banknote emoji exists, so use a currency-neutral coin 🪙. */
[data-country="th"] .cur-thb { display: unset !important; }
[data-country="th"] .cur-eur { display: none !important; }

@keyframes float {
    0%, 100% { transform: translateY(0px) rotate(0deg); }
    33% { transform: translateY(-20px) rotate(1deg); }
    66% { transform: translateY(10px) rotate(-1deg); }
}

@keyframes slideUp {
    from { opacity: 0; transform: translateY(40px); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-40px); }
    to { opacity: 1; transform: translateX(0); }
}

@keyframes slideInRight {
    from { opacity: 0; transform: translateX(40px); }
    to { opacity: 1; transform: translateX(0); }
}

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

@keyframes scaleIn {
    from { opacity: 0; transform: scale(0.9); }
    to { opacity: 1; transform: scale(1); }
}

@keyframes bounceSoft {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-5px); }
}

@keyframes progressFill {
    from { width: 0%; }
}

/* Glass cards — ONE definition (tokens in the Novara block). Static by default;
   only links/buttons lift on hover. Radius/padding stay on the markup utilities
   (rounded-3xl p-6 = card; .nv-tile = small tile) so pills and rows keep their shape. */
.glass-card, .nv-card {
    background: var(--nv-glass);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--nv-line);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
    transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.nv-card { border-radius: var(--nv-r-card); padding: 1.5rem; }
.nv-tile { border-radius: var(--nv-r-tile); padding: 1.25rem; }
.glass-card:hover { transform: none; }
a.glass-card:hover, button.glass-card:hover, .nv-card--link:hover {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));
    border-color: rgba(255, 255, 255, 0.18);
    transform: translateY(-3px);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 22px 55px -24px rgba(34, 211, 238, 0.4);
}

.glass-badge {
    background: rgba(255, 255, 255, 0.055);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.12);
}

/* Buttons — cyan primary (dark text, cyan glow); glass secondary; 16px radius. */
.glass-button-primary, .nv-btn-primary {
    background: linear-gradient(120deg, var(--nv-cyan), var(--nv-cyan-soft));
    border: 1px solid transparent;
    border-radius: var(--nv-r-tile);
    box-shadow: 0 12px 30px -10px rgba(34, 211, 238, 0.5);
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.glass-button-primary:hover, .nv-btn-primary:hover {
    background: linear-gradient(120deg, #22d3ee, #a5f3fc);
    transform: translateY(-1px);
    box-shadow: 0 16px 40px -10px rgba(34, 211, 238, 0.6);
}
.glass-button-primary, .glass-button-primary *, .nv-btn-primary, .nv-btn-primary * { color: #04121a !important; }

.glass-button, .nv-btn-secondary {
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--nv-r-tile);
    transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.glass-button:hover, .nv-btn-secondary:hover {
    background: rgba(255, 255, 255, 0.14);
    transform: translateY(-1px);
}

/* Chapter cards */
.chapter-card {
    cursor: pointer;
    text-decoration: none;
}

.chapter-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}

/* Content sections within chapter pages */
.content-section {
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 1.5rem;
    padding: 2rem;
    margin-bottom: 2rem;
}

.content-section h3 {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

.content-section p, .content-section li {
    color: rgba(255, 255, 255, 0.8);
    line-height: 1.8;
}

.content-section ul {
    list-style: none;
    padding-left: 0;
}

.content-section ul li {
    padding: 0.5rem 0;
    padding-left: 1.5rem;
    position: relative;
}

.content-section ul li::before {
    content: '▸';
    position: absolute;
    left: 0;
    color: var(--nv-cyan-soft);
    opacity: 0.85;
}

/* Lesson call-out boxes — one rule, five on-palette tints (class names unchanged:
   info = cyan · exercise = soft cyan · example = violet · tip = teal (cyan-derived) · warning = gold). */
.nv-box, .info-box, .tip-box, .warning-box, .example-box, .exercise-box {
    --nv-box: var(--nv-cyan);
    border-radius: var(--nv-r-tile);
    padding: 1.25rem 1.5rem;
    margin: 1.25rem 0;
    border: 1px solid color-mix(in srgb, var(--nv-box) 32%, transparent);
    background: color-mix(in srgb, var(--nv-box) 12%, transparent);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.exercise-box { --nv-box: var(--nv-cyan-soft); }
.example-box  { --nv-box: var(--nv-violet); }
.tip-box      { --nv-box: var(--nv-teal); }
.warning-box  { --nv-box: var(--nv-gold); }

/* Test styling */
.test-container {
    max-width: 48rem;
    margin: 0 auto;
}

.question-card {
    background: rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 1.5rem;
    padding: 1.5rem;
    margin-bottom: 1.5rem;
    transition: all 0.3s ease;
}

.question-card.correct {
    border-color: rgba(52, 211, 153, 0.5);
    background: rgba(52, 211, 153, 0.08);
}

.question-card.incorrect {
    border-color: rgba(248, 113, 113, 0.5);
    background: rgba(248, 113, 113, 0.08);
}

.answer-option {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.75rem 1rem;
    margin: 0.5rem 0;
    border-radius: var(--nv-r-tile);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.02));
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--nv-ink);
    cursor: pointer;
    transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}

.answer-option:hover:not(.selected):not(.disabled) {
    border-color: rgba(103, 232, 249, 0.5);
    background: rgba(34, 211, 238, 0.08);
    transform: translateY(-1px);
}

.answer-option.selected {
    border-color: var(--nv-cyan);
    background: rgba(34, 211, 238, 0.14);
    box-shadow: 0 0 0 1px var(--nv-cyan) inset;
}

.answer-option.correct-answer {
    background: rgba(52, 211, 153, 0.18);
    border-color: rgba(52, 211, 153, 0.6);
}

.answer-option.wrong-answer {
    background: rgba(248, 113, 113, 0.18);
    border-color: rgba(248, 113, 113, 0.6);
}

.answer-option.disabled {
    cursor: default;
    opacity: 0.7;
}

/* Progress bar */
.progress-bar {
    height: 0.5rem;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.08);
    overflow: hidden;
}

.progress-fill {
    height: 100%;
    border-radius: 9999px;
    background: var(--nv-grad-h);
    transition: width 0.5s ease;
    animation: progressFill 1s ease-out;
}

/* Scroll animations */
.animate-on-scroll {
    opacity: 0;
    transform: translateY(20px);
    transition: all 0.6s ease-out;
}

.animate-on-scroll.visible {
    opacity: 1;
    transform: translateY(0);
}

/* Chapter navigation */
.chapter-nav {
    /* 1fr auto 1fr: prev and next get equal width so the row never looks ragged,
       and "Overview" stays only as wide as its own label. */
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: stretch;
    gap: 0.6rem;
    margin-top: 3rem;
    padding-top: 2rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.chapter-nav a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-width: 0;
    min-height: 52px;
    padding: 0.8rem 1.05rem;
    border-radius: 1rem;
    /* same glass recipe as .glass-card / .roster-face, not a flat grey slab */
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.025));
    border: 1px solid rgba(255, 255, 255, 0.10);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
    color: #e8ecf8;
    font-weight: 600;
    font-size: 0.92rem;
    line-height: 1.15;
    text-decoration: none;
    /* the arrow and its label are one string ("← Kapitel 3"); without this the
       row wrapped mid-label and the buttons grew to two ragged lines */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: transform .18s ease, border-color .18s ease, background .18s ease, box-shadow .18s ease, color .18s ease;
}

/* prev hugs the left edge, next the right — the middle stays centred */
.chapter-nav a:first-child { justify-content: flex-start }
.chapter-nav a:last-child  { justify-content: flex-end }

/* "Overview" is the secondary action: same shape, quieter fill */
.chapter-nav a:nth-child(2) {
    background: transparent;
    border-color: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.62);
    box-shadow: none;
}

/* Hover/press picks up the CHAPTER's own accent (body[data-chapter] --acc), so
   the nav belongs to the chapter it sits in. */
.chapter-nav a:hover,
.chapter-nav a:focus-visible {
    transform: translateY(-2px);
    color: #fff;
    border-color: color-mix(in srgb, var(--acc, #22d3ee) 55%, transparent);
    box-shadow: 0 10px 26px -14px color-mix(in srgb, var(--acc, #22d3ee) 75%, transparent),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
.chapter-nav a:active { transform: translateY(0) scale(.985) }
.chapter-nav a:focus-visible { outline: 2px solid var(--acc, #22d3ee); outline-offset: 3px }

@media (max-width: 420px) {
    .chapter-nav { gap: 0.4rem }
    .chapter-nav a { font-size: 0.82rem; padding: 0.8rem 0.7rem }
}

@media (prefers-reduced-motion: reduce) {
    .chapter-nav a:hover, .chapter-nav a:active { transform: none }
}

/* Scoreboard */
.people-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 1rem;
}

.score-row {
    display: grid;
    grid-template-columns: 2fr repeat(5, 1fr);
    gap: 0.5rem;
    padding: 1rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    align-items: center;
}

.score-row.header {
    font-weight: 700;
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Premium score cell: a graded circular progress ring (donut) for a
   completed chapter, and an intentional ghost ring for "not started". */
.score-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem;
    min-width: 0;
}

.score-donut {
    position: relative;
    width: 48px;
    height: 48px;
    display: grid;
    place-items: center;
}

.score-donut svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.ring-track {
    fill: none;
    stroke: rgba(255, 255, 255, 0.10);
    stroke-width: 3.5;
}

.ring-arc {
    fill: none;
    stroke: var(--ring, #22d3ee);
    stroke-width: 3.5;
    stroke-linecap: round;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
    filter: drop-shadow(0 0 3px var(--glow, transparent));
    transition: stroke-dasharray 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

.ring-val {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'Bricolage Grotesque', 'Inter', system-ui, sans-serif;
    font-weight: 800;
    font-size: 0.8rem;
    line-height: 1;
    letter-spacing: -0.02em;
    color: #ffffff;
    font-variant-numeric: tabular-nums;
}

.ring-val i {
    font-style: normal;
    font-weight: 700;
    font-size: 0.62em;
    opacity: 0.7;
    margin-left: 0.5px;
}

/* Not-started: a faint dashed ghost ring, clearly intentional */
.score-donut.ghost .ring-ghost {
    fill: none;
    stroke: rgba(255, 255, 255, 0.16);
    stroke-width: 2.5;
    stroke-dasharray: 1.5 4.5;
    stroke-linecap: round;
}

.ring-dash {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.30);
    font-weight: 700;
    font-size: 0.85rem;
    line-height: 1;
}

@media (max-width: 480px) {
    .score-donut { width: 42px; height: 42px; }
    .ring-val { font-size: 0.72rem; }
}

@media (prefers-reduced-motion: reduce) {
    .ring-arc { transition: none; }
}

/* Smooth scrolling */
html {
    scroll-behavior: smooth;
}

/* Custom scrollbar */
::-webkit-scrollbar {
    width: 8px;
}

::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.2);
}

::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.3);
}

/* Interactive calculator styling */
.calc-input {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 0.75rem;
    padding: 0.75rem 1rem;
    color: white;
    width: 100%;
    transition: all 0.2s ease;
}

.calc-input:focus {
    outline: none;
    border-color: var(--nv-cyan);
    background: rgba(255, 255, 255, 0.07);
    box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.18);
}

/* Hide native number-input spinners (the ▲▼ stepper) app-wide — the sliders do
   the stepping, and the bare field reads far cleaner in the premium glass inputs. */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.calc-result {
    background: linear-gradient(180deg, rgba(34, 211, 238, 0.12), rgba(167, 139, 250, 0.10));
    border: 1px solid rgba(103, 232, 249, 0.35);
    border-radius: 20px;
    padding: 1.5rem;
    text-align: center;
}

/* Tab styling for kid selector */
.kid-tab {
    min-height: 44px;
    padding: 0.5rem 1.35rem;
    border-radius: var(--nv-r-pill);
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--nv-line);
    color: var(--nv-muted);
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.kid-tab.active {
    background: linear-gradient(120deg, var(--nv-cyan), var(--nv-cyan-soft));
    border-color: transparent;
    color: #04121a;
    box-shadow: 0 10px 24px -12px rgba(34, 211, 238, 0.6);
}

.kid-tab:hover:not(.active) {
    background: rgba(255, 255, 255, 0.1);
    color: white;
}

/* Bonus/Advanced section - collapsible */
.bonus-section {
    background: linear-gradient(135deg, rgba(167, 139, 250, 0.10), rgba(34, 211, 238, 0.06));
    border: 1px solid rgba(167, 139, 250, 0.3);
    border-radius: 1.5rem;
    margin: 2rem 0;
    overflow: hidden;
}

.bonus-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1.25rem 1.5rem;
    cursor: pointer;
    transition: background 0.2s ease;
    user-select: none;
}

.bonus-header:hover {
    background: rgba(167, 139, 250, 0.1);
}

.bonus-header h4 {
    font-weight: 700;
    color: #c4b5fd;
    margin: 0;
}

.bonus-chevron {
    transition: transform 0.3s ease;
    color: #c4b5fd;
}

.bonus-section.open .bonus-chevron {
    transform: rotate(180deg);
}

.bonus-content {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.4s ease, padding 0.3s ease;
    padding: 0 1.5rem;
}

.bonus-section.open .bonus-content {
    max-height: 2000px;
    padding: 0 1.5rem 1.5rem;
}

.bonus-content p, .bonus-content li {
    color: rgba(255, 255, 255, 0.8);
    line-height: 1.8;
}

/* Notes system */
.notes-container {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 1rem;
    padding: 1rem;
    margin-top: 2rem;
}

.notes-textarea {
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 0.75rem;
    padding: 0.75rem 1rem;
    color: white;
    width: 100%;
    min-height: 100px;
    resize: vertical;
    font-family: inherit;
    font-size: 0.875rem;
    transition: border-color 0.2s ease;
}

.notes-textarea:focus {
    outline: none;
    border-color: var(--nv-cyan);
    box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.18);
}

.notes-textarea::placeholder {
    color: rgba(255, 255, 255, 0.3);
}

/* Quiz difficulty tabs */
.difficulty-tab {
    min-height: 40px;
    padding: 0.45rem 1.1rem;
    border-radius: var(--nv-r-pill);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
    border: 1px solid var(--nv-line);
    background: rgba(255, 255, 255, 0.05);
    color: var(--nv-muted);
}

.difficulty-tab.active {
    color: #04121a;
    border-color: transparent;
    background: linear-gradient(120deg, var(--nv-cyan), var(--nv-cyan-soft));
}

.difficulty-tab.advanced.active {
    background: linear-gradient(120deg, var(--nv-violet), #c4b5fd);
}

/* Family challenge */
.challenge-card {
    background: var(--nv-glass);
    border: 1px solid rgba(251, 191, 36, 0.28);
    border-radius: var(--nv-r-card);
    padding: 1.5rem;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
    transition: border-color 0.2s ease;
}

.challenge-card:hover {
    border-color: rgba(251, 191, 36, 0.45);
}

.challenge-card.completed {
    opacity: 0.6;
    border-color: rgba(52, 211, 153, 0.3);
    background: linear-gradient(135deg, rgba(52, 211, 153, 0.08), rgba(52, 211, 153, 0.03));
}

/* ===== Novara design upscale (2026) ===== */
body{font-family:var(--nv-font-body);color:var(--nv-ink);}
h1,h2,h3,h4,.font-display{font-family:var(--nv-font-display);letter-spacing:-0.02em;}
/* Thai headings keep the display face for Latin/digits/"Novara"; Noto Sans Thai renders the Thai glyphs */
[data-lang="th"] h1,[data-lang="th"] h2,[data-lang="th"] h3,[data-lang="th"] h4,[lang="th"] h1,[lang="th"] h2,[lang="th"] h3,[lang="th"] h4{font-family:var(--nv-font-display);letter-spacing:0;line-height:1.3;}
.chapter-card:hover{box-shadow:0 22px 55px -24px rgba(34,211,238,.4);}
.avatar-ring{padding:3px;border-radius:50%;background:linear-gradient(120deg,#22d3ee,#a78bfa);display:inline-block;line-height:0;}
.avatar-ring>img{border-radius:50%;display:block;width:100%;height:100%;object-fit:cover;background:#141a33;}

/* Full-body avatar. The avatars are drawn head-to-toe, so the 40px ring throws
   most of the picture away — this renders the whole figure at a given HEIGHT,
   letting the width follow the art. Used on Home and anywhere the avatar is the
   subject rather than a label. */
.nv-unlock-avatar{margin:.9rem auto 0;max-width:34ch;font-size:.86rem;line-height:1.5;
  color:var(--nv-cyan-soft);}
.nv-unlock-perks{list-style:none;margin:.9rem auto 0;padding:0;max-width:26ch;
  display:flex;flex-direction:column;gap:.35rem;font-size:.86rem;color:var(--nv-muted);}
.nv-unlock-perks li{display:flex;align-items:center;gap:.5rem;justify-content:center;}
.nv-unlock-perks li::before{content:"";width:6px;height:6px;border-radius:50%;flex:none;
  background:linear-gradient(120deg,var(--nv-cyan),var(--nv-violet));}

.nv-fig{display:inline-block;line-height:0;position:relative;}
/* Round is the default shape of an avatar in this app; the square figure read as
   a picture OF someone rather than as them. Gradient rim, same as .avatar-ring. */
.nv-fig.is-round{border-radius:50%;padding:3px;overflow:visible;
  background:linear-gradient(120deg,var(--nv-cyan),var(--nv-violet));}
.nv-fig.is-round>img{width:100%;height:100%;border-radius:50%;object-fit:cover;
  object-position:center 22%;background:#141a33;}

/* Streak light. The streak was a number nobody looked at; this makes it the
   light the avatar stands in — cyan on day one, gold at a week, dark the day
   it breaks. Driven by Gamification.getStreak(kid).current, nothing new stored. */
.nv-floor{position:absolute;left:50%;bottom:-13px;transform:translateX(-50%);
  width:calc(60px + var(--so,0) * 110px);height:26px;border-radius:50%;pointer-events:none;
  filter:blur(6px);opacity:var(--so,0);
  background:radial-gradient(ellipse at center,var(--sc,#22d3ee) 0%,transparent 70%);
  transition:opacity .5s ease,width .5s ease;}
.nv-fig[data-streak="0"]{--so:0;}
.nv-fig[data-streak="1"]{--so:.35;--sc:#22d3ee;}
.nv-fig[data-streak="2"]{--so:.45;--sc:#67e8f9;}
.nv-fig[data-streak="3"]{--so:.56;--sc:#a78bfa;}
.nv-fig[data-streak="4"]{--so:.67;--sc:#c084fc;}
.nv-fig[data-streak="5"]{--so:.78;--sc:#f472b6;}
.nv-fig[data-streak="6"]{--so:.89;--sc:#fb923c;}
.nv-fig[data-streak="7"]{--so:1;--sc:#fbbf24;}
/* drop-shadow follows the artwork's own silhouette, so the glow hugs the figure */
.nv-fig[data-streak]:not([data-streak="0"])>img{
  filter:drop-shadow(0 14px 26px rgba(0,0,0,.55))
         drop-shadow(0 0 calc(var(--so,0) * 18px) var(--sc,#22d3ee));}
@media (prefers-reduced-motion:reduce){.nv-floor{transition:none;}}
.nv-fig>img{height:100%;width:auto;max-width:100%;object-fit:contain;display:block;
  filter:drop-shadow(0 14px 26px rgba(0,0,0,.55));}
/* The next, unearned look — shown deliberately. Greyed and dimmed so it reads
   as a destination rather than a state, with the lock doing the explaining. */
.nv-next{position:relative;}
.nv-next>img{filter:grayscale(1) brightness(.52) contrast(.9) drop-shadow(0 10px 18px rgba(0,0,0,.5));}
.nv-next-lock{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:1.5rem;line-height:1;filter:drop-shadow(0 2px 6px rgba(0,0,0,.8));}
.nv-stage-row{display:flex;align-items:flex-end;justify-content:center;gap:1.5rem;flex-wrap:wrap;}
.nv-stage-col{display:flex;flex-direction:column;align-items:center;gap:.5rem;}
.nv-stage-cap{font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;font-weight:700;
  color:var(--nv-faint);}
/* Name, edited where the avatar is. Picture and name are one decision about how
   you appear, so they share a card rather than a card and a prompt(). */
.nv-namefield{display:flex;flex-direction:column;align-items:center;gap:.3rem;margin-top:.55rem;width:100%;}
.nv-namefield-lbl{font-size:.62rem;letter-spacing:.15em;text-transform:uppercase;
  color:var(--nv-faint);font-weight:700;}
.nv-namefield input,.nv-name-input{
  width:100%;max-width:15rem;text-align:center;
  font-family:var(--nv-font-display);font-weight:800;font-size:1.05rem;letter-spacing:-.01em;
  color:var(--nv-ink);background:rgba(255,255,255,.06);
  border:1px solid var(--nv-line);border-radius:var(--nv-r-ctl);
  padding:.5rem .75rem;transition:border-color .18s,background .18s;}
.nv-name-input{max-width:none;text-align:left;font-size:.95rem;}
.nv-namefield input:hover,.nv-name-input:hover{border-color:rgba(255,255,255,.22);}
.nv-namefield input:focus,.nv-name-input:focus{
  outline:none;border-color:var(--nv-cyan);background:rgba(34,211,238,.08);}
.nv-namefield input::placeholder,.nv-name-input::placeholder{color:var(--nv-faint);font-weight:600;}

.nv-look-line{font-size:.85rem;color:var(--nv-muted);font-variant-numeric:tabular-nums;
  display:flex;align-items:center;gap:.5rem;justify-content:center;flex-wrap:wrap;}
.nv-look-line b{color:var(--nv-cyan-soft);font-weight:700;}

/* ===== Novara premium overhaul (2026-b) ===== */
/* Ground: flat brand base on <body> + the cyan/violet/pink glow on a FIXED pseudo-
   element. (background-attachment:fixed is ignored by iOS WKWebView and breaks the
   render harness; the pseudo-element behaves identically everywhere.) */
/* html carries the ground too, not just body: the canvas outside the body box
   (rubber-band overscroll, and the safe-area insets in the native shell) paints
   from here. Left unset it fell back to the platform's white. */
html{background:var(--nv-bg-2);}
body{background:var(--nv-bg-2) !important;}
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;background:
    radial-gradient(1100px 760px at 84% -10%, rgba(124,58,237,.30), transparent 56%),
    radial-gradient(900px 680px at 2% 4%, rgba(34,211,238,.15), transparent 52%),
    radial-gradient(760px 720px at 62% 112%, rgba(244,114,182,.10), transparent 55%),
    linear-gradient(165deg,#080b16,#140a2a 50%,#080b16)}
/* inline cel icons (from the iconifier) — scale with their context */
.ce-ic{height:1.22em;width:1.22em;vertical-align:-0.24em;object-fit:contain;display:inline-block;margin:0 .05em}
h1 .ce-ic,h2 .ce-ic,h3 .ce-ic{filter:drop-shadow(0 2px 6px rgba(0,0,0,.4))}
.chapter-card{border-radius:24px}
.chapter-card:hover{transform:translateY(-6px);box-shadow:0 30px 62px -26px rgba(34,211,238,.45);border-color:rgba(103,232,249,.4)}
.glass-badge{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1)}
h1{font-weight:800}

/* ===== Novara premium cards (2026-c) — artifact-grade boxes ===== */
.chapter-card:has(.ch-hero){display:flex;flex-direction:column;border-radius:24px;overflow:hidden;padding:0;
  background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.02));
  border:1px solid rgba(255,255,255,.09);transition:transform .22s ease,border-color .22s ease,box-shadow .22s ease}
.chapter-card:has(.ch-hero):hover{transform:translateY(-7px);
  border-color:color-mix(in srgb, var(--acc) 50%, transparent);
  box-shadow:0 34px 70px -28px color-mix(in srgb, var(--acc) 60%, transparent)}
.ch-hero{position:relative;height:158px;display:flex;align-items:center;justify-content:center;
  background:
    radial-gradient(130% 105% at 50% -10%, color-mix(in srgb, var(--acc) 30%, transparent), transparent 68%),
    linear-gradient(180deg, color-mix(in srgb, var(--acc) 15%, transparent), rgba(255,255,255,.015));
  border-bottom:1px solid rgba(255,255,255,.08)}
.ch-ico{width:104px;height:104px;display:flex;align-items:center;justify-content:center;transition:transform .22s ease}
.ch-ico img{width:100%;height:100%;object-fit:contain;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.55)) drop-shadow(0 0 22px color-mix(in srgb, var(--acc) 45%, transparent))}
.chapter-card:hover .ch-ico{transform:scale(1.07) translateY(-2px)}
.ch-badge{position:absolute;top:12px;right:12px;font-size:11px;font-weight:700;letter-spacing:.05em;
  color:var(--acc);background:rgba(0,0,0,.32);border:1px solid rgba(255,255,255,.14);
  padding:5px 12px;border-radius:999px;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.ch-body{padding:20px 22px 22px;display:flex;flex-direction:column;gap:8px;flex:1}
.ch-body h3{font-size:21px;line-height:1.15;margin:0;transition:color .18s ease}
.chapter-card:hover .ch-body h3{color:var(--acc)}
.ch-body p{margin:0;flex:1}

/* ===== Novara premium — everywhere (2026-d) ===== */
/* lesson content boxes (all 16 chapters) */
.content-section{
  background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.02)) !important;
  border:1px solid rgba(255,255,255,.09) !important;border-radius:24px !important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 22px 55px -32px rgba(0,0,0,.75);
  padding:1.9rem 2rem !important;
}
.content-section h3{font-size:1.55rem}
/* inputs — premium dark glass + cyan focus (login, tools, settings, notes) */
input:not([type=checkbox]):not([type=radio]),select,textarea,.calc-input,.notes-textarea{
  background:rgba(255,255,255,.05) !important;border:1px solid rgba(255,255,255,.12) !important;border-radius:14px !important;color:#eef2ff;transition:border-color .15s,box-shadow .15s}
input:not([type=checkbox]):not([type=radio]):focus,select:focus,textarea:focus,.calc-input:focus,.notes-textarea:focus{
  border-color:#22d3ee !important;box-shadow:0 0 0 3px rgba(34,211,238,.18) !important;outline:none !important}
::placeholder{color:#6b7794}

/* ===== Novara premium hero + stats + headings (2026-e) — all languages ===== */
h1,h2,h3{text-wrap:balance}
/* big hero icons (chapter pages: the text-6xl / text-5xl iconified glyph) glow */
.text-6xl .ce-ic,.text-5xl .ce-ic{height:1em;width:1em;vertical-align:-.12em;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.55)) drop-shadow(0 0 26px color-mix(in srgb,var(--acc,var(--nv-cyan)) 45%,transparent))}
/* home hero headline: a touch bigger + luminous */
section.min-h-screen h1{font-size:clamp(2.6rem,7vw,5rem);line-height:1.03}
/* eyebrow / badge chips: refined pill */
.glass-badge{background:rgba(255,255,255,.055)!important;border:1px solid rgba(255,255,255,.12)!important;
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
/* stat cards */
/* CTA buttons wrap gracefully for long languages */
#hero-buttons{flex-wrap:wrap}

/* ===== #4 avatar quiz reaction ===== */
.quiz-react{position:absolute;top:-16px;right:14px;z-index:20;display:flex;align-items:center;gap:9px;pointer-events:none;
  animation:qrPop .34s cubic-bezier(.2,1.4,.5,1) both}
.quiz-react.qr-out{animation:qrOut .32s ease both}
.qr-face{width:48px;height:48px;flex:none;filter:drop-shadow(0 6px 14px rgba(0,0,0,.5))}
.qr-face .avatar-ring{width:48px;height:48px}
.quiz-react.correct .qr-face{animation:qrBounce .55s ease}
.quiz-react.wrong .qr-face{animation:qrShake .45s ease}
.qr-bubble{font-family:"Bricolage Grotesque","Inter",sans-serif;font-weight:700;font-size:14px;padding:7px 13px;border-radius:13px;white-space:nowrap;
  background:linear-gradient(180deg,rgba(255,255,255,.1),rgba(255,255,255,.04));border:1px solid rgba(255,255,255,.15)}
.quiz-react.correct .qr-bubble{color:#04121a;background:linear-gradient(120deg,#34d399,#67e8f9);border:none;box-shadow:0 8px 20px -8px rgba(52,211,153,.6)}
.quiz-react.wrong .qr-bubble{color:#fde68a;border-color:rgba(251,191,36,.5)}
.qr-spark{position:absolute;left:16px;top:16px;width:8px;height:8px;border-radius:50%;background:#67e8f9;opacity:0;animation:qrSpark .75s ease-out forwards}
.qr-spark:nth-of-type(2){background:#a78bfa;animation-delay:.05s}
.qr-spark:nth-of-type(3){background:#34d399;animation-delay:.1s}
@keyframes qrPop{from{opacity:0;transform:translateY(6px) scale(.8)}to{opacity:1;transform:none}}
@keyframes qrOut{to{opacity:0;transform:translateY(-10px) scale(.9)}}
@keyframes qrBounce{0%,100%{transform:translateY(0)}30%{transform:translateY(-9px)}60%{transform:translateY(-3px)}}
@keyframes qrShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-5px)}60%{transform:translateX(5px)}}
@keyframes qrSpark{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--dx,20px),var(--dy,-24px)) scale(.3)}}
@media (prefers-reduced-motion:reduce){.quiz-react,.qr-face,.qr-spark{animation-duration:.01ms!important;animation-iteration-count:1!important}}

/* ===== Novara premium roster cards (2026-f) — scoreboard summary + home progress ===== */
/* A consistent, premium frame for a member's face on the summary / progress
   cards. Holds EITHER the gradient avatar-ring (real avatar) or the emoji/
   initial fallback, so both look identical: a soft glass disc with a cyan/violet
   glow. Size via --rf (default 72px). */
.roster-face{width:var(--rf,72px);height:var(--rf,72px);border-radius:50%;flex:none;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.02));
  border:1px solid rgba(255,255,255,.10);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 12px 30px -16px rgba(34,211,238,.55)}
.roster-face .avatar-ring{width:calc(var(--rf,72px) - 8px);height:calc(var(--rf,72px) - 8px)}
.roster-face .nova-face-emoji{font-size:calc(var(--rf,72px) * .48);line-height:1}
/* the summary card's own layout: tidy vertical rhythm */
/* Family line-up. The roster was a row of 40px discs in a list; this stands the
   same kids on ONE shared floor at full height, each wearing the look they have
   earned. The comparison is the point — siblings notice an outfit they do not
   have yet long before they notice a percentage. */
.nv-lineup{position:relative;display:flex;flex-wrap:wrap;justify-content:center;
  align-items:flex-end;gap:1.75rem;padding:1.75rem 1rem 2.75rem;
  border-radius:var(--nv-r-card);border:1px solid var(--nv-line);
  background:linear-gradient(180deg,rgba(13,19,41,.78),rgba(8,11,22,.92));}
.nv-lineup::after{content:"";position:absolute;left:1.5rem;right:1.5rem;bottom:2.25rem;
  height:1px;background:linear-gradient(90deg,transparent,rgba(103,232,249,.32),transparent);}
.nv-lineup .summary-card{flex:0 1 190px;position:relative;z-index:1;}
.sc-fig{line-height:0;}
@media (max-width:520px){.nv-lineup{gap:1.1rem;padding:1.25rem .75rem 2rem}
  .nv-lineup .summary-card{flex:0 1 140px}}

.summary-card{display:flex;flex-direction:column;align-items:center;gap:.6rem}
.summary-card .sc-name{font-family:'Bricolage Grotesque','Inter','Noto Sans Thai',system-ui,sans-serif;
  font-weight:800;letter-spacing:-.02em;font-size:1.05rem;line-height:1.1;text-align:center}
.summary-card .progress-bar{width:100%}
/* the home progress card header face sits inline, a touch smaller */
.progress-card-face{--rf:44px}

/* ===== home "Dein Fortschritt" card =====================================
 * Three bands with real breathing room: WHO (face + name + streak),
 * HOW FAR (bar + %), HOW WELL (average + badges). The card used to cram the
 * average into the header beside the name, which buried the one number the
 * learner actually looks for. */
.nv-prog{display:flex;flex-direction:column;gap:.85rem}
.nv-prog-top{display:flex;align-items:center;gap:.75rem}
.nv-prog-id{min-width:0;flex:1}
.nv-prog-name{font-family:'Bricolage Grotesque','Inter','Noto Sans Thai',system-ui,sans-serif;
  font-weight:800;letter-spacing:-.02em;font-size:1.06rem;line-height:1.15}
.nv-prog-sub{font-size:.75rem;color:rgba(255,255,255,.55);margin-top:.1rem}
.nv-prog-barrow{display:flex;align-items:center;gap:.6rem}
.nv-prog-barrow .progress-bar{flex:1}
.nv-prog-pct{font-family:'Bricolage Grotesque','Inter',sans-serif;font-weight:800;
  font-size:.82rem;color:rgba(255,255,255,.72);flex:none;min-width:2.6em;text-align:right;
  font-variant-numeric:tabular-nums}
.nv-prog-foot{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  flex-wrap:wrap;padding-top:.7rem;border-top:1px solid rgba(255,255,255,.07)}
.nv-prog-avg{font-family:'Bricolage Grotesque','Inter',sans-serif;font-weight:800;
  font-size:1.35rem;line-height:1;font-variant-numeric:tabular-nums}
.nv-prog-badges{display:flex;gap:.25rem;flex-wrap:wrap;justify-content:flex-end}
/* the richer card needs more than the 150px roster minimum */
#home-progress-cards{grid-template-columns:repeat(auto-fit,minmax(min(100%,238px),1fr))}
/* ===== quiz result card ================================================
 * One score, shown once. The ring around the learner's own avatar IS the
 * result, so the card needs neither a second hero graphic (the old trophy /
 * books emoji sat right above the avatar) nor the figure repeated in the
 * name pill above it. */
.nv-res{--res:var(--nv-pos)}
.nv-res-gold{--res:var(--nv-gold)}
.nv-res-neg{--res:var(--nv-neg)}
.nv-res-dial{position:relative;width:140px;height:140px;margin:0 auto .9rem}
.nv-res-dial svg{width:100%;height:100%;transform:rotate(-90deg);overflow:visible}
.nv-res-track{fill:none;stroke:rgba(255,255,255,.09);stroke-width:7}
.nv-res-arc{fill:none;stroke:var(--res);stroke-width:7;stroke-linecap:round;
  filter:drop-shadow(0 0 10px color-mix(in srgb,var(--res) 55%,transparent));
  animation:nvResArc .9s cubic-bezier(.22,1,.36,1) both}
@keyframes nvResArc{from{stroke-dashoffset:327}}
.nv-res-face{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  pointer-events:none}
/* the emoji fallback ignores the px argument (avatars.js) — size it here so a
   member without an avatar fills the dial like a real one does */
.nv-res-face .nova-face-emoji{font-size:52px;line-height:1}
/* the avatar's own cyan/violet ring would sit concentric inside the score arc —
   two rings reading as one control. Inside the dial it's just the portrait. */
.nv-res-face .avatar-ring{padding:2px;background:rgba(255,255,255,.10)}
/* .content-section p wins on specificity inside a chapter, so every text rule
   below is scoped through .nv-res */
.nv-res .nv-res-name{font-family:'Bricolage Grotesque','Inter','Noto Sans Thai',system-ui,sans-serif;
  font-weight:800;letter-spacing:-.02em;font-size:1.3rem;line-height:1.1;margin:0;
  color:#fff}
.nv-res .nv-res-pct{font-family:'Bricolage Grotesque','Inter',sans-serif;font-weight:800;
  font-size:3.1rem;line-height:1;margin:.45rem 0 0;color:var(--res);
  font-variant-numeric:tabular-nums}
.nv-res .nv-res-pct span{font-size:.45em;margin-left:.06em;vertical-align:.42em;opacity:.7}
.nv-res .nv-res-raw{font-size:.8rem;line-height:1.4;color:rgba(255,255,255,.5);margin:.3rem 0 0;
  font-variant-numeric:tabular-nums}
.nv-res .nv-res-verdict{font-size:.95rem;line-height:1.5;color:rgba(255,255,255,.8);
  max-width:30ch;margin:1.1rem auto 1.5rem}
@media (prefers-reduced-motion:reduce){.nv-res-arc{animation:none}}

/* ===== unlock moment — the new avatar look ==============================
 * Fires the instant a gate chapter (3/7/11/15) is passed — js/main.js,
 * AvatarUnlock — with the look that was just earned, full size.
 *
 * Deliberately NOT a modal. The results card underneath keeps its scroll (no
 * html/body overflow lock, unlike .nvfr-overlay), focus is offered but never
 * trapped, and the scrim, the ×, Escape and the button all dismiss it. z-index
 * 9995 sits above the bottom tab bar (9990) and below the first-run overlay
 * (10000), which must always win.
 *
 * Same glass, radius and cyan→violet gradient as .nvfr-card and .nv-res — no
 * new visual language, just the existing one at celebration size. */
.nv-um{position:fixed;inset:0;z-index:9995;display:flex;align-items:center;justify-content:center;
  padding:max(16px,env(safe-area-inset-top,0px)) 16px calc(20px + env(safe-area-inset-bottom,0px));
  font-family:var(--nv-font-body);color:var(--nv-ink)}
.nv-um-scrim{position:absolute;inset:0;background:rgba(6,9,20,.74);cursor:pointer;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  animation:nvUmFade .26s ease-out both}
.nv-um-card{position:relative;width:100%;max-width:380px;margin:auto;text-align:center;
  padding:16px 20px 22px;border-radius:var(--nv-r-card);
  background:
    radial-gradient(120% 92% at 50% 0%,rgba(167,139,250,.22),transparent 64%),
    linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.025));
  border:1px solid rgba(103,232,249,.30);
  -webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);
  box-shadow:0 40px 90px -40px rgba(0,0,0,.85),inset 0 1px 0 rgba(255,255,255,.06);
  animation:nvUmIn .42s cubic-bezier(.22,.68,.3,1) both}
@keyframes nvUmFade{from{opacity:0}}
@keyframes nvUmIn{from{opacity:0;transform:translateY(14px) scale(.96)}}
.nv-um-x{position:absolute;top:4px;right:4px;width:44px;height:44px;border:0;border-radius:12px;
  background:transparent;color:var(--nv-muted);font-size:26px;line-height:1;cursor:pointer;
  font-family:inherit;transition:color .18s ease,background .18s ease}
.nv-um-x:hover{color:#fff;background:rgba(255,255,255,.08)}
/* padded clear of the × so a long kicker (Thai) can never run under it */
.nv-um .nv-um-kicker{margin:.35rem 0 .1rem;padding:0 44px;font-size:.72rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--nv-cyan-soft)}
.nv-um-fig{display:flex;align-items:flex-end;justify-content:center;margin:.4rem 0 1rem;min-height:230px}
/* The art ships on an opaque navy square (api/avatar-stage.js flattens it), so
   it needs a frame or it reads as a stray box on the glass. Rounded like every
   other tile in the app, lit from its own silhouette — the celebration, in two
   properties. */
.nv-um-fig .nv-fig>img{border-radius:var(--nv-r-tile);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10);
  filter:drop-shadow(0 18px 30px rgba(0,0,0,.6)) drop-shadow(0 0 34px rgba(34,211,238,.45))}
.nv-um .nv-um-title{margin:0;font-family:var(--nv-font-display);font-weight:800;
  font-size:1.5rem;line-height:1.16;letter-spacing:-.02em;text-wrap:balance;
  background:linear-gradient(120deg,#22d3ee,#a78bfa);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.nv-um .nv-um-sub{margin:.55rem auto 1.2rem;max-width:28ch;font-size:.95rem;line-height:1.5;
  color:#cbd5e1;text-wrap:balance}
.nv-um-cta{min-height:48px;padding:0 28px;border:0;border-radius:var(--nv-r-ctl);cursor:pointer;
  font-family:inherit;font-weight:700;font-size:.98rem;color:#04121a;
  background:linear-gradient(120deg,#22d3ee,#67e8f9);
  box-shadow:0 12px 26px -12px rgba(34,211,238,.65)}
.nv-um-cta:hover{background:linear-gradient(120deg,#22d3ee,#a5f3fc)}
.nv-um-x:focus-visible,.nv-um-cta:focus-visible{outline:2px solid var(--nv-cyan-soft);outline-offset:3px}
.nv-um.is-out .nv-um-scrim,.nv-um.is-out .nv-um-card{animation:none;opacity:0;transition:opacity .24s ease}
[data-lang="th"] .nv-um .nv-um-title{letter-spacing:0;line-height:1.36;font-size:1.3rem}
@media (max-height:640px){
  .nv-um-fig{min-height:150px}
  .nv-um-fig .nv-fig{height:150px !important}
}
@media (prefers-reduced-motion:reduce){
  .nv-um-scrim,.nv-um-card{animation:none}
  .nv-um.is-out .nv-um-scrim,.nv-um.is-out .nv-um-card{transition:none}
  .nv-um-x{transition:none}
}

/* single-line name that ellipsises when long (built tailwind.css omits .truncate) */
.rf-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* =============================================================================
 * Novara tokens + shared classes (docs/DESIGN_AUDIT.md §3) — the single source of
 * truth for colour, type, radius and the page frame. LOCKED brand values.
 * ========================================================================== */
:root{
  --nv-cyan:#22d3ee; --nv-cyan-soft:#67e8f9; --nv-violet:#a78bfa; --nv-violet-deep:#7c3aed;
  --nv-pink:#f472b6; --nv-gold:#fbbf24; --nv-pos:#34d399; --nv-neg:#f87171;
  --nv-teal:color-mix(in srgb, #22d3ee 55%, #34d399);          /* tip boxes: cyan-derived teal */
  --nv-bg:#0a0e1c; --nv-bg-2:#080b16; --nv-bg-3:#1a1035;
  --nv-ink:#eef2ff; --nv-muted:#94a3b8; --nv-faint:#5b6785; --nv-line:rgba(255,255,255,.09);
  --nv-grad:linear-gradient(120deg,#22d3ee,#a78bfa); --nv-grad-h:linear-gradient(90deg,#22d3ee,#a78bfa);
  --nv-glass:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.02));
  --nv-r-card:24px; --nv-r-tile:16px; --nv-r-ctl:14px; --nv-r-pill:999px;
  --nv-font-display:'Bricolage Grotesque','Inter','Noto Sans Thai',system-ui,sans-serif;
  --nv-font-body:'Inter','Noto Sans Thai',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  color-scheme:dark; accent-color:var(--nv-cyan);
}
/* keyboard focus — one ring for every control (inputs keep their cyan box-shadow) */
:focus-visible{outline:2px solid var(--nv-cyan-soft);outline-offset:2px}
.nv-tab:focus-visible{outline-offset:-2px}

/* page frame + hero (Home keeps its own full-height hero) */
.nv-page{position:relative;z-index:1;max-width:64rem;margin:0 auto;
  padding:calc(5.5rem + env(safe-area-inset-top,0px)) 1rem calc(3rem + env(safe-area-inset-bottom,0px))}
.nv-page-hero{text-align:center;margin-bottom:2.5rem}
.nv-hero-ic{width:84px;height:84px;object-fit:contain;margin:0 auto .75rem;display:block;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.55)) drop-shadow(0 0 26px color-mix(in srgb,var(--acc,var(--nv-cyan)) 45%,transparent))}
.nv-page-hero h1{font-family:var(--nv-font-display);font-weight:800;letter-spacing:-.02em;text-wrap:balance;
  font-size:clamp(2rem,5.5vw,3rem);line-height:1.08;margin:0 0 .5rem}
.nv-h1-gradient{background:var(--nv-grad);-webkit-background-clip:text;background-clip:text;color:transparent}
.nv-lead{color:var(--nv-muted);font-size:1.05rem;max-width:36rem;margin:0 auto}
.nv-eyebrow{display:inline-flex;align-items:center;gap:.4rem;padding:.4rem 1rem;border-radius:var(--nv-r-pill);
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.12);color:var(--nv-cyan-soft);font-size:.85rem;font-weight:600;margin-bottom:1rem}

/* buttons (the .glass-button* pair above carries the same values for existing markup) */
.nv-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:44px;padding:.65rem 1.25rem;
  border-radius:var(--nv-r-tile);font-weight:600;font-size:.95rem;border:1px solid transparent;cursor:pointer;
  transition:transform .15s,box-shadow .15s,background .15s}
.nv-btn-danger{background:rgba(248,113,113,.14);border-color:rgba(248,113,113,.45);color:#fecaca}
.nv-btn-danger:hover{background:rgba(248,113,113,.22)}
.nv-btn-ghost{background:transparent;border-color:transparent;color:var(--nv-muted)}
.nv-btn-ghost:hover{background:rgba(255,255,255,.08);color:var(--nv-ink)}
.nv-icon-btn{width:44px;height:44px;display:inline-grid;place-items:center;border-radius:12px;color:var(--nv-muted);background:transparent;border:0}
.nv-icon-btn:hover{background:rgba(255,255,255,.08);color:var(--nv-ink)}
.nv-icon-btn svg{width:18px;height:18px}
/* segmented control (login mode, kid/difficulty tabs use their own classes with the same look) */
.nv-seg{display:inline-flex;gap:.35rem;padding:.25rem;border-radius:var(--nv-r-pill);background:rgba(255,255,255,.05);border:1px solid var(--nv-line)}
.nv-seg>*{min-height:40px;padding:.45rem 1.1rem;border-radius:var(--nv-r-pill);color:var(--nv-muted);font-weight:600;border:0;background:transparent}
.nv-seg>.is-active{background:linear-gradient(120deg,var(--nv-cyan),var(--nv-cyan-soft));color:#04121a}
.nv-seg>.is-active.is-advanced{background:linear-gradient(120deg,var(--nv-violet),#c4b5fd)}
.nv-link{color:var(--nv-cyan-soft);text-decoration:underline;text-underline-offset:3px;min-height:44px;display:inline-flex;align-items:center}

/* semantic + accent text (the only status colours: used sparingly, never raw Tailwind) */
.nv-pos{color:var(--nv-pos)} .nv-neg{color:var(--nv-neg)} .nv-gold{color:var(--nv-gold)}
.nv-cyan{color:var(--nv-cyan-soft)} .nv-violet{color:var(--nv-violet)} .nv-pink{color:var(--nv-pink)}
.nv-border-neg{border-color:rgba(248,113,113,.35)} .nv-border-pos{border-color:rgba(52,211,153,.35)}
.nv-dot{display:inline-block;width:.6em;height:.6em;border-radius:50%;background:currentColor;vertical-align:middle}

/* chapter accent — the ONLY place a chapter's colour is defined (by FILE number:
   cyan → violet → pink → gold). Home / Chapters cards mirror these four values. */
body[data-chapter="1"],body[data-chapter="5"],body[data-chapter="9"],body[data-chapter="13"]{--acc:var(--nv-cyan)}
body[data-chapter="2"],body[data-chapter="6"],body[data-chapter="10"],body[data-chapter="14"]{--acc:var(--nv-violet)}
body[data-chapter="3"],body[data-chapter="7"],body[data-chapter="11"],body[data-chapter="15"]{--acc:var(--nv-pink)}
body[data-chapter="4"],body[data-chapter="8"],body[data-chapter="12"],body[data-chapter="16"]{--acc:var(--nv-gold)}
.nv-ch-badge{color:var(--acc,var(--nv-cyan))}
/* chapter sub-cards: calm ink headings (accent only via .nv-* classes) + glass tables */
.content-section .glass-card h4{color:var(--nv-ink)}
.content-section table{border-color:var(--nv-line)}
.content-section thead,.content-section th{background:rgba(255,255,255,.04)}

/* controls */
.nv-range{-webkit-appearance:none;appearance:none;width:100%;height:6px;padding:19px 0;background-clip:content-box;border-radius:var(--nv-r-pill);
  background:rgba(255,255,255,.14);cursor:pointer}
.nv-range::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;border-radius:50%;background:#fff;border:2px solid var(--nv-cyan);box-shadow:0 0 0 4px rgba(34,211,238,.18)}
.nv-range::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:#fff;border:2px solid var(--nv-cyan);box-shadow:0 0 0 4px rgba(34,211,238,.18)}

/* empty state + footer */
.nv-empty{display:grid;justify-items:center;gap:.5rem;padding:2rem 1rem;text-align:center;color:var(--nv-muted)}
.nv-empty img{width:64px;height:64px;object-fit:contain;filter:drop-shadow(0 8px 18px rgba(0,0,0,.5))}
.nv-footer{position:relative;z-index:1;margin:3rem 1rem 1rem;padding:1.25rem 0 0;text-align:center;color:var(--nv-muted);font-size:.8rem;border-top:1px solid var(--nv-line)}
.nv-footer img{width:20px;height:20px;vertical-align:-5px;margin-right:.35rem;display:inline-block}
.nv-footer a{color:var(--nv-cyan-soft);text-decoration:underline;text-underline-offset:3px}

/* legal shell (33 pages): brand strip + back link, ink headings 700–800, no bottom bar */
.nv-legal{max-width:48rem}
.nv-legal h1{font-size:1.9rem;margin:.5rem 0 1.25rem}
.nv-legal h2{font-weight:700;font-size:1.1rem;margin-top:1.5rem}
.nv-back{display:inline-flex;align-items:center;min-height:44px;color:var(--nv-cyan-soft);font-size:.9rem;text-decoration:underline;text-underline-offset:3px;white-space:nowrap}

/* Thai bottom-tab labels: room for tone marks */
[data-lang="th"] .nv-tab-label{font-size:11px;line-height:1.35}

@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}.animate-on-scroll{opacity:1;transform:none}}

/* =============================================================================
 * Bottom tab bar (js/bottom-nav.js) — 2026-09
 * Scoped under html.nv-bottomnav, which bottom-nav.js sets on every
 * authenticated page. login.html never loads that script, so its full pre-auth
 * nav is untouched.
 * ========================================================================== */

/* ── Slim brand strip (replaces the retired top <nav> on every page, legal pages
      included): N mark + wordmark, SCROLLS AWAY (position:absolute, not fixed) so
      nothing overlays the content. Any secondary control (legal "back" link) sits
      at the right. ── */
.nv-brand { position: absolute; top: 0; left: 0; right: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  height: calc(3.25rem + env(safe-area-inset-top, 0px)); padding: env(safe-area-inset-top, 0px) 1rem 0; }
.nv-brand-link { display: inline-flex; align-items: center; gap: .5rem; min-height: 44px; text-decoration: none; }
.nv-brand-link img { width: 28px; height: 28px; border-radius: 8px; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .55)); }
.nv-wordmark { font-family: var(--nv-font-display); font-weight: 800; font-size: 1.25rem; letter-spacing: -.02em; line-height: 1;
  background: var(--nv-grad); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* ── Native-style fixed bottom tab bar ── */
.nv-bottombar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000;
  background: rgba(8, 11, 22, .82);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border-top: 1px solid rgba(255, 255, 255, .09);
  padding-bottom: max(6px, env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -8px 30px -14px rgba(0, 0, 0, .65);
}
.nv-bottombar-row {
  max-width: 560px; margin: 0 auto; height: 58px;
  display: flex; align-items: stretch;
  padding-top: 2px;                 /* keep the active-tab indicator off the border */
}
.nv-tab {
  position: relative; flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; text-decoration: none; padding: 4px 2px 6px;
  color: rgba(226, 232, 240, .55);
  -webkit-tap-highlight-color: transparent;
  transition: color .15s ease;
}
.nv-tab-ic {
  width: 26px; height: 26px; object-fit: contain; display: block;
  filter: grayscale(.55) brightness(.92); opacity: .72;
  transition: filter .15s ease, opacity .15s ease, transform .15s ease;
}
.nv-tab-label {
  font-size: 10.5px; line-height: 1.2; font-weight: 600; letter-spacing: .01em;
  max-width: 100%; overflow: visible; white-space: nowrap;
}
.nv-tab.is-active { color: #67e8f9; }
.nv-tab.is-active .nv-tab-ic { filter: none; opacity: 1; transform: translateY(-1px); }
/* active indicator: short cyan→violet bar across the top of the active tab */
.nv-tab.is-active::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 28px; height: 3px; border-radius: 0 0 3px 3px;
  background: linear-gradient(90deg, #22d3ee, #a78bfa);
  box-shadow: 0 0 10px rgba(34, 211, 238, .5);
}
.nv-tab:active .nv-tab-ic { transform: scale(.92); }

/* content clears the fixed bar (bar height + iPhone home indicator) */
html.nv-bottomnav body { padding-bottom: calc(58px + max(6px, env(safe-area-inset-bottom, 0px))); }

/* ===== Novara premium — Chapters overview cards (2026-g) =====
 * The Chapters list reuses the Home page's .chapter-card / .ch-* design (defined
 * above). These rules only add the Chapters-specific pieces: the freemium
 * Open/Locked state and the per-member progress, folded INTO the premium card. */

/* Locked chapters open the paywall via a <button>; make it identical to the <a> cards. */
button.chapter-card { width: 100%; text-align: left; font: inherit; color: inherit;
  cursor: pointer; -webkit-appearance: none; appearance: none; }

/* Completion / progress seal — top-left of the hero, opposite the "Chapter N" badge. */
.ch-seal { position: absolute; top: 12px; left: 12px; z-index: 2;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 700; letter-spacing: .03em; padding: 5px 11px; border-radius: 999px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.ch-seal--done { color: #6ee7b7; background: rgba(52,211,153,.18); border: 1px solid rgba(52,211,153,.42); }
.ch-seal--progress { color: #fde68a; background: rgba(251,191,36,.16); border: 1px solid rgba(251,191,36,.40); }

/* Locked hero: dim the art and float a lock disc over it (corner chips stay crisp). */
.chapter-card.is-locked .ch-ico { opacity: .32; filter: grayscale(.55); }
.chapter-card.is-locked .ch-hero {
  background:
    radial-gradient(130% 105% at 50% -10%, rgba(148,163,184,.14), transparent 68%),
    linear-gradient(180deg, rgba(148,163,184,.08), rgba(255,255,255,.015)); }
.ch-lock-disc { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); z-index: 2;
  width: 58px; height: 58px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 26px; background: rgba(6,10,22,.60); border: 1px solid rgba(255,255,255,.18);
  box-shadow: 0 10px 26px -10px rgba(0,0,0,.7); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }

/* Per-member score chips (name + %). */
.ch-kids { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.ch-kid { font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px; line-height: 1.55; }

/* Meta row: status pill (left) + CTA (right), pinned to the card bottom (p is flex:1). */
.ch-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 6px; }
.ch-status { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
  padding: 4px 11px; border-radius: 999px; border: 1px solid rgba(255,255,255,.12);
  background: rgba(255,255,255,.05); color: #cbd5e1; }
.ch-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.ch-status--done { color: #6ee7b7; background: rgba(52,211,153,.14); border-color: rgba(52,211,153,.32); }
.ch-status--progress { color: #fde68a; background: rgba(251,191,36,.14); border-color: rgba(251,191,36,.32); }
.ch-status--locked { color: #cbd5e1; background: rgba(255,255,255,.06); }
.ch-status--open { color: #94a3b8; }

/* CTA (Start / Continue / Review / Unlock) — turns accent on hover, like Home's "Start ›". */
.ch-cta { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 600;
  color: #94a3b8; white-space: nowrap; transition: color .18s ease; }
.chapter-card:hover .ch-cta { color: var(--acc); }
.ch-cta svg { transition: transform .18s ease; }
.chapter-card:hover .ch-cta svg { transform: translateX(3px); }

/* ===== bugfix (2026-09-03, app-shell agent): Netherlands jurisdiction hooks =====
 * Every other market has a .ctry-xx / xx-hide pair; NL had none, so a
 * LANGUAGE-NEUTRAL cell (a shared number/row) could not vary for the Dutch
 * jurisdiction. Mirrors the .ctry-es / es-hide pattern above: opt in per element
 * by putting `nl-hide` on the .ctry-de span that has a .ctry-nl sibling. No blanket
 * [data-country="nl"] .ctry-de{none} — language and jurisdiction stay independent. */
.ctry-nl { display: none !important; }
[data-country="nl"] .ctry-nl { display: unset !important; }
[data-country="nl"] .nl-hide { display: none !important; }

/* =============================================================================
 * Novara CONVERSION block (2026-09, sales-levers agent) — append-only.
 * Paywall sheet (js/iap.js), unlock-moment card under a free chapter's quiz
 * score, quiz "Share" button + toast (js/share.js), web → App Store banner,
 * settings "Recommend" card. Brand: cyan #22d3ee · violet #a78bfa · gold #fbbf24.
 * Tap targets ≥ 44px, :focus-visible rings, content kept clear of the bottom bar.
 * ========================================================================== */

/* ── paywall sheet ── */
.iap-sheet { background:
    radial-gradient(120% 90% at 50% -20%, rgba(34,211,238,.16), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,.025)) !important;
  border: 1px solid rgba(103,232,249,.22) !important;
  box-shadow: 0 40px 90px -40px rgba(0,0,0,.85), 0 0 0 1px rgba(255,255,255,.04) inset, 0 30px 70px -40px rgba(34,211,238,.35) !important; }
.iap-sheet:hover { transform: none; }
.iap-hero { width: 72px; height: 72px; margin: 0 auto 12px; border-radius: 22px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, rgba(34,211,238,.22), rgba(167,139,250,.22)); border: 1px solid rgba(255,255,255,.14);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.12), 0 14px 30px -14px rgba(34,211,238,.6); }
.iap-hero-ic { width: 46px; height: 46px; object-fit: contain; filter: drop-shadow(0 6px 14px rgba(0,0,0,.5)) drop-shadow(0 0 16px rgba(34,211,238,.45)); }
.iap-headline { font-family: 'Bricolage Grotesque','Inter','Noto Sans Thai',system-ui,sans-serif; font-size: 1.5rem; line-height: 1.15;
  background: linear-gradient(120deg, #e0fbff, #c4b5fd); -webkit-background-clip: text; background-clip: text; color: transparent; }
.iap-benefits { display: flex; flex-direction: column; gap: 10px; }
.iap-benefit { display: flex; align-items: flex-start; gap: 10px; line-height: 1.4; }
.iap-check { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, rgba(251,191,36,.28), rgba(251,191,36,.12)); border: 1px solid rgba(251,191,36,.55);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 6px 14px -8px rgba(251,191,36,.7); }
.iap-check .ce-ic { width: 16px; height: 16px; margin: 0; vertical-align: 0;
  filter: sepia(1) saturate(4) hue-rotate(5deg) brightness(1.05) drop-shadow(0 1px 2px rgba(0,0,0,.4)); }
.iap-pricebox { padding: 12px 14px; border-radius: 18px; background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.09); }
.iap-price:empty::before { content: '…'; color: #64748b; font-weight: 500; }
.iap-anchor { line-height: 1.45; text-wrap: balance; }
.iap-buy { min-height: 56px; }
.iap-buy .ce-ic { width: 1.25em; height: 1.25em; margin: 0; }
.iap-restore { min-height: 44px; }
.iap-trust .ce-ic { width: 1.1em; height: 1.1em; vertical-align: -0.2em; }
.iap-close { border-radius: 12px; }

/* ── unlock moment (quiz results) ── */
.nv-unlock-card { border: 1px solid rgba(103,232,249,.18) !important;
  background: radial-gradient(110% 80% at 50% -10%, rgba(34,211,238,.13), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.02)) !important; }
.nv-unlock-card:hover { transform: none; }
.nv-unlock-card.is-primary { border-color: rgba(251,191,36,.35) !important;
  background: radial-gradient(110% 80% at 50% -10%, rgba(251,191,36,.14), transparent 60%),
    radial-gradient(90% 70% at 100% 100%, rgba(34,211,238,.12), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.02)) !important; }
.nv-unlock-progress { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: #67e8f9; padding: 5px 12px; border-radius: 999px; background: rgba(34,211,238,.1); border: 1px solid rgba(34,211,238,.3); }
.nv-unlock-dot { width: 7px; height: 7px; border-radius: 50%; background: #22d3ee; box-shadow: 0 0 10px #22d3ee; }
.nv-unlock-lead { font-family: 'Bricolage Grotesque','Inter','Noto Sans Thai',system-ui,sans-serif; font-weight: 800; font-size: 1.35rem; margin: 12px 0 6px; }
.nv-unlock-next { color: #67e8f9; text-decoration: underline; text-underline-offset: 3px; font-weight: 600; }
.nv-unlock-next:hover { color: #fff; }
.nv-unlock-btn { min-height: 48px; }
.nv-unlock-btn .ce-ic { width: 1.2em; height: 1.2em; margin: 0; }
.nv-unlock-btn--soft { color: #67e8f9; background: rgba(34,211,238,.08); border: 1px solid rgba(34,211,238,.45);
  transition: background .18s ease, border-color .18s ease, transform .18s ease; }
.nv-unlock-btn--soft:hover { background: rgba(34,211,238,.16); border-color: #22d3ee; transform: translateY(-1px); }

/* ── share button + toast ── */
.nv-share-btn { min-height: 48px; }
.nv-share-btn .ce-ic { width: 1.2em; height: 1.2em; margin: 0; }
.nv-toast { position: fixed; left: 50%; bottom: calc(58px + env(safe-area-inset-bottom, 0px) + 1rem); transform: translateX(-50%); z-index: 10000;
  padding: .75rem 1.25rem; border-radius: 1rem; background: rgba(20,16,40,.96); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.15); color: #e5e7eb; font-size: .9rem; box-shadow: 0 8px 30px rgba(0,0,0,.4); max-width: 90vw; text-align: center; }
html.nv-has-storebanner .nv-toast { bottom: calc(58px + 76px + env(safe-area-inset-bottom, 0px) + 1rem); }

/* ── web → App Store banner (non-native only; sits above the bottom tab bar) ── */
.nv-storebanner { position: fixed; left: 10px; right: 10px; bottom: calc(58px + env(safe-area-inset-bottom, 0px) + 8px); z-index: 9990;
  display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 10px; border-radius: 18px;
  background: linear-gradient(180deg, rgba(20,16,44,.92), rgba(12,10,28,.94)); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid rgba(103,232,249,.28); box-shadow: 0 18px 44px -18px rgba(0,0,0,.8), 0 0 0 1px rgba(255,255,255,.03) inset; }
@media (min-width: 640px) { .nv-storebanner { left: 50%; right: auto; transform: translateX(-50%); width: min(640px, calc(100vw - 24px)); } }
.nv-sb-logo { width: 34px; height: 34px; border-radius: 10px; flex: 0 0 auto; object-fit: contain; }
.nv-sb-text { flex: 1; margin: 0; font-size: 12.5px; line-height: 1.3; color: #e2e8f0; min-width: 0; }
.nv-sb-cta { flex: 0 0 auto; min-height: 44px; padding: 0 14px; border-radius: 12px; display: inline-flex; align-items: center; font-weight: 700; font-size: 13px;
  color: #04121a !important; background: linear-gradient(120deg, #22d3ee, #67e8f9); box-shadow: 0 10px 24px -10px rgba(34,211,238,.6); white-space: nowrap; }
.nv-sb-cta:hover { background: linear-gradient(120deg, #22d3ee, #a5f3fc); }
.nv-sb-close { flex: 0 0 auto; width: 44px; height: 44px; border-radius: 12px; font-size: 24px; line-height: 1; color: #94a3b8; background: transparent; }
.nv-sb-close:hover { color: #fff; background: rgba(255,255,255,.08); }
/* keep page content clear of banner + bottom bar */
html.nv-has-storebanner.nv-bottomnav body { padding-bottom: calc(58px + 76px + env(safe-area-inset-bottom, 0px)); }

/* ── settings: recommend card ── */
.nv-recommend { border-color: rgba(167,139,250,.28) !important;
  background: radial-gradient(110% 80% at 0% 0%, rgba(167,139,250,.14), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.02)) !important; }
.nv-recommend-btn { min-height: 44px; }
/* ===== tap targets ========================================================
 * Apple HIG asks for 44×44pt. Found by scripts/qa-suite.mjs --only=tap: the
 * shared button/input classes sat at 30–42px. Set as a MINIMUM so nothing
 * shrinks and existing padding still wins where it is already larger.
 * Inline links inside prose are text, not controls, and are left alone. */
.glass-button,
.glass-button-primary,
.nv-btn,
.difficulty-tab,
.kid-tab { min-height: 44px }

/* buttons that are laid out as flex rows need the content centred once the
   min-height exceeds their own padding */
.glass-button, .glass-button-primary, .nv-btn { display: inline-flex; align-items: center; justify-content: center }

.calc-input,
input[type="number"], input[type="text"], input[type="email"],
input[type="password"], input[type="time"], input[type="date"], select { min-height: 44px }

/* a slider is dragged, so its track needs the full target height too */
input[type="range"] { min-height: 44px }

/* The settings legal row is a list of navigation links (display:block), not
   inline prose — at 20px they were the smallest targets in the app. */
#legal-links a, .nv-legal-links a { min-height: 44px; display: inline-flex; align-items: center }

/* a 20px checkbox is a 20px target; grow the box and give the row room */
input[type="checkbox"], input[type="radio"] { width: 22px; height: 22px }
label:has(> input[type="checkbox"]), label:has(> input[type="radio"]) { min-height: 44px; display: flex; align-items: center }

/* ===== small-phone fixes (iPhone SE / 320px) =============================
 * Found by scripts/qa-suite.mjs --only=layout. */

/* The tools' Save/Reset row is a centred flex row of two px-6 buttons: at 320px
   they total more than the viewport and pushed out both edges. */
.nv-actions-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem }

/* The bottom bar splits 5 ways, so at 320px each tab gets ~64px and the longest
   label ("Einstellungen" / "Instellingen") ran past its cell. */
@media (max-width: 360px) {
  .nv-tab-label { font-size: 9px; letter-spacing: 0 }
  .nv-tab { padding-left: 1px; padding-right: 1px }
}

/* Results table: each chapter wears its own accent (set per row as --acc in
   tests/scoreboard.html) so the CI carries across from the chapter cards. */
.score-row .sr-num { color: var(--acc, #22d3ee); font-weight: 700; opacity: .9 }
/* the chapter title is the row's navigation target — give it the full 44px */
.score-row .sr-title { display: inline-flex; align-items: center; min-height: 44px }
.score-row .sr-title:hover { color: var(--acc, #22d3ee) }

/* =============================================================================
 * Page-to-page transitions (2026-09)
 * Every screen is its own document, so a tab tap swapped documents with a hard
 * cut. Two layers, both pure CSS — the legal pages load no JS at all, and CSS
 * alone can never strand a page mid-fade the way an interrupted script can:
 *   1. Cross-document View Transitions where the engine has them (iOS 18.2+):
 *      the CONTENT cross-fades while the tab bar and brand strip hold still,
 *      which is what makes it read as one app rather than two pages.
 *   2. Everywhere else: the incoming document eases up from the brand ground.
 *      Opacity only — a transform on <body> would re-root every position:fixed
 *      child (the tab bar) to the body box and drag it along.
 * ========================================================================== */
@view-transition { navigation: auto; }

/* WHY IT IS BUILT THIS WAY — a cross-fade flickered.
 * The first version faded the old frame OUT over .16s while the new one faded
 * IN over .26s. Between 160ms and 260ms the outgoing frame was already gone and
 * the incoming one was still translucent, so the page ground showed through:
 * measured on a device recording as a flat dark frame for 34-100ms on EVERY
 * navigation. (The UA's own cross-fade avoids this with mix-blend-mode:
 * plus-lighter, which is energy-preserving; overriding the animations with
 * mismatched durations threw that away.)
 *
 * So: never let the composite go translucent. The outgoing frame is HELD fully
 * opaque for the whole transition and the incoming one fades in ON TOP of it
 * (::view-transition-new paints above ::view-transition-old). At every instant
 * the screen shows either 100% of the old page, or the new page over a fully
 * opaque old page. There is no moment where the ground can show through.
 * mix-blend-mode must be normal here — plus-lighter would ADD the two opaque
 * layers and wash the picture out. */
::view-transition-old(root),
::view-transition-new(root) { mix-blend-mode: normal; }
::view-transition-old(root) { animation: nvDocHold .22s linear both; z-index: 0; }
::view-transition-new(root) { animation: nvDocIn   .22s ease-out both; z-index: 1; }
@keyframes nvDocHold { from { opacity: 1 } to { opacity: 1 } }
@keyframes nvDocIn   { from { opacity: 0 } to { opacity: 1 } }

/* Chrome is continuous across the swap, so it gets its own names and is lifted
   out of the root snapshot instead of cross-fading with the content. */
.nv-bottombar { view-transition-name: nv-bottombar; }
.nv-brand     { view-transition-name: nv-brand; }

/* Engines without view transitions still get a soft entry. Scoped so a
   VT-capable engine never runs both (a body starting at opacity 0 would be
   snapshotted blank and the content would only appear once the VT finished). */
@supports not (view-transition-name: none) {
  /* Starting at opacity 0 would show the ground for the whole fade — the very
     thing this section exists to prevent. Start nearly opaque: enough to read
     as an arrival, never enough to flash. */
  body { animation: nvDocSoft .18s ease-out; }
  @keyframes nvDocSoft { from { opacity: .6 } to { opacity: 1 } }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none }
  body { animation: none }
}

/* tools card "go" chevron. The cards are whole-card <a>s, so the "Öffnen"
   label only restated what the card already was; the chevron stays as the
   affordance, pushed to the trailing edge so it isn't orphaned in the space the
   word used to fill. (justify-end isn't in the built tailwind.css subset.) */
.nv-tool-go{display:flex;align-items:center;justify-content:flex-end}
/* paywall "back" — same 44px target as every other control in the sheet */
.iap-back { min-height: 44px; padding: 0 .75rem; }

/* ── keyboard focus (all new controls) ── */
.iap-buy:focus-visible, .iap-restore:focus-visible, .iap-close:focus-visible, .nv-unlock-btn:focus-visible, .nv-unlock-next:focus-visible,
.nv-share-btn:focus-visible, .nv-sb-cta:focus-visible, .nv-sb-close:focus-visible, .nv-recommend-btn:focus-visible {
  outline: 2px solid #22d3ee; outline-offset: 3px; box-shadow: 0 0 0 5px rgba(34,211,238,.22); }

/* =============================================================================
 * ===== Novara first-run =====
 * (2026-09-04, onboarding agent) — append-only, namespaced .nvfr-*.
 * The four-step welcome overlay driven by js/firstrun.js: story → country →
 * name → avatar. Step 4 hands off to avatar/avatar-onboarding.js (.nvo-*,
 * z-index 9998), so this overlay sits at 10000: above the bottom tab bar
 * (9990) and the avatar step, BELOW the register sheet (js/account.js, 10050)
 * which must be able to open on top of it.
 * Brand: cyan #22d3ee → violet #a78bfa, navy #0a0e1c/#080b16, gold #fbbf24,
 * glass cards at 24px, Bricolage headings / Inter body. Tap targets ≥ 44px,
 * :focus-visible rings, clear of the home indicator, no horizontal scroll,
 * honours prefers-reduced-motion.
 * ========================================================================== */

/* Freeze the page behind the overlay (restored in FirstRun._finish). */
html.nvfr-open, html.nvfr-open body { overflow: hidden; }

.nvfr-overlay {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: max(16px, env(safe-area-inset-top, 0px)) 16px calc(20px + env(safe-area-inset-bottom, 0px));
  color: var(--nv-ink, #eef2ff);
  font-family: var(--nv-font-body, 'Inter', 'Noto Sans Thai', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
  /* the app ground (css/style.css body::before), a touch denser for a modal */
  background:
    radial-gradient(1100px 760px at 84% -10%, rgba(124, 58, 237, .30), transparent 56%),
    radial-gradient(900px 680px at 2% 4%, rgba(34, 211, 238, .15), transparent 52%),
    radial-gradient(760px 720px at 62% 112%, rgba(244, 114, 182, .10), transparent 55%),
    linear-gradient(165deg, #080b16, #140a2a 50%, #0a0e1c);
}
.nvfr, .nvfr * { box-sizing: border-box; }
.nvfr { width: 100%; max-width: 560px; margin: auto; }

.nvfr-card {
  border-radius: var(--nv-r-card, 24px);
  padding: 18px 20px 22px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, .025));
  border: 1px solid rgba(255, 255, 255, .12);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  box-shadow: 0 40px 90px -40px rgba(0, 0, 0, .85), inset 0 1px 0 rgba(255, 255, 255, .06);
  animation: nvfrIn .34s cubic-bezier(.22, .68, .3, 1) both;
}
@keyframes nvfrIn { from { opacity: 0; transform: translateY(10px) scale(.985); } }

/* ── top row: progress dots + the persistent Skip ── */
.nvfr-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 44px; margin-bottom: 6px; }
.nvfr-top-spacer { display: block; width: 1px; height: 44px; }
.nvfr-dots { display: flex; align-items: center; gap: 6px; }
.nvfr-dot { width: 7px; height: 7px; border-radius: 999px; background: rgba(255, 255, 255, .18); transition: width .25s ease, background .25s ease; }
.nvfr-dot.is-done { background: rgba(103, 232, 249, .55); }
.nvfr-dot.is-on { width: 24px; background: linear-gradient(90deg, #22d3ee, #a78bfa); box-shadow: 0 0 12px rgba(34, 211, 238, .55); }
.nvfr-skip {
  min-height: 44px; padding: 0 12px; border: 0; border-radius: 12px; cursor: pointer;
  background: transparent; color: var(--nv-muted, #94a3b8);
  font-family: inherit; font-size: 14px; font-weight: 600;
  transition: color .18s ease, background .18s ease;
}
.nvfr-skip:hover { color: #fff; background: rgba(255, 255, 255, .08); }

/* ── story ── */
.nvfr-logo-wrap { display: flex; justify-content: center; margin: 4px 0 14px; }
/* The N mark ships as an opaque square app icon (no alpha), so it gets the
   app-icon treatment — squircle radius + hairline ring — instead of reading as a
   stray box floating on the ground. */
.nvfr-logo {
  width: 76px; height: 76px; object-fit: contain;
  border-radius: 22px; box-shadow: 0 0 0 1px rgba(255, 255, 255, .10) inset, 0 0 0 1px rgba(34, 211, 238, .28);
  filter: drop-shadow(0 14px 28px rgba(0, 0, 0, .6)) drop-shadow(0 0 30px rgba(34, 211, 238, .45));
}
.nvfr-title {
  margin: 0 0 .6rem; text-align: center;
  font-family: var(--nv-font-display, 'Bricolage Grotesque', 'Inter', 'Noto Sans Thai', system-ui, sans-serif);
  font-weight: 800; font-size: 1.72rem; line-height: 1.14; letter-spacing: -.02em; text-wrap: balance;
  background: linear-gradient(120deg, #22d3ee, #a78bfa);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.nvfr-card[lang="th"] .nvfr-title { letter-spacing: 0; line-height: 1.34; font-size: 1.5rem; }
.nvfr-sub { margin: 0 0 1.15rem; text-align: center; color: #cbd5e1; font-size: .95rem; line-height: 1.5; text-wrap: balance; }
.nvfr-story { margin: 0 0 .55rem; text-align: center; color: #cbd5e1; font-size: .94rem; line-height: 1.6; }
.nvfr-sign { margin: 0 0 1.05rem; text-align: center; color: var(--nv-gold, #fbbf24); font-weight: 700; font-size: .82rem; letter-spacing: .05em; }

.nvfr-facts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 0 0 1.25rem; }
.nvfr-fact {
  display: inline-flex; align-items: center; gap: 6px; line-height: 1.3;
  padding: 6px 11px; border-radius: 999px; font-size: 12.5px; font-weight: 600; color: #e2e8f0;
  background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .12);
}
.nvfr-fact .nvfr-ic { width: 16px; height: 16px; margin: 0; vertical-align: 0; flex: 0 0 auto; }

/* ── country tiles ── */
.nvfr-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0 0 1.25rem; }
@media (min-width: 520px) { .nvfr-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.nvfr-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  min-height: 84px; padding: 12px 8px; border-radius: 18px; cursor: pointer;
  color: #e2e8f0; font-family: inherit;
  background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .12);
  transition: transform .15s ease, border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.nvfr-tile:hover { transform: translateY(-2px); border-color: rgba(34, 211, 238, .55); }
.nvfr-flag { font-size: 1.8rem; line-height: 1; }
.nvfr-cname { font-size: 12.5px; font-weight: 600; line-height: 1.25; text-align: center; overflow-wrap: anywhere; }
.nvfr-tile[aria-checked="true"] {
  border-color: #22d3ee; color: #fff;
  background: linear-gradient(180deg, rgba(34, 211, 238, .18), rgba(167, 139, 250, .10));
  box-shadow: 0 0 0 1px rgba(34, 211, 238, .5), 0 16px 34px -16px rgba(34, 211, 238, .65);
}

/* ── name field ── */
.nvfr-field {
  width: 100%; min-height: 52px; margin: 0 0 1.25rem; padding: 14px 16px;
  border-radius: var(--nv-r-tile, 16px); border: 1px solid rgba(255, 255, 255, .14);
  background: rgba(255, 255, 255, .05); color: var(--nv-ink, #eef2ff);
  font-family: inherit; font-size: 1rem; outline: none;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.nvfr-field::placeholder { color: #64748b; }
.nvfr-field:focus { border-color: #22d3ee; box-shadow: 0 0 0 3px rgba(34, 211, 238, .22); }

/* ── primary action ── */
.nvfr-cta { width: 100%; min-height: 52px; font-weight: 700; font-size: 1rem; }

/* ── keyboard focus ── */
.nvfr-card:focus { outline: none; }   /* the dialog takes focus per step; it must not ring */
.nvfr-skip:focus-visible, .nvfr-tile:focus-visible, .nvfr-cta:focus-visible, .nvfr-field:focus-visible {
  outline: 2px solid #22d3ee; outline-offset: 3px; box-shadow: 0 0 0 5px rgba(34, 211, 238, .22);
}

/* Short phones: keep the story on one screen without scrolling. */
@media (max-height: 720px) {
  .nvfr-logo { width: 60px; height: 60px; border-radius: 17px; }
  .nvfr-logo-wrap { margin: 0 0 10px; }
  .nvfr-title { font-size: 1.5rem; }
  .nvfr-story { font-size: .9rem; line-height: 1.55; }
}

@media (prefers-reduced-motion: reduce) {
  .nvfr-card { animation: none; }
  .nvfr-card, .nvfr-tile, .nvfr-dot, .nvfr-skip, .nvfr-field { transition: none !important; }
  .nvfr-tile:hover { transform: none; }
}

/* ==========================================================================
 * Home greeting — the avatar is the hero here, not a 40px chip beside the name.
 * Sized in CSS rather than by the rendered pixel width so it stays responsive:
 * capped at 240px on a wide screen, 52vw on a narrow one, so it can never
 * overflow or crowd the CTAs below.
 * ====================================================================== */
#account-greeting .avatar-ring,
#account-greeting .nova-avatar {
  width: min(240px, 52vw) !important;
  height: min(240px, 52vw) !important;
  box-shadow: 0 0 0 4px rgba(15, 23, 42, .55),
              0 0 42px rgba(34, 211, 238, .38),
              0 0 70px rgba(167, 139, 250, .32);
}
#account-greeting .nova-face-emoji { font-size: min(120px, 26vw); line-height: 1; }

/* ===== drag & drop sort exercise (js/sortgame.js) =========================
 * Replaces two passive "discuss together" lists with something the learner
 * drives. Drag works on a pointer; tap-chip-then-tap-bucket works everywhere,
 * which is the path that actually gets used on a phone. */
.nvsg { margin-top: .5rem }
.nvsg-head { margin-bottom: .9rem }
.nvsg-title { font-weight: 700; color: #fff; margin: 0 0 .15rem; font-size: .98rem }
.nvsg-sub { font-size: .8rem; color: #94a3b8; margin: 0 }

.nvsg-zones { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem }
.nvsg-zone {
  border-radius: 1rem; padding: .7rem .6rem; min-height: 104px; cursor: pointer;
  border: 1.5px dashed rgba(255,255,255,.20);
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.02));
  transition: border-color .15s ease, background .15s ease, transform .15s ease;
}
.nvsg-zone-label { font-weight: 800; font-size: .92rem; line-height: 1.15; color: #fff }
.nvsg-zone-hint { font-size: .72rem; color: #94a3b8; margin-top: .1rem; line-height: 1.25 }
.nvsg-zone-a { border-color: rgba(52,211,153,.45) }
.nvsg-zone-b { border-color: rgba(248,113,113,.45) }
.nvsg-zone-a .nvsg-zone-label { color: #34d399 }
.nvsg-zone-b .nvsg-zone-label { color: #f87171 }
/* armed = a chip is picked and this bucket is a legal target */
.nvsg-zone.is-armed { border-style: solid; background: rgba(34,211,238,.08); transform: translateY(-2px) }
.nvsg-zone.is-over  { border-color: #22d3ee; background: rgba(34,211,238,.16) }
.nvsg-zone.is-hit   { animation: nvsgHit .38s ease }
@keyframes nvsgHit { 0%{transform:scale(1)} 40%{transform:scale(1.035)} 100%{transform:scale(1)} }

.nvsg-drop { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .5rem }
.nvsg-tray { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: .8rem; min-height: 44px }

.nvsg-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .5rem .7rem; min-height: 44px;
  border-radius: .8rem; cursor: grab; font-size: .85rem; font-weight: 600; color: #e8ecf8;
  background: linear-gradient(180deg, rgba(255,255,255,.085), rgba(255,255,255,.03));
  border: 1px solid rgba(255,255,255,.16);
  transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease, opacity .2s ease;
}
.nvsg-chip:hover { border-color: rgba(34,211,238,.55); transform: translateY(-1px) }
.nvsg-chip.is-picked {
  border-color: #22d3ee; cursor: grabbing;
  box-shadow: 0 0 0 2px rgba(34,211,238,.45), 0 8px 22px -10px rgba(34,211,238,.8);
  transform: translateY(-2px) scale(1.03);
}
.nvsg-chip.is-wrong { animation: nvsgShake .4s ease; border-color: #f87171 }
@keyframes nvsgShake { 0%,100%{transform:translateX(0)} 20%{transform:translateX(-6px)} 40%{transform:translateX(6px)} 60%{transform:translateX(-4px)} 80%{transform:translateX(4px)} }
.nvsg-chip.is-done { cursor: default; font-size: .76rem; min-height: 32px; padding: .3rem .5rem; opacity: .92 }
.nvsg-chip.is-done:hover { transform: none; border-color: rgba(255,255,255,.16) }
.nvsg-chip-icon { font-size: 1.05em; line-height: 1 }

.nvsg-feedback { margin-top: .8rem; min-height: 1px }
.nvsg-why {
  border-radius: .9rem; padding: .7rem .8rem;
  background: rgba(34,211,238,.08); border: 1px solid rgba(34,211,238,.3);
  animation: nvsgIn .26s ease-out;
}
.nvsg-why.is-both { background: rgba(251,191,36,.10); border-color: rgba(251,191,36,.38) }
@keyframes nvsgIn { from { opacity: 0; transform: translateY(6px) } to { opacity: 1; transform: none } }
.nvsg-why-top { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .25rem }
.nvsg-why-icon { font-size: 1.1rem; line-height: 1 }
.nvsg-why-name { font-weight: 800; color: #fff; font-size: .9rem }
.nvsg-why-tag { font-size: .7rem; font-weight: 700; color: #fbbf24; border: 1px solid rgba(251,191,36,.5); border-radius: 999px; padding: .05rem .45rem }
.nvsg-why-text { margin: 0; font-size: .84rem; line-height: 1.5; color: #cbd5e1 }

.nvsg-done { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin-top: .6rem }
.nvsg-done-t { font-weight: 800; color: #34d399; font-size: 1rem }
.nvsg-done-s { font-size: .8rem; color: #94a3b8 }

.nvsg-foot { display: flex; align-items: center; justify-content: space-between; gap: .6rem; margin-top: .8rem }
.nvsg-dots { display: flex; gap: .25rem; flex-wrap: wrap }
.nvsg-dot { width: 7px; height: 7px; border-radius: 999px; background: rgba(255,255,255,.18); transition: background .2s ease }
.nvsg-dot.on { background: #22d3ee }
.nvsg-again {
  min-height: 44px; padding: 0 .9rem; border-radius: .7rem; font-size: .8rem; font-weight: 600;
  color: #94a3b8; background: transparent; border: 1px solid rgba(255,255,255,.14); cursor: pointer;
}
.nvsg-again:hover { color: #fff; border-color: rgba(255,255,255,.3) }

@media (max-width: 360px) { .nvsg-chip { font-size: .8rem; padding: .45rem .55rem } }
@media (prefers-reduced-motion: reduce) {
  .nvsg-chip, .nvsg-zone { transition: none }
  .nvsg-why, .nvsg-chip.is-wrong, .nvsg-zone.is-hit { animation: none }
}

/* A term used before it is explained gets a forward pointer to the section that
   explains it, so the reader is told "this is coming" instead of being lost.
   (Reviewer, 18 Sep: "Wenn das Wort Schufa erstmals fällt, sollt gleich klar
   gemacht werden, dass hierzu noch eine Erklärung folgt, sonst verlierst du den
   Leser.") */
.nv-fwd {
  display: inline-flex; align-items: center; gap: .2rem;
  margin-left: .4rem; padding: .05rem .45rem;
  font-size: .72em; font-weight: 700; white-space: nowrap;
  color: var(--nv-cyan, #22d3ee); text-decoration: none;
  border: 1px solid color-mix(in srgb, var(--nv-cyan, #22d3ee) 45%, transparent);
  border-radius: 999px; vertical-align: middle;
}
.nv-fwd::after { content: "↓" }
.nv-fwd:hover { color: #fff; background: color-mix(in srgb, var(--nv-cyan, #22d3ee) 22%, transparent) }

/* ===== the real chart (js/chartdemo.js) ==================================
 * The "how to read a stock chart" section described an x-axis and a y-axis and
 * then showed nothing. This is the thing it describes. */
.nvch { margin: 1rem 0 }
.nvch-svg { width: 100%; height: auto; display: block; touch-action: none; cursor: crosshair; border-radius: .8rem;
  background: linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,.012)); border: 1px solid rgba(255,255,255,.10) }
.nvch-grid { stroke: rgba(255,255,255,.09); stroke-width: 1 }
.nvch-ylab, .nvch-xlab { fill: #64748b; font-size: 11px; font-family: 'Inter', system-ui, sans-serif }
.nvch-area { fill: rgba(34,211,238,.13) }
.nvch-line { fill: none; stroke: #22d3ee; stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 6px rgba(34,211,238,.45)) }
.nvch-mark { fill: #f472b6; stroke: #0b1020; stroke-width: 2 }
.nvch-cross { stroke: rgba(255,255,255,.35); stroke-width: 1; stroke-dasharray: 3 3 }
.nvch-dot { fill: #fff; stroke: #22d3ee; stroke-width: 3 }

.nvch-read { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; margin-top: .6rem; min-height: 1.6rem }
.nvch-year { font-family: 'Bricolage Grotesque','Inter',sans-serif; font-weight: 800; font-size: 1.05rem; color: #fff }
.nvch-val  { font-weight: 800; color: #22d3ee; font-variant-numeric: tabular-nums }
.nvch-chg  { font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums }
.nvch-chg.up { color: #34d399 } .nvch-chg.down { color: #f87171 }
.nvch-tot  { font-size: .78rem; color: #94a3b8; font-variant-numeric: tabular-nums }
.nvch-note-in { flex-basis: 100%; font-size: .8rem; color: #f472b6; font-weight: 600 }
.nvch-axes { display: flex; justify-content: space-between; gap: .5rem; font-size: .72rem; color: #64748b; margin-top: .25rem }
.nvch-lesson { font-size: .88rem; line-height: 1.5; color: #cbd5e1; margin: .7rem 0 0 }
.nvch-note { font-size: .72rem; line-height: 1.4; color: #64748b; margin: .45rem 0 0 }
