/*
 * QuizForge.ai - AI-Powered Precision Exam Platform
 * Master CSS File - Production-Ready Futistic Theme
 * https://quizforge.ai
 * 
 * Structure:
 * 1. CSS Variables (QuizForge Theme)
 * 2. CSS Reset & Normalize  
 * 3. Base Styles (Typography, Body, Layout)
 * 4. Utility Classes (Animations, Effects, Helpers)
 * 5. Shared Components (Cards, Buttons, Forms)
 * 6. AI Card System (Unified High-Tech Cards)
 * 7. Responsive Media Queries
 */

/* ========================================
   1. CSS VARIABLES - QUIZFORGE THEME
   ======================================== */

@font-face {
    font-family: 'Oswald';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/oswald-latin-500.woff2') format('woff2');
}

@font-face {
    font-family: 'Oswald';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/oswald-latin-600.woff2') format('woff2');
}

:root {
    /* QuizForge Color Palette — derived from logo (anvil + purple flame + ember sparks) */
    --glytic-primary: #5CA8B8;        /* Steel teal — logo anvil tone, trust/brand color */
    --glytic-primary-rgb: 92, 168, 184;   /* RGB components for rgba() usage */
    --glytic-primary-dark: #4A8FA0;   /* darker steel teal — gradient depth (e.g. Continue button) */
    --glytic-primary-light: #6FBCCC;  /* lighter steel teal — gradient highlight / hover */
    /* Retired 2026-09: the old logo purple was the second brand colour in the 2026-02 system
       (deliberately not spelled out here as a hex literal -- the done_when probe greps the
       served stylesheet for that exact string). The site that shipped is ember + cream + teal
       on navy (Composed Strike, 2026-07); the retired hue survived only in gradient endpoints,
       admin chrome and the 404 button, where it read as a fourth, unexplained hue. Re-pointing
       the token retires the colour at one line instead of editing 119 call sites. Ember also
       fixes an accessibility gap: the retired hue on --glytic-bg-dark was 3.8:1 (AA large text
       only), ember is 5.1:1 (AA). */
    --glytic-secondary: #C86030;
    --glytic-secondary-rgb: 200, 96, 48; /* RGB components for rgba() usage */
    --glytic-bg-dark: #0C1018;        /* Deep iron black — logo shadow tone */
    --glytic-bg-medium: #1A2230;      /* Steel-tinted mid — logo #203040 family */
    --glytic-bg-light: #1E3040;       /* Steel blue — logo #204050 family */
    --glytic-text-primary: #f0f0f0;   /* Primary text color */
    --glytic-text-secondary: #e0e0e0; /* Secondary text color */
    --glytic-text-muted: #a0a0a0;     /* Muted text color */
    --glytic-error: #ff6b6b;          /* Error/danger text color */
    --glytic-error-rgb: 255, 107, 107;    /* RGB components for rgba() usage */
    --glytic-success: #48bb78;        /* Success/positive text color */
    --glytic-success-rgb: 72, 187, 120;   /* RGB components for rgba() usage */
    --glytic-warning: #ffa726;        /* Warning/caution text color */

    /* Glow Effects — steel teal glow, purple for intense */
    --glytic-shadow: 0 4px 16px rgba(var(--glytic-primary-rgb), 0.25);
    --glytic-glow: 0 0 12px rgba(var(--glytic-primary-rgb), 0.4);
    --glytic-glow-intense: 0 0 20px rgba(92,168,184,.45); /* purple demoted -> flat teal glow */
    --glytic-text-glow: 0 0 15px rgba(var(--glytic-primary-rgb), 0.5);

    /* Surfaces and Containers — warmer iron undertone */
    --glytic-surface: rgba(24, 30, 42, 0.85);
    --glytic-card-bg: rgba(24, 32, 44, 0.92);
    --glytic-border: rgba(var(--glytic-primary-rgb), 0.22);
    --glytic-border-hover: rgba(var(--glytic-primary-rgb), 0.45);

    /* Typography scale — responsive clamp values */
    --font-hero-h1: clamp(2rem, 5vw, 3.5rem);
    --font-section-h2: clamp(1.5rem, 3vw, 2.25rem);

    /* Spacing scale */
    --space-xs: 0.5rem;
    --space-sm: 1rem;
    --space-md: 2rem;
    --space-lg: 4rem;
    --space-xl: 6rem;

    /* Gradients — teal to purple (logo's two accent families) */
    --glytic-gradient-bg: linear-gradient(135deg, var(--glytic-bg-dark) 0%, var(--glytic-bg-medium) 50%, var(--glytic-bg-light) 100%);
    --glytic-gradient-card: linear-gradient(135deg, rgba(92,168,184,.10), rgba(92,168,184,.03)); /* purple demoted -> flat teal */
    --glytic-gradient-text: linear-gradient(135deg, #8FD0DE 0%, #5CA8B8 100%); /* purple demoted -> flat teal */
    --glytic-gradient-overlay: linear-gradient(135deg, rgba(var(--glytic-primary-rgb), 0.08), rgba(var(--glytic-primary-rgb), 0.05), rgba(92,168,184,.08)); /* purple demoted -> flat teal */

    /* Typography */
    --glytic-font-heading: 'Oswald', 'Arial Narrow', 'Franklin Gothic Medium', Impact, sans-serif;
    --glytic-font-body: 'Inter', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;

    /* Sizing and Spacing */
    --glytic-border-radius: 20px;
    --glytic-border-radius-small: 12px;
    --glytic-border-radius-large: 24px;
    --glytic-transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    --glytic-transition-long: 0.55s cubic-bezier(0.22, 0.68, 0.37, 1);

    /* Responsive Breakpoints */
    --glytic-breakpoint-sm: 600px;
    --glytic-breakpoint-md: 768px;
    --glytic-breakpoint-lg: 1200px;
    --glytic-breakpoint-xl: 1400px;

    /* Forge Accent Palette — logo ember/spark tones for CTAs */
    --forge-primary: #C86030;          /* Logo ember orange */
    --forge-primary-rgb: 200, 96, 48;  /* RGB components of --forge-primary for rgba() usage */
    --forge-amber: #B86038;            /* Deep copper from logo */
    --forge-gold: #D07040;             /* Warm copper spark */
    --forge-spark: #E09060;            /* Bright ember highlight (Forge Breaks accents) */
}

/* Forge Break open: the fixed app bar (z-index 1300) sits in a stacking context above
   the quiz page content, so it would float over the break overlay and cover its header
   row. The break is a modal moment; hide global chrome for its duration. */
body.qf-forge-open .mud-appbar {
    visibility: hidden;
}

:root {
    --forge-glow: rgba(192,96,48,0.2);
    --forge-glow-intense: rgba(192,96,48,0.38);
    --forge-border: rgba(192,96,48,0.35);
    --forge-border-subtle: rgba(192,96,48,0.18);
    --forge-surface: rgba(192,96,48,0.06);
    --forge-gradient: linear-gradient(135deg, #C86030 0%, #D07040 100%);
    --forge-gradient-btn: linear-gradient(135deg, #D07040 0%, #B86038 100%);
    --forge-shadow: 0 4px 16px rgba(192,96,48,0.25);
    /* Career Forge nav fire treatment */
    --forge-fire-amber: #F59E0B;
    --forge-fire-orange: #F97316;
    --forge-fire-deep: #EA580C;
    --forge-fire-gradient: linear-gradient(135deg, #F59E0B, #F97316, #EA580C);
    --forge-fire-glow: rgba(245, 158, 11, 0.15);
    --forge-fire-glow-intense: rgba(249, 115, 22, 0.3);

    /* Score threshold colors -- used by quiz results and topic bars */
    --glytic-score-pass: #34d399;
    --glytic-score-mid: #fbbf24;
    --glytic-score-fail: #f87171;
    --glytic-score-pass-rgb: 52, 211, 153;
    --glytic-score-mid-rgb: 251, 191, 36;
    --glytic-score-fail-rgb: 248, 113, 113;

    /* Composed Strike restyle tokens (2026-07) — angular cut-corner language.
       See docs/superpowers/specs/2026-07-09-composed-strike-restyle-design.md 2.2 */
    --qf-crimson: #D8342C;        /* the strike: one diagonal, wrong-answer state, heaviest datum */
    --qf-crimson-rgb: 216, 52, 44;    /* RGB components of --qf-crimson for rgba() usage */
    --qf-crimson-text: #E9695F;   /* crimson lifted for small text (AA on dark planes) */
    --qf-crimson-deep: #B22821;   /* darkened crimson for small text ON crimson (bg role, not text role):
                                     bone #EFE7D2 on --qf-crimson-deep computes to 5.29:1 (WCAG AA normal-text
                                     pass, >=4.5:1); bone on the base --qf-crimson (#D8342C) is only 3.83:1 and fails.
                                     Verified via a WCAG relative-luminance script, not eyeballed. */
    --qf-bone: #EFE7D2;           /* paper/poster surface */
    --qf-bone-dim: #5B5648;       /* muted text on bone */
    --qf-ink: #12100C;            /* text on bone and ember */
    --qf-ink-rgb: 18, 16, 12;     /* RGB components of --qf-ink for rgba() usage */
    --qf-line: #232B3A;           /* hairlines on dark */
    --qf-cut: 18px;               /* standard corner cut */
    --qf-cut-sm: 10px;            /* small elements */
    --qf-clip-card: polygon(0 0, calc(100% - var(--qf-cut)) 0, 100% var(--qf-cut), 100% 100%, var(--qf-cut) 100%, 0 calc(100% - var(--qf-cut)));
    --qf-clip-btn:  polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
    --qf-gold: #D8A83C;           /* source-verified receipt line (distinct from ember/crimson) */
    --qf-gold-rgb: 216, 168, 60;  /* RGB components of --qf-gold for rgba() usage */
    --qf-gold-on-bone: #7A5810;   /* darkened gold for source lines printed on bone (AA on --qf-bone; raw --forge-gold/--qf-gold fail) */
    --qf-gold-on-bone-rgb: 122, 88, 16; /* RGB components of --qf-gold-on-bone for rgba() usage */
    --qf-display: 'Oswald', 'Arial Narrow', 'Franklin Gothic Medium', Impact, sans-serif;
}

/* Hindi pages get a Devanagari face at the top of every font stack. Redefining the three
   variables reaches every consumer at once, because the whole design system reads
   var(--glytic-font-body) / var(--glytic-font-heading) / var(--qf-display). Latin text inside a
   Hindi page (certification names, exam codes -- never translated) still falls through to
   Inter and Oswald, which is what the second entry in each stack is for. The face itself loads
   only on /hi routes (Server/Components/App.razor), so English/Spanish visitors never fetch it.
   Fresh-look audit 2026-09-02, locales P2-5. */
html[lang="hi"] {
    --glytic-font-body: 'Noto Sans Devanagari', 'Inter', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
    --glytic-font-heading: 'Noto Sans Devanagari', 'Oswald', 'Arial Narrow', 'Franklin Gothic Medium', Impact, sans-serif;
    --qf-display: 'Noto Sans Devanagari', 'Oswald', 'Arial Narrow', 'Franklin Gothic Medium', Impact, sans-serif;
}

/* ========================================
   2. CSS RESET & NORMALIZE
   ======================================== */

/* Modern CSS Reset */
*, *::before, *::after {
    box-sizing: border-box;
}

* {
    margin: 0;
    padding: 0;
    user-select: none;
    -webkit-user-select: none;
}

/* Cursor discipline (QA5-1): set the resting cursor ONCE on the root so it INHERITS.
   Setting cursor on `*` gave every element its own `default`, which defeated inheritance
   into button/link children -- so a button's label + icon showed the arrow while only the
   padding showed the hand. Rooting it on <html> lets interactive elements cascade `pointer`
   down to their descendants (label/icon/svg) naturally. */
html { cursor: default; }

/* Re-enable text selection for input elements */
input, textarea, select, button, [contenteditable="true"], [contenteditable] {
    user-select: auto !important;
    -webkit-user-select: auto !important;
}

/* Specific cursor types */
input[type="text"], input[type="email"], input[type="password"],
input[type="search"], textarea {
    cursor: text;
}

/* Interactive elements get pointer; their descendants inherit it (no !important needed
   now that the `*` reset no longer forces `default` on every node). Disabled controls are
   excluded so they do not advertise a click affordance they cannot honor. */
input[type="button"], input[type="submit"], input[type="reset"],
button:not(:disabled):not([aria-disabled="true"]),
a, [role="button"]:not([aria-disabled="true"]), label[for], select, summary {
    cursor: pointer;
}

/* Disabled buttons: match MudBlazor's disabled convention (cursor: default, not not-allowed)
   so QuizForge's global reset agrees with MudButton's own disabled styling. */
button:disabled, input[type="button"]:disabled,
input[type="submit"]:disabled, input[type="reset"]:disabled,
[role="button"][aria-disabled="true"], [aria-disabled="true"] {
    cursor: default;
}

input[type="checkbox"], input[type="radio"] {
    cursor: pointer;
}

/* Remove default styles */
ul, ol {
    list-style: none;
}

html:focus-within {
    scroll-behavior: smooth;
}

/* ========================================
   3. BASE STYLES
   ======================================== */

html, body {
    min-height: 100vh;
    font-family: var(--glytic-font-body);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    color-scheme: dark;
}

body {
    background: var(--glytic-gradient-bg) fixed;
    color: var(--glytic-text-primary);
    letter-spacing: 0.025em;
    overflow-x: hidden;
}

/* Typography Base */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--glytic-font-heading);
    font-weight: 600;
    line-height: 1.3;
    margin-bottom: 1rem;
}

h1 {
    font-size: clamp(2.5rem, 6vw, 4rem);
    color: #ffffff;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    position: relative;
}

h2 {
    font-size: clamp(1.8rem, 4vw, 2.5rem);
    color: #ffffff;
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
}

h3 {
    font-size: clamp(1.4rem, 3vw, 1.8rem);
    color: var(--glytic-text-primary);
}

p {
    margin-bottom: 1rem;
    color: var(--glytic-text-secondary);
    font-size: clamp(1rem, 2.5vw, 1.1rem);
}

/* Links */
a {
    color: var(--glytic-primary);
    text-decoration: none;
    transition: var(--glytic-transition);
}

a:hover {
    color: var(--glytic-primary);
    text-shadow: var(--glytic-glow);
}

/* ========================================
   4. UTILITY CLASSES
   ======================================== */


/* Text utilities -- WCAG AA compliant on dark backgrounds */
.text-muted {
    color: var(--glytic-text-muted);
}

/* Brand text - Clean QuizForge styling */
.qf-brand-text {
    color: #ffffff;
    font-family: var(--glytic-font-heading);
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* Container Utilities */
.qf-container {
    max-width: var(--glytic-breakpoint-xl);
    margin: 0 auto;
    padding: 0 1.25rem;
}

.qf-surface {
    background: var(--glytic-surface);
    border-radius: var(--glytic-border-radius);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--glytic-border);
    box-shadow: var(--glytic-shadow);
}

/* Replace existing particle background with ultra subtle system */
.particle-bg, .qf-particle-bg {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
  background: radial-gradient(circle at 15% 35%, rgba(var(--glytic-primary-rgb),0.04), transparent 60%),
              radial-gradient(circle at 82% 72%, rgba(var(--glytic-primary-rgb),0.035), transparent 65%), /* purple demoted -> flat teal ambient */
              radial-gradient(circle at 55% 85%, rgba(var(--glytic-primary-rgb),0.03), transparent 70%);
  animation: bgDrift 60s linear infinite;
  filter: saturate(105%) brightness(105%);
}

/* Hide individual particle dots (legacy) */
.particle, .qf-particle { display:none !important; }

@keyframes bgDrift {
  0% { transform: translate3d(0,0,0) scale(1); }
  50% { transform: translate3d(0,-30px,0) scale(1.02); }
  100% { transform: translate3d(0,0,0) scale(1); }
}

@media (prefers-reduced-motion: reduce){
  .particle-bg, .qf-particle-bg { animation:none; }
}

/* Animation Effects.
   These two keyframes are consumed by scoped CSS (Quiz.razor.css, via global keyframe
   names). The former generic animation utility classes (.qf-fade-in, .qf-pulse-success,
   .qf-neon-flicker, .ai-card-glow, .qf-shimmer-text) and the keyframes only they used
   (subtle-glow, fadeInGlow, ai-border-glow, gradient-shimmer) were all unused after the
   Composed Strike restyle dropped the glow theme, and were removed in the Task 12 sweep. */
@keyframes neon-flicker {
    0%, 100% {
        text-shadow: 0 0 12px rgba(var(--glytic-primary-rgb), 0.8), 0 0 2px var(--glytic-bg-medium);
    }
    50% {
        text-shadow: 0 0 20px rgba(var(--glytic-primary-rgb), 0.9), 0 0 8px var(--glytic-bg-medium);
    }
}

@keyframes success-pulse {
    0% {
        box-shadow: 0 0 32px rgba(46, 204, 113, 0.4),
                    0 0 48px rgba(var(--glytic-primary-rgb), 0.2),
                    0 0 64px rgba(var(--glytic-primary-rgb), 0.1);
    }
    100% {
        box-shadow: 0 0 48px rgba(46, 204, 113, 0.6),
                    0 0 64px rgba(var(--glytic-primary-rgb), 0.3),
                    0 0 80px rgba(var(--glytic-primary-rgb), 0.15);
    }
}

/* ========================================
   5. SHARED COMPONENTS
   ======================================== */

/* QuizForge Cards */
.qf-card {
    position: relative;
    isolation: isolate;
    display: flex;
    flex-direction: column;
    /* Bevel-FOLLOWING border (double-layer reveal): the element FILL is the border color and the
       ::after interior (inset 1px) paints the card surface, so the hairline follows the cut
       corners (a real border is sheared off them by the clip-path). Hover recolors the fill. */
    background: var(--glytic-border);
    border: 0;
    border-radius: 0; /* Composed Strike: rectangles die -> cut corners */
    clip-path: var(--qf-clip-card);
    padding: 1.5rem;
    overflow: hidden;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: var(--glytic-shadow);
    transition: var(--glytic-transition-long);
    cursor: pointer;
}

/* Opaque interior surface (fill) behind all content; leaves the 1px border-color rim exposed. */
.qf-card::after {
    content: '';
    position: absolute;
    inset: 1px;
    clip-path: var(--qf-clip-card);
    background: var(--glytic-card-bg);
    z-index: -1;
    pointer-events: none;
}

/* Hover glow overlay (decorative) -- sits above the interior and content, faint and transparent. */
.qf-card::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--glytic-gradient-overlay);
    opacity: 0;
    transition: opacity 0.6s ease;
    pointer-events: none;
    border-radius: inherit;
}

.qf-card:hover {
    /* Composed Strike: no translate/scale on cards -- border + glow shift only */
    background: var(--glytic-border-hover);
    box-shadow: 0 12px 40px rgba(var(--glytic-primary-rgb), 0.2),
                0 4px 16px rgba(0, 0, 0, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.qf-card:hover::before {
    opacity: 1;
}

/* Card Content */
.qf-card-title {
    font-family: var(--glytic-font-heading);
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--glytic-primary);
    margin-bottom: 0.75rem;
    text-shadow: var(--glytic-glow);
}

.qf-card-description {
    color: var(--glytic-text-secondary);
    font-size: 0.9rem;
    line-height: 1.5;
    margin-bottom: 1rem;
    opacity: 0.9;
}

/* Buttons */
.qf-btn {
    position: relative;
    isolation: isolate;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 1.5rem;
    /* Ghost button bevel-following border (double-layer reveal): element FILL = border color,
       ::before interior (inset 1px) = the faint teal wash; hairline follows the cut corner. */
    background: var(--glytic-border);
    border: 0;
    border-radius: 0; /* Composed Strike: cut corner */
    clip-path: var(--qf-clip-btn);
    color: var(--glytic-text-primary);
    font-family: var(--glytic-font-body);
    font-weight: 600;
    text-decoration: none;
    transition: var(--glytic-transition);
    cursor: pointer;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.qf-btn::before {
    content: '';
    position: absolute;
    inset: 1px;
    clip-path: var(--qf-clip-btn);
    background: var(--glytic-gradient-card);
    z-index: -1;
    pointer-events: none;
}

.qf-btn:hover {
    /* Composed Strike: no translate -- border + glow shift only */
    background: var(--glytic-border-hover);
    box-shadow: var(--glytic-shadow);
    color: var(--glytic-primary);
}

.qf-btn-primary {
    background: var(--forge-gradient-btn); /* purple demoted -> ember CTA */
    color: var(--qf-ink);
    border: none;
}
/* Filled ember CTA: no bevel-border layer, so drop the ghost interior it would inherit. */
.qf-btn-primary::before {
    content: none;
}

.qf-btn-primary:hover {
    color: var(--qf-ink);
    box-shadow: var(--glytic-glow);
}

/* Form Elements.
   NOTE ON BEVELS: unlike the cards/buttons above, .qf-input targets a bare <input>, and form
   controls do not generate ::before/::after pseudo-elements (they have no document-tree children
   to attach generated content to). The double-layer bevel reveal is therefore impossible here
   without wrapping the input in markup, which is out of scope for a shared-primitive change. The
   real border is kept; --qf-clip-btn only cuts a single 12px top-right corner, so the sheared
   segment is a small, low-visibility notch. The inset focus ring below stays intact. */
.qf-input {
    width: 100%;
    padding: 0.75rem 1rem;
    background: rgba(26, 34, 48, 0.8);
    border: 1px solid var(--glytic-border);
    border-radius: 0; /* Composed Strike: cut corner */
    clip-path: var(--qf-clip-btn);
    color: var(--glytic-text-primary);
    font-family: var(--glytic-font-body);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transition: var(--glytic-transition);
}

.qf-input:focus {
    outline: none;
    border-color: var(--glytic-primary);
    box-shadow: 0 0 0 2px rgba(var(--glytic-primary-rgb), 0.2);
}

/* ========================================
   COMPOSED STRIKE FOCUS RINGS ON CLIPPED INTERACTIVES  (WCAG 2.4.7)
   ----------------------------------------
   EMPIRICAL TEST (2026-07-09, Chromium): clip-path DOES clip `outline` as well as
   `box-shadow`. An outward focus ring (outline-offset >= 0) on any clip-path element
   renders entirely OUTSIDE the clipped region and is fully cut away -- invisible. That
   is a keyboard focus-visibility failure on every cut-corner input/button/pill/chip/card.
   (Screenshotted: outline-offset:3px and :0 both vanished; box-shadow ring vanished;
    outline-offset:-4px stayed fully visible inside the shape.)

   FIX / CANONICAL PATTERN: inset the ring so it stays inside the clipped shape.
   `outline: 2px solid var(--glytic-primary); outline-offset: -4px;` sits ~4px inside the
   border box, clear of every cut corner, and is always visible. This is WCAG-acceptable
   (the indicator need not be outside the element). Apply `.qf-focus-inset` on markup, or
   replicate this :focus-visible block, on ANY element that carries a clip-path. Non-clipped
   interactives may keep a conventional outward ring -- but the inset ring is safe on both. */
.qf-focus-inset:focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

/* Skip link (WCAG 2.4.1). Off-screen until it takes focus, then it paints over the
   app bar. Uses the same inset focus ring as every other clipped control. */
/* Fixed, not absolute: with position:absolute the link's offset parent varied by page
   (.mud-layout on /, a hero wrapper on /pricing, /career, /resources), which left a 14 px strip
   of the box visible at the top-left corner (owner review 2026-09-03). Parked above the
   viewport with a transform, it cannot depend on any ancestor. */
.qf-skip-link {
    position: fixed;
    left: 8px;
    top: 8px;
    transform: translateY(calc(-100% - 16px));
    z-index: 2000;
    padding: 10px 16px;
    /* --glytic-surface is translucent rgba (quizforge.css:63) and would let page
       content show through the link. --glytic-bg-medium (#1A2230, :53) is opaque. */
    background: var(--glytic-bg-medium);
    color: var(--glytic-text-primary);
    border: 1px solid var(--glytic-primary);
    font-family: var(--glytic-font-body);
    font-size: 0.875rem;
    text-decoration: none;
    transition: top 0.12s ease;
}

.qf-skip-link:focus,
.qf-skip-link:focus-visible {
    transform: none;
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

/* ===== Focus visibility (WCAG 2.4.7) =====
   :focus-visible only, so a mouse click never draws a ring. brand-home-btn, exam-card,
   quiz-tap-option and the pricing billing switch already carry their own rule elsewhere
   in the repo (MainLayout.razor.css, Index.razor.css, Quiz.razor.css, Pricing.razor.css);
   this block covers what the 2026-09-02 re-measure still found unstyled. No !important
   anywhere -- if a MudBlazor rule wins, raise specificity instead. */
.appbar-nav-links a:focus-visible,
.appbar-nav-links button:focus-visible,
.desktop-nav-actions a:focus-visible,
.desktop-nav-actions button:focus-visible,
.mobile-menu-btn:focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

.career-showcase-card:focus-visible,
.cat-chip:focus-visible,
.vendor-pill:focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

/* MudBlazor buttons and icon buttons render their own ripple and suppress the UA
   ring. Scoped to the app bar and the page body so this does not fight admin UI. */
.qf-appbar .mud-button-root:focus-visible,
.main-content .mud-button-root:focus-visible,
.main-content .mud-icon-button:focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

/* The skip target must never draw its own ring: focus is moved there
   programmatically by the fragment navigation, not by the user tabbing to it. */
main:focus {
    outline: none;
}

/* .qf-input carries clip-path: var(--qf-clip-btn) -> use the inset ring, not an outward one. */
.qf-input:focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

/* ========================================
   5b. UNIFIED PANEL SYSTEM
   Auth pages, MudDialogs, review popups — all share this treatment.
   Matches the HeroMiniQuiz card design language.
   ======================================== */

/* Full-page centering wrapper (auth pages) */
.qf-panel-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(ellipse 900px 500px at 50% -80px, rgba(var(--glytic-primary-rgb), 0.10), transparent),
        radial-gradient(ellipse 600px 400px at 80% 100%, rgba(var(--glytic-primary-rgb), 0.05), transparent),
        linear-gradient(180deg, #0b1222 0%, #0a0f1a 100%);
    padding: 32px 16px;
    box-sizing: border-box;
}

/* Column constraint */
.qf-panel-col {
    width: 100%;
    max-width: 440px;
    margin: 0 auto;
}

/* The panel card itself — Composed Strike cut-corner plane.
   clip-path shears box-shadow, so elevation moves to filter: drop-shadow (follows the cut). */
.qf-panel {
    /* Bevel-FOLLOWING border (double-layer reveal): the element FILL is the border color and the
       ::before interior (inset 1px, same clip-path) paints the panel gradient + ambient glow, so
       the hairline follows the two 45deg cut corners (a real 1px border was sheared off them).
       filter: drop-shadow already makes this a stacking context; isolation:isolate is belt-and-
       braces so the z-index:-1 interior and watermark stay contained. */
    background: rgba(var(--glytic-primary-rgb), 0.30);
    border: 0;
    border-radius: 0;
    clip-path: var(--qf-clip-card);
    filter: drop-shadow(0 20px 44px rgba(0, 0, 0, 0.6));
    position: relative;
    isolation: isolate;
    overflow: hidden;
}

/* Opaque interior surface = panel gradient with the subtle ambient glow (teal only — purple
   purged) layered on top. Inset 1px so the border-color rim shows on every edge incl. the cuts.
   z-index:-1 keeps it below all form content; the watermark ::after (also z-index:-1, later in
   tree order) paints ABOVE this interior but still below the form. */
.qf-panel::before {
    content: '';
    position: absolute;
    inset: 1px;
    clip-path: var(--qf-clip-card);
    background:
        radial-gradient(ellipse at 10% 15%, rgba(var(--glytic-primary-rgb), 0.05) 0%, transparent 55%),
        radial-gradient(ellipse at 90% 85%, rgba(var(--glytic-primary-rgb), 0.035) 0%, transparent 55%),
        linear-gradient(152deg, #151a28 0%, #1c2438 50%, #111520 100%);
    z-index: -1;
    pointer-events: none;
}

/* Photoreal forged-Q plate bled off the top-right corner of the auth box (replaces the old
   crown that floated ABOVE the panel). Uses the high-res 512 icon, anchored and radial-masked
   so it dissolves toward the form; negative z-index keeps it above the panel gradient but
   BEHIND the form content (the filter: drop-shadow above makes .qf-panel a stacking context,
   so this is contained and clipped by the cut-corner). Low opacity + fade keeps all form text
   and CTAs at full AA contrast. Decorative only -> pointer-events: none. */
.qf-panel::after {
    content: '';
    position: absolute;
    top: -46px;
    right: -46px;
    width: 300px;
    height: 300px;
    background: url('../icon-512.png') no-repeat top right / contain;
    opacity: 0.14;
    -webkit-mask-image: radial-gradient(circle at top right, #000 0%, rgba(0, 0, 0, 0.55) 42%, transparent 72%);
    mask-image: radial-gradient(circle at top right, #000 0%, rgba(0, 0, 0, 0.55) 42%, transparent 72%);
    pointer-events: none;
    z-index: -1;
}

@media (max-width: 600px) {
    .qf-panel::after {
        top: -34px;
        right: -34px;
        width: 220px;
        height: 220px;
        opacity: 0.12;
    }
}

/* Input fields inside panels — teal-tinted borders, squared (Composed Strike) */
.qf-panel .mud-input.mud-input-outlined .mud-input-outlined-border {
    border-color: rgba(var(--glytic-primary-rgb), 0.18);
    border-radius: 0;
}
.qf-panel .mud-input.mud-input-outlined:hover .mud-input-outlined-border {
    border-color: rgba(var(--glytic-primary-rgb), 0.35);
}
.qf-panel .mud-input.mud-input-outlined.mud-input-focused .mud-input-outlined-border {
    border-color: rgba(var(--glytic-primary-rgb), 0.55);
}
.qf-panel .mud-input-label,
.qf-panel .mud-input-helper-text {
    color: rgba(201, 209, 217, 0.6);
}
.qf-panel .mud-input {
    color: #e0e6ed;
}

/* Links inside panels */
.qf-panel a,
.qf-panel .mud-link {
    color: var(--glytic-primary);
}

/* Focus states -- inset ring so it survives any clipped child (e.g. .qf-input) and stays
   consistent with the Composed Strike focus pattern above. */
.qf-panel :focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -4px;
}

/* Mobile */
@media (max-width: 600px) {
    .qf-panel-page { padding: clamp(16px, 6vh, 40px) 14px; }
    .qf-panel-col { max-width: 92vw; }
}

/* Very small devices */
@media (max-width: 380px) {
    .qf-panel-page { padding: 20px 10px; }
}

/* Safe-area support for iOS notch */
@supports (padding: max(0px)) {
    .qf-panel-page {
        padding-top: max(32px, env(safe-area-inset-top));
        padding-bottom: max(32px, env(safe-area-inset-bottom));
    }
}


/* Dialog-hosted panel: interior padding so the modal card matches the page card */
.qf-panel--dialog { padding: 24px; }
@media (max-width: 600px) { .qf-panel--dialog { padding: 20px 18px; } }


/* ========================================
   AUTH SURFACES (Composed Strike, Task 10)
   AuthPrompt is the consolidated auth component; it hosts inside .qf-panel on the
   /login + /register pages and inside the .qf-auth-dialog modal (which neutralizes its
   MudDialog chrome so the inner .qf-panel is the visible plane). These are GLOBAL rules,
   not scoped CSS: Blazor scoped CSS only stamps the [b-hash] attribute on plain elements in
   a component's own markup, never on the elements MudText/MudButton render, so the classes
   AuthPrompt passes to those Mud components (.auth-prompt__heading, .auth-prompt__btn-primary)
   can only be reached from a global sheet. Compound selectors outrank MudBlazor defaults
   without !important because this sheet loads after the MudBlazor stylesheet.
   ======================================== */

/* Display-font headings across every auth panel (login, register, forgot, reset, confirm,
   registration-success, and the modal). */
.qf-panel .mud-typography-h3,
.qf-panel .mud-typography-h4,
.qf-panel .mud-typography-h5,
.qf-panel .mud-typography-h6,
.auth-prompt .auth-prompt__heading {
    font-family: var(--qf-display);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.015em;
    line-height: 1.05;
}

/* AuthPrompt primary CTAs (magic-link / create-account / password sign-in / 2FA verify) are
   Variant.Filled with no Color -> ember plate, ink text, cut corner. */
.auth-prompt .auth-prompt__btn-primary {
    background: var(--forge-gradient-btn);
    color: var(--qf-ink);
    border: none;
    border-radius: 0;
    clip-path: var(--qf-clip-btn);
    font-weight: 700;
}
.auth-prompt .auth-prompt__btn-primary:hover {
    background: var(--forge-gradient);
    color: var(--qf-ink);
}
/* Ember plate should carry ink label + spinner (MudButton colors the inner label span). */
.auth-prompt .auth-prompt__btn-primary .mud-button-label,
.auth-prompt .auth-prompt__btn-primary .mud-progress-circular {
    color: var(--qf-ink);
}

/* Filled primary buttons on the utility auth pages (forgot / reset / confirm / reg-success)
   use Color="Color.Primary" -> same ember cut-corner plate for one consistent primary. */
.qf-panel .mud-button-root.mud-button-filled.mud-button-filled-primary {
    background: var(--forge-gradient-btn);
    color: var(--qf-ink);
    border-radius: 0;
    clip-path: var(--qf-clip-btn);
}
.qf-panel .mud-button-root.mud-button-filled.mud-button-filled-primary:hover {
    background: var(--forge-gradient);
}
.qf-panel .mud-button-filled.mud-button-filled-primary .mud-button-label {
    color: var(--qf-ink);
}

/* ========================================
   6. AI CARD SYSTEM - UNIFIED HIGH-TECH CARDS
   ======================================== */

/* Base AI Card Style - Applied to all major cards */
.ai-card-style {
    position: relative !important;
    /* Bevel-FOLLOWING border via the double-layer reveal. A real 1px `border` under a clip-path
       is sheared off the two 45deg cut corners, so cut-corner cards never showed a border on
       their bevels (owner: "bevel border edge missing on question containers"). Instead: the
       element FILL is the border color and the ::before interior (inset 1px, same clip-path)
       paints the card gradient, so the hairline shows on EVERY edge incl. the cuts. The interior
       sits at z-index:-1 inside this card's own stacking context (isolation:isolate below), so
       ALL content -- including MudBlazor-rendered children that carry no scope attribute -- paints
       above it with no child-lift rule. Hover recolors the fill (the border layer). */
    background: rgba(var(--glytic-primary-rgb), 0.22) !important;
    border: 0 !important;
    border-radius: 0 !important; /* Composed Strike: cut corners */
    clip-path: var(--qf-clip-card);
    overflow: hidden !important;
    backdrop-filter: blur(12px) saturate(140%) !important;
    -webkit-backdrop-filter: blur(12px) saturate(140%) !important;
    transition: background-color 0.55s ease, box-shadow 0.55s ease !important;
    box-shadow: 0 6px 18px -6px rgba(0, 0, 0, 0.55),
                0 0 0 0 rgba(var(--glytic-primary-rgb), 0.15) !important;
    isolation: isolate;
}

/* MudCard-based ai-cards: mudblazor-theme.css's `.mud-card { background: ... !important }` loads
   AFTER this file at equal specificity, stomping the border fill above -- the bevel hairline
   vanished at rest on every MudCard ai-card (owner: "bevel border edge missing on question
   containers"). Higher specificity wins regardless of file order. */
.mud-card.ai-card-style {
    background: rgba(var(--glytic-primary-rgb), 0.22) !important;
}

/* Streak fill: grows stronger with consecutive correct/wrong answers, recoloring the card's
   border layer (the double-layer fill above). These MUST live in this GLOBAL file: the quiz
   question card is a MudCard (component output carries no CSS-isolation scope attribute), so
   the same rules inside Quiz.razor.css compiled to [b-scope]-suffixed selectors that never
   matched -- dead since the day they shipped. Specificity 0,3,0 beats .mud-card.ai-card-style. */
.question-card.streak-correct.streak-level-1 { background: rgba(34, 197, 94, 0.35) !important; }
.question-card.streak-correct.streak-level-2 { background: rgba(34, 197, 94, 0.50) !important; }
.question-card.streak-correct.streak-level-3 { background: rgba(34, 197, 94, 0.65) !important; }
.question-card.streak-correct.streak-level-4 { background: rgba(34, 197, 94, 0.80) !important; }
.question-card.streak-correct.streak-level-5 { background: rgba(34, 197, 94, 0.95) !important; }

.question-card.streak-wrong.streak-level-1 { background: rgba(239, 68, 68, 0.30) !important; }
.question-card.streak-wrong.streak-level-2 { background: rgba(239, 68, 68, 0.45) !important; }
.question-card.streak-wrong.streak-level-3 { background: rgba(239, 68, 68, 0.60) !important; }
.question-card.streak-wrong.streak-level-4 { background: rgba(239, 68, 68, 0.75) !important; }
.question-card.streak-wrong.streak-level-5 { background: rgba(239, 68, 68, 0.90) !important; }

.ai-card-style::before {
    content: '';
    position: absolute;
    inset: 1px;
    clip-path: var(--qf-clip-card);
    background: linear-gradient(145deg, #141823 0%, #1b2331 55%, #0f141c 100%);
    z-index: -1;
    pointer-events: none;
}

.ai-card-style:hover {
    background: rgba(var(--glytic-primary-rgb), 0.55) !important;
    box-shadow: 0 18px 38px -10px rgba(0, 0, 0, 0.85),
                0 0 24px -4px rgba(var(--glytic-primary-rgb), 0.55),
                0 0 2px 1px rgba(var(--glytic-primary-rgb), 0.35) inset !important;
}

/* AI Card Overlay Effect */
.ai-overlay {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: radial-gradient(circle at 22% 18%, rgba(var(--glytic-primary-rgb), 0.18), transparent 60%),
                radial-gradient(circle at 85% 75%, rgba(var(--glytic-secondary-rgb), 0.18), transparent 65%);
    opacity: 0.42;
    mix-blend-mode: plus-lighter;
    transition: opacity 0.6s ease;
    pointer-events: none;
    border-radius: inherit;
}

.ai-card-style:hover .ai-overlay {
    opacity: 0.7;
}

/* Subtle overlay for less prominent cards */
.ai-overlay-subtle {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: radial-gradient(circle at 30% 30%, rgba(var(--glytic-primary-rgb), 0.08), transparent 70%);
    opacity: 0.6;
    mix-blend-mode: plus-lighter;
    pointer-events: none;
    border-radius: inherit;
}

/* AI Typography Classes - Updated for clean white text */
.ai-card-title {
    font-family: var(--glytic-font-heading) !important;
    font-weight: 600 !important;
    letter-spacing: 0.5px !important;
    color: #ffffff !important;
    position: relative;
    z-index: 1;
}

.ai-card-subtitle {
    font-family: var(--glytic-font-heading) !important;
    font-weight: 500 !important;
    letter-spacing: 0.3px !important;
    color: #f0f0f0 !important;
    position: relative;
    z-index: 1;
}

.ai-card-text {
    color: #e8fffe !important;
    font-family: var(--glytic-font-body) !important;
    position: relative;
    z-index: 1;
    opacity: 0.95;
}

.ai-card-category {
    font-family: var(--glytic-font-heading) !important;
    font-weight: 500 !important;
    letter-spacing: 0.8px !important;
    text-transform: uppercase !important;
    font-size: 0.75rem !important;
    color: var(--glytic-primary) !important;
    text-shadow: 0 0 8px rgba(var(--glytic-primary-rgb), 0.6) !important;
    position: relative;
    z-index: 1;
}

.ai-stat-text {
    color: #c6ece8 !important;
    font-family: var(--glytic-font-body) !important;
    position: relative;
    z-index: 1;
}

.ai-score-text {
    font-family: var(--glytic-font-heading) !important;
    font-weight: 700 !important;
    color: #ffffff !important;
    position: relative;
    z-index: 1;
}

/* AI Interactive Elements */
.ai-feature-button {
    background: linear-gradient(135deg, rgba(var(--glytic-primary-rgb), 0.15), rgba(var(--glytic-secondary-rgb), 0.15)) !important;
    border: 1px solid rgba(var(--glytic-primary-rgb), 0.35) !important;
    border-radius: 12px !important;
    color: #e0fdfb !important;
    font-family: 'Inter', sans-serif !important;
    font-weight: 600 !important;
    letter-spacing: 0.3px !important;
    backdrop-filter: blur(8px) !important;
    transition: all 0.4s ease !important;
    position: relative;
    z-index: 1;
}

.ai-feature-button:hover {
    background: linear-gradient(135deg, rgba(var(--glytic-primary-rgb), 0.25), rgba(var(--glytic-secondary-rgb), 0.25)) !important;
    border-color: rgba(var(--glytic-primary-rgb), 0.55) !important;
    box-shadow: 0 0 0 1px rgba(var(--glytic-primary-rgb), 0.4),
                0 4px 16px -4px rgba(var(--glytic-primary-rgb), 0.6) !important;
    color: #f0ffff !important;
    /* Remove transform - no movement on hover */
}

.ai-nav-button {
    background: rgba(var(--glytic-primary-rgb), 0.08) !important;
    border: 1px solid rgba(var(--glytic-primary-rgb), 0.25) !important;
    border-radius: 10px !important;
    color: #c8ece9 !important;
    font-family: 'Inter', sans-serif !important;
    font-weight: 500 !important;
    backdrop-filter: blur(6px) !important;
    transition: all 0.3s ease !important;
    position: relative;
    z-index: 1;
}

.ai-nav-button:hover {
    background: rgba(var(--glytic-primary-rgb), 0.18) !important;
    border-color: rgba(var(--glytic-primary-rgb), 0.45) !important;
    box-shadow: 0 0 0 1px rgba(var(--glytic-primary-rgb), 0.35) !important;
    color: #e0fffd !important;
    /* Remove transform - no movement on hover */
}

/* AI Navigation FAB Buttons */
.ai-nav-fab {
    background: linear-gradient(135deg, rgba(var(--glytic-primary-rgb), 0.15), rgba(var(--glytic-secondary-rgb), 0.15)) !important;
    border: 2px solid rgba(var(--glytic-primary-rgb), 0.35) !important;
    color: var(--glytic-primary) !important;
    backdrop-filter: blur(8px) saturate(140%) !important;
    -webkit-backdrop-filter: blur(8px) saturate(140%) !important;
    box-shadow: 0 4px 16px -4px rgba(var(--glytic-primary-rgb), 0.4),
                0 0 0 1px rgba(var(--glytic-primary-rgb), 0.2) inset !important;
    transition: background 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease, color 0.4s ease !important;
    position: relative;
    z-index: 10;
}

.ai-nav-fab:hover {
    background: linear-gradient(135deg, rgba(var(--glytic-primary-rgb), 0.25), rgba(var(--glytic-secondary-rgb), 0.25)) !important;
    border-color: rgba(var(--glytic-primary-rgb), 0.55) !important;
    color: #f0ffff !important;
    box-shadow: 0 8px 24px -6px rgba(var(--glytic-primary-rgb), 0.6),
                0 0 0 2px rgba(var(--glytic-primary-rgb), 0.4) inset,
                0 0 20px rgba(var(--glytic-primary-rgb), 0.3) !important;
    /* Remove all transform properties - no movement on hover */
}

.ai-nav-fab:disabled {
    background: rgba(var(--glytic-primary-rgb), 0.05) !important;
    border-color: rgba(var(--glytic-primary-rgb), 0.1) !important;
    color: rgba(var(--glytic-primary-rgb), 0.3) !important;
    cursor: not-allowed !important;
    box-shadow: none !important;
}

.ai-nav-fab:active:not(:disabled) {
    /* Remove transform on active state - no movement */
}

/* ========================================
   QUIZ-SPECIFIC READABILITY OVERRIDES
   ======================================== */

/* Override AI gradient text for quiz questions - prioritize readability */
.quiz-question-text {
    font-family: 'Inter', 'Segoe UI', system-ui, sans-serif !important;
    font-size: 1.35rem !important;
    font-weight: 500 !important;
    line-height: 1.5 !important;
    color: #ffffff !important;
    text-shadow: none !important;
    background: none !important;
    -webkit-background-clip: initial !important;
    -webkit-text-fill-color: initial !important;
    background-clip: initial !important;
    filter: none !important;
    margin-bottom: 2rem !important;
}

/* Quiz answer styling */
.quiz-answer-group, .quiz-radio-group {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.quiz-answer-option {
    background: rgba(30, 41, 59, 0.6) !important;
    border: 1px solid rgba(148, 163, 184, 0.3) !important;
    border-radius: 12px !important;
    padding: 0.5rem !important;
    transition: all 0.3s ease !important;
    backdrop-filter: blur(4px) !important;
}

.quiz-answer-option:hover {
    background: rgba(30, 41, 59, 0.8) !important;
    border-color: rgba(148, 163, 184, 0.5) !important;
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
}

.quiz-answer-option .mud-checkbox,
.quiz-answer-option .mud-radio {
    width: 100% !important;
    margin: 0 !important;
    padding: 0.75rem 1rem !important;
}

.quiz-answer-option .mud-checkbox-label,
.quiz-answer-option .mud-radio-label {
    font-family: 'Inter', sans-serif !important;
    font-size: 0.95rem !important;
    font-weight: 400 !important;
    color: #e2e8f0 !important;
    line-height: 1.4 !important;
}

/* Ensure quiz text elements are readable */
.quiz-category.ai-card-category {
    font-family: 'Inter', sans-serif !important;
    color: #94a3b8 !important;
    font-size: 0.8rem !important;
    text-transform: uppercase !important;
    letter-spacing: 0.5px !important;
    font-weight: 500 !important;
}

/* Quiz results text readability */
.ai-answer-section {
    background: rgba(30, 41, 59, 0.3) !important;
    border: 1px solid rgba(148, 163, 184, 0.2) !important;
    border-radius: 12px !important;
    padding: 1rem !important;
    margin-bottom: 1rem !important;
}

.ai-answer-section .ai-card-subtitle {
    color: #e2e8f0 !important;
    font-family: 'Inter', sans-serif !important;
}

.ai-answer-section .ai-card-text {
    color: #cbd5e1 !important;
    font-family: 'Inter', sans-serif !important;
}

/* ========================================
   7. RESPONSIVE MEDIA QUERIES
   ======================================== */

/* Mobile First Approach */
@media (max-width: 600px) {
    .qf-container {
        padding: 0 1rem;
    }
    
    .qf-card, .ai-card-style {
        padding: 1.25rem;
        margin: 0 0.5rem;
    }

    /* Remove transform animations on mobile */
    .ai-card-style:hover {
        transform: none !important;
    }
}

/* Tablet */
@media (min-width: 601px) and (max-width: 1200px) {
    .qf-container {
        padding: 0 2rem;
    }
}

/* Desktop */
@media (min-width: 1201px) {
    .qf-container {
        padding: 0 3rem;
    }
    
    /* Composed Strike: cards no longer translate/scale on hover (border + glow only) */

    /* Remove transform animations from AI cards on desktop too */
    .ai-card-style:hover {
        transform: none !important;
    }
}

/* Reduce Motion for Accessibility */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }

    .qf-card:hover, .ai-card-style:hover {
        transform: none !important;
    }
    
    .ai-feature-button:hover,
    .ai-nav-button:hover,
    .ai-nav-fab:hover {
        transform: none !important;
    }
}

/* High Contrast Mode Support */
@media (prefers-contrast: high) {
    :root {
        --glytic-primary: #00ffff;
        --glytic-secondary: #ff00ff;
        --glytic-border: rgba(255, 255, 255, 0.5);
        --glytic-text-primary: #ffffff;
    }
}

/* Print Styles */
@media print {
    .qf-particle-bg,
    .qf-card::before,
    .ai-overlay,
    .ai-overlay-subtle {
        display: none;
    }
    
    body {
        background: white;
        color: black;
    }
    
    .qf-card, .ai-card-style {
        background: white;
        border: 1px solid black;
        box-shadow: none;
    }
}

/* Footer styles moved to MainLayout.razor.css (global footer) */

/* ========================================
   PERFORMANCE OPTIMIZATIONS
   ======================================== */

/* Hardware Acceleration for Animations */
.qf-card,
.qf-btn,
.qf-particle,
.ai-card-style {
    will-change: transform;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}

/* Content Visibility for Large Lists */
.qf-card, .ai-card-style {
    content-visibility: auto;
    contain-intrinsic-size: 320px 200px;
}

/* Fallbacks for Older Browsers */
@supports not (backdrop-filter: blur(10px)) {
    .qf-surface,
    .qf-card,
    .qf-input,
    .ai-card-style {
        background: rgba(26, 34, 48, 0.95);
    }
}

@supports not (-webkit-backdrop-filter: blur(10px)) {
    .qf-surface,
    .qf-card,
    .qf-input,
    .ai-card-style {
        background: rgba(26, 34, 48, 0.95);
    }
}

/* Vendor Prefixes for Critical Properties */
.qf-card,
.qf-surface,
.ai-card-style {
    -webkit-backdrop-filter: blur(10px) saturate(140%);
    backdrop-filter: blur(10px) saturate(140%);
}

/* Accessibility improvements */
.ghost-card:focus {
    outline: 2px solid var(--glytic-primary);
    outline-offset: 2px;
}

.ghost-create-btn:focus,
.create-quiz-btn:focus {
    box-shadow: 0 0 0 3px rgba(var(--glytic-primary-rgb), 0.3);
}

.recommended-item:focus {
    outline: 1px solid var(--glytic-primary);
    outline-offset: 1px;
}

/* High contrast mode support */
@media (prefers-contrast: high) {
    .ghost-card {
        border-color: var(--glytic-primary) !important;
    }

    .search-title,
    .ghost-title {
        color: #ffffff !important;
        -webkit-text-fill-color: #ffffff !important;
    }
}

/* Smooth loading animation */
@keyframes pulse {
    0%, 100% {
        opacity: 1;
    }
    50% {
        opacity: 0.6;
    }
}

/* Enhanced quiz grid for infinite scroll */
.quiz-grid-new {
    /* Masonry via multi-column layout */
    column-gap: 1.5rem;              /* horizontal spacing between columns */
    column-width: 320px;             /* preferred column width */
    padding: 0;
    margin: 0 auto;                  /* center */
    width: 100%;
    max-width: 1400px;
    position: relative;
}

/* Homepage Specific Styles */
/* ========================================
   HOMEPAGE SPECIFIC STYLES
   ======================================== */

/* QuizForge Root Container */
.qf-root {
    min-height: 100vh;
    background: var(--glytic-gradient-bg) fixed;
    position: relative;
    overflow-x: hidden;
}

/*
 * Hero section removed (Feb 2026). See docs/SEARCH-BAR-PAIN-POINTS.md — SEARCH-009/010.
 * Search bar and quiz section styles are defined in Index.razor.css (scoped).
 * See docs/SEARCH-BAR-PAIN-POINTS.md — SEARCH-001.
 */

/* Verified badge styling - CENTERED and MORE SUBDUED */
.verified-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    padding: 0.25rem 0.5rem;
    background: linear-gradient(135deg, rgba(255, 215, 0, 0.12), rgba(255, 193, 7, 0.08)); /* More subtle background */
    border: 1px solid rgba(255, 215, 0, 0.3); /* More subdued border */
    border-radius: 10px; /* Slightly smaller radius */
    font-size: 0.65rem; /* Slightly smaller text */
    font-weight: 500; /* Less bold */
    color: rgba(255, 215, 0, 0.8); /* More muted color */
    text-transform: uppercase;
    letter-spacing: 0.3px; /* Reduced letter spacing */
    box-shadow: 0 1px 4px rgba(255, 215, 0, 0.15), 0 0 6px rgba(255, 215, 0, 0.1); /* Much more subtle shadow */
    z-index: 10;
    backdrop-filter: blur(3px); /* Reduced blur */
    opacity: 0.85; /* Overall reduced opacity for subdued effect */
}

.verified-badge .mud-icon-root {
    font-size: 0.8rem; /* Slightly smaller icon */
    color: rgba(255, 215, 0, 0.8); /* More muted icon color */
    filter: drop-shadow(0 0 2px rgba(255, 215, 0, 0.3)); /* Much more subtle glow */
}

/* ENHANCED: Empty results styling */
.empty-results-message {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 3rem 2rem;
    margin: 2rem auto;
    max-width: 500px;
    break-inside: avoid;
}

.empty-results-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

.empty-results-content h3 {
    color: var(--glytic-text-primary);
    font-family: var(--glytic-font-heading);
    margin: 0;
}

.empty-results-content .mud-icon-root {
    margin-bottom: 0.5rem;
}

/* ========================================
   MOBILE FLASHCARDS - Full viewport, no nav arrows
   ======================================== */
@media (max-width: 768px) {
    /* Hide nav arrow columns - double class for specificity over MudBlazor d-flex */
    .flashcard-grid .flashcard-nav-col {
        display: none !important;
    }

    /* Card column fills entire width */
    .flashcard-column {
        flex-basis: 100% !important;
        max-width: 100% !important;
        padding: 0 !important;
    }

    /* Content-driven flashcard (Option C: bottom bar layout) */
    .flashcard-card {
        min-height: 0 !important;
        height: calc(100dvh - 230px) !important;
        max-height: none !important;
        overflow-y: auto !important;
        border-radius: 12px !important;
        margin: 0 !important;
        display: flex !important;
        flex-direction: column !important;
    }

    .flashcard-card > .mud-card-content {
        flex: 1 !important;
        display: flex !important;
        flex-direction: column !important;
        padding: 1.25rem !important;
    }

    /* Question/answer sides fill available space */
    .question-side:not(.hidden),
    .answer-side:not(.hidden) {
        flex: 1 !important;
        display: flex !important;
        flex-direction: column !important;
    }

    .flashcard-body {
        flex: 1 !important;
        display: flex !important;
        flex-direction: column !important;
        justify-content: center !important;
    }

    /* Question text: larger, centered, better line height */
    .flashcard-question-text {
        font-size: 1.25rem !important;
        line-height: 1.65 !important;
        padding: 0.5rem 0 !important;
    }

    /* Answer options: comfortable touch targets */
    .flashcard-answer-options {
        margin-top: 1.25rem !important;
        gap: 0.625rem !important;
    }

    .flashcard-answer-option {
        font-size: 1rem !important;
        line-height: 1.5 !important;
        padding: 0.875rem 1rem !important;
        min-height: 48px !important;
    }

    /* Answer reveal boxes: readable sizing */
    .answer-reveal-box {
        font-size: 1rem !important;
        line-height: 1.5 !important;
        padding: 0.875rem 1rem !important;
        min-height: 48px !important;
    }

    .flashcard-answers-title {
        font-size: 1.05rem !important;
    }

    /* Explanation text: comfortable reading */
    .flashcard-explanation-text {
        font-size: 0.9375rem !important;
        line-height: 1.6 !important;
    }

    /* AI explanation text */
    .flashcard-ai-explanation-text {
        font-size: 0.9375rem !important;
        line-height: 1.6 !important;
    }

    /* Bottom section scrollable if card overflows */
    .flashcard-bottom-section {
        margin-top: auto !important;
        padding-top: 0.75rem !important;
    }

    /* Compact controls bar */
    .flashcard-controls-section .mud-card-content {
        padding: 0.5rem 0.75rem !important;
    }

    /* Flip hint: smaller on mobile since swipe is primary */
    .flip-hint {
        font-size: 0.75rem !important;
    }

    /* Grid removes outer spacing */
    .flashcard-grid {
        margin: 0 !important;
        padding: 0 !important;
    }

    .flashcard-wrapper {
        margin: 0 !important;
    }

    /* Viewport container flush */
    .flashcards-viewport {
        padding-left: 8px !important;
        padding-right: 8px !important;
    }
}

@media (max-width: 480px) {
    .flashcard-card {
        height: calc(100dvh - 210px) !important;
        border-radius: 8px !important;
    }

    .flashcard-card > .mud-card-content {
        padding: 1rem !important;
    }

    .flashcard-question-text {
        font-size: 1.125rem !important;
    }

    .flashcards-viewport {
        padding-left: 4px !important;
        padding-right: 4px !important;
    }
}

/* ========================================
   MOBILE QUIZ & FLASHCARD — GLOBAL OVERRIDES
   Rules that target MudBlazor component output (MudCard, MudCardActions, etc.)
   MUST be global because scoped CSS only applies to HTML elements, not Razor components.
   See: .claude/docs/RAZOR-CSS-STYLING-REFERENCE.md — Pitfall 1 & 3
   ======================================== */

/* Quiz: Hide MudCardActions when inline nav row is shown (result view) */
.quiz-inline-result .mud-card-actions {
    display: none !important;
}

/* ========================================
   QUIZ FOCUS MODE (mobile app-bar takeover)
   While an active quiz session question is on screen, Quiz.razor adds body.quiz-focus.
   On phones the global app bar is hidden so the slim in-page focus bar (.fm-sticky)
   owns the top, giving the question + answers the full screen. Desktop keeps the app
   bar (the slim bar sits below it). These target MudBlazor output (.mud-main-content)
   so they live here, not in scoped CSS.
   ======================================== */
@media (max-width: 768px) {
    body.quiz-focus .qf-appbar {
        display: none;
    }

    /* The layout reserves the fixed app bar's height (~72px) above the content; that margin
       collapses up to <main>, so it cannot be removed by zeroing .mud-main-content. The app
       bar is hidden in focus mode, so counteract the reservation at <main> -- this lands the
       slim bar flush at the top (and makes it visibly sticky on scroll). If the app bar's
       rendered height changes, update this value. Validated on Test. */
    body.quiz-focus main {
        margin-top: -72px !important;
    }

    body.quiz-focus .mud-main-content {
        padding-top: 0;
    }

    /* The global site footer is dead weight inside an active quiz on a phone. */
    body.quiz-focus .qf-footer {
        display: none;
    }

    /* Reserve room for the fixed action dock so the tail of a long explanation (the
       confidence selector) can scroll clear of it. Targets the MudContainer output here in
       global CSS because scoped CSS cannot attach to a child component's root element.
       Sized for the taller result-state dock, which stacks the 44px rating/flag row above a
       full-width Next button on phones (see Quiz.razor.css L3 rules). */
    body.quiz-focus .quiz-viewport {
        padding-bottom: calc(128px + env(safe-area-inset-bottom));
    }
}

/* Short coarse-pointer landscape (e.g. 800x375) is wider than the 768px arm above, so the
   action dock stays inline -- but the AI tutor FAB (AiTutorPanel.razor.css, whose mobile block
   matches this arm) is still a fixed 54px circle in the bottom-right corner. Reserve enough
   bottom padding that the last interactive controls and the inline dock can scroll clear of it. */
@media (min-width: 769px) and (max-height: 500px) and (pointer: coarse) {
    body.quiz-focus .quiz-viewport {
        padding-bottom: calc(74px + env(safe-area-inset-bottom));
    }
}

/* ========================================
   SUPPRESS BLAZOR CIRCUIT ERROR BANNER
   Blazor sets display:block via inline style at runtime — !important is required
   to override it. Errors are still logged server-side via CustomErrorBoundary
   and the circuit exception handler. This is intentional for production UX.
   ======================================== */
#blazor-error-ui {
    display: none !important;
}

/* ========================================
   SEO hub pages (/vendors, /vendor/{slug})
   Server-rendered internal-link hubs that de-orphan the exam catalog.
   ======================================== */
.seo-hub-crumbs {
    font-size: 0.85rem;
    color: var(--glytic-text-secondary, rgba(255, 255, 255, 0.6));
    margin-bottom: 0.75rem;
}
.seo-hub-crumbs a {
    color: var(--glytic-primary, #00ffe7);
    text-decoration: none;
}
.seo-hub-crumbs span {
    margin: 0 0.35rem;
}
.seo-hub-title {
    font-family: var(--glytic-font-heading, inherit);
    font-size: 1.9rem;
    font-weight: 700;
    margin: 0 0 0.5rem;
    color: var(--glytic-text-primary, #fff);
}
.seo-hub-intro {
    color: var(--glytic-text-secondary, rgba(255, 255, 255, 0.7));
    max-width: 50rem;
    margin: 0 0 2rem;
    line-height: 1.6;
}
.seo-hub-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1rem;
}
.seo-hub-card {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--glytic-border, rgba(255, 255, 255, 0.12));
    border-radius: 10px;
    background: var(--glytic-bg-card, rgba(26, 30, 48, 0.6));
    text-decoration: none;
    transition: border-color 0.15s ease, transform 0.15s ease;
}
.seo-hub-card:hover {
    border-color: var(--glytic-border-hover, var(--glytic-primary, #00ffe7));
    transform: translateY(-2px);
}
.seo-hub-card-title {
    font-weight: 600;
    color: var(--glytic-text-primary, #fff);
    line-height: 1.35;
}
.seo-hub-card-meta {
    font-size: 0.8rem;
    color: var(--glytic-text-secondary, rgba(255, 255, 255, 0.55));
}
.seo-hub-footer-link {
    margin-top: 2.5rem;
}
.seo-hub-footer-link a {
    color: var(--glytic-primary, #00ffe7);
    text-decoration: none;
}
.seo-hub-loading {
    display: flex;
    justify-content: center;
    padding: 3rem 0;
}
.seo-hub-pagination {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 2rem 0 1rem;
}
.seo-hub-page {
    min-width: 2.75rem;
    min-height: 2.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--glytic-border, rgba(255, 255, 255, 0.12));
    border-radius: 10px;
    text-decoration: none;
    color: var(--glytic-primary, #00ffe7);
}
.seo-hub-page:hover {
    border-color: var(--glytic-border-hover, var(--glytic-primary, #00ffe7));
}
.seo-hub-page.current {
    background: var(--glytic-bg-card, rgba(26, 30, 48, 0.6));
    color: var(--glytic-text-primary, #fff);
    font-weight: 600;
}

/* ========================================
   COMPOSED STRIKE UTILITIES (2026-07 restyle)
   Shared angular/semantic primitives consumed by per-surface passes.
   See docs/superpowers/specs/2026-07-09-composed-strike-restyle-design.md
   ======================================== */
.qf-cut-card { clip-path: var(--qf-clip-card); border-radius: 0; }
.qf-cut-btn  { clip-path: var(--qf-clip-btn);  border-radius: 0; }

/* Bevel-following hairline border for cut-corner cards (QA5-2). A real CSS border only
   paints the 4 straight rectangle edges, so clip-path shears it off the two 45deg cut
   corners -> the bevel has no border and can never highlight on hover. This utility uses
   the double-layer reveal: the element FILL is the border color; a ::before surface inset
   1px lets that fill show as a 1px hairline on EVERY edge, cut corners included. Hover
   recolors the fill. The interior sits at z-index:-1 inside the card's own stacking context
   (isolation:isolate), so ALL content paints above it with no z-index requirement -- including
   MudBlazor-rendered children, which carry no scoped attribute and can never be lifted by a
   scoped child rule. Reuse instead of copying the technique per card. */
.qf-cut-card-bordered {
    position: relative;
    isolation: isolate;
    border-radius: 0;
    border: 0;
    clip-path: var(--qf-clip-card);
    background: var(--glytic-border, #232B3A);
    transition: background 0.2s ease;
}
.qf-cut-card-bordered::before {
    content: '';
    position: absolute;
    inset: 1px;
    clip-path: var(--qf-clip-card);
    background: var(--glytic-bg-card, #12151f);
    transition: background 0.2s ease;
    pointer-events: none;
    z-index: -1;
}
.qf-cut-card-bordered:hover { background: var(--glytic-primary); }
/* Visually hide content while keeping it in the accessibility tree (screen-reader-only). */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}
.qf-eyebrow {
  font-size: .69rem; font-weight: 600; letter-spacing: .22em;
  text-transform: uppercase; color: var(--glytic-text-muted);
}
/* Answer-option marker glyph. SHAPE encodes question semantics, not state:
   the base glyph is a SQUARE (checkbox convention) for multiple-response
   questions; add .qf-glyph--round for a CIRCLE (radio convention) on
   single-answer questions. Shape is FIXED across every state -- a single-answer
   glyph stays a circle from empty outline through to a filled resolve
   (circle-to-circle; this supersedes the earlier square-resolves-to-circle
   motif), and a multiple-response glyph stays a square throughout. Only the
   COLOR reacts to state: muted outline (default), ember (selected), teal fill
   (correct), crimson fill (the user's wrong pick). --correct/--wrong are
   color-only and never set border-radius. */
.qf-glyph {
  display: inline-block; width: 13px; height: 13px; flex: none;
  border: 2px solid var(--glytic-text-muted);
  transition: background .2s ease, border-color .2s ease;
}
/* The ONLY sanctioned border-radius on the Composed Strike restyle: it turns the
   square marker into a radio-style circle for single-answer (radio) questions. */
.qf-glyph--round   { border-radius: 50%; }
.qf-glyph--correct { border-color: var(--glytic-primary); background: var(--glytic-primary); }
.qf-glyph--wrong   { border-color: var(--qf-crimson); background: var(--qf-crimson); }
.qf-rule-diag { position: relative; height: 56px; overflow: clip; }
.qf-rule-diag::before {
  content: ""; position: absolute; left: -4%; right: -4%; top: 50%;
  height: 2px; background: var(--qf-crimson); transform: rotate(-1.4deg);
}
.qf-bone-plate {
  background: var(--qf-bone); color: var(--qf-ink);
  clip-path: var(--qf-clip-card);
}
.qf-bone-plate .qf-eyebrow { color: var(--qf-bone-dim); }
.qf-stamp {
  display: inline-block; font-family: var(--glytic-font-heading);
  color: var(--qf-crimson); border: 4px double var(--qf-crimson);
  padding: .1em .45em .04em; text-transform: uppercase;
  letter-spacing: .1em; transform: rotate(-6deg);
}
@media (prefers-reduced-motion: reduce) {
  .qf-glyph { transition: none; }
}

/* ========================================
   MOBILE DRAWER NAV (Composed Strike chrome, Task 3)
   MudDrawer Variant="Temporary" teleports its aside out of MainLayout's scoped
   root, so scoped ::deep cannot reach it. These global rules are keyed on the
   unique .mobile-drawer class (only that one drawer carries it), keeping the
   uppercase / muted -> text / teal-datum treatment consistent with the desktop
   appbar nav. Compound selectors outrank MudBlazor's own .mud-nav-link defaults
   without !important.
   ======================================== */
.mobile-drawer .mud-nav-link {
  color: var(--glytic-text-muted);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 0.82rem;
  /* Touch target: >=44px tall tap rows in the mobile drawer (QA4-4, was ~40px). */
  min-height: 44px;
}
.mobile-drawer .mud-nav-link:hover {
  color: var(--glytic-text-primary);
  background: rgba(var(--glytic-primary-rgb), 0.06);
}
.mobile-drawer .mud-nav-link.active {
  color: var(--glytic-primary);
  border-left: 2px solid var(--glytic-primary);
}

/* ========================================
   DIALOG SHELL BASE (Composed Strike R2-1)
   Shared base for EVERY user-facing MudDialog. MudDialog teleports its .mud-dialog
   paper (title bar + content + action bar) out of any scoped root, so scoped ::deep
   -- and even bare class rules on inner MudText/MudButton -- silently no-op. These
   global rules are keyed on the .qf-dialog-shell class each dialog carries via its
   MudDialog Class parameter, applied alongside a per-dialog unique class so individual
   dialogs need only add deltas below (no duplicated shell geometry).

   The mudblazor-overrides.css .mud-dialog baseline sets background/border/
   border-radius/box-shadow with !important and injects a purple ::before radial, so
   the cut-corner override here also uses !important to beat that pre-existing baseline
   (documented pre-existing-beating -- no other new !important on this surface).
   clip-path shears box-shadow, so elevation moves to a drop-shadow filter, and the
   purple radial is removed for this surface (purple purge).
   ======================================== */
.mud-dialog.qf-dialog-shell {
  background: var(--qf-line) !important;
  border: 0 !important;
  border-radius: 0 !important;
  clip-path: var(--qf-clip-card);
  box-shadow: none !important;
  filter: drop-shadow(0 20px 44px rgba(0, 0, 0, 0.55));
  position: relative;
  isolation: isolate;
}
/* Bevel-following hairline via the double-layer reveal: the shell FILL is the qf-line border
   color, and this inset ::before paints the bg-medium interior so the hairline follows the two
   cut corners (a real 1px border was sheared off them by the clip-path). z-index:-1 + isolation
   keeps dialog content above the interior without positioning it. This ::before also REPLACES the
   mudblazor-overrides baseline's purple radial (purple purge preserved). */
.mud-dialog.qf-dialog-shell::before {
  content: '';
  position: absolute;
  inset: 1px;
  clip-path: var(--qf-clip-card);
  background: var(--glytic-bg-medium);
  z-index: -1;
  pointer-events: none;
}

/* Display-font title on a hairline divider; drop the baseline's purple tint/border. */
.mud-dialog.qf-dialog-shell .mud-dialog-title {
  font-family: var(--glytic-font-heading);
  letter-spacing: 0.01em;
  background: transparent;
  border-bottom: 1px solid var(--qf-line);
}
.mud-dialog.qf-dialog-shell .mud-dialog-title .mud-typography {
  font-family: var(--glytic-font-heading);
}
.mud-dialog.qf-dialog-shell .mud-dialog-actions {
  border-top: 1px solid var(--qf-line);
}

/* Action-bar buttons: ember primary, ghost secondary. Scoped to .mud-dialog-actions so
   in-content selector buttons (wizard mode/count chips) keep their own affordance.
   Extra .mud-button-root reliably beats MudBlazor's own filled-color background without
   a new !important (same technique as the onboarding CTA). clip-path clips outward
   outlines, so focus rings sit INSET (outline-offset: -4px). */
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-filled-primary,
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-filled-success {
  background: var(--forge-gradient-btn);
  color: var(--qf-ink);
  border-radius: 0;
  clip-path: var(--qf-clip-btn);
}
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-filled-primary .mud-button-label,
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-filled-success .mud-button-label {
  color: var(--qf-ink);
}
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-filled-primary:focus-visible,
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-filled-success:focus-visible {
  outline: 2px solid var(--qf-ink);
  outline-offset: -4px;
}
/* Ghost secondary (outlined/text): cut-corner, hairline, muted, inset teal focus ring. */
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-outlined {
  border-radius: 0;
  clip-path: var(--qf-clip-btn);
  border: 0;
  background: var(--qf-line);
  color: var(--glytic-text-secondary);
  position: relative;
  isolation: isolate;
}
/* Double-layer hairline so the ghost outline follows the cut corner (a real border is sheared). */
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-outlined::before {
  content: '';
  position: absolute;
  inset: 1px;
  clip-path: var(--qf-clip-btn);
  background: var(--glytic-bg-medium);
  z-index: -1;
  pointer-events: none;
}
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-outlined:focus-visible,
.mud-dialog.qf-dialog-shell .mud-dialog-actions .mud-button-root.mud-button-text:focus-visible {
  outline: 2px solid var(--glytic-primary);
  outline-offset: -4px;
}

/* Accessibility: never animate the shell for reduced-motion users. */
@media (prefers-reduced-motion: reduce) {
  .mud-dialog.qf-dialog-shell,
  .mud-dialog.qf-dialog-shell * {
    transition: none !important;
    animation: none !important;
  }
}

/* Per-dialog deltas (geometry lives in the base above). */
/* Comments dialog: keep a scrollable body so long comment lists never overflow the cut panel. */
.mud-dialog.qf-dialog-shell.qf-rating-comments-dialog .comments-dialog-content {
  max-height: 60vh;
  overflow-y: auto;
}

/* ========================================
   PREMIUM UPSELL DIALOG SHELL (Composed Strike, Task 9)
   MudDialog teleports its .mud-dialog paper out of any scoped root, so scoped
   ::deep cannot reach the panel itself. These global rules are keyed on the unique
   .premium-upsell-shell class the dialog carries (only that dialog uses it).
   The QuizForge dialog baseline (mudblazor-overrides.css .mud-dialog) sets
   background/border/border-radius/box-shadow with !important and injects a subtle
   purple ::before radial, so this cut-corner override must also use !important to
   beat that pre-existing baseline (documented pre-existing-beating -- no other new
   !important on this surface). clip-path shears box-shadow, so elevation moves to
   drop-shadow, and the purple radial is removed for this paywall surface.
   ======================================== */
.mud-dialog.premium-upsell-shell {
  background: var(--glytic-border-hover) !important;
  border: 0 !important;
  border-radius: 0 !important;
  clip-path: var(--qf-clip-card);
  box-shadow: none !important;
  filter: drop-shadow(0 20px 44px rgba(0, 0, 0, 0.55));
  position: relative;
  isolation: isolate;
}
/* Bevel-following hairline via the double-layer reveal: shell FILL = the border-hover color, and
   this inset ::before paints the bg-medium interior so the hairline follows the cut corners. Also
   REPLACES the baseline's purple ::before radial (purple purge preserved). */
.mud-dialog.premium-upsell-shell::before {
  content: '';
  position: absolute;
  inset: 1px;
  clip-path: var(--qf-clip-card);
  background: var(--glytic-bg-medium);
  z-index: -1;
  pointer-events: none;
}
.mud-dialog.premium-upsell-shell .mud-dialog-content {
  padding-top: 1.25rem;
}

/* ========================================
   PREMIUM ONBOARDING DIALOG (Composed Strike, Task 13)
   MudDialog teleports its .mud-dialog paper (title bar + content + action bar) out of
   any scoped root, so scoped ::deep -- and even bare class rules on the MudText title and
   the MudButton in <DialogActions> -- silently no-op. These global rules are keyed on the
   unique .premium-onboarding-shell class the dialog carries (only that dialog uses it).
   ======================================== */
.mud-dialog.premium-onboarding-shell .onboarding-dialog-title {
  font-family: var(--glytic-font-heading);
  /* Purple purge: teal->ember brand ramp. */
  background: linear-gradient(135deg, var(--glytic-primary), var(--forge-primary));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.mud-dialog.premium-onboarding-shell .onboarding-content { max-width: 480px; }
.mud-dialog.premium-onboarding-shell .onboarding-intro {
  font-size: 0.95rem;
  color: var(--glytic-text-secondary);
  line-height: 1.6;
  margin-bottom: 1.5rem;
}
.mud-dialog.premium-onboarding-shell .onboarding-steps {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.mud-dialog.premium-onboarding-shell .onboarding-step {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}
.mud-dialog.premium-onboarding-shell .step-number {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(var(--glytic-primary-rgb), 0.18), rgba(var(--glytic-primary-rgb), 0.06));
  border: 1px solid var(--glytic-border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--glytic-font-heading);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--glytic-primary);
}
.mud-dialog.premium-onboarding-shell .step-body {
  font-size: 0.9rem;
  color: var(--glytic-text-secondary);
  line-height: 1.5;
}
.mud-dialog.premium-onboarding-shell .step-body strong { color: var(--glytic-text-primary); }
.mud-dialog.premium-onboarding-shell .onboarding-tip {
  font-size: 0.85rem;
  color: var(--glytic-text-secondary);
  opacity: 0.8;
  font-style: italic;
}
/* Ember primary CTA (purple purge). Extra .mud-button-root reliably beats MudBlazor's
   own .mud-button-filled-primary background without !important. */
.mud-dialog.premium-onboarding-shell .mud-button-root.onboarding-start-btn {
  text-transform: none;
  font-weight: 600;
  background: var(--forge-gradient-btn);
  color: var(--qf-ink);
  border-radius: 0;
  clip-path: var(--qf-clip-btn);
  min-height: 44px;
  padding: 0 2rem;
}
.mud-dialog.premium-onboarding-shell .onboarding-start-btn .mud-button-label {
  color: var(--qf-ink);
}
.mud-dialog.premium-onboarding-shell .mud-button-root.onboarding-start-btn:focus-visible {
  outline: 2px solid var(--qf-ink);
  outline-offset: -4px;
}

/* ==========================================================================
   QfSpinner centering helpers (Composed Strike branded loader)
   Pair these containers with <QfSpinner> so the mark lands dead-centre.
   ========================================================================== */

/* Section-level: reserves vertical room and centres the spinner in its box. */
.qf-spin-center {
  min-height: 200px;
  display: grid;
  place-items: center;
  width: 100%;
}

/* Page/boot-level: full-viewport overlay, spinner centred over the page bg. */
.qf-spin-page {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 2400;
  background: var(--glytic-bg-dark);
}

/* Admin user-detail (/admin/users/{id}) mobile containment.
   MudContainer does not carry the Blazor scoped-css scope attribute, so these
   must be global (non-::deep) rules keyed on the page's own class. Keeps the
   page within a 390px viewport across all four tabs (verified at 390x844). */
.user-detail-page {
  max-width: 100%;
  overflow-x: hidden;
}
.user-detail-page .mud-table-container,
.user-detail-page .mud-simple-table {
  overflow-x: auto;
  max-width: 100%;
}
.user-detail-page table {
  min-width: 0;
}
.user-detail-page .flex-grow-1 {
  min-width: 0;
}
.user-detail-page .flex-grow-1 .mud-typography {
  overflow-wrap: anywhere;
  word-break: break-word;
}
.user-detail-page .mud-tabs-tabbar,
.user-detail-page .mud-tabs-tabbar-inner,
.user-detail-page .mud-tabs-tabbar-wrapper {
  max-width: 100%;
  overflow-x: auto;
}
.user-detail-page .mud-tabs-panels {
  max-width: 100%;
  overflow-x: hidden;
}

/* ============================================================
   ACCESSIBILITY MODES
   Classes stamped on <html> by js/qf-a11y.js from localStorage
   (set via the Accessibility sheet on quiz + flashcards).
   ============================================================ */

/* Text size: rem-based type scales with the root. */
html.qf-a11y-lg { font-size: 112.5%; }
html.qf-a11y-xl { font-size: 125%; }

/* High contrast: brighten the shared text/border tokens everywhere they cascade. */
html.qf-a11y-contrast {
  --glytic-text-secondary: #f5f5f5;
  --glytic-text-muted: #d6d6d6;
  --glytic-border: rgba(var(--glytic-primary-rgb), 0.55);
}

/* Comfort spacing: wider tracking + taller lines for easier scanning (helps
   dyslexic and low-vision readers; based on BDA readability guidance). */
html.qf-a11y-spacing body {
  letter-spacing: 0.03em;
  word-spacing: 0.08em;
}
html.qf-a11y-spacing p,
html.qf-a11y-spacing li,
html.qf-a11y-spacing blockquote,
html.qf-a11y-spacing .mud-typography-body1,
html.qf-a11y-spacing .mud-typography-body2 {
  line-height: 1.75;
}

/* Reduce motion: the forced equivalent of prefers-reduced-motion. !important is
   the established convention for reduced-motion resets (see component css). */
html.qf-a11y-motion *,
html.qf-a11y-motion *::before,
html.qf-a11y-motion *::after {
  animation-duration: 0.001s !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001s !important;
  scroll-behavior: auto !important;
}

/* Content that must reach assistive technology but not the visual layout.
   Used by the brand wordmark, where the forged Q is an image and the "Q" letter
   would otherwise be missing from the accessible name. */
.qf-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* One error-state button system. Three shipped: .qf-notfound-btn anchors on /404, a flat
   MudBlazor Color.Primary pair on the exam "not found" card, and .btn-try-again /
   .btn-go-home / .btn-contact-support in the error boundary. They now share these classes. */
.qf-error-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.6rem 1.25rem;
    border-radius: var(--glytic-border-radius-small);
    border: 1px solid var(--glytic-border);
    background: var(--glytic-card-bg);
    color: var(--glytic-text-primary);
    font-family: var(--glytic-font-heading);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 0.85rem;
    text-decoration: none;
    cursor: pointer;
    transition: border-color 0.2s ease, transform 0.2s ease;
}

.qf-error-btn:hover {
    border-color: var(--glytic-border-hover);
    transform: translateY(-1px);
}

.qf-error-btn--primary {
    background: var(--forge-gradient-btn);
    color: var(--qf-ink);
    border-color: transparent;
}

.qf-error-btn:focus-visible {
    outline: 2px solid var(--glytic-primary);
    outline-offset: -3px;
}

@media (prefers-reduced-motion: reduce) {
    .qf-error-btn { transition: none; }
    .qf-error-btn:hover { transform: none; }
}

/* Legal identity block (Copyright, Terms, Privacy, Contact). Renders only once a legal entity
   name is supplied (owner decision D3); see Client/Shared/Components/LegalIdentityBlock.razor. */
.legal-identity {
    margin: 12px 0 0;
    padding: 12px 14px;
    border: 1px solid var(--glytic-border);
    border-radius: 6px;
}

.legal-identity p {
    margin: 0 0 4px;
    color: var(--glytic-text-secondary);
}

.legal-identity-name {
    font-weight: 700;
    color: var(--glytic-text-primary);
}

/* Consent banner (EEA/UK/CH only). Bottom-anchored, above the sticky quiz bars. */
.qf-consent {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2600;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 14px 18px;
    background: var(--glytic-bg-medium);
    border-top: 1px solid var(--glytic-border);
}

.qf-consent-text {
    margin: 0;
    max-width: 720px;
    font-size: 0.85rem;
    color: var(--glytic-text-secondary);
}

.qf-consent-actions {
    display: flex;
    gap: 10px;
}

.qf-consent-btn {
    min-height: 44px;
    min-width: 44px;
    padding: 8px 16px;
    border-radius: 6px;
    border: 1px solid var(--glytic-border);
    background: transparent;
    color: var(--glytic-text-primary);
    font-size: 0.85rem;
    cursor: pointer;
}

.qf-consent-btn--accept {
    border-color: var(--glytic-primary);
    color: var(--glytic-primary);
}

/* Cookie disclosure table on /privacy. Scrolls inside its own box on narrow screens. */
.legal-cookie-table {
    display: block;
    width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    margin: 12px 0;
    font-size: 0.85rem;
}

.legal-cookie-table th,
.legal-cookie-table td {
    border: 1px solid var(--glytic-border);
    padding: 8px 10px;
    text-align: left;
    vertical-align: top;
    color: var(--glytic-text-secondary);
}

.legal-cookie-table th {
    color: var(--glytic-text-primary);
    font-weight: 700;
}

.legal-cookie-note {
    margin-top: 8px;
    font-size: 0.85rem;
    color: var(--glytic-text-secondary);
}

/* Mobile drawer close button: 44px tap target (epic X5). MudDrawer Variant="Temporary" teleports
   its aside outside MainLayout's scoped root, so this cannot live in MainLayout.razor.css
   (Codex bundle review 2026-09-03 P1). The Size.Small icon keeps its glyph size; only the hit
   area widens. */
.mobile-drawer .drawer-close-btn {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
