/* ===== SOCRATIC TUTOR — Theme-Adaptive Styles ===== */

#socratic-tutor-app {
    --st-primary: #2ea3f2;
    --st-primary-dark: #1a8cd8;
    --st-primary-light: #0f2135;
    --st-bg: #0a0a0a;
    --st-card: #151515;
    --st-text: #f0f0f0;
    --st-text2: #d0d0d0;
    /* --st-text3 used to be #6b6b6b — failed WCAG AA on the dark bg, making
       hints/subtitles/coverage text inside the chat barely legible. Bumped to
       #c0c0c0 (~7.5:1 contrast on #0a0a0a) so secondary text stays clearly
       readable while still reading as visually subordinate to --st-text. */
    --st-text3: #c0c0c0;
    --st-border: #2a2a2a;
    --st-radius: 14px;
    /* Z-index scale — kept here so layering is consistent across components.
       Toast/modal sit on top; chat itself stays in normal flow (z-index: 1). */
    --st-z-toast: 100002;
    --st-z-modal: 100010;
    font-family: inherit;
    color: var(--st-text);
    line-height: 1.7;
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 20px;
    font-size: 16px;
}

/* Color variants computed in CSS — overrides PHP fallbacks when supported */
@supports (color: color-mix(in oklch, red, blue)) {
    #socratic-tutor-app {
        --st-primary-dark: color-mix(in oklch, var(--st-primary), black 20%);
        --st-primary-light: color-mix(in oklch, var(--st-primary), var(--st-bg) 85%);
    }
}

/* Mirror of the #socratic-tutor-app variable set, scoped to #st-chat-view.
   Required because the fullscreen fallback in public.js portals #st-chat-view
   directly to <body> when the native Fullscreen API isn't available — that
   move takes the chat view OUT of #socratic-tutor-app, breaking the variable
   cascade. Without this mirror, every `var(--st-primary)` and `var(--st-bg)`
   inside the chat would fall back to its hardcoded fallback (or to nothing),
   stripping the dark theme and the brand-blue student bubble. We keep both
   scopes in sync because the chat-view always renders the same theme as the
   app container — the duplication is the price of supporting the portal.
   Admin's color override is read by the inline `style="--st-primary: ..."`
   on #socratic-tutor-app, so for full custom-color survival across portal
   moves the inline style would need to be mirrored too — out of scope for
   this fix; the fallback hex below is the safety net. */
#st-chat-view {
    --st-primary: #2ea3f2;
    --st-primary-dark: #1a8cd8;
    --st-primary-light: #0f2135;
    --st-bg: #0a0a0a;
    --st-card: #151515;
    --st-text: #f0f0f0;
    --st-text2: #d0d0d0;
    --st-text3: #c0c0c0;
    --st-border: #2a2a2a;
    --st-radius: 14px;
}
@supports (color: color-mix(in oklch, red, blue)) {
    #st-chat-view {
        --st-primary-dark: color-mix(in oklch, var(--st-primary), black 20%);
        --st-primary-light: color-mix(in oklch, var(--st-primary), var(--st-bg) 85%);
    }
}

/* Zero-specificity resets — theme CSS can override these without !important */
:where(#socratic-tutor-app) *, :where(#socratic-tutor-app) *::before, :where(#socratic-tutor-app) *::after { box-sizing: border-box; }
:where(#socratic-tutor-app) a { color: var(--st-primary); text-decoration: none; }
:where(#socratic-tutor-app) button { cursor: pointer; font-family: inherit; border: none; background: none; }
:where(#socratic-tutor-app) input, :where(#socratic-tutor-app) textarea { font-family: inherit; }

/* ===== HERO ===== */
.st-hero { text-align: center; padding: 48px 20px 28px; }
.st-hero-logo { max-height: 70px; margin-bottom: 18px; }
.st-hero-title { font-size: 2.2rem; font-weight: 700; margin: 0 0 10px; color: var(--st-primary); }
.st-hero-text { font-size: 1.1rem; color: var(--st-text2); max-width: 620px; margin: 0 auto; opacity: 0.85; }

/* ===== CATEGORY FILTER ===== */
.st-category-filter { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-bottom: 32px; }
.st-pill {
    padding: 8px 20px; border-radius: 24px; font-size: 0.9rem; font-weight: 500;
    background: var(--st-card); color: var(--st-text2); border: 1.5px solid var(--st-border);
    transition: all 0.25s; cursor: pointer;
}
.st-pill:hover { border-color: var(--st-primary); color: var(--st-primary); }
.st-pill.active { background: var(--st-primary); color: #fff; border-color: var(--st-primary); }

/* ===== SUBJECT CARDS ===== */
.st-subjects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 24px; padding-bottom: 48px; container-type: inline-size; }
.st-card {
    background: var(--st-card); border-radius: var(--st-radius); overflow: hidden;
    border: 1.5px solid var(--st-border); transition: transform 0.25s, box-shadow 0.25s;
    display: flex; flex-direction: column;
    box-shadow: 0 4px 12px rgba(0,0,0,0.06);
}
.st-card:hover { transform: translateY(-4px); box-shadow: 0 12px 32px rgba(0,0,0,0.12); }
.st-card-cover {
    height: 180px; background: var(--st-primary-light);
    display: flex; align-items: center; justify-content: center; overflow: hidden; position: relative;
}
.st-card-cover img { width: 100%; height: 100%; object-fit: cover; }
.st-card-cover .st-cover-icon { font-size: 3.5rem; opacity: 0.5; }
.st-card-cover .st-cover-icon-img { width: 80px; height: 80px; object-fit: contain; }
.st-card-badge {
    position: absolute; top: 12px; left: 12px; padding: 4px 12px; border-radius: 12px;
    font-size: 0.75rem; font-weight: 600; color: #fff; background: rgba(0,0,0,0.5);
    -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.st-card-body { padding: 20px; display: flex; flex-direction: column; flex-grow: 1; }
.st-card-body h3 { font-size: 1.2rem; font-weight: 700; margin: 0 0 6px; }
.st-card-body p {
    font-size: 0.95rem; color: var(--st-text2); flex-grow: 1; margin: 0 0 16px;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.st-card-footer {
    display: flex; align-items: center; justify-content: space-between;
    padding-top: 16px; border-top: 1px solid var(--st-border);
}
.st-card-footer .st-mat-count { font-size: 0.8rem; color: var(--st-text3); }
.st-btn-study {
    background: var(--st-primary); color: #fff; padding: 10px 24px; border-radius: 24px;
    font-size: 0.9rem; font-weight: 600; transition: background 0.25s, transform 0.15s;
}
.st-btn-study:hover { background: var(--st-primary-dark); transform: scale(1.03); }

/* ===== EMPTY STATE ===== */
.st-empty { text-align: center; padding: 60px 20px; color: var(--st-text2); }
.st-empty-icon { font-size: 3rem; margin-bottom: 14px; opacity: 0.4; }
.st-empty h3 { font-size: 1.2rem; margin: 0 0 8px; }
.st-empty p { margin: 0; }

/* ===== CHAT VIEW ===== */
/* When portaled to <body>, chat needs its own font/color context */
body > #st-chat-view {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    color: var(--st-text);
    line-height: 1.7;
    font-size: 16px;
}
body > #st-chat-view *, body > #st-chat-view *::before, body > #st-chat-view *::after { box-sizing: border-box; }
body > #st-chat-view button { cursor: pointer; font-family: inherit; border: none; background: none; }
body > #st-chat-view a { color: var(--st-primary); text-decoration: none; }

#st-chat-view {
    display: flex; flex-direction: column;
    /* Bounded embedded card. Desktop: 75vh capped at 800px so it fits in
       13" laptops. Mobile rules below tighten this further. The user can
       opt into fullscreen via #st-btn-fullscreen — see the .st-fullscreen
       block further down for the takeover styles. */
    height: 75vh;
    min-height: 500px;
    max-height: 800px;
    background: var(--st-bg); border-radius: var(--st-radius);
    overflow: hidden; border: 1.5px solid var(--st-border);
    /* Layout isolation: themes with absolute/transform/filter on ancestors
       were bleeding through the chat (page text showing behind chat content).
       z-index + isolation force a new stacking context bound to this element. */
    position: relative; z-index: 1; isolation: isolate;
}

.st-chat-header {
    padding: 14px 24px; background: var(--st-card); border-bottom: 1.5px solid var(--st-border);
    display: flex; align-items: center; gap: 14px;
}
.st-chat-back { color: var(--st-text2); font-size: 0.95rem; font-weight: 500; padding: 8px 0; transition: color 0.2s; }
.st-chat-back:hover { color: var(--st-primary); }
.st-chat-header-info { flex: 1; min-width: 0; }
.st-chat-header-info h2 { font-size: 1.1rem; font-weight: 700; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st-chat-subtitle { font-size: 0.8rem; color: var(--st-text3); }
.st-btn-icon {
    width: 36px; height: 36px; border-radius: 8px; background: var(--st-bg);
    display: flex; align-items: center; justify-content: center; font-size: 1rem;
    color: var(--st-text); transition: background 0.2s;
}
.st-btn-icon svg { fill: currentColor; }
.st-btn-icon:hover { background: var(--st-primary-light); }

/* ===== MESSAGES =====
   Bubbles get a forced !important on background + alignment because several
   WordPress themes (Astra, Kadence, GeneratePress, Twenty-Twenty-Three) ship
   `.entry-content *` resets that strip backgrounds and force flex alignment
   on descendants. Without these guards, student bubbles showed up with the
   same dark background as tutor bubbles and aligned to the left — making it
   visually impossible to tell who said what at a glance. */
.st-chat-messages { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 24px; display: flex; flex-direction: column; gap: 16px; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.st-msg { display: flex; gap: 12px; max-width: 78%; animation: stMsgIn 0.3s ease; content-visibility: auto; contain-intrinsic-size: auto 80px; }
@keyframes stMsgIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
/* Student messages: right-aligned row (avatar on the right). margin-left:auto
   is a belt-and-braces fallback for themes that override align-self.
   PORTAL-FULLSCREEN SAFETY (2.5.40): the fullscreen fallback path in
   public.js moves #st-chat-view to <body> (out of #socratic-tutor-app)
   when native Fullscreen API is unavailable. Rules scoped only under
   #socratic-tutor-app stop matching once that happens — student bubbles
   silently revert to the unscoped .st-msg-bubble default (no background,
   no right-align). To survive both states we list three selectors:
   the canonical app scope, an #st-chat-view scope (always an ancestor
   regardless of portal state), and an unscoped fallback for the
   pathological case where neither ancestor matches. */
/* HARDENED 2.5.46. Earlier ruleset was getting beaten by Divi's
   `.et_pb_*` / `.et-db` selectors on .com installs (the user's site
   uses Divi + Divi-child + an et-tb Theme Builder layout). Divi's
   resets are not just specific, they're often built with chained
   classes like `.et_pb_text_align_left * { text-align: left }`
   that match deep into our DOM. Defenses:
   - Compound `.st-msg.st-msg-user` selector raises our base
     specificity to 0,0,2,0 (vs the previous 0,0,1,0 for the bare
     `.st-msg-user`).
   - Body-scoped variant gives an even higher fallback (0,0,2,1)
     for cases where neither `#socratic-tutor-app` nor `#st-chat-view`
     is in scope.
   - All declarations forced !important. */
#socratic-tutor-app .st-msg.st-msg-user,
#st-chat-view .st-msg.st-msg-user,
body .st-msg.st-msg-user,
.st-msg.st-msg-user,
.st-msg-user {
    align-self: flex-end !important;
    flex-direction: row-reverse !important;
    margin-left: auto !important;
    margin-right: 0 !important;
    text-align: left !important;
}
.st-msg-tutor { align-self: flex-start; }
.st-msg-avatar {
    width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center;
    justify-content: center; font-size: 0.9rem; flex-shrink: 0;
}
/* Avatar colors — fallback hex values so the avatar stays visually distinct
   even when --st-primary doesn't resolve (portal-fullscreen mode escapes
   the var scope defined on #socratic-tutor-app). */
.st-msg-user .st-msg-avatar { background: var(--st-primary, #2ea3f2); color: #fff; }
.st-msg-tutor .st-msg-avatar { background: var(--st-primary-light, #0f2135); color: var(--st-primary, #2ea3f2); }
.st-msg-bubble { padding: 12px 18px; border-radius: var(--st-radius, 14px); font-size: clamp(0.9rem, 2.2vw, 1rem); word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; line-height: 1.5; color: var(--st-text, #f0f0f0); overflow-x: auto; }
/* Force the student bubble to the brand color + white text. Triple-scoped
   (see "PORTAL-FULLSCREEN SAFETY" above) so the rule survives the chat
   view being portaled to <body>. !important here ALSO protects against
   `.entry-content *` background resets in WP themes. var() includes a
   hardcoded fallback color so the bubble stays branded even when the
   custom property doesn't resolve in portaled state. */
/* HARDENED 2.5.46 — same Divi-defense rationale as `.st-msg.st-msg-user`
   above. Compound class + body fallback raises specificity beyond what
   `.et_pb_*` resets can reach with their typical class chains. Explicit
   `background-color` in ADDITION to the shorthand `background` because
   Divi has both `background` and `background-color` resets and !important
   on a shorthand doesn't always win against !important on a longhand
   property in the same cascade tie. Hardcoded hex as a primary value
   (no var() indirection that could collapse if --st-primary fails to
   resolve in some portaled state). border-bottom-right-radius and
   border:none also get !important so a theme's `* { border: 1px solid }`
   reset can't leak a 1px border around our pill. */
#socratic-tutor-app .st-msg.st-msg-user .st-msg-bubble,
#st-chat-view .st-msg.st-msg-user .st-msg-bubble,
body .st-msg.st-msg-user .st-msg-bubble,
.st-msg.st-msg-user .st-msg-bubble,
.st-msg-user .st-msg-bubble {
    /* var() with hardcoded fallback (2.5.50). Previously this was a raw
       hardcoded #2ea3f2 so the bubble survived even when --st-primary
       failed to resolve in portal-fullscreen mode, but that meant an
       admin's custom brand color never reached the student bubble. The
       JS path in addMsg() now resolves --st-primary at render time and
       writes the resolved value inline, so this CSS rule no longer
       needs the hardcoded hex to win — it's kept as the static-defense
       layer (e.g. resumed conversations, where the bubble's HTML was
       persisted before the JS resolver added inline styles). */
    background: var(--st-primary, #2ea3f2) !important;
    background-color: var(--st-primary, #2ea3f2) !important;
    color: #ffffff !important;
    border: none !important;
    border-radius: 14px !important;
    border-bottom-right-radius: 4px !important;
    padding: 12px 18px !important;
}
#socratic-tutor-app .st-msg.st-msg-tutor .st-msg-bubble,
#st-chat-view .st-msg.st-msg-tutor .st-msg-bubble,
body .st-msg.st-msg-tutor .st-msg-bubble,
.st-msg.st-msg-tutor .st-msg-bubble,
.st-msg-tutor .st-msg-bubble {
    background: var(--st-card, #151515) !important;
    background-color: var(--st-card, #151515) !important;
    border: 1.5px solid var(--st-border, #2a2a2a) !important;
    border-bottom-left-radius: 4px !important;
    color: var(--st-text, #f0f0f0) !important;
}

/* Markdown in messages */
.st-msg-bubble strong { font-weight: 700; }
/* Bold text in TUTOR messages is colored with the brand primary so that
   the theory anchors (definitions, key principles, "the rule is..." phrases)
   stand out visually from the surrounding Socratic dialogue. Restricted to
   .st-msg-tutor specifically — the student's own bubbles (white-on-blue)
   would lose contrast if their bolds were also blue.
   Scoped under #socratic-tutor-app and forced with !important to survive
   theme resets like `strong { color: inherit !important }` that some WP
   themes ship (Astra/Kadence/etc were both observed wiping the primary
   color in the wild). The plugin's color cascade is intentional UX, not
   accidental typography drift — winning the cascade fight is correct. */
#socratic-tutor-app .st-msg-tutor .st-msg-bubble strong,
#socratic-tutor-app .st-msg-tutor .st-msg-bubble b {
    color: var(--st-primary) !important;
}
.st-msg-bubble em { font-style: italic; }
.st-msg-bubble code { background: rgba(0,0,0,0.06); padding: 2px 6px; border-radius: 4px; font-size: 0.88em; }
.st-msg-user .st-msg-bubble code { background: rgba(255,255,255,0.2); }
.st-msg-bubble hr { border: none; border-top: 1.5px solid var(--st-border); margin: 8px 0; }
.st-msg-user .st-msg-bubble hr { border-top-color: rgba(255,255,255,0.3); }
/* Tight paragraph rhythm. The model is also instructed (in the system prompt)
   to produce dense paragraphs rather than one-sentence-per-line, but we keep
   the CSS conservative as a second line of defense — a model that ignores the
   instruction still won't generate a wall of half-empty lines. */
.st-msg-bubble p { margin: 0 0 0.5em; }
.st-msg-bubble p:last-child { margin-bottom: 0; }
.st-msg-bubble p:empty { display: none; }
.st-msg-bubble br + br { display: none; } /* collapse double <br> into single linebreak */
.st-msg-bubble ul, .st-msg-bubble ol { margin: 0.4em 0; padding-left: 20px; }
.st-msg-bubble li { margin-bottom: 0; line-height: 1.45; }
.st-msg-bubble li + li { margin-top: 0.15em; }
/* Numbered list rendered as st-md-oli divs (not <ol>): tighten the gap
   between consecutive items the same way native <li> does. */
.st-msg-bubble .st-md-oli + .st-md-oli { margin-top: 0.15em; }
.st-msg-bubble hr { margin: 8px 0; }
.st-msg-bubble .st-md-oli { margin: 2px 0; padding-left: 4px; }
.st-msg-bubble .st-md-num { font-weight: 700; color: var(--st-primary); }
/* Markdown headers (#/##/### inside tutor bubbles). Rendered as styled
   divs rather than <h1>/<h2>/<h3> so they sit naturally in the chat flow
   without breaking the paragraph cascade. Color uses the brand primary
   to match the rest of the theory highlighting. */
.st-msg-bubble .st-md-h {
    font-weight: 700;
    color: var(--st-primary);
    margin: 0.6em 0 0.3em;
    line-height: 1.3;
}
.st-msg-bubble .st-md-h1 { font-size: 1.25em; }
.st-msg-bubble .st-md-h2 { font-size: 1.15em; }
.st-msg-bubble .st-md-h3 { font-size: 1.05em; }
.st-msg-bubble .st-md-h4 { font-size: 1em; }
.st-msg-bubble .st-md-table { width: 100%; border-collapse: collapse; margin: 8px 0; font-size: 0.9em; }
.st-msg-bubble .st-md-table th,
.st-msg-bubble .st-md-table td { padding: 6px 10px; border: 1px solid var(--st-border); text-align: left; }
.st-msg-bubble .st-md-table th { background: rgba(255,255,255,0.05); font-weight: 700; }
.st-msg-user .st-msg-bubble .st-md-table th,
.st-msg-user .st-msg-bubble .st-md-table td { border-color: rgba(255,255,255,0.2); }
.st-msg-user .st-msg-bubble .st-md-table th { background: rgba(255,255,255,0.1); }

/* ===== COPY BUTTON ===== */
.st-btn-copy {
    position: absolute; top: 6px; right: 6px;
    width: 28px; height: 28px; border-radius: 6px;
    background: rgba(0,0,0,0.15); color: var(--st-text);
    display: flex; align-items: center; justify-content: center;
    font-size: 0.8rem; cursor: pointer; opacity: 0;
    transition: opacity 0.2s, background 0.2s; border: none; padding: 0;
}
.st-msg-tutor:hover .st-btn-copy { opacity: 1; }
.st-btn-copy:hover { background: rgba(0,0,0,0.3); }
.st-msg-tutor { position: relative; }

/* ===== OPTION BUTTONS ===== */
.st-option-buttons {
    display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px;
    padding-top: 14px; border-top: 1px solid var(--st-border);
}
.st-option-btn {
    background: var(--st-primary-light); color: var(--st-primary); border: 1.5px solid var(--st-primary);
    padding: 8px 18px; border-radius: 20px; font-size: 0.88rem; font-weight: 600;
    cursor: pointer; transition: all 0.2s;
}
.st-option-btn:hover {
    background: var(--st-primary); color: #fff; transform: scale(1.03);
}

/* Letter-prefixed options (A/B/C/D): vertical stack with a circular letter
   chip on the left and the option label to its right. Reads like a real
   multiple-choice list and gives a big tap target on touch screens. */
.st-option-buttons-letters {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
}
.st-option-btn-letter {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 14px;
    border-radius: 12px;
    text-align: left;
    background: var(--st-bg);
    color: #fff;
    border: 1.5px solid var(--st-border);
    font-weight: 500;
    font-size: 0.92rem;
    width: 100%;
}
.st-option-btn-letter:hover {
    border-color: var(--st-primary);
    background: var(--st-primary-light);
    transform: none;
}
.st-option-btn-letter .st-option-letter {
    flex-shrink: 0;
    width: 30px; height: 30px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--st-primary); color: #fff;
    font-weight: 700; font-size: 0.95rem;
    transition: background 0.2s;
}
.st-option-btn-letter .st-option-label {
    flex: 1;
    color: #fff;
    line-height: 1.4;
}
.st-option-btn-letter:hover .st-option-letter {
    background: var(--st-primary-dark);
}

/* ===== WELCOME ===== */
.st-welcome { text-align: center; padding: 36px 20px; color: var(--st-text2); }
.st-welcome-icon { font-size: 3rem; margin-bottom: 14px; }
.st-welcome h2 { font-size: 1.3rem; font-weight: 700; margin: 0 0 8px; }
.st-welcome p { font-size: 1rem; max-width: 400px; margin: 0 auto; }

/* ===== START SCREEN =====
   CENTERING — DEFENDED (2.5.45). The start-screen centering broke on
   one student install after the 2.5.40 portal-fullscreen CSS additions
   crossed paths with a theme rule that re-aliased `.st-start-screen`
   to display:block. The original rule had no !important / specificity
   defenses, so any theme reset that targeted the descendant elements
   could collapse it. Triple-scoped + !important is the same belt-and-
   braces pattern we already use for the student bubble (see
   #socratic-tutor-app .st-msg-user above). */
#socratic-tutor-app .st-start-screen,
#st-chat-view .st-start-screen,
.st-start-screen {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center !important;
    padding: 60px 20px;
    flex: 1;
    min-height: 50vh;
}
.st-start-icon { font-size: 4rem; margin-bottom: 20px; }
.st-start-subject-icon { width: 80px; height: 80px; object-fit: contain; border-radius: 12px; margin-bottom: 20px; }
.st-start-screen h2 { font-size: 1.5rem; font-weight: 700; margin: 0 0 12px; color: var(--st-text); }
.st-start-screen p { font-size: 1rem; color: var(--st-text2); max-width: 420px; margin: 0 0 32px; opacity: 0.85; line-height: 1.6; }
.st-btn-start {
    background: var(--st-primary); color: #fff; padding: 14px 32px; border-radius: 28px;
    font-size: 1.1rem; font-weight: 700; cursor: pointer; border: none;
    transition: background 0.25s, transform 0.15s; font-family: inherit;
    /* Inline-flex so the icon span and label span align on the same baseline,
       with a small gap between them. Without this each <span> would still
       flow inline-block but the emoji baseline can sit visibly off vs. the
       text — flex auto-centers them. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}
.st-btn-start:hover { background: var(--st-primary-dark); transform: scale(1.04); }
/* Icon sits slightly bigger than the label so it reads as a visual anchor
   without dominating; line-height: 1 trims the emoji's intrinsic top/bottom
   padding so the button stays the same height as the icon-less version. */
.st-btn-start-icon {
    font-size: 1.25rem;
    line-height: 1;
}
.st-btn-start-label {
    line-height: 1.2;
}
/* Wrapper for the three mode-start buttons on the start screen. Horizontal
   row on desktop so the student sees the choices side-by-side at a glance;
   wraps to a second row on narrow widths and stacks on phone-sized viewports.

   Spacing strategy: per-button `margin`, NOT flex `gap`. Reasons:
     - `gap` on flex containers needs Safari ≥ 14.1, and some in-app
       browsers / older mobile WebKit still skip it.
     - Some host themes apply `button { margin: 0 }` as part of their CSS
       reset. The `!important` on the button margin defends against that
       — there's no other way to guarantee the override without scoping
       every rule under `#socratic-tutor-app` for higher specificity.
   With margin: 10px 16px each side, adjacent buttons get 32px horizontal
   air and 20px vertical when the row wraps. */
.st-start-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    margin: 0 auto;
}
.st-start-actions .st-btn-start {
    margin: 10px 16px !important;
}
.st-btn-resume {
    background: transparent; color: var(--st-primary); padding: 10px 28px; border-radius: 24px;
    font-size: 0.9rem; font-weight: 600; cursor: pointer; margin-top: 16px;
    border: 1.5px solid var(--st-primary); transition: all 0.25s; font-family: inherit;
}
.st-btn-resume:hover { background: var(--st-primary); color: #fff; }

/* ===== FULLSCREEN (opt-in via the toolbar button) =====
   Activated only when JS adds .st-fullscreen. Body scroll is locked via
   body.st-fullscreen-active so the page behind doesn't peek through.

   Top-offset strategy: --st-fs-top-offset is set by JS (see public.js
   detectTopOverlayHeight()) to the height of any sticky/fixed top bar in
   the host theme — site nav, WP admin bar, sticky banners. The chat view
   sits BELOW that bar so the user's site navigation stays accessible.
   Default is 0 when the variable isn't set (e.g. native Fullscreen API path
   where the browser hides the host page entirely).

   Note on stacking: a host theme that puts `transform`, `filter` or
   `backdrop-filter` on an ancestor of #socratic-tutor-app would scope this
   position:fixed to that ancestor (CSS spec). The JS fallback portals
   #st-chat-view to <body> before adding this class — that's why position:
   fixed reliably resolves to the viewport here. */
#st-chat-view.st-fullscreen {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    top: var(--st-fs-top-offset, 0px) !important;
    width: 100vw !important;
    height: calc(100vh - var(--st-fs-top-offset, 0px)) !important;
    height: calc(100dvh - var(--st-fs-top-offset, 0px)) !important;
    min-height: calc(100vh - var(--st-fs-top-offset, 0px)) !important;
    min-height: calc(100dvh - var(--st-fs-top-offset, 0px)) !important;
    max-height: calc(100vh - var(--st-fs-top-offset, 0px)) !important;
    max-height: calc(100dvh - var(--st-fs-top-offset, 0px)) !important;
    border-radius: 0 !important;
    /* z-index sits BELOW typical theme nav z-indexes (which are usually
       9999-99999) so the host menu remains clickable. The chat itself
       claims the visible viewport area below the nav, which is what the
       --st-fs-top-offset above guarantees. */
    z-index: 9990;
    margin: 0 !important;
    background: var(--st-bg) !important;
}

/* Body scroll lock while the chat is fullscreen. Cleanup is handled in JS
   on toggle, ESC key, and chat-back. */
body.st-fullscreen-active { overflow: hidden !important; }

/* Safe-area insets for fullscreen on notch / island devices. */
#st-chat-view.st-fullscreen .st-chat-header {
    padding-top: calc(14px + env(safe-area-inset-top, 0px));
    padding-left: calc(24px + env(safe-area-inset-left, 0px));
    padding-right: calc(24px + env(safe-area-inset-right, 0px));
}
#st-chat-view.st-fullscreen .st-chat-input-area {
    padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    padding-left: calc(24px + env(safe-area-inset-left, 0px));
    padding-right: calc(24px + env(safe-area-inset-right, 0px));
}

/* ===== COVERAGE INDICATOR (removed in 2.5.31) =====
   The separate "Level X/Y" progress bar under the subject name was
   redundant with the header % pill, which carries the same signal more
   cleanly. Rule kept as a defensive `display: none` so any stray
   leftover node (from an older cached client / DOM) collapses silently
   instead of jumping into the header layout. */
.st-coverage-indicator,
#st-coverage-indicator { display: none !important; }

/* ===== REGENERATE BUTTON ===== */
#st-btn-regenerate {
    font-size: 0.85rem;
    opacity: 0.7;
    transition: opacity 0.2s;
}
#st-btn-regenerate:hover { opacity: 1; }

/* ===== TYPING ===== */
.st-typing { display: none; padding: 12px 16px; background: var(--st-card); border: 1.5px solid var(--st-border); border-radius: var(--st-radius); border-bottom-left-radius: 4px; margin: 0 24px; align-self: flex-start; }
.st-typing.active { display: flex; gap: 5px; align-items: center; }
.st-typing-dot { width: 8px; height: 8px; background: var(--st-text3); border-radius: 50%; animation: stBounce 1.4s infinite; }
.st-typing-dot:nth-child(2) { animation-delay: 0.2s; }
.st-typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes stBounce { 0%,60%,100% { transform: translateY(0); } 30% { transform: translateY(-6px); } }

/* ===== INPUT ===== */
.st-chat-input-area { padding: 16px 24px; background: var(--st-card); border-top: 1.5px solid var(--st-border); }
.st-chat-input-wrapper { display: flex; align-items: flex-end; gap: 12px; max-width: 780px; margin: 0 auto; }
.st-chat-input {
    flex: 1; border: 1.5px solid var(--st-border); border-radius: var(--st-radius);
    padding: 12px 16px; font-size: 1rem; resize: none; min-height: 44px; max-height: 120px;
    outline: none; color: #fff !important; background: transparent; transition: border-color 0.2s;
}
.st-chat-input:focus { border-color: var(--st-primary); box-shadow: 0 0 0 3px rgba(46,163,242,0.12); }
.st-chat-input::placeholder { color: var(--st-text3); }
.st-chat-input:disabled { opacity: 0.5; cursor: not-allowed; }
.st-btn-send {
    width: 44px; height: 44px; background: var(--st-primary); color: #fff; border-radius: 50%;
    display: flex; align-items: center; justify-content: center; font-size: 1.1rem;
    flex-shrink: 0; transition: background 0.2s;
}
.st-btn-send:hover { background: var(--st-primary-dark); }
.st-btn-send:disabled { background: var(--st-border); cursor: not-allowed; }
/* .st-btn-voice / .st-voice-active rules were removed in v2.0.0 along with
   the Web Speech voice feature. The .st-btn-voice element no longer renders. */
.st-input-hint { text-align: center; font-size: 0.75rem; color: var(--st-text3); margin-top: 8px; }

/* ===== TIME LIMIT ===== */
.st-time-limit-msg {
    text-align: center; padding: 40px 20px; margin: 20px 0;
    background: var(--st-card); border-radius: var(--st-radius);
    border: 2px dashed var(--st-border);
}
.st-time-limit-icon { font-size: 3rem; margin-bottom: 12px; }
.st-time-limit-msg h3 { font-size: 1.2rem; margin: 0 0 8px; color: var(--st-primary); }
.st-time-limit-msg p { font-size: 0.95rem; color: var(--st-text2); margin: 0; }

/* ===== TOAST ===== */
.st-toast {
    position: fixed; bottom: 24px; right: 24px; padding: 12px 22px; color: #fff;
    border-radius: 10px; font-size: 0.9rem; z-index: var(--st-z-toast, 100002);
    animation: stToastIn 0.3s ease, stToastOut 0.3s ease 2.7s forwards;
    box-shadow: 0 4px 16px rgba(0,0,0,0.2);
}
@keyframes stToastIn { from { opacity: 0; transform: translateY(10px); } }
@keyframes stToastOut { to { opacity: 0; transform: translateY(10px); } }
.st-toast-error { background: #e53e3e; }
.st-toast-success { background: #38a169; }
.st-toast-info { background: #3182ce; }

/* ===== RESPONSIVE ===== */

/* -- TABLET (max 768px) -- */
@media (max-width: 768px) {
    #socratic-tutor-app { padding: 0 12px; font-size: 15px; }
    .st-hero-title { font-size: 1.5rem; }
    .st-hero { padding: 20px 12px 16px; }
    .st-hero-text { font-size: 0.95rem; }
    .st-hero-logo { max-height: 50px; margin-bottom: 12px; }

    /* Category pills: horizontal scroll instead of wrapping */
    .st-category-filter {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding: 0 12px 12px;
        gap: 8px;
        scroll-snap-type: x mandatory;
    }
    .st-category-filter::-webkit-scrollbar { display: none; }
    .st-pill { white-space: nowrap; flex-shrink: 0; scroll-snap-align: start; padding: 10px 20px; min-height: 44px; display: flex; align-items: center; }

    /* Cards: single column, compact */
    .st-subjects-grid { grid-template-columns: 1fr; gap: 14px; padding-bottom: 32px; }
    .st-card-cover { height: 150px; }
    .st-card-body { padding: 16px; }
    .st-card-body h3 { font-size: 1.1rem; }
    .st-card-body p { font-size: 0.9rem; margin-bottom: 12px; -webkit-line-clamp: 2; }
    .st-btn-study { padding: 12px 24px; min-height: 44px; font-size: 0.95rem; }
    .st-card-footer .st-mat-count { font-size: 0.78rem; }

    .st-msg { max-width: 90%; }

    /* ----- Mobile embedded chat (XL card, NO fullscreen) -----
       Mobile has NO fullscreen toggle (it kept breaking layouts on certain
       host themes). To compensate, the conversation board is intentionally
       LARGER than the viewport (~130% of screen height). The user scrolls
       the PAGE to access the full chat — header at top, messages middle,
       input near the bottom — instead of scrolling inside a small window.
       This trades "everything visible at once" for "room for many messages". */
    #st-chat-view {
        height: 130vh;
        min-height: 900px;
        max-height: 1600px;
        background: var(--st-bg) !important;
    }
    /* Hide all auxiliary toolbar/input buttons on mobile — INCLUDING fullscreen.
       Power features (concepts, summary, export, new chat, regenerate) are
       desktop-only. Mobile header keeps just: title, send and (if there's a
       catalog) the back arrow. */
    #st-btn-concepts,
    #st-btn-summary,
    #st-btn-export,
    #st-btn-fullscreen,
    #st-btn-new-chat,
    #st-btn-regenerate {
        display: none !important;
    }
    /* Compact start screen so it fits inside the smaller embedded box */
    .st-start-screen {
        padding: 24px 16px;
        min-height: 0;
    }
    .st-start-screen p {
        margin-bottom: 16px;
    }

    /* Mobile spacing tweaks for header/messages/input */
    .st-chat-messages { padding: 16px; gap: 12px; }
    .st-chat-input-area {
        padding: 12px 16px;
        padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    }
    .st-chat-header {
        padding: 12px 16px;
        padding-top: calc(12px + env(safe-area-inset-top, 0px));
        min-height: 52px;
    }

    /* Touch-friendly: all interactive elements min 44px */
    .st-btn-send { width: 48px; height: 48px; }
    .st-btn-icon { width: 44px; height: 44px; }
    .st-chat-back { padding: 12px 0; min-height: 44px; display: flex; align-items: center; font-size: 1rem; }
    .st-option-btn { padding: 12px 20px; font-size: 0.95rem; min-height: 44px; }
    .st-chat-input { font-size: 16px; min-height: 48px; }

    /* Toast repositioned for mobile */
    .st-toast { bottom: auto; top: 12px; right: 12px; left: 12px; text-align: center; }

    /* Copy button always visible on touch */
    .st-btn-copy { opacity: 0.7; }

    /* Suggested questions: inside messages area on mobile (scrollable, not fixed) */
    .st-suggested-questions {
        flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
        padding: 8px 0; gap: 6px; border-top: none; background: transparent;
    }
    .st-suggested-label { display: none; }
    .st-suggested-btn { white-space: nowrap; flex-shrink: 0; min-height: 36px; padding: 6px 14px; font-size: 0.8rem; }

    /* Scrollbar hidden on mobile */
    .st-chat-messages::-webkit-scrollbar { display: none; }
    .st-chat-messages { -ms-overflow-style: none; scrollbar-width: none; }

    /* Start screen compact */
    .st-start-screen { padding: 40px 16px; min-height: 40vh; }
    .st-start-icon { font-size: 3rem; }
    .st-start-subject-icon { width: 60px; height: 60px; }
    .st-start-screen h2 { font-size: 1.3rem; }
    .st-start-screen p { font-size: 0.92rem; margin-bottom: 24px; }
    .st-btn-start { padding: 14px 40px; font-size: 1rem; min-height: 48px; }
    .st-btn-resume { min-height: 44px; padding: 10px 24px; }

    /* Empty state compact */
    .st-empty { padding: 40px 16px; }
}

/* (Removed: previously forced fullscreen on mobile — chat now stays embedded in page) */

/* -- MOBILE SMALL (max 480px) -- */
@media (max-width: 480px) {
    .st-hero-title { font-size: 1.3rem; }
    .st-hero-text { font-size: 0.9rem; }
    .st-hero { padding: 16px 8px 12px; }
    .st-card-cover { height: 120px; }
    .st-msg-bubble { font-size: 0.92rem; padding: 10px 14px; }
    .st-msg-avatar { width: 28px; height: 28px; font-size: 0.75rem; }
    .st-msg { gap: 8px; }
    .st-chat-header-info h2 { font-size: 1rem; }
    .st-welcome h2 { font-size: 1.1rem; }
    .st-welcome-icon { font-size: 2.5rem; }
    /* Cards: horizontal layout on small phones */
    .st-card { flex-direction: row; }
    .st-card:hover { transform: none; }
    .st-card-cover { height: auto; width: 100px; min-height: 100px; flex-shrink: 0; border-radius: var(--st-radius) 0 0 var(--st-radius); }
    .st-card-body { padding: 12px; }
    .st-card-body h3 { font-size: 1rem; }
    .st-card-body p { -webkit-line-clamp: 2; font-size: 0.85rem; margin-bottom: 8px; }
    .st-card-footer { padding-top: 8px; }
    .st-btn-study { padding: 8px 16px; font-size: 0.85rem; }
    .st-card-badge { top: 6px; left: 6px; font-size: 0.65rem; padding: 2px 8px; }
}

/* -- MOBILE TINY (max 360px) — very small phones -- */
@media (max-width: 360px) {
    .st-hero-title { font-size: 1.15rem; }
    .st-hero-text { font-size: 0.85rem; }
    .st-card-cover { width: 80px; min-height: 80px; }
    .st-card-body h3 { font-size: 0.95rem; }
    .st-card-body { padding: 10px; }
    .st-card-body p { display: none; }
    .st-card-footer { border-top: none; padding-top: 4px; }
    .st-card-footer .st-mat-count { display: none; }
    .st-btn-study { width: 100%; }
    .st-chat-input { font-size: 16px; padding: 10px 12px; }
    .st-msg-bubble { font-size: 0.88rem; padding: 8px 12px; }
    .st-option-btn { padding: 10px 14px; font-size: 0.85rem; }
    .st-pill { font-size: 0.8rem; padding: 8px 14px; }
}

/* -- LANDSCAPE MOBILE -- */
@media (max-height: 500px) and (orientation: landscape) {
    /* In landscape on a phone there's barely any vertical room — let the chat
       size to whatever the embedded box can give it (already bounded above). */
    #st-chat-view {
        min-height: 320px;
        max-height: 90vh;
    }
    .st-chat-header { padding: 8px 16px; min-height: 44px; }
    .st-chat-header-info h2 { font-size: 0.95rem; }
    .st-chat-subtitle { display: none; }
    .st-chat-messages { padding: 8px 16px; gap: 8px; }
    .st-chat-input-area { padding: 8px 16px; }
    .st-start-screen { padding: 20px; min-height: auto; }
    .st-start-icon, .st-start-subject-icon { display: none; }
    .st-start-screen h2 { font-size: 1.1rem; margin-bottom: 8px; }
    .st-start-screen p { margin-bottom: 16px; }
}

/* ===== SUGGESTED QUESTIONS ===== */
.st-suggested-questions {
    display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
    padding: 10px 24px; background: var(--st-card); border-top: 1px solid var(--st-border);
}
.st-suggested-label { font-size: 0.78rem; color: var(--st-text3); margin-right: 4px; }
.st-suggested-btn {
    background: var(--st-bg); color: var(--st-text2); border: 1.5px solid var(--st-border);
    padding: 6px 16px; border-radius: 18px; font-size: 0.82rem; cursor: pointer;
    transition: all 0.2s; font-family: inherit;
}
.st-suggested-btn:hover {
    border-color: var(--st-primary); color: var(--st-primary); background: var(--st-primary-light);
}

/* ===== KATEX OVERRIDES ===== */
.st-msg-bubble .katex { font-size: 1em; }
.st-msg-bubble .katex-display { margin: 12px 0; overflow-x: auto; overflow-y: hidden; }

/* ===== ACCESSIBILITY ===== */

/* Screen reader only */
.st-sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* Focus visible for keyboard navigation */
#socratic-tutor-app :focus-visible {
    outline: 2px solid var(--st-primary);
    outline-offset: 2px;
}
#socratic-tutor-app button:focus:not(:focus-visible),
#socratic-tutor-app textarea:focus:not(:focus-visible) {
    outline: none;
}

/* Reduced motion: disable all animations */
@media (prefers-reduced-motion: reduce) {
    #socratic-tutor-app *, #socratic-tutor-app *::before, #socratic-tutor-app *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    .st-card:hover { transform: none; }
    .st-btn-study:hover { transform: none; }
    .st-btn-start:hover { transform: none; }
    .st-option-btn:hover { transform: none; }
}

/* High contrast adjustments */
@media (prefers-contrast: high) {
    .st-msg-tutor .st-msg-bubble { border-width: 2px; }
    .st-pill { border-width: 2px; }
    .st-chat-input { border-width: 2px; }
    .st-btn-study { border: 2px solid #fff; }
    .st-card { border-width: 2px; }
}

/* ===== REMAINING TIME / SECTION INDICATOR ===== */
.st-remaining-time,
.st-remaining-pct {
    font-size: 0.7rem; color: var(--st-text3); white-space: nowrap;
    padding: 2px 8px; background: var(--st-border); border-radius: 10px;
    display: inline-block; margin-top: 2px;
    transition: background 0.4s ease, color 0.4s ease, box-shadow 0.4s ease, transform 0.4s ease;
}
/* The section indicator (2.5.52+) reads "📘 Sección 2 de 5" — typically a
   bit longer than the legacy "📘 42%" so widen the chip slightly and let
   the layout flex around it. */
.st-remaining-pct { margin-left: 6px; font-weight: 600; }
.st-remaining-caution { color: #f6ad55; background: rgba(246,173,85,0.15); }
.st-remaining-warning { color: #fc8181; background: rgba(252,129,129,0.15); animation: stPulse 2s ease-in-out infinite; }
/* Milestone color cues — green near completion, amber midway. Same hues
   as the legacy percentage pill so the visual language stays consistent. */
.st-remaining-pct-near-done { color: #38a169; background: rgba(56,161,105,0.15); }
.st-remaining-pct-midway { color: #f6ad55; background: rgba(246,173,85,0.15); }
@keyframes stPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.6; } }

/* Golden-pulse celebration (2.5.52+). Fires for ~2s when the student
   crosses a section boundary (updateRemainingPercentage(true)). The
   `box-shadow` glow + a subtle scale-up draw the eye to the chip without
   covering the chat. Uses gold (#ffd700) tones independent of --st-primary
   so the celebration reads the same regardless of the admin's brand color
   — the brand color reflects "this plugin", gold reflects "achievement". */
.st-remaining-pct-pulse {
    animation: stSectionPulse 2.2s ease-out 1;
    /* These !important overrides win against the near-done / midway color
       classes during the animation so the gold pulse is visible even when
       the student is at e.g. 80%+ progress (which would otherwise leave
       the chip green). The animation resets the chip to its idle state. */
    color: #1a1a1a !important;
    background: linear-gradient(135deg, #fff3a8 0%, #ffd700 50%, #ffb800 100%) !important;
    box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.85);
    font-weight: 700;
}
@keyframes stSectionPulse {
    0%   { transform: scale(1);     box-shadow: 0 0 0 0    rgba(255, 215, 0, 0.85); }
    20%  { transform: scale(1.18);  box-shadow: 0 0 0 6px  rgba(255, 215, 0, 0.55); }
    45%  { transform: scale(1.08);  box-shadow: 0 0 0 12px rgba(255, 215, 0, 0.25); }
    70%  { transform: scale(1.12);  box-shadow: 0 0 0 18px rgba(255, 215, 0, 0.10); }
    100% { transform: scale(1);     box-shadow: 0 0 0 24px rgba(255, 215, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
    /* Honor the user's reduced-motion preference: no scale / shadow
       animation, just a brief gold-tint background fade. Same duration
       so the JS class-removal timeout still lines up. */
    .st-remaining-pct-pulse { animation: none; }
}

/* ===== SCROLLBAR ===== */
.st-chat-messages::-webkit-scrollbar { width: 6px; }
.st-chat-messages::-webkit-scrollbar-track { background: transparent; }
.st-chat-messages::-webkit-scrollbar-thumb { background: var(--st-border); border-radius: 3px; }

/* ===== EXAM MODE — strict flow =====
   Hide every auxiliary control that would let the student exit the
   question-by-question loop or seek hints. Matches the exam prompt's
   "NEVER explain, hint or accept open questions" contract. Kept as CSS
   (not JS) so the UI is locked in even if a tampered client tries to
   re-show them programmatically — the data-attribute is what gates it. */
#st-chat-view[data-exam-mode="1"] #st-btn-concepts,
#st-chat-view[data-exam-mode="1"] #st-btn-summary,
#st-chat-view[data-exam-mode="1"] #st-btn-regenerate,
#st-chat-view[data-exam-mode="1"] #st-btn-new-chat,
#st-chat-view[data-exam-mode="1"] .st-suggested-questions {
    display: none !important;
}

/* TEST_ONLY MODE — laxer. The student is allowed brief questions between
   items, so suggestions stay; only regenerate is hidden (re-rolling the
   same question with a different wording is essentially cheating). */
#st-chat-view[data-test-only="1"] #st-btn-regenerate {
    display: none !important;
}

/* ===== PRINT ===== */
/* When the user prints a chat page (Ctrl+P), hide the chrome (header buttons,
   input area, toolbar, suggestion pills, fullscreen button) and flatten the
   dark theme to white-on-black so the printer doesn't burn ink on the
   bg-dark gradient. The message bubbles themselves print fine. */
@media print {
    .st-chat-header .st-btn-icon,
    .st-chat-back,
    .st-chat-input-area,
    .st-typing,
    .st-toast,
    .st-suggested-questions,
    .st-option-buttons,
    .st-btn-copy,
    #st-remaining-time,
    #st-remaining-pct,
    #st-coverage-indicator { display: none !important; }
    #socratic-tutor-app,
    #st-chat-view,
    .st-chat-messages,
    .st-msg-bubble {
        background: #fff !important;
        color: #000 !important;
        border-color: #999 !important;
        box-shadow: none !important;
        max-height: none !important;
        height: auto !important;
        overflow: visible !important;
    }
    .st-msg-bubble { page-break-inside: avoid; }
    .st-msg-user .st-msg-bubble { background: #f0f0f0 !important; color: #000 !important; }
}

/* ===== DASHBOARD ===== */
#socratic-dashboard-app {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    color: var(--st-text, #f0f0f0); max-width: 900px; margin: 0 auto; padding: 0 20px;
    /* Same WCAG-AA-friendly greys as #socratic-tutor-app — keeps the dashboard
       legible on the dark background instead of the old #6b6b6b that washed
       out completely against #0a0a0a. */
    --st-bg: #0a0a0a; --st-card: #151515; --st-text: #f0f0f0; --st-text2: #d0d0d0;
    --st-text3: #c0c0c0; --st-border: #2a2a2a; --st-radius: 14px;
}
.st-dashboard-loading { text-align: center; padding: 60px; color: var(--st-text3); }
.st-dashboard-summary {
    display: flex; gap: 16px; margin-bottom: 32px; flex-wrap: wrap;
}
.st-dash-stat {
    flex: 1; min-width: 120px; background: var(--st-card); border: 1.5px solid var(--st-border);
    border-radius: var(--st-radius); padding: 20px; text-align: center;
}
.st-dash-stat-num { display: block; font-size: 1.5rem; font-weight: 700; color: var(--st-primary, #2ea3f2); }
.st-dash-stat-label { font-size: 0.8rem; color: var(--st-text3); }
.st-dashboard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }
.st-dash-card {
    background: var(--st-card); border: 1.5px solid var(--st-border); border-radius: var(--st-radius);
    padding: 20px; transition: transform 0.2s;
}
.st-dash-card:hover { transform: translateY(-2px); }
.st-dash-card-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.st-dash-card-header h3 { margin: 0; font-size: 1.1rem; font-weight: 700; color: var(--st-text); }
.st-dash-card-header small { color: var(--st-text3); font-size: 0.8rem; }
.st-dash-icon { width: 40px; height: 40px; border-radius: 8px; object-fit: contain; }
.st-dash-emoji { font-size: 2rem; }
.st-dash-progress {
    height: 6px; background: var(--st-border); border-radius: 3px; overflow: hidden; margin-bottom: 10px;
}
.st-dash-progress-fill { height: 100%; background: var(--st-primary, #2ea3f2); border-radius: 3px; transition: width 0.5s; }
.st-dash-card-info { display: flex; justify-content: space-between; align-items: center; }
.st-dash-badge { font-size: 0.75rem; color: var(--st-text2); padding: 2px 8px; background: var(--st-border); border-radius: 8px; }
.st-dash-completed { color: #38a169; background: rgba(56,161,105,0.15); }
.st-dash-time { font-size: 0.75rem; color: var(--st-text3); }

@media (prefers-color-scheme: light) {
    #socratic-dashboard-app {
        --st-bg: #fff; --st-card: #f5f6f8; --st-text: #1a1a2e;
        --st-text2: #555566; --st-text3: #8888a0; --st-border: #e2e4e8;
    }
}

/* ===== CONCEPT MAP MODAL ===== */
.st-concepts-modal {
    position: fixed; inset: 0; z-index: var(--st-z-modal, 100010); background: rgba(0,0,0,0.6);
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.st-concepts-content {
    background: var(--st-card, #151515); border-radius: var(--st-radius, 14px);
    max-width: 420px; width: 100%; max-height: 70vh; overflow-y: auto;
    border: 1.5px solid var(--st-border, #2a2a2a); padding: 20px;
}
.st-concepts-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.st-concepts-header h3 { margin: 0; font-size: 1.1rem; color: var(--st-text, #f0f0f0); }
.st-concept-item {
    padding: 8px 12px; margin-bottom: 4px; border-radius: 8px;
    background: var(--st-bg, #0a0a0a); color: var(--st-text, #f0f0f0); font-size: 0.9rem;
}
.st-concept-num { color: var(--st-primary, #2ea3f2); font-weight: 700; margin-right: 4px; }

/* ===== CONTAINER QUERIES — card adaptation ===== */
@container (max-width: 350px) {
    .st-card-cover { height: 120px; }
    .st-card-body h3 { font-size: 1rem; }
    .st-card-body { padding: 14px; }
    .st-card-body p { -webkit-line-clamp: 2; }
}

/* ===== LIGHT MODE (opt-in via data attribute) ===== */
#socratic-tutor-app[data-st-theme="auto"] {
    /* Light mode inherits from user's system preference */
}
@media (prefers-color-scheme: light) {
    #socratic-tutor-app[data-st-theme="auto"] {
        --st-bg: #ffffff;
        --st-card: #f5f6f8;
        --st-text: #1a1a2e;
        --st-text2: #555566;
        --st-text3: #8888a0;
        --st-border: #e2e4e8;
    }
    #socratic-tutor-app[data-st-theme="auto"] .st-chat-input { color: var(--st-text) !important; }
    #socratic-tutor-app[data-st-theme="auto"] .st-msg-tutor .st-msg-bubble code { background: rgba(0,0,0,0.06); }
}

/* ===== MODE PICKER =====
   Three large cards (Socratic / Test / Exam) shown on the start screen and
   inside the change-mode modal. Layout is a CSS grid so the cards naturally
   wrap on narrow viewports without a media-query carve-out.

   Card states:
     - default       — interactive, hover lifts it
     - --selected    — the currently-chosen mode (border + glow in primary)
     - --disabled    — Exam when no question bank exists; pointer-events off
                       and the contents fade so it reads as "not available"
                       without disappearing entirely (keeps the layout stable
                       AND signals the path the student could unlock).
*/
/* .st-mode-cards / .st-mode-card are now only used by the change-mode modal
   (the start screen switched to three .st-btn-start buttons in v2.5.0). The
   selectors stay scoped to .st-modal so future use on top-level pages won't
   accidentally inherit the modal-specific spacing. */
.st-mode-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px;
    width: 100%;
    max-width: 640px;
    margin: 0 0 24px;
}
.st-mode-card {
    background: var(--st-card);
    border: 2px solid var(--st-border);
    border-radius: 14px;
    padding: 20px 16px;
    display: flex; flex-direction: column; align-items: center;
    gap: 8px;
    cursor: pointer;
    transition: border-color 0.2s, transform 0.15s, box-shadow 0.2s, background 0.2s;
    font-family: inherit;
    text-align: center;
    color: var(--st-text);
    min-height: 150px;
}
.st-mode-card:hover:not(.st-mode-card--disabled) {
    border-color: var(--st-primary);
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(46, 163, 242, 0.15);
}
.st-mode-card:focus-visible {
    outline: 2px solid var(--st-primary);
    outline-offset: 2px;
}
.st-mode-card--selected {
    border-color: var(--st-primary);
    background: var(--st-primary-light);
    box-shadow: 0 4px 18px rgba(46, 163, 242, 0.2);
}
.st-mode-card--disabled {
    opacity: 0.45;
    cursor: not-allowed;
    /* Keep hover noop but visually flat — no transform / shadow lift. */
    filter: grayscale(0.6);
}
.st-mode-card-icon {
    font-size: 2rem; line-height: 1;
}
.st-mode-card-title {
    font-size: 1.05rem; font-weight: 700; color: var(--st-text);
}
.st-mode-card-desc {
    font-size: 0.85rem; color: var(--st-text2); line-height: 1.45;
    max-width: 220px;
}

/* ===== MODE BANNER =====
   Compact strip above the messages area, only present in test/exam modes.
   Acts as a passive reminder of which rule set is active — useful when the
   student switches modes mid-session and the next AI reply might otherwise
   surprise them.
*/
/* Banner styling — single look for both test and exam (was: orange for exam,
   primary-tinted for test). Keeping them visually identical avoids implying
   that one mode is "more dangerous" than the other; the actual rule set
   difference is in the prompt, not the chrome. */
.st-mode-banner {
    padding: 8px 16px;
    font-size: 0.85rem; font-weight: 600;
    text-align: center;
    border-bottom: 1px solid var(--st-border);
    background: var(--st-primary-light);
    color: var(--st-primary-dark);
    flex-shrink: 0;
}

/* ===== MODE-CHANGE MODAL =====
   The modal is appended to <body>, OUTSIDE the #socratic-tutor-app scope
   where the CSS custom properties (--st-bg, --st-text, etc.) are defined.
   That means `var(--st-bg)` would resolve to nothing on this element and
   the background would be transparent, letting the chat bleed through.
   Every var() below uses an explicit dark fallback so the modal stays
   readable regardless of where it's mounted — mirrors the strategy used
   by .st-concepts-modal a few rules above. */
.st-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100010;
    padding: 20px;
}
.st-modal {
    background: var(--st-card, #1a1a2e);
    color: var(--st-text, #ffffff);
    border-radius: 16px;
    padding: 24px;
    max-width: 720px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
    border: 1.5px solid var(--st-border, #2a2a2a);
}
.st-modal-title {
    font-size: 1.2rem; font-weight: 700;
    margin: 0;
    /* Same outside-the-app-scope concern as .st-modal — explicit fallback. */
    color: var(--st-text, #ffffff);
}
/* Header row: title on the left, close X on the right. Lets the modal
   skip a separate Cancel button — students close with X or click outside. */
.st-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 18px;
}
.st-modal-close {
    background: transparent;
    border: none;
    color: var(--st-text2, rgba(255,255,255,0.7));
    font-size: 1.2rem;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 6px;
    line-height: 1;
}
.st-modal-close:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--st-text, #ffffff);
}
.st-modal-hint {
    font-size: 0.9rem; color: var(--st-text2, rgba(255,255,255,0.7));
    margin: 0 0 18px;
    line-height: 1.5;
}
.st-modal-actions {
    display: flex; gap: 10px; justify-content: flex-end;
    margin-top: 8px;
}
/* Highlight the currently-active mode inside the change-mode modal so the
   student can see at a glance which one they're already on. The button
   stays clickable (re-selecting is a no-op) but reads as "you are here". */
.st-btn-start.st-btn-start--current {
    outline: 3px solid var(--st-primary-dark);
    outline-offset: 2px;
    cursor: default;
}
.st-btn-secondary {
    background: transparent;
    color: var(--st-text);
    padding: 10px 22px;
    border-radius: 22px;
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    border: 1.5px solid var(--st-border);
    transition: background 0.2s, border-color 0.2s;
    font-family: inherit;
}
.st-btn-secondary:hover {
    background: var(--st-card);
    border-color: var(--st-text3);
}
.st-btn-primary {
    background: var(--st-primary);
    color: #fff;
    padding: 10px 26px;
    border-radius: 22px;
    font-size: 0.95rem;
    font-weight: 700;
    cursor: pointer;
    border: none;
    transition: background 0.2s, transform 0.15s;
    font-family: inherit;
}
.st-btn-primary:hover {
    background: var(--st-primary-dark);
    transform: translateY(-1px);
}

/* Reduced-motion respect — undo the lift transforms so vestibular-sensitive
   users don't get the bounce on hover. */
@media (prefers-reduced-motion: reduce) {
    .st-mode-card,
    .st-btn-primary,
    .st-btn-secondary {
        transition: none;
    }
    .st-mode-card:hover:not(.st-mode-card--disabled),
    .st-btn-primary:hover {
        transform: none;
    }
}

/* Mobile: cards stack to a single column on narrow screens, modal trims its
   padding so it doesn't push the actions off-screen. */
@media (max-width: 520px) {
    .st-mode-cards {
        grid-template-columns: 1fr;
        max-width: 100%;
    }
    .st-mode-card {
        min-height: auto;
        flex-direction: row;
        text-align: left;
        align-items: center;
    }
    .st-mode-card-icon {
        font-size: 1.7rem;
        flex-shrink: 0;
    }
    .st-mode-card-desc {
        max-width: none;
    }
    .st-modal {
        padding: 18px;
        border-radius: 12px;
    }
    .st-modal-actions {
        flex-direction: column-reverse;
    }
    .st-btn-primary, .st-btn-secondary {
        width: 100%;
    }
}
