/* ============================================
   Mind Match Education — shared styles
   Used by index.html (gated app shell) + login.html.
   ============================================ */

:root {
    /* Fixed-height topbar — pinned so the sidebar can compute
       `top: var(--topbar-height)` and start exactly below it.
       Lets the menu button in the topbar stay clickable when the
       sidebar (which slides in from the left at this same y-offset)
       is open. */
    --topbar-height: 64px;

    /* Mind Match — LIGHT theme palette. Mirrors apps/mind-match/main
       light-mode block: white surfaces, deep slate text, Mind Match
       accent blues + purples + orange. */
    --brand-blue:        #2563EB;
    --brand-blue-deep:   #3B82F6;
    --brand-purple:      #8B5CF6;
    --brand-orange:      #F97316;
    --brand-gradient:    linear-gradient(90deg, #3B82F6, #8B5CF6, #F97316);

    --bg:                #F5F7FA;
    --bg-card:           #FFFFFF;
    --bg-input:          #FFFFFF;
    --bg-secondary:      #E9EEF5;

    --text:              #0F172A;
    --text-muted:        #475569;
    --text-dim:          #94A3B8;

    --border:            rgba(15, 23, 42, 0.10);
    --border-strong:     rgba(15, 23, 42, 0.16);

    --danger:            #DC2626;
    --danger-bg:         rgba(220, 38, 38, 0.10);
    --success:           #16A34A;
    --success-bg:        rgba(22, 163, 74, 0.10);
    --warning:           #D97706;
    --info:              #2563EB;

    --shadow-sm: 0 2px 8px rgba(15, 23, 42, 0.06);
    --shadow-md: 0 4px 16px rgba(15, 23, 42, 0.10);
    --shadow-lg: 0 8px 32px rgba(15, 23, 42, 0.15);

    /* ─── Theme Phase A — design tokens (2026-05-27) ────────────
       Foundation layer for the "Dark Academic Arcade" redesign.
       These tokens are ADDITIVE — every existing CSS rule and
       inline style continues to work unchanged. New components
       built after Phase A pick these up automatically; the plugin
       theming pass in Phase D will migrate inline colors → tokens.

       Categories below: semantic surfaces, accent palette, status,
       typography, motion, radius, elevation, focus. */

    /* Semantic surfaces (3 layers of depth for layered glassmorphism) */
    --surface-0:         #F5F7FA;   /* page background */
    --surface-1:         #FFFFFF;   /* primary card */
    --surface-2:         #F8FAFC;   /* nested panel */
    --surface-overlay:   rgba(15, 23, 42, 0.45);   /* modal/sheet backdrop */
    --surface-glass:     rgba(255, 255, 255, 0.80); /* glassmorphism panels */
    --surface-glass-border: rgba(15, 23, 42, 0.08);

    /* Accent palette */
    --accent-blue:       #2563EB;   /* primary action — aligns with brand-blue */
    --accent-cyan:       #2FB2EA;   /* esports accent — brighter than brand-blue */
    --accent-purple:     #8B5CF6;   /* secondary accent — aligns with brand-purple */
    --accent-gold:       #FBBF24;   /* rank / achievement / streak — NEW */
    --accent-orange:     #F97316;   /* warm CTA — aligns with brand-orange */

    /* Hover / pressed variants for accents */
    --accent-blue-hover:   #1D4ED8;
    --accent-purple-hover: #7C3AED;
    --accent-gold-hover:   #F59E0B;

    /* Typography stack — Sora for headings (modern/futuristic),
       Inter for body/UI (clean + dense + legible). System fallbacks
       keep the page usable if Google Fonts fails to load. */
    --font-display: 'Sora', 'Space Grotesk', 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-body:    'Inter', 'Manrope', 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-mono:    'JetBrains Mono', 'SF Mono', 'Roboto Mono', monospace;

    /* Type scale (rem-based; root html size = 16px) */
    --text-2xs: 0.65rem;   /* tiny category labels (UPPERCASE) */
    --text-xs:  0.75rem;   /* small meta */
    --text-sm:  0.875rem;  /* body small */
    --text-base: 1rem;     /* body */
    --text-lg:  1.125rem;  /* lead paragraph */
    --text-xl:  1.25rem;   /* card title */
    --text-2xl: 1.5rem;    /* section heading */
    --text-3xl: 1.875rem;  /* page heading */
    --text-4xl: 2.25rem;   /* hero */
    --tracking-wide: 0.05em;   /* category labels */
    --tracking-tight: -0.02em; /* big display text */

    /* Motion — keep restrained, premium-feel timings */
    --motion-fast:    120ms;
    --motion-medium:  200ms;
    --motion-slow:    320ms;
    --motion-ease:    cubic-bezier(0.4, 0, 0.2, 1);    /* standard */
    --motion-ease-out: cubic-bezier(0.16, 1, 0.3, 1);  /* expo-out, for popovers */

    /* Border radii (tactile gaming-UI feel without going round-button) */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
    --radius-xl: 24px;
    --radius-pill: 9999px;

    /* Elevation / shadows (Phase A keeps the existing shadow-sm/md/lg
       for back-compat AND adds a "glow" set for the gaming feel) */
    --glow-blue:   0 0 24px rgba(47, 178, 234, 0.25);
    --glow-purple: 0 0 24px rgba(139, 92, 246, 0.25);
    --glow-gold:   0 0 24px rgba(251, 191, 36, 0.30);

    /* Focus ring (a11y) — visible against both light + dark */
    --focus-ring: 0 0 0 3px rgba(47, 178, 234, 0.40);
}

/* ─── Theme Phase A — DARK overlay ───────────────────────────────
   Applied via `<html data-theme="dark">` (or `<body data-theme>`).
   Bootstrap script in index.html sets this before paint to avoid
   light-to-dark flash. Maps onto the SAME token names so any
   component reading `var(--bg-card)` etc. flips automatically.
   Brand-blue / -purple / -orange tokens stay aligned with the
   light-theme brand identity; surface colors flip to slate-900/
   navy. */
[data-theme="dark"] {
    --bg:                #0B1020;
    --bg-card:           #131C31;
    --bg-input:          #131C31;
    --bg-secondary:      #0F1730;

    --text:              #F8FAFC;
    --text-muted:        #94A3B8;
    --text-dim:          #64748B;

    --border:            rgba(255, 255, 255, 0.08);
    --border-strong:     rgba(255, 255, 255, 0.14);

    --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.40);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.50);
    --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.55);

    /* Surfaces — 3 layers of navy depth */
    --surface-0:         #0B1020;
    --surface-1:         #131C31;
    --surface-2:         #18233D;
    --surface-overlay:   rgba(0, 0, 0, 0.65);
    --surface-glass:     rgba(19, 28, 49, 0.70);
    --surface-glass-border: rgba(255, 255, 255, 0.06);

    /* Accent hover variants — slightly brighter for dark context */
    --accent-blue-hover:   #3B82F6;
    --accent-purple-hover: #A78BFA;
    --accent-gold-hover:   #FCD34D;

    /* Glow shadows render visibly on dark */
    --glow-blue:   0 0 28px rgba(47, 178, 234, 0.35);
    --glow-purple: 0 0 28px rgba(139, 92, 246, 0.35);
    --glow-gold:   0 0 28px rgba(251, 191, 36, 0.40);

    --focus-ring: 0 0 0 3px rgba(47, 178, 234, 0.55);
}

* { box-sizing: border-box; }

/* iOS focus-zoom guard: Safari/WKWebView auto-zooms when a focused text
   input has font-size < 16px, and doesn't zoom back out. Force >=16px on
   every text-entry control so focusing an input never zooms the page. */
input, select, textarea { font-size: 16px; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    min-height: 100vh;
}

a { color: var(--brand-blue); text-decoration: none; font-weight: 600; }
a:hover { text-decoration: underline; }

.bg-glow {
    background: radial-gradient(circle at 20% 20%, rgba(37, 99, 235, 0.08), transparent 55%),
                radial-gradient(circle at 80% 80%, rgba(139, 92, 246, 0.08), transparent 55%),
                var(--bg);
}

/* ===== App shell (index.html) ===== */
.shell {
    /* Normal document scroll — the page body scrolls. The .topbar is
       pinned via position:sticky (below) rather than by locking the
       scroll model, so content always scrolls freely. */
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}
.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* iOS safe area: when the native Capacitor WebView overlays the
       status bar (StatusBar.overlaysWebView: true), the topbar sits
       under the notch / Dynamic Island / front camera. Grow it by the
       top inset and pad its content down so the glass surface fills the
       inset area. env() is 0 on web/Android, so this is a no-op there.
       box-sizing: border-box (global) keeps the content row at 64px. */
    height: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    padding: env(safe-area-inset-top, 0px) 18px 0;
    /* Phase B — token-aware glass surface so dark theme flips the
       topbar to a translucent navy instead of staying white. */
    border-bottom: 1px solid var(--surface-glass-border, var(--border));
    background: var(--surface-glass, rgba(255, 255, 255, 0.92));
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    flex-shrink: 0;
    z-index: 70; /* above sidebar so the menu toggle stays clickable */
    /* Subtle bottom-edge accent gradient — the layered/premium feel
       called for in the brief. Doesn't impose color on the topbar
       itself, just adds a 1px gradient highlight below. */
    /* Sticky so the header stays pinned to the top as the page body
       scrolls (works because no ancestor clips overflow). Keeps normal
       document scrolling intact. */
    position: sticky;
    top: 0;
}
.topbar::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: -1px; height: 1px;
    background: linear-gradient(90deg, transparent 0%, var(--accent-cyan, #2FB2EA) 30%, var(--accent-purple, #8B5CF6) 70%, transparent 100%);
    opacity: 0.18;
    pointer-events: none;
}
.brand {
    display: flex;
    align-items: center;
    gap: 14px;
    font-weight: 700;
    font-size: 16px;
    min-width: 0;
}
.brand .emoji { font-size: 22px; line-height: 1; }
.brand-logo {
    height: 48px;
    width: auto;
    display: block; /* now visible at every viewport (sidebar no longer carries the logo) */
}
/* New menu toggle — a 2x2 grid of squares when the sidebar is
   closed; a left-facing caret when the sidebar is open. Both
   SVG icons live inside the same button; CSS hides one or the
   other based on body.sidebar-is-open. */
.menu-btn {
    background: transparent;
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    width: 38px;
    height: 38px;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.menu-btn:hover { background: rgba(148, 163, 184, 0.10); border-color: var(--text-muted); }
.menu-btn:focus-visible { outline: 2px solid var(--brand-blue); outline-offset: 2px; }
.menu-btn-icon {
    width: 20px;
    height: 20px;
    display: block;
}
.menu-btn-icon-caret { display: none; }
body.sidebar-is-open .menu-btn-icon-grid  { display: none; }
body.sidebar-is-open .menu-btn-icon-caret { display: block; }
/* Legacy alias — sidebarToggleBtn used to be .hamburger-btn.
   Kept as a no-op selector in case any external CSS still refs it. */
.hamburger-btn { display: none; }

/* Theme toggle (Phase A) — sits next to Sign in/out in the topbar.
   Same look as .menu-btn so the topbar stays visually consistent.
   Icon swap: moon visible in LIGHT mode (click to go dark), sun
   visible in DARK mode (click to go light). */
.theme-toggle {
    background: transparent;
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    width: 38px;
    height: 38px;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background var(--motion-fast, 120ms) ease, border-color var(--motion-fast, 120ms) ease, transform var(--motion-fast, 120ms) ease;
}
.theme-toggle:hover { background: rgba(148, 163, 184, 0.10); border-color: var(--text-muted); }
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent-cyan, #2FB2EA); outline-offset: 2px; }
.theme-icon { width: 18px; height: 18px; display: block; }
/* Default (light theme): show moon. Dark theme: show sun. */
.theme-icon-sun  { display: none; }
[data-theme="dark"] .theme-icon-moon { display: none; }
[data-theme="dark"] .theme-icon-sun  { display: block; }
.actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* ===== Notification bell (notification center) ===== */
#mmEduNotifBtn { position: relative; overflow: visible; }
/* The bell glyph renders ~2/3 size (the SVG has no .theme-icon sizing). */
#mmEduNotifBtn svg { width: 16px; height: 16px; display: block; }
.mm-notif-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 9px;
    background: #DC2626;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
    box-sizing: border-box;
    box-shadow: 0 0 0 2px var(--bg, #fff);
    pointer-events: none;
}

/* Bell swing "ring" + enlarge pulse (Part B). transform-origin at the
   top so it swings like a real bell. Classes are toggled from app.js for
   the animation's duration only. */
@keyframes mmNotifRing {
    0%   { transform: rotate(0); }
    10%  { transform: rotate(16deg); }
    25%  { transform: rotate(-14deg); }
    40%  { transform: rotate(11deg); }
    55%  { transform: rotate(-8deg); }
    70%  { transform: rotate(5deg); }
    85%  { transform: rotate(-2deg); }
    100% { transform: rotate(0); }
}
@keyframes mmNotifEnlarge {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.28); }
    60%  { transform: scale(0.95); }
    100% { transform: scale(1); }
}
#mmEduNotifBtn.mm-notif-ring svg { transform-origin: 50% 4px; animation: mmNotifRing 0.9s ease-in-out; }
#mmEduNotifBtn.mm-notif-enlarge { animation: mmNotifEnlarge 0.6s ease-in-out; }
@media (prefers-reduced-motion: reduce) {
    #mmEduNotifBtn.mm-notif-ring svg,
    #mmEduNotifBtn.mm-notif-enlarge { animation: none; }
}

/* Dropdown panel — appended to <body>, positioned (fixed) under the bell
   by app.js. */
.mm-notif-panel {
    background: var(--card-bg, var(--bg, #fff));
    color: var(--text, #0B1020);
    border: 1px solid var(--border-strong, rgba(148,163,184,0.35));
    border-radius: 12px;
    box-shadow: 0 12px 34px rgba(0,0,0,0.22);
    z-index: 4000;
    max-height: 60vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    font-size: 13px;
}
.mm-notif-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border, rgba(148,163,184,0.2));
    flex-shrink: 0;
}
.mm-notif-head-title { font-weight: 700; font-size: 13px; }
.mm-notif-head-actions { display: flex; align-items: center; gap: 10px; }
.mm-notif-clear,
.mm-notif-mark {
    background: transparent;
    border: none;
    color: var(--accent-cyan, #2563EB);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 6px;
    white-space: nowrap;
}
.mm-notif-mark { color: var(--text-muted, #64748B); }
.mm-notif-clear:hover,
.mm-notif-mark:hover { text-decoration: underline; }
.mm-notif-list { overflow-y: auto; }
.mm-notif-empty {
    padding: 28px 16px;
    text-align: center;
    color: var(--text-muted, #64748B);
}
/* In-panel "enable push" / "blocked" banner. The list itself works
   regardless of browser push permission. */
.mm-notif-banner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--text-muted, #64748B);
    background: rgba(37,99,235,0.07);
    border-bottom: 1px solid var(--border, rgba(148,163,184,0.14));
}
.mm-notif-banner--blocked { background: rgba(148,163,184,0.10); }
.mm-notif-banner span { flex: 1; }
.mm-notif-enable {
    flex-shrink: 0;
    background: var(--brand-blue, #2563EB);
    color: #fff;
    border: 0;
    border-radius: 6px;
    padding: 5px 12px;
    font-family: inherit;
    font-weight: 700;
    font-size: 12px;
    cursor: pointer;
}
.mm-notif-enable:hover { filter: brightness(1.05); }
.mm-notif-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border, rgba(148,163,184,0.14));
    cursor: pointer;
}
.mm-notif-row:last-child { border-bottom: none; }
.mm-notif-row:hover { background: rgba(148,163,184,0.10); }
.mm-notif-row--unread { background: rgba(37,99,235,0.07); }
.mm-notif-row--unread:hover { background: rgba(37,99,235,0.13); }
.mm-notif-row-main { flex: 1; min-width: 0; }
.mm-notif-row-title { font-weight: 700; margin-bottom: 2px; word-break: break-word; }
.mm-notif-row-body { color: var(--text-muted, #64748B); margin-bottom: 3px; word-break: break-word; }
.mm-notif-row-time { color: var(--text-muted, #94A3B8); font-size: 11px; }
.mm-notif-row-x {
    flex-shrink: 0;
    background: transparent;
    border: none;
    color: var(--text-muted, #94A3B8);
    cursor: pointer;
    font-size: 13px;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 6px;
}
.mm-notif-row-x:hover { color: var(--text, #0B1020); background: rgba(148,163,184,0.18); }
.who {
    color: var(--text-muted);
    font-size: 13px;
}

/* ===== Body layout: sidebar + main panel ===== */
.shell-body {
    flex: 1;
    display: flex;
    min-height: 0;
    position: relative;
}
.sidebar {
    /* Slide-out drawer at every viewport. Starts below the
       topbar (top: var(--topbar-height)) so the menu toggle in the
       topbar stays accessible while the sidebar is open. Default
       state is `translateX(-100%)` (off-screen left); the
       .sidebar-open class on .shell-body slides it in. */
    position: fixed;
    top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    bottom: 0;
    left: 0;
    width: 260px;
    z-index: 60;
    flex-shrink: 0;
    /* Phase B — flips with theme. Light: white surface. Dark: deep
       navy panel. */
    background: var(--bg-card, #FFFFFF);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    padding: 16px 14px;
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform var(--motion-medium, 220ms) var(--motion-ease, ease);
    box-shadow: var(--shadow-md, 4px 0 24px rgba(15, 23, 42, 0.10));
}
.shell-body.sidebar-open .sidebar { transform: translateX(0); }
/* Sidebar's internal header is retired — the logo lives in the
   topbar across all viewports, and the close action moved to the
   menu toggle in the topbar (which transforms into a left-caret
   when the sidebar is open). Keeping the DOM node so older JS
   that queries it doesn't break; just hidden. */
.sidebar-header {
    display: none;
    position: relative;
    align-items: center;
    justify-content: center;
    padding: 18px 4px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.sidebar-logo {
    height: 56px;
    width: auto;
    max-width: 100%;
    display: block;
}
.sidebar-close-btn {
    display: none; /* desktop: hidden; mobile media query reveals it */
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    color: var(--text-muted);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    padding: 6px 11px;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    font-family: inherit;
}
.sidebar-close-btn:hover {
    background: rgba(148, 163, 184, 0.10);
    color: var(--text);
}
/* Pin button — the counterpart to the X. Shown in the sidebar header
   ONLY on desktop while the menu is being used the "old way" (undocked
   slide-out drawer, open). Clicking it re-docks the menu (pins it open)
   so it behaves like a fresh desktop load again. Hidden everywhere else
   (mobile, and docked mode where the X takes over). */
.sidebar-pin-btn {
    display: none;
    background: transparent;
    color: var(--text-muted);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    padding: 5px 10px;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    font-family: inherit;
}
.sidebar-pin-btn:hover {
    background: rgba(148, 163, 184, 0.10);
    color: var(--text);
}
.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
/* Section header inside the sidebar nav — small, uppercase,
   muted. Used to group "Learn" + "Play" rows; the standalone
   Schoolhouse button sits above the first header without one. */
.sidebar-section-label {
    margin-top: 14px;
    padding: 6px 13px 4px;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
/* First section label has less top spacing since it follows the
   single Schoolhouse button directly. */
.sidebar-nav > .sidebar-section-label:first-child,
.sidebar-section-label + .sidebar-section-label {
    margin-top: 6px;
}
/* "Soon" badge on the not-yet-wired Play modes. Subtle so it
   doesn't compete with the row's icon + label. */
.sidebar-nav-btn .sn-soon {
    margin-left: auto;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-dim);
    background: rgba(15, 23, 42, 0.06);
    border: 1px solid rgba(15, 23, 42, 0.08);
}
.sidebar-nav-btn {
    display: flex;
    align-items: center;
    gap: 12px;
    background: transparent;
    color: var(--text-muted);
    border: 1px solid transparent;
    border-radius: 10px;
    padding: 11px 13px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.sidebar-nav-btn:hover {
    background: rgba(15, 23, 42, 0.05);
    color: var(--text);
}
[data-theme="dark"] .sidebar-nav-btn:hover {
    background: rgba(255, 255, 255, 0.05);
}
/* Phase B — active state: gradient fill, gradient border, soft
   accent glow, and a 3px left-edge accent that doubles as a "you
   are here" indicator. Premium-gaming feel without going neon. */
.sidebar-nav-btn.active {
    background: linear-gradient(135deg, rgba(37, 99, 235, 0.14), rgba(139, 92, 246, 0.14));
    border-color: rgba(37, 99, 235, 0.45);
    color: var(--brand-blue);
    box-shadow: 0 0 0 1px rgba(47, 178, 234, 0.18), var(--glow-blue, 0 0 24px rgba(47, 178, 234, 0.25));
    position: relative;
}
.sidebar-nav-btn.active::before {
    content: '';
    position: absolute;
    left: 0;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: linear-gradient(180deg, var(--accent-cyan, #2FB2EA), var(--accent-purple, #8B5CF6));
}
[data-theme="dark"] .sidebar-nav-btn.active {
    background: linear-gradient(135deg, rgba(47, 178, 234, 0.18), rgba(139, 92, 246, 0.18));
    border-color: rgba(47, 178, 234, 0.55);
    color: var(--accent-cyan, #2FB2EA);
}
.sidebar-nav-btn.locked {
    opacity: 0.65;
}
.sidebar-nav-btn.locked:hover {
    opacity: 0.85;
    background: rgba(15, 23, 42, 0.04);
}
/* Click-launch state — pulses the button after click so the user
   can see their click registered even before the plugin renders.
   Added via JS in the sidebar handler; removed after ~1.8s. */
.sidebar-nav-btn.is-launching {
    background: linear-gradient(135deg, rgba(37, 99, 235, 0.18), rgba(139, 92, 246, 0.18));
    border-color: rgba(37, 99, 235, 0.55);
    color: var(--brand-blue);
}
.sidebar-nav-btn.is-launching .sn-icon {
    animation: mmEduPulse 0.9s ease-in-out infinite;
}
@keyframes mmEduPulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.55; transform: scale(0.92); }
}
.sidebar-nav-btn .sn-icon {
    font-size: 18px;
    line-height: 1;
    flex-shrink: 0;
}
.sidebar-nav-btn .sn-label { flex: 1; }
.sidebar-footer {
    margin-top: auto;
    padding-top: 16px;
    color: var(--text-dim);
    font-size: 12px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    border-top: 1px solid var(--border);
}
.sidebar-chip {
    background: rgba(22, 163, 74, 0.10);
    color: #16A34A;
    border: 1px solid rgba(22, 163, 74, 0.35);
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    text-align: center;
    align-self: flex-start;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sidebar-email {
    color: var(--text-muted);
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* When the user is signed in, the email becomes a button that
   opens the Mind Match Education Profile plugin. Styled to read
   like a subtle link rather than a heavy button so it doesn't
   compete with the Plans & pricing CTA underneath. */
.sidebar-email-btn {
    appearance: none;
    background: transparent;
    border: none;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    padding: 4px 0;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: color 0.12s ease;
}
.sidebar-email-btn:hover,
.sidebar-email-btn:focus-visible {
    color: var(--brand-blue);
    text-decoration: underline;
    outline: none;
}
.sidebar-plans-btn {
    background: transparent;
    color: var(--brand-blue);
    border: 1px solid rgba(37, 99, 235, 0.30);
    border-radius: 8px;
    padding: 7px 10px;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.sidebar-plans-btn:hover {
    background: rgba(37, 99, 235, 0.08);
    border-color: rgba(37, 99, 235, 0.50);
}
/* Curtain that drops over the main content when the sidebar
   slides out. Starts below the topbar so the topbar (and the
   menu-toggle's caret state) stays interactable above the
   backdrop. Visible at every viewport when .sidebar-open. */
.sidebar-backdrop {
    display: none;
    position: fixed;
    top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(15, 23, 42, 0.40);
    backdrop-filter: blur(2px);
    z-index: 55;
}
.shell-body.sidebar-open .sidebar-backdrop { display: block; }
.main-panel {
    flex: 1;
    overflow-y: auto;
    /* Bottom inset so the last scrolled content (and the footer) clears
       the iOS home indicator; env() is 0 on web/Android. */
    padding: 24px 22px calc(24px + env(safe-area-inset-bottom, 0px));
    min-width: 0;
    /* Animate the push-right/back when the desktop sidebar docks/undocks. */
    transition: margin-left var(--motion-medium, 220ms) var(--motion-ease, ease);
}

/* ===== Desktop docked sidebar ==================================
   On desktop (≥901px) the side menu defaults to pinned-open: the
   sidebar sits as a fixed left rail and the main panel is pushed
   right to make room — no overlay, no backdrop — and clicking a nav
   row leaves it open. The X in the sidebar header undocks it, which
   app.js persists (localStorage mmEduSidebarDocked=false) and reverts
   to the slide-out drawer + topbar toggle for the rest of the session.
   app.js adds body.mmedu-sidebar-docked only when the pref is on AND
   the viewport is desktop; every rule here is desktop-only, so mobile
   (≤900px) is completely unaffected. */
@media (min-width: 901px) {
    body.mmedu-sidebar-docked .sidebar {
        transform: translateX(0);
        box-shadow: none;
    }
    body.mmedu-sidebar-docked .main-panel {
        margin-left: 260px;
    }
    /* No dimming curtain while docked. */
    body.mmedu-sidebar-docked .sidebar-backdrop {
        display: none !important;
    }
    /* The topbar menu toggle is meaningless while the menu is pinned
       open — hide it. It returns once the user undocks. */
    body.mmedu-sidebar-docked .menu-btn {
        display: none;
    }
    /* Reveal the sidebar header only in docked mode OR while the
       undocked drawer is open on desktop. The header FLOATS in the
       sidebar's top-right corner (position:fixed, mirroring the
       sidebar's own top/left/width) so the control never takes layout
       space or pushes the nav down — it overlays the corner. The logo
       is redundant (it's in the topbar) so it's dropped. pointer-events
       are off on the empty band and re-enabled on the button, so clicks
       pass through to the nav underneath everywhere except the button. */
    body.mmedu-sidebar-docked .sidebar-header,
    .shell-body.sidebar-open .sidebar-header {
        display: flex;
        justify-content: flex-end;
        align-items: flex-start;
        position: fixed;
        top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
        left: 0;
        width: 260px; /* matches .sidebar width */
        padding: 10px 12px 0;
        margin: 0;
        border: none;
        background: transparent;
        pointer-events: none;
        z-index: 61; /* above the sidebar body (z-index 60) */
    }
    body.mmedu-sidebar-docked .sidebar-header > button,
    .shell-body.sidebar-open .sidebar-header > button {
        pointer-events: auto;
    }
    body.mmedu-sidebar-docked .sidebar-header .sidebar-logo,
    .shell-body.sidebar-open .sidebar-header .sidebar-logo {
        display: none;
    }
    /* Docked → the X undocks (unpins). Overlay-open on desktop → the
       pin re-docks. Each mode shows only its own control. (These states
       never coexist: docking clears sidebar-open.) Both float as a chip
       (solid bg + shadow) so they stay legible over scrolling content. */
    body.mmedu-sidebar-docked .sidebar-close-btn,
    .shell-body.sidebar-open .sidebar-pin-btn {
        display: block;
        position: static;
        transform: none;
        background: var(--bg-card);
        box-shadow: var(--shadow-sm);
    }
    body.mmedu-sidebar-docked .sidebar-pin-btn,
    .shell-body.sidebar-open .sidebar-close-btn {
        display: none;
    }
}
/* Top-level view containers — full-width so plugins (Schoolhouse,
   format launchers) and the Curriculum Library grid can expand on
   large screens. Individual sub-views still cap their own widths
   inline where appropriate (My Content + Community both use a
   max-width: 880px inner wrapper). */
.view-panel {
    width: 100%;
}
/* Pre-mount placeholder card: center inside the main panel. */
#content { display: flex; justify-content: center; padding: 24px 0; }
#content:empty { display: none; }
.recently-used-section { margin-bottom: 22px; }

/* ─── Phase B — Home / Learning Command Center ─────────────────
   Scaffold layout for the redesigned dashboard. Phase C wires real
   data into the placeholder cards. Uses the Phase A token system
   throughout so dark theme flips automatically. */
.cc-wrap {
    /* No max-width cap — Home (Learning Command Center) spans the
       full main-panel width so the dashboard reads as a real cockpit
       on wide monitors. .main-panel already has its own padding. */
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 22px;
}
.cc-hero {
    background: linear-gradient(135deg, rgba(37, 99, 235, 0.10) 0%, rgba(139, 92, 246, 0.10) 50%, rgba(251, 191, 36, 0.10) 100%);
    border: 1px solid var(--surface-glass-border, var(--border));
    border-radius: var(--radius-lg, 16px);
    padding: 28px 32px;
    position: relative;
    overflow: hidden;
}
.cc-hero::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at top right, rgba(47, 178, 234, 0.12), transparent 60%);
    pointer-events: none;
}
.cc-hero-eyebrow {
    color: var(--text-dim);
    font-family: var(--font-display, inherit);
    font-size: var(--text-2xs, 0.65rem);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide, 0.05em);
    margin-bottom: 6px;
}
.cc-hero-greeting {
    color: var(--text);
    font-family: var(--font-display, inherit);
    font-size: var(--text-3xl, 1.875rem);
    font-weight: 700;
    letter-spacing: var(--tracking-tight, -0.02em);
    margin: 0 0 8px 0;
    line-height: 1.15;
}
.cc-hero-sub {
    color: var(--text-muted);
    font-size: var(--text-sm, 0.875rem);
    margin: 0;
    line-height: 1.55;
    max-width: 560px;
}

/* Stat-card grid — three KPI tiles. Phase C wires real values. */
.cc-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 14px;
}
.cc-stat-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg, 16px);
    padding: 18px 20px;
    display: flex;
    align-items: center;
    gap: 14px;
    transition: transform var(--motion-fast, 120ms) var(--motion-ease, ease), box-shadow var(--motion-fast, 120ms) var(--motion-ease, ease), border-color var(--motion-fast, 120ms) var(--motion-ease, ease);
    cursor: default;
}
.cc-stat-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-strong);
    box-shadow: var(--shadow-md);
}
.cc-stat-icon {
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md, 10px);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    flex-shrink: 0;
}
.cc-stat-icon.is-streak { background: linear-gradient(135deg, rgba(249, 115, 22, 0.18), rgba(239, 68, 68, 0.12)); color: var(--accent-orange, #F97316); }
.cc-stat-icon.is-xp     { background: linear-gradient(135deg, rgba(47, 178, 234, 0.18), rgba(139, 92, 246, 0.18)); color: var(--accent-cyan, #2FB2EA); }
.cc-stat-icon.is-rank   { background: linear-gradient(135deg, rgba(251, 191, 36, 0.18), rgba(249, 115, 22, 0.12)); color: var(--accent-gold, #FBBF24); }

.cc-stat-eyebrow {
    color: var(--text-dim);
    font-family: var(--font-display, inherit);
    font-size: var(--text-2xs, 0.65rem);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide, 0.05em);
    margin-bottom: 2px;
}
.cc-stat-value {
    color: var(--text);
    font-family: var(--font-display, inherit);
    font-size: var(--text-2xl, 1.5rem);
    font-weight: 700;
    line-height: 1.1;
}
.cc-stat-meta {
    color: var(--text-muted);
    font-size: var(--text-xs, 0.75rem);
    margin-top: 2px;
}

/* "Continue Learning" + "Active Challenges" — wider placeholder cards */
.cc-module {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg, 16px);
    padding: 22px 24px;
}
.cc-module-row {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 14px;
}
.cc-module-eyebrow {
    color: var(--text-dim);
    font-family: var(--font-display, inherit);
    font-size: var(--text-2xs, 0.65rem);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide, 0.05em);
    margin-bottom: 4px;
}
.cc-module-title {
    color: var(--text);
    font-family: var(--font-display, inherit);
    font-size: var(--text-xl, 1.25rem);
    font-weight: 700;
    margin: 0 0 6px 0;
}
.cc-module-body {
    color: var(--text-muted);
    font-size: var(--text-sm, 0.875rem);
    line-height: 1.55;
}
.cc-module-empty {
    margin-top: 12px;
    padding: 14px 16px;
    background: var(--bg-secondary);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-md, 10px);
    color: var(--text-muted);
    font-size: var(--text-sm, 0.875rem);
    text-align: center;
}
.cc-module-cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    padding: 10px 18px;
    background: linear-gradient(135deg, var(--accent-blue, #2563EB), var(--accent-purple, #8B5CF6));
    color: #FFFFFF;
    text-decoration: none;
    border-radius: var(--radius-md, 10px);
    font-family: var(--font-body, inherit);
    font-weight: 700;
    font-size: var(--text-sm, 0.875rem);
    transition: transform var(--motion-fast, 120ms) var(--motion-ease, ease), box-shadow var(--motion-fast, 120ms) var(--motion-ease, ease);
}
.cc-module-cta:hover {
    transform: translateY(-1px);
    box-shadow: var(--glow-blue, 0 0 24px rgba(47, 178, 234, 0.25));
}

@media (max-width: 900px) {
    .cc-hero { padding: 22px 20px; }
    .cc-hero-greeting { font-size: 1.5rem; }
    .cc-stats { grid-template-columns: 1fr; }
    .cc-module-row { grid-template-columns: 1fr; }
}

/* Mobile/tablet — slimmer main-panel padding. The sidebar
   slide-out + curtain + menu-toggle behavior is now base CSS
   (applies at every viewport), so this query only carries the
   small-screen typography/spacing tweaks. */
@media (max-width: 900px) {
    .main-panel { padding: 18px 16px; }
    /* Narrow phones — drop the menu button width slightly so the
       topbar's logo + actions don't overflow. */
    .menu-btn { width: 36px; height: 36px; }
    .brand-logo { height: 40px; }
}

/* Legacy `.main` selector kept for the verifying card layout — used
   only by the pre-auth #content block. */
.main {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px 22px;
}

/* ===== Cards (used by both pages) ===== */
.card {
    max-width: 560px;
    width: 100%;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 18px;
    padding: 40px;
    text-align: center;
    box-shadow: var(--shadow-lg);
}
.card .emoji {
    font-size: 64px;
    line-height: 1;
    margin-bottom: 14px;
    display: block;
}
.card h1 {
    font-size: 28px;
    margin: 0 0 8px 0;
    background: linear-gradient(135deg, var(--brand-blue), var(--brand-purple));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}
.card .tagline {
    color: var(--text-muted);
    font-size: 15px;
    margin: 0 0 28px 0;
}
.status {
    background: rgba(37, 99, 235, 0.12);
    border: 1px solid rgba(37, 99, 235, 0.35);
    border-radius: 12px;
    padding: 18px 20px;
    text-align: left;
    margin-bottom: 24px;
}
.status-label {
    color: var(--brand-blue);
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
}
.status-body {
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
}
.footer {
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1.6;
}

/* ===== Login shell ===== */
.login-shell {
    min-height: 100vh;
    min-height: 100dvh;                 /* dynamic viewport — accurate on mobile */
    display: flex;
    align-items: center;
    justify-content: center;
    /* Reserve the safe areas so the card never sits under the notch/home indicator. */
    padding: max(20px, env(safe-area-inset-top, 0px)) 20px max(20px, env(safe-area-inset-bottom, 0px));
    box-sizing: border-box;
}
/* Native iOS: the auth pages (login/register/verify) have no header to fill
   the top safe-area, so the light page background bled around the notch /
   camera island. Paint just that strip a solid dark. 0-height on web/Android
   (no notch), so it's invisible everywhere except notched iOS. */
.login-shell::before {
    content: '';
    position: fixed;
    top: 0; left: 0; right: 0;
    height: env(safe-area-inset-top, 0px);
    background: #0F172A;
    z-index: 10;
    pointer-events: none;
}
.login-card {
    max-width: 420px;
    width: 100%;
    /* Fit within the safe-area viewport; scroll internally if the content
       (SSO buttons + fields + links) is taller than the screen. */
    max-height: calc(100vh - 40px);
    max-height: calc(100dvh - max(20px, env(safe-area-inset-top, 0px)) - max(20px, env(safe-area-inset-bottom, 0px)));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 18px;
    padding: 32px;
    box-shadow: var(--shadow-lg);
    box-sizing: border-box;
}
.login-card h1 {
    font-size: 22px;
    margin: 0 0 2px 0;
    color: var(--text);
}
.login-card .sub {
    color: var(--text-muted);
    font-size: 13px;
}
.field { margin-bottom: 14px; }
.field label {
    display: block;
    font-size: 12px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
    font-weight: 600;
}
.field input {
    width: 100%;
    padding: 11px 13px;
    background: var(--bg-input);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    color: var(--text);
    /* 16px (not 14) so iOS Safari/WKWebView doesn't auto-zoom on focus —
       sub-16px inputs trigger a zoom that never resets to the viewport. */
    font-size: 16px;
    font-family: inherit;
}
.field input:focus {
    outline: none;
    border-color: var(--brand-blue);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.25);
}

.btn-primary {
    width: 100%;
    padding: 12px 16px;
    background: linear-gradient(135deg, var(--brand-blue), var(--brand-purple));
    color: white;
    border: 0;
    border-radius: 10px;
    font-weight: 700;
    font-size: 14px;
    cursor: pointer;
    transition: transform 0.05s ease, box-shadow 0.2s ease;
}
.btn-primary:hover:not(:disabled) {
    box-shadow: 0 4px 14px rgba(37, 99, 235, 0.4);
}
.btn-primary:active:not(:disabled) { transform: translateY(1px); }
.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }

.btn-secondary {
    padding: 8px 14px;
    background: transparent;
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
}
.btn-secondary:hover { background: rgba(15, 23, 42, 0.05); }

.divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 20px 0 14px;
    color: var(--text-dim);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.divider::before, .divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border);
}

.sso-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.sso-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 11px 14px;
    background: #FFFFFF;
    color: #0F172A;
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    transition: box-shadow 0.15s ease;
}
.sso-btn:hover:not(:disabled) {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
.sso-btn:disabled { opacity: 0.6; cursor: not-allowed; }

.alert {
    padding: 10px 12px;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.5;
    margin-bottom: 16px;
}
.alert-error {
    background: var(--danger-bg);
    color: var(--danger);
    border: 1px solid rgba(239, 68, 68, 0.35);
}
.alert-success {
    background: var(--success-bg);
    color: var(--success);
    border: 1px solid rgba(34, 197, 94, 0.35);
}

.spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid rgba(37, 99, 235, 0.20);
    border-top-color: var(--brand-blue);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
    margin-right: 6px;
    vertical-align: -2px;
}
/* White spinner variant for use on dark/coloured backgrounds */
.spinner-light {
    border: 2px solid rgba(255, 255, 255, 0.30);
    border-top-color: #FFFFFF;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ===== Flashcard grid filter animation =====
   The set-card grids in My Sets + Community animate on filter change
   via a JS FLIP technique (see _flipCapture / _flipPlay in app.js):
   persisting cards slide from their old position to their new one,
   entering cards fade + scale in. The transition + transform are
   applied inline per-card, so no keyframe rule is needed here — this
   comment is a signpost to the JS. FLIP is skipped when the user
   prefers reduced motion. */

/* ===== Flashcard contenteditable definition ===== */
/* Empty-state placeholder for the contenteditable definition area
   in the My Flashcards create form. Browsers don't render
   placeholders on contenteditable, so we use ::before. We also
   match a stray <br> (which some browsers leave behind after the
   user deletes everything) via the data-empty attribute the JS
   keeps in sync. */
.mmEduCardDef[contenteditable="true"]:empty::before,
.mmEduCardDef[contenteditable="true"][data-empty="true"]::before {
    content: attr(data-placeholder);
    color: var(--text-dim);
    pointer-events: none;
}
.mmEduCardDef[contenteditable="true"] img {
    max-width: 100%;
    height: auto;
    vertical-align: middle;
    border-radius: 4px;
}
.mmEduCardDef[contenteditable="true"] a {
    color: var(--brand-blue);
    text-decoration: underline;
}

/* ===== Fullscreen plugin overlay (format launcher) ===== */
#pluginFullscreenOverlay {
    position: fixed;
    inset: 0;
    background: var(--bg);
    z-index: 9500;
    flex-direction: column;
    overflow: hidden;
}
#pluginFullscreenOverlay.open { display: flex !important; }

#pluginLeaveBar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* iOS safe area: the fullscreen overlay covers y=0, so this Close
       bar sat under the notch / camera. Pad the top by the inset so the
       bar's own background fills the notch area. env() is 0 elsewhere. */
    padding: calc(10px + env(safe-area-inset-top, 0px)) 18px 10px;
    border-bottom: 1px solid var(--border);
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(10px);
    z-index: 1;
}
#pluginLeaveBarTitle {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text);
    font-weight: 700;
    font-size: 14px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#pluginCategoryLabel {
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
#pluginCategoryLabel:not(:empty)::after {
    content: '·';
    margin-left: 10px;
    color: var(--text-dim);
}
#pluginLeaveBtn {
    background: rgba(220, 38, 38, 0.10);
    color: #DC2626;
    border: 1px solid rgba(220, 38, 38, 0.40);
    padding: 6px 14px;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 600;
    font-family: inherit;
    font-size: 13px;
}
#pluginLeaveBtn:hover { background: rgba(220, 38, 38, 0.25); }
/* On phones the modal close button is just the ✕ (the " Close" label is
   hidden) to save the cramped top-bar width. aria-label keeps it
   accessible. Desktop/tablet keep the full "✕ Close". */
@media (max-width: 768px) {
    #pluginLeaveBtn .plugin-leave-label { display: none; }
    #pluginLeaveBtn { padding: 6px 12px; font-size: 15px; }
}

#pluginFullscreenContent {
    flex: 1;
    overflow: auto;
    /* Bottom inset so plugin content (flashcards, games, results) clears
       the iOS home indicator. env() is 0 on web/Android. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    color: var(--text);
    background: var(--bg);
}
/* Plugins render into #pluginContent which gets moved into
   #pluginFullscreenContent on open. Make sure the content fills
   the available area so plugin-internal layouts render correctly. */
#pluginFullscreenContent #pluginContent {
    width: 100%;
    min-height: 100%;
}

/* Footer — sits at the bottom of the main-panel scroll area. Scrolls
   with content; hidden when the plugin fullscreen overlay is open
   (overlay is a fixed-inset cover, so no z-index work needed). */
.mmedu-footer {
    margin-top: 40px;
    padding: 24px 16px 18px;
    border-top: 1px solid var(--border, rgba(15, 23, 42, 0.10));
    color: var(--text-muted, #8892b8);
    font-size: 13px;
}
.mmedu-footer-inner {
    max-width: 1100px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.mmedu-footer-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text);
    font-weight: 700;
}
.mmedu-footer-mark {
    width: 26px;
    height: 26px;
    object-fit: contain;
}
.mmedu-footer-links {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 18px;
}
.mmedu-footer-links a,
.mmedu-footer-links .mmedu-footer-linkbtn {
    color: var(--text-muted, #8892b8);
    text-decoration: none;
    font-size: 13px;
    font-family: inherit;
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
}
.mmedu-footer-links a:hover,
.mmedu-footer-links .mmedu-footer-linkbtn:hover {
    color: var(--accent, #00f0ff);
    text-decoration: underline;
}
.mmedu-footer-meta {
    color: var(--text-dim, #8892b8);
    font-size: 12px;
}
@media (min-width: 720px) {
    .mmedu-footer-inner {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: space-between;
        align-items: center;
    }
    .mmedu-footer-links {
        order: 2;
    }
    .mmedu-footer-meta {
        order: 3;
        margin-left: auto;
    }
}
