body.dashboard-body {
    font-family: 'Roboto', sans-serif;
    margin: 0;
    padding: 20px;
    /* Darker, cooler vertical gradient — gives the page atmosphere
       so white cards visibly lift off it instead of blending in.
       Earlier #f4f6fb → #eef0f6 was too close to the card colour. */
    background: linear-gradient(180deg, #e8edf5 0%, #dfe5ef 100%);
    color: #333;
    min-height: 100vh;
}

/* ── Phone gate — Tutor Larry is tablet/laptop-only. ─────────────────
   Visibility is decided by an inline script in index.html that flips
   the [hidden] attr based on screen.width/height (phones only). */
.dashboard-phone-gate {
    position: fixed;
    inset: 0;
    background: linear-gradient(180deg, #e8edf5 0%, #dfe5ef 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 24px;
    font-family: 'Roboto', sans-serif;
}
.dashboard-phone-gate[hidden] { display: none; }
.dashboard-phone-gate-card {
    text-align: center;
    max-width: 320px;
    color: #333;
}
.dashboard-phone-gate-card h1 {
    font-size: 22px;
    margin: 0 0 10px;
    color: #2c3e50;
}
.dashboard-phone-gate-card p {
    color: #576574;
    font-size: 15px;
    line-height: 1.5;
    margin: 0;
}
.dashboard-container {
    max-width: 1280px;
    margin: 0 auto;
    padding: 28px 32px;
    position: relative;
}

/* Per-category palette — sets a CSS variable on every element that
   carries the category class. --cat-halo is a solid pastel fill
   behind the emoji (opaque, picks tone from the category); --cat-solid
   is the hue at full saturation, used for the section-heading
   underline accent and the chip progress fill.

   IMPORTANT: fallback values come FIRST so the category-specific
   classes (same selector specificity) win via source order. */
.dashboard-card, .cat-chip, .dashboard-category {
    --cat-halo: #eef0f6;
    --cat-solid: #64748b;
}
/* Anatomy is the perceptual reference — pink-100 reads strongly. The
   other categories use 200-level pastels so they hit the same visual
   weight (blues / greens / violets are weaker per-channel than pinks
   at equal lightness, so they need to step up to keep parity).
   Geography moved out of the green family entirely (was teal/mint —
   too close to plant-green at a glance) into cyan, putting all five
   live categories in clearly distinct hues. */
.cat-human-anatomy   { --cat-halo: #fbcfe8; --cat-solid: #ec4899; } /* pink-200 */
.cat-cell-biology    { --cat-halo: #bfdbfe; --cat-solid: #3b82f6; } /* blue-200 */
.cat-plant-biology   { --cat-halo: #bbf7d0; --cat-solid: #22c55e; } /* green-200 */
.cat-geography       { --cat-halo: #a5f3fc; --cat-solid: #06b6d4; } /* cyan-200 */
.cat-physics         { --cat-halo: #ddd6fe; --cat-solid: #8b5cf6; } /* violet-200 */
.cat-chemistry       { --cat-halo: #fed7aa; --cat-solid: #f97316; } /* orange-200 */

/* ── Production-mode hide ────────────────────────────────────────
   The env-detect script in <head> adds .app-prod to <html> when the
   host isn't a dev host. Dev affordances (reset button, builder /
   smoke-test links) hide in that mode so the live beta build doesn't
   expose tools the student shouldn't use. Override locally with
   ?dev=1 or localStorage tl_dev_mode='1'. */
html.app-prod #dev-reset-btn,
html.app-prod .dev-only {
    display: none !important;
}

/* Welcome-gate flicker prevention. The inline script in <head> sets
   .tl-welcome-pending on <html> when the welcome gate is going to show.
   Hide the dashboard chrome so the subjects grid doesn't paint
   behind the overlay before script.js mounts the gate. Cleared by
   script.js (initWelcomeGate / on dismiss). */
html.tl-welcome-pending body.dashboard-body > .container.dashboard-container {
    visibility: hidden;
}

/* ── Welcome gate ────────────────────────────────────────────────
   First-visit-in-production landing screen. Full-screen overlay over
   a soft cream background — same visual register as the tutor's
   welcome gate inside a subject, so the two feel like one product. */
.tl-welcome-gate {
    position: fixed;
    inset: 0;
    background: linear-gradient(180deg, #e8edf5 0%, #dfe5ef 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 24px;
    font-family: 'Roboto', sans-serif;
}
.tl-welcome-gate[hidden] { display: none; }
.tl-welcome-card {
    background: #fff;
    border: 1px solid #e6e4dd;
    border-radius: 16px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
    padding: 36px 44px 32px;
    max-width: 560px;
    width: 100%;
    text-align: center;
}
.tl-welcome-eyebrow {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: #b8862e;
    margin-bottom: 10px;
}
.tl-welcome-title {
    font-size: 36px;
    font-weight: 900;
    color: #2c3e50;
    margin: 0 0 4px;
    letter-spacing: -0.5px;
}
.tl-welcome-tagline {
    font-size: 18px;
    color: #34495e;
    margin: 0 0 22px;
    font-weight: 400;
}
.tl-welcome-body {
    font-size: 15px;
    color: #4a4a4a;
    line-height: 1.55;
    margin: 0 0 14px;
}
.tl-welcome-subjects {
    font-size: 13.5px;
    color: #576574;
    margin: 0 0 24px;
    font-weight: 500;
    letter-spacing: 0.01em;
}
.tl-welcome-form {
    display: flex;
    gap: 8px;
    margin: 0 auto 4px;
    max-width: 380px;
}
.tl-welcome-input {
    flex: 1 1 auto;
    padding: 11px 14px;
    border: 1px solid #d9d4c2;
    border-radius: 10px;
    font: inherit;
    font-size: 15px;
    background: #fff;
    color: #1f2937;
}
.tl-welcome-input:focus {
    outline: none;
    border-color: #2a6df4;
    box-shadow: 0 0 0 3px rgba(42, 109, 244, 0.18);
}
.tl-welcome-btn {
    background: #2a6df4;
    color: #fff;
    border: 1px solid #1c54c4;
    border-radius: 10px;
    padding: 11px 28px;
    font: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: background 100ms ease, transform 80ms ease;
}
.tl-welcome-btn:hover  { background: #1c54c4; }
.tl-welcome-btn:active { transform: translateY(1px); }
.tl-welcome-btn[disabled] {
    opacity: 0.55;
    cursor: progress;
}
.tl-welcome-error {
    color: #b33;
    font-size: 13.5px;
    margin: 10px 0 0;
    font-weight: 500;
}
.tl-welcome-error[hidden] { display: none; }
.tl-welcome-foot {
    margin: 20px 0 0;
    font-size: 13.5px;
    color: #888;
}
/* WhatsApp CTA — links straight into a chat with Larry. Uses the
   official WhatsApp green so it reads instantly as a WhatsApp action.
   The icon is an inline SVG glyph so we don't pull in another asset. */
.tl-welcome-wa {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: #1da851;
    font-weight: 600;
    text-decoration: none;
    margin-left: 4px;
    transition: color 100ms ease;
}
.tl-welcome-wa:hover { color: #178f44; text-decoration: underline; }
.tl-welcome-wa-icon {
    width: 16px;
    height: 16px;
    fill: currentColor;
    flex-shrink: 0;
}

/* With the reset button hidden in production, the container's top
   padding (sized to clear the absolute-positioned button in dev mode)
   becomes wasted vertical space. Tighten it so the heading sits
   higher on the page. Dev mode keeps the original spacing so the
   reset button has its room. */
html.app-prod body.dashboard-body {
    padding-top: 8px;
}
html.app-prod .dashboard-container {
    padding-top: 12px;
}

/* Dev/testing affordance — wipes local progress so the dashboard
   re-shows the first-visit flow on every topic. Utility chrome,
   not a button — kept discoverable but visually faded. */
.dev-reset-btn {
    position: absolute;
    top: 14px;
    right: 20px;
    background: transparent;
    border: 0;
    color: #576574;
    padding: 4px 6px;
    font-family: inherit;
    font-size: 0.8em;
    font-weight: 500;
    cursor: pointer;
    opacity: 0.3;
    transition: opacity 0.15s, color 0.15s;
}
.dev-reset-btn:hover {
    opacity: 1;
    color: #b91c1c;
}
.dashboard-container h1 {
    font-size: 2.25em;
    font-weight: 900;
    color: #2c3e50;
    text-align: center;
    margin-bottom: 4px;
    letter-spacing: -0.5px;
}
/* Tagline sits between the brand name and the subject line. Lighter
   weight than h1 but more present than the muted subject line — gives
   editorial hierarchy: brand → promise → scope. */
.dashboard-container .tagline {
    font-size: 1.18em;
    color: #34495e;
    text-align: center;
    margin: 0 0 6px;
    line-height: 1.3;
    font-weight: 400;
    letter-spacing: 0.01em;
}
.dashboard-container .subtitle {
    font-size: 1.02em;
    color: #576574;
    text-align: center;
    margin: 0 0 30px;
    line-height: 1.35;
    font-weight: 500;
}
/* Topic count appended inline to the subtitle as muted grey text
   with a middot separator. No pill — just a count chip's worth of
   weight to register the size of the library without competing
   with the subtitle copy. */
.subjects-count {
    color: #95a5a6;
    font-weight: 500;
}
.subjects-count:not(:empty)::before {
    content: ' · ';
    margin: 0 4px;
    color: #cbd5e0;
}
.subjects-count:empty { display: none; }

/* Category jump-nav — sticky chip bar at top */
.cat-nav {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(245, 247, 250, 0.92);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    margin: 0 -32px 26px;
    padding: 10px 32px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    border-bottom: 1px solid rgba(52, 152, 219, 0.15);
}
.cat-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border-radius: 999px;
    background: #fff;
    border: 1px solid #d5dbe1;
    color: #2c3e50;
    text-decoration: none;
    font-size: 0.92em;
    font-weight: 700;
    transition: all 0.15s;
    box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.cat-chip:hover {
    border-color: var(--cat-solid, #3498db);
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(0,0,0,0.06);
}
.cat-chip-label { line-height: 1.1; }
/* Inline count badge — tinted with the category's halo pastel for
   the background and --cat-solid for the text. Same visual language
   as the per-card halos. */
.cat-chip-count {
    font-size: 0.85em;
    background: var(--cat-halo, #f1f3f5);
    color: var(--cat-solid, #7f8c8d);
    padding: 2px 8px;
    border-radius: 999px;
    font-weight: 700;
}

.dashboard-category {
    margin-bottom: 36px;
    margin-top: 28px;
    scroll-margin-top: 80px;
}
.dashboard-category:first-of-type { margin-top: 12px; }
/* Section heading — bigger, more breathing room, with a 3px
   category-coloured accent stripe under the title. */
.dashboard-category h2 {
    font-size: 1.8em;
    color: #1c2733;
    margin: 0 0 18px 0;
    border-bottom: 3px solid var(--cat-solid, #3498db);
    display: inline-block;
    padding-bottom: 6px;
    font-weight: 900;
    letter-spacing: -0.3px;
}
.dashboard-grid {
    display: grid;
    /* auto-fill (not auto-fit) so empty trailing tracks aren't
       collapsed; minmax with a fixed max so cards don't balloon when
       a category has 1 or 2 items. justify-content:start packs the
       cards to the left and lets leftover space sit on the right.
       align-items:start prevents row-stretching — each card sizes to
       its own content. A card with two medal badges stays slightly
       taller than a sibling with one, which reads as "more progress"
       and is good signal. */
    grid-template-columns: repeat(auto-fill, minmax(200px, 240px));
    justify-content: start;
    align-items: start;
    gap: 14px;
}
.dashboard-card {
    /* Off-white instead of pure #fff. Imperceptible per card, removes
       the fluorescent-grid feel cumulatively. */
    background: #fdfdff;
    border-radius: 12px;
    /* Two-layer shadow — thin contact line + softer ambient glow.
       Second-layer alpha bumped 0.06 → 0.08 to compensate for the
       darker page background; cards still need to visibly lift. */
    box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 8px 24px rgba(30,40,80,0.08);
    padding: 16px 14px;
    text-align: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    position: relative;
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}
.dashboard-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 2px 4px rgba(0,0,0,0.06), 0 16px 36px rgba(30,40,80,0.14);
}
.card-header {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 12px;
}
.medal {
    font-size: 1.4em;
    text-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.medal.placeholder {
    filter: grayscale(100%) opacity(0.2);
}
.medal.earned {
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.15));
    transform: scale(1.05);
}
/* Tinted halo behind the emoji — soft 64px circle in the card's
   category colour. Anchors the eye, makes categories scannable at
   speed, replaces the old emoji drop-shadow (no longer needed once
   the halo provides visual depth). isolation:isolate creates a new
   stacking context so the pseudo's z-index:-1 stays inside the icon
   (behind the emoji text) but still paints in front of the card's
   white background. */
.icon {
    position: relative;
    isolation: isolate;
    font-size: 2.2em;
    margin: 0 auto;
    line-height: 1;
    width: 56px;
    height: 56px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.icon::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--cat-halo);
    border-radius: 50%;
    z-index: -1;
}
.dashboard-card h3 {
    font-size: 1.15em;
    color: #2c3e50;
    margin: 0 0 4px 0;
    font-weight: 900;
    line-height: 1.2;
}
.dashboard-card .details {
    color: #95a5a6;
    font-size: 0.82em;
    margin: 0;
    line-height: 1.3;
}
/* Per-card mode progress row — sits below the "N parts" line.
   Two indicators: 🔗 Connect (blue), ⏱ Test (yellow). Three states:
   not-started (faint outline only), in-progress (mode-colour at low
   opacity), done (solid mode colour). Each indicator can carry a
   medal badge overlapping its bottom-right corner. */
.card-progress {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 18px;
    /* Cards no longer stretch (align-items:start on the grid), so the
       indicator row just needs a normal gap below "X parts" — no
       margin-top:auto trickery. :empty below collapses cards with no
       indicators. */
    margin-top: 8px;
}
.card-progress:empty { display: none; }
.card-progress-slot {
    position: relative;
    display: inline-flex;
    line-height: 1;
}
/* Medal badge — sits over the bottom-right of its indicator. White
   ring + soft shadow so it always reads as a separate object,
   critical when Gold lands on the yellow Test indicator. */
.card-medal-badge {
    position: absolute;
    bottom: -8px;
    right: -10px;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    line-height: 1;
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 0 0 2px #fff, 0 2px 5px rgba(0,0,0,0.28);
    pointer-events: none;
    user-select: none;
}
.card-progress-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    font-size: 0.85em;
    line-height: 1;
    border: 1.5px solid;
    transition: background 0.18s, opacity 0.18s, border-color 0.18s;
    user-select: none;
    cursor: help;
}
/* Connect-blue palette — matches the chooser's connect tile and the
   in-topic dot fill (#2196f3). */
.card-progress-icon.connect.not-started { background: transparent;     border-color: #cbd5e1; opacity: 0.45; }
.card-progress-icon.connect.in-progress { background: #bbdefb;         border-color: #2196f3; }
.card-progress-icon.connect.done        { background: #2196f3;         border-color: #1976d2; }
/* Test-yellow palette — matches the chooser's test tile (#fcd34d
   border, amber-300 fill). */
.card-progress-icon.test.not-started    { background: transparent;     border-color: #cbd5e1; opacity: 0.45; }
.card-progress-icon.test.in-progress    { background: #fef3c7;         border-color: #f59e0b; }
.card-progress-icon.test.done           { background: #fcd34d;         border-color: #b45309; }
.status-container {
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 0;
}
.status-container:empty { display: none; }
.badge-new {
    display: inline-block;
    background: #e74c3c;
    color: white;
    padding: 6px 14px;
    border-radius: 20px;
    font-size: 0.9em;
    font-weight: 900;
    letter-spacing: 1.5px;
    margin: 0 auto;
    box-shadow: 0 4px 10px rgba(231, 76, 60, 0.3);
}
.progress-bar {
    background: #ecf0f1;
    border-radius: 10px;
    height: 12px;
    width: 100%;
    overflow: hidden;
    margin-bottom: 10px;
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.05);
}
.progress-bar .fill {
    background: linear-gradient(90deg, #3498db, #2980b9);
    height: 100%;
    transition: width 0.8s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.progress-bar .fill.green {
    background: linear-gradient(90deg, #2ecc71, #27ae60);
}
.progress-text {
    font-size: 0.95em;
    color: #7f8c8d;
    font-weight: 700;
}
.card-btn {
    display: block;
    width: 100%;
    padding: 11px 0;
    border-radius: 10px;
    text-decoration: none;
    font-weight: 900;
    font-size: 1em;
    transition: all 0.2s;
    box-sizing: border-box;
    letter-spacing: 0.5px;
}
.btn-start {
    background: #3498db;
    color: white;
    box-shadow: 0 6px 15px rgba(52, 152, 219, 0.4);
}
.btn-start:hover { background: #2980b9; transform: translateY(-2px); }
.btn-resume {
    background: #f39c12;
    color: white;
    box-shadow: 0 6px 15px rgba(243, 156, 18, 0.4);
}
.btn-resume:hover { background: #d35400; transform: translateY(-2px); }
.btn-replay {
    background: #ecf0f1;
    color: #2c3e50;
    border: 2px solid #bdc3c7;
}
.btn-replay:hover { background: #bdc3c7; transform: translateY(-2px); }

/* v2 mode-stack — compact mode rows */
.mode-stack {
    display: flex; flex-direction: column; gap: 4px;
    margin-top: 4px;
}
.mode-row {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px;
    border-radius: 8px;
    text-decoration: none;
    transition: background 0.12s, transform 0.12s;
    font-weight: 700;
    font-size: 0.96em;
}
.mode-row.btn-start { background: #3498db; color: white; box-shadow: 0 2px 5px rgba(52,152,219,0.25); }
.mode-row.btn-start:hover { background: #2980b9; transform: translateY(-1px); }
.mode-row.btn-replay { background: #ecf0f1; color: #2c3e50; border: 1px solid #cfd5da; }
.mode-row.btn-replay:hover { background: #dde2e6; transform: translateY(-1px); }
.mode-row-medal { font-size: 1.05em; line-height: 1; }
.mode-row-label { flex: 1; text-align: left; letter-spacing: 0.02em; }
.mode-row-cta { font-size: 0.85em; opacity: 0.85; }

/* The mode row is now a wrapper holding two compact action links —
   🔁 Practice and ⏱ Assess — instead of a single CTA. Each action
   is its own clickable target. */
.mode-row-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px; height: 32px;
    border-radius: 6px;
    text-decoration: none;
    background: rgba(255,255,255,0.6);
    font-size: 1.1em;
    line-height: 1;
    transition: background 0.12s, transform 0.12s;
}
.mode-row-action:hover { background: #fff; transform: scale(1.08); }
.mode-row-practice { color: #047857; }
.mode-row-assess { color: #b45309; }

/* The mode row is keyboard-accessible (role=button, tabindex=0).
   Make it look interactive; cursor: pointer signals it's clickable. */
.mode-row { cursor: pointer; }
.mode-row:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 2px; }

/* ── Practice / Assessment chooser modal ────────────────────────── */
.pa-chooser-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.6);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.pa-chooser-modal {
    position: relative;
    background: #fff;
    border-radius: 14px;
    max-width: 720px;
    width: 100%;
    padding: 28px 32px 24px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
    font-family: inherit;
}
.pa-chooser-close {
    position: absolute;
    top: 10px; right: 12px;
    background: transparent;
    border: none;
    font-size: 1.5em;
    line-height: 1;
    color: #9ca3af;
    cursor: pointer;
    padding: 4px 10px;
    border-radius: 6px;
}
.pa-chooser-close:hover { background: #f3f4f6; color: #4b5563; }
.pa-chooser-modal h2 {
    margin: 0 0 12px;
    font-size: 1.5em;
    color: #1f2937;
}
.pa-chooser-hint {
    margin: 0 0 20px;
    padding: 12px 14px;
    background: #fffbeb;
    border-left: 3px solid #f59e0b;
    border-radius: 4px;
    color: #4b5563;
    font-size: 0.95em;
    line-height: 1.5;
}
.pa-chooser-hint strong { color: #b45309; }
.pa-chooser-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}
.pa-chooser-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 22px 18px;
    border-radius: 12px;
    border: 2px solid transparent;
    text-decoration: none;
    color: inherit;
    transition: transform 0.12s, box-shadow 0.12s, border-color 0.12s;
}
.pa-chooser-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0,0,0,0.1);
}
.pa-chooser-assess {
    background: #eff6ff;
    border-color: #bfdbfe;
}
.pa-chooser-assess:hover { border-color: #3b82f6; }
.pa-chooser-practice {
    background: #ecfdf5;
    border-color: #bbf7d0;
}
.pa-chooser-practice:hover { border-color: #047857; }
.pa-chooser-badge {
    position: absolute;
    top: -10px;
    right: 12px;
    background: #1d4ed8;
    color: #fff;
    font-size: 0.7em;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 999px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.pa-chooser-icon {
    font-size: 2.6em;
    line-height: 1;
    margin-bottom: 8px;
}
.pa-chooser-name {
    font-size: 1.2em;
    font-weight: 800;
    color: #1f2937;
    margin-bottom: 6px;
}
.pa-chooser-card p {
    margin: 0;
    color: #4b5563;
    font-size: 0.9em;
    line-height: 1.5;
}
@media (max-width: 600px) {
    .pa-chooser-cards { grid-template-columns: 1fr; }
}

/* ── Favourites ────────────────────────────────────────────────── */

/* Star button sits in the top-right of every v2 dashboard card.
   Empty (☆) when not favourited, filled (★) when on. Active fill
   uses a slightly desaturated amber (#e8b923) — the old #f59e0b
   was harsh against the warm-grey background; this reads as gold
   without shouting. */
.fav-star {
    position: absolute;
    top: 12px;
    right: 12px;
    background: transparent;
    border: none;
    font-size: 1.5em;
    line-height: 1;
    color: #d6dde6;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 6px;
    transition: color 0.12s, background 0.12s, transform 0.12s;
    z-index: 2;
}
.fav-star:hover { color: #e8b923; background: rgba(232, 185, 35, 0.10); transform: scale(1.1); }
.fav-star.is-fav { color: #e8b923; }
.fav-star.is-fav:hover { color: #c79a18; }

/* ── Tutor-ready badge ─────────────────────────────────────────── */
/* The 📚 badge sits in the top-LEFT of cards whose subject has
   tutorReady: true on subjects.json. Signals "AI tutor lesson
   available" — matches the Lesson chip on the tutor demo's report
   card. Click on the card routes to the tutor instead of drills. */
.card-tutor-badge {
    position: absolute;
    top: 12px;
    left: 12px;
    font-size: 1.2em;
    line-height: 1;
    padding: 4px 8px;
    border-radius: 8px;
    background: rgba(124, 58, 237, 0.10);
    border: 1px solid rgba(124, 58, 237, 0.25);
    color: #6d28d9;
    z-index: 2;
    pointer-events: none;
}
/* Subtle accent on the whole card so tutor-ready tiles read as a
   distinct entry path at a glance, without shouting. */
.dashboard-card.is-tutor-ready {
    box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.18) inset, 0 1px 3px rgba(0, 0, 0, 0.04);
}

/* Favourites section sits at the top of the dashboard, above the
   category sections. Star theme — amber for both heading text and
   the 3px accent stripe under it. */
.dashboard-favourites { --cat-solid: #e8b923; }
.dashboard-favourites h2 { color: #b45309; }
.favourites-empty {
    background: #fff;
    border: 1px dashed #f59e0b;
    border-radius: 12px;
    padding: 18px 22px;
    color: #6b7280;
    font-size: 1em;
    line-height: 1.5;
    text-align: center;
}
.favourites-empty-star {
    font-size: 1.2em;
    color: #f59e0b;
    font-weight: 700;
}
