/* /Components/Layout/Breadcrumbs.razor.rz.scp.css */
.breadcrumbs[b-z7y7p98ed4] {
    /* No margin: the trail lives inside .app-topbar now, which owns the
       padding and the border below it. */
    min-width: 0;
}

.breadcrumbs ol[b-z7y7p98ed4] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.15rem 0.4rem;
    list-style: none;
    margin: 0;
    padding: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    font-weight: 700;
}

.breadcrumbs li[b-z7y7p98ed4] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

/* Separator on the marker, not between elements, so it never wraps onto a
   line by itself. */
.breadcrumbs li + li[b-z7y7p98ed4]::before {
    content: '›';
    color: var(--edf-muted, #dadada);
    font-weight: 800;
}

.breadcrumbs a[b-z7y7p98ed4] {
    color: var(--edf-ink-soft, #5a6b7b);
    text-decoration: none;
    padding: 0.15rem 0.1rem;
    border-radius: 4px;
}

.breadcrumbs a:hover[b-z7y7p98ed4] {
    color: var(--edf-pink, #e94b93);
    text-decoration: underline;
}

.breadcrumbs [aria-current="page"][b-z7y7p98ed4] {
    color: var(--edf-ink, #1e1e1e);
    font-weight: 800;
}

@media (max-width: 640.98px) {
    .breadcrumbs ol[b-z7y7p98ed4] {
        font-size: 0.75rem;
    }
}
/* /Components/Layout/ConnectionWatch.razor.rz.scp.css */
/* A BAR ACROSS THE TOP, NOT A COVER OVER THE PAGE (2026-10-09). A false
   alarm - a slow connection, or the watch itself misjudging - must not lock a
   child out of buttons that work. Covering the page made the worst case "the
   whole app unusable until a redeploy"; a bar makes it an annoying message.

   Not display:flex on the element itself: that would beat the hidden
   attribute, and the bar would show on every page from the first paint. */
.connection-watch:not([hidden])[b-3i74muzf5h] {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2000;
    padding-top: env(safe-area-inset-top);
    background: var(--edf-yellow);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
}

.connection-watch-card[b-3i74muzf5h] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem 1rem;
    /* Room on the right for the close button, so text never runs under it. */
    padding: 0.6rem 3.5rem 0.6rem 1rem;
    text-align: center;
    font-family: var(--edf-font-display);
    font-size: 1rem;
    color: var(--edf-ink);
}

.connection-watch-card p[b-3i74muzf5h] {
    margin: 0;
}

/* One reason at a time; the script puts it on the outer element. */
.connection-watch-too-old[b-3i74muzf5h],
.connection-watch-no-circuit[b-3i74muzf5h] {
    display: none;
}

.reason-too-old .connection-watch-too-old[b-3i74muzf5h],
.reason-no-circuit .connection-watch-no-circuit[b-3i74muzf5h] {
    display: block;
}

.connection-watch-card button[b-3i74muzf5h] {
    min-height: 44px;
    touch-action: manipulation;
}

/* 44px tap target around a small ✕ (Apple's minimum; see CLAUDE.md). */
.connection-watch-close[b-3i74muzf5h] {
    position: absolute;
    top: calc(env(safe-area-inset-top) + 0.25rem);
    right: 0.25rem;
    width: 44px;
    height: 44px;
    border: none;
    background: transparent;
    font-size: 1.25rem;
    line-height: 1;
    color: var(--edf-ink);
    cursor: pointer;
}

/* Small, for whoever helps: which browser version this iPad is on. */
.connection-watch-browser[b-3i74muzf5h] {
    font-family: inherit;
    font-size: 0.8rem;
    opacity: 0.75;
}
/* /Components/Layout/LanguageSwitcher.razor.rz.scp.css */
.language-switcher[b-g8mday6zsp] {
    /* relative, not fixed: it is laid out by .app-topbar (MainLayout) so it
       sits on that bar's white strip on every page, and can never overlap an
       exercise's own background. Still positioned, because .language-options
       anchors to it. */
    position: relative;
    z-index: 1040;
}

.language-current[b-g8mday6zsp] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--edf-ink, #1e1e1e);
    background: var(--edf-surface, #fff);
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 100px;
    padding: 0.4rem 0.9rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.language-current[b-g8mday6zsp]::-webkit-details-marker {
    display: none;
}

.language-current[b-g8mday6zsp]::after {
    content: '';
    width: 0.4rem;
    height: 0.4rem;
    border-right: 2px solid var(--edf-ink-soft, #5a6b7b);
    border-bottom: 2px solid var(--edf-ink-soft, #5a6b7b);
    transform: rotate(45deg) translateY(-2px);
    margin-left: 0.15rem;
}

.language-switcher[open] .language-current[b-g8mday6zsp]::after {
    transform: rotate(-135deg) translateY(2px);
}

.language-current img[b-g8mday6zsp],
.language-options img[b-g8mday6zsp] {
    display: block;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
    flex-shrink: 0;
}

.language-options[b-g8mday6zsp] {
    list-style: none;
    margin: 0.4rem 0 0;
    padding: 0.4rem;
    position: absolute;
    right: 0;
    min-width: 11rem;
    background: var(--edf-surface, #fff);
    border-radius: 0.75rem;
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.2);
}

.language-options a[b-g8mday6zsp] {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.6rem;
    border-radius: 0.5rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--edf-ink, #1e1e1e);
    text-decoration: none;
}

.language-options a:hover[b-g8mday6zsp] {
    background: var(--edf-surface-alt, #f9f9f9);
}

.language-options a.active[b-g8mday6zsp] {
    background: #e5f0fa;
    color: var(--edf-blue, #1270b7);
    font-weight: 800;
}

@media (max-width: 640.98px) {
    .language-current[b-g8mday6zsp] {
        font-size: 0.78rem;
        padding: 0.3rem 0.6rem;
    }

    .language-current span[b-g8mday6zsp] {
        display: none;
    }
}
/* /Components/Layout/LoginLayout.razor.rz.scp.css */
.login-shell[b-efihpu5k3d] {
    min-height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 16px;
    background: #24b473;
    background-image: linear-gradient(160deg, #24b473 0%, #1270b7 100%);
}

#blazor-error-ui[b-efihpu5k3d] {
    color-scheme: light only;
    background: #fcee1f;
    color: #1270b7;
    font-weight: 800;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-efihpu5k3d] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-qkcsgju203] {
    position: relative;
    display: flex;
    flex-direction: column;
}

main[b-qkcsgju203] {
    flex: 1;
    background-color: #fff;
    /* The topbar must not scroll away from the article below it, and on desktop
       the article can be taller than the viewport. */
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Sidebar takes the site's green brand block */
.sidebar[b-qkcsgju203] {
    background-color: #24b473;
    background-image: linear-gradient(180deg, #24b473 0%, #1fa568 100%);
}

/* --- the checkbox that drives the sidebar collapse ---------------------
   Never visible; only its :checked state is used. */
.sidebar-toggle[b-qkcsgju203] {
    display: none;
}

/* --- topbar: breadcrumbs + language switcher, on every page ------------
   White, so the language dropdown always sits on the same neutral strip
   instead of floating over an exercise's blue background. */
.app-topbar[b-qkcsgju203] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
    padding: 0.5rem 1.5rem;
    background: #fff;
    border-bottom: 1px solid #f2f2f2;
}

.topbar-crumbs[b-qkcsgju203] {
    flex: 1;
    min-width: 0;
}

.topbar-lang[b-qkcsgju203] {
    flex-shrink: 0;
}

/* Phones: pin the shell to the viewport and let <main> be the scroll
   container, so a page can opt into filling exactly the space left over
   below the nav bar (see .mm-page in exercise.css) instead of adding to
   the document height. */
@media (max-width: 640.98px) {
    .page[b-qkcsgju203] {
        height: 100dvh;
    }

    main[b-qkcsgju203] {
        min-height: 0;
        overflow-y: auto;
    }

    article.content[b-qkcsgju203] {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-height: 0;
    }

    .app-topbar[b-qkcsgju203] {
        padding: 0.4rem 0.9rem;
    }

    /* The sidebar's own hamburger already collapses the nav on phones, so a
       second control would just be confusing. */
    .sidebar-toggle-btn[b-qkcsgju203] {
        display: none;
    }

    /* No pointer drag on phones; the sidebar width is layout-driven there. */
    .sidebar-resize-handle[b-qkcsgju203] {
        display: none;
    }
}

@media (min-width: 641px) {
    .page[b-qkcsgju203] {
        flex-direction: row;
    }

    .sidebar[b-qkcsgju203] {
        /* --sidebar-width is set on <html> by wwwroot/sidebar-resize.js from
           the persisted value; the fallback is the width used before the
           script has run (or if localStorage is unavailable). */
        width: var(--sidebar-width, 250px);
        /* dvh, with vh for browsers that predate it. On iPad Safari 100vh is
           the height with the toolbar HIDDEN, so while it shows, the bottom of
           the sidebar - where the collapse arrow sits - was under it. */
        height: 100vh;
        height: 100dvh;
        position: sticky;
        top: 0;
        flex-shrink: 0;
        /* Collapsing animates the width, so the content must be clipped
           rather than spilling into <main> on the way out. */
        overflow: hidden;
        transition: width .18s ease;
    }

    /* More specific than the rule above, so collapsing still wins over any
       dragged width. */
    .sidebar-toggle:checked ~ .sidebar[b-qkcsgju203] {
        width: 0;
    }

    /* The easing above would make a live drag trail the cursor. */
    :root.sidebar-resizing .sidebar[b-qkcsgju203] {
        transition: none;
    }

    /* Grip along the sidebar's inner right edge. Transparent until hovered or
       focused so it does not draw a line down the green block. */
    .sidebar-resize-handle[b-qkcsgju203] {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        width: 6px;
        cursor: col-resize;
        touch-action: none;
        background-color: transparent;
        transition: background-color .15s ease;
    }

    .sidebar-resize-handle:hover[b-qkcsgju203],
    .sidebar-resize-handle:focus-visible[b-qkcsgju203],
    :root.sidebar-resizing .sidebar-resize-handle[b-qkcsgju203] {
        background-color: rgba(255, 255, 255, 0.45);
        outline: none;
    }

    .app-topbar[b-qkcsgju203] {
        padding-left: 2rem;
        padding-right: 1.5rem;
    }

    article[b-qkcsgju203] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }

    /* Hamburger drawn from one <span> plus its two pseudo-elements. */
    .sidebar-toggle-btn[b-qkcsgju203] {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 2.25rem;
        height: 2.25rem;
        flex-shrink: 0;
        border-radius: 0.5rem;
        cursor: pointer;
        color: #6b7a88;
        transition: background-color .15s ease, color .15s ease;
    }

    .sidebar-toggle-btn:hover[b-qkcsgju203] {
        background-color: #f2f2f2;
        color: #1e1e1e;
    }

    .sidebar-toggle-btn > span[b-qkcsgju203] {
        position: relative;
        display: block;
        width: 1.15rem;
        height: 2px;
        border-radius: 2px;
        background-color: currentColor;
    }

    .sidebar-toggle-btn > span[b-qkcsgju203]::before,
    .sidebar-toggle-btn > span[b-qkcsgju203]::after {
        content: '';
        position: absolute;
        left: 0;
        width: 100%;
        height: 100%;
        border-radius: 2px;
        background-color: currentColor;
    }

    .sidebar-toggle-btn > span[b-qkcsgju203]::before {
        top: -6px;
    }

    .sidebar-toggle-btn > span[b-qkcsgju203]::after {
        top: 6px;
    }
}

#blazor-error-ui[b-qkcsgju203] {
    color-scheme: light only;
    background: #fcee1f;
    color: #1270b7;
    font-weight: 800;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-qkcsgju203] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

/* Bottom-left reopen control: hidden unless the sidebar is collapsed, and
   never on phones, where the sidebar has its own hamburger. */
.sidebar-reopen[b-qkcsgju203] {
    display: none;
}

@media (min-width: 641px) {
    .sidebar-toggle:checked ~ .sidebar-reopen[b-qkcsgju203] {
        position: fixed;
        left: 0.7rem;
        bottom: 0.7rem;
        z-index: 1030;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 2.1rem;
        height: 2.1rem;
        border-radius: 0.45rem;
        cursor: pointer;
        color: #fff;
        background-color: #24b473;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        user-select: none;
        transition: background-color .15s ease;
    }

    .sidebar-toggle:checked ~ .sidebar-reopen:hover[b-qkcsgju203] {
        background-color: #1fa568;
    }

    /* Two right-pointing chevrons, mirroring the collapse control in the
       sidebar (NavMenu.razor.css) — borders rather than a glyph. */
    .sidebar-reopen > span[b-qkcsgju203] {
        position: relative;
        display: block;
        width: 0.8rem;
        height: 0.5rem;
    }

    .sidebar-reopen > span[b-qkcsgju203]::before,
    .sidebar-reopen > span[b-qkcsgju203]::after {
        content: '';
        position: absolute;
        top: 50%;
        width: 0.34rem;
        height: 0.34rem;
        border-top: 2px solid currentColor;
        border-right: 2px solid currentColor;
        transform: translateY(-50%) rotate(45deg);
    }

    .sidebar-reopen > span[b-qkcsgju203]::before {
        left: 0.06rem;
    }

    .sidebar-reopen > span[b-qkcsgju203]::after {
        left: 0.36rem;
    }
}
/* /Components/Layout/NavMenu.razor.rz.scp.css */
.navbar-toggler[b-stj3ks8k55] {
    appearance: none;
    cursor: pointer;
    width: 3.5rem;
    height: 2.5rem;
    color: white;
    position: absolute;
    top: 0.5rem;
    right: 1rem;
    border-radius: 100px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.85%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(0, 0, 0, 0.15);
}

.navbar-toggler:checked[b-stj3ks8k55] {
    background-color: rgba(0, 0, 0, 0.3);
}

.top-row[b-stj3ks8k55] {
    min-height: 3.5rem;
    background-color: #343434;
    border-bottom: 4px solid #e94b93;
}

.navbar-brand[b-stj3ks8k55] {
    display: flex;
    align-items: center;
    padding: 0;
    margin: 0;
}

/* Round white disc. object-fit is contain rather than cover because the arched
   "ESTRELA DA FAVELA" wordmark overhangs the emblem's green circle, and a
   cover-crop would slice it off. */
.brand-logo[b-stj3ks8k55] {
    display: block;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    background: #fff;
    object-fit: contain;
    padding: 2px;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
    transition: box-shadow .15s ease, transform .15s ease;
}

.navbar-brand:hover .brand-logo[b-stj3ks8k55] {
    box-shadow: 0 0 0 2px #fcee1f;
    transform: scale(1.04);
}

/* Breathing room under the brand bar's pink border. Lives on the container
   rather than the first item, because the items are rendered by
   NavTreeItem and scoped CSS cannot reach across components. */
.nav[b-stj3ks8k55] {
    padding-top: 1rem;
    padding-bottom: 0.5rem;
}

.nav-scrollable[b-stj3ks8k55] {
    display: none;
}

.navbar-toggler:checked ~ .nav-scrollable[b-stj3ks8k55] {
    display: block;
}

@media (min-width: 641px) {
    .navbar-toggler[b-stj3ks8k55] {
        display: none;
    }

    .nav-scrollable[b-stj3ks8k55] {
        /* Never collapse the sidebar for wide screens */
        display: block;

        /* Allow sidebar to scroll for tall menus. dvh for the same reason as
           .sidebar in MainLayout: the visible height, not the toolbar-hidden
           one. */
        height: calc(100vh - 3.5rem);
        height: calc(100dvh - 3.5rem);
        overflow-y: auto;
    }
}

/* Signed-in team member, at the head of the sidebar */
.nav-user[b-stj3ks8k55] {
    padding: 1rem 1.25rem 1.1rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.25);
    font-family: 'Trebuchet MS', sans-serif;
}

/* Round portrait, matching the brand logo's treatment in the bar above. */
.nav-user-avatar[b-stj3ks8k55] {
    width: 3.5rem;
    height: 3.5rem;
    margin-bottom: 0.6rem;
    border-radius: 50%;
    overflow: hidden;
    background: #fff;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
}

.nav-user-avatar img[b-stj3ks8k55] {
    width: 100%;
    height: 100%;
    /* cover, not contain: these are portraits, and letterboxing a face inside
       a circle looks broken. */
    object-fit: cover;
    display: block;
}

.nav-user-initials[b-stj3ks8k55] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.25rem;
    color: #1fa568;
}

.nav-user-row[b-stj3ks8k55] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.nav-user-text[b-stj3ks8k55] {
    min-width: 0;
}

.nav-user-name[b-stj3ks8k55] {
    color: #fff;
    font-weight: 800;
    font-size: 0.9rem;
    line-height: 1.2;
}

.nav-user-role[b-stj3ks8k55] {
    color: rgba(255, 255, 255, 0.75);
    font-weight: 600;
    font-size: 0.72rem;
    margin-top: 2px;
}

.nav-user-signout[b-stj3ks8k55] {
    display: inline-block;
    flex-shrink: 0;
    padding: 0.35rem 0.9rem;
    border-radius: 100px;
    background: rgba(0, 0, 0, 0.2);
    color: #fff;
    font-weight: 800;
    font-size: 0.75rem;
    text-decoration: none;
}

.nav-user-signout:hover[b-stj3ks8k55] {
    background: #e94b93;
    color: #fff;
    text-decoration: none;
}

/* Collapse control, bottom-right of the sidebar. Phones already collapse the
   nav with the hamburger in the bar above, so this is desktop-only. */
.sidebar-collapse[b-stj3ks8k55] {
    display: none;
}

@media (min-width: 641px) {
    .sidebar-collapse[b-stj3ks8k55] {
        /* Anchors to .sidebar, which is position:sticky and therefore a
           positioning context. */
        position: absolute;
        bottom: 0.55rem;
        right: 0.7rem;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 1.9rem;
        height: 1.9rem;
        border-radius: 0.45rem;
        cursor: pointer;
        color: rgba(255, 255, 255, 0.6);
        user-select: none;
        transition: background-color .15s ease, color .15s ease;
    }

    .sidebar-collapse:hover[b-stj3ks8k55] {
        background-color: rgba(0, 0, 0, 0.2);
        color: #fff;
    }

    /* Two left-pointing chevrons, drawn from borders so there is no font or
       encoding dependency. */
    .sidebar-collapse > span[b-stj3ks8k55] {
        position: relative;
        display: block;
        width: 0.8rem;
        height: 0.5rem;
    }

    .sidebar-collapse > span[b-stj3ks8k55]::before,
    .sidebar-collapse > span[b-stj3ks8k55]::after {
        content: '';
        position: absolute;
        top: 50%;
        width: 0.34rem;
        height: 0.34rem;
        border-left: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: translateY(-50%) rotate(45deg);
    }

    .sidebar-collapse > span[b-stj3ks8k55]::before {
        left: 0;
    }

    .sidebar-collapse > span[b-stj3ks8k55]::after {
        left: 0.3rem;
    }
}
/* /Components/Layout/NavTreeItem.razor.rz.scp.css */
/* Nav link styling lives here rather than in NavMenu.razor.css: scoped CSS is
   keyed to the component that declares the markup, and the links are declared
   in this component. */

.nav-item[b-6ap8tg0gdx] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 500;
    padding-bottom: 0.3rem;
}

.nav-item[b-6ap8tg0gdx]  .nav-link {
    display: flex;
    align-items: center;
    width: 100%;
    color: #dadada;
    background: none;
    border: none;
    border-radius: 100px;
    padding-right: 0.6rem;
}

.nav-item[b-6ap8tg0gdx]  a.active {
    background-color: #e94b93;
    color: #fff;
    font-weight: 800;
}

.nav-item[b-6ap8tg0gdx]  .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.18);
    color: #fff;
}

.nav-item[b-6ap8tg0gdx]  a.active:hover {
    background-color: #d13a80;
    color: #fff;
}

/* An ancestor of the current page: readable as "you are inside this" without
   competing with the pink pill on the page you are actually on. */
.nav-item[b-6ap8tg0gdx]  a.on-path {
    color: #fff;
    font-weight: 700;
    background-color: rgba(0, 0, 0, 0.18);
}

.nav-label[b-6ap8tg0gdx] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- depth ramp -------------------------------------------------------
   Each level is smaller, dimmer and further in than its parent, so a child
   of Adição is never mistaken for a sibling of Matemática. */
.depth-0 > .nav-item[b-6ap8tg0gdx]  .nav-link {
    font-size: 1.05rem;
    min-height: 2.75rem;
    padding-left: 0.9rem;
}

.depth-1 > .nav-item[b-6ap8tg0gdx]  .nav-link {
    font-size: 0.95rem;
    min-height: 2.35rem;
    padding-left: 0.75rem;
    color: #cfe9dc;
}

.depth-2 > .nav-item[b-6ap8tg0gdx]  .nav-link {
    font-size: 0.86rem;
    min-height: 2.1rem;
    padding-left: 0.75rem;
    color: #b6ddc9;
}

.depth-3 > .nav-item[b-6ap8tg0gdx]  .nav-link {
    font-size: 0.8rem;
    min-height: 1.95rem;
    padding-left: 0.75rem;
    color: #a5d4bd;
}

/* Guide rail: makes the parent/child relationship structural rather than
   something you infer from font size alone. */
.nav-children[b-6ap8tg0gdx] {
    margin-left: 1.4rem;
    padding-left: 0.55rem;
    border-left: 2px solid rgba(255, 255, 255, 0.28);
}

.depth-1 > .nav-children[b-6ap8tg0gdx],
.depth-2 > .nav-children[b-6ap8tg0gdx] {
    border-left-color: rgba(255, 255, 255, 0.18);
}

/* --- branch: label navigates, caret toggles --- */
.nav-summary[b-6ap8tg0gdx] {
    display: flex;
    align-items: center;
    list-style: none;
    cursor: default;
}

.nav-summary[b-6ap8tg0gdx]::-webkit-details-marker {
    display: none;
}

/* The link fills the row; only the caret box toggles the branch. */
.nav-summary > .nav-item[b-6ap8tg0gdx] {
    flex: 1;
    min-width: 0;
}

.nav-caret[b-6ap8tg0gdx] {
    display: flex;
    align-items: center;
    justify-content: center;
    /* A finger-sized hit area — the arrow itself is far too small to tap. */
    width: 2.25rem;
    align-self: stretch;
    flex-shrink: 0;
    cursor: pointer;
    color: #dadada;
    opacity: 0.75;
}

.nav-caret[b-6ap8tg0gdx]::before {
    content: '';
    width: 0.4rem;
    height: 0.4rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(-45deg) translate(-1px, -1px);
    transition: transform .15s ease;
}

.nav-caret:hover[b-6ap8tg0gdx] {
    opacity: 1;
}

.nav-branch[open] > .nav-summary > .nav-caret[b-6ap8tg0gdx]::before {
    transform: rotate(45deg) translate(-1px, -1px);
}

.bi[b-6ap8tg0gdx] {
    display: inline-block;
    position: relative;
    width: 1.25rem;
    height: 1.25rem;
    margin-right: 0.75rem;
    top: -1px;
    background-size: cover;
    flex-shrink: 0;
}

.bi-house-door-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}

.bi-plus-square-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}

.bi-people-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-people-fill' viewBox='0 0 16 16'%3E%3Cpath d='M7 14s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1zm4-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6m-5.784 6A2.24 2.24 0 0 1 5 13c0-1.355.68-2.75 1.936-3.72A6.3 6.3 0 0 0 5 9c-4 0-5 3-5 4s1 1 1 1zM4.5 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5'/%3E%3C/svg%3E");
}

.bi-mortarboard-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-mortarboard-fill' viewBox='0 0 16 16'%3E%3Cpath d='M8.211 2.047a.5.5 0 0 0-.422 0l-7.5 3.5a.5.5 0 0 0 .025.917l7.5 3a.5.5 0 0 0 .372 0L14 7.14V13a1 1 0 0 0-1 1v2h3v-2a1 1 0 0 0-1-1V6.739l.686-.275a.5.5 0 0 0 .025-.917z'/%3E%3Cpath d='M4.176 9.032a.5.5 0 0 0-.656.327l-.5 1.7a.5.5 0 0 0 .294.605l4.5 1.8a.5.5 0 0 0 .372 0l4.5-1.8a.5.5 0 0 0 .294-.605l-.5-1.7a.5.5 0 0 0-.656-.327L8 10.466z'/%3E%3C/svg%3E");
}

.bi-easel-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-easel-fill' viewBox='0 0 16 16'%3E%3Cpath d='M8.473.337a.5.5 0 0 0-.946 0L6.954 2H2a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h1.85l-1.323 3.837a.5.5 0 1 0 .946.326L4.908 11H7.5v2.5a.5.5 0 0 0 1 0V11h2.592l1.435 4.163a.5.5 0 0 0 .946-.326L12.15 11H14a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H9.046z'/%3E%3C/svg%3E");
}

.bi-lightbulb-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-lightbulb-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 6a6 6 0 1 1 10.174 4.31c-.203.196-.359.4-.453.619l-.762 1.769A.5.5 0 0 1 10.5 13a.5.5 0 0 1 0 1 .5.5 0 0 1 0 1l-.224.447a1 1 0 0 1-.894.553H6.618a1 1 0 0 1-.894-.553L5.5 15a.5.5 0 0 1 0-1 .5.5 0 0 1 0-1 .5.5 0 0 1-.46-.302l-.761-1.77a2 2 0 0 0-.453-.618A5.98 5.98 0 0 1 2 6'/%3E%3C/svg%3E");
}

/* Bootstrap Icons "play-btn-fill", for the how-to videos. */
.bi-broadcast-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-broadcast' viewBox='0 0 16 16'%3E%3Cpath d='M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707m2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708m5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708m2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM10 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0'/%3E%3C/svg%3E");
}

.bi-flag-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-flag-fill' viewBox='0 0 16 16'%3E%3Cpath d='M14.778.085A.5.5 0 0 1 15 .5V8a.5.5 0 0 1-.314.464L14.5 8l.186.464-.003.001-.006.003-.023.009a12 12 0 0 1-.397.15c-.264.095-.631.223-1.047.35-.816.252-1.879.523-2.71.523-.847 0-1.548-.28-2.158-.525l-.028-.01C7.68 8.71 7.14 8.5 6.5 8.5c-.7 0-1.638.23-2.437.477A20 20 0 0 0 3 9.342V15.5a.5.5 0 0 1-1 0V.5a.5.5 0 0 1 1 0v.282c.226-.079.496-.17.79-.26C4.606.272 5.67 0 6.5 0c.84 0 1.524.277 2.121.519l.043.018C9.286.788 9.828 1 10.5 1c.7 0 1.638-.23 2.437-.477a20 20 0 0 0 1.349-.476l.019-.007.004-.002h.001'/%3E%3C/svg%3E");
}

.bi-play-btn-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-play-btn-fill' viewBox='0 0 16 16'%3E%3Cpath d='M0 12V4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2m6.79-6.907A.5.5 0 0 0 6 5.5v5a.5.5 0 0 0 .79.407l3.5-2.5a.5.5 0 0 0 0-.814z'/%3E%3C/svg%3E");
}

/* Bootstrap Icons "stars", for the AI exercise generator. Inlined as a data URI
   like the others above: the icon font is not loaded, so each nav glyph is its
   own background image. */
.bi-stars-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-stars' viewBox='0 0 16 16'%3E%3Cpath d='M7.657 6.247c.11-.33.576-.33.686 0l.645 1.937a2.89 2.89 0 0 0 1.829 1.828l1.936.645c.33.11.33.576 0 .686l-1.937.645a2.89 2.89 0 0 0-1.828 1.829l-.645 1.936a.361.361 0 0 1-.686 0l-.645-1.937a2.89 2.89 0 0 0-1.828-1.828l-1.937-.645a.361.361 0 0 1 0-.686l1.937-.645a2.89 2.89 0 0 0 1.828-1.828zM3.794 1.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387A1.73 1.73 0 0 0 4.593 5.69l-.387 1.162a.217.217 0 0 1-.412 0L3.407 5.69A1.73 1.73 0 0 0 2.31 4.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387A1.73 1.73 0 0 0 3.407 2.31zM10.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.16 1.16 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.16 1.16 0 0 0-.732-.732L9.1 2.137a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732z'/%3E%3C/svg%3E");
}

/* Bootstrap Icons "puzzle-fill", for Math Dynamic. Chosen to match the 
   section's own puzzle-piece emoji on the hub cards, so the sidebar and the
   cards name the same thing. SiteMap previously asked for "diagram-3-fill",
   which has no rule here, so the slot simply rendered empty. */
.bi-puzzle-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-puzzle-fill' viewBox='0 0 16 16'%3E%3Cpath d='M3.112 3.645A1.5 1.5 0 0 1 4.605 2H7a.5.5 0 0 1 .5.5v.382c0 .696-.497 1.182-.872 1.469a.5.5 0 0 0-.115.118l-.012.025L6.5 4.5v.003l.003.01q.005.015.036.053a.9.9 0 0 0 .27.194C7.09 4.9 7.51 5 8 5c.492 0 .912-.1 1.19-.24a.9.9 0 0 0 .271-.194.2.2 0 0 0 .036-.054l.003-.01v-.008l-.012-.025a.5.5 0 0 0-.115-.118c-.375-.287-.872-.773-.872-1.469V2.5A.5.5 0 0 1 9 2h2.395a1.5 1.5 0 0 1 1.493 1.645L12.645 6.5h.237c.195 0 .42-.147.675-.48.21-.274.528-.52.943-.52.568 0 .947.447 1.154.862C15.877 6.807 16 7.387 16 8s-.123 1.193-.346 1.638c-.207.415-.586.862-1.154.862-.415 0-.733-.246-.943-.52-.255-.333-.48-.48-.675-.48h-.237l.243 2.855A1.5 1.5 0 0 1 11.395 14H9a.5.5 0 0 1-.5-.5v-.382c0-.696.497-1.182.872-1.469a.5.5 0 0 0 .115-.118l.012-.025.001-.006v-.003l-.003-.01a.2.2 0 0 0-.036-.053.9.9 0 0 0-.27-.194C8.91 11.1 8.49 11 8 11s-.912.1-1.19.24a.9.9 0 0 0-.271.194.2.2 0 0 0-.036.054l-.003.01v.002l.001.006.012.025c.016.027.05.068.115.118.375.287.872.773.872 1.469v.382a.5.5 0 0 1-.5.5H4.605a1.5 1.5 0 0 1-1.493-1.645L3.356 9.5h-.238c-.195 0-.42.147-.675.48-.21.274-.528.52-.943.52-.568 0-.947-.447-1.154-.862C.123 9.193 0 8.613 0 8s.123-1.193.346-1.638C.553 5.947.932 5.5 1.5 5.5c.415 0 .733.246.943.52.255.333.48.48.675.48h.238z'/%3E%3C/svg%3E");
}

/* Bootstrap Icons "signpost-fill", for Learning routes - the other nav node
   whose icon slot was rendering empty for want of a rule. */
.bi-signpost-fill-nav-menu[b-6ap8tg0gdx] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-signpost-fill' viewBox='0 0 16 16'%3E%3Cpath d='M7.293.707A1 1 0 0 0 7 1.414V4H2a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h5v6h2v-6h3.532a1 1 0 0 0 .768-.36l1.933-2.32a.5.5 0 0 0 0-.64L13.3 4.36a1 1 0 0 0-.768-.36H9V1.414A1 1 0 0 0 7.293.707'/%3E%3C/svg%3E");
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
dialog[b-k9tri7f8je] {
    border: none;
    border-radius: 12px;
    padding: 0;
    max-width: min(22rem, calc(100vw - 2rem));
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25);
}

dialog[b-k9tri7f8je]::backdrop {
    background: var(--edf-overlay);
}

.reconnect-card[b-k9tri7f8je] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 1.75rem 1.5rem;
    text-align: center;
    font-family: var(--edf-font-display);
    font-size: 1.15rem;
    color: var(--edf-ink);
}

.reconnect-card p[b-k9tri7f8je] {
    margin: 0;
}

/* Every message is hidden until the state class the framework (or the
   script, for "rejected") puts on the dialog asks for it. */
.reconnect-card > *[b-k9tri7f8je] {
    display: none;
}

.components-reconnect-show .reconnect-first[b-k9tri7f8je],
.components-reconnect-show .reconnect-busy[b-k9tri7f8je],
.components-reconnect-retrying .reconnect-retrying[b-k9tri7f8je],
.components-reconnect-retrying .reconnect-busy[b-k9tri7f8je],
.components-reconnect-rejected .reconnect-rejected[b-k9tri7f8je],
.components-reconnect-rejected .reconnect-busy[b-k9tri7f8je],
.components-reconnect-failed .reconnect-failed[b-k9tri7f8je],
.components-reconnect-paused .reconnect-paused[b-k9tri7f8je],
.components-reconnect-resume-failed .reconnect-resume-failed[b-k9tri7f8je] {
    display: block;
}

.components-reconnect-retrying .reconnect-first[b-k9tri7f8je] {
    display: none;
}

.reconnect-spinner[b-k9tri7f8je] {
    width: 3rem;
    height: 3rem;
    border: 0.35rem solid var(--edf-muted);
    border-top-color: var(--edf-pink);
    border-radius: 50%;
    animation: reconnect-spin-b-k9tri7f8je 0.9s linear infinite;
}

@keyframes reconnect-spin-b-k9tri7f8je {
    to { transform: rotate(360deg); }
}
/* /Components/Pages/Admin/AiGeneratorWorkbench.razor.rz.scp.css */
/* Editor and playtest side by side, because the point of the page is watching
   one change the other. They stack below the app's own phone breakpoint - a
   split screen on a phone is two unusable panes rather than one useful one, and
   this is a desktop authoring tool anyway. */
.workbench-split[b-omjgvzeuv1] {
    display: grid;
    gap: 1rem;
    grid-template-columns: 1fr;
    align-items: start;
}

@media (min-width: 992px) {
    .workbench-split[b-omjgvzeuv1] {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

/* min-width: 0 on the panes as well: a grid item's default min-width is auto,
   so one long unbroken line in the JSON (a base64 glyph, a wide expression)
   would otherwise push the column wider than its track and make the whole page
   scroll sideways. */
.workbench-pane[b-omjgvzeuv1] {
    min-width: 0;
    overflow-x: auto;
}

.workbench-editor[b-omjgvzeuv1] {
    font-family: ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
    font-size: 0.85rem;
    line-height: 1.45;
    min-height: 26rem;
    white-space: pre;
    tab-size: 2;
}

/* Status lines. Same treatment as the roster and idea pages, restated rather
   than shared: .backup-message is defined in each page's own scoped stylesheet,
   and Blazor's CSS isolation does not cascade one component's rules into
   another. */
.backup-message[b-omjgvzeuv1] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: #2e8a54;
}

.backup-message.is-error[b-omjgvzeuv1] {
    color: #e0503d;
}

/* The neutral default above already reads as "went well"; the modifier exists
   so the intent is stated at the call site rather than inferred from a colour. */
.backup-message.is-success[b-omjgvzeuv1] {
    color: #2e8a54;
}

/* --- the file picker ----------------------------------------------------
   Off-screen rather than display:none: a hidden-by-display input is removed
   from the tab order, and the label below would then be the only way in for a
   mouse. This keeps it focusable, with the focus ring drawn on the label. */
/* A visible target. Dashed, because that is the one border convention people
   already read as "things can be dropped here". */
.file-field[b-omjgvzeuv1] {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.7rem 0.9rem;
    border: 2px dashed #d9e6ee;
    border-radius: 0.6rem;
    background: #fbfdfe;
    transition: border-color .15s ease, background-color .15s ease;
}

/* Set while a drag is over the box, and flashed briefly after a paste that
   landed somewhere else on the page - otherwise a paste has no visible effect
   until the attachment list redraws. */
.file-field.is-active[b-omjgvzeuv1] {
    border-color: #24b473;
    background: #eef7f2;
}

.file-drop-hint[b-omjgvzeuv1] {
    flex: 1;
    min-width: 12rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    color: #6b7a88;
}

/* ::deep, because the <input> is rendered by InputFile and not by this
   component - scoped CSS puts its attribute on OUR elements only, so a plain
   selector compiles to input[b-xxx] and matches nothing. The wrapper above
   carries the attribute; ::deep steps past it into the child's markup.

   Clipped rather than display:none - the latter takes the input out of the tab
   order, leaving the label reachable by mouse alone. */
.file-field[b-omjgvzeuv1]  input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.file-pick[b-omjgvzeuv1] {
    display: inline-block;
    padding: 0.35rem 0.9rem;
    border: 1px solid #d9e6ee;
    border-radius: 0.4rem;
    background: #fff;
    color: #4a5560;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.8rem;
    cursor: pointer;
}

.file-pick:hover[b-omjgvzeuv1] {
    border-color: #24b473;
    color: #1e1e1e;
}

.file-field[b-omjgvzeuv1]  input[type="file"]:focus-visible + .file-pick {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

/* --- tags on the spec being edited -------------------------------------
   A row under the validity line, inside the editor pane, because that is what
   the tags belong to: the document in the textarea, not the save panel below
   where the category and the file name live. */
.workbench-tags[b-omjgvzeuv1] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.7rem;
    padding-top: 0.7rem;
    border-top: 1px solid #eef3f7;
}

.workbench-tags-label[b-omjgvzeuv1] {
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.78rem;
    font-weight: 700;
    color: #4a5560;
}

.workbench-tags-empty[b-omjgvzeuv1] {
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.78rem;
    color: #9aa7b2;
    font-style: italic;
}

.workbench-tag[b-omjgvzeuv1] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.3rem 0.15rem 0.6rem;
    border: 1px solid #cfe6da;
    border-radius: 999px;
    background: #f2f8f5;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.78rem;
    color: #14664a;
}

.workbench-tag-remove[b-omjgvzeuv1] {
    border: 0;
    background: none;
    padding: 0 0.25rem;
    font-size: 0.95rem;
    line-height: 1;
    color: #6d8a7c;
    cursor: pointer;
}

.workbench-tag-remove:hover[b-omjgvzeuv1] {
    color: #b3261e;
}

/* Narrow: a tag is two or three words, and a full-width box beside the chips
   would read as the place the whole spec is edited. */
.workbench-tag-input[b-omjgvzeuv1] {
    width: 11rem;
    font-size: 0.78rem;
    padding: 0.2rem 0.45rem;
}
/* /Components/Pages/GettingStarted/GettingStartedPage.razor.rz.scp.css */
/* The four language versions are child components, so their markup carries
   their own scope - hence ::deep for everything below the card. */

.getting-started[b-s63bemy3to] {
    max-width: 52rem;
    font-size: 1rem;
    line-height: 1.55;
}

.getting-started[b-s63bemy3to]  h2 {
    margin: 1.75rem 0 0.6rem;
    font-size: 1.25rem;
    color: #14664a;
}

.getting-started[b-s63bemy3to]  h2:first-child {
    margin-top: 0;
}

.getting-started[b-s63bemy3to]  ol,
.getting-started[b-s63bemy3to]  ul {
    padding-left: 1.4rem;
    margin-bottom: 0.75rem;
}

.getting-started[b-s63bemy3to]  li {
    margin-bottom: 0.35rem;
}

.getting-started[b-s63bemy3to]  li ul {
    margin: 0.3rem 0 0;
}

/* The intro facts: goal, time, what you need. */
.getting-started[b-s63bemy3to]  .gs-facts {
    list-style: none;
    padding: 0;
}

/* The "this is a test" note. */
.getting-started[b-s63bemy3to]  .gs-note {
    margin: 1rem 0 0.5rem;
    padding: 0.7rem 0.9rem;
    border-left: 4px solid #e6a817;
    border-radius: 0.4rem;
    background: #fffaf0;
}

.getting-started[b-s63bemy3to]  code {
    padding: 0.05rem 0.35rem;
    border-radius: 0.3rem;
    background: #e5f0fa;
    color: #1270b7;
}

.getting-started[b-s63bemy3to]  hr {
    margin: 2rem 0 1.25rem;
    border-color: #e3ecf2;
    opacity: 1;
}
/* /Components/Pages/Ideas/IdeaDetail.razor.rz.scp.css */
.roster-head[b-eggn7na9q3] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.roster-head h2[b-eggn7na9q3] {
    margin: 0;
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.5rem;
    color: var(--edf-green, #24b473);
}

.idea-count[b-eggn7na9q3] {
    color: var(--edf-ink, #1e1e1e);
    font-weight: 500;
    font-size: 1rem;
}

/* pre-wrap so the teacher's own paragraphs and line breaks survive, without
   us interpreting any of their text as markup. */
.idea-body[b-eggn7na9q3] {
    margin: 0;
    white-space: pre-wrap;
    line-height: 1.6;
    max-width: 48rem;
}

/* The file input is opened by clicking its own label, which already looks like
   a button. */
.restore-button[b-eggn7na9q3] {
    margin: 0;
    cursor: pointer;
}

.restore-button[b-eggn7na9q3]  input[type="file"] {
    display: none;
}

.backup-message[b-eggn7na9q3] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: #2e8a54;
}

.backup-message.is-error[b-eggn7na9q3] {
    color: #e0503d;
}

/* --- attachments -------------------------------------------------------- */
.attachment-grid[b-eggn7na9q3] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    /* auto-fill rather than a fixed count, so the grid reflows from a phone to
       a wide screen without breakpoints. */
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: 0.75rem;
}

.attachment[b-eggn7na9q3] {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--edf-surface-alt, #f9f9f9);
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.6rem;
    overflow: hidden;
}

.attachment-open[b-eggn7na9q3] {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.6rem;
    color: var(--edf-ink, #1e1e1e);
    text-decoration: none;
    min-width: 0;
}

.attachment-open:hover[b-eggn7na9q3] {
    background: #f1f7f4;
    text-decoration: none;
}

/* Fixed height with cover, so a portrait and a landscape photo produce tiles
   of the same size instead of a ragged grid. */
.attachment img[b-eggn7na9q3] {
    width: 100%;
    height: 7rem;
    object-fit: cover;
    border-radius: 0.4rem;
    background: #fff;
    display: block;
}

.attachment-icon[b-eggn7na9q3] {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 7rem;
    font-size: 2.5rem;
    background: #fff;
    border-radius: 0.4rem;
}

.attachment-name[b-eggn7na9q3] {
    font-size: 0.78rem;
    font-weight: 700;
    /* Long file names are the norm; break rather than widen the tile. */
    overflow-wrap: anywhere;
    line-height: 1.3;
}

.attachment-size[b-eggn7na9q3] {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
}

.attachment-remove[b-eggn7na9q3] {
    margin: 0 0.6rem 0.6rem;
}

/* --- discussion --------------------------------------------------------- */
.comment-list[b-eggn7na9q3] {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.comment[b-eggn7na9q3] {
    padding: 0.7rem 0.9rem;
    background: var(--edf-surface-alt, #f9f9f9);
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.6rem;
}

.comment-head[b-eggn7na9q3] {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin-bottom: 0.3rem;
}

.comment-author[b-eggn7na9q3] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.85rem;
    color: var(--edf-green, #24b473);
}

.comment-date[b-eggn7na9q3] {
    flex: 1;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
}

.comment-remove[b-eggn7na9q3] {
    flex-shrink: 0;
    width: 1.4rem;
    height: 1.4rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #fde7e4;
    color: var(--edf-pink-dark, #d13a80);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.comment-remove:hover[b-eggn7na9q3] {
    background: var(--edf-pink-dark, #d13a80);
    color: #fff;
}

/* pre-wrap so the writer's own line breaks survive, without their text ever
   being interpreted as markup. */
.comment-body[b-eggn7na9q3] {
    margin: 0;
    white-space: pre-wrap;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.comment-form[b-eggn7na9q3] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.6rem;
}

.comment-input[b-eggn7na9q3] {
    width: 100%;
    resize: vertical;
    font-family: inherit;
}

/* A withdrawn comment: still present so the thread reads, visibly not a
   comment any more. */
.comment.is-deleted[b-eggn7na9q3] {
    background: #fff;
    border-style: dashed;
}

.comment.is-deleted .comment-author[b-eggn7na9q3],
.comment.is-deleted .comment-date[b-eggn7na9q3] {
    color: #9aa7b2;
}

.comment-deleted[b-eggn7na9q3] {
    font-style: italic;
    color: #9aa7b2;
}

/* --- back to the list, at the top of the page --------------------------- */
.idea-back[b-eggn7na9q3] {
    margin: 0 0 1rem;
}

.idea-back a[b-eggn7na9q3] {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

/* Chevron from borders, matching the sidebar's collapse control rather than
   depending on a glyph. */
.idea-back-arrow[b-eggn7na9q3] {
    width: 0.4rem;
    height: 0.4rem;
    border-left: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    flex-shrink: 0;
}

/* --- grading ------------------------------------------------------------ */
.grade-label[b-eggn7na9q3] {
    margin: 0 0 0.5rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.78rem;
    color: var(--edf-ink-soft, #5a6b7b);
}

.grade-scale[b-eggn7na9q3] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.grade-button[b-eggn7na9q3] {
    width: 2.4rem;
    height: 2.4rem;
    flex-shrink: 0;
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem;
    background: var(--edf-surface-alt, #f9f9f9);
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.95rem;
    color: var(--edf-ink, #1e1e1e);
    cursor: pointer;
    transition: background-color .12s ease, color .12s ease;
}

.grade-button:hover[b-eggn7na9q3] {
    background: #e5f0fa;
    color: var(--edf-blue, #1270b7);
}

/* The grade this person has given, so changing your mind starts from what you
   chose last time. */
.grade-button.is-mine[b-eggn7na9q3] {
    background: var(--edf-green, #24b473);
    border-color: var(--edf-green, #24b473);
    color: #fff;
}

.grade-button.is-mine:hover[b-eggn7na9q3] {
    background: #1fa568;
    color: #fff;
}

/* --- the removal confirmation -----------------------------------------
   Reuses the global .dialog-overlay/.dialog-card; only the two paragraphs are
   new. The warning is loud because the file itself goes with it. */
.confirm-body[b-eggn7na9q3] {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-warning[b-eggn7na9q3] {
    margin: 0 0 1rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.85rem;
    font-weight: 600;
    color: #8c2d22;
}
/* /Components/Pages/Ideas/IdeasList.razor.rz.scp.css */
.roster-head[b-lu01owb8gq] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.roster-head h2[b-lu01owb8gq] {
    margin: 0;
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.5rem;
    color: var(--edf-green, #24b473);
}

/* Desktop always shows the Add button, so there is nothing to unfold. */
.roster-toggle[b-lu01owb8gq] {
    display: none;
}

/* PHONES AND TABLETS - restated from Students.razor.css, which this page
   mirrors; scoped CSS cannot be shared. The heading becomes a card of its own
   above the table, with the Add button behind the arrow. */
@media (max-width: 1024.98px), (hover: none) and (pointer: coarse) {
    .roster-card[b-lu01owb8gq] {
        padding: 0;
        border: 0;
        background: none;
    }

    .roster-head[b-lu01owb8gq],
    .idea-table-scroll[b-lu01owb8gq] {
        padding: 0.6rem 1rem;
        border: 1px solid var(--edf-border, #f2f2f2);
        border-radius: 0.5rem;
        background: var(--edf-surface, #fff);
    }

    .roster-toggle[b-lu01owb8gq] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2.25rem;
        height: 2.25rem;
        margin-left: auto;
        padding: 0;
        border: 0;
        background: none;
        color: #8a97a3;
        cursor: pointer;
    }

    .roster-toggle > span[b-lu01owb8gq] {
        width: 0.7rem;
        height: 0.7rem;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: translateY(-0.2rem) rotate(45deg);
        transition: transform .15s ease;
    }

    .roster-head.is-open .roster-toggle > span[b-lu01owb8gq] {
        transform: translateY(0.2rem) rotate(-135deg);
    }

    .roster-toggle:focus-visible[b-lu01owb8gq] {
        outline: 2px solid #1270b7;
        outline-offset: 2px;
        border-radius: 0.4rem;
    }

    .roster-head .roster-tools[b-lu01owb8gq] {
        display: none;
    }

    .roster-head.is-open .roster-tools[b-lu01owb8gq] {
        display: flex;
        flex-basis: 100%;
    }
}

.idea-count[b-lu01owb8gq] {
    color: var(--edf-ink, #1e1e1e);
    font-weight: 500;
    font-size: 1rem;
}

.idea-table-scroll[b-lu01owb8gq] {
    overflow-x: auto;
}

.idea-table[b-lu01owb8gq] {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0 0.5rem;
}

.idea-table th[b-lu01owb8gq] {
    padding: 0 1rem 0.15rem;
    text-align: left;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--edf-ink-soft, #5a6b7b);
    white-space: nowrap;
}

.idea-table td[b-lu01owb8gq] {
    padding: 0.7rem 1rem;
    background: var(--edf-surface-alt, #f9f9f9);
    border-top: 1px solid var(--edf-border, #f2f2f2);
    border-bottom: 1px solid var(--edf-border, #f2f2f2);
    vertical-align: middle;
}

.idea-table td:first-child[b-lu01owb8gq] {
    border-left: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem 0 0 0.5rem;
}

.idea-table td:last-child[b-lu01owb8gq] {
    border-right: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0 0.5rem 0.5rem 0;
}

/* The whole row opens the idea, so it has to look clickable. */
.idea-row[b-lu01owb8gq] {
    cursor: pointer;
}

.idea-row:hover td[b-lu01owb8gq] {
    background: #f1f7f4;
}

.cell-title a[b-lu01owb8gq] {
    font-weight: 700;
    color: var(--edf-ink, #1e1e1e);
    text-decoration: none;
}

.cell-title a:hover[b-lu01owb8gq] {
    color: var(--edf-pink, #e94b93);
    text-decoration: underline;
}

.attach-count[b-lu01owb8gq] {
    margin-left: 0.5rem;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--edf-ink-soft, #5a6b7b);
    white-space: nowrap;
}

.cell-created[b-lu01owb8gq],
.cell-creator[b-lu01owb8gq] {
    font-size: 0.85rem;
    color: var(--edf-ink-soft, #5a6b7b);
    white-space: nowrap;
}

.cell-actions[b-lu01owb8gq] {
    text-align: right;
    white-space: nowrap;
}

/* A description needs more room than a name, so this dialog is wider than the
   student one. Only the override lives here - .dialog-card itself is global,
   in app.css. */
.dialog-card--wide[b-lu01owb8gq] {
    max-width: 34rem;
}

.idea-description[b-lu01owb8gq] {
    resize: vertical;
    min-height: 8rem;
    font-family: inherit;
}

.backup-message[b-lu01owb8gq] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: #2e8a54;
}

.backup-message.is-error[b-lu01owb8gq] {
    color: #e0503d;
}

/* --- attachments staged in the create/edit dialog ---------------------- */
.pending-attachments[b-lu01owb8gq] {
    margin-top: 0.75rem;
}

/* The file input is opened by clicking its own label, which already looks
   like a button. */
.restore-button[b-lu01owb8gq] {
    margin: 0;
    cursor: pointer;
}

.restore-button[b-lu01owb8gq]  input[type="file"] {
    display: none;
}

.pending-list[b-lu01owb8gq] {
    list-style: none;
    margin: 0.6rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.pending-list li[b-lu01owb8gq] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.6rem;
    background: var(--edf-surface-alt, #f9f9f9);
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.45rem;
    font-size: 0.8rem;
}

.pending-name[b-lu01owb8gq] {
    flex: 1;
    min-width: 0;
    font-weight: 700;
    overflow-wrap: anywhere;
}

.pending-size[b-lu01owb8gq] {
    flex-shrink: 0;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
}

.pending-remove[b-lu01owb8gq] {
    flex-shrink: 0;
    width: 1.4rem;
    height: 1.4rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #fde7e4;
    color: var(--edf-pink-dark, #d13a80);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.pending-remove:hover[b-lu01owb8gq] {
    background: var(--edf-pink-dark, #d13a80);
    color: #fff;
}

/* --- average grade ------------------------------------------------------ */
.cell-grade[b-lu01owb8gq] {
    white-space: nowrap;
}

.grade-pill[b-lu01owb8gq] {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 100px;
    background: #e5f4ea;
    font-weight: 800;
    font-size: 0.85rem;
    color: #2e8a54;
}

.grade-votes[b-lu01owb8gq] {
    margin-left: 0.35rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
}

.grade-none[b-lu01owb8gq] {
    color: #9aa7b2;
    font-weight: 700;
}

/* --- the removal confirmation -----------------------------------------
   Reuses the global .dialog-overlay/.dialog-card; only the two paragraphs are
   new. The warning is loud because nothing in the app undoes a removal. */
.confirm-body[b-lu01owb8gq] {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-warning[b-lu01owb8gq] {
    margin: 0 0 1rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.85rem;
    font-weight: 600;
    color: #8c2d22;
}
/* /Components/Pages/Login.razor.rz.scp.css */
.login-card[b-5rjfcu5i1s] {
    width: 100%;
    max-width: 26rem;
    background: #fff;
    border-radius: 24px;
    padding: 2rem 1.75rem 1.5rem;
    box-shadow: 0 14px 0 rgba(19, 122, 114, .12), 0 6px 24px rgba(33, 49, 66, .18);
    text-align: center;
    box-sizing: border-box;
}

.login-logo[b-5rjfcu5i1s] {
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 50%;
    background: #fff;
    object-fit: contain;
    box-shadow: 0 0 0 3px #cde7f5;
}

.login-card h1[b-5rjfcu5i1s] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.6rem;
    margin: 0.85rem 0 0.15rem;
    color: #213142;
}

.login-sub[b-5rjfcu5i1s] {
    color: #5a6b7b;
    font-weight: 600;
    font-size: 0.95rem;
    margin: 0 0 1.25rem;
}

.login-label[b-5rjfcu5i1s] {
    display: block;
    text-align: left;
    font-weight: 800;
    font-size: 0.78rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #5a6b7b;
    margin-bottom: 0.3rem;
}

.login-input[b-5rjfcu5i1s] {
    margin-bottom: 0.85rem;
    border-radius: 12px;
    border: 2px solid #cde7f5;
    padding: 0.6rem 0.8rem;
}

.login-input:focus[b-5rjfcu5i1s] {
    border-color: #e94b93;
}

.login-validation[b-5rjfcu5i1s] {
    display: block;
    text-align: left;
    color: #e0503d;
    font-size: 0.8rem;
    font-weight: 700;
    margin: -0.65rem 0 0.65rem;
}

.login-error[b-5rjfcu5i1s] {
    background: #fde7e4;
    color: #e0503d;
    font-weight: 800;
    font-size: 0.85rem;
    border-radius: 12px;
    padding: 0.6rem 0.8rem;
    margin-bottom: 1rem;
    text-align: left;
}

.login-remember[b-5rjfcu5i1s] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: #5a6b7b;
    margin: 0.15rem 0 1.1rem;
}

.login-submit[b-5rjfcu5i1s] {
    width: 100%;
    font-size: 1.05rem;
}
/* /Components/Pages/Logout.razor.rz.scp.css */
.login-card[b-1unonboghw] {
    width: 100%;
    max-width: 26rem;
    background: #fff;
    border-radius: 24px;
    padding: 2rem 1.75rem 1.5rem;
    box-shadow: 0 14px 0 rgba(19, 122, 114, .12), 0 6px 24px rgba(33, 49, 66, .18);
    text-align: center;
    box-sizing: border-box;
}

.login-logo[b-1unonboghw] {
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 50%;
    background: #fff;
    object-fit: contain;
    box-shadow: 0 0 0 3px #cde7f5;
}

.login-card h1[b-1unonboghw] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.6rem;
    margin: 0.85rem 0 0.15rem;
    color: #213142;
}

.login-sub[b-1unonboghw] {
    color: #5a6b7b;
    font-weight: 600;
    font-size: 0.95rem;
    margin: 0 0 1.25rem;
}

.login-label[b-1unonboghw] {
    display: block;
    text-align: left;
    font-weight: 800;
    font-size: 0.78rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #5a6b7b;
    margin-bottom: 0.3rem;
}

.login-input[b-1unonboghw] {
    margin-bottom: 0.85rem;
    border-radius: 12px;
    border: 2px solid #cde7f5;
    padding: 0.6rem 0.8rem;
}

.login-input:focus[b-1unonboghw] {
    border-color: #e94b93;
}

.login-validation[b-1unonboghw] {
    display: block;
    text-align: left;
    color: #e0503d;
    font-size: 0.8rem;
    font-weight: 700;
    margin: -0.65rem 0 0.65rem;
}

.login-error[b-1unonboghw] {
    background: #fde7e4;
    color: #e0503d;
    font-weight: 800;
    font-size: 0.85rem;
    border-radius: 12px;
    padding: 0.6rem 0.8rem;
    margin-bottom: 1rem;
    text-align: left;
}

.login-remember[b-1unonboghw] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: #5a6b7b;
    margin: 0.15rem 0 1.1rem;
}

.login-submit[b-1unonboghw] {
    width: 100%;
    font-size: 1.05rem;
}

.login-hint[b-1unonboghw] {
    font-size: 0.75rem;
    color: #5a6b7b;
    font-weight: 600;
    margin: 1.1rem 0 0;
    line-height: 1.45;
}
/* /Components/Pages/Math/Addition/AdditionHome.razor.rz.scp.css */
.module-card[b-16rg02fflj] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.module-icon[b-16rg02fflj] {
    font-size: 1.75rem;
    line-height: 1;
    margin-bottom: 0.4rem;
}

.module-card h2[b-16rg02fflj] {
    font-size: 1.25rem;
    margin-bottom: 0.35rem;
}

.module-card p[b-16rg02fflj] {
    font-size: 0.9rem;
    /* Push the button to the bottom so a row of cards lines up regardless of
       how long each subtitle runs in the active language. */
    flex: 1;
}
/* /Components/Pages/Math/Dynamic/DynamicExercisePage.razor.rz.scp.css */
/* --- the route strip ----------------------------------------------------
   Shown above the exercise while the child is working through a route. Two
   jobs: say where they are in the sequence, and carry the only control that
   ends a step early.

   Deliberately quiet. It is orientation, not the task - the exercise below it
   is what the child is meant to be looking at. */
/* 1fr auto 1fr, NOT space-between. With space-between the clock would sit
   wherever the two side items happened to leave it, drifting sideways as a
   route title got longer or the Next button came and went. Equal side columns
   put it in the true middle of the page, which is where an eye that is
   watching a clock expects to find it. */
/* NO BOX OF ITS OWN. The grid only positions; it draws nothing. A single
   bordered strip wrapped all three items in one panel, which read as one
   control - and the clock, boxed inside another box, looked nested rather
   than important. Each item now carries its own outline and sits on the page
   background, which is what separates them. */
.route-strip[b-z90mzr31d2] {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.75rem;

    /* PADDING, not margin: the strip draws no box of its own, so a bottom
       margin has nothing to push against and collapses through its parent.

       THE BOTTOM IS 1.1rem LARGER THAN THE TOP, AND THAT IS NOT A TYPO.
       The exercise panel below sets `margin: -1.1rem ...` (wwwroot/exercise.css)
       so that its blue pulls up flush under the topbar - written before this
       strip existed and still right for every page without one. It eats the
       first 1.1rem of whatever sits above it, so the gap a child actually
       sees here is 2rem - 1.1rem = 0.9rem, matching the top.

       Chosen over changing .mm-page because that margin is correct for the
       pages that have no strip, and they are most of them. */
    padding: 0.9rem 0 2rem;
    font-family: 'Trebuchet MS', sans-serif;
}

/* justify-self: start, so the pill hugs its own text instead of stretching
   across the whole left column. */
.route-strip-left[b-z90mzr31d2] {
    justify-self: start;
    min-width: 0;
    padding: 0.35rem 0.9rem;
    border: 1px solid #cfe6da;
    border-radius: 0.7rem;
    background: #f6faf8;
}

.route-strip-centre[b-z90mzr31d2] {
    justify-self: center;
}

.route-strip-right[b-z90mzr31d2] {
    justify-self: end;
}

.route-strip-name[b-z90mzr31d2] {
    font-weight: 700;
    color: #14664a;
}

.route-strip-position[b-z90mzr31d2] {
    margin-left: 0.4rem;
    font-size: 0.82rem;
    color: #6b7a88;
}

/* The countdown. A child who knows three questions are left works differently
   from one who cannot see the end of the task. */
.route-strip-remaining[b-z90mzr31d2] {
    font-size: 0.85rem;
    font-weight: 600;
    color: #4a5a68;
    white-space: nowrap;
}

/* --- the strip on a phone -----------------------------------------------
   TWO SHORT LINES, NOT A THREE-COLUMN ROW. With 1fr-auto-1fr a phone gave the
   left pill a third of 360px, so "Semfim / Etapa 1 de 1" wrapped over three
   lines and the centred count ran into it. Squeezing all three into one row
   was tried next and failed the other way: the Next button keeps its pill
   size, took half the width, and the count wrapped over four lines while the
   pill overflowed.

   So: pill left and a small button right on the first line, the count
   centred on its own line under them. Each gets the width it needs, and the
   strip is two short lines instead of ~120px off an exercise that has to fit
   one screen (invariant 12). The true-centre argument above is a desktop one.

   The bottom padding is still 1.1rem larger than the top, for the same reason
   as above: the exercise panel's negative top margin eats it. */
@media (max-width: 640.98px) {
    .route-strip[b-z90mzr31d2] {
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "left right"
            "centre centre";
        gap: 0.3rem 0.5rem;
        padding: 0.3rem 0 1.4rem;
        font-size: 0.8rem;
    }

    .route-strip-left[b-z90mzr31d2] {
        grid-area: left;
        display: flex;
        align-items: baseline;
        max-width: 100%;
        padding: 0.2rem 0.6rem;
        white-space: nowrap;
    }

    .route-strip-right[b-z90mzr31d2] {
        grid-area: right;
    }

    /* The global pill button is sized for a desktop toolbar. */
    .route-strip-right .btn[b-z90mzr31d2] {
        padding: 0.2rem 0.7rem;
        font-size: 0.78rem;
        line-height: 1.3;
    }

    .route-strip-name[b-z90mzr31d2] {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .route-strip-position[b-z90mzr31d2] {
        flex: none;
        margin-left: 0.35rem;
        font-size: 0.72rem;
    }

    .route-strip-centre[b-z90mzr31d2] {
        grid-area: centre;
        justify-self: center;
        text-align: center;
    }

    .route-strip-remaining[b-z90mzr31d2] {
        font-size: 0.75rem;
    }

    /* Qualified by the strip so it outranks the base .step-countdown rule
       further down this file. */
    .route-strip .step-countdown[b-z90mzr31d2] {
        min-width: 3.4rem;
        padding: 0 0.5rem;
        font-size: 1.15rem;
    }
}

/* --- the finished-route results ----------------------------------------
   Shown in place of the exercise. The child has just earned this, so it gets
   the middle of the screen rather than a toast that disappears. */
.route-done[b-z90mzr31d2] {
    /* Wider than it was: five columns of numbers beside an exercise title do
       not fit in 32rem without the titles wrapping to two lines each. */
    max-width: 42rem;
    margin: 0 auto;
    text-align: center;
    font-family: 'Trebuchet MS', sans-serif;
}

.route-done-title[b-z90mzr31d2] {
    margin: 0.2rem 0 1rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.6rem;
    color: #14664a;
}

.route-done-table[b-z90mzr31d2] {
    width: 100%;
    margin-bottom: 1rem;
    border-collapse: collapse;
    font-size: 0.9rem;
    text-align: left;
}

.route-done-table th[b-z90mzr31d2] {
    padding: 0.35rem 0.5rem;
    border-bottom: 2px solid #cfe6da;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 0.82rem;
    color: #14664a;
}

/* The number columns read as numbers, not as prose. Narrow, so the exercise
   title keeps the room it needs - these hold at most three characters. */
.route-done-table th:not(:first-child)[b-z90mzr31d2],
.route-done-table td:not(:first-child)[b-z90mzr31d2] {
    width: 4.2rem;
    text-align: right;
}

/* The percentage is the column being looked for, so it is the one that stands
   out - the raw counts are the working behind it. */
.route-done-table th:last-child[b-z90mzr31d2],
.route-done-table td:last-child[b-z90mzr31d2] {
    font-weight: 700;
    color: #14664a;
}

/* Wrong answers are named, not coloured red. A child reading their own
   results does not need the mistakes shouting at them, and the number is
   already in a column headed "Erradas". */
.route-done-table td:nth-child(4)[b-z90mzr31d2] {
    color: #6b7a88;
}

.route-done-table td[b-z90mzr31d2] {
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid #e9eef2;
    color: #1e1e1e;
}

.route-done-table tfoot td[b-z90mzr31d2] {
    border-bottom: 0;
    border-top: 2px solid #cfe6da;
    font-weight: 700;
}

/* Exam mode only. Deliberately the largest thing here and nothing more -
   no colour scale, no pass line: a percentage in front of a nine-year-old
   does not need help being significant. */
.route-done-mark[b-z90mzr31d2] {
    margin: 0 0 1rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 2.4rem;
    line-height: 1;
    color: #14664a;
}

/* --- the countdown on a timed step -------------------------------------
   Tabular figures so the digits do not shuffle sideways as they change - a
   clock that jiggles once a second is far more distracting than one that
   sits still, and a child is meant to be looking at the maths. */
/* Big enough to read from across a room, in its own box so it reads as an
   instrument rather than as a line of text. Tabular figures so the digits do
   not shuffle sideways as they change - a clock that jiggles once a second is
   far more distracting than one that sits still, and the child is meant to be
   looking at the maths. */
.step-countdown[b-z90mzr31d2] {
    display: inline-block;
    min-width: 4.5rem;
    padding: 0.1rem 0.9rem;
    border: 2px solid #14664a;
    border-radius: 0.6rem;
    background: #fff;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.6rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    line-height: 1.25;
    text-align: center;
    color: #14664a;
}

/* The last ten seconds. Amber rather than red, and no animation: this is a
   practice step running out, not an alarm, and a flashing clock in front of
   a child who is mid-sum is a way to make them lose the sum. */
.step-countdown.is-urgent[b-z90mzr31d2] {
    border-color: #d68910;
    color: #b8761a;
}
/* /Components/Pages/Math/Dynamic/DynamicHome.razor.rz.scp.css */
/* The draft ("in test") controls: one switch above the catalogue, one per
   exercise card. Scoped, so nothing here leaks onto the other hub pages that
   share .module-card. */

.drafts-bar[b-rbpm9h3kbd] {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.7rem 1rem;
}

/* Everything packed on the left, button first; the wider gaps separate the
   groups (button | label + select | switch) the way the narrow one cannot. */
.drafts-bar > .btn[b-rbpm9h3kbd] {
    margin-right: 1rem;
}

.draft-filter-label[b-rbpm9h3kbd] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.8rem;
    color: #4a5560;
    margin: 0;
}

/* Sized to its content rather than the row: a full-width select for three
   short options reads as a form field, and this is a view control. */
.draft-filter[b-rbpm9h3kbd] {
    width: auto;
    min-width: 12rem;
    font-size: 0.85rem;
    margin-right: 1rem;
}

.draft-count[b-rbpm9h3kbd] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.8rem;
    color: #8a6d3b;
}

/* --- the switch itself -------------------------------------------------
   A checkbox with its own track drawn beside it, rather than a styled
   appearance:none input: the checkbox stays a real checkbox, so it keeps its
   keyboard behaviour and its accessible name from the surrounding label. */
.draft-switch[b-rbpm9h3kbd] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.8rem;
    color: #4a5560;
    user-select: none;
}

/* Off-screen rather than display:none, which would take it out of the tab
   order and make the control unreachable by keyboard. */
.draft-switch input[b-rbpm9h3kbd] {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.draft-track[b-rbpm9h3kbd] {
    position: relative;
    display: inline-block;
    width: 2.1rem;
    height: 1.15rem;
    flex-shrink: 0;
    border-radius: 999px;
    background: #cbd5dd;
    transition: background-color .15s ease;
}

.draft-track[b-rbpm9h3kbd]::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: calc(1.15rem - 4px);
    height: calc(1.15rem - 4px);
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    transition: transform .15s ease;
}

/* Checked = "this is a draft", so the ON colour is a warning amber, not the
   usual success green. The switch is not something you want left on. */
.draft-switch input:checked + .draft-track[b-rbpm9h3kbd] {
    background: #e6a817;
}

.draft-switch input:checked + .draft-track[b-rbpm9h3kbd]::after {
    transform: translateX(0.95rem);
}

.draft-switch input:focus-visible + .draft-track[b-rbpm9h3kbd] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

.draft-switch input:disabled + .draft-track[b-rbpm9h3kbd] {
    opacity: 0.5;
    cursor: progress;
}

/* --- the per-card control --------------------------------------------- */
.module-card[b-rbpm9h3kbd] {
    position: relative;
}

/* The card's own controls, top-right: the favourite heart, and for staff the
   draft switch beside it. One positioned box, so the two cannot overlap. */
.card-corner[b-rbpm9h3kbd] {
    position: absolute;
    top: 0.5rem;
    right: 0.6rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.card-draft-switch[b-rbpm9h3kbd] {
    gap: 0.35rem;
    font-size: 0.7rem;
}

/* Hidden until the card is hovered or the switch itself has focus, so a shelf
   of published exercises is not covered in controls nobody is using. A draft
   card keeps its label visible: that one is a status, not just a control. */
.card-draft-switch .draft-label[b-rbpm9h3kbd] {
    opacity: 0;
    transition: opacity .15s ease;
}

.module-card:hover .card-draft-switch .draft-label[b-rbpm9h3kbd],
.card-draft-switch input:focus-visible ~ .draft-label[b-rbpm9h3kbd],
.module-card.is-draft .card-draft-switch .draft-label[b-rbpm9h3kbd] {
    opacity: 1;
}

/* An unmistakable edge on anything a child cannot see yet. */
.module-card.is-draft[b-rbpm9h3kbd] {
    border-color: #e6a817;
    background-image: linear-gradient(180deg, #fffaf0 0%, #fff 40%);
}

/* Which version this card is. Quiet: it matters to whoever is authoring and
   not at all to the child, so it sits beside the title rather than in it. */
.version-tag[b-rbpm9h3kbd] {
    display: inline-block;
    vertical-align: middle;
    margin-left: .4rem;
    padding: .05rem .4rem;
    border-radius: 999px;
    background: #eef3f7;
    color: #4a5560;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: .7rem;
    font-weight: 700;
}

/* --- add a folder -------------------------------------------------------
   Its own bar rather than a control tucked into the drafts row: that row is
   about which exercises are shown, this is about changing what exists, and
   they answer different questions. */
.folder-bar[b-rbpm9h3kbd] {
    padding: 0.7rem 1rem;
}

.folder-form[b-rbpm9h3kbd] {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.folder-label[b-rbpm9h3kbd] {
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.8rem;
    color: #4a5560;
}

/* Sized to what it holds. The name is a phrase, the icon is one emoji, and a
   full-width field for either would read as a form rather than as a control. */
.folder-name[b-rbpm9h3kbd] {
    width: auto;
    min-width: 14rem;
    flex: 1 1 14rem;
    font-size: 0.85rem;
}

.folder-icon[b-rbpm9h3kbd] {
    width: 4.5rem;
    flex: none;
    font-size: 1rem;
    text-align: center;
}

/* Top-right of a folder card, where an exercise card carries its publish
   toggle. Quiet until the card is hovered or it takes focus - a shelf of
   folders should not be a row of bins. */
.card-folder-delete[b-rbpm9h3kbd] {
    position: absolute;
    top: 0.5rem;
    right: 0.6rem;
    padding: 0.1rem 0.35rem;
    border: 0;
    border-radius: 0.4rem;
    background: none;
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity .15s ease, background-color .15s ease;
}

.module-card:hover .card-folder-delete[b-rbpm9h3kbd],
.card-folder-delete:focus-visible[b-rbpm9h3kbd] {
    opacity: 1;
}

.card-folder-delete:hover[b-rbpm9h3kbd] {
    background: #fdecea;
}

.card-folder-delete:focus-visible[b-rbpm9h3kbd] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

/* --- delete confirmation ------------------------------------------------
   Own backdrop and card rather than Bootstrap's modal: only its CSS is loaded
   in this app, so data-bs-toggle would render a dialog that never opens.

   These rules deliberately repeat RouteList.razor.css and
   ExerciseList.razor.css. Scoped CSS stamps a per-component attribute, so a
   shared class cannot cross between them; the class NAMES are kept identical
   so the dialogs stay recognisably the same thing, and so whoever restyles one
   can find the others by grepping for the name. */
.modal-backdrop-own[b-rbpm9h3kbd] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(18, 49, 42, 0.45);
}

.confirm-card[b-rbpm9h3kbd] {
    width: min(30rem, 100%);
    max-height: 90vh;
    overflow-y: auto;
    padding: 1.4rem 1.5rem 1.2rem;
    border-radius: 1rem;
    background: #fff;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
    font-family: 'Trebuchet MS', sans-serif;
}

.confirm-card h2[b-rbpm9h3kbd] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.25rem;
    color: #1e1e1e;
}

.confirm-body[b-rbpm9h3kbd] {
    margin: 0 0 0.4rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-note[b-rbpm9h3kbd] {
    margin: 0 0 0.6rem;
    font-size: 0.82rem;
    color: #6b7a88;
}

/* The size of the decision, stated loudly. Separated from .confirm-note on
   purpose: that one is the reassurance, and styling the two alike would let
   the reassurance swallow the warning. */
.confirm-warning[b-rbpm9h3kbd] {
    margin: 0 0 0.6rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.88rem;
    font-weight: 600;
    color: #8c2d22;
}

.confirm-actions[b-rbpm9h3kbd] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

/* --- a folder card is its own link --------------------------------------
   The title's anchor is stretched over the whole card, so clicking anywhere on
   it enters the folder and no open button is needed. The link is real, so the
   card keeps every behaviour an anchor has and that an onclick handler would
   have thrown away. */
.module-card.is-folder[b-rbpm9h3kbd] {
    cursor: pointer;
}

.card-stretch-link[b-rbpm9h3kbd] {
    color: inherit;
    text-decoration: none;
}

.card-stretch-link[b-rbpm9h3kbd]::after {
    content: '';
    position: absolute;
    inset: 0;
    /* Below the delete control, above the card. */
    z-index: 1;
    border-radius: inherit;
}

.module-card.is-folder:hover[b-rbpm9h3kbd] {
    border-color: var(--brand, #24b473);
}

.module-card.is-folder:has(.card-stretch-link:focus-visible)[b-rbpm9h3kbd] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

/* Above the stretched link, or the card's own link would swallow the click and
   navigate into the folder instead of offering to delete it. */
.card-folder-delete[b-rbpm9h3kbd] {
    z-index: 2;
}

/* Beside the draft filter, which answers the same kind of question: which of
   these exercises are mine to worry about. */
.exclude-base[b-rbpm9h3kbd] {
    margin: 0;
    font-size: 0.85rem;
}
/* /Components/Pages/Math/Dynamic/ExerciseList.razor.rz.scp.css */
/* The table is wider than a phone and there is no useful way to reflow six
   columns of it, so it scrolls inside its own card rather than making the whole
   page scroll sideways. */
.table-wrap[b-9t3c5werxk] {
    overflow-x: auto;
    padding: 0;
}

/* PHONES: article.content is a viewport-high flex column there (MainLayout),
   so exercises can fill exactly one screen. A flex child shrinks by default,
   and being a scroll container this is the only one allowed to shrink to
   nothing - it got whatever the band and the chips left over, which was one
   row on a Galaxy S20 and none at all on an S8.

   So it does not shrink, and it is capped at the height <main> shows below
   the 3.5rem nav bar: scrolled into view, the table fills the screen and
   scrolls inside itself, which is also what keeps the two sticky header rows
   - and with them the filters - in sight. */
@media (max-width: 640.98px) {
    .table-wrap[b-9t3c5werxk] {
        flex-shrink: 0;
        max-height: calc(100dvh - 3.5rem);
        overflow: auto;
    }
}

.exercise-table[b-9t3c5werxk] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.exercise-table th[b-9t3c5werxk],
.exercise-table td[b-9t3c5werxk] {
    text-align: left;
    padding: 0.6rem 0.9rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.exercise-table thead th[b-9t3c5werxk] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

/* Both header rows stay put while the body scrolls. Two rows means two
   explicit offsets - the second has to know how tall the first is, and a
   sticky row cannot work that out for itself. */
.exercise-table thead tr:first-child th[b-9t3c5werxk] {
    position: sticky;
    top: 0;
    z-index: 2;
}

.exercise-table thead tr.filter-row th[b-9t3c5werxk] {
    position: sticky;
    top: 2.4rem;
    z-index: 2;
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid #e3ecf2;
}

/* Full width of whatever column they are in - which is the point of putting
   them here rather than in a bar above, where every width was a guess. */
.filter-row .form-control[b-9t3c5werxk],
.filter-row .form-select[b-9t3c5werxk] {
    width: 100%;
    min-width: 0;
    font-size: 0.8rem;
    padding: 0.25rem 0.5rem;
    font-weight: 400;
}

/* Button left, count right, one line. */
.list-toolbar[b-9t3c5werxk] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

.list-count[b-9t3c5werxk] {
    margin: 0;
    text-align: right;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.8rem;
    color: #8a6d3b;
}

.empty-row[b-9t3c5werxk] {
    padding: 1.2rem 0.9rem;
    color: #8a97a3;
    font-style: italic;
}

.exercise-table tbody tr:hover[b-9t3c5werxk] {
    background: #fafcfd;
}

/* An in-test row reads the same as an in-test card: amber down the edge. */
.exercise-table tbody tr.is-draft[b-9t3c5werxk] {
    background: #fffaf0;
    box-shadow: inset 3px 0 0 #e6a817;
}

/* Deleted: greyed and struck through, so it is unmistakably not part of the
   working set even when the filter that revealed it is forgotten. Not hidden
   behind an opacity so low it cannot be read - it is here to be restored. */
.exercise-table tbody tr.is-deleted[b-9t3c5werxk] {
    background: #fbfbfc;
    box-shadow: inset 3px 0 0 #c4ccd4;
    color: #8a97a3;
}

.exercise-table tbody tr.is-deleted .row-title[b-9t3c5werxk] {
    color: #8a97a3;
    text-decoration: line-through;
}

.deleted-tag[b-9t3c5werxk] {
    display: inline-block;
    margin-left: 0.35rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #eceff2;
    color: #6b7a88;
    font-size: 0.7rem;
    font-weight: 700;
    vertical-align: middle;
}

.row-title[b-9t3c5werxk] {
    font-weight: 700;
    color: #1e1e1e;
}

/* The id is the file name and the URL segment - needed when someone goes
   looking on disk, noise the rest of the time, hence the quiet treatment. */
.row-id[b-9t3c5werxk] {
    font-family: ui-monospace, Consolas, monospace;
    font-size: 0.72rem;
    color: #8a97a3;
    margin-top: 0.15rem;
}

.kind-tag[b-9t3c5werxk],
.version-tag[b-9t3c5werxk] {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #eef3f7;
    color: #4a5560;
    font-size: 0.7rem;
    font-weight: 700;
}

.version-tag[b-9t3c5werxk] {
    margin-left: 0.35rem;
    vertical-align: middle;
}

.unfiled[b-9t3c5werxk] {
    color: #8a97a3;
    font-style: italic;
}

.row-actions[b-9t3c5werxk] {
    white-space: nowrap;
}

/* The name cell: title, id and tags on the left, the favourite heart right
   after them, centred on the block. */
.name-cell[b-9t3c5werxk] {
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

/* --- the per-row action menu -------------------------------------------- */
.row-menu[b-9t3c5werxk] {
    display: inline-block;
}

/* The default disclosure triangle is replaced by a caret of our own, so the
   trigger reads as a menu button rather than as an expandable paragraph. */
.row-menu-trigger[b-9t3c5werxk] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border: 1px solid #d9e6ee;
    border-radius: 999px;
    background: #fff;
    color: #4a5560;
    font-weight: 700;
    font-size: 0.78rem;
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.row-menu-trigger[b-9t3c5werxk]::-webkit-details-marker {
    display: none;
}

.row-menu-trigger[b-9t3c5werxk]::after {
    content: '▾';
    font-size: 0.7rem;
    color: #8a97a3;
}

.row-menu[open] > .row-menu-trigger[b-9t3c5werxk] {
    border-color: var(--brand, #24b473);
    color: #1e1e1e;
}

.row-menu[open] > .row-menu-trigger[b-9t3c5werxk]::after {
    content: '▴';
}

.row-menu-trigger:hover[b-9t3c5werxk] {
    border-color: var(--brand, #24b473);
}

.row-menu-trigger:focus-visible[b-9t3c5werxk] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

.row-menu-items[b-9t3c5werxk] {
    display: flex;
    flex-direction: column;
    margin-top: 0.35rem;
    border: 1px solid #e3ecf2;
    border-radius: 0.6rem;
    background: #fff;
    overflow: hidden;
}

.row-menu-items a[b-9t3c5werxk],
.row-menu-items button[b-9t3c5werxk] {
    padding: 0.4rem 0.7rem;
    border: 0;
    background: none;
    text-align: left;
    color: #1e1e1e;
    text-decoration: none;
    font: inherit;
    font-weight: 700;
    font-size: 0.8rem;
    cursor: pointer;
}

.row-menu-items > * + *[b-9t3c5werxk] {
    border-top: 1px solid #eef3f7;
}

.row-menu-items a:hover[b-9t3c5werxk],
.row-menu-items button:hover[b-9t3c5werxk] {
    background: #eef7f2;
    color: var(--brand-dark, #1fa568);
}

/* Destructive, so it says so - but only in colour. It is a soft delete and the
   row comes straight back from the same menu, which is not worth a scarier
   treatment than this. */
.row-menu-items .menu-delete[b-9t3c5werxk] {
    color: #e0503d;
}

.row-menu-items .menu-delete:hover[b-9t3c5werxk] {
    background: #fdecea;
    color: #c33f2d;
}

.row-menu-items .menu-restore[b-9t3c5werxk] {
    color: var(--brand-dark, #1fa568);
}

.row-menu-items button:disabled[b-9t3c5werxk] {
    opacity: 0.5;
    cursor: progress;
}

/* A page-level action now, so it is sized to its own text rather than stretched
   to a column's width. */
.reset-btn[b-9t3c5werxk] {
    padding: 0.35rem 0.9rem;
    border: 1px solid #d9e6ee;
    border-radius: 0.4rem;
    background: #fff;
    color: #4a5560;
    font-family: inherit;
    font-weight: 700;
    font-size: 0.78rem;
    white-space: nowrap;
    cursor: pointer;
}

.reset-btn:hover:not(:disabled)[b-9t3c5werxk] {
    border-color: var(--brand, #24b473);
    color: #1e1e1e;
}

.reset-btn:disabled[b-9t3c5werxk] {
    opacity: 0.45;
    cursor: default;
}

.reset-btn:focus-visible[b-9t3c5werxk] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

/* Header button rather than a click handler on the <th>: sorting has to be
   reachable by keyboard, and a button already is. */
.sort-btn[b-9t3c5werxk] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 700;
    color: inherit;
    cursor: pointer;
}

.sort-btn:hover[b-9t3c5werxk] {
    color: #1e1e1e;
}

.sort-arrow[b-9t3c5werxk] {
    font-size: 0.65rem;
    color: #8a97a3;
}

/* --- the draft switch, restated -----------------------------------------
   Defined in DynamicHome's own scoped stylesheet as well. Blazor's CSS
   isolation does not cascade one component's rules into another, so a shared
   control has to be restated rather than referenced - the same reason
   .backup-message appears in four page stylesheets. */
.draft-switch[b-9t3c5werxk] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    font-weight: 700;
    font-size: 0.75rem;
    color: #4a5560;
    user-select: none;
    margin: 0;
}

.draft-switch input[b-9t3c5werxk] {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.draft-track[b-9t3c5werxk] {
    position: relative;
    display: inline-block;
    width: 2.1rem;
    height: 1.15rem;
    flex-shrink: 0;
    border-radius: 999px;
    background: #cbd5dd;
    transition: background-color .15s ease;
}

.draft-track[b-9t3c5werxk]::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: calc(1.15rem - 4px);
    height: calc(1.15rem - 4px);
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    transition: transform .15s ease;
}

.draft-switch input:checked + .draft-track[b-9t3c5werxk] {
    background: #e6a817;
}

.draft-switch input:checked + .draft-track[b-9t3c5werxk]::after {
    transform: translateX(0.95rem);
}

.draft-switch input:focus-visible + .draft-track[b-9t3c5werxk] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

.draft-switch input:disabled + .draft-track[b-9t3c5werxk] {
    opacity: 0.5;
    cursor: progress;
}

/* --- the delete confirmation ------------------------------------------
   Own backdrop and card rather than Bootstrap's modal: only its CSS is loaded
   in this app, so data-bs-toggle would render a dialog that never opens. */
.modal-backdrop-own[b-9t3c5werxk] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(18, 49, 42, 0.45);
}

.confirm-card[b-9t3c5werxk] {
    width: min(28rem, 100%);
    padding: 1.4rem 1.5rem 1.2rem;
    border-radius: 1rem;
    background: #fff;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
    font-family: 'Trebuchet MS', sans-serif;
}

.confirm-card h2[b-9t3c5werxk] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.25rem;
    color: #1e1e1e;
}

.confirm-body[b-9t3c5werxk] {
    margin: 0 0 0.4rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

/* The reassurance, quieter than the warning above it - it is the reason this
   dialog is a speed bump and not a scare. */
.confirm-note[b-9t3c5werxk] {
    margin: 0 0 1.1rem;
    font-size: 0.82rem;
    color: #6b7a88;
}

.confirm-actions[b-9t3c5werxk] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

/* The permanence, and the routes that would break. Louder than .confirm-note,
   which was written to reassure back when this was a soft delete with Restore
   in the same menu - neither of which is true any more. */
.confirm-warning[b-9t3c5werxk] {
    margin: 0 0 0.6rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.85rem;
    font-weight: 600;
    color: #8c2d22;
}

/* --- tags on a row ------------------------------------------------------
   Restated rather than shared with TagChips: Blazor's scoped CSS stamps a
   per-component attribute, so that component's rules cannot reach these. Same
   look on purpose - a tag should read as the same thing in the bar and on the
   row it explains. */
.row-tags[b-9t3c5werxk] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem;
    margin-top: 0.3rem;
}

/* Colour comes from TagPalette as an inline style, the same one the chip in
   the bar above gets - that shared hue is what lets a reader see at a glance
   WHICH chip a row matched. Only the shape is here. */
.row-tag[b-9t3c5werxk] {
    padding: 0.05rem 0.45rem;
    border: 1px solid transparent;
    border-radius: 999px;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.7rem;
    cursor: pointer;
}

.row-tag:hover[b-9t3c5werxk] {
    filter: brightness(0.96);
}

.row-tag.is-on[b-9t3c5werxk] {
    font-weight: 700;
}

.row-tag:focus-visible[b-9t3c5werxk] {
    outline: 2px solid currentColor;
    outline-offset: 1px;
}

/* --- backup and restore --------------------------------------------------
   The same pair of controls as on the roster page, and deliberately the same
   shapes: a teacher who has downloaded one backup should recognise the other.
   Scoped styles are per component, so the rules are repeated rather than
   shared - copying six declarations beats a global class that any page could
   pick up by accident. */
.list-backup-tools[b-9t3c5werxk] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1rem;
}

/* The file input is driven by clicking its own <label>, which already looks
   like a button; showing the native control as well would just be a second,
   uglier one. */
.restore-button[b-9t3c5werxk] {
    margin: 0;
    cursor: pointer;
}

.restore-button[b-9t3c5werxk]  input[type="file"] {
    display: none;
}

.backup-message[b-9t3c5werxk] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: #2e8a54;
}

.backup-message.is-error[b-9t3c5werxk] {
    color: #e0503d;
}

/* Beside the reset button rather than in a column head: it filters the whole
   table, like the reset, and unlike the six controls that each filter one
   column. */
.exclude-base[b-9t3c5werxk] {
    margin: 0 0 0 auto;
    font-size: 0.85rem;
}
/* /Components/Pages/Math/MathHome.razor.rz.scp.css */
.module-card[b-ukgimhhf7j] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.module-icon[b-ukgimhhf7j] {
    font-size: 1.75rem;
    line-height: 1;
    margin-bottom: 0.4rem;
}

.module-card h2[b-ukgimhhf7j] {
    font-size: 1.25rem;
    margin-bottom: 0.35rem;
}

.module-card p[b-ukgimhhf7j] {
    font-size: 0.9rem;
    /* Push the button to the bottom so a row of cards lines up regardless of
       how long each subtitle runs in the active language. */
    flex: 1;
}
/* /Components/Pages/OnlineNowPage.razor.rz.scp.css */
/* Who is online. The table and the status dot restate StudentDetailPage.razor.css
   and Students.razor.css: scoped CSS cannot be shared, so the class names are
   kept identical and the rules copied. */

.muted[b-7ntagwnm55] {
    color: #7d8b97;
}

.nowrap[b-7ntagwnm55] {
    white-space: nowrap;
}

.table-wrap[b-7ntagwnm55] {
    overflow-x: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.detail-table[b-7ntagwnm55] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.9rem;
}

.detail-table th[b-7ntagwnm55],
.detail-table td[b-7ntagwnm55] {
    text-align: left;
    padding: 0.45rem 0.75rem;
    vertical-align: middle;
    border-bottom: 1px solid #eef3f7;
}

.detail-table thead th[b-7ntagwnm55] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.detail-table tbody tr:last-child td[b-7ntagwnm55] {
    border-bottom: 0;
}

.person[b-7ntagwnm55] {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
}

.person-avatar[b-7ntagwnm55] {
    position: relative;
    width: 2.25rem;
    height: 2.25rem;
    flex-shrink: 0;
    border-radius: 50%;
    background: #e8f5ee;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Rounded on the image, not by overflow on the frame: the dot hangs over the
   frame's edge and would be clipped. */
.person-avatar img[b-7ntagwnm55] {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

.person-initials[b-7ntagwnm55] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.85rem;
    color: #1fa568;
}

/* Everyone listed is online, so the dot is always green - it is there so the
   page reads the same way as the student list. */
.status-dot[b-7ntagwnm55] {
    position: absolute;
    right: -0.05rem;
    bottom: -0.05rem;
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    background: #3fae6a;
    box-shadow: 0 0 0 2px #fff;
}
/* /Components/Pages/Routes/AttemptReportPage.razor.rz.scp.css */
/* One finished run, read after the fact. Calmer than the live monitor - there
   is nothing to catch here, only something to understand. */

.report-card[b-4vhxsamn9h] {
    font-family: 'Trebuchet MS', sans-serif;
}

.report-subtitle[b-4vhxsamn9h] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.15rem;
    color: #14664a;
}

.report-headline[b-4vhxsamn9h] {
    margin: 0 0 0.9rem;
}

.report-big[b-4vhxsamn9h] {
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 2rem;
    line-height: 1;
    color: #14664a;
}

.report-caption[b-4vhxsamn9h] {
    margin-left: 0.5rem;
    font-size: 0.88rem;
    color: #6b7a88;
}

.report-table[b-4vhxsamn9h] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

.report-table th[b-4vhxsamn9h] {
    padding: 0.35rem 0.5rem;
    border-bottom: 2px solid #cfe6da;
    text-align: left;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 0.8rem;
    color: #14664a;
}

.report-table td[b-4vhxsamn9h] {
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid #eef3f7;
    color: #1e1e1e;
}

.report-table tfoot td[b-4vhxsamn9h] {
    border-bottom: 0;
    border-top: 2px solid #cfe6da;
    font-weight: 700;
}

/* Numbers right-aligned, so a column can be read down rather than one cell at
   a time. The per-exercise score table has one text column; the wrong-answers
   table has two, and .report-exercise opts the second one back out below. */
.report-table th:not(:first-child)[b-4vhxsamn9h],
.report-table td:not(:first-child)[b-4vhxsamn9h] {
    width: 8rem;
    text-align: right;
}

/* A name, not a number: left-aligned and given room to be read. */
.report-table th.report-exercise[b-4vhxsamn9h],
.report-table td.report-exercise[b-4vhxsamn9h] {
    width: auto;
    text-align: left;
    color: #4a5a68;
}

.row-title[b-4vhxsamn9h] {
    font-weight: 700;
    color: #1e1e1e;
}

.report-pct[b-4vhxsamn9h] {
    font-weight: 700;
}

.report-of[b-4vhxsamn9h] {
    margin-left: 0.3rem;
    font-size: 0.8rem;
    color: #6b7a88;
}

/* What the child actually answered - the diagnostic column. Left as plain
   text rather than coloured red: this is a report being studied, not a
   correction being delivered, and a wall of red is harder to read. */
.report-given[b-4vhxsamn9h] {
    font-variant-numeric: tabular-nums;
    color: #8c2d22;
}

/* Wrong more than once. The row a teacher should look at first, so it is the
   one that stands out - the rest are single slips. */
.report-table tr.is-repeated[b-4vhxsamn9h] {
    background: #fdf6e3;
}

.report-repeated[b-4vhxsamn9h] {
    margin: 0 0 0.6rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #d68910;
    border-radius: 0.35rem;
    background: #fdf6e3;
    font-size: 0.87rem;
    font-weight: 600;
    color: #7a5b00;
}

/* Missed, then got right later. Worth distinguishing from a gap that was
   never closed - one is learning, the other is not. */
.report-recovered[b-4vhxsamn9h] {
    margin-left: 0.3rem;
    cursor: help;
}

.report-note[b-4vhxsamn9h] {
    margin: 0;
    font-size: 0.9rem;
    color: #6b7a88;
}

/* --- sorting and filtering the wrong answers ---------------------------
   Mirrors the exercise list's controls, restated because scoped CSS cannot
   be shared. A header BUTTON rather than a click handler on the <th>:
   sorting has to be reachable by keyboard, and a button already is. */
.sort-btn[b-4vhxsamn9h] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 700;
    color: inherit;
    cursor: pointer;
}

.sort-btn:hover[b-4vhxsamn9h] {
    color: #1e1e1e;
}

.sort-arrow[b-4vhxsamn9h] {
    color: #8a97a3;
}

/* The filter sits IN its column, so it is exactly as wide as what it
   filters and no width has to be guessed. */
.report-table thead tr.filter-row th[b-4vhxsamn9h] {
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid #cfe6da;
}

.report-table thead tr.filter-row .form-select[b-4vhxsamn9h] {
    width: 100%;
    min-width: 0;
    font-size: 0.8rem;
}
/* /Components/Pages/Routes/AttemptTimeline.razor.rz.scp.css */
/* One child's scores at one route, oldest to newest. */

.timeline-card[b-3y4cgvdvx6] {
    margin-bottom: 1rem;
}

.timeline-head[b-3y4cgvdvx6] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.25rem;
}

.timeline-title[b-3y4cgvdvx6] {
    margin: 0;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.05rem;
    color: #14664a;
}

.timeline-tools[b-3y4cgvdvx6] {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.period-select[b-3y4cgvdvx6] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.78rem;
    color: var(--edf-ink, #1e1e1e);
    background: #fff;
    border: 1px solid var(--edf-border, #e3ecf2);
    border-radius: 100px;
    padding: 0.25rem 0.6rem;
    cursor: pointer;
}

.period-select:focus[b-3y4cgvdvx6] {
    outline: 2px solid var(--edf-pink, #e94b93);
    outline-offset: 1px;
}

.timeline-empty[b-3y4cgvdvx6] {
    margin: 1.5rem 0 1rem;
    text-align: center;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
    font-weight: 600;
    color: #6b7a88;
}

.timeline-legend[b-3y4cgvdvx6] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.75rem;
    color: #6b7a88;
}

/* The legend's sample of a hollow dot. */
.legend-dot[b-3y4cgvdvx6] {
    display: inline-block;
    width: 11px;
    height: 11px;
    border: 2px solid #2f9e6f;
    border-radius: 50%;
    background: #fff;
}

/* The whole card's width at a fixed height. The padding is the room for the
   axis labels (left, bottom) and the value and group labels (top). */
.timeline[b-3y4cgvdvx6] {
    container-type: inline-size;
    height: 15rem;
    padding: 2.6rem 1.25rem 1.9rem 3rem;
    font-family: 'Trebuchet MS', sans-serif;
}

.plot[b-3y4cgvdvx6] {
    position: relative;
    height: 100%;
}

.grid[b-3y4cgvdvx6] {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px solid #e3ecf2;
}

.axis[b-3y4cgvdvx6] {
    position: absolute;
    font-size: 11px;
    line-height: 1;
    white-space: nowrap;
    color: #7d8b97;
}

.axis-y[b-3y4cgvdvx6] {
    right: calc(100% + 0.6rem);
    transform: translateY(-50%);
}

.axis-x[b-3y4cgvdvx6] {
    top: calc(100% + 0.8rem);
    transform: translateX(-50%);
}

/* Labels keep their size now rather than shrinking with the chart, so on a
   narrow card the dates in between would collide: first and last only. */
@container (max-width: 34rem) {
    .axis-x:not(.is-edge)[b-3y4cgvdvx6] {
        display: none;
    }
}

.round-line[b-3y4cgvdvx6] {
    position: absolute;
    top: -0.9rem;
    bottom: 0;
    border-left: 1px dashed #c9d6df;
}

.round-label[b-3y4cgvdvx6] {
    position: absolute;
    top: -2.3rem;
    transform: translateX(-50%);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    color: #4a5560;
}

.line-layer[b-3y4cgvdvx6] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
}

.line[b-3y4cgvdvx6] {
    fill: none;
    stroke: #2f9e6f;
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.dot[b-3y4cgvdvx6] {
    position: absolute;
    box-sizing: border-box;
    width: 13px;
    height: 13px;
    padding: 0;
    border: 2.5px solid #2f9e6f;
    border-radius: 50%;
    background: #2f9e6f;
    transform: translate(-50%, -50%);
    cursor: pointer;
}

/* Repeated mistakes: the same colour, emptied out. */
.dot.is-hollow[b-3y4cgvdvx6] {
    background: #fff;
}

.dot.is-on[b-3y4cgvdvx6] {
    width: 16px;
    height: 16px;
    border: 3px solid #14664a;
}

.value[b-3y4cgvdvx6] {
    position: absolute;
    transform: translate(-50%, calc(-100% - 9px));
    font-size: 11px;
    line-height: 1;
    white-space: nowrap;
    color: #4a5560;
}

.value.is-on[b-3y4cgvdvx6] {
    font-weight: 700;
    color: #14664a;
}
/* /Components/Pages/Routes/RouteAttemptsPage.razor.rz.scp.css */
/* Every run at one route.

   MIRRORS ExerciseList.razor.css rule for rule. Scoped CSS cannot be shared
   across components, so the rules are restated - but the class names are kept
   identical so the lists stay one design, and whoever restyles one can find
   the others by grepping for .filter-row, .sort-btn or .empty-row. */

.list-toolbar[b-2ix3awxw9w] {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.9rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

.list-count[b-2ix3awxw9w] {
    margin: 0;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.1rem;
    color: #14664a;
}

.idea-count[b-2ix3awxw9w] {
    margin-left: 0.4rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    font-weight: 400;
    color: #6b7a88;
}

.reset-btn[b-2ix3awxw9w] {
    padding: 0.35rem 0.9rem;
    border: 1px solid #d9e6ee;
    border-radius: 0.4rem;
    background: #fff;
    color: #4a5560;
    font-family: inherit;
    font-weight: 700;
    font-size: 0.78rem;
    white-space: nowrap;
    cursor: pointer;
}

.reset-btn:hover:not(:disabled)[b-2ix3awxw9w] {
    border-color: var(--brand, #24b473);
    color: #1e1e1e;
}

.reset-btn:disabled[b-2ix3awxw9w] {
    opacity: 0.45;
    cursor: default;
}

/* PADDING ZERO IS LOAD-BEARING, not tidiness. .edf-card carries 1.5rem of
   padding, and on a scroll container padding does NOT clip its content: rows
   scroll up through that strip and stay visible there, while a sticky header
   pinned at top:0 sits below it. The result is a row floating above its own
   table header. The table's cells carry their own padding instead. */
.table-wrap[b-2ix3awxw9w] {
    max-height: 70vh;
    overflow: auto;
    padding: 0;
}

/* PHONES: the same fix as ExerciseList.razor.css, which has the reasoning.
   article.content is a viewport-high flex column there, and a scroll container
   is the one child allowed to shrink to nothing - so it does not shrink, and
   it may fill the screen below the 3.5rem nav bar instead of 70vh of it. */
@media (max-width: 640.98px) {
    .table-wrap[b-2ix3awxw9w] {
        flex-shrink: 0;
        max-height: calc(100dvh - 3.5rem);
    }
}

.attempts-table[b-2ix3awxw9w] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.attempts-table th[b-2ix3awxw9w],
.attempts-table td[b-2ix3awxw9w] {
    text-align: left;
    padding: 0.6rem 0.9rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.attempts-table thead th[b-2ix3awxw9w] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

/* Both header rows stay put while the body scrolls. Two rows means two
   explicit offsets - the second has to know how tall the first is, and a
   sticky row cannot work that out for itself. */
.attempts-table thead tr:first-child th[b-2ix3awxw9w] {
    position: sticky;
    top: 0;
    z-index: 2;
}

.attempts-table thead tr.filter-row th[b-2ix3awxw9w] {
    position: sticky;
    top: 2.4rem;
    z-index: 2;
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid #e3ecf2;
}

.attempts-table thead tr.filter-row .form-select[b-2ix3awxw9w] {
    width: 100%;
    min-width: 0;
    font-size: 0.8rem;
}

.attempts-table tbody tr:hover[b-2ix3awxw9w] {
    background: #fbfdfe;
}

/* Header button rather than a click handler on the <th>: sorting has to be
   reachable by keyboard, and a button already is. */
.sort-btn[b-2ix3awxw9w] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 700;
    color: inherit;
    cursor: pointer;
}

.sort-btn:hover[b-2ix3awxw9w] {
    color: #1e1e1e;
}

.sort-arrow[b-2ix3awxw9w] {
    color: #8a97a3;
}

.empty-row[b-2ix3awxw9w] {
    padding: 1.2rem 0.9rem;
    color: #8a97a3;
    font-style: italic;
}

.attempt-pct[b-2ix3awxw9w] {
    font-weight: 700;
    color: #14664a;
}

.attempt-of[b-2ix3awxw9w] {
    margin-left: 0.3rem;
    font-size: 0.8rem;
    color: #6b7a88;
}

/* A count of questions missed more than once. Amber, not red: it is a thing
   to look at, not a failure - and this page is read by the child too. */
.attempt-repeated[b-2ix3awxw9w] {
    display: inline-block;
    min-width: 1.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #fdf1cf;
    font-weight: 700;
    text-align: center;
    color: #7a5b00;
}

.attempts-action[b-2ix3awxw9w] {
    white-space: nowrap;
}

/* --- status pill, mirroring StudentRoutes.razor.css --------------------- */
.route-badge[b-2ix3awxw9w] {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.route-badge.is-todo[b-2ix3awxw9w] {
    background: #e9eef2;
    color: #4a5a68;
}

.route-badge.is-unfinished[b-2ix3awxw9w] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-badge.is-completed[b-2ix3awxw9w] {
    background: #d8f2e3;
    color: #14664a;
}

/* --- delete selected ----------------------------------------------------
   The dialog rules below are RESTATED, not shared. Blazor's scoped CSS stamps
   a per-component attribute, so RouteList's copy of these class names
   cannot reach this component - a fact this project has been caught by
   before. Same names on purpose, so a restyle is greppable. */
.modal-backdrop-own[b-2ix3awxw9w] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(18, 49, 42, 0.45);
}

.confirm-card[b-2ix3awxw9w] {
    width: min(30rem, 100%);
    max-height: 90vh;
    overflow-y: auto;
    padding: 1.4rem 1.5rem 1.2rem;
    border-radius: 1rem;
    background: #fff;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
    font-family: 'Trebuchet MS', sans-serif;
}

.confirm-card h2[b-2ix3awxw9w] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.25rem;
    color: #1e1e1e;
}

.confirm-body[b-2ix3awxw9w] {
    margin: 0 0 0.9rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-actions[b-2ix3awxw9w] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

/* Narrow, and never the column that wraps: a checkbox column that grows
   steals width from the score. */
.attempt-col-pick[b-2ix3awxw9w] {
    width: 1%;
    white-space: nowrap;
    text-align: center;
}

/* Sits under the table, aligned right so it reads as an action ON the list
   rather than a heading above the next thing. */
.attempts-actions[b-2ix3awxw9w] {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.75rem;
}

/* `backup-message` carries only `is-error` globally - see RouteList, where
   the same restatement is needed for the same reason. */
.backup-message.is-success[b-2ix3awxw9w] {
    background: #eef8f2;
    border: 1px solid #bfe3d0;
    border-radius: 0.6rem;
    padding: 0.6rem 0.9rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
    color: #1d6b4b;
}

/* The row whose dot is pointed at in the chart above. */
.attempts-table tbody tr.is-highlighted td[b-2ix3awxw9w] {
    background: #eef8f2;
}
/* /Components/Pages/Routes/RouteDetailPage.razor.rz.scp.css */
/* One route, in full.

   The status pill and version tag restate RouteList.razor.css: scoped CSS
   cannot be shared across components, so the class names are kept identical
   and the rules copied, the same arrangement the attempts page uses. */

.route-status[b-u7ova83jqr] {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    vertical-align: middle;
}

.route-status.is-test[b-u7ova83jqr] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-status.is-live[b-u7ova83jqr] {
    background: #d8f2e3;
    color: #14664a;
}

.version-tag[b-u7ova83jqr] {
    margin-left: 0.35rem;
    padding: 0.05rem 0.35rem;
    border-radius: 999px;
    background: #eef3f7;
    color: #4a5560;
    font-size: 0.7rem;
    font-weight: 700;
    vertical-align: middle;
}

.back-link[b-u7ova83jqr] {
    color: inherit;
    font-size: 0.85rem;
}

/* Label left, value right; one column on a phone. */
.facts[b-u7ova83jqr] {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0.4rem 1.5rem;
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.88rem;
}

.facts dt[b-u7ova83jqr] {
    font-weight: 700;
    color: #4a5560;
}

.facts dd[b-u7ova83jqr] {
    margin: 0;
}

@media (max-width: 540px) {
    .facts[b-u7ova83jqr] {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.1rem;
    }

    .facts dd[b-u7ova83jqr] {
        margin-bottom: 0.5rem;
    }
}

.plain-list[b-u7ova83jqr] {
    list-style: none;
    margin: 0;
    padding: 0;
}

.muted[b-u7ova83jqr] {
    color: #7d8b97;
}

.nowrap[b-u7ova83jqr] {
    white-space: nowrap;
}

/* Scrolls sideways inside its card on a narrow screen rather than making the
   page do it. */
.table-wrap[b-u7ova83jqr] {
    overflow-x: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.detail-table[b-u7ova83jqr] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.detail-table th[b-u7ova83jqr],
.detail-table td[b-u7ova83jqr] {
    text-align: left;
    padding: 0.45rem 0.75rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.detail-table thead th[b-u7ova83jqr] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.detail-table tbody tr:last-child td[b-u7ova83jqr] {
    border-bottom: 0;
}

.col-num[b-u7ova83jqr] {
    width: 1%;
    white-space: nowrap;
    color: #7d8b97;
}

/* --- progress ----------------------------------------------------------
   Badge words and colours as on the student monitor. The word is always there
   as well as the colour: colour alone would exclude a colour-blind teacher. */
.route-badge[b-u7ova83jqr] {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.route-badge.is-todo[b-u7ova83jqr] {
    background: #e9eef2;
    color: #4a5a68;
}

.route-badge.is-unfinished[b-u7ova83jqr] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-badge.is-completed[b-u7ova83jqr] {
    background: #d8f2e3;
    color: #14664a;
}

.progress-track[b-u7ova83jqr] {
    display: inline-block;
    width: 4.5rem;
    height: 0.45rem;
    margin-right: 0.4rem;
    border-radius: 999px;
    background: #e9eef2;
    overflow: hidden;
    vertical-align: middle;
}

.progress-fill[b-u7ova83jqr] {
    display: block;
    height: 100%;
    background: #2f9e6f;
}

/* --- send again ---------------------------------------------------------
   Narrow, never the column that wraps - as on the attempts page. */
.col-pick[b-u7ova83jqr] {
    width: 1%;
    white-space: nowrap;
    text-align: center;
}

/* Right above the ticked boxes it acts on. */
.send-bar[b-u7ova83jqr] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    padding: 0.4rem 0.75rem;
    border-radius: 0.6rem;
    background: #eaf2fb;
    color: #1d4f80;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.send-bar-gap[b-u7ova83jqr] {
    flex: 1;
}

/* Wider than a plain confirmation: it holds two pickers side by side. */
.confirm-card.send-card[b-u7ova83jqr] {
    width: min(40rem, 100%);
}

.send-label[b-u7ova83jqr] {
    margin: 0 0 0.25rem;
    font-size: 0.8rem;
    font-weight: 700;
    color: #4a5560;
}

.send-pickers[b-u7ova83jqr] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0.75rem;
    margin: 0 0 1rem;
}

.send-error[b-u7ova83jqr] {
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    color: #a3261b;
}

.send-names[b-u7ova83jqr] {
    max-height: 12rem;
    overflow-y: auto;
    margin: 0 0 1rem;
    padding-left: 1.2rem;
    font-size: 0.9rem;
}

/* The dialog rules are RESTATED from RouteAttemptsPage.razor.css, not
   shared: scoped CSS stamps a per-component attribute, so another page's
   copy cannot reach this one. Same names on purpose, so a restyle is
   greppable. */
.modal-backdrop-own[b-u7ova83jqr] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(18, 49, 42, 0.45);
}

.confirm-card[b-u7ova83jqr] {
    width: min(30rem, 100%);
    max-height: 90vh;
    overflow-y: auto;
    padding: 1.4rem 1.5rem 1.2rem;
    border-radius: 1rem;
    background: #fff;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
    font-family: 'Trebuchet MS', sans-serif;
}

.confirm-card h2[b-u7ova83jqr] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.25rem;
    color: #1e1e1e;
}

.confirm-body[b-u7ova83jqr] {
    margin: 0 0 0.9rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-actions[b-u7ova83jqr] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}
/* /Components/Pages/Routes/RouteEditorPage.razor.rz.scp.css */
/* The route form, split out of the old RouteBuilder. Its rules moved here
   with it: scoped CSS does not reach across components. */

/* The one-line explanation of what the status MEANS. Teachers should not have
   to learn that "in test" implies "invisible to children" - the row says so. */
.route-row-hint[b-cjfy4w3pnr] {
    margin-top: 0.15rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.78rem;
    color: #6b7a88;
}

/* --- the four numbered steps ---------------------------------------------
   The step itself is RouteSection, with its own stylesheet. "Próximo" sits
   bottom right of each open step, where the eye ends up after filling it. */
.route-section-next[b-cjfy4w3pnr] {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.8rem;
}

/* --- per-step goals ------------------------------------------------------
   The goal controls sit UNDER the step title rather than beside it: on a
   narrow screen a title, three buttons, a select, a number and a checkbox on
   one line wraps into something unreadable, and the goal is read as often as
   the title while building a route. */
.route-step-main[b-cjfy4w3pnr] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
}

.route-step-goal[b-cjfy4w3pnr] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.8rem;
    margin: 0.3rem 0 0.6rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    color: #4a5a68;
}

.route-step-goal label[b-cjfy4w3pnr] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
}

.route-step-goal select[b-cjfy4w3pnr] {
    width: auto;
    min-width: 11rem;
}

/* Wide enough for two digits and the spinner, no wider - a number box sized
   like a text field invites a sentence. */
.route-goal-amount[b-cjfy4w3pnr] {
    width: 4.5rem;
}

/* The one goal field still waiting for the teacher: amber, like the other
   "still to do" warnings on this form, and a soft pulse so it is found in a
   list of several steps. Only one field per step carries it at a time - the
   kind first, then the amount. */
.needs-input[b-cjfy4w3pnr] {
    border: 2px solid #d68910;
    background-color: #fdf6e3;
    animation: needs-input-pulse-b-cjfy4w3pnr 1.6s ease-in-out infinite;
}

.needs-input:focus[b-cjfy4w3pnr] {
    border-color: #d68910;
    box-shadow: 0 0 0 0.2rem rgba(214, 137, 16, 0.25);
    animation: none;
}

@keyframes needs-input-pulse-b-cjfy4w3pnr {
    0%, 100% { box-shadow: 0 0 0 0 rgba(214, 137, 16, 0.35); }
    50% { box-shadow: 0 0 0 0.25rem rgba(214, 137, 16, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .needs-input[b-cjfy4w3pnr] {
        animation: none;
    }
}

.route-goal-unit[b-cjfy4w3pnr] {
    color: #6b7a88;
}

.route-goal-check[b-cjfy4w3pnr] {
    font-size: 0.8rem;
}

/* --- the assignment pickers --------------------------------------------
   A filter rather than a scrollbar. A roster of thirty is a long row of chips
   and a roster of two hundred is unusable as one; typing three letters of a
   name is how a teacher actually finds a child. */
.route-student-filter[b-cjfy4w3pnr] {
    max-width: 18rem;
}

/* `is-warning` is not defined globally - `backup-message` only carries
   `is-error` - so it is stated here. Amber and not red on purpose: a route
   assigned to nobody is an unfinished thought, not a failure. It is worth
   saying loudly because it is otherwise SILENT: such a route saves fine,
   validates fine, and looks finished while reaching no child at all. */
.backup-message.is-warning[b-cjfy4w3pnr] {
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #d68910;
    border-radius: 0.35rem;
    background: #fdf6e3;
    color: #7a5b00;
}

/* Green, and stated here for the same reason `is-warning` is: `backup-message`
   only carries `is-error` globally, and Blazor's scoped CSS does not inherit
   another component's rules. */
.backup-message.is-success[b-cjfy4w3pnr] {
    background: #eef8f2;
    border-color: #bfe3d0;
    color: #1d6b4b;
}

/* --- the form's own furniture -------------------------------------------
   None of these classes was defined anywhere. .route-chip, .route-steps and
   .route-step-title had no rules at all, and .roster-head / .idea-count exist
   only as SCOPED css on the Ideas and Students pages, so they never reached
   here. Everything on this form that looked deliberate was Bootstrap's
   defaults on a bare <button> and <ol>. */
.roster-head[b-cjfy4w3pnr] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.8rem;
}

.roster-head h2[b-cjfy4w3pnr] {
    margin: 0;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.3rem;
    color: #14664a;
}

.idea-count[b-cjfy4w3pnr] {
    margin-left: 0.4rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    font-weight: 400;
    color: #6b7a88;
}

.form-label[b-cjfy4w3pnr] {
    display: block;
    margin-bottom: 0.3rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 0.9rem;
    font-weight: 700;
    color: #1e1e1e;
}

/* --- the exercise picker ------------------------------------------------
   Nothing here. The picker is its own component now (ExercisePicker) and
   brings its own scoped stylesheet; the row of chips this section used to
   style is gone. Rules left here could not have reached it in any case -
   Blazor's CSS isolation does not cascade into another component, which is a
   trap this project has already fallen into once. */

/* --- the chosen sequence ------------------------------------------------ */
.route-steps[b-cjfy4w3pnr] {
    margin: 0 0 0.6rem;
    padding-left: 1.5rem;
    font-family: 'Trebuchet MS', sans-serif;
}

.route-steps > li[b-cjfy4w3pnr] {
    margin-bottom: 0.5rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px dashed #e4e9ee;
}

.route-steps > li:last-child[b-cjfy4w3pnr] {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: 0;
}

.route-step-title[b-cjfy4w3pnr] {
    font-size: 0.9rem;
    font-weight: 700;
    color: #1e1e1e;
}

/* No gap: each round button already carries invisible tap area around its
   circle, which is the spacing (see .round-btn in app.css). Pulled up and
   right by that margin so the circles line up with the title, not the
   tap area. */
.route-step-actions[b-cjfy4w3pnr] {
    display: inline-flex;
    flex: 0 0 auto;
    margin: -5px -5px 0 0;
}

/* --- the two assignment pickers, side by side ---------------------------
   Classes and children are one decision - who gets this route - so they read
   as a pair rather than as two unrelated fields stacked up.

   align-items: start matters: the two columns fill to different heights as
   tags are added, and stretched columns would drag the shorter dropdown's
   header away from its label. */
.route-assign-row[b-cjfy4w3pnr] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 0 1rem;
}

/* One column below 44rem. Two columns there would leave each too narrow for a
   child's full name, which is the whole point of the option list. */
@media (max-width: 44rem) {
    .route-assign-row[b-cjfy4w3pnr] {
        grid-template-columns: 1fr;
    }
}

/* A step whose exercise is in test or deleted. Loud, because the save will be
   refused and the teacher needs to know WHICH step to fix - an error message
   naming no step is one nobody can act on. */
.route-step-broken[b-cjfy4w3pnr] {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #fdecea;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #8c2d22;
    cursor: help;
}

/* A fieldset only so a whole section can be disabled with one attribute (see
   RouteField in the page). It must not look like one: no border, no padding,
   no minimum width - the default min-width of a fieldset stops its contents
   from shrinking on a narrow screen. */
.route-lockable[b-cjfy4w3pnr] {
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

/* --- step 3: chosen on the left, available on the right ------------------
   Two cards side by side, as in the mock-up (2026-10-09). The chosen list is
   the narrower one: it holds at most twenty exercises and their goals, the
   available list a whole table. */
.route-pick-wrap[b-cjfy4w3pnr] {
    container-type: inline-size;
}

.route-pick[b-cjfy4w3pnr] {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: 1rem;
    align-items: start;
}

/* A once-published route offers no list to choose from. */
.route-pick.is-single[b-cjfy4w3pnr] {
    grid-template-columns: minmax(0, 1fr);
}

/* Stacked, chosen first, when the CARD is narrow - judged by the card and not
   the screen, because an iPad in portrait with the sidebar open is as narrow
   as a phone. */
@container (max-width: 56rem) {
    .route-pick[b-cjfy4w3pnr] {
        grid-template-columns: minmax(0, 1fr);
    }
}

.route-chosen[b-cjfy4w3pnr],
.route-available[b-cjfy4w3pnr] {
    min-width: 0;
    padding: 0.9rem;
    border: 1px solid #2f9e6f;
    border-radius: 0.6rem;
    background: #fff;
}

.route-chosen-title[b-cjfy4w3pnr] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.35rem;
    font-weight: 800;
    color: #14664a;
}

.route-chosen-count[b-cjfy4w3pnr] {
    font-size: 1rem;
    font-weight: 400;
    color: #6b7a88;
}

.route-chosen-empty[b-cjfy4w3pnr] {
    margin: 0;
    padding: 1.2rem 0;
    text-align: center;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
    color: #7d8b97;
}

/* The step still waiting for its goal stands out from the finished ones. */
.route-steps > li.is-pending[b-cjfy4w3pnr] {
    margin-left: -0.5rem;
    padding: 0.4rem 0.5rem 0.5rem;
    border-radius: 0.4rem;
    background: #fdf6e3;
}

.route-step-name[b-cjfy4w3pnr] {
    min-width: 0;
}

.route-step-tags[b-cjfy4w3pnr] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-top: 0.15rem;
}

.route-step-tag[b-cjfy4w3pnr] {
    background: #eef3f7;
    border-radius: 0.6rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.7rem;
    color: #5a6874;
}

/* Says why the list beside it is faded, in the place the teacher is looking. */
.route-available-wait[b-cjfy4w3pnr] {
    margin: 0 0 0.6rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #d68910;
    border-radius: 0.35rem;
    background: #fdf6e3;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    color: #7a5b00;
}

/* --- step 4: the mode as two cards --------------------------------------- */
.route-modes[b-cjfy4w3pnr] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

@media (max-width: 36rem) {
    .route-modes[b-cjfy4w3pnr] {
        grid-template-columns: minmax(0, 1fr);
    }
}

.route-mode-card[b-cjfy4w3pnr] {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin: 0;
    padding: 0.8rem 0.9rem;
    border: 2px solid #e4e9ee;
    border-radius: 0.6rem;
    background: #fff;
    cursor: pointer;
}

.route-mode-card:hover[b-cjfy4w3pnr] {
    border-color: #a9d8c2;
}

.route-mode-card.is-chosen[b-cjfy4w3pnr] {
    border-color: #2f9e6f;
    background: #f2f9f5;
}

/* The radio itself is hidden, so its focus ring is drawn on the card. */
.route-mode-card:focus-within[b-cjfy4w3pnr] {
    outline: 2px solid #2f9e6f;
    outline-offset: 2px;
}

.route-modes:disabled .route-mode-card[b-cjfy4w3pnr] {
    opacity: 0.6;
    cursor: not-allowed;
}

.route-mode-name[b-cjfy4w3pnr] {
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.05rem;
    font-weight: 700;
    color: #14664a;
}

.route-mode-check[b-cjfy4w3pnr] {
    margin-left: 0.35rem;
    color: #2f9e6f;
}

.route-mode-hint[b-cjfy4w3pnr] {
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    color: #4a5a68;
}

/* Why Save is disabled, said where the teacher is looking. Amber like the
   other "still to do" notes on this form: not an error, a next step. */
.route-save-hint[b-cjfy4w3pnr] {
    margin: 0.6rem 0 0;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #d68910;
    background: #fdf6e3;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    color: #7a5b00;
}
/* /Components/Pages/Routes/RouteList.razor.rz.scp.css */
/* --- route status -------------------------------------------------------
   Whether a route is published decides whether any child can see it, which
   makes it the most consequential thing about a row. It reads as a pill beside
   the title rather than as a word in a menu, so a teacher scanning the list
   can tell at a glance which of their routes are actually live. */
.route-status[b-6dkyrldh3o] {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    vertical-align: middle;
}

/* Amber, not red: a draft is the normal state of a new route, not a fault. */
.route-status.is-test[b-6dkyrldh3o] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-status.is-live[b-6dkyrldh3o] {
    background: #d8f2e3;
    color: #14664a;
}


/* --- the withdraw confirmation -----------------------------------------
   Own backdrop and card rather than Bootstrap's modal: only its CSS is loaded
   in this app, so data-bs-toggle would render a dialog that never opens.

   These rules deliberately repeat ExerciseList.razor.css's delete dialog.
   Scoped CSS stamps a per-component attribute, so a shared class cannot cross
   from there to here; the class NAMES are kept identical so the two dialogs
   stay recognisably the same thing, and so whoever restyles one can find the
   other by grepping for the name. */
.modal-backdrop-own[b-6dkyrldh3o] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(18, 49, 42, 0.45);
}

.confirm-card[b-6dkyrldh3o] {
    width: min(30rem, 100%);
    max-height: 90vh;
    overflow-y: auto;
    padding: 1.4rem 1.5rem 1.2rem;
    border-radius: 1rem;
    background: #fff;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
    font-family: 'Trebuchet MS', sans-serif;
}

/* Wider than a confirmation: two pickers with names in them, side by side
   where there is room. */
.confirm-card.assign-card[b-6dkyrldh3o] {
    width: min(40rem, 100%);
}

.assign-pickers[b-6dkyrldh3o] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0.75rem;
    margin: 0.4rem 0 1rem;
}

.confirm-card h2[b-6dkyrldh3o] {
    margin: 0 0 0.6rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.25rem;
    color: #1e1e1e;
}

.confirm-body[b-6dkyrldh3o] {
    margin: 0 0 0.4rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

/* The quieter half: a child who merely loses their saved place. */
.confirm-note[b-6dkyrldh3o] {
    margin: 0 0 0.6rem;
    font-size: 0.82rem;
    color: #6b7a88;
}

/* The loud half: a child who is on the route RIGHT NOW and will be
   interrupted. Visually separated from .confirm-note on purpose - the whole
   point of splitting the message is that these two are not equally serious,
   and styling them the same would undo that. */
.confirm-warning[b-6dkyrldh3o] {
    margin: 0 0 0.6rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.88rem;
    font-weight: 600;
    color: #8c2d22;
}

/* Who is affected, by name. A count tells a teacher how big the decision is;
   the names are what let them judge whether to make it now or wait five
   minutes. */
.withdraw-students[b-6dkyrldh3o] {
    margin: 0 0 1.1rem;
    padding: 0.4rem 0 0.4rem 1.1rem;
    border-top: 1px solid #e4e9ee;
    font-size: 0.85rem;
    color: #1e1e1e;
}

.withdraw-students li[b-6dkyrldh3o] {
    margin-bottom: 0.2rem;
}

.confirm-actions[b-6dkyrldh3o] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

/* `is-warning` is not defined globally - `backup-message` only carries
   `is-error` - so it is stated here. Amber and not red on purpose: a route
   assigned to nobody is an unfinished thought, not a failure. It is worth
   saying loudly because it is otherwise SILENT: such a route saves fine,
   validates fine, and looks finished while reaching no child at all. */
.backup-message.is-warning[b-6dkyrldh3o] {
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #d68910;
    border-radius: 0.35rem;
    background: #fdf6e3;
    color: #7a5b00;
}

/* Green, and stated here for the same reason `is-warning` is: `backup-message`
   only carries `is-error` globally, and Blazor's scoped CSS does not inherit
   another component's rules. */
.backup-message.is-success[b-6dkyrldh3o] {
    background: #eef8f2;
    border-color: #bfe3d0;
    color: #1d6b4b;
}

.idea-count[b-6dkyrldh3o] {
    margin-left: 0.4rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    font-weight: 400;
    color: #6b7a88;
}

/* --- the row actions menu ----------------------------------------------
   The same pattern as the exercise list's. Restated rather than shared:
   scoped CSS stamps a per-component attribute, so a class cannot cross from
   ExerciseList.razor.css to here. The class NAMES are kept identical so the
   two menus stay recognisably the same control, and so whoever restyles one
   can find the other by grepping for the name.

   Four controls per row read as a toolbar and invite a mis-click; one
   trigger that opens a named list does not - and the destructive item is
   then a word rather than a bin icon sitting beside a pencil. */
.row-menu[b-6dkyrldh3o] {
    display: inline-block;
}

/* The default disclosure triangle is replaced by a caret of our own, so the
   trigger reads as a menu button rather than as an expandable paragraph. */
.row-menu-trigger[b-6dkyrldh3o] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border: 1px solid #d9e6ee;
    border-radius: 999px;
    background: #fff;
    color: #4a5560;
    font-weight: 700;
    font-size: 0.78rem;
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.row-menu-trigger[b-6dkyrldh3o]::-webkit-details-marker {
    display: none;
}

.row-menu-trigger[b-6dkyrldh3o]::after {
    content: '▾';
    font-size: 0.7rem;
    color: #8a97a3;
}

.row-menu[open] > .row-menu-trigger[b-6dkyrldh3o] {
    border-color: var(--brand, #24b473);
    color: #1e1e1e;
}

.row-menu[open] > .row-menu-trigger[b-6dkyrldh3o]::after {
    content: '▴';
}

.row-menu-trigger:hover[b-6dkyrldh3o] {
    border-color: var(--brand, #24b473);
}

.row-menu-trigger:focus-visible[b-6dkyrldh3o] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

.row-menu-items[b-6dkyrldh3o] {
    display: flex;
    flex-direction: column;
    min-width: 10rem;
    margin-top: 0.35rem;
    border: 1px solid #e3ecf2;
    border-radius: 0.6rem;
    background: #fff;
    overflow: hidden;
}

.row-menu-items a[b-6dkyrldh3o],
.row-menu-items button[b-6dkyrldh3o] {
    padding: 0.4rem 0.7rem;
    border: 0;
    background: none;
    text-align: left;
    color: #1e1e1e;
    text-decoration: none;
    font: inherit;
    font-weight: 700;
    font-size: 0.8rem;
    cursor: pointer;
}

.row-menu-items > * + *[b-6dkyrldh3o] {
    border-top: 1px solid #eef3f7;
}

.row-menu-items a:hover[b-6dkyrldh3o],
.row-menu-items button:hover[b-6dkyrldh3o] {
    background: #eef7f2;
    color: var(--brand-dark, #1fa568);
}

/* Publishing is the one action here that puts a route in front of children,
   so it reads as the affirmative one. */
.row-menu-items .menu-publish[b-6dkyrldh3o] {
    color: var(--brand-dark, #1fa568);
}

/* Destructive, so it says so - but only in colour. Unlike the exercise
   list's, THIS delete is permanent: RemoveAsync drops the route and its
   attempts, with no restore to bring it back. */
.row-menu-items .menu-delete[b-6dkyrldh3o] {
    color: #e0503d;
}

.row-menu-items .menu-delete:hover[b-6dkyrldh3o] {
    background: #fdecea;
    color: #c33f2d;
}


/* --- the routes table ---------------------------------------------------
   MIRRORS ExerciseList.razor.css's .exercise-table, rule for rule. Scoped CSS
   stamps a per-component attribute, so the rules cannot be shared - but the
   structure and the class names inside are kept identical so the two lists
   stay one design, and so whoever restyles one can find the other by grepping
   for .row-title, .filter-row or .sort-btn. */
/* PADDING ZERO IS LOAD-BEARING, not tidiness. .edf-card carries 1.5rem of
   padding, and on a scroll container padding does NOT clip its content: rows
   scroll up through that strip and stay visible there, while a sticky header
   pinned at top:0 sits below it. The result is a row floating above its own
   table header. The table's cells carry their own padding instead. */
.table-wrap[b-6dkyrldh3o] {
    max-height: 70vh;
    overflow: auto;
    padding: 0;
}

/* PHONES: the same fix as ExerciseList.razor.css, which has the reasoning.
   article.content is a viewport-high flex column there, and a scroll container
   is the one child allowed to shrink to nothing - so it does not shrink, and
   it may fill the screen below the 3.5rem nav bar instead of 70vh of it. */
@media (max-width: 640.98px) {
    .table-wrap[b-6dkyrldh3o] {
        flex-shrink: 0;
        max-height: calc(100dvh - 3.5rem);
    }
}

.route-table[b-6dkyrldh3o] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.route-table th[b-6dkyrldh3o],
.route-table td[b-6dkyrldh3o] {
    text-align: left;
    padding: 0.6rem 0.9rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.route-table thead th[b-6dkyrldh3o] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

/* Both header rows stay put while the body scrolls. Two rows means two
   explicit offsets - the second has to know how tall the first is, and a
   sticky row cannot work that out for itself. */
.route-table thead tr:first-child th[b-6dkyrldh3o] {
    position: sticky;
    top: 0;
    z-index: 2;
}

.route-table thead tr.filter-row th[b-6dkyrldh3o] {
    position: sticky;
    top: 2.4rem;
    z-index: 2;
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid #e3ecf2;
}

/* Full width of whatever column they are in - which is the point of putting
   them here rather than in a bar above, where every width was a guess. */
.route-table thead tr.filter-row .form-control[b-6dkyrldh3o],
.route-table thead tr.filter-row .form-select[b-6dkyrldh3o] {
    width: 100%;
    min-width: 0;
    font-size: 0.8rem;
}

.route-table tbody tr:hover[b-6dkyrldh3o] {
    background: #fbfdfe;
}

/* A draft is the normal state of a new route, so it is tinted rather than
   flagged - the pill in the status column does the saying. */
.route-table tbody tr.is-draft[b-6dkyrldh3o] {
    background: #fffdf5;
}

.row-title[b-6dkyrldh3o] {
    font-weight: 700;
    color: #1e1e1e;
}

.row-link[b-6dkyrldh3o] {
    text-decoration: none;
}

.row-link:hover[b-6dkyrldh3o],
.row-link:focus-visible[b-6dkyrldh3o] {
    text-decoration: underline;
}

.version-tag[b-6dkyrldh3o] {
    margin-left: 0.35rem;
    padding: 0.05rem 0.35rem;
    border-radius: 999px;
    background: #eef3f7;
    font-size: 0.7rem;
    font-weight: 700;
    color: #6b7a88;
}

.sort-btn[b-6dkyrldh3o] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 700;
    color: inherit;
    cursor: pointer;
}

.sort-arrow[b-6dkyrldh3o] {
    color: #8a97a3;
}

.empty-row[b-6dkyrldh3o] {
    padding: 1.2rem 0.9rem;
    color: #8a97a3;
    font-style: italic;
}

/* flex-start, not space-between: the button belongs BESIDE the count, where
   it reads as acting on that number, rather than marooned at the far right of
   a wide table. (The exercise list puts them at opposite ends; this page was
   drawn the other way round.) */
.list-toolbar[b-6dkyrldh3o] {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.9rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

/* Filters left, the button right and vertically centred across them. The
   bottom margin matches the band's mb-4 above (1.5rem), and the count row
   gives up its own, so the button is exactly midway between band and table. */
.route-list-head[b-6dkyrldh3o] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0 1rem;
    margin-bottom: 1.5rem;
}

.route-list-filters[b-6dkyrldh3o] {
    min-width: 0;
}

.route-list-filters .list-toolbar[b-6dkyrldh3o] {
    margin-bottom: 0;
}

/* A phone: the button on its own line above the filters, right-aligned. */
@media (max-width: 36rem) {
    .route-list-head[b-6dkyrldh3o] {
        grid-template-columns: minmax(0, 1fr);
    }

    .route-create-btn[b-6dkyrldh3o] {
        grid-row: 1;
        justify-self: end;
        margin-bottom: 0.75rem;
    }
}

.list-count[b-6dkyrldh3o] {
    margin: 0;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.1rem;
    color: #14664a;
}


/* Mirrors ExerciseList.razor.css's .reset-btn - scoped CSS cannot be shared,
   so the rules are restated and the class name kept identical. */
.reset-btn[b-6dkyrldh3o] {
    padding: 0.35rem 0.9rem;
    border: 1px solid #d9e6ee;
    border-radius: 0.4rem;
    background: #fff;
    color: #4a5560;
    font-family: inherit;
    font-weight: 700;
    font-size: 0.78rem;
    white-space: nowrap;
    cursor: pointer;
}

.reset-btn:hover:not(:disabled)[b-6dkyrldh3o] {
    border-color: var(--brand, #24b473);
    color: #1e1e1e;
}

.reset-btn:disabled[b-6dkyrldh3o] {
    opacity: 0.45;
    cursor: default;
}

.reset-btn:focus-visible[b-6dkyrldh3o] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

/* Loud only while it has something to do. Rows hidden by a filter were being
   missed, so while any filter is on the way out is a filled button; with
   nothing filtered it stays the faded outline above. Page-local on purpose:
   the exercise list's reset button keeps its own look. */
.reset-btn.is-active[b-6dkyrldh3o],
.route-tags[b-6dkyrldh3o]  .tag-clear {
    padding: 0.35rem 0.9rem;
    border: 1px solid var(--edf-pink, #e94b93);
    border-radius: 0.4rem;
    background: var(--edf-pink, #e94b93);
    color: #fff;
    font-family: inherit;
    font-weight: 700;
    font-size: 0.78rem;
    text-decoration: none;
    white-space: nowrap;
}

.reset-btn.is-active[b-6dkyrldh3o]::before,
.route-tags[b-6dkyrldh3o]  .tag-clear::before {
    content: "✕";
    margin-right: 0.35rem;
}

.reset-btn.is-active:hover[b-6dkyrldh3o],
.route-tags[b-6dkyrldh3o]  .tag-clear:hover {
    border-color: #c93277;
    background: #c93277;
    color: #fff;
}

/* A date is one token and must not wrap onto two lines - the column is narrow
   and a broken date reads as two numbers. */
.row-date[b-6dkyrldh3o] {
    white-space: nowrap;
}
/* /Components/Pages/Routes/RouteSection.razor.rz.scp.css */
.route-section[b-dgi6mhvmr6] {
    border: 1px solid #e4e9ee;
    border-radius: 0.6rem;
    margin-bottom: 0.6rem;
    background: #fff;
}

/* The open step stands out from the closed ones around it. */
.route-section.is-open[b-dgi6mhvmr6] {
    border-color: #2f9e6f;
    box-shadow: 0 1px 6px rgba(47, 158, 111, 0.15);
}

.route-section-head[b-dgi6mhvmr6] {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    width: 100%;
    padding: 0.75rem 0.9rem;
    border: 0;
    border-radius: 0.6rem;
    background: transparent;
    text-align: left;
    cursor: pointer;
}

.route-section-head:hover:not(:disabled)[b-dgi6mhvmr6] {
    background: #f5faf7;
}

/* Locked until an earlier step is filled in: faded, and no hand cursor, so
   it does not invite a click that does nothing. */
.route-section-head:disabled[b-dgi6mhvmr6] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Outlined until the step has something in it, then filled - so a glance
   down the left edge shows what is still to do. */
.route-section-num[b-dgi6mhvmr6] {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 2px solid #2f9e6f;
    border-radius: 50%;
    background: #fff;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.05rem;
    font-weight: 700;
    color: #2f9e6f;
}

.route-section-num.is-done[b-dgi6mhvmr6] {
    background: #2f9e6f;
    color: #fff;
}

.route-section-text[b-dgi6mhvmr6] {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.route-section-title[b-dgi6mhvmr6] {
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 2rem;
    color: #14664a;
}

/* A closed step that has not been reached yet is quieter than the rest. */
.route-section:not(.is-open) .route-section-num:not(.is-done) + .route-section-text .route-section-title[b-dgi6mhvmr6] {
    color: #6b7a88;
}

.route-section-count[b-dgi6mhvmr6] {
    margin-left: 0.3rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    font-weight: 400;
    color: #6b7a88;
}

.route-section-check[b-dgi6mhvmr6] {
    margin-left: 0.4rem;
    color: #2f9e6f;
}

.route-section-hint[b-dgi6mhvmr6],
.route-section-summary[b-dgi6mhvmr6] {
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    color: #6b7a88;
}

/* One line: a summary of twelve exercises must not turn a closed step into
   an open-looking one. */
.route-section-summary[b-dgi6mhvmr6] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #33414d;
}

.route-section-arrow[b-dgi6mhvmr6] {
    flex: none;
    line-height: 2rem;
    font-size: 0.9rem;
    color: #6b7a88;
}

.route-section-body[b-dgi6mhvmr6] {
    padding: 0 0.9rem 0.9rem;
}
/* /Components/Pages/Routes/StudentRouteMonitor.razor.rz.scp.css */
/* One child's routes, live, as one row each.

   MIRRORS StudentRoutes.razor.css - the list a child sees of their own routes
   - so a teacher and a child are looking at the same thing in the same shape.
   Scoped CSS cannot be shared across components, so the rules are restated and
   the class names kept identical. */

/* PADDING ZERO IS LOAD-BEARING, not tidiness. .edf-card carries 1.5rem of
   padding, and on a scroll container padding does NOT clip its content: rows
   scroll up through that strip and stay visible there, while a sticky header
   pinned at top:0 sits below it. The result is a row floating above its own
   table header. The table's cells carry their own padding instead. */
.table-wrap[b-8l27opdz1v] {
    max-height: 70vh;
    overflow: auto;
    padding: 0;
}

/* PHONES: the same fix as ExerciseList.razor.css, which has the reasoning.
   article.content is a viewport-high flex column there, and a scroll container
   is the one child allowed to shrink to nothing - so it does not shrink, and
   it may fill the screen below the 3.5rem nav bar instead of 70vh of it. */
@media (max-width: 640.98px) {
    .table-wrap[b-8l27opdz1v] {
        flex-shrink: 0;
        max-height: calc(100dvh - 3.5rem);
    }
}

.route-table[b-8l27opdz1v] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.88rem;
}

.route-table th[b-8l27opdz1v] {
    padding: 0.4rem 0.6rem;
    border-bottom: 2px solid #cfe6da;
    text-align: left;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 0.82rem;
    font-weight: 700;
    color: #14664a;
    white-space: nowrap;
}

.route-table td[b-8l27opdz1v] {
    padding: 0.55rem 0.6rem;
    border-bottom: 1px solid #e9eef2;
    vertical-align: top;
}

.route-table tbody tr:last-child td[b-8l27opdz1v] {
    border-bottom: 0;
}

.route-table tbody tr:hover[b-8l27opdz1v] {
    background: #fbfdfe;
}

/* --- status ------------------------------------------------------------
   The word is always there as well as the colour: colour alone would exclude
   a colour-blind teacher, and this is the first column read. */
.route-badge[b-8l27opdz1v] {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.route-badge.is-todo[b-8l27opdz1v] {
    background: #e9eef2;
    color: #4a5a68;
}

.route-badge.is-unfinished[b-8l27opdz1v] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-badge.is-completed[b-8l27opdz1v] {
    background: #d8f2e3;
    color: #14664a;
}

/* The name is the way into this route's history, the same as on the child's
   own list - so the two pages are navigated the same way. */
.route-detail-title[b-8l27opdz1v] {
    font-weight: 700;
    color: #1e1e1e;
}

a.route-detail-title[b-8l27opdz1v] {
    text-decoration: none;
}

a.route-detail-title:hover[b-8l27opdz1v] {
    color: #14664a;
    text-decoration: underline;
}

/* An exam behaves differently from every other route on the list - one
   sitting, no repeats, a mark at the end - so it is flagged in the row. */
.route-tag[b-8l27opdz1v] {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #fdecea;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #8c2d22;
}

/* --- the per-step detail, folded ---------------------------------------- */
.route-detail > summary[b-8l27opdz1v] {
    margin-top: 0.15rem;
    cursor: pointer;
    list-style: none;
    font-size: 0.8rem;
    color: #6b7a88;
}

.route-detail > summary[b-8l27opdz1v]::-webkit-details-marker {
    display: none;
}

/* A caret of our own: the default triangle sits badly under a bold title. */
.route-detail > summary[b-8l27opdz1v]::before {
    content: '▸';
    display: inline-block;
    width: 1em;
    transition: transform 120ms ease-out;
}

.route-detail[open] > summary[b-8l27opdz1v]::before {
    transform: rotate(90deg);
}

.monitor-table[b-8l27opdz1v] {
    width: 100%;
    margin: 0.4rem 0 0;
    border-collapse: collapse;
    font-size: 0.82rem;
}

.monitor-table th[b-8l27opdz1v] {
    padding: 0.25rem 0.4rem;
    border-bottom: 1px solid #cfe6da;
    font-size: 0.74rem;
}

.monitor-table td[b-8l27opdz1v] {
    padding: 0.25rem 0.4rem;
    border-bottom: 1px solid #f2f5f8;
    color: #1e1e1e;
}

.monitor-table th:not(:first-child)[b-8l27opdz1v],
.monitor-table td:not(:first-child)[b-8l27opdz1v] {
    width: 6.5rem;
    text-align: right;
}

.monitor-table tr.is-done td[b-8l27opdz1v] {
    color: #6b7a88;
}

/* Where the child is at this moment - the row a teacher is looking for. */
.monitor-table tr.is-current[b-8l27opdz1v] {
    background: #f2f8f5;
    font-weight: 700;
}

.monitor-now[b-8l27opdz1v] {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #d8f2e3;
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #14664a;
}

.monitor-pct[b-8l27opdz1v] {
    font-weight: 700;
    color: #14664a;
}

/* The raw counts behind the percentage, quieter than it. */
.monitor-of[b-8l27opdz1v] {
    margin-left: 0.3rem;
    font-size: 0.78rem;
    font-weight: 400;
    color: #6b7a88;
}

.monitor-clock[b-8l27opdz1v] {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: #14664a;
}

/* Coverage, which only appears once the route has finished - see
   RouteProgressSummary.PercentAnswered for why it cannot be shown before. */
.monitor-coverage[b-8l27opdz1v] {
    margin: 0.5rem 0 0;
    font-size: 0.8rem;
    color: #4a5a68;
}

/* --- progress ----------------------------------------------------------- */
.objective-progress[b-8l27opdz1v] {
    width: 6rem;
    height: 0.45rem;
    margin-bottom: 0.2rem;
    border-radius: 999px;
    background: #e9eef2;
    overflow: hidden;
}

.objective-bar[b-8l27opdz1v] {
    height: 100%;
    border-radius: 999px;
    background: #2f9e6f;

    /* Eased, so a step completing visibly slides the bar along rather than
       teleporting - a teacher glancing up should catch that it moved. */
    transition: width 300ms ease-out;
}

.objective-count[b-8l27opdz1v] {
    font-size: 0.78rem;
    color: #6b7a88;
}

/* --- what to do next ---------------------------------------------------- */
.route-col-action[b-8l27opdz1v] {
    text-align: right;
    white-space: nowrap;
}

.monitor-actions[b-8l27opdz1v] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.2rem;
    font-size: 0.8rem;
}

/* A button among links, so it is styled to sit with them rather than to
   compete - granting a retake is rare and deliberate, not the main action. */
.monitor-retake[b-8l27opdz1v] {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: #8c2d22;
    text-decoration: underline;
    cursor: pointer;
}

/* A date is one token; a wrapped one reads as two separate numbers. */
.route-col-published[b-8l27opdz1v] {
    white-space: nowrap;
}
/* /Components/Pages/Routes/StudentRoutes.razor.rz.scp.css */
/* The child's routes, as a list.

   NOTE ON WHY THIS FILE EXISTS AT ALL: the component this grew out of used
   .objective-card, .objective-bar and friends, and NONE of those classes was
   ever defined - not in app.css, not in a scoped file. The progress bar was a
   div with no height. Anything that looked deliberate about it came from
   Bootstrap's defaults. */

.route-table[b-s3oitwcumf] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.88rem;
}

.route-table th[b-s3oitwcumf] {
    padding: 0.4rem 0.6rem;
    border-bottom: 2px solid #cfe6da;
    text-align: left;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 0.82rem;
    font-weight: 700;
    color: #14664a;
    white-space: nowrap;
}

/* Sorting is discoverable only if the header looks pressable. */
.route-table th.sortable[b-s3oitwcumf] {
    cursor: pointer;
    user-select: none;
}

.route-table th.sortable:hover[b-s3oitwcumf] {
    background: #f2f8f5;
}

.route-table td[b-s3oitwcumf] {
    padding: 0.55rem 0.6rem;
    border-bottom: 1px solid #e9eef2;
    vertical-align: top;
}

.route-table tbody tr:last-child td[b-s3oitwcumf] {
    border-bottom: 0;
}

/* --- status ------------------------------------------------------------
   Three states, three colours, and the colours carry meaning: amber for work
   left half-done, grey for not begun, green for finished. The WORD is always
   there too - colour alone would exclude a colour-blind child, and this is
   the column the whole list sorts on. */
.route-badge[b-s3oitwcumf] {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.route-badge.is-todo[b-s3oitwcumf] {
    background: #e9eef2;
    color: #4a5a68;
}

.route-badge.is-unfinished[b-s3oitwcumf] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-badge.is-completed[b-s3oitwcumf] {
    background: #d8f2e3;
    color: #14664a;
}

/* --- the name cell, which folds open ------------------------------------ */
.route-detail > summary[b-s3oitwcumf] {
    cursor: pointer;
    list-style: none;
}

/* The default triangle sits badly next to a bold title; a rotating caret of
   our own tracks the open state instead. */
.route-detail > summary[b-s3oitwcumf]::-webkit-details-marker {
    display: none;
}

.route-detail > summary[b-s3oitwcumf]::before {
    content: '▸';
    display: inline-block;
    width: 1em;
    color: #6b7a88;
    transition: transform 120ms ease-out;
}

.route-detail[open] > summary[b-s3oitwcumf]::before {
    transform: rotate(90deg);
}

.route-detail-title[b-s3oitwcumf] {
    font-weight: 700;
    color: #1e1e1e;
}

/* An exam is worth flagging in the row: it behaves differently from every
   other route on the list - one sitting, no repeats, and a mark at the end. */
.route-tag[b-s3oitwcumf] {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #fdecea;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #8c2d22;
}

.route-col-action[b-s3oitwcumf] {
    text-align: right;
    white-space: nowrap;
}

.route-locked[b-s3oitwcumf] {
    font-size: 0.8rem;
    color: #6b7a88;
}

.route-done-tick[b-s3oitwcumf] {
    font-size: 1.1rem;
}

/* --- progress ----------------------------------------------------------- */
.objective-progress[b-s3oitwcumf] {
    width: 6rem;
    height: 0.45rem;
    margin-bottom: 0.2rem;
    border-radius: 999px;
    background: #e9eef2;
    overflow: hidden;
}

.objective-bar[b-s3oitwcumf] {
    height: 100%;
    border-radius: 999px;
    background: #2f9e6f;

    /* Eased so a completed step visibly slides the bar along. The movement is
       the reward, and a bar that jumps has not been noticed. */
    transition: width 280ms ease-out;
}

.objective-count[b-s3oitwcumf] {
    font-size: 0.78rem;
    color: #6b7a88;
}

.route-mark[b-s3oitwcumf] {
    margin-left: 0.3rem;
    color: #14664a;
}

/* --- the folded-out detail --------------------------------------------- */
.objective-steps[b-s3oitwcumf] {
    margin: 0.4rem 0 0;
    padding-left: 1.4rem;
    font-size: 0.85rem;
    color: #1e1e1e;
}

.objective-step[b-s3oitwcumf] {
    margin-bottom: 0.2rem;
}

.objective-step.is-done[b-s3oitwcumf] {
    color: #6b7a88;
    text-decoration: line-through;
}

/* Where the child will land when they press Continue. */
.objective-step.is-next[b-s3oitwcumf] {
    font-weight: 700;
}

.objective-tick[b-s3oitwcumf] {
    margin-right: 0.2rem;
}

/* What the step asks for - "10 perguntas", "5 minutos". Quiet: a reassurance
   about how long this will take, not an instruction. */
.task-goal[b-s3oitwcumf] {
    margin-left: 0.35rem;
    font-size: 0.74rem;
    color: #6b7a88;
}

/* Said before a single-sitting route is started, never after. */
.task-warning[b-s3oitwcumf] {
    margin: 0.4rem 0 0;
    padding: 0.4rem 0.6rem;
    border-left: 3px solid #d68910;
    border-radius: 0.35rem;
    background: #fdf6e3;
    font-size: 0.82rem;
    color: #7a5b00;
}

/* Desktop and tablet show the status in its own column. */
.route-badge-inline[b-s3oitwcumf] {
    display: none;
}

/* THE CARD IS THE CONTAINER, so the compact table below keys on the room the
   TABLE has, not on the screen. A screen-width rule was tried first and missed
   the iPad Mini in portrait: 768px wide, but with the sidebar open the card
   had ~410px, and the table pushed out of it exactly as on a phone.

   Inline-size containment also stops the table from widening the card - and
   with it the page - however wide it gets. overflow-x is the last resort: a
   table that still does not fit scrolls inside its own card rather than
   making the whole page scroll sideways. */
.route-card[b-s3oitwcumf] {
    container-type: inline-size;
    overflow-x: auto;
}

/* The page's own padding is what a phone has least of. */
@media (max-width: 640.98px) {
    .route-card[b-s3oitwcumf] {
        padding: 0.6rem;
    }
}

/* A COMPACT TABLE when the card is narrow. Four columns did not fit, so the
   table pushed out of its card and the whole page scrolled sideways, cutting
   the left edge off.

   The status column goes and its label moves above the route name; padding,
   the progress bar and the buttons shrink. Chosen over turning each row into
   a stacked block, which would have lost the column headings. The cost:
   sorting by status needs a wider card - the list still opens newest first.

   560px is roughly what the four full columns need with a short route name. */
@container (max-width: 560px) {
    /* The status column; its label is shown above the name instead. */
    .route-table th:first-child[b-s3oitwcumf],
    .route-table td:first-child[b-s3oitwcumf] {
        display: none;
    }

    /* display:table puts it on a line of its own, above the name, while it
       stays as narrow as its text. */
    .route-badge-inline[b-s3oitwcumf] {
        display: table;
        margin-bottom: 0.2rem;
    }

    .route-table th[b-s3oitwcumf],
    .route-table td[b-s3oitwcumf] {
        padding-left: 0.35rem;
        padding-right: 0.35rem;
    }

    /* A route named as one long word must wrap rather than widen the table. */
    .route-col-name[b-s3oitwcumf] {
        overflow-wrap: anywhere;
    }

    .objective-progress[b-s3oitwcumf] {
        width: 3.5rem;
    }

    .route-col-action .btn[b-s3oitwcumf] {
        padding: 0.3rem 0.75rem;
        font-size: 0.8rem;
    }
}

/* The route name is a link to its attempts now, not a disclosure trigger. */
a.route-detail-title[b-s3oitwcumf] {
    color: #1e1e1e;
    text-decoration: none;
}

a.route-detail-title:hover[b-s3oitwcumf] {
    color: #14664a;
    text-decoration: underline;
}

/* How many runs there have been - a nudge to the page rather than a list of
   them crammed into the cell. */
.route-history-link[b-s3oitwcumf] {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.78rem;
    color: #6b7a88;
}
/* /Components/Pages/Routes/StudentRoutesPage.razor.rz.scp.css */
/* The eviction notice. Restated here rather than shared: the same rule lives
   on RouteList for the teacher's side, and scoped CSS does not cross
   components. Amber, not red - the child did nothing wrong. */
.backup-message.is-warning[b-5xaqgl5tgk] {
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #d68910;
    border-radius: 0.35rem;
    background: #fdf6e3;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.88rem;
    color: #7a5b00;
}
/* /Components/Pages/StudentDetailPage.razor.rz.scp.css */
/* One child, in one place.

   The status dot and group tag restate Students.razor.css, and the badge and
   progress bar RouteDetailPage.razor.css: scoped CSS cannot be shared across
   components, so the class names are kept identical and the rules copied. */

/* Initials in the round frame the teacher's portrait uses, beside the name. */
.student-title[b-uzt8kh68rt] {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    margin-bottom: 0.75rem;
}

.student-avatar[b-uzt8kh68rt] {
    position: relative;
    width: 5.5rem;
    height: 5.5rem;
    flex-shrink: 0;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Rounded on the image itself, not by overflow on the frame: the status dot
   hangs over the frame's edge and would be clipped. */
.student-avatar img[b-uzt8kh68rt] {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    /* cover, not contain: a face letterboxed inside a circle looks broken. */
    object-fit: cover;
    display: block;
}

.student-initials[b-uzt8kh68rt] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.9rem;
    color: #1fa568;
}

/* Online: a badge on the frame's lower right, ringed in white so it reads
   against both the frame and the green band. */
.status-dot[b-uzt8kh68rt] {
    position: absolute;
    right: 0.2rem;
    bottom: 0.2rem;
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 50%;
    box-shadow: 0 0 0 3px #fff;
    transition: background-color .3s ease;
}

.status-dot.online[b-uzt8kh68rt] {
    background: #3fae6a;
}

.status-dot.offline[b-uzt8kh68rt] {
    background: #e0503d;
}

/* --- "now" in the practice table ----------------------------------------
   The exercise the child is on at this moment: the row tinted, and a badge
   with the same green as the online dot, so the two read as one signal. */
.detail-table tr.is-current td[b-uzt8kh68rt] {
    background: #eef8f2;
}

.now-badge[b-uzt8kh68rt] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: 0.5rem;
    padding: 0.05rem 0.5rem;
    border-radius: 999px;
    background: #d8f2e3;
    color: #14664a;
    font-size: 0.72rem;
    font-weight: 700;
    vertical-align: middle;
}

/* Pulsing, because it is live - a static dot reads as a status that was true
   once. Still for anyone who has asked for less motion. */
.now-dot[b-uzt8kh68rt] {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: #3fae6a;
    animation: now-pulse-b-uzt8kh68rt 1.6s ease-in-out infinite;
}

@keyframes now-pulse-b-uzt8kh68rt {
    0%, 100% { box-shadow: 0 0 0 0 rgba(63, 174, 106, 0.55); }
    50% { box-shadow: 0 0 0 0.3rem rgba(63, 174, 106, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .now-dot[b-uzt8kh68rt] {
        animation: none;
    }
}

.back-link[b-uzt8kh68rt] {
    color: inherit;
    font-size: 0.85rem;
}

.group-tag[b-uzt8kh68rt] {
    display: inline-block;
    margin: 0.1rem 0.25rem 0.1rem 0;
    padding: 0.15rem 0.55rem;
    border-radius: 100px;
    background: #e5f0fa;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--edf-blue, #1270b7);
    white-space: nowrap;
}

/* Label left, value right; one column on a phone. */
.facts[b-uzt8kh68rt] {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0.6rem 2rem;
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 1.05rem;
}

/* The group tags sit in the same rows, so they grow with the text. */
.facts .group-tag[b-uzt8kh68rt] {
    font-size: 0.85rem;
    padding: 0.2rem 0.65rem;
}

.facts dt[b-uzt8kh68rt] {
    font-weight: 700;
    color: #4a5560;
}

.facts dd[b-uzt8kh68rt] {
    margin: 0;
}

@media (max-width: 540px) {
    .facts[b-uzt8kh68rt] {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.1rem;
    }

    .facts dd[b-uzt8kh68rt] {
        margin-bottom: 0.5rem;
    }
}

.section-head[b-uzt8kh68rt] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.muted[b-uzt8kh68rt] {
    color: #7d8b97;
}

.nowrap[b-uzt8kh68rt] {
    white-space: nowrap;
}

.text-correct[b-uzt8kh68rt] {
    color: #14664a;
}

.text-wrong[b-uzt8kh68rt] {
    color: #b3261e;
}

/* Scrolls sideways inside its card on a narrow screen rather than making the
   page do it. */
.table-wrap[b-uzt8kh68rt] {
    overflow-x: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.detail-table[b-uzt8kh68rt] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.detail-table th[b-uzt8kh68rt],
.detail-table td[b-uzt8kh68rt] {
    text-align: left;
    padding: 0.45rem 0.75rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.detail-table thead th[b-uzt8kh68rt] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.detail-table tbody tr:last-child td[b-uzt8kh68rt] {
    border-bottom: 0;
}

.route-badge[b-uzt8kh68rt] {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.route-badge.is-todo[b-uzt8kh68rt] {
    background: #e9eef2;
    color: #4a5a68;
}

.route-badge.is-unfinished[b-uzt8kh68rt] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-badge.is-completed[b-uzt8kh68rt] {
    background: #d8f2e3;
    color: #14664a;
}

/* The route being done right now: the online green and the pulsing dot of
   the "now" badge on the Exercises tab, so both tabs say "now" the same way. */
.route-badge.is-working-now[b-uzt8kh68rt] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: #d8f2e3;
    color: #14664a;
    box-shadow: inset 0 0 0 1px #3fae6a;
}

.progress-track[b-uzt8kh68rt] {
    display: inline-block;
    width: 4.5rem;
    height: 0.45rem;
    margin-right: 0.4rem;
    border-radius: 999px;
    background: #e9eef2;
    overflow: hidden;
    vertical-align: middle;
}

.progress-fill[b-uzt8kh68rt] {
    display: block;
    height: 100%;
    background: #2f9e6f;
}

.student-actions[b-uzt8kh68rt] {
    display: flex;
    gap: 0.5rem;
}

/* Header button rather than a click handler on the <th>: sorting has to be
   reachable by keyboard, and a button already is. */
.sort-btn[b-uzt8kh68rt] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
}

.sort-arrow[b-uzt8kh68rt] {
    font-size: 0.65rem;
    color: #7d8b97;
}

/* --- tabs ------------------------------------------------------------------
   Pills in the site's green, like its buttons: a white bar of underlined words
   under a white header card left the page with no colour between the band and
   the cards. The active tab is solid; the others are tinted, so it is still
   obvious at a glance which ones can be clicked. */
.tabs[b-uzt8kh68rt] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0.4rem;
    border-radius: 999px;
    background: #e8f5ee;
    width: fit-content;
    max-width: 100%;
}

.tab[b-uzt8kh68rt] {
    padding: 0.4rem 1.2rem;
    border-radius: 999px;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1rem;
    font-weight: 700;
    color: #14664a;
    text-decoration: none;
    transition: background-color .15s ease, color .15s ease;
}

.tab:hover[b-uzt8kh68rt] {
    background: #cfeadb;
    color: #0f513a;
}

.tab.is-on[b-uzt8kh68rt] {
    background: var(--edf-green, #24b473);
    color: #fff;
    box-shadow: 0 2px 6px rgba(36, 180, 115, 0.35);
}

.tab:focus-visible[b-uzt8kh68rt] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}
/* /Components/Pages/StudentExerciseAttemptPage.razor.rz.scp.css */
/* One attempt at one exercise. The table rules restate StudentExercisePage.razor.css:
   scoped CSS cannot be shared across components. */

.back-link[b-7896z2dz9k] {
    color: inherit;
    font-size: 0.85rem;
}

.muted[b-7896z2dz9k] {
    color: #7d8b97;
}

.nowrap[b-7896z2dz9k] {
    white-space: nowrap;
}

.table-wrap[b-7896z2dz9k] {
    overflow-x: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.detail-table[b-7896z2dz9k] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.detail-table th[b-7896z2dz9k],
.detail-table td[b-7896z2dz9k] {
    text-align: left;
    padding: 0.45rem 0.75rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.detail-table thead th[b-7896z2dz9k] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.detail-table tbody tr:last-child td[b-7896z2dz9k] {
    border-bottom: 0;
}

.col-num[b-7896z2dz9k] {
    width: 1%;
    white-space: nowrap;
    color: #7d8b97;
}

/* The figures a teacher reads first, side by side; they wrap on a phone. */
.summary[b-7896z2dz9k] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 2rem;
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
}

.summary dt[b-7896z2dz9k] {
    font-size: 0.75rem;
    font-weight: 700;
    color: #6b7a88;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.summary dd[b-7896z2dz9k] {
    margin: 0.1rem 0 0;
    font-size: 1.1rem;
    font-weight: 700;
    color: #1e1e1e;
}

.score[b-7896z2dz9k] {
    color: #14664a;
}

.wrong-only[b-7896z2dz9k] {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
    cursor: pointer;
}

/* A wrong answer is what a teacher came to find, so its row stands out. */
.detail-table tbody tr.is-wrong td[b-7896z2dz9k] {
    background: #fdf3f2;
}

.result[b-7896z2dz9k] {
    font-weight: 700;
}

.result.is-right[b-7896z2dz9k] {
    color: #14664a;
}

.result.is-wrong[b-7896z2dz9k] {
    color: #b3261e;
}

.reask[b-7896z2dz9k] {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #fdf1cf;
    color: #7a5b00;
    font-size: 0.7rem;
    font-weight: 700;
    white-space: nowrap;
}
/* /Components/Pages/StudentExercisePage.razor.rz.scp.css */
/* One child, one exercise. The table rules restate StudentDetailPage.razor.css:
   scoped CSS cannot be shared across components. */

.back-link[b-ijihgae2u9] {
    color: inherit;
    font-size: 0.85rem;
}

.muted[b-ijihgae2u9] {
    color: #7d8b97;
}

.nowrap[b-ijihgae2u9] {
    white-space: nowrap;
}

.table-wrap[b-ijihgae2u9] {
    overflow-x: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.detail-table[b-ijihgae2u9] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.detail-table th[b-ijihgae2u9],
.detail-table td[b-ijihgae2u9] {
    text-align: left;
    padding: 0.45rem 0.75rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.detail-table thead th[b-ijihgae2u9] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.detail-table tbody tr:last-child td[b-ijihgae2u9] {
    border-bottom: 0;
}

.score[b-ijihgae2u9] {
    font-weight: 700;
    color: #14664a;
}

.repeated[b-ijihgae2u9] {
    font-weight: 700;
    color: #b3261e;
}

/* The attempt whose dot is pointed at in the chart above. */
.detail-table tbody tr.is-highlighted td[b-ijihgae2u9] {
    background: #eef8f2;
}

/* A row opens its attempt. */
tr.row-link[b-ijihgae2u9] {
    cursor: pointer;
}

tr.row-link:hover td[b-ijihgae2u9] {
    background: #f4faf7;
}
/* /Components/Pages/StudentGroupDetailPage.razor.rz.scp.css */
/* One class, in one place.

   The facts list, tables, badges and status dot restate
   StudentDetailPage.razor.css: scoped CSS cannot be shared across components,
   so the class names are kept identical and the rules copied. */

.back-link[b-nr8d5s6z56] {
    color: inherit;
    font-size: 0.85rem;
}

.section-head[b-nr8d5s6z56] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.muted[b-nr8d5s6z56] {
    color: #7d8b97;
}

.nowrap[b-nr8d5s6z56] {
    white-space: nowrap;
}

/* Label left, value right; one column on a phone. */
.facts[b-nr8d5s6z56] {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0.6rem 2rem;
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 1.05rem;
}

.facts dt[b-nr8d5s6z56] {
    font-weight: 700;
    color: #4a5560;
}

.facts dd[b-nr8d5s6z56] {
    margin: 0;
}

@media (max-width: 540px) {
    .facts[b-nr8d5s6z56] {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.1rem;
    }

    .facts dd[b-nr8d5s6z56] {
        margin-bottom: 0.5rem;
    }
}

/* --- members: portrait and name, in as many columns as fit ------------- */
.member-list[b-nr8d5s6z56] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
    gap: 0.5rem;
}

/* The card and its remove button side by side; the button sits on the
   card's right edge. */
.member-list li[b-nr8d5s6z56] {
    position: relative;
}

.member-remove[b-nr8d5s6z56] {
    position: absolute;
    top: 50%;
    right: 0.45rem;
    transform: translateY(-50%);
    width: 1.8rem;
    height: 1.8rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: #8a97a3;
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
}

.member-remove:hover[b-nr8d5s6z56] {
    background: #fdecea;
    color: #c33f2d;
}

.member-remove:focus-visible[b-nr8d5s6z56] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

.member-error[b-nr8d5s6z56] {
    margin: 0 0 0.75rem;
    font-weight: 700;
    font-size: 0.85rem;
    color: #e0503d;
}

.member[b-nr8d5s6z56] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    /* Room on the right for the remove button. */
    padding: 0.45rem 2.6rem 0.45rem 0.6rem;
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem;
    background: var(--edf-surface-alt, #f9f9f9);
    color: inherit;
    font-weight: 700;
    text-decoration: none;
}

.member:hover[b-nr8d5s6z56] {
    border-color: var(--brand, #24b473);
}

.member-avatar[b-nr8d5s6z56] {
    position: relative;
    width: 2.5rem;
    height: 2.5rem;
    flex-shrink: 0;
    border-radius: 50%;
    background: #e8f5ee;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Rounded on the image, not by overflow on the frame: the status dot hangs
   over the frame's edge and would be clipped. */
.member-avatar img[b-nr8d5s6z56] {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

.member-initials[b-nr8d5s6z56] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.95rem;
    color: #1fa568;
}

.status-dot[b-nr8d5s6z56] {
    position: absolute;
    right: -0.05rem;
    bottom: -0.05rem;
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 50%;
    box-shadow: 0 0 0 2px #fff;
}

.status-dot.online[b-nr8d5s6z56] {
    background: #3fae6a;
}

.status-dot.offline[b-nr8d5s6z56] {
    background: #e0503d;
}

/* --- results tables ----------------------------------------------------- */

/* Scrolls sideways inside its card on a narrow screen rather than making the
   page do it - the per-student table grows a column per route. */
.table-wrap[b-nr8d5s6z56] {
    overflow-x: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.detail-table[b-nr8d5s6z56] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
}

.detail-table th[b-nr8d5s6z56],
.detail-table td[b-nr8d5s6z56] {
    text-align: left;
    padding: 0.45rem 0.75rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

.detail-table thead th[b-nr8d5s6z56] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.detail-table tbody tr:last-child td[b-nr8d5s6z56] {
    border-bottom: 0;
}

/* The name column stays put while the routes scroll past it. */
.matrix th:first-child[b-nr8d5s6z56],
.matrix td:first-child[b-nr8d5s6z56] {
    position: sticky;
    left: 0;
    background: #fff;
}

.matrix thead th:first-child[b-nr8d5s6z56] {
    background: #f7fafc;
}

.cell-link[b-nr8d5s6z56] {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: inherit;
    text-decoration: none;
}

.cell-link:hover .route-badge[b-nr8d5s6z56] {
    filter: brightness(0.95);
}

.route-badge[b-nr8d5s6z56] {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.route-badge.is-todo[b-nr8d5s6z56] {
    background: #e9eef2;
    color: #4a5a68;
}

.route-badge.is-unfinished[b-nr8d5s6z56] {
    background: #fdf1cf;
    color: #7a5b00;
}

.route-badge.is-completed[b-nr8d5s6z56] {
    background: #d8f2e3;
    color: #14664a;
}

/* --- dialogs: add children, take one out ---------------------------------
   The frame restates StudentGroupEditDialog.razor.css - scoped CSS cannot be
   shared, so the class names are kept identical and the rules copied. */
.dialog-overlay[b-nr8d5s6z56] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-nr8d5s6z56] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-nr8d5s6z56] {
    margin-top: 0;
}

.dialog-actions[b-nr8d5s6z56] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

/* A school's worth of names scrolls inside the dialog, not the page. */
.candidate-list[b-nr8d5s6z56] {
    max-height: 50vh;
    overflow-y: auto;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
    padding: 0.25rem 0.5rem;
}

.candidate[b-nr8d5s6z56] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0;
    font-size: 0.9rem;
    cursor: pointer;
}

.candidate input[b-nr8d5s6z56] {
    width: 1rem;
    height: 1rem;
    cursor: pointer;
}
/* /Components/Pages/StudentGroups.razor.rz.scp.css */
.roster-head[b-t30z647cux] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.roster-head h2[b-t30z647cux] {
    margin: 0;
}

/* Desktop always shows the tools, so there is nothing to unfold. */
.roster-toggle[b-t30z647cux] {
    display: none;
}

/* PHONES AND TABLETS - restated from Students.razor.css, which this page
   mirrors; scoped CSS cannot be shared. The heading becomes a card of its own
   above the list, with the tools behind the arrow. */
@media (max-width: 1024.98px), (hover: none) and (pointer: coarse) {
    .roster-card[b-t30z647cux] {
        padding: 0;
        border: 0;
        background: none;
    }

    .roster-head[b-t30z647cux],
    .group-list[b-t30z647cux] {
        padding: 0.6rem 1rem;
        border: 1px solid var(--edf-border, #f2f2f2);
        border-radius: 0.5rem;
        background: var(--edf-surface, #fff);
    }

    .roster-toggle[b-t30z647cux] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2.25rem;
        height: 2.25rem;
        margin-left: auto;
        padding: 0;
        border: 0;
        background: none;
        color: #8a97a3;
        cursor: pointer;
    }

    .roster-toggle > span[b-t30z647cux] {
        width: 0.7rem;
        height: 0.7rem;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: translateY(-0.2rem) rotate(45deg);
        transition: transform .15s ease;
    }

    .roster-head.is-open .roster-toggle > span[b-t30z647cux] {
        transform: translateY(0.2rem) rotate(-135deg);
    }

    .roster-toggle:focus-visible[b-t30z647cux] {
        outline: 2px solid #1270b7;
        outline-offset: 2px;
        border-radius: 0.4rem;
    }

    /* Qualified by .roster-head so it outranks the plain .roster-tools rule
       further down this file, which would otherwise win on order. */
    .roster-head .roster-tools[b-t30z647cux] {
        display: none;
    }

    .roster-head.is-open .roster-tools[b-t30z647cux] {
        display: flex;
        flex-basis: 100%;
        flex-direction: column;
        align-items: flex-start;
    }
}

.group-count[b-t30z647cux] {
    color: var(--edf-ink, #1e1e1e);
    font-weight: 500;
    font-size: 1rem;
}

.group-list[b-t30z647cux] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.group-list li[b-t30z647cux] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.65rem 1rem;
    background: var(--edf-surface-alt, #f9f9f9);
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem;
}

.group-info[b-t30z647cux] {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.group-name[b-t30z647cux] {
    font-weight: 700;
    color: inherit;
    text-decoration: none;
}

/* The whole row opens the class's page. */
.group-list li.row-link[b-t30z647cux] {
    cursor: pointer;
    transition: border-color .15s ease;
}

.group-list li.row-link:hover[b-t30z647cux] {
    border-color: var(--brand, #24b473);
}

.group-list li.row-link:hover .group-name[b-t30z647cux] {
    text-decoration: underline;
}

.group-meta[b-t30z647cux] {
    color: var(--edf-ink-soft, #5a6b7b);
    font-size: 0.85rem;
    font-weight: 600;
}

.group-actions[b-t30z647cux] {
    display: flex;
    gap: 0.5rem;
    flex-shrink: 0;
}

.btn-edit-group[b-t30z647cux],
.btn-remove-group[b-t30z647cux] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.8rem;
    border: none;
    border-radius: 100px;
    padding: 0.4rem 0.9rem;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.btn-edit-group[b-t30z647cux] {
    color: var(--edf-blue, #1270b7);
    background: #e5f0fa;
}

.btn-edit-group:hover[b-t30z647cux] {
    background: var(--edf-blue, #1270b7);
    color: #fff;
}

.btn-remove-group[b-t30z647cux] {
    color: var(--edf-pink-dark, #d13a80);
    background: #fde7e4;
}

.btn-remove-group:hover[b-t30z647cux] {
    background: var(--edf-pink-dark, #d13a80);
    color: #fff;
}

/* --- Add/edit-group dialog --- */

.dialog-overlay[b-t30z647cux] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-t30z647cux] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-t30z647cux] {
    margin-top: 0;
}

.dialog-card input[b-t30z647cux],
.dialog-card select[b-t30z647cux] {
    width: 100%;
    margin-bottom: 0.5rem;
}

.dialog-actions[b-t30z647cux] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.add-student-error[b-t30z647cux] {
    color: var(--edf-pink-dark, #d13a80);
    font-weight: 700;
    font-size: 0.9rem;
    margin: 0.5rem 0 0;
}

/* --- backup / restore, matching the Alunos page ------------------------ */
.roster-tools[b-t30z647cux] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.restore-button[b-t30z647cux] {
    margin: 0;
    cursor: pointer;
}

.restore-button[b-t30z647cux]  input[type="file"] {
    display: none;
}

.backup-message[b-t30z647cux] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: #2e8a54;
}

.backup-message.is-error[b-t30z647cux] {
    color: #e0503d;
}

/* --- the removal confirmation -----------------------------------------
   Reuses .dialog-overlay/.dialog-card from the add/edit dialog; only the two
   paragraphs are new. The warning is loud because nothing in the app undoes a
   removal. */
.confirm-body[b-t30z647cux] {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-warning[b-t30z647cux] {
    margin: 0 0 1rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.85rem;
    font-weight: 600;
    color: #8c2d22;
}
/* /Components/Pages/StudentPeekPage.razor.rz.scp.css */
/* Where the route strip sits on the child's page, with its padding and for
   its reason (DynamicExercisePage.razor.css): the exercise panel below pulls
   itself up by -1.1rem, so the bottom is 1.1rem larger than the top. PADDING
   on a strip with no box of its own, not margin - a margin would collapse
   through the parent. */
.peek-strip[b-e7toxo0l18] {
    padding: 0.9rem 0 2rem;
}

/* In a colour no child's screen uses, so a teacher can never take this copy
   for their own screen. */
.peek-banner[b-e7toxo0l18] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    padding: 0.45rem 0.9rem;
    border-radius: 0.7rem;
    background: #2d2a6e;
    color: #fff;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.9rem;
}

.peek-eye[b-e7toxo0l18] {
    font-size: 1.1rem;
}

.peek-label[b-e7toxo0l18] {
    opacity: 0.85;
}

.peek-name[b-e7toxo0l18] {
    font-weight: 700;
    color: #fcee1f;
    text-decoration: none;
}

.peek-name:hover[b-e7toxo0l18] {
    text-decoration: underline;
}

.peek-sep[b-e7toxo0l18] {
    opacity: 0.6;
}

.peek-route[b-e7toxo0l18] {
    font-weight: 700;
}

.peek-step[b-e7toxo0l18] {
    font-size: 0.82rem;
    opacity: 0.85;
}

.peek-stop[b-e7toxo0l18] {
    margin-left: auto;
}

.peek-note[b-e7toxo0l18] {
    margin-top: 1.5rem;
}
/* /Components/Pages/Students.razor.rz.scp.css */
.roster-head[b-qirweftoz3] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.roster-head h2[b-qirweftoz3] {
    margin: 0;
}

/* Desktop always shows the tools, so there is nothing to unfold. */
.roster-toggle[b-qirweftoz3] {
    display: none;
}

/* PHONES AND TABLETS - the same media query as the folding green band in
   app.css, so the two fold on the same devices. The heading becomes a card of
   its own, apart from the table, with the tools behind the arrow. The outer
   card is dissolved rather than split in the markup, which would have changed
   desktop as well. */
@media (max-width: 1024.98px), (hover: none) and (pointer: coarse) {
    .roster-card[b-qirweftoz3] {
        padding: 0;
        border: 0;
        background: none;
    }

    .roster-head[b-qirweftoz3],
    .student-table-scroll[b-qirweftoz3] {
        padding: 0.6rem 1rem;
        border: 1px solid var(--edf-border, #f2f2f2);
        border-radius: 0.5rem;
        background: var(--edf-surface, #fff);
    }

    .roster-toggle[b-qirweftoz3] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2.25rem;
        height: 2.25rem;
        margin-left: auto;
        padding: 0;
        border: 0;
        background: none;
        color: #8a97a3;
        cursor: pointer;
    }

    /* Drawn rather than a glyph, like the band's chevron. */
    .roster-toggle > span[b-qirweftoz3] {
        width: 0.7rem;
        height: 0.7rem;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: translateY(-0.2rem) rotate(45deg);
        transition: transform .15s ease;
    }

    .roster-head.is-open .roster-toggle > span[b-qirweftoz3] {
        transform: translateY(0.2rem) rotate(-135deg);
    }

    .roster-toggle:focus-visible[b-qirweftoz3] {
        outline: 2px solid #1270b7;
        outline-offset: 2px;
        border-radius: 0.4rem;
    }

    /* Qualified by .roster-head so it outranks the plain .roster-tools rule
       further down this file, which would otherwise win on order. */
    .roster-head .roster-tools[b-qirweftoz3] {
        display: none;
    }

    /* Stacked on their own line under the heading, as on a phone before. */
    .roster-head.is-open .roster-tools[b-qirweftoz3] {
        display: flex;
        flex-basis: 100%;
        flex-direction: column;
        align-items: flex-start;
    }
}

.student-count[b-qirweftoz3] {
    color: var(--edf-ink, #1e1e1e);
    font-weight: 500;
    font-size: 1rem;
}

/* --- filters, in the table header --------------------------------------- */
.student-filters[b-qirweftoz3] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.presence-filter[b-qirweftoz3] {
    display: inline-flex;
    padding: 3px;
    border-radius: 100px;
    background: var(--edf-surface-alt, #f9f9f9);
}

.presence-option[b-qirweftoz3] {
    min-height: 44px;
    min-width: 44px;
    padding: 0 1rem;
    border: none;
    border-radius: 100px;
    background: transparent;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--edf-ink-soft, #5a6b7b);
    cursor: pointer;
    touch-action: manipulation;
}

.presence-option.is-active[b-qirweftoz3] {
    background: #fff;
    color: var(--edf-ink, #1e1e1e);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

/* Pushed right; "Limpar filtros" stays beside the presence buttons. */
.sort-status[b-qirweftoz3] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    padding-left: 0.9rem;
    border-radius: 100px;
    background: rgba(233, 75, 147, 0.12);
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.85rem;
    color: var(--edf-ink, #1e1e1e);
}

.sort-status strong[b-qirweftoz3] {
    color: var(--edf-pink, #e94b93);
}

.sort-clear[b-qirweftoz3] {
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 100px;
    background: transparent;
    font-size: 1.3rem;
    line-height: 1;
    color: var(--edf-ink-soft, #5a6b7b);
    cursor: pointer;
    touch-action: manipulation;
}

.filter-row td[b-qirweftoz3] {
    padding: 0 1rem 0.35rem;
    vertical-align: top;
}

.filter-select[b-qirweftoz3],
.filter-input[b-qirweftoz3] {
    width: 100%;
    min-width: 8rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--edf-ink, #1e1e1e);
    padding: 0.3rem 0.55rem;
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem;
    background: #fff;
}

.filter-select[b-qirweftoz3] {
    cursor: pointer;
}

.filter-input[b-qirweftoz3]::placeholder {
    font-weight: 500;
    color: #9aa7b2;
}

.filter-select:focus[b-qirweftoz3],
.filter-input:focus[b-qirweftoz3] {
    outline: 2px solid var(--edf-pink, #e94b93);
    outline-offset: 1px;
}

/* --- sortable headings --------------------------------------------------- */
/* 44px tall for a finger; the negative margin keeps the label in line with
   the cells below while the sorted heading wears its pill. */
.column-sort[b-qirweftoz3] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 44px;
    margin-left: -0.6rem;
    padding: 0 0.6rem;
    border-radius: 100px;
    touch-action: manipulation;
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
}

@media (hover: hover) {
    .column-sort:hover[b-qirweftoz3] {
        color: var(--edf-pink, #e94b93);
    }
}

.column-sort.is-sorted[b-qirweftoz3] {
    color: var(--edf-pink, #e94b93);
    background: rgba(233, 75, 147, 0.12);
}

/* Dimmed until the column is the active one, so the affordance is visible
   without four arrows competing for attention. */
.sort-arrow[b-qirweftoz3] {
    flex: none;
    opacity: 0.45;
}

.column-sort.is-sorted .sort-arrow[b-qirweftoz3] {
    opacity: 1;
}

/* "Limpar filtros". Outlined in pink and 44px tall: grey on grey, a teacher
   did not see it was a button. */
.btn-clear-filters[b-qirweftoz3] {
    min-height: 44px;
    margin-left: 0.75rem;
    padding: 0 1.1rem;
    border: 2px solid var(--edf-pink, #e94b93);
    border-radius: 100px;
    background: #fff;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--edf-pink, #e94b93);
    cursor: pointer;
    touch-action: manipulation;
}

@media (hover: hover) {
    .btn-clear-filters:hover[b-qirweftoz3] {
        background: var(--edf-pink, #e94b93);
        color: #fff;
    }
}

/* --- roster table ------------------------------------------------------- */
/* Scrolls on its own rather than pushing the page sideways on a phone. */
.student-table-scroll[b-qirweftoz3] {
    overflow-x: auto;
}

.student-table[b-qirweftoz3] {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0 0.5rem;
}

.student-table th[b-qirweftoz3] {
    padding: 0 1rem 0.15rem;
    text-align: left;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--edf-ink-soft, #5a6b7b);
    white-space: nowrap;
}

.student-table td[b-qirweftoz3] {
    padding: 0.65rem 1rem;
    background: var(--edf-surface-alt, #f9f9f9);
    border-top: 1px solid var(--edf-border, #f2f2f2);
    border-bottom: 1px solid var(--edf-border, #f2f2f2);
    vertical-align: middle;
}

/* Rounded ends on the row, which border-radius cannot do on the <tr> itself
   once the cells carry the background. */
.student-table td:first-child[b-qirweftoz3] {
    border-left: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem 0 0 0.5rem;
}

.student-table td:last-child[b-qirweftoz3] {
    border-right: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0 0.5rem 0.5rem 0;
}

.no-match td[b-qirweftoz3] {
    text-align: center;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
    border-radius: 0.5rem;
    border-left: 1px solid var(--edf-border, #f2f2f2);
    border-right: 1px solid var(--edf-border, #f2f2f2);
}

/* --- group tags --------------------------------------------------------- */
.group-tag[b-qirweftoz3] {
    display: inline-block;
    margin: 0.1rem 0.25rem 0.1rem 0;
    padding: 0.15rem 0.55rem;
    border-radius: 100px;
    background: #e5f0fa;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--edf-blue, #1270b7);
    white-space: nowrap;
}

.student-groups-empty[b-qirweftoz3] {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
}

.student-name[b-qirweftoz3] {
    font-weight: 700;
    display: flex;
    align-items: center;
    min-width: 0;
    white-space: nowrap;
}

/* Online = at least one live Blazor circuit for that student's login. */
.status-dot[b-qirweftoz3] {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    margin-right: 0.55rem;
    flex-shrink: 0;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9);
    /* The dots update on a timer, so ease the colour change rather than
       having rows blink. */
    transition: background-color .3s ease;
}

.status-dot.online[b-qirweftoz3] {
    background: #3fae6a;
}

.status-dot.offline[b-qirweftoz3] {
    background: #e0503d;
}

/* The portrait, copied from Teachers.razor.css (scoped CSS cannot be shared):
   the photo, or initials until there is one. */
.student-avatar[b-qirweftoz3] {
    width: 2.5rem;
    height: 2.5rem;
    flex-shrink: 0;
    margin-right: 0.75rem;
    border-radius: 50%;
    overflow: hidden;
    background: #e8f5ee;
    display: flex;
    align-items: center;
    justify-content: center;
    /* A button now (it changes the photo), drawn exactly as the circle was. */
    padding: 0;
    border: 0;
    cursor: pointer;
}

.student-avatar:hover[b-qirweftoz3] {
    box-shadow: 0 0 0 2px var(--brand, #24b473);
}

.student-avatar:focus-visible[b-qirweftoz3] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}

.student-avatar img[b-qirweftoz3] {
    width: 100%;
    height: 100%;
    /* cover, not contain: a face letterboxed inside a circle looks broken. */
    object-fit: cover;
    display: block;
}

.student-initials[b-qirweftoz3] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.95rem;
    color: #1fa568;
}

/* Live exercise metrics: answered / correct / percentage. */
.student-progress[b-qirweftoz3] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-shrink: 0;
    margin-left: auto;
    margin-right: 1rem;
}

.progress-exercise[b-qirweftoz3] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.78rem;
    color: var(--edf-ink, #1e1e1e);
}

.progress-select[b-qirweftoz3] {
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.75rem;
    color: var(--edf-ink, #1e1e1e);
    background: #fff;
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 100px;
    padding: 0.2rem 0.5rem;
    cursor: pointer;
}

.progress-text[b-qirweftoz3] {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.78rem;
    /* Tabular figures so the numbers do not jitter as they tick up. */
    font-variant-numeric: tabular-nums;
    color: var(--edf-ink-soft, #5a6b7b);
}

.text-correct[b-qirweftoz3] {
    color: #2e8a54;
}

.text-wrong[b-qirweftoz3] {
    color: #e0503d;
}

.text-pct[b-qirweftoz3] {
    font-weight: 800;
    color: var(--edf-blue, #1270b7);
}

/* Peek: a small pill after the count, so it reads as an action on the
   exercise beside it rather than a column of its own. */
.peek-btn[b-qirweftoz3] {
    flex: none;
    padding: 0.1rem 0.55rem;
    border: 1px solid #2d2a6e;
    border-radius: 999px;
    color: #2d2a6e;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.75rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

.peek-btn:hover[b-qirweftoz3] {
    background: #2d2a6e;
    color: #fff;
}

.progress-empty[b-qirweftoz3] {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--edf-ink-soft, #5a6b7b);
}

/* --- backup / restore ------------------------------------------------- */
.roster-tools[b-qirweftoz3] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* The file input is driven by clicking its own <label>, which already looks
   like a button; showing the native control as well would just be a second,
   uglier one. */
.restore-button[b-qirweftoz3] {
    margin: 0;
    cursor: pointer;
}

.restore-button[b-qirweftoz3]  input[type="file"] {
    display: none;
}

.backup-message[b-qirweftoz3] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
    color: #2e8a54;
}

.backup-message.is-error[b-qirweftoz3] {
    color: #e0503d;
}

/* --- the route progress column -----------------------------------------
   BESIDE the activity column, not instead of it: that one says what a child
   is doing right now, this one says how far through their assigned work they
   are. Different questions, different lifetimes. */
.cell-route[b-qirweftoz3] {
    min-width: 9rem;
}

/* --- the route column ---------------------------------------------------
   The name of the route the bar beside it measures. Quiet, like the rest of
   the row; the link goes where the bar's does. */
/* "1 de 3" - one short token that must not break across two lines. */
.cell-route-step[b-qirweftoz3],
.cell-route-score[b-qirweftoz3] {
    white-space: nowrap;
}

.route-name-link[b-qirweftoz3] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: inherit;
    font-weight: 600;
    text-decoration: none;
}

.route-name-link:hover[b-qirweftoz3] {
    text-decoration: underline;
}

/* The whole cell is the target. A teacher scanning a class is aiming at a
   row, not at a 6mm bar. */
.route-progress-link[b-qirweftoz3] {
    display: block;
    text-decoration: none;
    color: inherit;
}

.route-progress-link:hover .route-progress-fill[b-qirweftoz3] {
    background: #1fa568;
}

.route-progress-bar[b-qirweftoz3] {
    display: block;
    height: 0.5rem;
    border-radius: 999px;
    background: #e9eef2;
    overflow: hidden;
}

.route-progress-fill[b-qirweftoz3] {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: #2f9e6f;

    /* Eased, so a step completing visibly slides the bar along rather than
       teleporting - a teacher glancing up should catch that it moved. */
    transition: width 300ms ease-out;
}

.route-progress-label[b-qirweftoz3] {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.76rem;
    color: #4a5560;
}

/* A row opens the child's page. */
tr.row-link[b-qirweftoz3] {
    cursor: pointer;
}

tr.row-link:hover td[b-qirweftoz3] {
    background: #f4faf7;
}

/* A link, but reading as the name it always was until hovered. */
.student-link[b-qirweftoz3] {
    color: inherit;
    text-decoration: none;
}

.student-link:hover[b-qirweftoz3],
.student-link:focus-visible[b-qirweftoz3] {
    text-decoration: underline;
}
/* /Components/Pages/TeacherDetailPage.razor.rz.scp.css */
/* One teacher. These rules restate StudentDetailPage.razor.css, so the two
   pages read as one design: scoped CSS cannot be shared across components. */

/* Portrait beside the name, round like the one in the menu. */
.teacher-title[b-37zno7r6k0] {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    margin-bottom: 0.75rem;
}

.teacher-avatar[b-37zno7r6k0] {
    width: 5.5rem;
    height: 5.5rem;
    flex-shrink: 0;
    border-radius: 50%;
    overflow: hidden;
    background: #fff;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
}

.teacher-avatar img[b-37zno7r6k0] {
    width: 100%;
    height: 100%;
    /* cover, not contain: a face letterboxed inside a circle looks broken. */
    object-fit: cover;
    display: block;
}

.teacher-initials[b-37zno7r6k0] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.9rem;
    color: #1fa568;
}

.back-link[b-37zno7r6k0] {
    color: inherit;
    font-size: 0.85rem;
}

.facts[b-37zno7r6k0] {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0.6rem 2rem;
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 1.05rem;
}

.facts dt[b-37zno7r6k0] {
    font-weight: 700;
    color: #4a5560;
}

.facts dd[b-37zno7r6k0] {
    margin: 0;
}

.section-head[b-37zno7r6k0] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

@media (max-width: 540px) {
    .facts[b-37zno7r6k0] {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.1rem;
    }

    .facts dd[b-37zno7r6k0] {
        margin-bottom: 0.5rem;
    }
}

.profile-actions[b-37zno7r6k0] {
    display: flex;
    gap: 0.5rem;
}

/* --- tabs ------------------------------------------------------------------
   Pills in the site's green, like its buttons: a white bar of underlined words
   under a white header card left the page with no colour between the band and
   the cards. The active tab is solid; the others are tinted, so it is still
   obvious at a glance which ones can be clicked. */
.tabs[b-37zno7r6k0] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0.4rem;
    border-radius: 999px;
    background: #e8f5ee;
    width: fit-content;
    max-width: 100%;
}

.tab[b-37zno7r6k0] {
    padding: 0.4rem 1.2rem;
    border-radius: 999px;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 1rem;
    font-weight: 700;
    color: #14664a;
    text-decoration: none;
    transition: background-color .15s ease, color .15s ease;
}

.tab:hover[b-37zno7r6k0] {
    background: #cfeadb;
    color: #0f513a;
}

.tab.is-on[b-37zno7r6k0] {
    background: var(--edf-green, #24b473);
    color: #fff;
    box-shadow: 0 2px 6px rgba(36, 180, 115, 0.35);
}

.tab:focus-visible[b-37zno7r6k0] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}
/* /Components/Pages/Teachers.razor.rz.scp.css */
.roster-head[b-clzzm1jqaf] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.roster-head h2[b-clzzm1jqaf] {
    margin: 0;
}

/* Desktop always shows the Add button, so there is nothing to unfold. */
.roster-toggle[b-clzzm1jqaf] {
    display: none;
}

/* PHONES AND TABLETS - restated from Students.razor.css, which this page
   mirrors; scoped CSS cannot be shared. The heading becomes a card of its own
   above the list, with the Add button behind the arrow. */
@media (max-width: 1024.98px), (hover: none) and (pointer: coarse) {
    .roster-card[b-clzzm1jqaf] {
        padding: 0;
        border: 0;
        background: none;
    }

    .roster-head[b-clzzm1jqaf],
    .teacher-list[b-clzzm1jqaf] {
        padding: 0.6rem 1rem;
        border: 1px solid var(--edf-border, #f2f2f2);
        border-radius: 0.5rem;
        background: var(--edf-surface, #fff);
    }

    .roster-toggle[b-clzzm1jqaf] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2.25rem;
        height: 2.25rem;
        margin-left: auto;
        padding: 0;
        border: 0;
        background: none;
        color: #8a97a3;
        cursor: pointer;
    }

    .roster-toggle > span[b-clzzm1jqaf] {
        width: 0.7rem;
        height: 0.7rem;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: translateY(-0.2rem) rotate(45deg);
        transition: transform .15s ease;
    }

    .roster-head.is-open .roster-toggle > span[b-clzzm1jqaf] {
        transform: translateY(0.2rem) rotate(-135deg);
    }

    .roster-toggle:focus-visible[b-clzzm1jqaf] {
        outline: 2px solid #1270b7;
        outline-offset: 2px;
        border-radius: 0.4rem;
    }

    .roster-head .roster-tools[b-clzzm1jqaf] {
        display: none;
    }

    .roster-head.is-open .roster-tools[b-clzzm1jqaf] {
        display: flex;
        flex-basis: 100%;
    }
}

.teacher-count[b-clzzm1jqaf] {
    color: var(--edf-ink, #1e1e1e);
    font-weight: 500;
    font-size: 1rem;
}

.teacher-list[b-clzzm1jqaf] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.teacher-list li[b-clzzm1jqaf] {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.85rem;
    padding: 0.65rem 1rem;
    background: var(--edf-surface-alt, #f9f9f9);
    border: 1px solid var(--edf-border, #f2f2f2);
    border-radius: 0.5rem;
}

/* The teacher page's portrait, at row size. */
.teacher-avatar[b-clzzm1jqaf] {
    width: 2.5rem;
    height: 2.5rem;
    flex-shrink: 0;
    border-radius: 50%;
    overflow: hidden;
    background: #e8f5ee;
    display: flex;
    align-items: center;
    justify-content: center;
}

.teacher-avatar img[b-clzzm1jqaf] {
    width: 100%;
    height: 100%;
    /* cover, not contain: a face letterboxed inside a circle looks broken. */
    object-fit: cover;
    display: block;
}

.teacher-initials[b-clzzm1jqaf] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.95rem;
    color: #1fa568;
}

.teacher-name[b-clzzm1jqaf] {
    font-weight: 700;
}

/* A row opens the teacher's page. */
.teacher-list li.row-link[b-clzzm1jqaf] {
    cursor: pointer;
}

.teacher-list li.row-link:hover[b-clzzm1jqaf] {
    background: #f4faf7;
}

/* A link, but reading as the name it always was until hovered. */
.teacher-link[b-clzzm1jqaf] {
    color: inherit;
    text-decoration: none;
}

.teacher-link:hover[b-clzzm1jqaf],
.teacher-link:focus-visible[b-clzzm1jqaf] {
    text-decoration: underline;
}
/* /Components/Pages/Videos/VideosPage.razor.rz.scp.css */
.videos-head[b-j0nefxjqn4] {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 1rem;
}

/* One column on a phone, as many ~20rem cards as fit beyond that. */
.video-grid[b-j0nefxjqn4] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
    gap: 1.25rem;
}

.video-card[b-j0nefxjqn4] {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--edf-border, #e3e3e3);
    border-radius: 0.75rem;
    overflow: hidden;
    background: var(--edf-surface, #fff);
}

.video-frame[b-j0nefxjqn4] {
    aspect-ratio: 16 / 9;
    background: #000;
}

.video-frame iframe[b-j0nefxjqn4] {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

.video-body[b-j0nefxjqn4] {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.9rem 1rem 1rem;
    flex: 1;
}

.video-title[b-j0nefxjqn4] {
    margin: 0;
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.1rem;
    color: var(--edf-green, #24b473);
}

.video-description[b-j0nefxjqn4] {
    margin: 0;
    font-size: 0.9rem;
    white-space: pre-line;
}

/* Pushed to the bottom so the buttons line up across cards of unequal text. */
.video-actions[b-j0nefxjqn4] {
    margin-top: auto;
    padding-top: 0.5rem;
    flex-wrap: wrap;
}

.video-actions button:disabled[b-j0nefxjqn4] {
    opacity: 0.4;
    cursor: default;
}

.backup-message[b-j0nefxjqn4] {
    margin: 0 0 1rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 700;
    font-size: 0.85rem;
}

.backup-message.is-error[b-j0nefxjqn4] {
    color: #e0503d;
}

/* Four languages of title and description need more room than one line. */
.dialog-card--wide[b-j0nefxjqn4] {
    max-width: 36rem;
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
}

.video-hint[b-j0nefxjqn4] {
    margin: 0.25rem 0 0.75rem;
    font-size: 0.85rem;
    color: var(--edf-body, #555);
}

.video-language[b-j0nefxjqn4] {
    margin: 0 0 0.75rem;
}

.video-language legend[b-j0nefxjqn4] {
    font-size: 0.9rem;
    font-weight: 700;
    margin-bottom: 0.35rem;
}

.video-required[b-j0nefxjqn4] {
    color: var(--edf-pink-dark, #d13a80);
}

.video-description-input[b-j0nefxjqn4] {
    resize: vertical;
    font-family: inherit;
}

.confirm-body[b-j0nefxjqn4] {
    margin: 0 0 1rem;
    font-size: 0.9rem;
}
/* /Components/Shared/ExercisePicker.razor.rz.scp.css */
/* Chips above, table below, full width - the folder tree that sat beside them
   is gone. min-width: 0 is what stops a wide table from pushing the card
   wider than the page. */
.picker[b-nbnjr1oh75] {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

/* Switched off until the route's newest exercise has a goal: faded, so it
   reads as "not yet" rather than as broken. */
.picker.is-disabled[b-nbnjr1oh75] {
    opacity: 0.45;
    pointer-events: none;
}

.picker-results[b-nbnjr1oh75] {
    min-width: 0;
}

/* --- filters ---------------------------------------------------------- */

/* Full width of whatever column they are in - which is the point of putting
   them in the table rather than in a bar above, where every width was a guess. */
.picker-table .filter-row .form-control[b-nbnjr1oh75],
.picker-table .filter-row .form-select[b-nbnjr1oh75] {
    width: 100%;
    min-width: 0;
    font-size: 0.8rem;
    padding: 0.25rem 0.5rem;
    font-weight: 400;
}

.picker-table thead tr.filter-row th[b-nbnjr1oh75] {
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid #e3ecf2;
}

/* Button left, count right, one line - as on /math/dynamic/exercises. */
.picker-toolbar[b-nbnjr1oh75] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.btn-clear[b-nbnjr1oh75] {
    background: #fff;
    border: 1px solid #d3dee6;
    border-radius: 0.4rem;
    padding: 0.25rem 0.7rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    color: #4a5560;
    cursor: pointer;
}

.btn-clear:hover:not(:disabled)[b-nbnjr1oh75] {
    background: #f2f7fa;
}

.btn-clear:disabled[b-nbnjr1oh75] {
    opacity: 0.45;
    cursor: default;
}

/* --- the table -------------------------------------------------------- */

/* Scrolls inside its own box rather than making the page scroll sideways.
   PADDING ZERO IS LOAD-BEARING: padding on a scroll container does not clip,
   so rows scroll up through it and appear ABOVE the sticky header. That has
   already been fixed once on the attempts page.

   A FIXED HEIGHT, not a maximum: with max-height the box shrank to two rows
   when a filter left two, and jumped back on the next keystroke - restless
   to watch while typing a search (2026-10-09). */
.picker-table-wrap[b-nbnjr1oh75] {
    height: 22rem;
    overflow: auto;
    padding: 0;
    border: 1px solid #e3ecf2;
    border-radius: 0.5rem;
}

.picker-table[b-nbnjr1oh75] {
    width: 100%;
    border-collapse: collapse;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.82rem;
}

.picker-table th[b-nbnjr1oh75],
.picker-table td[b-nbnjr1oh75] {
    text-align: left;
    padding: 0.45rem 0.7rem;
    vertical-align: top;
    border-bottom: 1px solid #eef3f7;
}

/* The whole head is sticky, not each cell: with two rows, per-cell sticky
   needs the second row's offset hard-coded to the first row's height. */
.picker-table thead[b-nbnjr1oh75] {
    position: sticky;
    top: 0;
    z-index: 2;
}

.picker-table thead th[b-nbnjr1oh75] {
    background: #f7fafc;
    font-weight: 700;
    color: #4a5560;
    white-space: nowrap;
}

.sort-btn[b-nbnjr1oh75] {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
}

.sort-arrow[b-nbnjr1oh75] {
    font-size: 0.65rem;
    color: #7d8b97;
}

.row-title[b-nbnjr1oh75] {
    font-weight: 600;
    color: #22303a;
}

.row-muted[b-nbnjr1oh75] {
    color: #9aa7b2;
}

.row-tags[b-nbnjr1oh75] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem;
    margin-top: 0.2rem;
}

.row-tag[b-nbnjr1oh75] {
    background: #eef3f7;
    border-radius: 0.6rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.7rem;
    color: #5a6874;
}

.col-add[b-nbnjr1oh75] {
    width: 1%;
    white-space: nowrap;
    text-align: center;
}

.picker-empty[b-nbnjr1oh75] {
    text-align: center;
    color: #7d8b97;
    padding: 1.2rem 0;
}

.picker-count[b-nbnjr1oh75] {
    margin: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.75rem;
    color: #7d8b97;
}
/* /Components/Shared/FavoriteHeart.razor.rz.scp.css */
.fav-heart[b-n9tgzijzwz] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.2rem;
    height: 2.2rem;
    padding: 0.2rem;
    border: 0;
    border-radius: 0.5rem;
    background: none;
    cursor: pointer;
    line-height: 0;
    flex-shrink: 0;
}

.fav-heart svg[b-n9tgzijzwz] {
    width: 100%;
    height: 100%;
    fill: none;
    stroke: #e31b23;
    stroke-width: 1.4;
    stroke-linejoin: round;
    transition: fill .15s ease;
}

.fav-heart.is-on svg[b-n9tgzijzwz] {
    fill: #e31b23;
}

.fav-heart:focus-visible[b-n9tgzijzwz] {
    outline: 2px solid #1270b7;
    outline-offset: 2px;
}
/* /Components/Shared/PhotoPicker.razor.rz.scp.css */
/* The round frame of the student and teacher lists, larger, with its buttons
   beside it. The live camera shows in the same circle, so what is framed is
   what will be stored - the module crops the middle square. */
.photo-picker[b-fufd4suzgd] {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.75rem;
}

.photo-frame[b-fufd4suzgd] {
    width: 6rem;
    height: 6rem;
    flex-shrink: 0;
    border-radius: 50%;
    overflow: hidden;
    background: #e8f5ee;
    display: flex;
    align-items: center;
    justify-content: center;
}

.photo-frame img[b-fufd4suzgd],
.photo-frame video[b-fufd4suzgd] {
    width: 100%;
    height: 100%;
    /* cover, not contain: a face letterboxed inside a circle looks broken. */
    object-fit: cover;
    display: block;
}

/* [hidden] loses to the display:block above without this. */
.photo-frame video[hidden][b-fufd4suzgd] {
    display: none;
}

.photo-initials[b-fufd4suzgd] {
    font-family: 'Outfit', 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 1.9rem;
    color: #1fa568;
}

.photo-actions[b-fufd4suzgd] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
}

.photo-actions label[b-fufd4suzgd] {
    cursor: pointer;
    margin: 0;
}

/* The dialogs' own error style (add-student-error), copied: scoped CSS
   cannot be shared. */
.photo-error[b-fufd4suzgd] {
    color: var(--edf-pink-dark, #d13a80);
    font-weight: 700;
    font-size: 0.9rem;
    margin: 0 0 0.5rem;
}
/* /Components/Shared/SearchableMultiSelect.razor.rz.scp.css */
.ms-field[b-rb4q3tgiaj] {
    margin-bottom: 1rem;
    font-family: 'Trebuchet MS', sans-serif;
}

.ms-field > .form-label[b-rb4q3tgiaj] {
    display: block;
    margin-bottom: 0.3rem;
    font-family: 'Baloo 2', Nunito, sans-serif;
    font-size: 0.9rem;
    font-weight: 700;
    color: #1e1e1e;
}

/* The count, spaced off the label. Without the margin it reads as part of the
   word - "Atribuir a alunos1" - which is how this looked before. */
.ms-count[b-rb4q3tgiaj] {
    margin-left: 0.4rem;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    background: #d8f2e3;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.72rem;
    font-weight: 700;
    color: #14664a;
}

/* --- chosen items, as removable tags ----------------------------------- */
.ms-tags[b-rb4q3tgiaj] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 0.4rem;
}

.ms-tag[b-rb4q3tgiaj] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.3rem 0.15rem 0.6rem;
    border-radius: 999px;
    background: #e4f3ec;
    font-size: 0.82rem;
    color: #14664a;
}

.ms-tag-remove[b-rb4q3tgiaj] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15rem;
    height: 1.15rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    font-size: 0.95rem;
    line-height: 1;
    color: #14664a;
    cursor: pointer;
}

.ms-tag-remove:hover[b-rb4q3tgiaj] {
    background: #c3e6d4;
}

.ms-clear[b-rb4q3tgiaj] {
    padding: 0.1rem 0.4rem;
    border: 0;
    background: transparent;
    font-size: 0.78rem;
    color: #6b7a88;
    text-decoration: underline;
    cursor: pointer;
}

/* --- the dropdown ------------------------------------------------------- */
.ms-drop[b-rb4q3tgiaj] {
    position: relative;
}

/* The header is the search box: one bordered row holding the input and the
   caret, so it reads as a single control. */
.ms-summary[b-rb4q3tgiaj] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.4rem 0 0.7rem;
    border: 1px solid #ced4da;
    border-radius: 0.5rem;
    background: #fff;
    cursor: text;
}

.ms-summary:hover[b-rb4q3tgiaj],
.ms-summary:focus-within[b-rb4q3tgiaj] {
    border-color: #2f9e6f;
}

.ms-search[b-rb4q3tgiaj] {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.4rem 0;
    border: 0;
    outline: none;
    background: transparent;
    font-family: inherit;
    font-size: 0.88rem;
    color: #1e1e1e;
}

.ms-search[b-rb4q3tgiaj]::placeholder {
    color: #6b7a88;
}

.ms-search:disabled[b-rb4q3tgiaj] {
    cursor: not-allowed;
}

.ms-caret[b-rb4q3tgiaj] {
    flex: 0 0 auto;
    padding: 0.2rem 0.3rem;
    border: 0;
    background: transparent;
    color: #6b7a88;
    cursor: pointer;
    transition: transform 120ms ease-out;
}

.ms-drop.is-open .ms-caret[b-rb4q3tgiaj] {
    transform: rotate(180deg);
}

/* ABSOLUTE, so opening the list does not shove the rest of the form down the
   page - which on a form with two of these would move the second one out from
   under the cursor as the first opened. */
.ms-panel[b-rb4q3tgiaj] {
    display: none;
    position: absolute;
    z-index: 20;
    left: 0;
    right: 0;
    margin-top: 0.2rem;
    padding: 0.5rem;
    border: 1px solid #cfe6da;
    border-radius: 0.6rem;
    background: #fff;
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.12);
}

.ms-drop.is-open .ms-panel[b-rb4q3tgiaj] {
    display: block;
}

/* Capped and scrolled: two hundred children must not produce a panel taller
   than the screen. Ten-ish rows is enough to see that filtering worked. */
.ms-options[b-rb4q3tgiaj] {
    max-height: 15rem;
    overflow-y: auto;
}

.ms-option[b-rb4q3tgiaj] {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0;
    padding: 0.28rem 0.35rem;
    border-radius: 0.35rem;
    font-size: 0.86rem;
    color: #1e1e1e;
    cursor: pointer;
}

.ms-option:hover[b-rb4q3tgiaj] {
    background: #f2f8f5;
}

.ms-option.is-on[b-rb4q3tgiaj] {
    background: #e4f3ec;
    font-weight: 600;
}

.ms-option > input[type="checkbox"][b-rb4q3tgiaj] {
    flex: 0 0 auto;
    margin: 0;
}

.ms-option-label[b-rb4q3tgiaj] {
    flex: 1 1 auto;
}

/* The class a child is in, or a year. Quiet, but it is what tells two
   children with the same first name apart. */
.ms-option-hint[b-rb4q3tgiaj] {
    flex: 0 0 auto;
    font-size: 0.75rem;
    font-weight: 400;
    color: #6b7a88;
}

.ms-empty[b-rb4q3tgiaj] {
    margin: 0;
    padding: 0.4rem 0.35rem;
    font-size: 0.82rem;
    color: #6b7a88;
}
/* /Components/Shared/StudentEditDialog.razor.rz.scp.css */
/* The dialog frame. StudentRemoveDialog.razor.css carries the same rules:
   scoped CSS cannot be shared between components, so the class names are kept
   identical and the rules copied. */

.dialog-overlay[b-jkzxty1w7l] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-jkzxty1w7l] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-jkzxty1w7l] {
    margin-top: 0;
}

.dialog-card input[b-jkzxty1w7l] {
    width: 100%;
    margin-bottom: 0.5rem;
}

.dialog-actions[b-jkzxty1w7l] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.add-student-error[b-jkzxty1w7l] {
    color: var(--edf-pink-dark, #d13a80);
    font-weight: 700;
    font-size: 0.9rem;
    margin: 0.5rem 0 0;
}

/* --- group membership --------------------------------------------------- */
.student-login[b-jkzxty1w7l] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.25rem 0 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.78rem;
    color: var(--edf-ink-soft, #5a6b7b);
}

.student-login code[b-jkzxty1w7l] {
    font-weight: 600;
    font-size: 0.8rem;
    color: var(--edf-blue, #1270b7);
    background: #e5f0fa;
    padding: 0.1rem 0.4rem;
    border-radius: 0.35rem;
}

.group-picker[b-jkzxty1w7l] {
    margin: 0.25rem 0 0.75rem;
    padding: 0;
    border: none;
}

.group-picker legend[b-jkzxty1w7l] {
    padding: 0;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.8rem;
    color: var(--edf-ink-soft, #5a6b7b);
}

/* A column, not a wrapping row: group names vary in width, and a ragged grid
   of checkboxes is harder to scan than a short list. */
.group-option[b-jkzxty1w7l] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.2rem 0;
    font-size: 0.9rem;
    cursor: pointer;
}

.group-option input[b-jkzxty1w7l] {
    width: 1rem;
    height: 1rem;
    cursor: pointer;
}

.group-picker-empty[b-jkzxty1w7l] {
    margin: 0.25rem 0 0;
    font-size: 0.85rem;
    color: var(--edf-ink-soft, #5a6b7b);
}
/* /Components/Shared/StudentGroupEditDialog.razor.rz.scp.css */
/* The dialog frame, moved here from StudentGroups.razor.css with the dialog
   itself. StudentEditDialog.razor.css carries the same rules: scoped CSS cannot
   be shared, so the class names are kept identical and the rules copied. */

.dialog-overlay[b-h9e21u84lp] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-h9e21u84lp] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-h9e21u84lp] {
    margin-top: 0;
}

.dialog-card input[b-h9e21u84lp],
.dialog-card select[b-h9e21u84lp] {
    width: 100%;
    margin-bottom: 0.5rem;
}

/* The teacher is the one field whose empty choice is a real answer ("no
   teacher"), so it gets a label instead of relying on a placeholder. */
.dialog-label[b-h9e21u84lp] {
    display: block;
    margin: 0.25rem 0 0.2rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: 800;
    font-size: 0.8rem;
    color: var(--edf-ink-soft, #5a6b7b);
}

.dialog-actions[b-h9e21u84lp] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.add-student-error[b-h9e21u84lp] {
    color: var(--edf-pink-dark, #d13a80);
    font-weight: 700;
    font-size: 0.9rem;
    margin: 0.5rem 0 0;
}
/* /Components/Shared/StudentPhotoDialog.razor.rz.scp.css */
/* The dialog frame. StudentEditDialog.razor.css carries the same rules:
   scoped CSS cannot be shared between components, so the class names are kept
   identical and the rules copied. */

.dialog-overlay[b-v2uk9mhjed] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-v2uk9mhjed] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-v2uk9mhjed] {
    margin-top: 0;
}

.dialog-actions[b-v2uk9mhjed] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.photo-dialog-error[b-v2uk9mhjed] {
    color: var(--edf-pink-dark, #d13a80);
    font-weight: 700;
    font-size: 0.9rem;
    margin: 0.5rem 0 0;
}
/* /Components/Shared/StudentRemoveDialog.razor.rz.scp.css */
/* The dialog frame. StudentEditDialog.razor.css carries the same rules:
   scoped CSS cannot be shared between components, so the class names are kept
   identical and the rules copied. */

.dialog-overlay[b-8p0h2js5st] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-8p0h2js5st] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-8p0h2js5st] {
    margin-top: 0;
}

.dialog-card input[b-8p0h2js5st] {
    width: 100%;
    margin-bottom: 0.5rem;
}

.dialog-actions[b-8p0h2js5st] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

/* --- the removal confirmation -----------------------------------------
   The frame is the add/edit dialog's; only the two paragraphs are new. The warning is loud because a removal takes the login
   and the password with it and nothing in the app brings them back. */
.confirm-body[b-8p0h2js5st] {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-warning[b-8p0h2js5st] {
    margin: 0 0 1rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.85rem;
    font-weight: 600;
    color: #8c2d22;
}
/* /Components/Shared/TagChips.razor.rz.scp.css */
/* Wraps rather than scrolls: a teacher should be able to see every tag at
   once, and a horizontally scrolling filter hides exactly the options nobody
   thought to look for. */
.tag-bar[b-2e652r7h5a] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    /* Its own breathing room, here rather than on each page: whatever comes
       next - cards, a count, a table - sat right on top of the chips. */
    margin-bottom: 1rem;
}

.tag-bar-label[b-2e652r7h5a] {
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    font-weight: 700;
    color: #4a5560;
    margin-right: 0.2rem;
}

.tag-chip[b-2e652r7h5a] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.22rem 0.65rem;
    border: 1px solid #cfe6da;
    border-radius: 999px;
    background: #fff;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.8rem;
    color: #14664a;
    cursor: pointer;
}

/* THE COLOURS LIVE IN AN INLINE STYLE, from TagPalette - a stylesheet cannot
   know the tag ids. What is left here is everything that does NOT vary by tag:
   shape, size, weight, and the hover and focus affordances.

   Hover lifts the chip rather than recolouring it, because recolouring would
   fight the hue that identifies it. */
.tag-chip:hover[b-2e652r7h5a] {
    filter: brightness(0.96);
}

/* Filled, not merely outlined. A selected chip has to be readable at a glance
   from across a row of fifteen, and a border-only difference is not. The fill
   itself comes from the tag's own hue. */
.tag-chip.is-on[b-2e652r7h5a] {
    font-weight: 700;
}

/* currentColor, so the focus ring is visible on a pale chip and on a filled
   one alike - a fixed dark green vanished on the darker hues. */
.tag-chip:focus-visible[b-2e652r7h5a] {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* Inherits the chip's own colour and steps back with opacity, so the count is
   readable on twelve different backgrounds without twelve rules for it. A
   fixed grey worked on white and disappeared on the darker fills. */
.tag-count[b-2e652r7h5a] {
    font-size: 0.7rem;
    color: inherit;
    opacity: 0.65;
    font-variant-numeric: tabular-nums;
}

.tag-clear[b-2e652r7h5a] {
    background: none;
    border: 0;
    padding: 0.2rem 0.4rem;
    font-family: 'Trebuchet MS', sans-serif;
    font-size: 0.78rem;
    color: #4a5560;
    text-decoration: underline;
    cursor: pointer;
}

/* Inside a form: smaller, quieter, no counts. */
.tag-bar.is-compact .tag-chip[b-2e652r7h5a] {
    padding: 0.15rem 0.5rem;
    font-size: 0.75rem;
}
/* /Components/Shared/TeacherEditDialog.razor.rz.scp.css */
/* The dialog frame. TeacherRemoveDialog.razor.css carries the same rules:
   scoped CSS cannot be shared between components, so the class names are kept
   identical and the rules copied. */

.dialog-overlay[b-811tyui68g] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-811tyui68g] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-811tyui68g] {
    margin-top: 0;
}

.dialog-card input[b-811tyui68g] {
    width: 100%;
    margin-bottom: 0.5rem;
}

.dialog-actions[b-811tyui68g] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.add-teacher-error[b-811tyui68g] {
    color: var(--edf-pink-dark, #d13a80);
    font-weight: 700;
    font-size: 0.9rem;
    margin: 0.5rem 0 0;
}
/* /Components/Shared/TeacherRemoveDialog.razor.rz.scp.css */
/* The dialog frame. TeacherEditDialog.razor.css carries the same rules:
   scoped CSS cannot be shared between components, so the class names are kept
   identical and the rules copied. */

.dialog-overlay[b-bzaq5ssxmk] {
    position: fixed;
    inset: 0;
    background: rgba(30, 30, 30, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 1050;
}

.dialog-card[b-bzaq5ssxmk] {
    width: 100%;
    max-width: 26rem;
    background: var(--edf-surface, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.dialog-card h2[b-bzaq5ssxmk] {
    margin-top: 0;
}

.dialog-card input[b-bzaq5ssxmk] {
    width: 100%;
    margin-bottom: 0.5rem;
}

.dialog-actions[b-bzaq5ssxmk] {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

/* --- the removal confirmation -----------------------------------------
   The frame is the add/edit dialog's; only the two paragraphs are new. The warning is loud because nothing in the app undoes a
   removal. */
.confirm-body[b-bzaq5ssxmk] {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    color: #1e1e1e;
}

.confirm-warning[b-bzaq5ssxmk] {
    margin: 0 0 1rem;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid #c0392b;
    border-radius: 0.35rem;
    background: #fdecea;
    font-size: 0.85rem;
    font-weight: 600;
    color: #8c2d22;
}
