/* /Components/Chat/ContentOverlay.razor.rz.scp.css */
/* Modal reassurance overlay over the dimmed door. The native <dialog> (showModal) supplies the top
   layer + ::backdrop; we theme it with the --ff-* tokens, so dark mode (.fox) is inherited for free.
   Desktop: a centered card. Mobile (<=560px): a slide-up bottom sheet that dismisses back down. */

.ff-content-overlay[b-kwvgbi2apu] {
    border: none;
    padding: 0;
    margin: auto;                 /* center in the viewport; the backdrop fills around it */
    width: min(560px, 92vw);
    max-height: 85vh;
    background: transparent;      /* the inner panel paints the surface */
    color: var(--ff-chat-text);
    overflow: visible;
}

.ff-content-overlay[b-kwvgbi2apu]::backdrop {
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}

.ff-co-panel[b-kwvgbi2apu] {
    display: flex;
    flex-direction: column;
    max-height: 85vh;
    background: var(--ff-chat-column-bg);
    border: 1px solid var(--ff-tutor-bubble-border);
    border-radius: 14px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
    overflow: hidden;
}

.ff-co-header[b-kwvgbi2apu] {
    flex: 0 0 auto;
    display: flex;
    justify-content: flex-end;
    padding: 10px 10px 0;
}

.ff-co-close[b-kwvgbi2apu] {
    width: 34px;
    height: 34px;
    border: none;
    border-radius: 50%;
    background: var(--ff-tutor-bubble-bg);
    color: var(--ff-chat-text);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}

.ff-co-close:hover[b-kwvgbi2apu] {
    background: rgba(var(--ff-accent-purple), 0.15);
}

.ff-co-body[b-kwvgbi2apu] {
    flex: 1 1 auto;
    padding: 4px 22px 22px;
    overflow-y: auto;             /* long articles scroll INSIDE the overlay */
}

.ff-co-title[b-kwvgbi2apu] {
    margin: 0 0 10px;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--ff-chat-text);
}

.ff-co-article[b-kwvgbi2apu] {
    font-size: 15px;
    line-height: 1.55;
    color: var(--ff-chat-text);
}

.ff-co-article[b-kwvgbi2apu]  p:first-child { margin-top: 0; }
.ff-co-article[b-kwvgbi2apu]  p:last-child  { margin-bottom: 0; }

.ff-co-faq-lead[b-kwvgbi2apu] {
    margin-bottom: 6px;
    padding-bottom: 12px;
    font-size: 15px;
    line-height: 1.55;
    color: var(--ff-chat-text);
    border-bottom: 1px solid var(--ff-tutor-bubble-border);
}

.ff-co-faq-item[b-kwvgbi2apu] { margin-top: 16px; }

.ff-co-faq-q[b-kwvgbi2apu] {
    margin: 0 0 4px;
    font-size: 1rem;
    font-weight: 650;
    color: var(--ff-chat-text);
}

.ff-co-faq-a[b-kwvgbi2apu] {
    font-size: 14px;
    line-height: 1.5;
    color: var(--ff-chat-text-muted);
}

.ff-co-nudge[b-kwvgbi2apu] {
    margin-top: 20px;
    padding-top: 14px;
    border-top: 1px solid var(--ff-tutor-bubble-border);
    text-align: center;
    font-weight: 600;
    color: rgba(var(--ff-accent-purple), 1);
}

.ff-co-demo-intro[b-kwvgbi2apu] {
    margin-bottom: 12px;
    font-size: 15px;
    line-height: 1.5;
    color: var(--ff-chat-text);
}

.ff-co-video[b-kwvgbi2apu] {
    display: block;
    width: 100%;
    border-radius: 10px;
    background: #000;
}

/* The demo-video payload goes large — as big as the lightbox — while the article/pricing cards stay
   compact. Scoped to wider screens so the mobile bottom-sheet rules below still win on small ones. */
@media (min-width: 561px) {
    .ff-content-overlay--wide[b-kwvgbi2apu] {
        width: min(1400px, 95vw);
        max-width: 95vw;
        max-height: 95vh;
    }

    .ff-content-overlay--wide .ff-co-panel[b-kwvgbi2apu] {
        max-height: 95vh;
    }

    .ff-content-overlay--wide .ff-co-video[b-kwvgbi2apu] {
        max-height: 82vh;
        object-fit: contain;
    }
}

.ff-co-nodemo[b-kwvgbi2apu] {
    padding: 20px;
    font-size: 15px;
    text-align: center;
    color: var(--ff-chat-text-muted);
}

.ff-co-demo-outro[b-kwvgbi2apu] {
    margin-top: 14px;
    text-align: center;
    font-weight: 600;
    color: rgba(var(--ff-accent-purple), 1);
}

/* Mobile: full-width slide-up sheet pinned to the bottom edge. */
@media (max-width: 560px) {
    .ff-content-overlay[b-kwvgbi2apu] {
        width: 100vw;
        max-width: 100vw;
        max-height: 90vh;
        margin: auto 0 0;          /* pin to the bottom of the viewport */
    }

    .ff-co-panel[b-kwvgbi2apu] {
        max-height: 90vh;
        border-radius: 16px 16px 0 0;
    }

    .ff-content-overlay[open][b-kwvgbi2apu] {
        animation: ff-co-slide-up-b-kwvgbi2apu 0.25s ease-out;
    }
}

@keyframes ff-co-slide-up-b-kwvgbi2apu {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}
/* /Components/Chat/EntranceInput.razor.rz.scp.css */
/* ChatGPT-style hero input for the cold-open door. Centered by the entrance wrapper's align-items;
   a rounded pill on the chat surface with an inline send button. Themed via the --ff-* tokens. */
.ff-entrance-input[b-3lfi77a4au] {
    display: flex;
    align-items: center;
    gap: 6px;
    width: min(560px, 92%);
    margin: 4px auto 6px;
    padding: 6px 6px 6px 18px;
    background: var(--ff-entrance-input-bg);
    border: 1px solid var(--ff-entrance-input-border);
    border-radius: 26px;
    box-shadow: var(--ff-entrance-input-shadow);   /* deep warm-brown float in light, subtle in dark */
    transition: border-color 0.15s, box-shadow 0.15s;
}

.ff-entrance-input:focus-within[b-3lfi77a4au] {
    border-color: rgba(var(--ff-action-line), 0.7);
    box-shadow: 0 0 0 3px rgba(var(--ff-action-line), 0.15);
}

.ff-entrance-input-box[b-3lfi77a4au] {
    flex: 1 1 auto;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--ff-chat-text);
    font-size: 15px;
    line-height: 1.4;
    padding: 8px 0;
}

.ff-entrance-input-box[b-3lfi77a4au]::placeholder {
    color: var(--ff-chat-text-muted);
}

.ff-entrance-input-send[b-3lfi77a4au] {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border: none;
    border-radius: 50%;
    background: var(--ff-action-fill);   /* warm orange gradient (light) / purple (dark) */
    box-shadow: 0 6px 16px var(--ff-action-ring);
    color: #ffffff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.15s, transform 0.1s;
}

.ff-entrance-input-send:hover:not(:disabled)[b-3lfi77a4au] {
    transform: scale(1.05);
}

.ff-entrance-input-send:disabled[b-3lfi77a4au] {
    opacity: 0.4;
    cursor: default;
}

/* "Speak a language" mic — outlined circle matching the lesson mic (warm orange in light mode via
   the --ff-mic-button-* tokens). Sits between the input and the send button. */
.ff-entrance-input-mic[b-3lfi77a4au] {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border: 2px solid var(--ff-mic-button-border);
    border-radius: 50%;
    background: var(--ff-mic-button-bg);
    color: var(--ff-mic-button-text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
}

.ff-entrance-input-mic:hover:not(:disabled)[b-3lfi77a4au] {
    background: var(--ff-mic-button-hover-bg);
    border-color: var(--ff-mic-button-hover-border);
    transform: scale(1.05);
}

.ff-entrance-input-mic.ff-recording[b-3lfi77a4au] {
    background: var(--ff-mic-button-border);
    border-color: var(--ff-mic-button-border);
    color: #ffffff;
}

.ff-entrance-input-mic:disabled[b-3lfi77a4au] {
    cursor: default;
}
/* /Components/Chat/EntranceMarketingBand.razor.rz.scp.css */
/* Cold-open marketing band. Surfaces and text ride the --ff-* theme tokens so it follows light and
   dark like the rest of the door; the MrFox orange (card titles, mascot glow) is the one constant
   brand accent, same as the welcome-back card. */

.ff-mkt-band[b-osgoftiy1a] {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    max-width: 940px;
    margin: 22px auto 4px;
    text-align: center;
    animation: ff-mkt-fade-up-b-osgoftiy1a 0.6s ease;
}

/* ── Mascot over a soft orange bloom ── */

.ff-mkt-mascot[b-osgoftiy1a] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px 0 6px;
}

.ff-mkt-mascot[b-osgoftiy1a]::before {
    content: "";
    position: absolute;
    width: 210px;
    height: 210px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(241, 90, 36, 0.18) 0%, transparent 70%);
}

.ff-mkt-mascot img[b-osgoftiy1a] {
    position: relative;
    width: 116px;
    animation: ff-mkt-float-b-osgoftiy1a 5s ease-in-out infinite;
}

/* ── Hook + support ── */

.ff-mkt-hook[b-osgoftiy1a] {
    margin: 8px 0 6px;
    font-size: 20px;
    font-weight: 600;
    color: var(--ff-chat-text);
}

.ff-mkt-support[b-osgoftiy1a] {
    max-width: 520px;
    font-size: 15px;
    line-height: 1.6;
    color: var(--ff-chat-text-soft);
}

.ff-mkt-support[b-osgoftiy1a]  p {
    margin: 0;
}

/* ── Value-prop cards ── */

.ff-mkt-cards[b-osgoftiy1a] {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 14px;
    margin-top: 20px;
}

.ff-mkt-card[b-osgoftiy1a] {
    flex: 0 1 240px;
    min-width: 200px;
    padding: 14px 16px;
    text-align: left;
    background: var(--ff-mkt-card-bg);
    border: 1px solid var(--ff-mkt-card-border);
    border-top: 3px solid var(--ff-mkt-card-accent);   /* brand stripe — orange in light, violet in dark */
    border-radius: 12px;
    box-shadow: var(--ff-mkt-card-shadow);
}

.ff-mkt-card-title[b-osgoftiy1a] {
    margin-bottom: 8px;
    font-size: 19px;
    font-weight: 600;
    color: var(--ff-mkt-card-accent);
}

.ff-mkt-card-icon[b-osgoftiy1a] {
    margin-right: 8px;
}

.ff-mkt-card-body[b-osgoftiy1a] {
    font-size: 14px;
    line-height: 1.55;
    color: var(--ff-chat-text-soft);
}

.ff-mkt-card-body[b-osgoftiy1a]  p {
    margin: 0;
}

/* ── Honest footnote ── */

.ff-mkt-foot[b-osgoftiy1a] {
    margin-top: 16px;
    font-size: 13px;
    color: var(--ff-mkt-foot-text);
}

/* ── Motion ── */

@keyframes ff-mkt-fade-up-b-osgoftiy1a {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes ff-mkt-float-b-osgoftiy1a {
    0%, 100% { transform: translateY(5px); }
    50%      { transform: translateY(-5px); }
}

@media (prefers-reduced-motion: reduce) {
    .ff-mkt-band[b-osgoftiy1a] {
        animation: none;
    }

    .ff-mkt-mascot img[b-osgoftiy1a] {
        animation: none;
    }
}
/* /Components/Chat/FfChatUi.razor.rz.scp.css */
/* FfChatUi — owned transcript shell. Stage 1: container, plain bubbles, text footer.
   The rich ff-* card styling (ported from Lesson.razor.css via ::deep) arrives in Stage 2,
   once the host page supplies an EntryTemplate that reuses the leaf components. */

.ff-chat[b-p1jc97tb8g] {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    /* Shared readable column width — transcript rows and the footer input both center to this
       (Claude-Code / ChatGPT style) instead of stretching edge-to-edge on wide screens. */
    --ff-chat-max-width: 768px;
    /* Guard rails: contain the whole conversation (transcript + footer) in a centered column
       with subtle vertical borders, so it reads as a defined panel instead of hanging in mid-air
       on a wide window. The outer width is the readable column + the scroll's 16px side padding
       (×2) so the rails sit just outside the message bubbles; the scrollbar tucks against the
       right rail rather than floating at the window edge. */
    width: 100%;
    max-width: calc(var(--ff-chat-max-width, 768px) + 32px);
    margin: 0 auto;
    border-left: 1px solid var(--ff-chat-column-border);
    border-right: 1px solid var(--ff-chat-column-border);
    /* Transparent — the page canvas (.ff-lesson-surface: beige gradient in light, slate in dark)
       shows through, and the white entrance/lesson surfaces float on it (contrast-fix handoff).
       In dark this is a no-op: the column token matched the page already. --ff-chat-column-bg
       still backs the solid overlay surfaces (ContentOverlay, MessageDialog). */
    background: transparent;
}

/* ── Lesson progress strip ───────────────────────────────── */
/* Pinned above the scroll region (flex: 0 0 auto), centered to the same readable column as the
   rows so it lines up with the bubbles below. Theme-aware via the shared --ff-* tokens. */
.ff-chat-progress[b-p1jc97tb8g] {
    flex: 0 0 auto;
    width: 100%;
    max-width: calc(var(--ff-chat-max-width, 768px) + 32px);
    margin: 0 auto;
    padding: 10px 16px 11px;
    box-sizing: border-box;
    border-bottom: 1px solid var(--ff-chat-column-border);
}

.ff-chat-progress-row[b-p1jc97tb8g] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 7px;
}

.ff-chat-progress-label[b-p1jc97tb8g] {
    font-size: 14px;
    font-weight: 600;
    color: var(--ff-chat-text-soft);
}

.ff-chat-progress-pct[b-p1jc97tb8g] {
    font-size: 14px;
    font-weight: 700;
    color: var(--ff-progress-pct);
    font-variant-numeric: tabular-nums;
}

.ff-chat-progress-track[b-p1jc97tb8g] {
    height: 8px;
    border-radius: 99px;
    background: var(--ff-progress-track);
    overflow: hidden;
}

.ff-chat-progress-fill[b-p1jc97tb8g] {
    height: 100%;
    border-radius: 99px;
    background: var(--ff-progress-fill);   /* orange brand gradient */
    transition: width 0.4s ease;
}

.ff-chat-scroll[b-p1jc97tb8g] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;   /* center the transcript column; scrollbar stays at the window edge */
    gap: 10px;
    /* Muted, theme-aware scrollbar (tokens in app.css: mid-gray on light, slate on dark — replacing
       the old near-black / pure-white extremes). Firefox uses scrollbar-color; WebKit/Chromium uses
       the ::-webkit-scrollbar pseudo-elements below. Track is transparent so it reads as part of the
       column rather than a painted gutter. */
    scrollbar-width: thin;
    scrollbar-color: var(--ff-scrollbar-thumb) transparent;
}

.ff-chat-scroll[b-p1jc97tb8g]::-webkit-scrollbar {
    width: 8px;
}

.ff-chat-scroll[b-p1jc97tb8g]::-webkit-scrollbar-track {
    background: transparent;
}

.ff-chat-scroll[b-p1jc97tb8g]::-webkit-scrollbar-thumb {
    background: var(--ff-scrollbar-thumb);
    border-radius: 99px;
}

.ff-chat-scroll[b-p1jc97tb8g]::-webkit-scrollbar-thumb:hover {
    background: var(--ff-scrollbar-thumb-hover);
}

.ff-chat-row[b-p1jc97tb8g] {
    display: flex;
    width: 100%;
    max-width: var(--ff-chat-max-width, 768px);
}

.ff-chat-row-other[b-p1jc97tb8g]   { justify-content: flex-start; }
.ff-chat-row-student[b-p1jc97tb8g] { justify-content: flex-end; }

/* ── Default plain bubble (used until the host supplies an EntryTemplate) ── */
.ff-bubble[b-p1jc97tb8g] {
    max-width: 80%;
    padding: 10px 14px;
    border-radius: 12px;
    line-height: 1.5;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: anywhere;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.ff-bubble-tutor[b-p1jc97tb8g] {
    background: var(--ff-bubble-bg);
    color: var(--ff-chat-text);
    border: 1px solid var(--ff-chat-column-border);
    border-top-left-radius: 4px;
}

.ff-bubble-student[b-p1jc97tb8g] {
    background: #27ae60;
    color: #ffffff;
    border-top-right-radius: 4px;
}

.ff-bubble-status[b-p1jc97tb8g] {
    background: var(--ff-status-plain-bg);
    color: var(--ff-status-plain-text);
    font-style: italic;
}

.ff-bubble-score[b-p1jc97tb8g] {
    background: var(--ff-score-bg);
    color: var(--ff-chat-text);
    border: 1px solid var(--ff-score-border);
}

/* "Thinking…" indicator shown at the foot of the transcript while the engine works. */
.ff-typing[b-p1jc97tb8g] {
    color: var(--ff-chat-text-faint);
    font-style: italic;
}

/* ── Scroll-to-bottom arrow ──────────────────────────────── */
/* Zero-height anchor between the scroll area and the footer: the button hangs above it,
   floating over the transcript's bottom edge without joining the flex flow. Centered to
   the same readable column as the rows. */
.ff-scroll-bottom-anchor[b-p1jc97tb8g] {
    position: relative;
    height: 0;
    width: 100%;
    max-width: calc(var(--ff-chat-max-width, 768px) + 32px);
    margin: 0 auto;
}

/* Hidden by default; JS (ffChatScrollInit) toggles ff-scroll-bottom-visible from scroll
   state — the class arrives outside Blazor's render, which is fine: Blazor never rewrites
   an attribute it didn't change. */
.ff-scroll-bottom[b-p1jc97tb8g] {
    position: absolute;
    bottom: 14px;
    left: 50%;
    transform: translateX(-50%) translateY(8px);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--ff-tutor-bubble-border);
    background: var(--ff-bubble-bg);
    color: var(--ff-chat-text);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease, transform 0.15s ease;
    z-index: 5;
}

.ff-scroll-bottom.ff-scroll-bottom-visible[b-p1jc97tb8g] {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%);
}

.ff-scroll-bottom:hover[b-p1jc97tb8g] {
    border-color: var(--ff-input-border);
    box-shadow: 0 3px 14px rgba(0, 0, 0, 0.24);
}

/* ── Text footer ─────────────────────────────────────────── */
/* Centered to the SAME column as the transcript — NOT full-bleed. The bar used to span the
   whole window (border + background edge-to-edge), which dwarfed the narrower transcript above
   it. The max-width adds the transcript scroll's 16px side padding (+32px) so the input's edges
   line up exactly with the message bubbles' column; the input itself reads as a floating row. */
.ff-chat-footer[b-p1jc97tb8g] {
    width: 100%;
    max-width: calc(var(--ff-chat-max-width, 768px) + 32px);
    margin: 0 auto;
    padding: 12px 16px;
    box-sizing: border-box;
}

.ff-chat-footer-inner[b-p1jc97tb8g] {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}

/* Mic-mode footer: center the host-supplied mic content (button + escape hatch) rather than
   left-aligning it the way the text input sits. */
.ff-chat-footer-mic[b-p1jc97tb8g] {
    justify-content: center;
    gap: 12px;
}

/* Text-mode footer: a single rounded pill holding the input + inline send button, matching the
   cold-open entrance input (.ff-entrance-input). The input is transparent inside the pill; the
   pill itself carries the border, background, and focus ring. */
.ff-chat-footer-text[b-p1jc97tb8g] {
    gap: 6px;
    padding: 6px 6px 6px 18px;
    background: var(--ff-tutor-bubble-bg);
    border: 1px solid var(--ff-tutor-bubble-border);
    border-radius: 26px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    transition: border-color 0.15s, box-shadow 0.15s;
}

.ff-chat-footer-text:focus-within[b-p1jc97tb8g] {
    border-color: rgba(var(--ff-action-line), 0.7);
    box-shadow: 0 0 0 3px rgba(var(--ff-action-line), 0.15);
}

.ff-chat-input[b-p1jc97tb8g] {
    flex: 1 1 auto;
    min-width: 0;
    padding: 8px 0;
    border: none;
    border-radius: 0;
    font-size: 15px;
    line-height: 1.4;
    outline: none;
    background: transparent;
    color: var(--ff-chat-text);
}

.ff-chat-input[b-p1jc97tb8g]::placeholder {
    color: var(--ff-chat-text-muted);
}

.ff-chat-input:disabled[b-p1jc97tb8g] {
    opacity: 0.6;
}

.ff-chat-send[b-p1jc97tb8g] {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: var(--ff-action-fill);   /* warm orange gradient (light) / purple (dark) */
    box-shadow: 0 4px 12px var(--ff-action-ring);
    color: #ffffff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.15s, transform 0.1s;
}

.ff-chat-send:hover:not(:disabled)[b-p1jc97tb8g] { transform: scale(1.05); }
.ff-chat-send:disabled[b-p1jc97tb8g] { opacity: 0.4; cursor: default; }
/* /Components/Chat/FlagEmoji.razor.rz.scp.css */
/* Scoped to FlagEmoji — the ONE home of the flag-glyph font declaration. Windows ships no flag
   emoji glyphs, so flags use a self-hosted subset font containing ONLY the flag emoji:
   TwemojiCountryFlags (from the country-flag-emoji-polyfill package; MIT, Twemoji art CC-BY 4.0).
   The unicode-range keeps it inert for every other character, and platforms are consistent —
   everyone gets the Twemoji flag. (@font-face rules pass through the CSS scoper unscoped.) */
@font-face {
    font-family: "Twemoji Country Flags";
    src: url("/fonts/TwemojiCountryFlags.woff2") format("woff2");
    unicode-range: U+1F1E6-1F1FF;
    font-display: swap;
}

.ff-flag-emoji[b-qrxp5lu23x] {
    font-family: "Twemoji Country Flags", sans-serif;
    line-height: 1;
    /* Twemoji flags are borderless, so white regions (🇷🇺 🇺🇸) wash into light surfaces. A hairline
       drop-shadow traces the glyph's rounded-rect silhouette — an outline a border-box can't give
       a font glyph. Subtle enough to disappear on dark/gradient surfaces. */
    filter: drop-shadow(0 0 0.75px rgba(74, 36, 23, 0.55));
}
/* /Components/Chat/InlineLoginForm.razor.rz.scp.css */
/* Self-contained styling for the inline login form so it looks right wherever it renders —
   the chat transcript's welcome-back bubble AND the sidebar / bottom-nav login popover. Labels
   inherit color from the container (dark text in the light chat bubble, white in the dark
   popover); the input fields are white boxes with dark text in every theme. */
.ff-inline-login[b-6z5ct4621d] {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-width: 340px;
}

.ff-inline-login-field[b-6z5ct4621d] {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 0.85rem;
    color: inherit;
}

.ff-inline-login-field input[b-6z5ct4621d] {
    padding: 7px 10px;
    border: 1px solid #d0d0d0;
    border-radius: 6px;
    background: #fff;
    color: #1f2937;
    font-size: 0.95rem;
}

/* Remember-me on the left, Forgot-password link on the right, on one row. */
.ff-inline-login-row[b-6z5ct4621d] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.ff-inline-login-remember[b-6z5ct4621d] {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    color: inherit;
}

.ff-inline-login button[type="submit"][b-6z5ct4621d] {
    align-self: flex-start;
    margin-top: 2px;
}

.ff-inline-login-register[b-6z5ct4621d],
.ff-inline-login-forgot[b-6z5ct4621d] {
    font-size: 0.85rem;
    color: inherit;          /* white in the dark nav popover */
    text-decoration: underline;
    opacity: 0.9;
}

/* The register link is a standalone column child; the forgot link is positioned by its row. */
.ff-inline-login-register[b-6z5ct4621d] {
    align-self: flex-start;
    margin-top: 2px;
}

/* Keep the forgot link from stretching/wrapping; sits snug at the row's right edge. */
.ff-inline-login-forgot[b-6z5ct4621d] {
    flex-shrink: 0;
    white-space: nowrap;
}
/* /Components/Chat/LessonPlanCardMessage.razor.rz.scp.css */
/* Scoped to LessonPlanCardMessage. Theme-aware like the progress dashboard — the light values are
   the warm-coral design spec verbatim (coral gradient header over a white plan body, espresso
   text); dark swaps to the purple/slate look under the app's `.fox` class (the Blazor scoper
   rewrites `.fox .ff-plan-card` to a scoped selector, so the html-level theme class works from
   inside this file). Font stays the app font by design. */

.ff-plan-card[b-kvx30zdvbw] {
    /* Light theme (default) — warm-coral design-spec values */
    --plan-body-bg: #ffffff;
    --plan-header-gradient: linear-gradient(120deg, #E8552E 0%, #F47A45 100%);
    --plan-accent: #E8552E;
    --plan-lesson-title: #4A2417;
    --plan-lesson-description: #98776A;
    --plan-count: #B79B8E;
    --plan-badge-bg: #FCE9E0;
    --plan-badge-text: #E8552E;
    --plan-lesson-hover: #FBF0EA;
    --plan-shadow: 0 8px 30px rgba(122, 46, 26, 0.12);
}

.fox .ff-plan-card[b-kvx30zdvbw] {
    /* Dark theme — deep slate body, lifted lilac text, purple gradient header */
    --plan-body-bg: #1e293b;                      /* slate-800 */
    --plan-header-gradient: linear-gradient(120deg, #5B2A86 0%, #7C3AED 100%);
    --plan-accent: #a78bfa;                       /* violet-400 */
    --plan-lesson-title: #f1f5f9;                 /* slate-100 */
    --plan-lesson-description: #94a3b8;           /* slate-400 */
    --plan-count: #94a3b8;
    --plan-badge-bg: rgba(124, 58, 237, 0.28);
    --plan-badge-text: #c4b5fd;                   /* violet-300 */
    --plan-lesson-hover: #273449;
    --plan-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}

.ff-plan-card[b-kvx30zdvbw] {
    width: 100%;
    max-width: 660px;            /* match the progress dashboard + welcome-back cards */
    margin: 4px auto 12px;
    border-radius: 22px;
    overflow: hidden;
    background: var(--plan-body-bg);
    box-shadow: var(--plan-shadow);
}

/* ── Profile header — gradient band ─────────────────────────────────────── */
.ff-plan-header[b-kvx30zdvbw] {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 16px 22px;
    background: var(--plan-header-gradient);
}

.ff-plan-name-row[b-kvx30zdvbw] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
}

.ff-plan-name[b-kvx30zdvbw] {
    color: #fff;
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.ff-plan-age[b-kvx30zdvbw] {
    color: rgba(255, 255, 255, 0.78);
    font-size: 14px;
    font-weight: 700;
}

.ff-plan-chips[b-kvx30zdvbw] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.ff-plan-chip[b-kvx30zdvbw] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
}

.ff-plan-chip-arrow[b-kvx30zdvbw] {
    opacity: 0.7;
}

/* Sizing wrapper for the shared FlagEmoji glyph inside the language-pair chip. An unresolvable
   name renders no glyph; the wrapper collapses to nothing inside the flex chip. */
.ff-plan-flag[b-kvx30zdvbw] {
    font-size: 1.25em;
    line-height: 1;
}

.ff-plan-chip-icon[b-kvx30zdvbw] {
    flex: 0 0 auto;
    width: 13px;
    height: 13px;
    opacity: 0.9;
}

/* ── Plan body ───────────────────────────────────────────────────────────── */
.ff-plan-body[b-kvx30zdvbw] {
    padding: 14px 22px 16px;
}

.ff-plan-body-head[b-kvx30zdvbw] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 8px;
}

.ff-plan-title[b-kvx30zdvbw] {
    margin: 0;
    font-size: 15px;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--plan-accent);
}

.ff-plan-count[b-kvx30zdvbw] {
    font-size: 13px;
    font-weight: 700;
    color: var(--plan-count);
}

.ff-plan-lessons[b-kvx30zdvbw] {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ff-plan-lesson[b-kvx30zdvbw] {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 7px 10px;
    border-radius: 14px;
}

.ff-plan-lesson:hover[b-kvx30zdvbw] {
    background: var(--plan-lesson-hover);
}

.ff-plan-lesson-number[b-kvx30zdvbw] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    margin-top: 2px;
    border-radius: 10px;
    background: var(--plan-badge-bg);
    color: var(--plan-badge-text);
    font-size: 14px;
    font-weight: 800;
}

.ff-plan-lesson-text[b-kvx30zdvbw] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.ff-plan-lesson-title[b-kvx30zdvbw] {
    font-size: 16px;
    font-weight: 800;
    color: var(--plan-lesson-title);
}

.ff-plan-lesson-description[b-kvx30zdvbw] {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--plan-lesson-description);
}
/* /Components/Chat/MessageDialog.razor.rz.scp.css */
/* Small centered acknowledgment modal (message + OK). Native <dialog> top layer + ::backdrop,
   themed with the --ff-* tokens (dark mode inherited). */
.ff-message-dialog[b-jw71mmky42] {
    border: none;
    padding: 0;
    margin: auto;
    width: min(420px, 90vw);
    background: transparent;
    color: var(--ff-chat-text);
}

.ff-message-dialog[b-jw71mmky42]::backdrop {
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}

.ff-md-panel[b-jw71mmky42] {
    background: var(--ff-chat-column-bg);
    border: 1px solid var(--ff-tutor-bubble-border);
    border-radius: 14px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
    padding: 22px 22px 16px;
}

.ff-md-text[b-jw71mmky42] {
    font-size: 15px;
    line-height: 1.5;
    text-align: center;
    color: var(--ff-chat-text);
}

.ff-md-actions[b-jw71mmky42] {
    display: flex;
    justify-content: center;
    margin-top: 18px;
}

.ff-md-ok[b-jw71mmky42] {
    min-width: 96px;
    padding: 9px 22px;
    border: none;
    border-radius: 22px;
    background: rgba(var(--ff-accent-purple), 1);
    color: #ffffff;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.1s, opacity 0.15s;
}

.ff-md-ok:hover[b-jw71mmky42] {
    transform: scale(1.04);
}
/* /Components/Chat/PricingPanel.razor.rz.scp.css */
/* Pricing panel — the one structured "surface", now shown inside the ContentOverlay. Self-scoped
   here (it was previously styled from Lesson.razor.css via ::deep, which can't reach the overlay's
   top-layer <dialog>). Plain copy, no urgency theater. */
.ff-pricing-panel[b-y4d3h2yiy0] {
    background-color: var(--ff-tutor-bubble-bg) !important;
    border: 1px solid var(--ff-tutor-bubble-border) !important;
    border-radius: 10px !important;
    padding: 16px 18px !important;
}

.ff-pricing-head[b-y4d3h2yiy0] {
    margin-bottom: 12px;
}

.ff-pricing-title[b-y4d3h2yiy0] {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--ff-chat-text);
}

.ff-pricing-intro[b-y4d3h2yiy0] {
    font-size: 13px;
    color: var(--ff-chat-text-muted);
    margin-top: 2px;
}

.ff-pricing-tiers[b-y4d3h2yiy0] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.ff-pricing-tier[b-y4d3h2yiy0] {
    flex: 1 1 140px;
    border: 1px solid var(--ff-tutor-bubble-border);
    border-radius: 8px;
    padding: 12px 14px;
}

.ff-pricing-tier-featured[b-y4d3h2yiy0] {
    border-color: rgba(var(--ff-accent-purple), 0.6);
    box-shadow: 0 0 0 1px rgba(var(--ff-accent-purple), 0.25) inset;
}

.ff-pricing-tier-name[b-y4d3h2yiy0] {
    font-weight: 600;
    color: var(--ff-chat-text);
}

.ff-pricing-tier-price[b-y4d3h2yiy0] {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--ff-chat-text);
    margin: 4px 0;
}

.ff-pricing-tier-blurb[b-y4d3h2yiy0] {
    font-size: 12.5px;
    color: var(--ff-chat-text-muted);
    line-height: 1.4;
}

.ff-pricing-note[b-y4d3h2yiy0] {
    margin-top: 12px;
    font-size: 12px;
    color: var(--ff-chat-text-faint);
}
/* /Components/Chat/Stats/LearnerDashboardMessage.razor.rz.scp.css */
/* Scoped to LearnerDashboardMessage. Theme-aware progress card — light by default, dark slate under
   the app's `.fox` dark-mode class (the Blazor scoper rewrites `.fox .ff-dashboard` to
   `.fox .ff-dashboard[scope]`, so the html-level theme class works from inside this scoped file).
   All theme-dependent colors flow through the --dash-* variables; layout rules below are shared.
   Tiles + an activity heatmap; FluentFox orange for the accent. */

.ff-dashboard[b-nv2sli4li0] {
    /* Light theme (default) */
    --dash-bg: #ffffff;
    --dash-border: #e2e8f0;        /* slate-200 */
    --dash-text: #334155;          /* slate-700 */
    --dash-title: #0f172a;         /* slate-900 */
    --dash-muted: #64748b;         /* slate-500 */
    --dash-tile-bg: #f8fafc;       /* slate-50 */
    --dash-foot: #475569;          /* slate-600 */
    --dash-shadow: 0 6px 20px rgba(15, 23, 42, 0.08);
    --dash-heat-empty: #e2e8f0;    /* slate-200 */
    --dash-heat-l1: #fed7aa;       /* orange-200 */
    --dash-heat-l2: #fdba74;       /* orange-300 */
    --dash-heat-l3: #f97316;       /* orange-500 */
    --dash-heat-l4: #c2410c;       /* orange-700 */
}

.fox .ff-dashboard[b-nv2sli4li0] {
    /* Dark theme — the original slate panel */
    --dash-bg: #1e293b;            /* slate-800 */
    --dash-border: #334155;        /* slate-700 */
    --dash-text: #e2e8f0;          /* slate-200 */
    --dash-title: #f8fafc;         /* slate-50 */
    --dash-muted: #94a3b8;         /* slate-400 */
    --dash-tile-bg: #0f172a;       /* slate-900 */
    --dash-foot: #cbd5e1;          /* slate-300 */
    --dash-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
    --dash-heat-empty: #334155;    /* slate-700 */
    --dash-heat-l1: #7c2d12;       /* orange-900 */
    --dash-heat-l2: #c2410c;       /* orange-700 */
    --dash-heat-l3: #f97316;       /* orange-500 */
    --dash-heat-l4: #fdba74;       /* orange-300 */
}

.ff-dashboard[b-nv2sli4li0] {
    width: 100%;
    max-width: 660px;
    margin: 4px auto 12px;
    padding: 16px 18px;
    border-radius: 14px;
    background: var(--dash-bg);
    border: 1px solid var(--dash-border);
    color: var(--dash-text);
    box-shadow: var(--dash-shadow);
}

/* ── Header ─────────────────────────────────────────────────────────────── */
.ff-dash-head[b-nv2sli4li0] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
}

.ff-dash-fox[b-nv2sli4li0] {
    font-size: 20px;
    line-height: 1;
}

.ff-dash-title[b-nv2sli4li0] {
    font-weight: 700;
    font-size: 15px;
    color: var(--dash-title);
}

.ff-dash-since[b-nv2sli4li0] {
    margin-left: auto;
    font-size: 12px;
    color: var(--dash-muted);
}

/* ── Stat tiles ─────────────────────────────────────────────────────────── */
.ff-dash-tiles[b-nv2sli4li0] {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin-bottom: 16px;
}

.ff-tile[b-nv2sli4li0] {
    background: var(--dash-tile-bg);
    border: 1px solid var(--dash-border);
    border-radius: 10px;
    padding: 10px 12px;
    min-width: 0;
}

.ff-tile-label[b-nv2sli4li0] {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--dash-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ff-tile-value[b-nv2sli4li0] {
    margin-top: 4px;
    font-size: 22px;
    font-weight: 700;
    color: var(--dash-title);
    line-height: 1.1;
}

.ff-tile-unit[b-nv2sli4li0] {
    font-size: 13px;
    font-weight: 600;
    color: var(--dash-muted);
    margin-left: 2px;
}

/* ── Activity heatmap ───────────────────────────────────────────────────── */
.ff-dash-heatmap[b-nv2sli4li0] {
    display: flex;
    gap: 3px;
    padding: 2px 0;
    overflow-x: auto;
}

.ff-heat-col[b-nv2sli4li0] {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.ff-heat-cell[b-nv2sli4li0] {
    width: 13px;
    height: 13px;
    border-radius: 3px;
    background: var(--dash-heat-empty);
}

/* Future days in the current week — invisible spacers so the grid stays rectangular. */
.ff-heat-future[b-nv2sli4li0] {
    background: transparent;
}

.ff-heat-l0[b-nv2sli4li0] { background: var(--dash-heat-empty); }  /* no lessons */
.ff-heat-l1[b-nv2sli4li0] { background: var(--dash-heat-l1); }
.ff-heat-l2[b-nv2sli4li0] { background: var(--dash-heat-l2); }
.ff-heat-l3[b-nv2sli4li0] { background: var(--dash-heat-l3); }
.ff-heat-l4[b-nv2sli4li0] { background: var(--dash-heat-l4); }

/* ── Bottom row: streak line (left) + Share button pinned bottom-right ────── */
.ff-dash-bottom[b-nv2sli4li0] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 14px;
}

.ff-dash-foot[b-nv2sli4li0] {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    color: var(--dash-foot);
}

/* Narrow screens — two tile columns instead of four. */
@media (max-width: 520px) {
    .ff-dash-tiles[b-nv2sli4li0] {
        grid-template-columns: repeat(2, 1fr);
    }
}
/* /Components/Chat/Stats/StatsResultMessage.razor.rz.scp.css */
/* Scoped to StatsResultMessage. The chip + bubble styling is inherited from Lesson.razor.css's
   ::deep rules (this component renders inside the lesson message wrapper); only the chart's
   expand affordance is local here, because Lesson's .ff-img-expand is plain-scoped to that page
   and so does not reach a child component. Mirrors .ff-img-expand's look for a consistent cue. */

.ff-stats-chart-inline[b-mulm4enjtd] {
    position: relative;
}

.ff-stats-expand[b-mulm4enjtd] {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    border: none;
    background: rgba(0, 0, 0, 0.5);
    color: #ffffff;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, transform 0.15s;
}

.ff-stats-expand:hover[b-mulm4enjtd] {
    background: rgba(0, 0, 0, 0.75);
    transform: scale(1.08);
}

/* Text-result totals — keep any newlines the builder emits, wrap normally otherwise. */
.ff-stats-text[b-mulm4enjtd] {
    white-space: pre-line;
    line-height: 1.6;
}
/* /Components/Chat/SuggestionsBar.razor.rz.scp.css */
/* Scoped to SuggestionsBar. Sizing wrapper for the shared FlagEmoji glyph on language-name chips
   (the font itself is declared in FlagEmoji.razor.css); non-language chips render no flag. */
.ff-chip-flag[b-x77ogii211] {
    font-size: 1.4em;
    line-height: 1;
    vertical-align: -0.15em;    /* optically center against the chip label */
    margin-right: 5px;
}
/* /Components/Chat/WelcomeBackCardMessage.razor.rz.scp.css */
/* Scoped to WelcomeBackCardMessage. Light theme is the warm-coral palette (coral gradient header,
   espresso text on white); dark swaps to the purple/slate look under the app's `.fox` class (the
   Blazor scoper rewrites `.fox .ff-wb-card` to a scoped selector, so the html-level theme class
   works from inside this file). Buttons are sized to the app's standard chat pill
   (.ff-suggestion-btn: radius 16px, padding 5px 16px, 13px). */

.ff-wb-card[b-lc2mqiuktw] {
    /* Light theme (default) — warm coral */
    --wb-body-bg: #ffffff;
    --wb-header-gradient: linear-gradient(120deg, #E8552E 0%, #F47A45 100%);
    --wb-question: #4A2417;
    --wb-name: #4A2417;
    --wb-age: #B79B8E;
    --wb-accent: #E8552E;
    --wb-tile-bg: #FBF0EA;
    --wb-tile-value: #4A2417;
    --wb-primary-bg: linear-gradient(120deg, #E8552E 0%, #F47A45 100%);
    --wb-secondary-border: #EDD3C4;
    --wb-secondary-text: #A9451F;
    --wb-secondary-hover: #FBF0EA;
    --wb-shadow: 0 8px 30px rgba(122, 46, 26, 0.12);
}

.fox .ff-wb-card[b-lc2mqiuktw] {
    /* Dark theme — purple header, deep slate body, lifted lilac text (matches the plan card) */
    --wb-body-bg: #1e293b;                        /* slate-800 */
    --wb-header-gradient: linear-gradient(120deg, #6D28D9 0%, #8B5CF6 100%);
    --wb-question: #f1f5f9;                       /* slate-100 */
    --wb-name: #f1f5f9;
    --wb-age: #94a3b8;                            /* slate-400 */
    --wb-accent: #a78bfa;                         /* violet-400 */
    --wb-tile-bg: #273449;
    --wb-tile-value: #f1f5f9;
    --wb-primary-bg: linear-gradient(120deg, #7C3AED 0%, #8B5CF6 100%);
    --wb-secondary-border: #3b4a63;
    --wb-secondary-text: #e2e8f0;
    --wb-secondary-hover: #273449;
    --wb-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}

/* Flag glyphs render via the shared FlagEmoji component (which owns the subset-font declaration);
   these wrappers only size and align its 1em glyph for their spot in the card. */
.ff-wb-flag[b-lc2mqiuktw] {
    font-size: 1.35em;          /* relative, so it reads larger beside the tile values */
    line-height: 1;             /* keep the bigger glyph from stretching the row */
    vertical-align: -0.12em;    /* optically center against the adjacent text */
    margin-right: 2px;
}

.ff-wb-card[b-lc2mqiuktw] {
    width: 100%;
    max-width: 660px;            /* match the progress dashboard card above it */
    margin: 4px auto 12px;
    border-radius: 22px;
    overflow: hidden;
    background: var(--wb-body-bg);
    box-shadow: var(--wb-shadow);
}

/* ── Gradient header: icon chip + title, learning language beneath ───────── */
.ff-wb-header[b-lc2mqiuktw] {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 22px;
    background: var(--wb-header-gradient);
}

.ff-wb-icon[b-lc2mqiuktw] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 14px;                          /* rounded square, per the design */
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
}

.ff-wb-icon svg[b-lc2mqiuktw] {
    width: 22px;
    height: 22px;
}

/* The flag-as-icon glyph — the shared FlagEmoji, sized to fill the chip. */
.ff-wb-icon-flag[b-lc2mqiuktw] {
    font-size: 28px;
    line-height: 1;
}

.ff-wb-header-text[b-lc2mqiuktw] {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.ff-wb-title[b-lc2mqiuktw] {
    color: #fff;
    font-size: 20px;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.ff-wb-learning[b-lc2mqiuktw] {
    display: inline-flex;
    align-items: center;        /* mixed font sizes — center the label on the larger flag + language */
    gap: 7px;
    font-size: 14px;
}

.ff-wb-learning-label[b-lc2mqiuktw] {
    color: rgba(255, 255, 255, 0.75);
    font-weight: 600;
}

.ff-wb-learning-value[b-lc2mqiuktw] {
    color: #fff;
    font-weight: 800;
    font-size: 18px;            /* larger than the "Learning" label — the language is the point */
}

/* ── Body: the question + any remaining profile detail ───────────────────── */
.ff-wb-body[b-lc2mqiuktw] {
    padding: 16px 22px 18px;
}

.ff-wb-question[b-lc2mqiuktw] {
    font-size: 16px;
    font-weight: 800;
    color: var(--wb-question);
}

.ff-wb-name-row[b-lc2mqiuktw] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 10px;
}

.ff-wb-name[b-lc2mqiuktw] {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--wb-name);
}

.ff-wb-age[b-lc2mqiuktw] {
    font-size: 14px;
    font-weight: 700;
    color: var(--wb-age);
}

.ff-wb-tiles[b-lc2mqiuktw] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
    margin-top: 12px;
}

.ff-wb-tile[b-lc2mqiuktw] {
    padding: 12px 16px;
    border-radius: 14px;
    background: var(--wb-tile-bg);
}

.ff-wb-tile-label[b-lc2mqiuktw] {
    margin-bottom: 4px;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--wb-accent);
}

.ff-wb-tile-value[b-lc2mqiuktw] {
    font-size: 16px;
    font-weight: 700;
    color: var(--wb-tile-value);
}

/* ── Actions — the standard chat pill size (.ff-suggestion-btn spec) ─────── */
.ff-wb-actions[b-lc2mqiuktw] {
    display: flex;
    flex-wrap: wrap;            /* the multi-profile picker can carry several language pills */
    gap: 10px;
    margin-top: 14px;
}

.ff-wb-btn-primary[b-lc2mqiuktw],
.ff-wb-btn-secondary[b-lc2mqiuktw] {
    display: inline-flex;       /* centers the flag glyph beside the label */
    align-items: center;
    gap: 6px;
    border-radius: 16px;
    padding: 5px 16px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}

.ff-wb-btn-primary[b-lc2mqiuktw] {
    border: 1px solid transparent;
    background: var(--wb-primary-bg);
    color: #fff;
}

.ff-wb-btn-primary:hover[b-lc2mqiuktw] {
    filter: brightness(1.08);
}

.ff-wb-btn-secondary[b-lc2mqiuktw] {
    border: 1px solid var(--wb-secondary-border);
    background: transparent;
    color: var(--wb-secondary-text);
}

.ff-wb-btn-secondary:hover[b-lc2mqiuktw] {
    background: var(--wb-secondary-hover);
}
/* /Components/Chat/WelcomeBackMessage.razor.rz.scp.css */
/* Split-hero welcome-back card in a modal <dialog> over the dimmed lesson. Surfaces and text come
   from the --ff-wb-* theme tokens (tailwind.source.css: light on :root, deep navy on .fox — scoped
   CSS can't see the html-level .fox class, but custom properties inherit through any scope); the
   MrFox-orange accent (primary button, focus rings, mascot glow) and the white inputs are constant
   across themes. The child InlineLoginForm carries its own scoped base styles (it also renders in
   the nav popover); the ::deep rules below restyle it to the hero's larger scale. */

.ff-welcome-back-dialog[b-s1bh7c6vjc] {
    border: none;
    padding: 0;
    margin: auto;                 /* center in the viewport; the backdrop fills around it */
    width: min(960px, 94vw);
    max-height: 90vh;
    background: transparent;      /* the card paints the surface */
    overflow: visible;
}

.ff-welcome-back-dialog[b-s1bh7c6vjc]::backdrop {
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}

.ff-welcome-back[b-s1bh7c6vjc] {
    display: grid;
    grid-template-columns: 46% 54%;
    width: 100%;
    max-height: 90vh;
    overflow: hidden auto;        /* short screens scroll INSIDE the card */
    border: 1px solid var(--ff-wb-card-border);
    border-radius: 20px;
    background: var(--ff-wb-card-bg);
    box-shadow: var(--ff-wb-shadow);
    color: var(--ff-wb-body);
}

/* ── Brand panel ── */

.ff-wb-brand[b-s1bh7c6vjc] {
    display: flex;
    flex-direction: column;
    padding: 32px 36px;
    background: var(--ff-wb-brand-bg);
}

.ff-wb-logo[b-s1bh7c6vjc] {
    width: 170px;
    align-self: flex-start;
}

.ff-wb-mascot[b-s1bh7c6vjc] {
    position: relative;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 0;
    min-height: 240px;
}

/* Soft orange bloom behind the fox — ties the mascot into the accent color so he reads as part
   of the brand rather than a pasted-on graphic. */
.ff-wb-mascot[b-s1bh7c6vjc]::before {
    content: "";
    position: absolute;
    width: 320px;
    height: 320px;
    max-width: 95%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(241, 90, 36, 0.28) 0%, transparent 70%);
}

.ff-wb-mascot img[b-s1bh7c6vjc] {
    position: relative;
    width: 250px;
    max-width: 65%;
    animation: ff-wb-float-b-s1bh7c6vjc 5s ease-in-out infinite;
}

@keyframes ff-wb-float-b-s1bh7c6vjc {
    0%, 100% { transform: translateY(7px); }
    50%      { transform: translateY(-7px); }
}

@media (prefers-reduced-motion: reduce) {
    .ff-wb-mascot img[b-s1bh7c6vjc] {
        animation: none;
    }
}

.ff-wb-tagline h2[b-s1bh7c6vjc] {
    margin: 0 0 10px;
    font-size: 1.7rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--ff-wb-heading);
}

.ff-wb-tagline p[b-s1bh7c6vjc] {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.6;
    color: var(--ff-wb-body);
}

/* ── Form panel ── */

.ff-wb-form[b-s1bh7c6vjc] {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 44px 48px;
}

.ff-wb-title[b-s1bh7c6vjc] {
    margin: 0 0 6px;
    font-size: 1.9rem;
    font-weight: 600;
    color: var(--ff-wb-heading);
}

.ff-wb-sub[b-s1bh7c6vjc] {
    margin: 0 0 22px;
    font-size: 0.95rem;
    color: var(--ff-wb-body);
}

/* Scale the shared inline login form up to the hero: full-width fields, roomier padding, and the
   MrFox-orange primary button in place of the stock indigo e-primary. */
.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login {
    max-width: none;
    gap: 14px;
}

.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login-field {
    gap: 6px;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--ff-wb-label);
}

.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login-field input {
    padding: 12px 16px;
    border: 1px solid #d6dce4;
    border-radius: 10px;
    font-size: 15px;
    color: #1a2332;
}

.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login-field input:focus {
    outline: none;
    border-color: #f15a24;
    box-shadow: 0 0 0 3px rgba(241, 90, 36, 0.18);
}

.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login-remember {
    color: var(--ff-wb-label);
    accent-color: #f15a24;
}

.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login button[type="submit"] {
    align-self: stretch;
    margin-top: 6px;
    padding: 14px;
    border: none;
    border-radius: 10px;
    background: #f15a24;
    color: #fff;
    font-size: 16px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 10px 24px rgba(241, 90, 36, 0.32);
    transition: background 0.15s ease;
}

.ff-wb-form[b-s1bh7c6vjc]  .ff-inline-login button[type="submit"]:hover {
    background: #e14e1b;
}

/* ── Secondary actions: Register / Continue as guest as 50/50 ghost buttons ── */

.ff-welcome-back-actions[b-s1bh7c6vjc] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-top: 14px;
}

.ff-wb-ghost[b-s1bh7c6vjc] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 8px;
    border: 1px solid var(--ff-wb-ghost-border);
    border-radius: 10px;
    background: transparent;
    color: var(--ff-wb-label);
    font-size: 15px;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.ff-wb-ghost:hover[b-s1bh7c6vjc] {
    border-color: var(--ff-wb-ghost-hover-border);
    background: var(--ff-wb-ghost-hover-bg);
    color: var(--ff-wb-label);
}

/* ── Narrow screens: single column, form only (the brand panel is a nice-to-have) ── */

@media (max-width: 860px) {
    .ff-welcome-back[b-s1bh7c6vjc] {
        grid-template-columns: 1fr;
    }

    .ff-wb-brand[b-s1bh7c6vjc] {
        display: none;
    }

    .ff-wb-form[b-s1bh7c6vjc] {
        padding: 28px 24px;
    }
}

/* Mobile: full-width slide-up bottom sheet, same treatment as ContentOverlay. */
@media (max-width: 560px) {
    .ff-welcome-back-dialog[b-s1bh7c6vjc] {
        width: 100vw;
        max-width: 100vw;
        margin: auto 0 0;          /* pin to the bottom of the viewport */
    }

    .ff-welcome-back[b-s1bh7c6vjc] {
        border-radius: 16px 16px 0 0;
    }

    .ff-welcome-back-dialog[open][b-s1bh7c6vjc] {
        animation: ff-wb-slide-up-b-s1bh7c6vjc 0.25s ease-out;
    }

    /* Stacked full-width buttons — side-by-side they'd be too cramped to tap comfortably. */
    .ff-welcome-back-actions[b-s1bh7c6vjc] {
        grid-template-columns: 1fr;
        gap: 10px;
    }
}

@keyframes ff-wb-slide-up-b-s1bh7c6vjc {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-7mmc6k0zbu] {
    position: relative;
    display: flex;
    flex-direction: column;
}

main[b-7mmc6k0zbu] {
    flex: 1;
}

.sidebar[b-7mmc6k0zbu] {
    background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

.top-row[b-7mmc6k0zbu] {
    background-color: #f7f7f7;
    border-bottom: 1px solid #d6d5d5;
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

    .top-row[b-7mmc6k0zbu]  a, .top-row[b-7mmc6k0zbu]  .btn-link {
        white-space: nowrap;
        margin-left: 1.5rem;
        text-decoration: none;
    }

    .top-row[b-7mmc6k0zbu]  a:hover, .top-row[b-7mmc6k0zbu]  .btn-link:hover {
        text-decoration: underline;
    }

    .top-row[b-7mmc6k0zbu]  a:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
    }

@media (max-width: 640.98px) {
    .top-row[b-7mmc6k0zbu] {
        justify-content: space-between;
    }

    .top-row[b-7mmc6k0zbu]  a, .top-row[b-7mmc6k0zbu]  .btn-link {
        margin-left: 0;
    }
}

@media (min-width: 641px) {
    .page[b-7mmc6k0zbu] {
        flex-direction: row;
    }

    .sidebar[b-7mmc6k0zbu] {
        width: 250px;
        height: 100vh;
        position: sticky;
        top: 0;
    }

    .top-row[b-7mmc6k0zbu] {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .top-row.auth[b-7mmc6k0zbu]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-7mmc6k0zbu], article[b-7mmc6k0zbu] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }
}

/* NOTE: #blazor-error-ui is styled GLOBALLY in tailwind.source.css, not here. It's a framework
   singleton shared by every layout (MainLayout AND AccountLayout); a scoped rule here only matched
   MainLayout's copy, leaving AccountLayout's div permanently visible ("An unhandled error has
   occurred" with no error). Keep it unscoped so `display: none` applies everywhere. */
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-obhcwastue],
.components-reconnect-repeated-attempt-visible[b-obhcwastue],
.components-reconnect-failed-visible[b-obhcwastue],
.components-pause-visible[b-obhcwastue],
.components-resume-failed-visible[b-obhcwastue],
.components-rejoining-animation[b-obhcwastue] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-obhcwastue],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-obhcwastue],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-obhcwastue],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-obhcwastue],
#components-reconnect-modal.components-reconnect-retrying[b-obhcwastue],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-obhcwastue],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-obhcwastue],
#components-reconnect-modal.components-reconnect-failed[b-obhcwastue],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-obhcwastue] {
    display: block;
}


#components-reconnect-modal[b-obhcwastue] {
    /* Theme-aware, softened panel instead of a stark pure-white box — a gentle off-white in light
       mode and the slate card colour in dark, so it doesn't jar over the dimmed page. Tokens
       inherit from :root / .fox (app.css); referencing them via var() is scope-safe (only
       `.fox descendant` selectors break under CSS isolation, which we don't use here). */
    background-color: var(--ff-tutor-bubble-bg, #eef1f6);
    color: var(--ff-chat-text, #1a1a2e);
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 1px solid var(--ff-chat-column-border, #e6e6ef);
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-obhcwastue 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-obhcwastue 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-obhcwastue 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-obhcwastue]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-obhcwastue 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-obhcwastue {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-obhcwastue {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-obhcwastue {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-obhcwastue] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-obhcwastue] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-obhcwastue] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-obhcwastue] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-obhcwastue] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-obhcwastue] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-obhcwastue] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-obhcwastue 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-obhcwastue] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-obhcwastue {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Lesson.razor.rz.scp.css */
/* Lesson page scoped styles — the rich ff-* card styling, reused via ::deep into the leaf message
   components that FfChatUi's EntryTemplate renders.

   The EntryTemplate is authored in this page (Lesson.razor), so its rendered leaves carry this page's
   scope and these ::deep rules pierce into them. Because FfChatUi has no Syncfusion `.e-chat-ui` base,
   this file also supplies the base `.e-message-content` bubble plus the student-green hook. The owned
   mic footer, inline image / lightbox, and etymology styles live further down. */

/* ── Base bubble (replaces Syncfusion's `.e-chat-ui .e-message-content`) ── */
[b-v9s3hk0fve] .e-message-content {
    display: inline-block;
    max-width: 100%;
    background: var(--ff-bubble-bg);
    color: var(--ff-chat-text);
    border-radius: 12px;
    padding: 10px 14px;
    line-height: 1.5;
    white-space: normal !important;
    word-wrap: break-word;
    overflow-wrap: anywhere;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

/* The default (tutor) bubble would otherwise be white-on-white now that the chat column is its own
   white sheet — give the tutor's plain bubbles a soft neutral tint + hairline so they read as cards.
   Every other speaker/card (student green, status lavender, score, the pastel drill cards, coral
   tests) sets its own background below, so this only touches the plain tutor prompts. */
[b-v9s3hk0fve] .ff-mw-tutor .e-message-content,
[b-v9s3hk0fve] .ff-mw-convertprompt .e-message-content,
[b-v9s3hk0fve] .ff-mw-gettingstartedvideo .e-message-content {
    background: var(--ff-tutor-bubble-bg);
    border: 1px solid var(--ff-tutor-bubble-border);
    border-bottom-left-radius: 4px;                 /* speech tail — tight corner on the speaker's side */
    box-shadow: 0 1px 2px rgba(60, 45, 20, 0.05);   /* warm whisper — the third lift cue alongside fill + border */
}

/* Guest-conversion bubble ("Save your progress" / hard gate): tutor-styled bubble with a primary
   Create-account link, then an inline login form — the in-transcript replacement for the old modal +
   auth popup. The child ConvertPromptMessage / InlineLoginForm render inside this page's
   EntryTemplate, so these ::deep rules reach their elements (same pattern as welcome-back). */
[b-v9s3hk0fve] .ff-mw-convertprompt .ff-convert-actions {
    margin-top: 12px;
}

/* A quiet "Log in" section header above the inline form, separating the create-account path from the
   already-have-an-account path. */
[b-v9s3hk0fve] .ff-mw-convertprompt .ff-convert-login {
    margin-top: 14px;
    border-top: 1px solid var(--ff-tutor-bubble-border);
    padding-top: 12px;
}

[b-v9s3hk0fve] .ff-mw-convertprompt .ff-convert-login-label {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--ff-chat-text-muted);
    margin-bottom: 8px;
}

/* The form itself is styled by InlineLoginForm's own scoped CSS; here we only own the spacing. */
[b-v9s3hk0fve] .ff-mw-convertprompt .ff-inline-login {
    margin-top: 0;
}

/* Welcome-back login: a split-hero card in a modal <dialog> over the dimmed lesson — all of its
   styling lives in WelcomeBackMessage.razor.css, and the open dialog sits in the top layer, so its
   transcript wrapper renders nothing inline. This page keeps only the progressive-disclosure rule
   below, which spans two child components (the WelcomeBackMessage actions row keyed off the
   InlineLoginForm email field) and so needs this page's ::deep reach.

   Progressive disclosure: the moment the learner starts typing an email, the path is "log in" — so
   hide the secondary Register / Continue-as-guest buttons to keep one obvious action. They return as
   soon as the field is cleared. Pure CSS: the email input always carries a placeholder, so
   :placeholder-shown is true only while it's empty. */
[b-v9s3hk0fve] .ff-mw-welcomebacklogin .ff-welcome-back:has(input[name="email"]:not(:placeholder-shown)) .ff-welcome-back-actions {
    display: none;
}

/* Getting Started video: a click-to-watch poster in the bubble (the first frame), capped so it never
   dominates the column. Clicking it opens the lightbox below. The child component is rendered inside
   this page's EntryTemplate, so ::deep reaches its elements. */

/* Intro heading embedded in the video bubble (was a separate tutor line). */
[b-v9s3hk0fve] .ff-getting-started-video .ff-gs-heading {
    font-weight: 600;
    color: var(--ff-chat-text);
    margin-bottom: 2px;
}

[b-v9s3hk0fve] .ff-gs-video-wrap {
    position: relative;
    display: inline-block;
    width: 100%;
    max-width: 480px;
    margin-top: 8px;
    cursor: pointer;
}

[b-v9s3hk0fve] .ff-gs-video-wrap .ff-gs-video {
    display: block;
    width: 100%;
    /* preload=none means no metadata, so the element can't learn the clip's real aspect ratio — pin a
       standard 16:9 box and let the poster fill it. Make the uploaded .png 16:9 (e.g. 1280x720) to match. */
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 10px;
    background: #000;
    pointer-events: none;   /* the wrapper owns the click — the poster never plays inline */
}

/* Centered play glyph over the poster — the "watch" affordance, kept visible (not hover-gated) so
   it reads on touch too. Click-through so the wrapper handles the open. */
[b-v9s3hk0fve] .ff-gs-video-wrap .ff-gs-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    color: #ffffff;
    font-size: 26px;
    line-height: 64px;
    text-align: center;
    padding-left: 4px;        /* optically center the triangle */
    pointer-events: none;
    transition: background 0.15s, transform 0.15s;
}

[b-v9s3hk0fve] .ff-gs-video-wrap:hover .ff-gs-play {
    background: rgba(0, 0, 0, 0.75);
    transform: translate(-50%, -50%) scale(1.08);
}

[b-v9s3hk0fve] .ff-getting-started-video .ff-getting-started-video-actions {
    margin-top: 10px;
}

/* Hint shown in place of Continue until the student starts the video. */
[b-v9s3hk0fve] .ff-getting-started-video .ff-gs-watch-hint {
    font-size: 0.85rem;
    font-style: italic;
    opacity: 0.7;
}

/* The expanded player in the lightbox — mirrors `.ff-lightbox img`. Plain (page-scoped), since the
   lightbox is authored lexically in Lesson.razor. */
.ff-lightbox-video[b-v9s3hk0fve] {
    max-width: 90vw;
    max-height: 90vh;
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
    background: #000;
    cursor: default;
}

[b-v9s3hk0fve] .e-message-content .e-text {
    white-space: normal;
}

/* Full-width phase divider (e.g. "Set Up", "Device check") — centered label with a hairline rule
   reaching both edges of the chat column, à la Teams' "Last read" separator. The wrapper is forced
   to full width so the divider isn't shrunk to its label. */
[b-v9s3hk0fve] .ff-mw-sectiondivider {
    width: 100%;
}

[b-v9s3hk0fve] .ff-section-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    margin: 10px 0;
}

[b-v9s3hk0fve] .ff-section-divider::before,
[b-v9s3hk0fve] .ff-section-divider::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--ff-tutor-bubble-border, rgba(255, 255, 255, 0.15));
}

[b-v9s3hk0fve] .ff-section-divider > span {
    flex: 0 0 auto;
    color: var(--ff-chat-text);
    opacity: 0.7;
    font-weight: 700;
    font-size: 0.78rem;
    letter-spacing: 0.05em;
    white-space: nowrap;
}

/* ── Per-entry wrapper + student-green hook (Syncfusion supplied neither) ── */
[b-v9s3hk0fve] .ff-message-wrapper {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    max-width: 100%;
    min-width: 0;
}

[b-v9s3hk0fve] .ff-mw-student {
    align-items: flex-end;
}

/* Initial page-load spinner — centered over the lesson surface while the opening cold-open door is
   being generated (before any transcript entry exists). Absolutely positioned against the
   position:relative .ff-lesson-surface so it sits dead-center, not in the transcript flow. */
.ff-initial-loading[b-v9s3hk0fve] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
}

[b-v9s3hk0fve] .ff-mw-student .e-message-content {
    background: #27ae60;
    color: #ffffff;
}

/* Student bubble with a "replay what I said" button — text and button on one line. */
[b-v9s3hk0fve] .ff-mw-student .e-message-content.ff-has-replay {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

/* White-on-green variant of ff-play-btn so it reads on the student bubble. */
[b-v9s3hk0fve] .ff-mw-student .ff-student-replay {
    margin: 0;
    flex: none;
    width: 24px;
    height: 24px;
    border-color: rgba(255, 255, 255, 0.6);
    color: rgba(255, 255, 255, 0.9);
}

[b-v9s3hk0fve] .ff-mw-student .ff-student-replay:hover {
    background: rgba(255, 255, 255, 0.15);
    border-color: #ffffff;
    color: #ffffff;
}

[b-v9s3hk0fve] .ff-mw-student .e-text {
    color: #ffffff;
}

/* Center the lesson illustration in its row — the one non-text card, so it reads as a deliberate
   break from the left-aligned bubble stack. The wrapper fills the row width and centers the
   inline-block image (and its absolutely-pinned expand button rides along, top-right of the image). */
[b-v9s3hk0fve] .ff-mw-image {
    width: 100%;
    align-items: center;
}

/* Center the returning-student progress card the same way: its wrapper would otherwise
   shrink-wrap and sit at the row's flex-start, leaving the card hugging the left rail. */
[b-v9s3hk0fve] .ff-mw-learnerdashboard {
    width: 100%;
    align-items: center;
}

/* Lesson-plan card — same near-full-width, centered treatment as the dashboard card. */
[b-v9s3hk0fve] .ff-mw-lessonplancard {
    width: 100%;
    align-items: center;
}

/* Welcome-back card (returning-learner gates + the multi-language picker) — same treatment. */
[b-v9s3hk0fve] .ff-mw-welcomebackcard {
    width: 100%;
    align-items: center;
}

/* ── Status / system messages (Welcome, Profile, Session complete) ── */
[b-v9s3hk0fve] .ff-status-message {
    background-color: var(--ff-status-bg) !important;
    border-left: 4px solid #8e44ad;
    border-radius: 12px !important;
    padding: 8px 12px !important;
    color: var(--ff-status-text);
}

[b-v9s3hk0fve] .ff-status-message .e-text {
    text-align: left;
}

/* Transient status spinners (Generating lesson… / Starting lesson…) — plain and subtle,
   no coloured band, so they read as fleeting app chatter rather than an exchange card. */
[b-v9s3hk0fve] .ff-status-message-plain {
    background-color: var(--ff-status-plain-bg) !important;
    border-radius: 12px !important;
    padding: 8px 12px !important;
    color: var(--ff-status-plain-text);
    font-style: italic;
}

[b-v9s3hk0fve] .ff-status-message-plain .e-text {
    text-align: left;
}

/* Exchange instruction label — base style, overridden per exchange type. */
[b-v9s3hk0fve] .ff-exchange-label {
    font-size: 0.8em;
    font-weight: 600;
    font-style: normal;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.2;
    margin-bottom: 2px;
    color: var(--ff-chat-text-faint);
}

/* Collapse any default flex gap + top margin on every card type. */
[b-v9s3hk0fve] .ff-vocab-message,
[b-v9s3hk0fve] .ff-dup-message,
[b-v9s3hk0fve] .ff-model-message,
[b-v9s3hk0fve] .ff-dialog-message {
    gap: 0 !important;
    row-gap: 0 !important;
}

[b-v9s3hk0fve] .ff-dup-message .e-text,
[b-v9s3hk0fve] .ff-model-message .e-text,
[b-v9s3hk0fve] .ff-dialog-message .e-text,
[b-v9s3hk0fve] .ff-status-message .e-text {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

/* ── Vocabulary card — warm amber ── */
[b-v9s3hk0fve] .ff-vocab-message {
    background-color: var(--ff-vocab-bg) !important;
    border-left: 4px solid #e6a817 !important;
    border-radius: 12px !important;
    padding: 10px 14px !important;
    position: relative;   /* anchors the absolutely-positioned skip ⋮ in the top-right corner */
}

[b-v9s3hk0fve] .ff-vocab-message .ff-exchange-label {
    color: var(--ff-vocab-label);
}

/* Vocab body — our own class, free of Syncfusion's .e-text rules. */
[b-v9s3hk0fve] .ff-vocab-body {
    margin-top: 0;
    padding-top: 0;
}

/* Make the <em> target phrase large and prominent. */
[b-v9s3hk0fve] .ff-vocab-body em {
    display: block;
    font-size: 1.5em;
    font-weight: 700;
    font-style: italic;
    color: var(--ff-vocab-word);
    margin: 4px 0 2px;
    line-height: 1.2;
}

/* Translation line — plain, slightly muted. */
[b-v9s3hk0fve] .ff-translation {
    color: var(--ff-chat-text-muted);
    font-size: 0.95em;
    margin-bottom: 4px;
}

/* ── Duplication card — soft blue ── */
[b-v9s3hk0fve] .ff-dup-message {
    background-color: var(--ff-dup-bg) !important;
    border-left: 4px solid #3a8fd1 !important;
    border-radius: 12px !important;
    padding: 10px 14px !important;
}

[b-v9s3hk0fve] .ff-dup-message .ff-exchange-label {
    color: var(--ff-dup-label);
}

/* ── Model dialog card — soft indigo ── */
[b-v9s3hk0fve] .ff-model-message {
    background-color: var(--ff-model-bg) !important;
    border-left: 4px solid #7c5cbf !important;
    border-radius: 12px !important;
    padding: 10px 14px !important;
}

[b-v9s3hk0fve] .ff-model-message .ff-exchange-label {
    color: var(--ff-model-label);
}

[b-v9s3hk0fve] .ff-model-message .e-text {
    line-height: 1.9;
}

/* Person 1 / Person 2 lines inside a model dialog card. */
[b-v9s3hk0fve] .ff-dialog-line {
    display: flex;
    align-items: baseline;
    gap: 6px;
    padding: 3px 0;
}

[b-v9s3hk0fve] .ff-person-label {
    font-weight: 700;
    color: var(--ff-model-label);
    white-space: nowrap;
    min-width: 4.5em;
}

[b-v9s3hk0fve] .ff-dialog-text {
    color: var(--ff-chat-text);
}

/* ── Dialog (Scenario model) card — soft green ── */
[b-v9s3hk0fve] .ff-dialog-message {
    background-color: var(--ff-dialog-bg) !important;
    border-left: 4px solid #27ae60 !important;
    border-radius: 12px !important;
    padding: 10px 14px !important;
}

[b-v9s3hk0fve] .ff-dialog-message .ff-exchange-label {
    color: var(--ff-dialog-label);
}

/* ── Score message — plain background, colour-coded text ── */
[b-v9s3hk0fve] .ff-score-message {
    background-color: var(--ff-score-bg) !important;
    border: 1px solid var(--ff-score-border) !important;
    border-radius: 12px !important;
    padding: 4px 12px !important;
    font-weight: 500;
}

[b-v9s3hk0fve] .ff-score-pass .e-text    { color: var(--ff-score-pass); }
[b-v9s3hk0fve] .ff-score-partial .e-text { color: var(--ff-score-partial); }
[b-v9s3hk0fve] .ff-score-fail .e-text    { color: var(--ff-score-fail); }

/* Speaker label — "Tutor:". */
[b-v9s3hk0fve] .ff-speaker {
    font-weight: 600;
    margin-right: 4px;
}

/* Dictionary-style usage + pronunciation guides shown under the vocabulary word. */
[b-v9s3hk0fve] .ff-usage-note {
    color: var(--ff-chat-text-soft);
    font-size: 13px;
    margin-top: 4px;
}

[b-v9s3hk0fve] .ff-pronunciation {
    font-style: italic;
    color: var(--ff-chat-text-faint);
    font-size: 13px;
    margin-top: 4px;
    letter-spacing: 0.3px;
}

/* Pronunciation tip — a grapheme sound note shown just beneath the phonetic guide. A plain,
   readable sentence (not italic like the phonetic line), softly coloured so it reads as a friendly
   aside rather than required content. */
[b-v9s3hk0fve] .ff-pronunciation-tip {
    color: var(--ff-chat-text-soft);
    font-size: 13px;
    line-height: 1.4;
    margin-top: 5px;
}

/* ── Language tip — a standalone big-picture card shown at the start of a lesson. Cooler accent
   (purple) so it reads as distinct from the amber vocabulary card; calm and inviting, not a drill. */
[b-v9s3hk0fve] .ff-language-tip-message {
    position: relative;
    background: var(--ff-tip-bg) !important;
    border: 1px solid var(--ff-tip-border) !important;
    /* Solid colored left accent (like the other cards) so it curves cleanly into the rounded corners.
       A ::before / background spine renders square-ended in this setup; only a real border follows
       the border-radius — so the accent is a single colour rather than the old orange→indigo gradient. */
    border-left: 4px solid var(--ff-tip-spine) !important;
    border-radius: 14px !important;
    padding: 16px 20px 14px 18px !important;
    box-shadow: var(--ff-tip-shadow);
    gap: 0 !important;
    row-gap: 0 !important;
}

[b-v9s3hk0fve] .ff-language-tip-header {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 10px;
}

/* Emoji sits in a small rounded amber chip (light); in dark the chip is transparent so the glyph reads plain. */
[b-v9s3hk0fve] .ff-language-tip-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: var(--ff-tip-icon-bg);
    color: var(--ff-tip-icon-color);
    font-size: 15px;
}

[b-v9s3hk0fve] .ff-language-tip-title {
    font-size: 12.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    line-height: 1.2;
    color: var(--ff-tip-eyebrow);
}

[b-v9s3hk0fve] .ff-language-tip-body {
    color: var(--ff-chat-text);
    font-size: 15.5px;
    line-height: 1.6;
    margin-bottom: 16px;
}

/* Filled indigo Continue button — scoped to the tip/RWA card only (the shared .ff-suggestion-btn
   keeps its outline style everywhere else). Light = solid indigo gradient; dark = outline violet. */
[b-v9s3hk0fve] .ff-language-tip-message .ff-card-actions {
    display: flex;
    justify-content: flex-end;
}

[b-v9s3hk0fve] .ff-language-tip-message .ff-suggestion-btn {
    border-radius: 12px !important;
    padding: 10px 20px !important;
    font-size: 15px !important;
    font-weight: 700 !important;
    background: var(--ff-tip-cta-bg) !important;
    color: var(--ff-tip-cta-text) !important;
    border: 1px solid var(--ff-tip-cta-border) !important;
    box-shadow: var(--ff-tip-cta-shadow);
    transition: filter 0.15s ease, transform 0.15s ease;
}

[b-v9s3hk0fve] .ff-language-tip-message .ff-suggestion-btn:hover {
    background: var(--ff-tip-cta-bg) !important;
    filter: brightness(1.06);
    transform: translateY(-1px);
}

/* ── Tip of the Day card ── (reuses the tip/RWA card chrome above; no Continue button) */
[b-v9s3hk0fve] .ff-tip-message .ff-tip-body {
    margin-bottom: 0;   /* no Continue button follows; the images (if any) add their own top gap */
}

[b-v9s3hk0fve] .ff-tip-images {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 14px;
}

/* Screenshots sit side by side on a wide card and wrap to a stack on a narrow one. */
[b-v9s3hk0fve] .ff-tip-images img {
    flex: 1 1 0;
    min-width: 0;
    max-width: 100%;
    height: auto;
    border-radius: 10px;
    border: 1px solid var(--ff-tip-border);
}

/* ── Key-word definition card ── */
[b-v9s3hk0fve] .ff-key-word-message {
    background-color: var(--ff-card-bg) !important;   /* shared spine-card fill — purple border/label carries the cue */
    border-left: 4px solid rgba(var(--ff-accent-purple), 0.85) !important;
    border-radius: 12px !important;
    padding: 10px 14px !important;
    gap: 0 !important;
    row-gap: 0 !important;
}

[b-v9s3hk0fve] .ff-key-word-header {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    line-height: 1.2;
    color: var(--ff-chat-text-faint);
    margin-bottom: 4px;
}

[b-v9s3hk0fve] .ff-key-word-icon {
    font-size: 14px;
}

[b-v9s3hk0fve] .ff-key-word-term {
    color: var(--ff-chat-text);
    font-size: 16px;
    font-weight: 700;
    line-height: 1.3;
    margin-bottom: 2px;
}

[b-v9s3hk0fve] .ff-key-word-definition {
    color: var(--ff-chat-text);
    font-size: 14px;
    line-height: 1.5;
}

[b-v9s3hk0fve] .ff-key-word-usage {
    color: var(--ff-chat-text);
    font-size: 14px;
    line-height: 1.5;
    margin-top: 4px;
}

[b-v9s3hk0fve] .ff-key-word-sentence {
    color: var(--ff-card-note-text);   /* italic like a dictionary example, but readable — not muted */
    font-size: 14px;
    font-style: italic;
    line-height: 1.5;
    margin-top: 4px;
}

/* The inline row labels ("Definition:", "Meaning:") — bold and quietly toned so the value leads.
   Shared by the Key Word and New Vocabulary cards so both scan identically. */
[b-v9s3hk0fve] .ff-key-word-label,
[b-v9s3hk0fve] .ff-card-label {
    font-weight: 700;
    font-style: normal;
    color: var(--ff-chat-text-faint);
}

/* ── Suggestion / Continue row ── */
[b-v9s3hk0fve] .ff-suggestion-container {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
    padding-left: 2px;
}

/* Pill-shaped suggestion + Continue buttons (Syncfusion e-btn base, available globally).
   Syncfusion's default e-primary/e-outline purple is a mid-tone that reads as low-contrast on our
   dark surfaces (the vocab bubble's slate, the chat sheet), so retint to the dark-legible
   --ff-accent-purple token (deep purple in light mode, violet-300 in dark) used by the play button
   — readable in both themes for both the suggestion bar and the LEARN card's Continue. */
[b-v9s3hk0fve] .ff-suggestion-btn {
    border-radius: 16px !important;
    padding: 5px 16px !important;
    font-size: 13px !important;
    cursor: pointer;
    color: rgb(var(--ff-action-text)) !important;
    border-color: rgb(var(--ff-action-line)) !important;
}
[b-v9s3hk0fve] .ff-suggestion-btn:hover {
    background-color: var(--ff-action-soft) !important;
}

/* ── Lesson-complete Share button ── */
[b-v9s3hk0fve] .ff-share-container {
    display: flex;
    margin-top: 10px;
    padding-left: 2px;
}
/* Quiet, pill-shaped — a low-key celebration affordance, not a loud growth CTA (friendly brand
   voice). Reuses the dark-legible accent token like the suggestion pills. */
[b-v9s3hk0fve] .ff-share-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border-radius: 16px;
    padding: 5px 16px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    background: transparent;
    color: rgb(var(--ff-accent-purple));
    border: 1px solid rgb(var(--ff-accent-purple));
    transition: background-color 0.15s;
}
[b-v9s3hk0fve] .ff-share-btn:hover {
    background-color: rgba(var(--ff-accent-purple), 0.14);
}

/* LEARN card action footer — replay pinned bottom-LEFT, Continue bottom-right. */
[b-v9s3hk0fve] .ff-card-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 10px;
}

/* Left-align the replay button (Continue stays right). Without this the base .ff-play-btn's
   margin-left:auto would shove the replay button across to sit beside Continue — the same
   override ff-action-row uses to split the replay/mic pair. */
[b-v9s3hk0fve] .ff-card-actions .ff-play-btn {
    margin-top: 0;
    margin-left: 0;
    margin-right: auto;
}

/* ── Stage 3: spoken-production cards + mic + PA breakdown ──────────────────────────────────── */

/* Test / image-prompt card — coral, signals "your turn" (cold test). Used by ImageTestMessage /
   ReadAloudMessage / RepeatTestMessage, which host the inline mic in their ff-action-row (next to
   any replay button). The base .e-message-content bubble + .ff-exchange-label are defined above. */
[b-v9s3hk0fve] .ff-image-test-message {
    background-color: var(--ff-test-bg) !important;
    border-left: 4px solid #e8835f !important;
    border-radius: 12px !important;
    padding: 10px 14px !important;
}

[b-v9s3hk0fve] .ff-image-test-message .ff-exchange-label {
    color: var(--ff-test-label);
}

/* ── Pronunciation Assessment breakdown — folded into the score bubble by HandleScoreMessage ── */

/* Row of per-word chips — each chip is the reference word + its accuracy score. */
[b-v9s3hk0fve] .ff-pa-words {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

[b-v9s3hk0fve] .ff-pa-word {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.92em;
    font-weight: 600;
    border: 1px solid transparent;
}

[b-v9s3hk0fve] .ff-pa-word .ff-pa-score {
    font-size: 0.75em;
    font-weight: 500;
    opacity: 0.8;
}

/* Colour bands — green / amber / red by accuracy. */
[b-v9s3hk0fve] .ff-pa-good { background: var(--ff-pa-good-bg); color: var(--ff-score-pass); border-color: var(--ff-pa-good-border); }
[b-v9s3hk0fve] .ff-pa-meh  { background: var(--ff-pa-meh-bg); color: var(--ff-score-partial); border-color: var(--ff-pa-meh-border); }
[b-v9s3hk0fve] .ff-pa-bad  { background: var(--ff-pa-bad-bg); color: var(--ff-score-fail); border-color: var(--ff-pa-bad-border); }

/* Syllable / phoneme detail for the worst-scoring word. */
[b-v9s3hk0fve] .ff-pa-phonemes {
    font-size: 0.85em;
    color: var(--ff-chat-text-muted);
    margin-top: 6px;
    font-weight: 400;
}

[b-v9s3hk0fve] .ff-pa-phonemes em {
    font-style: normal;
    font-weight: 600;
    color: var(--ff-chat-text);
}

[b-v9s3hk0fve] .ff-pa-phonemes .ff-pa-good { color: var(--ff-score-pass); font-weight: 600; }
[b-v9s3hk0fve] .ff-pa-phonemes .ff-pa-meh  { color: var(--ff-score-partial); font-weight: 600; }
[b-v9s3hk0fve] .ff-pa-phonemes .ff-pa-bad  { color: var(--ff-score-fail); font-weight: 600; }

/* Four aggregate scores at the bottom. */
[b-v9s3hk0fve] .ff-pa-totals {
    font-size: 0.82em;
    color: var(--ff-chat-text-soft);
    margin-top: 6px;
    font-style: italic;
    font-weight: 400;
}

/* ── Action row — replay + mic on one line (RepeatTest replay arrives with TTS in Stage 4) ── */
[b-v9s3hk0fve] .ff-action-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 10px;
}

[b-v9s3hk0fve] .ff-action-row .ff-play-btn {
    margin-top: 0;
    margin-left: 0;
    margin-right: auto;   /* left-align the replay button; the mic is pushed to the right */
}

/* Play icon button — standalone uses margin-top; inside ff-action-row it is overridden to 0. */
[b-v9s3hk0fve] .ff-play-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 10px;
    margin-left: auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1.5px solid rgba(var(--ff-accent-purple), 0.5);
    background: transparent;
    color: rgba(var(--ff-accent-purple), 0.7);
    cursor: pointer;
    font-size: 10px;
    padding: 0;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

[b-v9s3hk0fve] .ff-play-btn:hover {
    background: rgba(var(--ff-accent-purple), 0.1);
    border-color: rgba(var(--ff-accent-purple), 0.9);
    color: rgba(var(--ff-accent-purple), 1);
}

/* ── Microphone button — rendered inline in the active spoken-production card's ff-action-row
      (MicButton's internals), next to any replay button. ── */
[b-v9s3hk0fve] .ff-mic-btn {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 2px solid var(--ff-mic-button-border);
    background: var(--ff-mic-button-bg);
    color: var(--ff-mic-button-text);
    font-size: 18px;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    position: relative;        /* anchors the live-level ring (::after) while recording */
    --ff-mic-level: 0;         /* 0..1 live mic input level, set from JS each frame */
    transition: background 0.2s, border-color 0.2s, color 0.2s, transform 0.2s;
}

[b-v9s3hk0fve] .ff-mic-btn:hover:not(:disabled) {
    background: var(--ff-mic-button-hover-bg);
    border-color: var(--ff-mic-button-hover-border);
    transform: scale(1.05);
}

[b-v9s3hk0fve] .ff-mic-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

[b-v9s3hk0fve] .ff-mic-recording {
    background: #e74c3c !important;
    border-color: #c0392b !important;
    color: #ffffff;
}

/* Voice-level ring — the "we hear you" feedback. It blooms outward and brightens
   with live mic input (--ff-mic-level, set from JS each frame) so the student can
   SEE their voice is reaching the mic. A silent room leaves it as a faint armed
   halo at the button edge; talking makes it pulse with the actual sound — unlike
   the old timer-based pulse, which animated even when nothing was being heard. */
[b-v9s3hk0fve] .ff-mic-recording::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid rgba(231, 76, 60, 0.75);
    transform: scale(calc(1 + var(--ff-mic-level, 0) * 1.1));
    opacity: calc(0.18 + var(--ff-mic-level, 0) * 0.62);
    transition: transform 0.06s linear, opacity 0.06s linear;
    pointer-events: none;
}

/* Honor reduced-motion: keep the ring as a static armed halo, no live scaling. */
@media (prefers-reduced-motion: reduce) {
    [b-v9s3hk0fve] .ff-mic-recording::after {
        transform: none;
        opacity: 0.4;
        transition: none;
    }
}

[b-v9s3hk0fve] .ff-mic-icon {
    line-height: 1;
}

/* ── Stage 4: etymology (word-origin) note + hoverable dialog words ──────────────────────────── */

/* These render inside the VocabularyMessage / DialogMessage leaf components (authored in their own
   .razor files, not here), so they carry a different scope and must be reached via ::deep — exactly
   like every other card internal above. Values are lifted verbatim from Lesson.razor.css. */

/* Word-origin / word-building note shown below the pronunciation. */
[b-v9s3hk0fve] .ff-derivation {
    font-style: italic;
    color: var(--ff-card-note-text);   /* italic like a dictionary etymology, but readable — not muted */
    font-size: 14px;
    margin-top: 4px;
}

/* ── Etymology card — the full word-origin expansion, spliced into the transcript right beneath its
   vocabulary card. It renders through the generic TutorMessage, so it is reached by the
   ff-etymology-message class the entry carries on its ExchangeCss. Given the same card system as the
   New Vocabulary card it sits under — warm fill + left accent spine + eyebrow + soft shadow — but in
   its own terracotta/rose hue so the three LEARN cards read as a family, not clones. */
[b-v9s3hk0fve] .ff-etymology-message {
    background: var(--ff-etym-bg) !important;
    border: 1px solid var(--ff-etym-border) !important;
    /* Solid colored spine (a real border-left, so it follows the 18px radius cleanly — a ::before
       spine renders square-ended here, matching how the Language Tip card does it). */
    border-left: 5px solid var(--ff-etym-spine) !important;
    border-radius: 18px !important;
    padding: 12px 16px !important;
    box-shadow: var(--ff-etym-shadow);
    gap: 0 !important;
    row-gap: 0 !important;
}

/* Eyebrow ("ETYMOLOGY:") — same uppercase/weight/tracking as the other cards' eyebrows, in the
   terracotta accent. Overrides the base .ff-exchange-label (two classes → wins on specificity). */
[b-v9s3hk0fve] .ff-etymology-message .ff-exchange-label {
    font-size: 12.5px;
    font-weight: 800;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    line-height: 1.2;
    margin-bottom: 6px;
    color: var(--ff-etym-eyebrow);
}

/* Body — readable, no Syncfusion .e-text top gap; keeps the inline italics on foreign terms. */
[b-v9s3hk0fve] .ff-etymology-message .e-text {
    color: var(--ff-etym-body);
    margin-top: 0 !important;
    padding-top: 0 !important;
}

/* Inline loading spinner shown while the etymology fetch is in-flight. */
[b-v9s3hk0fve] .ff-deriv-spinner {
    width: 11px;
    height: 11px;
    margin-left: 6px;
    vertical-align: middle;
    color: var(--ff-vocab-label);
    border-width: 2px;
}

/* Inline "more" button — unobtrusive, sits right after the derivation text. */
[b-v9s3hk0fve] .ff-deriv-more {
    display: inline;
    margin-left: 5px;
    padding: 0 5px;
    font-size: 11px;
    font-style: normal;
    color: var(--ff-vocab-label);
    background: transparent;
    border: 1px solid var(--ff-vocab-chip-border);
    border-radius: 4px;
    cursor: pointer;
    vertical-align: middle;
    line-height: 1.4;
    transition: background 0.15s, color 0.15s;
}

[b-v9s3hk0fve] .ff-deriv-more:hover {
    background: var(--ff-vocab-chip-hover-bg);
    color: var(--ff-vocab-action-strong);
}

/* Permanent "I already know this word" opt-out on a vocab card. Deliberately quiet: a faint ⋮ the
   learner has to notice and click to reveal the action, so a permanent skip is a considered choice,
   not a one-tap escape from the work. Tucked into the card's top-right corner (absolute, out of the
   flow) so it doesn't add an empty row beneath the action footer. */
[b-v9s3hk0fve] .ff-vocab-skip {
    position: absolute;
    top: 6px;
    right: 10px;
    text-align: right;
}

[b-v9s3hk0fve] .ff-vocab-skip-toggle {
    background: transparent;
    border: none;
    color: var(--ff-vocab-action-faint);
    font-size: 15px;
    line-height: 1;
    padding: 0 4px;
    cursor: pointer;
    opacity: 0.45;
    transition: opacity 0.15s, color 0.15s;
}

[b-v9s3hk0fve] .ff-vocab-skip-toggle:hover {
    opacity: 1;
    color: var(--ff-vocab-label);
}

[b-v9s3hk0fve] .ff-vocab-skip-action {
    background: transparent;
    border: none;
    color: var(--ff-vocab-action);
    font-size: 11px;
    cursor: pointer;
    padding: 2px 4px;
    text-decoration: underline;
    transition: color 0.15s;
}

[b-v9s3hk0fve] .ff-vocab-skip-action:hover {
    color: var(--ff-vocab-action-strong);
}

/* Hoverable dialog words — dotted underline signals the word can be translated on hover. */
[b-v9s3hk0fve] .ff-dialog-word {
    cursor: help;
    text-decoration-line: underline;
    text-decoration-style: dotted;
    text-decoration-color: rgba(var(--ff-accent-purple), 0.4);
    text-underline-offset: 3px;
}

/* ── Stage 4: inline lesson image + expand affordance + ephemeral lightbox ──────────────────────

   The image folds INTO the transcript (replacing Lesson's SfSplitter right pane). Both the inline
   container and the lightbox overlay are authored lexically in Lesson.razor, so they carry this
   page's scope and match plain rules. The lightbox in particular MUST be plain (not ::deep): it is a
   top-level sibling of the scoped root with no scoped ancestor, so a ::deep rule would never match. */

/* Inline image container — sits in the transcript flow; relative so the expand button can pin to
   its top-right corner. */
.ff-inline-image[b-v9s3hk0fve] {
    position: relative;
    display: inline-block;
    max-width: 100%;
    margin-top: 4px;
}

.ff-inline-image img[b-v9s3hk0fve] {
    display: block;
    max-width: 100%;
    max-height: 320px;
    object-fit: contain;
    border-radius: 12px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

/* Loading placeholder — fixed footprint so the transcript doesn't jump when the picture arrives. */
.ff-inline-image-loading[b-v9s3hk0fve] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 160px;
    height: 160px;
    background: var(--ff-image-loading-bg);
    border-radius: 12px;
    margin-top: 4px;
}

/* Expand affordance — always-visible top-right glyph button making it clear the image opens
   full-size in the lightbox (kept visible rather than hover-gated so the cue reads on touch too). */
.ff-img-expand[b-v9s3hk0fve] {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    border: none;
    background: rgba(0, 0, 0, 0.5);
    color: #ffffff;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, transform 0.15s;
}

.ff-img-expand:hover[b-v9s3hk0fve] {
    background: rgba(0, 0, 0, 0.75);
    transform: scale(1.08);
}

/* ── Live-mic "Listening" overlay ─────────────────────────────────────────────────────────────
   Large, centered, voice-reactive indicator shown while the mic is open — the can't-miss
   counterpart to the small button ring: a solid mic disc inside concentric translucent rings
   that expand and contract. Click-through by design (pointer-events: none): it never intercepts
   the mic button, Move On, or anything else. The whole pulse group also scales with
   --ff-mic-level (0..1, set on #ff-listening-overlay by the JS mic meter each frame), so it
   breathes gently while waiting and visibly swells with the learner's actual voice. */
/* The overlay positions against the lesson surface (not the viewport), so it centers over the
   transcript column and ignores the sidebar. */
.ff-lesson-surface[b-v9s3hk0fve] {
    position: relative;
}

.ff-listening-overlay[b-v9s3hk0fve] {
    position: absolute;
    inset: 0;
    z-index: 1070;             /* above the lesson surface, below the image lightbox (1080) */
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    --ff-mic-level: 0;
}

/* Gentle backdrop dim while the mic is live — pulls focus to the listening indicator without
   hiding the transcript (the prompt being answered must stay readable). The pulse group is a
   later positioned sibling, so it paints above the tint. */
.ff-listening-overlay[b-v9s3hk0fve]::before {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.10);
    animation: ff-listening-dim-in-b-v9s3hk0fve 0.25s ease-out;
}

/* Dark theme needs a slightly stronger tint to register against the slate surface. */
.fox .ff-listening-overlay[b-v9s3hk0fve]::before {
    background: rgba(0, 0, 0, 0.25);
}

@keyframes ff-listening-dim-in-b-v9s3hk0fve {
    from { opacity: 0; }
}

.ff-listening-pulse[b-v9s3hk0fve] {
    position: relative;
    width: 190px;
    height: 190px;
    display: flex;
    align-items: center;
    justify-content: center;
    animation: ff-listening-in-b-v9s3hk0fve 0.22s ease-out;
    /* Voice reactivity lives here (the rings' own keyframes would override a transform on them). */
    transform: scale(calc(1 + var(--ff-mic-level, 0) * 0.22));
    transition: transform 0.07s linear;
}

@keyframes ff-listening-in-b-v9s3hk0fve {
    from { opacity: 0; transform: scale(0.85); }
    to   { opacity: 1; }
}

/* During an auto-listen capture the pulse group is the stop control (the manual mic button is
   hidden then — see the showMic gate in Lesson.razor). Only the pulse takes clicks; the rest of
   the overlay stays click-through for Move On and anything else beneath. */
.ff-listening-stoppable .ff-listening-pulse[b-v9s3hk0fve] {
    pointer-events: auto;
    cursor: pointer;
}

/* Concentric rings — translucent light blues, MORE transparent outward, each on its own pulse phase
   so the expansion rolls outward instead of moving in lockstep. The alpha lets the page (and lesson
   image) show through, matching the translucent centre disc — solid rings clashed against the
   see-through mic. Each ring still has a transparent HOLE under the disc (radial-gradient) at the
   disc radius (43px); the pulse scales it a few px either way, reading as a soft breathing edge. */
.ff-ring[b-v9s3hk0fve] {
    position: absolute;
    border-radius: 50%;
    animation: ff-ring-pulse-b-v9s3hk0fve 1.9s ease-in-out infinite;
}

.ff-ring-1[b-v9s3hk0fve] { inset: 0;    background: radial-gradient(circle closest-side, transparent 43px, rgba(219, 234, 254, 0.30) 44px); animation-delay: 0.30s; }
.ff-ring-2[b-v9s3hk0fve] { inset: 22px; background: radial-gradient(circle closest-side, transparent 43px, rgba(191, 219, 254, 0.42) 44px); animation-delay: 0.15s; }
.ff-ring-3[b-v9s3hk0fve] { inset: 44px; background: radial-gradient(circle closest-side, transparent 43px, rgba(147, 197, 253, 0.55) 44px); animation-delay: 0s; }

/* Dark theme — the pale-blue rings above read as a glaring near-white blob on the slate surface.
   Deepen them (same brighter-inward roll, same translucency) so the indicator sits IN the dark page,
   and let the disc carry the brightness as the focal point. */
.fox .ff-ring-1[b-v9s3hk0fve] { background: radial-gradient(circle closest-side, transparent 43px, rgba(28, 50, 83, 0.35) 44px); }
.fox .ff-ring-2[b-v9s3hk0fve] { background: radial-gradient(circle closest-side, transparent 43px, rgba(39, 72, 111, 0.45) 44px); }
.fox .ff-ring-3[b-v9s3hk0fve] { background: radial-gradient(circle closest-side, transparent 43px, rgba(56, 101, 156, 0.60) 44px); }
.fox .ff-listening-mic[b-v9s3hk0fve] {
    background: rgba(59, 130, 246, 0.80);   /* blue-500 — brighter than the light-mode disc, pops on slate */
    box-shadow: 0 6px 22px rgba(37, 99, 235, 0.50);
}

@keyframes ff-ring-pulse-b-v9s3hk0fve {
    0%, 100% { transform: scale(0.88); }
    50%      { transform: scale(1.06); }
}

/* The solid center disc with the mic glyph — the anchor the rings radiate from. */
.ff-listening-mic[b-v9s3hk0fve] {
    position: relative;        /* above the rings */
    width: 86px;
    height: 86px;
    border-radius: 50%;
    background: rgba(26, 115, 232, 0.70);   /* translucent — softens the disc without losing presence */
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 22px rgba(26, 115, 232, 0.45);
}

/* Honor reduced-motion: no pulse, no entrance scale — a static badge whose size still reflects
   the live level (an accessibility-safe "we hear you"). */
@media (prefers-reduced-motion: reduce) {
    .ff-listening-pulse[b-v9s3hk0fve]           { animation: none; transition: none; }
    .ff-ring[b-v9s3hk0fve]                      { animation: none; }
    .ff-listening-overlay[b-v9s3hk0fve]::before { animation: none; }
}

/* Mobile: dead-centered, the pulse group lands directly on top of the prompt being read — most
   painfully the assessment read-aloud paragraph on a short screen. Drop it to the bottom of the
   surface (and shrink it a touch) so the text the student must read stays fully visible while the
   "we hear you" indicator remains on screen and voice-reactive. Desktop has the vertical room to
   keep it centered, so this is mobile-only. */
@media (max-width: 639.98px) {
    /* Narrow screens can't fit the door on one line — let the panel span the column so the wrapped
       headline still reads as a centered block, and add text-wrap:balance so the two lines split
       evenly (safe here because the full-width panel already constrains the line, so balance won't
       collapse it the way it does on the desktop fit-content box). */
    [b-v9s3hk0fve] .ff-entrance-panel {
        width: 100%;
        padding: 26px 24px;
    }

    [b-v9s3hk0fve] .ff-entrance-prompt {
        text-wrap: balance;
    }

    .ff-listening-overlay[b-v9s3hk0fve] {
        align-items: flex-end;
        padding-bottom: 28px;
    }

    .ff-listening-pulse[b-v9s3hk0fve] {
        width: 150px;
        height: 150px;
    }
}

/* Full-screen overlay — dismissed on backdrop / close / Esc-equivalent; the image itself stops
   propagation so clicking the picture doesn't close it. */
.ff-lightbox[b-v9s3hk0fve] {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.8);
    cursor: zoom-out;
}

.ff-lightbox img[b-v9s3hk0fve] {
    max-width: 90vw;
    max-height: 90vh;
    object-fit: contain;
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
    cursor: default;
}

.ff-lightbox-close[b-v9s3hk0fve] {
    position: absolute;
    top: 16px;
    right: 24px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: none;
    background: rgba(255, 255, 255, 0.15);
    color: #ffffff;
    font-size: 28px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}

.ff-lightbox-close:hover[b-v9s3hk0fve] {
    background: rgba(255, 255, 255, 0.3);
}

/* Admin-only curation actions (delete / upload) — top-left of the lightbox, opposite the close
   button. Both pills share the same shape; delete is red, upload is blue. */
.ff-lightbox-actions[b-v9s3hk0fve] {
    position: absolute;
    top: 16px;
    left: 24px;
    display: flex;
    gap: 10px;
}

.ff-lightbox-delete[b-v9s3hk0fve],
.ff-lightbox-upload[b-v9s3hk0fve] {
    height: 40px;
    padding: 0 16px;
    border-radius: 20px;
    border: none;
    color: #ffffff;
    font-size: 15px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
}

.ff-lightbox-delete[b-v9s3hk0fve] {
    background: rgba(220, 38, 38, 0.85);
}

.ff-lightbox-delete:hover[b-v9s3hk0fve] {
    background: rgba(220, 38, 38, 1);
    transform: scale(1.04);
}

.ff-lightbox-upload[b-v9s3hk0fve] {
    background: rgba(37, 99, 235, 0.85);
    margin: 0;   /* labels pick up a default bottom margin from Bootstrap's reset */
}

.ff-lightbox-upload:hover[b-v9s3hk0fve] {
    background: rgba(37, 99, 235, 1);
    transform: scale(1.04);
}

/* The label IS the button — hide the InputFile control it wraps (clicking the label opens the
   picker). ::deep because InputFile is a child component, so its input lacks the scope attribute. */
.ff-lightbox-upload[b-v9s3hk0fve]  input[type="file"] {
    display: none;
}

/* ── Cold-open entrance ─────────────────────────────────────────────────────────────────────────
   The door is the only LOUD thing on screen: a large, centered language question. The language
   chips reuse the standard .ff-suggestion-btn pills; the reassurance chips below are deliberately
   quieter (text-style), serving the hesitant visitor without competing with the action. */
/* Soft warm panel that gives the headline a defined "home" and added presence — subtle, just
   enough to lift off the page, not a hard callout box. Theme-aware surface via tokens (a scoped
   ::deep rule can't see the html-level .fox class, so the light/dark values live on the tokens). */
[b-v9s3hk0fve] .ff-entrance-panel {
    width: fit-content;                /* hug the headline — the door stays on one line on desktop */
    max-width: 100%;
    margin: 14px auto 30px;            /* tight above/below so the whole door + band fits above the fold */
    padding: 20px 30px;                /* comfortable, but trim the side gutters so the door fits one line */
    border-radius: 22px;
    background: var(--ff-headline-panel-bg);
    border: 1px solid var(--ff-headline-panel-border);
    box-shadow: var(--ff-headline-panel-shadow);   /* warm-brown soft shadow in light, none in dark */
    text-align: center;
}

[b-v9s3hk0fve] .ff-entrance-prompt {
    text-align: center;
    /* Fluid so the type scales with the viewport — one line at the 34px cap on desktop, shrinking to
       the 24px floor and wrapping to two balanced lines on phones. No nowrap: forcing a single line at
       any width overflows the panel on narrow screens; letting it wrap is the correct behaviour.
       text-wrap:balance is deliberately NOT here — on the fit-content panel it collapses the text to
       its balance point (two lines) even when there's room for one; it lives in the mobile rule where
       the column already constrains the width. The 30px cap is the largest that still fits the door
       on one line in this column; 34px orphaned "today?" onto a second line. */
    font-size: clamp(22px, 3.4vw, 30px);
    font-weight: 800;
    letter-spacing: -0.8px;            /* tight, intentional at large size */
    line-height: 1.2;
    color: var(--ff-entrance-ink);     /* cool near-black on the white panel (light) / light primary (dark) */
    margin: 0;                          /* spacing is owned by the panel now */
}

/* The single color touch — one accent word. Theme-aware: warm orange in light, violet in dark. */
[b-v9s3hk0fve] .ff-entrance-accent {
    color: var(--ff-headline-accent);
}

/* Center everything under the door — headline, language chips, and reassurance bar — as one stack.
   align-items:center centers each child BOX (the chip rows shrink to their content), which the
   per-row justify-content alone can't do once a shrunk container sits at the wrapper's left edge. */
[b-v9s3hk0fve] .ff-mw-entranceprompt {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Fill the row (it defaults to flex-start / shrink-wrap, which pins the headline to the left
       rail); only then does align-items:center truly center the stack between the two rails.
       Same fix as .ff-mw-image / .ff-mw-learnerdashboard above. */
    width: 100%;
}

/* Belt-and-suspenders: also center chips within their row if it ever stretches full width. */
[b-v9s3hk0fve] .ff-entrance-prompt ~ .ff-suggestion-container {
    justify-content: center;
}

/* Entrance-only chip skin — white pills with a warm hairline + whisper shadow so they read as
   objects on the beige canvas (contrast-fix handoff). Dark mode keeps the outline style via the
   token values. !important to outrank the generic .ff-suggestion-btn rule above. */
[b-v9s3hk0fve] .ff-mw-entranceprompt .ff-suggestion-btn {
    background: var(--ff-entrance-chip-bg) !important;
    border-color: var(--ff-entrance-chip-border) !important;
    color: var(--ff-entrance-chip-text) !important;
    box-shadow: var(--ff-entrance-chip-shadow);
}

/* Quieter, secondary reassurance bar — for the hesitant, not the ready. */
[b-v9s3hk0fve] .ff-reassure-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    justify-content: center;
    margin-top: 14px;
}

[b-v9s3hk0fve] .ff-reassure-chip {
    background: transparent;
    border: none;
    padding: 2px 4px;
    font-size: 12.5px;
    color: var(--ff-reassure-text);   /* soft warm at rest (light) / quiet slate (dark); warms to the accent on hover */
    cursor: pointer;
    border-radius: 6px;
    transition: color 0.15s, background 0.15s;
}

[b-v9s3hk0fve] .ff-reassure-chip:hover {
    color: rgb(var(--ff-action-line));
    background: var(--ff-action-soft);
    text-decoration: underline;
}
