/* Core layout and component styles for the Staples Education ODE Roadmap. */

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Segoe UI', 'Inter', system-ui, sans-serif;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* Global Header */

.global-header {
    background-color: var(--header-bg);
    border-bottom: 1px solid var(--panel-border);
    padding: 1.5rem 2rem;
}

.header-inner {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.brand-name {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent-color);
}

.app-title {
    font-size: 1.8rem;
    font-weight: 700;
    margin-top: 0.25rem;
}

.app-subtitle {
    color: var(--text-secondary);
    margin-top: 0.25rem;
    font-size: 0.95rem;
}

.header-controls {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

/* Google account sync controls. The sign-in button itself is rendered by the
   Identity Services SDK inside an iframe, so only its container and the
   signed-in status chip are styled here; both read live theme tokens so
   Light and Dark render natively. */
.auth-controls {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 32px;
}

.auth-status {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.85rem;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 999px;
    font-size: 0.85rem;
    color: var(--text-secondary);
    white-space: nowrap;
}

.auth-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success-color);
    flex-shrink: 0;
}

.auth-signout {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--accent-color);
    cursor: pointer;
}

.auth-signout:hover {
    text-decoration: underline;
}

/* Mobile auth adjustments live in the unified 768px block at the end of this
   sheet, alongside the rest of the header's responsive rules. */

/* Learning mode is selected through the shared .nav-dropdown component (see the
   Global navigation dropdown block below), so it carries no dedicated styling. */

/* The color theme control is selected through the shared .nav-dropdown
   component (see the Global navigation dropdown block below), so it carries no
   dedicated styling, matching the learning mode control. */

/* Global navigation dropdown, CSS-only via :hover and :focus-within */

.nav-dropdown {
    position: relative;
    display: inline-block;
}

.nav-dropdown-trigger {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--panel-bg);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.5rem 1rem;
    font-size: 0.85rem;
    font-family: inherit;
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.nav-dropdown-trigger:hover,
.nav-dropdown:focus-within .nav-dropdown-trigger {
    background: var(--accent-soft);
}

.nav-dropdown-trigger:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* Indicator arrow, rotates on expansion */

.nav-dropdown-arrow {
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    transition: transform 0.2s ease;
}

.nav-dropdown:hover .nav-dropdown-arrow,
.nav-dropdown:focus-within .nav-dropdown-arrow {
    transform: rotate(180deg);
}

/* The menu panel, hidden until hover or focus-within */

.nav-dropdown-menu {
    position: absolute;
    top: calc(100% + 0.4rem);
    left: 0;
    z-index: 1100;
    min-width: 12rem;
    margin: 0;
    padding: 0.35rem;
    list-style: none;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    box-shadow: 0 8px 24px var(--shadow-color);
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
    visibility: hidden;
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0.2s;
}

/* Transparent hover bridge spanning the 0.4rem gap below the trigger, so the
   cursor never leaves a hoverable descendant while crossing into the panel.
   Inherits the menu's pointer-events, so it stays inert while the menu is hidden. */
.nav-dropdown-menu::before {
    content: "";
    position: absolute;
    top: -0.4rem;
    left: 0;
    right: 0;
    height: 0.4rem;
}

.nav-dropdown:hover .nav-dropdown-menu,
.nav-dropdown:focus-within .nav-dropdown-menu {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    visibility: visible;
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0s;
}

.nav-dropdown-menu li {
    margin: 0;
}

.nav-dropdown-menu a,
.nav-dropdown-menu button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.5rem 0.75rem;
    border: none;
    border-radius: 6px;
    background: none;
    color: var(--text-color);
    text-decoration: none;
    font-size: 0.85rem;
    font-family: inherit;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.nav-dropdown-menu a:hover,
.nav-dropdown-menu a:focus-visible,
.nav-dropdown-menu button:hover,
.nav-dropdown-menu button:focus-visible {
    background: var(--accent-soft);
    color: var(--accent-color);
    outline: none;
}

/* The active learning mode option, marked so the open menu shows the selection. */
.nav-dropdown-menu button.active {
    background: var(--accent-soft);
    color: var(--accent-color);
    font-weight: 600;
}

/* Static navigation pages (Practice Sets, Cheat Sheets, and other scaffolded
   routes). The container inherits the app-container width from #app-content. */

.static-page {
    width: 100%;
}

.static-page-title {
    font-size: 1.8rem;
    font-weight: 700;
    color: var(--text-color);
    border-bottom: 2px solid var(--accent-color);
    padding-bottom: 0.5rem;
    margin: 0 0 1rem;
}

.static-page-placeholder {
    color: var(--text-secondary);
    font-size: 1rem;
}

/* Reusable primary action button for downloadable PDF links. Style an anchor
   to look like a primary button, inheriting the theme accent and shadow. */

.pdf-download-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--accent-color);
    color: var(--bg-color);
    border: 1px solid var(--accent-color);
    border-radius: 8px;
    padding: 0.6rem 1.1rem;
    font-size: 0.9rem;
    font-family: inherit;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.2s ease, box-shadow 0.2s ease, transform 0.1s ease;
}

.pdf-download-btn:hover {
    background: var(--accent-soft);
    color: var(--accent-color);
    box-shadow: 0 4px 14px var(--shadow-color);
}

.pdf-download-btn:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

.pdf-download-btn:active {
    transform: translateY(1px);
}

/* Materials index pages (Cheat Sheets and Practice Sets), rendered by router.js.
   The cards reuse the Table of Contents grid for responsive layout, and mirror
   the unit card look as a static container that holds its own action buttons. */

.materials-card {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    /* Pack every content block at the top so the title, description, button, and
       topic guides sit flush together. The grid stretches cards to a shared row
       height, and flex-start collects any leftover space at the bottom of the
       card, beneath the last subtopic, keeping a clean baseline across the row. */
    justify-content: flex-start;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    padding: 1.5rem;
    box-shadow: 0 2px 12px var(--shadow-color);
}

.materials-card-title {
    font-size: 1.15rem;
    font-weight: 700;
}

.materials-card-desc {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.4;
}

/* The primary action button hugs its content rather than stretching the card,
   and sits directly below the description on every card. The card no longer
   grows the description to fill height, so a short unit and a long unit place
   their button at the same tight offset under the text. */
.materials-card .pdf-download-btn {
    align-self: flex-start;
}

/* The topic guides block sits naturally right below the primary action button,
   separated only by the card flex gap and its own top border and padding. The
   card itself collects any leftover space at the bottom (see .materials-card),
   so there is no artificial gap between the button and this list. */
.materials-subtopics {
    border-top: 1px solid var(--panel-border);
    padding-top: 0.75rem;
}

.materials-subtopics-label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 0.4rem;
}

.materials-subtopics-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

/* A lighter link for each topic guide PDF, set apart from the solid primary
   button above it by a small accent marker rather than a filled background. */
.pdf-download-link {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    color: var(--accent-color);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 600;
    padding: 0.3rem 0.5rem;
    border-radius: 6px;
    transition: background-color 0.15s ease;
}

.pdf-download-link::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 2px;
    background: var(--accent-color);
    flex-shrink: 0;
}

.pdf-download-link:hover {
    background: var(--accent-soft);
}

.pdf-download-link:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* A plain text topic guide entry, used on the Practice Sets and Interactives
   hubs where the topic is not a downloadable PDF. It mirrors the link spacing
   and accent marker without the interactive affordance. */
.materials-subtopic-text {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    color: var(--text-secondary);
    font-size: 0.88rem;
    padding: 0.3rem 0.5rem;
}

.materials-subtopic-text::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 2px;
    background: var(--accent-color);
    flex-shrink: 0;
}

/* Practice Set sub-view (problems and toggleable solutions), rendered by
   router.js. Layout only, all themed visuals come from the reused classes
   (module-title, static-page-placeholder, pdf-download-btn). The flex column
   with a flex-start cross axis lets the toggle button hug its content while the
   problem and solution bodies still stretch to the full width. */
.practice-set-section {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
}

.practice-set-problems,
.practice-set-solutions {
    align-self: stretch;
}

/* Action row holding the cheat sheet download button, wraps on narrow screens. */
.practice-action-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* Practice problem list, a plain numbered list with comfortable spacing. */
.practice-problem-list {
    margin: 0;
    padding-left: 1.5rem;
}

.practice-problem-list li {
    margin-bottom: 0.85rem;
    line-height: 1.55;
}

/* The solutions block sits behind the toggle and is set apart with an accent
   top edge so it reads as a clearly separate section from the problems above. */
.practice-set-solutions {
    border-top: 2px solid var(--accent-color);
    padding-top: 1rem;
}

/* Each solution becomes a soft panel with an accent left bar, so a revealed
   solution is visually distinct from the practice problems. */
.practice-solution-list {
    list-style-position: inside;
    margin: 0;
    padding-left: 0;
}

.practice-solution-list li {
    margin-bottom: 0.85rem;
    line-height: 1.55;
    padding: 0.6rem 0.85rem;
    border-left: 3px solid var(--accent-color);
    background: var(--panel-bg);
    border-radius: 0 8px 8px 0;
}

/* Progress banner */

.progress-banner {
    max-width: 1200px;
    margin: 1.25rem auto 0;
    display: flex;
    align-items: center;
    gap: 1.5rem;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 12px;
    padding: 0.9rem 1.25rem;
}

.progress-title {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
}

.progress-percentage {
    font-size: 1.3rem;
    font-weight: 700;
}

.progress-track-bg {
    flex-grow: 1;
    height: 10px;
    background: var(--bg-color);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    width: 0%;
    background: var(--accent-color);
    border-radius: 10px;
    transition: width 0.4s ease;
}

/* Main content area */

.app-container {
    max-width: 1200px;
    width: 100%;
    margin: 2rem auto;
    padding: 0 2rem;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    gap: 2rem;
}

/* Table of Contents view, rendered by router.js */

.toc-intro {
    border-bottom: 2px solid var(--accent-color);
    padding-bottom: 0.75rem;
}

.toc-heading {
    font-size: 1.6rem;
    font-weight: 700;
}

.toc-subhead {
    color: var(--text-secondary);
    margin-top: 0.35rem;
    font-size: 0.95rem;
}

.toc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 1.25rem;
}

/* The Interactive Visualizers dashboard, rendered by router.js. The grid mirrors
   the responsive layout of the curriculum cards; the cards reuse .materials-card
   chrome and add a context badge plus a launch action. Every color resolves
   through the theme custom properties, so light and dark modes both stay on
   palette. */

/* Two-column dashboard split: a sticky unit-navigation sidebar locked to the
   left while the unit sections scroll on the right. One flex row inside the app
   container; align-items: flex-start lets the sidebar stay short enough to
   stick rather than stretching to the content's full height. */
.interactives-layout {
    display: flex;
    align-items: flex-start;
    gap: 1.5rem;
    width: 100%;
}

/* The left sidebar. Sticks 2rem below the viewport top through the whole scroll.
   Its panel wears the framework's light lavender wash (--accent-soft) with the
   --panel-border and 14px radius, so it reads as a soft violet rail in light mode
   and a muted violet-tinted panel in dark. A touch wider than the bare-number
   version so full unit titles wrap cleanly; height-capped and internally
   scrollable so a tall unit list never runs past the viewport. */
.interactives-sidebar {
    position: sticky;
    top: 2rem;
    flex: 0 0 232px;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    background: var(--accent-soft);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    padding: 1rem 0.85rem;
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
}

.interactives-sidebar-title {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent-text);
    padding: 0.1rem 0.65rem 0.5rem;
}

/* A unit anchor link carrying its full descriptive title. The brand purple text
   token (--accent-text, lightened for dark mode) is the resting label color; the
   text wraps over multiple lines with relaxed line-height and generous side
   padding so the longer strings sit beautifully. Hover/focus/active lifts it onto
   a clean page-background pill with
   a purple outline while the text stays purple, so the active state reads clearly
   against the lavender panel in both themes. */
.interactives-sidebar-link {
    text-align: left;
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--accent-text);
    background: transparent;
    border: 1px solid transparent;
    border-radius: 9px;
    padding: 0.5rem 0.75rem;
    cursor: pointer;
    white-space: normal;
    overflow-wrap: anywhere;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.interactives-sidebar-link:hover,
.interactives-sidebar-link.active {
    background: var(--bg-color);
    color: var(--accent-text);
    border-color: var(--accent-color);
}

.interactives-sidebar-link:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* The right content column. min-width: 0 lets the inner card grid shrink inside
   the flex row instead of forcing horizontal overflow. */
.interactives-content {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* Per-unit bounded sections. Each unit's visualizer cards are framed in a
   solid-bordered container so the dashboard reads as distinct unit groups. The
   frame uses the page background (cards are --panel-bg) so the gray cards stand
   out cleanly inside the lighter/darker section, matching the 14px radius used
   across the framework's card chrome. scroll-margin-top keeps a section clear of
   the viewport top when a sidebar link scrolls to it. */
.unit-section-container {
    background: var(--bg-color);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    padding: 1.25rem;
    margin-bottom: 1.75rem;
    scroll-margin-top: 1rem;
}

.unit-section-container:last-child {
    margin-bottom: 0;
}

/* The lavender header box topping each unit section. Built from the accent-soft
   token (a soft violet tint over white in light mode, a muted violet over
   near-black in dark mode) with bold accent-colored text, so it reads as an
   elegant full-width lavender band with guaranteed contrast in both themes. */
.unit-lavender-header {
    background: var(--accent-soft);
    color: var(--accent-text);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    padding: 0.7rem 1rem;
    margin-bottom: 1.25rem;
    text-align: center;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.interactives-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 1.25rem;
}

.interactive-badge {
    align-self: flex-start;
    display: inline-block;
    background: var(--accent-soft);
    color: var(--accent-text);
    border: 1px solid var(--panel-border);
    border-radius: 999px;
    padding: 0.2rem 0.7rem;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}

/* Cards are flex columns (inherited from .materials-card). The whole card is a
   <button>, matching the Table of Contents unit cards: clicking anywhere on the
   frame launches the tool, with no inner launch chip. The resets neutralize the
   user-agent button chrome so .materials-card's panel styling shows through
   unchanged, and the hover lift mirrors .toc-card for the same instant visual
   feedback in both themes. */
.interactive-card {
    display: flex;
    flex-direction: column;
    font: inherit;
    text-align: left;
    color: inherit;
    cursor: pointer;
    transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.interactive-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent-color);
    box-shadow: 0 6px 18px var(--shadow-color);
}

.interactive-card:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* With no launch chip below it, the description grows to absorb the card's
   leftover height (mirroring .toc-card-desc), so cards sharing a grid row keep
   flush bottom edges. */
.interactive-card .materials-card-desc {
    flex-grow: 1;
}

/* The framed panel that holds the live visualizer once it is mounted. A solid
   one-pixel border and rounded corners give the embedded checkpoint a clean,
   self-contained workspace, distinct from the dashed in-unit checkpoint frame. */
.interactive-workspace-card {
    margin-top: 1.25rem;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    padding: 1.5rem;
}

.toc-card {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    padding: 1.5rem;
    box-shadow: 0 2px 12px var(--shadow-color);
    transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.toc-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent-color);
    box-shadow: 0 6px 18px var(--shadow-color);
}

.toc-card:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

.toc-card-title {
    font-size: 1.2rem;
    font-weight: 700;
}

.toc-card-desc {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.4;
    flex-grow: 1;
}

.toc-card-progress-track {
    height: 8px;
    background: var(--bg-color);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    overflow: hidden;
    margin-top: 0.4rem;
}

.toc-card-progress-fill {
    height: 100%;
    width: 0%;
    background: var(--accent-color);
    border-radius: 10px;
    transition: width 0.4s ease;
}

.toc-card-progress-label {
    font-size: 0.8rem;
    color: var(--text-secondary);
}

/* Unit Detail navigation, rendered by router.js */

.unit-detail-nav {
    display: flex;
}

.back-to-toc-btn {
    font: inherit;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    color: var(--accent-color);
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    padding: 0.55rem 1rem;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.back-to-toc-btn:hover {
    border-color: var(--accent-color);
}

.back-to-toc-btn:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* Unit sections, rendered by router.js */

.unit-section {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.unit-header {
    border-bottom: 2px solid var(--accent-color);
    padding-bottom: 0.75rem;
}

.unit-title {
    font-size: 1.5rem;
    font-weight: 700;
}

.unit-desc {
    color: var(--text-secondary);
    margin-top: 0.35rem;
    font-size: 0.95rem;
}

.unit-modules {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

/* Module sections, rendered by router.js */

.module-section {
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    padding: 1.5rem;
    box-shadow: 0 2px 12px var(--shadow-color);
}

.module-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.module-title {
    font-size: 1.25rem;
    font-weight: 700;
}

.module-status {
    font-size: 0.8rem;
    font-weight: 600;
    padding: 0.3rem 0.75rem;
    border-radius: 20px;
    background: var(--accent-soft);
    color: var(--accent-color);
}

.module-section.locked {
    opacity: 0.55;
}

.module-section.locked .module-status {
    background: transparent;
    border: 1px solid var(--locked-color);
    color: var(--locked-color);
}

.video-list {
    list-style: none;
    margin-top: 1rem;
    display: grid;
    /* Single column stack so each video card spans the full module width,
       giving the embedded players room to grow without full screen mode. */
    grid-template-columns: 1fr;
    gap: 2rem;
}

.video-card {
    background: var(--bg-color);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    padding: 1rem;
    /* Allow the card to fill the full width of the stacked column. */
    width: 100%;
    max-width: 100%;
}

.video-card a {
    color: var(--accent-color);
    text-decoration: none;
    font-weight: 600;
}

.video-card a:hover {
    text-decoration: underline;
}

.video-title {
    font-weight: 600;
    margin-bottom: 0.6rem;
    line-height: 1.35;
}

/* Responsive 16:9 frame. The padding-bottom of 56.25 percent is nine
   divided by sixteen, so the box keeps a true widescreen ratio at any
   width while the iframe fills it absolutely. */
.video-embed {
    position: relative;
    width: 100%;
    height: 0;
    padding-bottom: 56.25%;
    border-radius: 10px;
    overflow: hidden;
    background: var(--bg-color);
}

.video-embed iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.video-fallback-link {
    display: inline-block;
    margin-top: 0.6rem;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-secondary);
}

.video-watched-toggle {
    display: block;
    margin-top: 0.5rem;
}

/* Checkpoint container, populated by the checkpoint registry */

.checkpoint-panel {
    margin-top: 1.25rem;
    border: 1px dashed var(--panel-border);
    border-radius: 10px;
    padding: 1.25rem;
}

.checkpoint-heading {
    font-size: 0.95rem;
    font-weight: 700;
    margin-bottom: 0.5rem;
}

.checkpoint-placeholder {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.checkpoint-intro {
    color: var(--text-secondary);
    font-size: 0.92rem;
    margin-bottom: 0.85rem;
}

.checkpoint-begin-btn,
.check-btn {
    background: var(--accent-color);
    color: var(--bg-color);
    border: none;
    border-radius: 8px;
    padding: 0.55rem 1.2rem;
    font-size: 0.9rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: opacity 0.2s ease;
}

.checkpoint-begin-btn:hover,
.check-btn:hover {
    opacity: 0.85;
}

.check-btn {
    margin-top: 1rem;
}

.checkpoint-body {
    margin-top: 0.75rem;
}

.checkpoint-prompt {
    font-size: 0.95rem;
    font-weight: 600;
    margin-bottom: 0.75rem;
}

.desmos-frame {
    /* The native Desmos expressions sidebar stays hidden; checkpoints that need
       parameter controls inject their own .slider-panel just below this frame. */
    width: 100%;
    height: 360px;
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 0.75rem;
    background: var(--bg-color);
}

.math-canvas {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    margin-bottom: 0.75rem;
    background: var(--bg-color);
}

/* Range slider controls for Desmos and canvas-based widgets */

/* Groups the native HTML sliders into a tidy control panel beneath a graph. */
.slider-panel {
    margin: 0 0 1rem;
    padding: 0.85rem 1rem;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
}

.slider-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0.6rem 0 1rem;
}

/* Inside a panel the rows sit closer together and need no outer margins. */
.slider-panel .slider-row {
    margin: 0.55rem 0;
}

.slider-panel .slider-row:first-child {
    margin-top: 0;
}

.slider-panel .slider-row:last-child {
    margin-bottom: 0;
}

.slider-label {
    font-weight: 700;
    font-size: 0.95rem;
    /* A shared width keeps every slider track left-aligned in the column. */
    min-width: 2.25rem;
    flex-shrink: 0;
}

.slider-row input[type="range"] {
    flex: 1 1 auto;
    /* min-width: 0 lets the track shrink so it never overflows a narrow card. */
    min-width: 0;
    accent-color: var(--accent-color);
    cursor: pointer;
}

.slider-readout {
    font-family: Consolas, Monaco, monospace;
    font-size: 0.9rem;
    min-width: 3.5rem;
    text-align: right;
    flex-shrink: 0;
}

/* Fixed point iteration widget */

.iteration-display {
    font-family: Consolas, Monaco, monospace;
    font-size: 1rem;
    font-weight: 700;
    padding: 0.6rem 0.8rem;
    background: var(--bg-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    margin-bottom: 0.6rem;
}

.iteration-log {
    font-family: Consolas, Monaco, monospace;
    font-size: 0.82rem;
    color: var(--text-secondary);
    margin-bottom: 0.75rem;
    min-height: 1rem;
}

/* Feedback and the guiding question failure state */

.checkpoint-feedback {
    margin-top: 0.9rem;
    border-radius: 10px;
    font-size: 0.92rem;
}

.checkpoint-feedback.success {
    border: 1px solid var(--success-color);
    color: var(--success-color);
    padding: 0.8rem 1rem;
    font-weight: 600;
}

.checkpoint-feedback.failure {
    border: 1px solid var(--accent-color);
    padding: 0.8rem 1rem;
}

.guiding-question {
    font-style: italic;
    margin-top: 0.4rem;
    color: var(--accent-color);
    font-weight: 600;
}

.feedback-extra {
    margin-top: 0.4rem;
    color: var(--text-secondary);
    font-size: 0.85rem;
}

/* Matching game */

.match-board {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.match-column {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.match-item {
    position: relative;
    background: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.65rem 0.8rem;
    font-size: 0.88rem;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease;
}

.match-item:hover {
    border-color: var(--accent-color);
}

.match-item.selected {
    border-color: var(--accent-color);
    background: var(--accent-soft);
}

.pair-badge {
    position: absolute;
    top: -8px;
    right: -8px;
    background: var(--accent-color);
    color: var(--bg-color);
    font-size: 0.7rem;
    font-weight: 700;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Category sorter */

.sorter-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--panel-border);
}

.sorter-text {
    font-size: 0.9rem;
}

.sorter-select {
    background: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.45rem 0.6rem;
    font-size: 0.85rem;
    font-family: inherit;
}

/* Expression tasks */

.expr-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.6rem;
    flex-wrap: wrap;
}

.expr-label {
    font-size: 0.9rem;
    font-weight: 600;
    min-width: 120px;
}

.expr-input {
    flex-grow: 1;
    min-width: 200px;
    background: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.55rem 0.75rem;
    font-size: 0.9rem;
    font-family: Consolas, Monaco, monospace;
}

.expr-input:focus {
    outline: none;
    border-color: var(--accent-color);
}

/* Multiple choice logic gate */

.mcq-question {
    font-size: 0.95rem;
    margin-bottom: 0.75rem;
}

.mcq-option {
    display: block;
    width: 100%;
    background: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.65rem 0.9rem;
    margin-bottom: 0.5rem;
    font-size: 0.9rem;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.mcq-option:hover {
    border-color: var(--accent-color);
    background: var(--accent-soft);
}

/* Quiz, Micro Practice (per video) and Unit Mastery (per unit).
   Micro Practice renders inline beside the video in a split layout. Unit
   Mastery keeps a launch card that opens a full screen modal overlay. */

/* Split layout, the video on the left and its Micro Practice on the right, so
   the student can watch and practice at the same time. The video column takes
   roughly two thirds of the width, the quiz column the remaining third. */
.video-lesson-split {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 1.5rem;
    align-items: start;
}

.video-lesson-main {
    min-width: 0;
}

.video-quiz-host {
    min-width: 0;
}

.unit-mastery-host {
    margin-top: 1.25rem;
}

/* Inline Micro Practice panel, the questions live directly in the column. */
.quiz-inline-panel {
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    padding: 0.9rem 1.1rem;
}

.quiz-inline-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
}

.quiz-inline-title {
    font-size: 1rem;
    margin: 0;
}

.quiz-inline-body {
    margin-top: 0.85rem;
}

.quiz-inline-footer {
    margin-top: 0.85rem;
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    min-height: 1rem;
}

/* Launch card */

.quiz-launch-card {
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    padding: 0.9rem 1.1rem;
}

.unit-mastery-host .quiz-launch-card {
    border-color: var(--accent-color);
}

.quiz-title {
    font-size: 1rem;
    margin: 0;
}

.quiz-intro {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin: 0.4rem 0 0;
}

.quiz-progress {
    font-size: 0.8rem;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    margin: 0.55rem 0 0.7rem;
}

.quiz-launch-btn {
    background: var(--accent-color);
    color: var(--bg-color);
    border: none;
    border-radius: 8px;
    padding: 0.55rem 1.1rem;
    font-size: 0.9rem;
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s ease;
}

.quiz-launch-btn:hover {
    opacity: 0.9;
}

/* Modal overlay */

body.quiz-modal-open {
    overflow: hidden;
}

.quiz-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(0, 0, 0, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}

.quiz-modal {
    background: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 12px;
    box-shadow: 0 18px 50px var(--shadow-color);
    width: 100%;
    max-width: 640px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.quiz-modal-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--panel-border);
}

.quiz-modal-title {
    font-size: 1.05rem;
    margin: 0;
    flex: 1;
}

.quiz-score {
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
    white-space: nowrap;
}

.quiz-modal-close {
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.4rem 0.75rem;
    font-size: 0.8rem;
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}

.quiz-modal-close:hover {
    border-color: var(--error-color);
    color: var(--error-color);
}

.quiz-modal-body {
    padding: 1.25rem;
    overflow-y: auto;
}

.quiz-counter {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    margin: 0 0 0.6rem;
}

.quiz-prompt {
    font-size: 1rem;
    margin: 0 0 0.9rem;
}

/* General hint toggle */

.quiz-hint-toggle {
    background: transparent;
    color: var(--accent-color);
    border: 1px solid var(--panel-border);
    border-radius: 6px;
    padding: 0.3rem 0.7rem;
    font-size: 0.8rem;
    font-family: inherit;
    cursor: pointer;
    margin-bottom: 0.85rem;
    transition: border-color 0.15s ease;
}

.quiz-hint-toggle:hover {
    border-color: var(--accent-color);
}

.quiz-hint {
    background: var(--accent-soft);
    border-radius: 8px;
    padding: 0.6rem 0.85rem;
    margin: 0 0 0.9rem;
}

.quiz-hint-text {
    font-size: 0.88rem;
    margin: 0;
    color: var(--text-color);
}

/* Options and their inline rationales */

.quiz-option-row {
    margin-bottom: 0.55rem;
}

.quiz-option {
    display: block;
    width: 100%;
    background: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.7rem 0.95rem;
    font-size: 0.92rem;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.quiz-option:hover:not(:disabled) {
    border-color: var(--accent-color);
    background: var(--accent-soft);
}

.quiz-option:disabled {
    cursor: default;
}

.quiz-option.correct {
    border-color: var(--success-color);
    background: var(--accent-soft);
    color: var(--success-color);
    font-weight: 600;
}

.quiz-option.incorrect {
    border-color: var(--error-color);
    color: var(--error-color);
    opacity: 0.85;
}

.quiz-rationale {
    background: var(--accent-soft);
    border-radius: 6px;
    padding: 0.55rem 0.8rem;
    margin: 0.4rem 0 0.2rem 0.6rem;
}

.quiz-rationale.incorrect {
    border-left: 3px solid var(--error-color);
}

.quiz-rationale.incorrect .quiz-rationale-text {
    color: var(--error-color);
}

.quiz-rationale.correct {
    border-left: 3px solid var(--success-color);
}

.quiz-rationale.correct .quiz-rationale-text {
    color: var(--success-color);
}

.quiz-rationale-text {
    font-size: 0.88rem;
    margin: 0;
}

/* Practice complete summary */

.quiz-summary {
    text-align: center;
    padding: 1.25rem 0.5rem 0.5rem;
}

.quiz-summary-title {
    font-size: 1.2rem;
    margin: 0 0 0.6rem;
}

.quiz-summary-score {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--success-color);
    font-variant-numeric: tabular-nums;
    margin: 0 0 0.6rem;
}

.quiz-summary-message {
    font-size: 0.9rem;
    color: var(--text-secondary);
    margin: 0;
    line-height: 1.5;
}

.quiz-modal-footer {
    padding: 1rem 1.25rem;
    border-top: 1px solid var(--panel-border);
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    min-height: 1rem;
}

.quiz-retry-btn {
    background: transparent;
    color: var(--accent-color);
    border: 1px solid var(--accent-color);
    border-radius: 8px;
    padding: 0.55rem 1.25rem;
    font-size: 0.9rem;
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease;
}

.quiz-retry-btn:hover {
    background: var(--accent-soft);
}

.quiz-next-btn {
    background: var(--accent-color);
    color: var(--bg-color);
    border: none;
    border-radius: 8px;
    padding: 0.55rem 1.25rem;
    font-size: 0.9rem;
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s ease;
}

.quiz-next-btn:hover {
    opacity: 0.9;
}

@media (max-width: 600px) {
    .quiz-modal {
        max-height: 94vh;
    }
}

/* Passed status badge */

.module-status.passed {
    background: transparent;
    border: 1px solid var(--success-color);
    color: var(--success-color);
}

@media (max-width: 600px) {
    .match-board {
        grid-template-columns: 1fr;
    }
}

/* Global Footer */

.global-footer {
    background-color: var(--header-bg);
    border-top: 1px solid var(--panel-border);
    text-align: center;
    padding: 1.5rem 2rem;
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.footer-note {
    font-size: 0.8rem;
    margin-top: 0.35rem;
}

/* Responsive adjustments */

/* On narrower screens the split layout stacks vertically, the video on top and
   the Micro Practice below, so neither column gets crushed. */
@media (max-width: 800px) {
    .video-lesson-split {
        grid-template-columns: 1fr;
    }
}

/* The unified mobile breakpoint. Everything structural collapses here: the
   header stacks into a single column, the control dropdowns become a wrap-ready
   flex matrix, the interactives dashboard folds to one column with a full-width
   navigation panel on top, and the progress banner stays bounded inside the
   viewport. All colors keep resolving through the theme tokens, so light and
   dark both render natively. */
@media (max-width: 768px) {
    .global-header {
        padding: 1.25rem 1rem;
    }

    .header-inner {
        flex-direction: column;
        align-items: stretch;
    }

    /* min-width: 0 releases each stacked block from its content's min-content
       width, so a wide child (like the sign-in chip row) can never push the
       whole header past the viewport edge. */
    .brand-block,
    .header-controls,
    .auth-controls {
        min-width: 0;
        max-width: 100%;
    }

    .app-title {
        font-size: 1.4rem;
        overflow-wrap: break-word;
    }

    /* The action dropdown row (Browse, Exploration Mode, Color Theme) as a
       wrap-ready flex matrix: triggers flow onto new lines instead of crowding
       or overlapping. */
    .header-controls {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.75rem;
    }

    /* An open menu panel never extends past the phone's right edge. */
    .nav-dropdown-menu {
        max-width: calc(100vw - 2rem);
    }

    /* The sign-in button and the sync status chip wrap as independent rows
       rather than forcing one wide line; the chip's text breaks normally. */
    .auth-controls {
        flex-wrap: wrap;
    }

    .auth-status {
        white-space: normal;
        max-width: 100%;
    }

    /* Progress banner: stacked metrics bounded to the viewport width. */
    .progress-banner {
        flex-direction: column;
        align-items: stretch;
        gap: 0.75rem;
        max-width: 100%;
        box-sizing: border-box;
    }

    .app-container {
        padding: 0 1rem;
    }

    /* The interactives dashboard collapses to a single column: the sticky
       sidebar un-sticks and sits full-width above the content, pushing it
       beneath. Its links stay stacked vertically, since the full descriptive
       titles read better as wrapped rows than as cramped horizontal chips. */
    .interactives-layout {
        flex-direction: column;
    }

    .interactives-sidebar {
        position: static;
        flex-basis: auto;
        width: 100%;
        max-height: none;
        overflow-y: visible;
    }
}
