/* GENERATED FILE — DO NOT EDIT.
 *
 * Built by tools/build-shot-css.mjs from:
 *   - public/css/insights.css
 *   - public/css/topic-modal.css
 *
 * Every selector is prefixed with `.pm-shot` so the insights app's styles apply only inside a
 * product shot on /tutoring/progress and nowhere else on the page. Edit the sources and re-run
 * the tool; editing this file by hand will be overwritten and will drift from the app.
 */

/* ══════════ public/css/insights.css ══════════ */

/* ── inlined from tier-palette.css ── */
/* ── The four tier colors, defined once ──
   Every tier-colored thing on the insights page and in the topic modal reads from here:
   cards, section titles, the summary bar, level chips, the modal, the confetti. Change a
   color here and everything follows; a hex anywhere else is a mistake.

   Chosen as one family — similar weight, similar warmth — and so white text holds on all
   four: the old pure-orange #ffa500 failed contrast badly for white type.
   `-deep`  the darker end of a card's gradient and its tinted shadow
   `-text`  the tier as ink on a white surface (section titles, modal accents)
   `-soft`  the tier as a faint wash behind dark text */
:root {
    --tier-beginner: #e5484d;
    --tier-beginner-deep: #cc3d42;
    --tier-beginner-text: #c0393e;
    --tier-beginner-soft: rgba(229, 72, 77, 0.12);

    --tier-intermediate: #e8891d;
    --tier-intermediate-deep: #cf7714;
    --tier-intermediate-text: #b8650f;
    --tier-intermediate-soft: rgba(232, 137, 29, 0.14);

    --tier-advanced: #3ea24c;
    --tier-advanced-deep: #348a40;
    --tier-advanced-text: #2c7a38;
    --tier-advanced-soft: rgba(62, 162, 76, 0.12);

    --tier-mastery: #7c88f4;
    --tier-mastery-deep: #6a5fe0;
    --tier-mastery-text: #5a4fd1;
    --tier-mastery-soft: rgba(124, 136, 244, 0.14);
    --tier-mastery-gradient: linear-gradient(45deg, #6f8ef7 0%, #8b7bf3 100%);

    --tier-accent-strip: linear-gradient(90deg, var(--tier-beginner), var(--tier-intermediate), var(--tier-advanced), var(--tier-mastery-deep));

    /* Chip inks for the two signals that are not a tier: pace and staleness. Up/down/hard
       borrow the advanced/beginner/intermediate inks. */
    --signal-pace: #1d6fd6;
    --signal-stale: #5c6470;
}



/* ── inlined from progress-summary.css ── */
/* progress-summary.css
 *
 * The one-screen progress summary: Where we started / Where we are / What we're working on /
 * What's next. Rendered by public/js/insights/insights-summary.mjs.
 *
 * Lives in its own file because TWO pages draw this component and only one of them is the app:
 * /insights loads it via insights.css, and the public /tutoring/progress sample loads it alone,
 * without pulling in the whole board stylesheet. Edit it here and both stay in step — the same
 * reason tier-palette.css was split out.
 *
 * Deliberately plain: no tier colors, no chips, nothing that needs the rest of the board
 * explained first. The audience is a parent who is going to read this and stop.
 */

/* ── The one-screen summary, for someone reading about another person ── */
/* Deliberately plainer than the board: no tier colors, no chips, nothing that needs the rest
   of the page explained first. A parent should be able to read this and stop. */
.pm-shot .parent-summary {
    margin-bottom: 1rem;
    padding: 1.1rem 1.15rem;
    border-radius: 1rem;
    background: var(--bs-body-bg);
    box-shadow: 0 0 0 1px var(--bs-border-color-translucent), 0 10px 30px -22px rgba(0, 0, 0, 0.45);
}

.pm-shot .ps-title {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.pm-shot .ps-sub {
    margin: 0.15rem 0 0;
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ps-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
    gap: 0.7rem;
    margin-top: 0.9rem;
}

.pm-shot .ps-panel {
    padding: 0.75rem 0.85rem;
    border-radius: 0.7rem;
    background: var(--bs-secondary-bg);
    box-shadow: inset 0 0 0 1px var(--bs-border-color-translucent);
}

/* The current standing is the one panel a parent looks for first. */
.pm-shot .ps-panel.is-now {
    background: var(--bs-body-bg);
    box-shadow: inset 0 0 0 2px var(--bs-primary-border-subtle);
}

.pm-shot .ps-label {
    display: block;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color);
}

.pm-shot .ps-figure {
    display: block;
    margin-top: 0.15rem;
    font-size: 1.6rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
    color: var(--bs-body-color);
}

.pm-shot .ps-detail {
    margin: 0.25rem 0 0;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ps-detail b { color: var(--bs-body-color); font-variant-numeric: tabular-nums; }

.pm-shot .ps-when {
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

.pm-shot .ps-verdict {
    margin: 0.35rem 0 0;
    font-size: 0.8rem;
    font-weight: 700;
}

.pm-shot .ps-verdict.is-up { color: var(--tier-advanced-text); }
.pm-shot .ps-verdict.is-down { color: var(--tier-beginner-text); }
.pm-shot .ps-verdict.is-level { color: var(--bs-secondary-color); }

.pm-shot .ps-topics {
    margin: 0.4rem 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.pm-shot .ps-topic {
    display: flex;
    flex-direction: column;
}

.pm-shot .ps-topic-name {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--bs-body-color);
}

.pm-shot .ps-topic-worth {
    font-size: 0.74rem;
    color: var(--bs-secondary-color);
}

/* The forward-looking line: what the work above is worth. Sits under the goal because it is the
   answer to "and how do we get there". */
.pm-shot .ps-reach {
    margin: 0.45rem 0 0;
    padding-top: 0.45rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ps-reach b {
    color: var(--bs-primary-text-emphasis);
    font-variant-numeric: tabular-nums;
}

/* Only ever drawn by ?preview=guardian on your own board. Loud on purpose: a preview that
   looks like the real thing is how an unfinished panel ends up in front of a parent. */
.pm-shot .ps-preview-flag {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    margin: 0 0 0.85rem;
    padding: 0.6rem 0.75rem;
    border-radius: 0.6rem;
    background: var(--bs-warning-bg-subtle);
    box-shadow: inset 0 0 0 1px var(--bs-warning-border-subtle);
    font-size: 0.8rem;
    color: var(--bs-body-color);
}

.pm-shot .ps-preview-flag code {
    padding: 0.05rem 0.3rem;
    border-radius: 0.25rem;
    background: var(--bs-body-bg);
    font-size: 0.95em;
}



/* ── Page background ── */
.pm-shot {
    background-color: #f8f9fa;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* ── Accent strip with animation ── */
.pm-shot .insights-accent-strip {
    height: 4px;
    background: var(--tier-accent-strip);
    background-size: 300% 100%;
    animation: accentFlow 8s ease infinite;
}

@keyframes accentFlow {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

/* ── Tier sections ── */
.pm-shot .tier-section {
    background: var(--bs-body-bg);
    border-radius: 1rem;
    padding: 0.85rem 1rem 1rem;
    /* Same layered shadow as the summary header, so the page has one card surface. */
    box-shadow:
        0 0 0 1px rgba(0, 0, 0, 0.05),
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 6px 16px -8px rgba(0, 0, 0, 0.08),
        0 16px 40px -20px rgba(0, 0, 0, 0.1);
    min-height: 140px;
    height: 100%;
    transition-property: box-shadow, opacity;
    transition-duration: 0.25s;
    transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pm-shot .tier-section.focus-beginner { --focus-ring: var(--tier-beginner); }
.pm-shot .tier-section.focus-intermediate { --focus-ring: var(--tier-intermediate); }
.pm-shot .tier-section.focus-advanced { --focus-ring: var(--tier-advanced); }
.pm-shot .tier-section.focus-mastery { --focus-ring: var(--tier-mastery); }

.pm-shot .tier-section.is-focused {
    box-shadow:
        0 0 0 3px var(--focus-ring),
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 6px 16px -8px rgba(0, 0, 0, 0.08),
        0 16px 40px -20px rgba(0, 0, 0, 0.1);
}

.pm-shot .tier-section.is-dimmed {
    opacity: 0.5;
}

.pm-shot .tier-title {
    font-size: 0.9rem;
    font-weight: 700;
    margin-bottom: 0.5rem;
    padding-left: 0.6rem;
    display: flex;
    align-items: center;
}

.pm-shot .tier-title.tier-mastery { border-left: 4px solid var(--tier-mastery); color: var(--tier-mastery-text); }
.pm-shot .tier-title.tier-advanced { border-left: 4px solid var(--tier-advanced); color: var(--tier-advanced-text); }
.pm-shot .tier-title.tier-intermediate { border-left: 4px solid var(--tier-intermediate); color: var(--tier-intermediate-text); }
.pm-shot .tier-title.tier-beginner { border-left: 4px solid var(--tier-beginner); color: var(--tier-beginner-text); }

/* A real <button> so it is reachable and announced; styled back down to the bare icon. */
.pm-shot .tier-title .tier-info-btn {
    display: inline-flex;
    align-items: center;
    padding: 0;
    border: 0;
    background: none;
    color: var(--bs-secondary);
    opacity: 0.5;
    transition: opacity 0.2s;
    font-size: 0.8rem;
    line-height: 1;
    cursor: pointer;
}

.pm-shot .tier-title .tier-info-btn:hover,
.pm-shot .tier-title .tier-info-btn:focus-visible {
    opacity: 1;
}

/* The board is dense, so make focus unmissable rather than relying on the default. */
.tier-info-btn:focus-visible,
.topic-card:focus-visible,

/* The low-data ring already owns the outline, so shift its focus ring clear of it. */
.pm-shot .low-data-card:focus-visible {
    outline-offset: 5px;
}

.pm-shot .worksheet-form-title {
    font-size: 1.35rem;
}

.pm-shot .tier-cards {
    display: flex;
    flex-wrap: wrap;
    /* Roomy enough that two adjacent .low-data-card rings never meet. */
    gap: 0.9rem;
    justify-content: center;
}

/* ── Tier card base ── */
.pm-shot .tier-card {
    --tier-bg: #999;
    --tier-deep: #777;
    /* Three sizes on a card, each with a job: the topic name, its score, and everything
       else. Before this there were five, none of them deliberate. */
    --card-title-font: 1.1rem;
    --card-count-font: 0.8rem;
    --card-pill-font: 0.7rem;
    --card-pill-height: 22px;
    --card-badge-height: 20px;
    /* Lit from the top-left: the tier color deepens toward the bottom-right, and the
       resting shadow is the card's own color, so cards sit on the page instead of on it. */
    background: linear-gradient(160deg, var(--tier-bg) 0%, var(--tier-deep) 100%);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 8px 20px -10px color-mix(in srgb, var(--tier-deep) 60%, transparent);
    border-radius: 1rem;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.25s ease, filter 0.2s ease;
    user-select: none;
    flex: 1 1 100%;
    animation: cardFadeIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* One soft highlight in the corner. The two lighter blobs it replaces read as smudges. */
.pm-shot .tier-card::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 100% 0%, rgba(255, 255, 255, 0.22), transparent 55%);
    pointer-events: none;
}

/* ── Card hover: lift, and the shadow deepens in the same color ── */
.pm-shot .tier-card:hover {
    transform: scale(1.05) translateY(-4px);
    box-shadow:
        0 2px 4px rgba(0, 0, 0, 0.08),
        0 18px 36px -14px color-mix(in srgb, var(--tier-deep) 75%, transparent);
    filter: brightness(1.04);
}

/* ── Card click / active: press down ── */
.pm-shot .tier-card:active {
    transform: scale(0.96);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    transition-duration: 0.1s;
}

/* ── Per-level colors, from the palette ── */
.pm-shot .tier-card.beginner-card { --tier-bg: var(--tier-beginner); --tier-deep: var(--tier-beginner-deep); }
.pm-shot .tier-card.intermediate-card { --tier-bg: var(--tier-intermediate); --tier-deep: var(--tier-intermediate-deep); }
.pm-shot .tier-card.advanced-card { --tier-bg: var(--tier-advanced); --tier-deep: var(--tier-advanced-deep); }
.pm-shot .tier-card.mastery-card {
    --tier-bg: var(--tier-mastery);
    --tier-deep: var(--tier-mastery-deep);
    background: var(--tier-mastery-gradient);
}

/* Mastery shine overlay (added as DOM element so ::after circle is preserved) */
.pm-shot .mastery-shine {
    position: absolute;
    inset: 0;
    background: linear-gradient(120deg, rgba(255, 255, 255, 0) 25%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 75%);
    background-size: 200% 100%;
    border-radius: 1rem;
    pointer-events: none;
}

/* The sweep plays when a card is looked at, not forever on every Mastery card at once —
   on a board with fifty of them that was fifty GPU animations for as long as the tab lived. */
.pm-shot .tier-card:hover .mastery-shine,
.pm-shot .tier-card:focus-visible .mastery-shine {
    animation: shine 2.5s linear 1;
}

@keyframes shine {
    0% { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}

/* ── Card body, shared by the board and "Where to focus" ──
   Left-aligned so a card scans as a list: name, score, what's notable, what's next. */
.pm-shot .card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.6rem;
}

.pm-shot .topic-title {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    color: #fff;
    line-height: 1.2;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
}

.pm-shot .topic-title small {
    font-size: 0.68em;
    font-weight: 600;
    opacity: 0.85;
}

.pm-shot .topic-title b {
    font-size: var(--card-title-font);
    line-height: 1.15;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    overflow-wrap: normal;
}

/* A column at the top-right of the head row, in flow: the head grows to fit however many
   badges there are, so the bar always sits below them. Absolutely positioned, the stack
   used to land beside the count on a one-line title, and the rings ate the gap. */
.pm-shot .card-badges {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.4rem;
}

/* The one thing to do next, set apart from the chips above it. */
.pm-shot .card-next {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin: 0;
    padding-top: 0.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.28);
    font-size: var(--card-pill-font);
    font-weight: 700;
    line-height: 1;
    color: #fff;
    animation: pillSlideIn 0.5s ease-out 0.4s both;
}

.pm-shot .card-next i:first-child { font-size: 1.1em; }

.pm-shot .tier-card .card-body {
    /* Above the decorative highlight, which is absolutely positioned and would otherwise
       paint over a left-aligned title's first letter. */
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.95rem 1rem 1rem;
}

.pm-shot .card-text {
    color: white;
    font-weight: bold;
    text-align: center;
}

.pm-shot .spinner-container {
    margin: 0 auto;
    width: fit-content;
    padding-bottom: 1rem;
    padding-top: 1rem;
}

/* ── "Where to focus": impact-ranked next steps ── */
.pm-shot .ih-focus {
    /* The header clips its rounded corners, so the last band leaves room for a card's
       hover lift and most of its shadow. */
    padding: 0.8rem 1.1rem 1.35rem;
}

.pm-shot .focus-list {
    list-style: none;
    margin: 0;
    padding: 0.2rem 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}

/* A small copy of the card it opens: same surface, blobs, bar and pills, at a size that
   says "preview". The board's own cards stay the bigger thing. */
.pm-shot .focus-card {
    --card-title-font: 0.92rem;
    --card-count-font: 0.72rem;
    --card-pill-font: 0.66rem;
    --card-pill-height: 20px;
    flex: 1 1 13rem;
    max-width: 100%;
    min-width: 0;
    border-radius: 0.85rem;
}

.pm-shot .focus-card:nth-child(1) { animation-delay: 0.05s; }
.pm-shot .focus-card:nth-child(2) { animation-delay: 0.12s; }
.pm-shot .focus-card:nth-child(3) { animation-delay: 0.19s; }
.pm-shot .focus-card:nth-child(4) { animation-delay: 0.26s; }
.pm-shot .focus-card:nth-child(5) { animation-delay: 0.33s; }

.pm-shot .focus-card:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 3px;
}

.pm-shot .focus-card .card-body {
    gap: 0.5rem;
    padding: 0.75rem 0.8rem 0.8rem;
}

/* Staff: the worksheet builder as the last card in the row. */
.pm-shot .focus-card-cta {
    flex: 1 1 100%;
    display: flex;
}

.pm-shot .focus-cta-btn {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 2.75rem;
    padding: 0.5rem 1rem;
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 0.85rem;
    background-color: var(--bs-primary-bg-subtle);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 8px 20px -12px rgba(13, 110, 253, 0.35);
    color: var(--bs-primary-text-emphasis);
    font-size: 0.8rem;
    cursor: pointer;
    transition-property: background-color, border-color, box-shadow;
    transition-duration: 0.2s;
    transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pm-shot .focus-cta-btn i { font-size: 1.15rem; }
.pm-shot .focus-cta-btn b { font-size: 0.88rem; }
.pm-shot .focus-cta-btn span { opacity: 0.85; }

.pm-shot .focus-cta-btn:hover,
.pm-shot .focus-cta-btn:focus-visible {
    border-color: var(--bs-primary);
    background-color: var(--bs-primary);
    color: #fff;
    box-shadow: 0 6px 18px -8px rgba(13, 110, 253, 0.6);
}

.pm-shot .focus-cta-btn:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 3px;
}

.pm-shot .focus-cta-btn:active {
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15);
}

/* ── "What's new" notice ── */
.pm-shot .whats-new {
    border: 0;
    border-radius: 1rem;
    background: linear-gradient(135deg, var(--bs-primary-bg-subtle) 0%, var(--bs-body-bg) 60%);
}

.pm-shot .whats-new .modal-body {
    position: relative;
    padding: 1.4rem 1.5rem;
}

.pm-shot .whats-new-close {
    position: absolute;
    top: 1rem;
    right: 1.1rem;
    z-index: 1;
}

.pm-shot .whats-new-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-right: 2rem;
    margin-bottom: 0.6rem;
}

.pm-shot .whats-new-badge {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background-color: var(--bs-primary);
    color: #fff;
    font-size: 1.1rem;
}

.pm-shot .whats-new-title {
    font-size: 1.1rem;
    font-weight: 700;
    margin: 0;
    color: var(--bs-primary-text-emphasis);
}

/* Lede and tier chips share a row so the panel uses its width instead of leaving a
   column of dead space beside a narrow paragraph. */
.pm-shot .whats-new-intro {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
    margin-bottom: 0.9rem;
}

.pm-shot .whats-new-lede {
    width: 100%;
    font-size: 0.9rem;
    line-height: 1.55;
    margin: 0;
    color: var(--bs-body-color);
}

.pm-shot .whats-new-bands {
    flex: 0 1 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
}

.pm-shot .wn-band {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.25rem 0.6rem;
    border-radius: 50px;
    color: #fff;
    white-space: nowrap;
}

.pm-shot .wn-band b {
    font-variant-numeric: tabular-nums;
    opacity: 0.9;
}

.pm-shot .wn-band-mastery { background: var(--tier-mastery-gradient); }
.pm-shot .wn-band-advanced { background-color: var(--tier-advanced); }
.pm-shot .wn-band-intermediate { background-color: var(--tier-intermediate); }
.pm-shot .wn-band-beginner { background-color: var(--tier-beginner); }

.pm-shot .whats-new-points {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--bs-border-color-translucent);
    padding-top: 0.85rem;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 0.45rem 1.25rem;
}

.pm-shot .whats-new-points li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--bs-secondary-color);
}

.pm-shot .whats-new-points li b {
    color: var(--bs-body-color);
}

.pm-shot .whats-new-points i {
    flex: 0 0 auto;
    margin-top: 0.15rem;
    color: var(--bs-primary);
}

.pm-shot .whats-new-foot {
    margin: 0.85rem 0 0;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

@media (max-width: 576px) {
    .pm-shot .whats-new {
        padding: 0.9rem 1rem;
    }

    .pm-shot .whats-new-bands {
        margin-top: 0.7rem;
    }
}

/* ── Card accuracy bar ──
   The count sits beside the bar, not on it. Centered over the track it landed wherever
   the fill happened to end — white-on-white at high accuracy, and unreadable either way. */
.pm-shot .topic-progress-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.pm-shot .topic-progress {
    flex: 1;
    height: 0.75rem;
    background-color: rgba(0, 0, 0, 0.3);
}

.pm-shot .topic-progress-count {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
    font-size: var(--card-count-font);
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
    /* Tabular figures so the counts line up down a column */
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

/* ── Signal panel: what the page tracks for a topic ──
   Accuracy is the headline and the only thing the tier is drawn from; the rest sit
   beside it because they change how you practice, not what tier you are in. */
.pm-shot .signal-panel {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 0.5rem;
    margin-bottom: 1.25rem;
}

.pm-shot .signal {
    border: 1px solid var(--bs-border-color);
    border-radius: 0.75rem;
    padding: 0.6rem 0.75rem;
    background-color: var(--bs-body-bg);
    animation: fadeSlideUp 0.5s ease-out both;
}

.pm-shot .signal:nth-child(2) { animation-delay: 0.06s; }
.pm-shot .signal:nth-child(3) { animation-delay: 0.12s; }
.pm-shot .signal:nth-child(4) { animation-delay: 0.18s; }

.pm-shot .signal-label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--bs-secondary-color);
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

.pm-shot .signal-value {
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.2;
    margin-top: 0.15rem;
}

.pm-shot .signal-note {
    font-size: 0.72rem;
    color: var(--bs-secondary-color);
}

.pm-shot .signal-headline {
    border-color: var(--bs-primary-border-subtle);
    background-color: var(--bs-primary-bg-subtle);
}

.pm-shot .signal-headline .signal-value { color: var(--bs-primary-text-emphasis); }
.pm-shot .signal-good .signal-value { color: var(--bs-success-text-emphasis); }
.pm-shot .signal-warn .signal-value { color: var(--bs-warning-text-emphasis); }
.pm-shot .signal-muted .signal-value { color: var(--bs-secondary-color); font-weight: 600; }

/* Tier key swatches in the "How this is measured" panel */
.pm-shot .tier-key {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 0.25rem;
    margin-right: 0.4rem;
    vertical-align: -1px;
}

.pm-shot .tier-key-mastery { background: var(--tier-mastery-gradient); }
.pm-shot .tier-key-advanced { background-color: var(--tier-advanced); }
.pm-shot .tier-key-intermediate { background-color: var(--tier-intermediate); }
.pm-shot .tier-key-beginner { background-color: var(--tier-beginner); }

/* ── Attempt squares ── */
.pm-shot .squares-container {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

.pm-shot .attempt-square {
    min-width: 6rem;
    min-height: 4rem;
    text-align: center;
    border-radius: 0.5rem;
    position: relative;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    cursor: pointer;
    font-family: sans-serif;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.25s ease;
    color: white;
    display: flex;
    flex-flow: column;
    justify-content: center;
    gap: 5px;
    user-select: none;
    animation: squarePop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.pm-shot .attempt-square.correct {
    background-color: var(--bs-success);
}

.pm-shot .attempt-square.incorrect {
    background-color: var(--bs-danger);
}

.pm-shot .attempt-square:hover {
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
}

.pm-shot .attempt-square:active {
    transform: scale(0.92);
    transition-duration: 0.08s;
}

.pm-shot .attempt-number,
.pm-shot .attempt-square .icon-clock {
    font-size: 1.2rem;
    font-weight: bold;
    color: white;
}

.pm-shot .icons {
    background-color: white;
    border-radius: 0.3rem;
    width: 75%;
    margin: 0 auto;
}

.pm-shot .icon-star,
.pm-shot .icon-lightning {
    font-size: 1rem;
    color: #cccccc;
    flex: 1;
    text-align: center;
}

.pm-shot .icon-fire {
    position: absolute;
    top: -13px;
    right: 0px;
    color: var(--bs-orange);
    font-size: 1.5rem;
}

.pm-shot .attempt-square .bi-fire::before {
    background-color: white;
    border-radius: 999rem;
    padding: 4px;
    filter: drop-shadow(0.25rem 0.25rem 0.3rem rgba(0, 0, 0, 0.5));
}

.pm-shot .attempt-square.history {
    background-color: var(--bs-secondary);
}

.pm-shot .icon-clock {
    align-self: center;
    position: relative;
    display: inline-table;
}

.pm-shot .icon-star.active {
    color: var(--bs-purple);
}

.pm-shot .icon-lightning.active {
    color: var(--bs-blue);
}

/* Legacy flat highlight, kept for anything outside the question breakdown. */
.pm-shot .highlight {
    background-color: #fffeb8;
    transition: background-color 0.3s ease;
}

/* ── Perfect score badge ── */
/* ── Corner badges: streak (left), perfect / low-data (right) ──
   One shape for all three so they share a baseline and height whichever pair shows. */
.pm-shot .card-badge {
    line-height: 1;
    box-shadow:
        0 0 0 1.5px rgba(255, 255, 255, 0.9),
        0 2px 6px rgba(0, 0, 0, 0.25);
    height: var(--card-badge-height);
    padding: 0 0.5rem;
    border-radius: 50px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--card-pill-font);
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.3px;
    white-space: nowrap;
    animation: badge-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
    z-index: 2;
}

.pm-shot .perfect-score-badge {
    background: linear-gradient(135deg, #ffd700, #ffb300);
    color: #7a5800;
    text-transform: uppercase;
}

.pm-shot .perfect-score-badge i {
    animation: starSpin 3s ease-in-out 2;
}

@keyframes starSpin {
    0%, 100% { transform: rotate(0deg) scale(1); }
    25% { transform: rotate(15deg) scale(1.2); }
    75% { transform: rotate(-15deg) scale(1.2); }
}

@keyframes badge-in {
    0% { transform: scale(0) rotate(-20deg); opacity: 0; }
    100% { transform: scale(1) rotate(0deg); opacity: 1; }
}

@media (max-width: 1200px) {
    .pm-shot .card-title {
        font-size: 1rem;
    }
}

@media (max-width: 992px) {
    .pm-shot #user-name {
        font-size: 1.2rem;
        display: block;
        margin-top: 7px;
    }

    .pm-shot .title-sep {
        display: none;
    }
}

@media (max-width: 380px) {
    .pm-shot .card-title {
        font-size: 1rem;
    }
}

.pm-shot .topic-card.selected {
    border: 2px solid var(--bs-primary);
}

/* ── Disabled topic cards in group worksheet mode ── */
.pm-shot .disabled-card {
    opacity: 0.5;
    pointer-events: none;
    filter: grayscale(30%);
    position: relative;
}

.pm-shot .disabled-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0.5rem;
}

.pm-shot .disabled-overlay .disabled-msg {
    color: #fff;
    background: black;
    border-radius: 0.5rem;
    padding: 0.35rem 0.5rem;
    line-height: 1.2;
    font-size: 0.8rem;
    font-weight: bold;
    z-index: 1;
}

/* ── Selected card styles ── */
.pm-shot .tier-card.selected {
    transform: scale(1.05);
    box-shadow: 0 0 20px rgba(var(--bs-primary-rgb), 0.35);
    border: 3px solid var(--bs-primary);
}

/* ── Selected topics badges ── */
.pm-shot .selected-topics {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.75rem;
    border: 1px dashed #dee2e6;
    border-radius: 0.25rem;
    background-color: rgba(0, 0, 0, 0.02);
    justify-content: center;
    align-items: center;
    margin: 1rem 0;
    height: 13rem;
    overflow: auto;
}

.pm-shot .selected-topics .badge {
    display: inline-flex;
    align-items: center;
    padding: 0.35rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 500;
    border-radius: 0.25rem;
    transition: transform 0.2s, box-shadow 0.2s;
    font-weight: bold;
    max-height: 78px;
    position: relative;
    padding-bottom: 1.25rem;
}

.pm-shot .text-decoration-line-through {
    text-decoration: line-through;
}

.pm-shot .selected-topics .badge .available-info {
    width: 100%;
    color: #fff;
    opacity: 0.95;
    position: absolute;
    bottom: 4px;
    left: 0;
    right: 0;
    pointer-events: none;
}

.pm-shot .selected-topics .badge:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.pm-shot .selected-topics .badge .quantity-control {
    display: flex;
    align-items: center;
    margin-left: 0.5rem;
    background-color: rgba(255, 255, 255, 0.2);
    border-radius: 0.25rem;
    padding: 0.1rem 0.25rem;
}

.pm-shot .selected-topics .badge .quantity-btn {
    background: none;
    border: none;
    color: white;
    font-weight: bold;
    padding: 0 0.25rem;
    cursor: pointer;
    font-size: 0.875rem;
    line-height: 1;
    transition: transform 0.15s ease;
}

.pm-shot .selected-topics .badge .quantity-btn:hover {
    background: rgba(255, 255, 255, 0.25);
    border-radius: 0.2rem;
}

.pm-shot .selected-topics .badge .quantity-btn:active {
    transform: scale(0.9);
}

.pm-shot .selected-topics .badge .quantity-input {
    width: 2rem;
    text-align: center;
    background: none;
    border: none;
    color: white;
    font-weight: bold;
    padding: 0;
    margin: 0 0.25rem;
    font-size: 0.875rem;
}

.pm-shot .selected-topics .badge .quantity-input::-webkit-inner-spin-button,
.pm-shot .selected-topics .badge .quantity-input::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.pm-shot .selected-topics .badge .quantity-input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.pm-shot .total-problems {
    font-size: 0.875rem;
    color: #495057;
}

.pm-shot #total-problems-count {
    color: var(--bs-primary);
    font-weight: bold;
}

/* ── Mode help panel ── */
.pm-shot #mode-help .alert {
    border: 1px solid #dee2e6;
    background: linear-gradient(135deg, #f8f9fa 0%, #eef2f6 100%);
}

.pm-shot #mode-help .bi-info-circle-fill {
    color: var(--bs-primary);
}

/* ── Badge colors ── */
.pm-shot .selected-topics .badge.beginner { background-color: var(--tier-beginner); color: white; }
.pm-shot .selected-topics .badge.intermediate { background-color: var(--tier-intermediate); color: white; }
.pm-shot .selected-topics .badge.advanced { background-color: var(--tier-advanced); color: white; }
.pm-shot .selected-topics .badge.mastery { background: var(--tier-mastery-gradient); color: white; }

.pm-shot .badge.beginner { background-color: var(--tier-beginner); color: white; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }
.pm-shot .badge.intermediate { background-color: var(--tier-intermediate); color: white; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }
.pm-shot .badge.advanced { background-color: var(--tier-advanced); color: white; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }
.pm-shot .badge.mastery { background: var(--tier-mastery-gradient); color: white; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }

/* ── Text colors ── */
.pm-shot .text-beginner { color: var(--tier-beginner) !important; }
.pm-shot .text-intermediate { color: var(--tier-intermediate) !important; }
.pm-shot .text-advanced { color: var(--tier-advanced) !important; }
.pm-shot .text-mastery {
    background: var(--tier-mastery-gradient);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    color: transparent;
}

.pm-shot .selected-topics .btn-close {
    margin-left: 0.5rem;
    font-size: 0.75rem;
    opacity: 0.8;
    color: white;
    text-shadow: none;
    padding: 0.25rem;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.2);
    transition: all 0.2s;
    line-height: 1;
    height: 1.25rem;
    width: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    border: 0px;
    font-weight: bold;
}

.pm-shot .selected-topics .btn-close:hover {
    opacity: 1;
    background-color: rgba(255, 255, 255, 0.3);
    transform: rotate(90deg);
}

/* ── Test creation form ── */
.pm-shot .test-creation-form {
    background-color: white;
    border-radius: 0.5rem;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
}

.pm-shot .test-creation-form h3 {
    font-size: 1.25rem;
    color: var(--bs-primary);
}

.pm-shot .test-creation-form .alert {
    padding: 0.75rem;
    margin-bottom: 1rem;
    font-size: 0.875rem;
    border-radius: 0.25rem;
}

.pm-shot #userSearch button,
.pm-shot #group-user-search button {
    border-radius: 0rem;
}

.pm-shot .problem-type-card {
    cursor: pointer;
    transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.pm-shot .problem-type-card .card {
    border: 2px solid #dee2e6;
    transition: all 0.2s ease;
}

.pm-shot .problem-type-card:hover .card {
    border-color: var(--bs-primary);
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

.pm-shot .problem-type-card.selected .card {
    border-color: var(--bs-primary);
    background-color: rgba(var(--bs-primary-rgb), 0.05);
}

.pm-shot .problem-type-card .card-title {
    color: var(--bs-dark);
    margin-bottom: 0.5rem;
}

.pm-shot .problem-type-card .card-text {
    font-size: 0.875rem;
    margin-bottom: 0;
}

/* ── Group Insights Container ── */
.pm-shot .group-insights-container {
    padding: 1.5rem;
    margin-bottom: 2rem;
}

.pm-shot .group-insights-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.pm-shot .group-insights-header h3 {
    margin: 0;
    color: var(--brand-primary);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Worksheet search uses blue instead of brand-primary green */
.pm-shot .worksheet-search-container .group-insights-header h3 {
    color: var(--bs-primary);
}

.pm-shot .group-info {
    background: var(--brand-primary);
    color: white;
    padding: 0.5rem 1rem;
    border-radius: 20px;
    font-weight: 600;
    font-size: 0.8rem;
}

/* ── Selected Students Display ── */
.pm-shot .selected-students {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-height: 3rem;
    align-items: center;
    padding: 0.5rem;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    background: white;
}

.pm-shot .selected-students.empty {
    justify-content: center;
    color: #6c757d;
    font-style: italic;
}

.pm-shot .student-badge {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--brand-primary);
    color: white;
    padding: 0.5rem 0.75rem;
    border-radius: 20px;
    font-weight: 500;
    font-size: 0.9rem;
    animation: badgeSlideIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes badgeSlideIn {
    from { opacity: 0; transform: translateY(-10px) scale(0.8); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.pm-shot .student-badge .remove-btn {
    background: none;
    border: none;
    color: white;
    cursor: pointer;
    padding: 0;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: background-color 0.2s ease, transform 0.2s ease;
}

.pm-shot .student-badge .remove-btn:hover {
    background: rgba(255, 255, 255, 0.2);
    transform: rotate(90deg);
}

/* ── Mode Indicators ── */
.pm-shot .group-insights-mode-indicator {
    position: fixed;
    top: 20px;
    left: 20px;
    background: var(--brand-primary);
    color: white;
    padding: 0.5rem;
    border-radius: 50%;
    font-weight: 600;
    z-index: 1000;
    opacity: 0;
    transform: translateY(-20px);
    transition: all 0.3s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pm-shot .group-insights-mode-indicator.show {
    opacity: 1;
    transform: translateY(0);
}

.pm-shot .worksheet-mode-indicator {
    position: fixed;
    top: 20px;
    left: 70px;
    background: var(--bs-primary);
    color: white;
    padding: 0.5rem;
    border-radius: 50%;
    font-weight: 600;
    z-index: 1000;
    opacity: 0;
    transform: translateY(-20px);
    transition: all 0.3s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pm-shot .worksheet-mode-indicator.show {
    opacity: 1;
    transform: translateY(0);
}

.pm-shot .group-insights-mode-indicator span,
.pm-shot .worksheet-mode-indicator span {
    display: none;
}

.pm-shot .group-insights-mode-indicator i,
.pm-shot .worksheet-mode-indicator i {
    margin-right: 0;
    font-size: 1.2rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pm-shot .group-insights-mode-indicator.both-visible { left: 20px; top: 20px; }
.pm-shot .worksheet-mode-indicator.both-visible { left: 70px; top: 20px; }

.pm-shot .group-insights-mode-indicator.single-visible,
.pm-shot .worksheet-mode-indicator.single-visible {
    left: 20px;
    top: 20px;
}

/* ── Combined Insights Header ── */
.pm-shot .combined-insights-header {
    background: var(--tier-advanced-soft);
    border: 1px solid var(--tier-advanced);
    border-radius: 8px;
    padding: 1rem 1.5rem;
    margin-bottom: 1.5rem;
}

.pm-shot .combined-insights-header h4 {
    margin: 0 0 0.5rem 0;
    color: var(--tier-advanced-text);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.pm-shot .combined-insights-header p {
    margin: 0;
    color: var(--tier-advanced-text);
    font-weight: 500;
}

/* ── Card entrance animation ── */
@keyframes cardFadeIn {
    from { opacity: 0; transform: translateY(20px) scale(0.95); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.pm-shot .tier-cards .tier-card:nth-child(1) { animation-delay: 0.05s; }
.pm-shot .tier-cards .tier-card:nth-child(2) { animation-delay: 0.12s; }
.pm-shot .tier-cards .tier-card:nth-child(3) { animation-delay: 0.19s; }
.pm-shot .tier-cards .tier-card:nth-child(4) { animation-delay: 0.26s; }
.pm-shot .tier-cards .tier-card:nth-child(5) { animation-delay: 0.33s; }
.pm-shot .tier-cards .tier-card:nth-child(n+6) { animation-delay: 0.40s; }

/* ── Worksheet / Group toggle styles (checkbox-based) ── */
.pm-shot #mode-toggle-container .form-check-input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.pm-shot #mode-toggle-container .form-check-label {
    margin-bottom: 0;
    cursor: pointer;
}

.pm-shot .create-worksheet-toggle,
.pm-shot .create-group-insights-toggle {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1rem;
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
    border-radius: 0.5rem;
    border: 2px solid #dee2e6;
    transition: all 0.3s ease;
    cursor: pointer;
    min-width: 300px;
}

.pm-shot .create-worksheet-toggle:hover {
    border-color: var(--bs-primary);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.pm-shot .create-group-insights-toggle:hover {
    border-color: var(--brand-primary);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.pm-shot .create-worksheet-toggle i {
    font-size: 1.5rem;
    color: var(--bs-primary);
    margin-bottom: 0.25rem;
    transition: transform 0.3s ease;
}

.pm-shot .create-group-insights-toggle i {
    font-size: 1.5rem;
    color: var(--brand-primary);
    margin-bottom: 0.25rem;
    transition: transform 0.3s ease;
}

.pm-shot .create-worksheet-toggle span,
.pm-shot .create-group-insights-toggle span {
    font-weight: 600;
    font-size: 0.95rem;
}

.pm-shot .create-worksheet-toggle small,
.pm-shot .create-group-insights-toggle small {
    font-size: 0.75rem;
    color: #6c757d;
}

.pm-shot .form-check-input:checked ~ .form-check-label .create-worksheet-toggle {
    background: linear-gradient(135deg, #e8f0fe 0%, #d2e3fc 100%);
    border-color: var(--bs-primary);
    color: var(--bs-primary);
}

.pm-shot .form-check-input:checked ~ .form-check-label .create-worksheet-toggle i {
    transform: scale(1.15);
    color: var(--bs-primary);
}

.pm-shot .form-check-input:checked ~ .form-check-label .create-group-insights-toggle {
    background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%);
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

.pm-shot .form-check-input:checked ~ .form-check-label .create-group-insights-toggle i {
    transform: scale(1.15);
    color: var(--brand-primary);
}

/* ── Placeholder cards (empty tiers) ── */
.pm-shot .gray-placeholder-card {
    background: #f8f9fa;
    border: 1px dashed #dee2e6;
    border-radius: 1rem;
    min-height: 80px;
    transition: border-color 0.3s ease;
}

.pm-shot .gray-placeholder-card:hover {
    border-color: #adb5bd;
}

/* ── Stats summary cards ── */
/* ── Motivational subtitle ── */
.pm-shot .insights-motivation {
    animation: fadeSlideUp 0.6s ease-out 0.2s both;
    font-size: 0.9rem;
    letter-spacing: 0.01em;
}

/* ── Progression hint pill ── */

@keyframes pillSlideIn {
    from { opacity: 0; transform: translateX(-8px); }
    to { opacity: 1; transform: translateX(0); }
}

/* ── Modal celebration (confetti burst) ── */
.pm-shot .modal-celebration {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 10;
}

.pm-shot .confetti-piece {
    position: absolute;
    top: -10px;
    width: 8px;
    height: 8px;
    opacity: 0;
    animation: confettiFall 1.8s ease-out forwards;
}

.pm-shot .confetti-piece:nth-child(odd) {
    border-radius: 50%;
}

.pm-shot .confetti-piece:nth-child(even) {
    border-radius: 2px;
    transform: rotate(45deg);
}

@keyframes confettiFall {
    0% { opacity: 1; transform: translateY(0) rotate(0deg) scale(1); }
    50% { opacity: 1; }
    100% { opacity: 0; transform: translateY(280px) rotate(720deg) scale(0.4); }
}

/* ── Accordion icons (modal) ── */
.pm-shot .accordion-icon {
    font-size: 0.9rem;
    opacity: 0.7;
}

/* ── Streak badge on cards ── */
.pm-shot .streak-badge {
    background: linear-gradient(135deg, #ff6b00, #ff9500);
    color: white;
}

/* ── Topic indicator filter buttons ── */
.pm-shot .topic-filter-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.65rem;
    border-radius: 1rem;
    font-size: 0.78rem;
    font-weight: 600;
    border: 1.5px solid #dee2e6;
    background: white;
    color: #6c757d;
    transition: all 0.2s ease;
    cursor: pointer;
}

.pm-shot .topic-filter-btn:hover {
    border-color: #adb5bd;
    color: #495057;
    background: #f8f9fa;
}

.pm-shot .topic-filter-btn i {
    font-size: 0.9rem;
}

/* ── Levels row: the tier spotlight, seen from the filters card ──
   Picked tiers take their own color; when a subset is picked the rest step back. None or
   all four picked looks normal, on the row and on the board. */
.pm-shot .tier-filter {
    display: flex;
    justify-content: center;
    padding-top: 0.6rem;
    margin-top: 0.6rem;
    border-top: 1px solid var(--bs-border-color-translucent);
}

.pm-shot .tier-filter-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color);
    margin-right: 0.15rem;
}

/* Off: an outlined pill. On: solid in its tier color, the same chip the summary's legend
   uses, so on and off cannot be confused — and a picked tier looks picked even when all
   four are (only the board's dimming depends on whether the spotlight is doing anything).
   The mobile board's tabs are the same chip. */
.pm-shot .tier-tab,
.pm-shot .tier-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.7rem;
    border-radius: 1rem;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.2;
    border: 1.5px solid #dee2e6;
    background: #fff;
    color: #6c757d;
    cursor: pointer;
    transition-property: background-color, border-color, color, opacity, box-shadow;
    transition-duration: 0.15s;
}

.pm-shot .tier-tab:hover,
.pm-shot .tier-toggle:hover {
    border-color: #adb5bd;
    color: #495057;
}

.pm-shot .tier-tab:focus-visible,
.pm-shot .tier-toggle:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

.pm-shot .tier-tab.is-selected,
.pm-shot .tier-toggle.is-selected {
    color: #fff;
    border-color: transparent;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}

.pm-shot .tier-tab.is-selected[data-tier="beginner"],
.pm-shot .tier-toggle.is-selected[data-tier="beginner"] { background-color: var(--tier-beginner); }
.pm-shot .tier-tab.is-selected[data-tier="intermediate"],
.pm-shot .tier-toggle.is-selected[data-tier="intermediate"] { background-color: var(--tier-intermediate); }
.pm-shot .tier-tab.is-selected[data-tier="advanced"],
.pm-shot .tier-toggle.is-selected[data-tier="advanced"] { background-color: var(--tier-advanced); }
.pm-shot .tier-tab.is-selected[data-tier="mastery"],
.pm-shot .tier-toggle.is-selected[data-tier="mastery"] { background: var(--tier-mastery-gradient); }

.pm-shot .tier-toggle.is-muted,
.pm-shot .ih-legend-item.is-muted {
    opacity: 0.45;
}

.pm-shot .topic-filter-btn.active[data-filter="trend-up"] {
    background-color: rgba(40, 167, 69, 0.1);
    border-color: #28a745;
    color: #28a745;
}

.pm-shot .topic-filter-btn.active[data-filter="trend-down"] {
    background-color: rgba(220, 53, 69, 0.1);
    border-color: #dc3545;
    color: #dc3545;
}

.pm-shot .topic-filter-btn.active[data-filter="speed-slow"] {
    background-color: var(--tier-intermediate-soft);
    border-color: var(--tier-intermediate);
    color: var(--tier-intermediate-text);
}

.pm-shot .topic-filter-btn.active[data-filter="speed-fast"] {
    background-color: rgba(25, 135, 84, 0.1);
    border-color: #198754;
    color: #198754;
}

/* ── Topic search (inside filters card) ── */
.pm-shot .topic-search-input {
    width: 200px;
    flex-shrink: 0;
}

.pm-shot #topic-search-container {
    border-top: 1px solid #eee;
    padding-top: 0.75rem;
}

.pm-shot #topic-search-container .form-control {
    border-radius: 0 0.5rem 0.5rem 0;
    border-color: #dee2e6;
}

.pm-shot #topic-search-container .form-control:focus {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 0.15rem rgba(var(--bs-primary-rgb), 0.15);
}

.pm-shot #topic-search-container .input-group-text {
    border-radius: 0.5rem 0 0 0.5rem;
    border-color: #dee2e6;
}

/* ── Next Steps guidance card (modal) ── */
.pm-shot .next-steps-card {
    background: linear-gradient(135deg, #f0f7ff, #e8f4fd);
    border: 1px solid rgba(var(--bs-primary-rgb), 0.15);
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    animation: fadeSlideUp 0.5s ease-out 0.3s both;
}

.pm-shot .next-steps-card .next-steps-title {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--bs-primary);
    margin-bottom: 0.25rem;
}

.pm-shot .next-steps-card .next-steps-text {
    font-size: 0.9rem;
    color: #495057;
    margin: 0 0 0.15rem;
}

.pm-shot .next-steps-card .next-steps-text:last-child {
    margin-bottom: 0;
}

/* ── Clear filters button ── */
.pm-shot .clear-filters-btn {
    font-size: 0.75rem;
    color: var(--bs-secondary);
    text-decoration: none;
    transition: color 0.2s ease;
    cursor: pointer;
    border: none;
    background: none;
    padding: 0;
}

.pm-shot .clear-filters-btn:hover {
    color: var(--bs-danger);
    text-decoration: underline;
}

/* ── Tier count badge ── */
.pm-shot .tier-count {
    font-weight: 600;
    font-size: 0.75rem !important;
    transition: background-color 0.3s ease, color 0.3s ease;
}

.pm-shot .tier-title:hover .tier-count {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-emphasis-color);
}

/* ── Mode indicator pulse ── */
.pm-shot .group-insights-mode-indicator.show,
.pm-shot .worksheet-mode-indicator.show {
    animation: pulseIndicator 2s ease-in-out 3;
}

@keyframes pulseIndicator {
    0%, 100% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); }
    50% { box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); }
}

/* ── Page title animation ── */
.pm-shot #insights-title {
    animation: titleFadeIn 0.6s ease-out;
}

@keyframes titleFadeIn {
    from { opacity: 0; transform: translateX(-15px); }
    to { opacity: 1; transform: translateX(0); }
}

/* ── Filters card ── */
/* Sits directly above the board it filters and scrolls away with it. It used to stick on
   wide screens; with a ~200-card board it covered too much of what you had scrolled to. */
.pm-shot .filters-card {
    background: var(--bs-body-bg);
    border-radius: 1rem;
    box-shadow:
        0 0 0 1px rgba(0, 0, 0, 0.05),
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 6px 16px -8px rgba(0, 0, 0, 0.08),
        0 16px 40px -20px rgba(0, 0, 0, 0.1);
    position: relative;
    overflow: hidden;
}

.pm-shot .filters-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--tier-accent-strip);
}

.pm-shot .filters-card:hover {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}

.pm-shot .filters-card-body {
    padding: 0.9rem 1.25rem;
}

.pm-shot .filters-card-body .row {
    row-gap: 0.75rem;
}

.pm-shot .filters-card-body .form-label {
    margin-bottom: 0.4rem;
}

.pm-shot .filters-card .form-select {
    border-radius: 0.5rem;
    border-color: #dee2e6;
    padding: 0.5rem 0.75rem;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.pm-shot .filters-card .form-select:focus {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 0.15rem rgba(var(--bs-primary-rgb), 0.15);
}

.pm-shot .filters-card .form-label i {
    font-size: 0.75rem;
}

/* ── Smooth transition for container ── */
.pm-shot .container-lg {
    animation: containerFadeIn 0.5s ease-out;
}

@keyframes containerFadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ── Dashboard button hover ── */
.pm-shot #btn-dashboard {
    transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.pm-shot #btn-dashboard:active {
    transform: scale(0.97);
}

/* ── Progress bar animation inside cards ── */
.pm-shot .tier-card .progress-bar {
    transition: width 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
    animation: progressGrow 0.8s ease-out;
}

@keyframes progressGrow {
    from { width: 0 !important; }
}

/* ── Card visual indicators (trend, staleness, speed risk) ── */
/* Indicators and the "n pts to <tier>" pill share one centered row under the progress
   bar. They used to be pinned to the card corner, where they overlapped the bar. */
.pm-shot .card-status-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    min-height: var(--card-pill-height);
}

/* Every pill on a card — indicator chips and the "n more correct" hint — is one shape
   and one size. They sit side by side in the status row, so any difference between them
   reads as a mistake rather than a distinction. */
.pm-shot .card-indicator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: var(--card-pill-height);
    height: var(--card-pill-height);
    /* Tight on purpose: three chips ("was 2/16", "2/5 hard", "77% slower") should share a
       row on a normal card. Chips are not in a column, so proportional figures are fine. */
    padding: 0 0.45rem;
    border-radius: 50px;
    font-size: var(--card-pill-font);
    font-weight: 700;
    white-space: nowrap;
    line-height: 1;
    color: #3a3f47;
    background-color: #fff;
    animation: indicatorPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.3s both;
    pointer-events: auto;
    cursor: default;
}

/* The focus card's one chip: what fixing the topic is worth, in the card's own color. */
.pm-shot .worth-indicator {
    background-color: #fff;
    color: var(--tier-bg);
}

.pm-shot .mastery-card .worth-indicator { color: var(--tier-mastery-text); }

/* Direction is the one thing the icon can't fully carry, so up and down keep a tint —
   on the glyph only, which reads clearly on the translucent plate without adding a
   second block of color to the card. */
/* One ink per kind of signal, so a glance tells them apart. White reads on every tier
   color; a solid green chip would vanish on a green card. */
.pm-shot .trend-indicator.trend-up { color: var(--tier-advanced-text); }
.pm-shot .trend-indicator.trend-down { color: var(--tier-beginner-text); }
.pm-shot .difficulty-indicator { color: var(--tier-intermediate-text); }
.pm-shot .speed-indicator { color: var(--signal-pace); }
.pm-shot .staleness-indicator { color: var(--signal-stale); }

/* Icons scale with their pill instead of each carrying a hardcoded size. */
.pm-shot .card-indicator i,
.pm-shot .streak-badge i,
.pm-shot .perfect-score-badge i,
.pm-shot .low-data-badge i {
    display: flex;
    font-size: 1.05em;
}





@keyframes indicatorPop {
    0% { transform: scale(0); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
}

.pm-shot .card-status-row .card-indicator:nth-child(2) { animation-delay: 0.4s; }
.pm-shot .card-status-row .card-indicator:nth-child(3) { animation-delay: 0.5s; }

/* ── Responsive adjustments ── */
@media (max-width: 576px) {
    .pm-shot .create-worksheet-toggle,
.pm-shot .create-group-insights-toggle {
        padding: 0.5rem;
        min-width: auto;
    }
    .pm-shot .create-worksheet-toggle i,
.pm-shot .create-group-insights-toggle i { font-size: 1rem; }
    .pm-shot .create-worksheet-toggle span,
.pm-shot .create-group-insights-toggle span { font-size: 0.85rem; }
    .pm-shot .create-worksheet-toggle small,
.pm-shot .create-group-insights-toggle small { font-size: 0.7rem; }

    /* One step down for the whole card scale, rather than per-element overrides. */
    .pm-shot .tier-card {
        --card-title-font: 1rem;
        --card-count-font: 0.72rem;
        --card-pill-font: 0.64rem;
        --card-pill-height: 19px;
        --card-badge-height: 18px;
    }

    .pm-shot .topic-search-input { width: 100%; }
    .pm-shot .topic-filter-btn { font-size: 0.72rem; padding: 0.2rem 0.5rem; }
}

/* ── The "still being placed" group ──
   The guesses live together at the foot of their column, behind a disclosure a student can shut.
   A native <details>, so the keyboard and a screen reader get it for free. */
.pm-shot .provisional-group {
    width: 100%;
    margin-top: 0.3rem;
}

.pm-shot .provisional-summary {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.6rem;
    border-radius: 0.6rem;
    cursor: pointer;
    list-style: none;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
    /* Dashed, like the cards it holds, so the two read as one idea. */
    border: 1px dashed var(--bs-border-color);
}

/* Safari draws its own marker on top of ours. */
.pm-shot .provisional-summary::-webkit-details-marker { display: none; }

.pm-shot .provisional-summary:hover {
    background: var(--bs-secondary-bg);
    color: var(--bs-body-color);
}

.pm-shot .provisional-summary:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

.pm-shot .provisional-summary b { color: var(--bs-body-color); }

.pm-shot .provisional-chevron {
    margin-left: auto;
    font-size: 0.9em;
    transition: transform 0.15s ease;
}

.pm-shot .provisional-group[open] .provisional-chevron { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
    .pm-shot .provisional-chevron { transition: none; }
}

/* Same stack as the column itself, so a folded-out group looks like more of the column. */
.pm-shot .provisional-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 0.9rem;
    justify-content: center;
    margin-top: 0.9rem;
}

/* ── Low-data topics (fewer than 3 questions seen) ── */
/* These cards are a GUESS. The board still shows them, because a topic a student has met once
   is worth knowing about, but the color is a placement we cannot stand behind yet — two lucky
   answers land a card in Mastery.
   A dashed ring alone did not say that: it is 2px of detail on a card whose color is shouting
   the opposite, and in practice nobody noticed it. So the color itself steps back — most of
   the saturation drains out and the card flattens against the board — and the ring and badge
   explain why. Gray enough to read as "not settled", not so gray that the tier is lost. */
.pm-shot .low-data-card {
    filter: grayscale(0.72);
    opacity: 0.72;
    outline: 2px dashed color-mix(in srgb, var(--tier-bg) 70%, transparent);
    outline-offset: 2px;
    /* Flat: a confident card sits on the page with its own colored shadow, this one does not. */
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

/* Reading one brings it back to full color, because by then the badge has explained itself. */
.pm-shot .low-data-card:hover,
.pm-shot .low-data-card:focus-visible {
    filter: grayscale(0.25);
    opacity: 0.95;
}

@media (prefers-reduced-motion: no-preference) {
    .pm-shot .low-data-card {
        transition: filter 0.2s ease, opacity 0.2s ease;
    }
}

/* The badge is the explanation, so it reads as a label rather than another chip. */
.pm-shot .low-data-badge {
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    /* Undo the card's own desaturation so the one element explaining the gray stays legible. */
    filter: grayscale(0);
}
/* ── Modal accordions ── */
.pm-shot .insights-accordion {
    border: 1px solid var(--bs-border-color);
    border-radius: 0.85rem;
    overflow: hidden;
}

.pm-shot .insights-accordion + .insights-accordion {
    margin-top: 0.6rem;
}

/* The panels sit under the "Next steps" note and above the practice call to action; without
   this they butt against both. */
.pm-shot .insights-accordion:first-of-type {
    margin-top: 0.9rem;
}

.pm-shot .insights-accordion:last-of-type {
    margin-bottom: 0.9rem;
}

.pm-shot .insights-accordion-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.8rem 1rem;
    border: 0;
    background-color: var(--bs-body-bg);
    text-align: left;
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.pm-shot .insights-accordion-head:hover,
.pm-shot .insights-accordion-head:focus-visible {
    background-color: var(--bs-secondary-bg);
}

.pm-shot .insights-accordion-head .accordion-icon {
    display: flex;
    font-size: 1rem;
    color: var(--bs-primary);
}

.pm-shot .insights-accordion-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.pm-shot .insights-accordion-text b {
    font-size: 0.95rem;
}

.pm-shot .insights-accordion-text small {
    font-size: 0.76rem;
    color: var(--bs-secondary-color);
}

.pm-shot .insights-accordion-chevron {
    display: flex;
    color: var(--bs-secondary-color);
    transition: transform 0.2s ease;
}

.pm-shot .insights-accordion-head[aria-expanded="true"] .insights-accordion-chevron {
    transform: rotate(180deg);
}

/* ── Question-by-question breakdown ── */
.pm-shot #detailedCalculations {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
}

.pm-shot .qb-item {
    border: 1px solid var(--bs-border-color);
    border-left: 4px solid var(--bs-secondary);
    border-radius: 0.7rem;
    overflow: hidden;
    background-color: var(--bs-body-bg);
}

.pm-shot .qb-item-correct { border-left-color: var(--bs-success); }
.pm-shot .qb-item-incorrect { border-left-color: var(--bs-danger); }

.pm-shot .qb-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.8rem;
    background-color: var(--bs-secondary-bg);
}

.pm-shot .qb-index {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    font-size: 0.75rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pm-shot .qb-status {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    font-weight: 700;
}

.pm-shot .qb-item-correct .qb-status { color: var(--bs-success-text-emphasis); }
.pm-shot .qb-item-incorrect .qb-status { color: var(--bs-danger-text-emphasis); }

.pm-shot .qb-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-left: auto;
}

.pm-shot .qb-fact {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: 50px;
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    color: var(--bs-secondary-color);
}

.pm-shot .qb-fact i { display: flex; font-size: 0.8em; }
.pm-shot .qb-fact-hard { color: var(--bs-purple); border-color: rgba(111, 66, 193, 0.35); }
.pm-shot .qb-fact-fast { color: var(--bs-blue); border-color: rgba(13, 110, 253, 0.35); }
.pm-shot .qb-fact-slow { color: #9a6200; border-color: rgba(255, 165, 0, 0.45); }

.pm-shot .qb-link {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.75rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--bs-primary);
    white-space: nowrap;
}

.pm-shot .qb-link:hover { text-decoration: underline; }
.pm-shot .qb-link i { display: flex; font-size: 0.75em; }

.pm-shot .qb-body {
    padding: 0.9rem 1rem;
}

.pm-shot .qb-body-empty {
    display: flex;
    align-items: center;
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}

.pm-shot .qb-body ol[type="A"] {
    margin-bottom: 0;
    padding-left: 1.4rem;
}

/* ── Asides: earlier hard questions, best run ── */
.pm-shot .qb-aside {
    border: 1px dashed var(--bs-border-color);
    border-radius: 0.7rem;
    padding: 0.75rem 0.9rem;
    background-color: var(--bs-tertiary-bg);
}

.pm-shot .qb-aside-head {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.9rem;
}

.pm-shot .qb-aside-head i { display: flex; color: var(--bs-secondary-color); }

.pm-shot .qb-aside-score {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pm-shot .qb-aside-note {
    margin: 0.4rem 0 0;
    font-size: 0.76rem;
    color: var(--bs-secondary-color);
}

.pm-shot .qb-run.is-hot {
    border-style: solid;
    border-color: rgba(255, 140, 0, 0.4);
    background-color: rgba(255, 165, 0, 0.08);
}

.pm-shot .qb-run.is-hot .qb-aside-head i { color: var(--bs-orange); }

/* ── Level info modal ──
   Per-tier accent, set once so the hero, the marked scale row and the icon all agree. */
.pm-shot .level-modal { --level-accent: var(--bs-secondary); --level-soft: var(--bs-secondary-bg); }
.pm-shot .level-modal-beginner { --level-accent: var(--tier-beginner-text); --level-soft: var(--tier-beginner-soft); }
.pm-shot .level-modal-intermediate { --level-accent: var(--tier-intermediate-text); --level-soft: var(--tier-intermediate-soft); }
.pm-shot .level-modal-advanced { --level-accent: var(--tier-advanced-text); --level-soft: var(--tier-advanced-soft); }
.pm-shot .level-modal-mastery { --level-accent: var(--tier-mastery-text); --level-soft: var(--tier-mastery-soft); }

.pm-shot .level-hero {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 1rem 1.1rem;
    border-radius: 0.9rem;
    background-color: var(--level-soft);
    border: 1px solid var(--level-accent);
}

.pm-shot .level-hero-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    background-color: var(--level-accent);
    color: #fff;
    font-size: 1.3rem;
}

.pm-shot .level-hero-icon i { display: flex; }

.pm-shot .level-hero-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.pm-shot .level-hero-band {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--level-accent);
    font-variant-numeric: tabular-nums;
}

.pm-shot .level-hero-meaning {
    margin: 0;
    font-size: 0.9rem;
    color: var(--bs-body-color);
}

.pm-shot .level-advice {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0.85rem 0;
    font-size: 0.86rem;
    color: var(--bs-body-color);
}

.pm-shot .level-advice i {
    display: flex;
    margin-top: 0.15rem;
    color: var(--bs-warning);
}

/* The whole scale, so the reader sees where this tier sits */
.pm-shot .level-scale {
    list-style: none;
    margin: 0 0 1rem;
    padding: 0.35rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.75rem;
}

.pm-shot .level-scale-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.55rem;
    border-radius: 0.5rem;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}

.pm-shot .level-scale-row.is-current {
    background-color: var(--level-soft);
    color: var(--bs-body-color);
    font-weight: 700;
}

.pm-shot .level-scale-swatch {
    flex: 0 0 auto;
    width: 0.85rem;
    height: 0.85rem;
    border-radius: 0.25rem;
    background-color: currentcolor;
    opacity: 0.35;
}

.pm-shot .level-scale-row.is-current .level-scale-swatch { opacity: 1; }
.pm-shot .level-scale-row.level-beginner .level-scale-swatch { background-color: var(--tier-beginner); }
.pm-shot .level-scale-row.level-intermediate .level-scale-swatch { background-color: var(--tier-intermediate); }
.pm-shot .level-scale-row.level-advanced .level-scale-swatch { background-color: var(--tier-advanced); }
.pm-shot .level-scale-row.level-mastery .level-scale-swatch { background: var(--tier-mastery-gradient); }

.pm-shot .level-scale-name { flex: 1 1 auto; }

.pm-shot .level-scale-band {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.pm-shot .level-facts {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.pm-shot .level-facts li {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
}

.pm-shot .level-facts i {
    flex: 0 0 auto;
    display: flex;
    margin-top: 0.2rem;
    color: var(--level-accent);
}

.pm-shot .level-facts div {
    display: flex;
    flex-direction: column;
    line-height: 1.4;
}

.pm-shot .level-facts b { font-size: 0.86rem; }

.pm-shot .level-facts span {
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}


/* ── The question you clicked ──
   A fill is invisible here: .qb-item paints its own header and body over it. Ring the card
   instead, pulse once so the eye catches the jump, then settle. */
.pm-shot .qb-item.highlight,
.pm-shot .qb-aside.highlight {
    background-color: var(--bs-body-bg);
    border-color: var(--bs-primary);
    border-style: solid;
    box-shadow: 0 0 0 3px var(--bs-primary-bg-subtle);
    animation: qbHighlightPulse 0.9s ease-out;
}

.pm-shot .qb-item.highlight .qb-head {
    background-color: var(--bs-primary-bg-subtle);
}

.pm-shot .qb-item.highlight .qb-index {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
    color: #fff;
}

@keyframes qbHighlightPulse {
    0% { box-shadow: 0 0 0 0 rgba(13, 110, 253, 0.5); }
    45% { box-shadow: 0 0 0 8px rgba(13, 110, 253, 0.18); }
    100% { box-shadow: 0 0 0 3px var(--bs-primary-bg-subtle); }
}

@media (prefers-reduced-motion: reduce) {
    .pm-shot .qb-item.highlight,
.pm-shot .qb-aside.highlight {
        animation: none;
    }
}

/* The attempt squares are the thing you click to get here. */
.pm-shot .attempt-square[role="button"] {
    cursor: pointer;
}

.pm-shot .attempt-square:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}


/* ── Icons inside the modal's flex rows ──
   Bootstrap Icons carry `vertical-align: -.125em` on ::before, so in a flex row the <i>
   box is taller than the glyph and the icon sits low. display:flex collapses the box to
   the glyph so align-items:center actually centers it. Inline icons keep the default. */
.pm-shot .qb-status i,
.pm-shot .qb-body-empty i,
.pm-shot .qh-mark i,
.pm-shot .signal-label i {
    display: flex;
}

/* ── Hard questions from earlier tests ── */
.pm-shot .qh-block .qb-aside-score.is-good {
    color: var(--bs-success-text-emphasis);
}

.pm-shot .qh-list {
    list-style: none;
    margin: 0.7rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.pm-shot .qh-row {
    border: 1px solid var(--bs-border-color);
    border-left: 3px solid var(--bs-secondary);
    border-radius: 0.55rem;
    background-color: var(--bs-body-bg);
    overflow: hidden;
}

.pm-shot .qh-row.is-correct { border-left-color: var(--bs-success); }
.pm-shot .qh-row.is-incorrect { border-left-color: var(--bs-danger); }

/* The row is the disclosure control for the question inside it. */
.pm-shot .qh-summary {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.45rem 0.6rem;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.pm-shot .qh-summary:hover,
.pm-shot .qh-summary:focus-visible {
    background-color: var(--bs-secondary-bg);
}

.pm-shot .qh-chevron {
    flex: 0 0 auto;
    color: var(--bs-secondary-color);
    transition: transform 0.2s ease;
}

.pm-shot .qh-summary[aria-expanded="true"] .qh-chevron {
    transform: rotate(180deg);
}

.pm-shot .qh-mark {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 50%;
    font-size: 0.8rem;
}

.pm-shot .qh-row.is-correct .qh-mark { background-color: var(--bs-success-bg-subtle); color: var(--bs-success-text-emphasis); }
.pm-shot .qh-row.is-incorrect .qh-mark { background-color: var(--bs-danger-bg-subtle); color: var(--bs-danger-text-emphasis); }

.pm-shot .qh-where {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.pm-shot .qh-where b {
    font-size: 0.82rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pm-shot .qh-where small {
    font-size: 0.72rem;
    color: var(--bs-secondary-color);
}

.pm-shot .qh-verdict {
    flex: 0 0 auto;
    font-size: 0.75rem;
    font-weight: 700;
    white-space: nowrap;
}

.pm-shot .qh-row.is-correct .qh-verdict { color: var(--bs-success-text-emphasis); }
.pm-shot .qh-row.is-incorrect .qh-verdict { color: var(--bs-danger-text-emphasis); }

.pm-shot .qh-detail {
    border-top: 1px solid var(--bs-border-color);
    background-color: var(--bs-body-bg);
}

.pm-shot .qh-detail-foot {
    padding: 0 1rem 0.9rem;
}

@media (max-width: 576px) {
    .pm-shot .qh-verdict { display: none; }
}

/* ── "Since your last test" ──
   The reward for practicing, earned by real work rather than by opening the page. */
.pm-shot .progress-strip {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 1rem 1.1rem;
    background: linear-gradient(135deg, var(--bs-success-bg-subtle) 0%, transparent 70%);
}

.pm-shot .focus-seen-note {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0.35rem 0 0;
    font-size: 0.76rem;
    color: var(--bs-secondary-color);
}

.pm-shot .practice-note {
    display: flex;
    /* The note is one line at almost every width, and flex-start left the icon riding above
       the text. Center it, and let the icon hold its own size rather than being stretched. */
    align-items: center;
    gap: 0.4rem;
    margin: 0.6rem 0 0;
    font-size: 0.78rem;
    line-height: 1.35;
    color: var(--bs-secondary-color);
}

.pm-shot .practice-note i {
    flex: 0 0 auto;
    font-size: 0.9rem;
}

/* A change worth explaining, announced on the button rather than across the board. */
.pm-shot #show-whats-new.has-news {
    position: relative;
}

.pm-shot #show-whats-new.has-news::after {
    content: "";
    position: absolute;
    top: 4px;
    right: 4px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: var(--bs-primary);
}

/* ── "What's new": the worked example, and what changed on this student's board ── */
/* The worked example. A rule stated is a rule argued with; a rule shown on a case the student
   recognizes is a rule understood. */
.pm-shot .whats-new-example {
    margin: 0.75rem 0 0.8rem;
    padding: 0.7rem 0.85rem;
    border-left: 3px solid var(--bs-primary-border-subtle);
    border-radius: 0 0.5rem 0.5rem 0;
    background-color: var(--bs-tertiary-bg);
    font-size: 0.85rem;
}

.pm-shot .wn-eg-label {
    display: block;
    margin-bottom: 0.15rem;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color);
}

.pm-shot .wn-inline-trail {
    padding: 0.05rem 0.35rem;
    border-radius: 50px;
    background-color: var(--bs-tertiary-bg);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pm-shot .whats-new-diff {
    margin: 0.9rem 0;
    padding: 0.85rem 1rem;
    border-radius: 0.85rem;
    background-color: var(--bs-tertiary-bg);
}

.pm-shot .whats-new-diff-head {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0 0 0.6rem;
    font-size: 0.85rem;
}

.pm-shot .whats-new-diff-head i {
    color: var(--bs-secondary-color);
}

.pm-shot .whats-new-diff-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
}

.pm-shot .whats-new-diff-table th,
.pm-shot .whats-new-diff-table td {
    padding: 0.55rem 0.75rem 0.55rem 0;
    text-align: left;
    vertical-align: middle;
}

.pm-shot .whats-new-diff-table thead th {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
    border-bottom: 1px solid var(--bs-border-color-translucent);
}

.pm-shot .whats-new-diff-table tbody th {
    font-weight: 700;
}

.pm-shot .whats-new-diff-table tbody td {
    white-space: nowrap;
}

/* The gap lives here rather than on the cell, so a band can never sit flush against the
   figure beside it without breaking the table's own layout. */
.pm-shot .whats-new-diff-table tbody td .wn-frac {
    display: inline-block;
    margin-right: 0.55rem;
}

.pm-shot .whats-new-diff-table tbody tr + tr th,
.pm-shot .whats-new-diff-table tbody tr + tr td {
    border-top: 1px solid var(--bs-border-color-translucent);
}

/* A row whose level actually moved is the one a student is looking for. */
.pm-shot .whats-new-diff-table tr.is-moved th,
.pm-shot .whats-new-diff-table tr.is-moved td {
    background-color: var(--bs-body-bg);
}

.pm-shot .wn-frac {
    min-width: 2.75rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color);
}

.pm-shot .whats-new-diff-table .wn-band {
    vertical-align: middle;
}

.pm-shot .whats-new-diff-rest {
    margin: 0.6rem 0 0;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

/* ── The filters, folded ──
   Expanded they ran six rows deep and pushed the board below the fold, so you could not see
   what a filter did to the thing it filtered. The bar is what is left when they are closed. */
.pm-shot .filters-bar {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.75rem 1.1rem;
    border: 0;
    border-radius: 1rem;
    background-color: transparent;
    color: var(--bs-body-color);
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
}

.pm-shot .filters-bar > i {
    color: var(--bs-secondary-color);
}

.pm-shot .filters-bar-summary {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--bs-secondary-color);
}

/* A filter that is on and out of sight is how someone ends up thinking they lost their work. */
.pm-shot .filters-bar.has-filters > i,
.pm-shot .filters-bar.has-filters .filters-bar-summary {
    color: var(--bs-primary);
    font-weight: 600;
}

.pm-shot .filters-bar-action {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 0 0 auto;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
}

.pm-shot .filters-bar[aria-expanded="true"] .filters-bar-action i {
    transform: rotate(180deg);
}

.pm-shot .filters-bar-action i {
    transition: transform 0.2s ease;
}

.pm-shot .filters-bar:hover .filters-bar-action,
.pm-shot .filters-bar:focus-visible .filters-bar-action {
    color: var(--bs-primary);
}

.pm-shot .filters-bar:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: -3px;
}

/* ── The area filter ──
   A listbox tells you what is chosen only while the highlighted rows are in view, which is a
   scroll away the moment there are more areas than fit. The chips say it plainly and give a
   one-click way out, which ctrl-clicking exactly the right row is not. */
.pm-shot #tagFilter[multiple] {
    padding: 0.25rem;
    background-image: none;
}

.pm-shot #tagFilter[multiple] option {
    padding: 0.3rem 0.5rem;
    border-radius: 0.4rem;
    text-transform: none;
    color: var(--bs-body-color);
}

.pm-shot #tagFilter[multiple] option.is-branch {
    font-weight: 700;
    margin-top: 0.15rem;
}

.pm-shot .area-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.45rem;
}

.pm-shot .area-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.5rem 0.2rem 0.65rem;
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 50px;
    background-color: var(--bs-primary-bg-subtle);
    color: var(--bs-primary-text-emphasis);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    transition-property: background-color, border-color;
    transition-duration: 0.15s;
}

.pm-shot .area-chip i {
    font-size: 0.95em;
    opacity: 0.7;
}

.pm-shot .area-chip:hover,
.pm-shot .area-chip:focus-visible {
    border-color: var(--bs-primary);
    background-color: var(--bs-primary);
    color: #fff;
}

.pm-shot .area-chip:hover i,
.pm-shot .area-chip:focus-visible i {
    opacity: 1;
}

/* ── Which sittings the board is built from ──
   A segmented control rather than a dropdown: three options, one of which is the default and
   the other two of which change what the numbers mean, so all three should be readable at a
   glance instead of hidden behind a click. */
.pm-shot .scope-switch {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.25rem;
    margin: 0.9rem auto 0;
    padding: 0.25rem;
    border-radius: 50px;
    background-color: var(--bs-tertiary-bg);
    width: fit-content;
    max-width: 100%;
}

.pm-shot .scope-option {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.85rem;
    border: 0;
    border-radius: 50px;
    background-color: transparent;
    color: var(--bs-secondary-color);
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition-property: background-color, color, box-shadow;
    transition-duration: 0.15s;
}

.pm-shot .scope-option i {
    font-size: 0.95em;
}

.pm-shot .scope-option:hover:not(.is-selected) {
    color: var(--bs-body-color);
}

.pm-shot .scope-option.is-selected {
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 4px 10px -6px rgba(0, 0, 0, 0.15);
}

.pm-shot .scope-option:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

/* What the chosen lens means. Only present when the answer is not the obvious one, so it
   reads as a caveat worth reading rather than permanent furniture. */
.pm-shot .scope-note {
    max-width: 44rem;
    margin: 0.5rem auto 0;
    text-align: center;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

/* ── The radar ──
   A student's shape across subject areas. Sits in the header as its own region so it reads as
   an overview of the board below rather than another card in it. */
.pm-shot .ih-radar {
    padding: 0.9rem 1.1rem 1.1rem;
    border-top: 1px solid var(--bs-border-color-translucent);
}

.pm-shot .radar-head {
    margin-bottom: 0.5rem;
}

.pm-shot .radar-title {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0;
    font-size: 0.95rem;
    font-weight: 700;
}

.pm-shot .radar-title i {
    color: var(--bs-secondary-color);
    font-size: 0.95rem;
}

.pm-shot .radar-sub {
    margin: 0.2rem 0 0;
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}

.pm-shot .radar-sub b {
    color: var(--bs-body-color);
}


.pm-shot .radar-canvas {
    position: relative;
    height: clamp(260px, 44vw, 320px);
    max-width: 520px;
    margin: 0 auto;
}

.pm-shot .radar-canvas.is-empty {
    display: flex;
    align-items: center;
    justify-content: center;
}

.pm-shot .radar-empty {
    max-width: 22rem;
    margin: 0;
    text-align: center;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}

/* ── What the level rests on ──
   The test driving it, then the whole record. An arrow trail of every sitting was tried here
   and said neither which tests they were nor what they came to. */
.pm-shot .card-trail {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.2rem 0.4rem;
    margin: 0.45rem 0 0;
    font-size: var(--card-pill-font, 0.72rem);
    color: rgba(255, 255, 255, 0.85);
}

.pm-shot .card-trail b {
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    color: #fff;
}

.pm-shot .trail-latest,
.pm-shot .trail-total {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
}

.pm-shot .trail-sep {
    opacity: 0.5;
}

.pm-shot .card-alltime-fixed {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    color: #fff;
    font-weight: 700;
}

.pm-shot .card-alltime-fixed i {
    font-size: 0.95em;
}

/* ── The practice button ──
   Its base rule sits here because the button appears in two very different places: on a
   tier-colored focus card, where it has to be a translucent white pill, and inside the blue
   .practice-cta banner in the topic modal, which overrides the colors below. Without this
   base the focus-card buttons render as bare browser buttons, and the `d-flex` icon inside
   them breaks onto its own line. */
.pm-shot .practice-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    margin-top: 0.55rem;
    padding: 0.4rem 0.75rem;
    border: 1px solid rgba(255, 255, 255, 0.45);
    border-radius: 50px;
    background-color: rgba(255, 255, 255, 0.18);
    color: #fff;
    font-size: var(--card-pill-font, 0.72rem);
    font-weight: 700;
    line-height: 1.2;
    cursor: pointer;
    transition-property: background-color, border-color;
    transition-duration: 0.18s;
}

.pm-shot .practice-btn i {
    font-size: 1.05em;
}

.pm-shot .practice-btn:hover:not(:disabled),
.pm-shot .practice-btn:focus-visible {
    background-color: rgba(255, 255, 255, 0.32);
    border-color: rgba(255, 255, 255, 0.75);
}

.pm-shot .practice-btn:focus-visible {
    outline: 3px solid #fff;
    outline-offset: 2px;
}

.pm-shot .practice-btn:disabled {
    opacity: 0.6;
    cursor: default;
}

/* The one action for everything in "Where to focus", so it reads as the primary thing here:
   solid white on the section's own background rather than the cards' translucent pill. */
.pm-shot .practice-btn-all {
    margin-top: 0;
    padding: 0.4rem 0.9rem 0.4rem 0.75rem;
    border: 0;
    border-radius: 50px;
    /* The section's own accent rather than flat Bootstrap blue, with the shadow in the same
       color so it reads as the one action here instead of a stray form button. */
    background: linear-gradient(135deg, var(--bs-primary), #4b7bec);
    box-shadow: 0 6px 16px -8px rgba(13, 110, 253, 0.65);
    color: #fff;
    font-size: 0.8rem;
    white-space: nowrap;
}

.pm-shot .practice-btn-all i {
    font-size: 0.95em;
    color: #fff;
}

.pm-shot .practice-btn-all:hover:not(:disabled),
.pm-shot .practice-btn-all:focus-visible {
    filter: brightness(1.06);
    box-shadow: 0 8px 20px -8px rgba(13, 110, 253, 0.75);
}

.pm-shot .practice-btn-all:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

/* Pushes the action to the end of the "Where to focus" heading row. */
.pm-shot .ih-title-action {
    margin-left: auto;
}

/* On a card the button is the card's one action, so it spans it. */
.pm-shot .focus-card .practice-btn,
.pm-shot .practice-btn-block {
    width: 100%;
}

.pm-shot .practice-cta {
    /* A top margin as well as a bottom one: with none, this sits flush against the accordion
       card above it and the two read as one broken box. */
    margin: 0.85rem 0 1rem;
    padding: 1rem;
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 0.85rem;
    background-color: var(--bs-primary-bg-subtle);
}

.pm-shot .practice-cta .practice-btn {
    margin-top: 0;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
    border-color: var(--bs-primary);
    background-color: var(--bs-primary);
    color: #fff;
    backdrop-filter: none;
}

.pm-shot .practice-cta .practice-btn:hover:not(:disabled),
.pm-shot .practice-cta .practice-btn:focus-visible {
    filter: brightness(1.08);
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
}

/* Set by showEmptyState() so the board and its controls step aside for the empty state,
   rather than sitting under it full of placeholders. An attribute, not .d-none, because
   several of these elements toggle .d-none for their own reasons. */
.pm-shot [data-empty-hidden] {
    display: none !important;
}

/* ── Filtered view ──
   A filtered board looks identical to a sparse one, so this has to be hard to miss:
   warning-toned, full width, directly above the board, with one click back. */
.pm-shot .filter-notice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    padding: 0.7rem 1rem;
    border: 1px solid var(--bs-warning-border-subtle);
    border-left: 4px solid var(--bs-warning);
    border-radius: 0.75rem;
    background-color: var(--bs-warning-bg-subtle);
    font-size: 0.86rem;
    color: var(--bs-body-color);
}

.pm-shot .filter-notice > i {
    color: #9a6200;
    font-size: 1rem;
}

.pm-shot .filter-notice-text {
    flex: 1 1 18rem;
    min-width: 0;
}

.pm-shot .filter-notice-clear {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: auto;
    padding: 0.25rem 0.7rem;
    border: 1px solid var(--bs-warning-border-subtle);
    border-radius: 50px;
    background-color: var(--bs-body-bg);
    font-size: 0.8rem;
    font-weight: 600;
    color: #8a6100;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pm-shot .filter-notice-clear:hover,
.pm-shot .filter-notice-clear:focus-visible {
    background-color: #fff;
    border-color: var(--bs-warning);
}


/* ── One header for the whole board ──
   Where you stand, what moved, and what to do next. These were three stacked cards, which
   read as a queue of things to get through before reaching the topics; as regions of one
   block they read as a header. */
.pm-shot .insights-header {
    position: relative;
    border-radius: 1rem;
    background-color: var(--bs-body-bg);
    /* Layered and transparent, so the card sits on any page background without a hard edge. */
    box-shadow:
        0 0 0 1px rgba(0, 0, 0, 0.05),
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 6px 16px -8px rgba(0, 0, 0, 0.08),
        0 16px 40px -20px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    margin-bottom: 1rem;
}

.pm-shot .ih-region + .ih-region {
    border-top: 1px solid var(--bs-border-color-translucent);
}

.pm-shot .ih-collapse {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 0.25rem;
    /* Visually small; padded out to a comfortable target. */
    padding: 0.6rem 0.75rem;
    border: 0;
    background: none;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
    cursor: pointer;
    transition-property: color;
    transition-duration: 0.15s;
}

.pm-shot .ih-collapse:hover,
.pm-shot .ih-collapse:focus-visible {
    color: var(--bs-primary);
}

.pm-shot .ih-collapse i {
    font-size: 0.8rem;
    transition-property: rotate;
    transition-duration: 0.2s;
    transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pm-shot .ih-collapsed .ih-collapse i {
    rotate: 180deg;
}

/* Folded, the summary keeps the four numbers and drops the two detail bands. */
.pm-shot .ih-collapsed #progress-strip,
.pm-shot .ih-collapsed #topic-radar,
.pm-shot .ih-collapsed #focus-panel {
    display: none;
}

/* Three bands: where you stand, what changed, what to do next. The first is context, so it
   sits on a tinted surface and the two actionable bands keep the plain one. */
/* Three bands: where you stand, what changed, what to do next. */
.pm-shot .ih-stats {
    padding: 0.8rem 1.1rem 0.75rem;
    background-color: var(--bs-tertiary-bg);
}

.pm-shot .ih-bar-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    /* The Hide button sits in this corner. */
    padding-right: 5rem;
    margin-bottom: 0.45rem;
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ih-bar-head > span {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
}

.pm-shot .ih-bar-head b {
    font-size: 1.05rem;
    color: var(--bs-body-color);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* The accent strip at the top of the page, made to mean something: this student's topics,
   in the four tier colors, in the tier order. */
.pm-shot .ih-tierbar {
    display: flex;
    height: 0.8rem;
    border-radius: 50px;
    overflow: hidden;
    background-color: var(--bs-secondary-bg);
    transform-origin: left center;
    animation: barIn 0.7s cubic-bezier(0.2, 0, 0, 1) both;
}

@keyframes barIn {
    from { transform: scaleX(0); }
}

.pm-shot .ih-seg {
    flex: 0 1 0;
    min-width: 0.35rem;
}

.pm-shot .ih-seg-beginner { background-color: var(--tier-beginner); }
.pm-shot .ih-seg-intermediate { background-color: var(--tier-intermediate); }
.pm-shot .ih-seg-advanced { background-color: var(--tier-advanced); }
.pm-shot .ih-seg-mastery { background: var(--tier-mastery-gradient); }

.pm-shot .ih-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.55rem;
}

.pm-shot .ih-legend-item {
    border: 0;
    cursor: pointer;
    animation: badge-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
    transition-property: filter, box-shadow;
    transition-duration: 0.15s;
}

.pm-shot .ih-legend-item:nth-child(2) { animation-delay: 0.05s; }
.pm-shot .ih-legend-item:nth-child(3) { animation-delay: 0.1s; }
.pm-shot .ih-legend-item:nth-child(4) { animation-delay: 0.15s; }

.pm-shot .ih-legend-item:hover,
.pm-shot .ih-legend-item:focus-visible {
    filter: brightness(1.08);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}

.pm-shot .ih-legend-item:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

.pm-shot .ih-legend-item.is-empty {
    opacity: 0.45;
}

/* Selected: a ring in the chip's own color, held off the chip by a white gap, and a tick. */
.pm-shot .ih-legend-item.is-selected::before {
    content: "\2713";
    font-size: 0.8em;
    margin-right: 0.1rem;
}

.pm-shot .ih-legend-item.is-selected.wn-band-beginner { box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--tier-beginner); }
.pm-shot .ih-legend-item.is-selected.wn-band-intermediate { box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--tier-intermediate); }
.pm-shot .ih-legend-item.is-selected.wn-band-advanced { box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--tier-advanced); }
.pm-shot .ih-legend-item.is-selected.wn-band-mastery { box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--tier-mastery-deep); }

.pm-shot .ih-unlock {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0.6rem 0 0;
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ih-unlock i { color: var(--tier-advanced); }
.pm-shot .ih-unlock b { color: var(--bs-body-color); }

/* Why some cards are gray, said once under the bar rather than on every card. */
.pm-shot .ih-provisional {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin: 0.4rem 0 0;
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ih-provisional i {
    color: var(--bs-secondary-color);
    margin-top: 0.1rem;
}

.pm-shot .ih-provisional b { color: var(--bs-body-color); }

/* ── Labels on the card's numbers ──
   A card carries several figures and, unlabelled, two of them read identically ("3/5"
   accuracy and "3/5" hard questions). The word is small and lower-contrast so the number
   still leads, but nothing is left to a tooltip a tablet will never show. */
.pm-shot .card-indicator small,
.pm-shot .topic-progress-count small {
    font-size: 0.82em;
    font-weight: 600;
    opacity: 0.75;
}

.pm-shot .card-indicator small {
    margin-left: 0.12rem;
}

.pm-shot .trend-indicator small {
    margin: 0 0.12rem 0 0;
}

.pm-shot .topic-progress-count small {
    font-size: 0.72em;
}

@media (max-width: 400px) {
    /* The words are the first thing to go when a card gets genuinely narrow. */
    .pm-shot .card-indicator small {
        display: none;
    }
}

/* ── Header regions ── */
.pm-shot .ih-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin: 0 0 0.5rem;
    font-size: 0.95rem;
    font-weight: 700;
}

.pm-shot .ih-title > i {
    color: var(--bs-secondary-color);
    font-size: 0.95rem;
}

.pm-shot .ih-title-inline {
    margin: 0;
    flex: 0 0 auto;
}

/* Reads as a subtitle beside the heading, not as a label floated over the column below it. */
.pm-shot .ih-title > small {
    margin-left: 0.15rem;
    padding-left: 0.55rem;
    border-left: 1px solid var(--bs-border-color);
    font-size: 0.78rem;
    font-weight: 400;
    color: var(--bs-secondary-color);
}

.pm-shot .ih-progress {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.9rem;
    padding: 0.7rem 1.1rem 0.75rem;
}

/* A caption for the stats beneath it, not a sentence floating over the page. */

/* In a narrow column the movement stats read better stacked than wrapped. */
.pm-shot .ps-nudge {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.86rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ps-nudge i { color: var(--tier-advanced); font-size: 1.05rem; }
.pm-shot .ps-nudge b { color: var(--bs-body-color); }

.pm-shot .ps-tally {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.pm-shot .ps-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.6rem 0.2rem 0.45rem;
    border-radius: 50px;
    font-size: 0.76rem;
    font-weight: 600;
    line-height: 1;
    color: #fff;
    animation: badge-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.pm-shot .ps-chip:nth-child(2) { animation-delay: 0.06s; }
.pm-shot .ps-chip:nth-child(3) { animation-delay: 0.12s; }

.pm-shot .ps-chip b {
    font-size: 0.88rem;
    font-variant-numeric: tabular-nums;
}

.pm-shot .ps-chip-up { background-color: var(--tier-advanced); }
.pm-shot .ps-chip-down { background-color: var(--tier-beginner); }
.pm-shot .ps-chip-level { background: var(--tier-mastery-gradient); }

.pm-shot .ps-move-change {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
}

.pm-shot .ps-move-change > i {
    font-size: 0.7rem;
    color: var(--bs-secondary-color);
}

.pm-shot .ps-move-change .wn-band {
    padding: 0.15rem 0.5rem;
    font-size: 0.7rem;
}

/* A move that stayed inside one band still shows its count, "then" muted, "now" leading. */
.pm-shot .ps-move-frac {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: 0.15rem;
}

.pm-shot .ps-move-frac .ps-was { color: var(--bs-secondary-color); }
.pm-shot .ps-move-frac i { font-size: 0.65rem; color: var(--bs-secondary-color); }

.pm-shot .ps-groups {
    flex: 1 0 100%;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.65rem 1.25rem;
    margin-top: 0.3rem;
}

/* A tone rail down the side says "these went up" / "these went down" before any word is
   read, and holds the two groups apart without another box. */
.pm-shot .ps-group {
    padding-left: 0.75rem;
    border-left: 3px solid var(--bs-border-color);
    border-radius: 2px;
}

.pm-shot .ps-group-up {
    border-left-color: var(--bs-success-border-subtle);
}

.pm-shot .ps-group-down {
    border-left-color: var(--bs-danger-border-subtle);
}

@media (min-width: 992px) {
    .pm-shot .ps-groups {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

.pm-shot .ps-group-title {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 0 0 0.3rem;
    padding-left: 0.55rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.pm-shot .ps-group-all {
    /* Small target, so the hit area is padded out past the underline. */
    padding: 0.35rem 0.25rem;
    margin: -0.35rem -0.25rem;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    color: var(--bs-secondary-color);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.pm-shot .ps-group-all:hover,
.pm-shot .ps-group-all:focus-visible {
    color: var(--bs-primary);
}

.pm-shot .ps-moves {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    margin: 0;
    padding: 0;
}

.pm-shot .ps-move {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    /* Still a comfortable target for a row that is only ~20px of text. */
    min-height: 2.25rem;
    padding: 0.25rem 0.55rem;
    border-radius: 0.5rem;
    font-size: 0.85rem;
    cursor: pointer;
    transition-property: background-color, box-shadow;
    transition-duration: 0.15s;
    transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.pm-shot .ps-move:hover {
    background-color: var(--bs-secondary-bg);
}

.pm-shot .ps-move:active {
    background-color: var(--bs-tertiary-bg);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.06);
}

.pm-shot .ps-move:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

.pm-shot .ps-move > i {
    font-size: 1.05rem;
}

.pm-shot .ps-move-go {
    flex: 0 0 auto;
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    opacity: 0;
    transition-property: opacity;
    transition-duration: 0.15s;
}

.pm-shot .ps-move:hover .ps-move-go,
.pm-shot .ps-move:focus-visible .ps-move-go {
    opacity: 1;
}

.pm-shot .ps-move-name {
    flex: 1 1 auto;
    font-size: 0.88rem;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--bs-body-color);
}

.pm-shot .ps-up { color: var(--tier-advanced-text); }
.pm-shot .ps-down { color: var(--tier-beginner-text); }

/* ── Narrow screens ──
   Everything above was built and checked at desktop width. Below it: the summary's rows
   stack, the Hide button stops needing 5rem of reserved space, the movement rows let their
   level chips drop under the name, focus cards go one or two to a row, and a badged card
   reserves less of its title for the corner. */
@media (max-width: 991.98px) {
    .pm-shot .ih-stats,
.pm-shot .ih-progress,
.pm-shot .ih-focus {
        padding-left: 0.9rem;
        padding-right: 0.9rem;
    }

    .pm-shot .ih-bar-head {
        padding-right: 4rem;
    }

    .pm-shot .focus-card {
        flex: 1 1 calc(50% - 0.3rem);
    }

    /* Two mode toggles on one line whenever the row exists at all. */
    .pm-shot #mode-toggle-container {
        flex-wrap: nowrap;
        gap: 0.6rem;
    }

    .pm-shot #mode-toggle-container .form-check {
        flex: 1 1 0;
        min-width: 0;
        padding-left: 0;
    }

    .pm-shot #mode-toggle-container .form-check-label {
        display: block;
    }

    .pm-shot .create-worksheet-toggle,
.pm-shot .create-group-insights-toggle {
        min-width: 0;
    }
}

@media (max-width: 575.98px) {
    /* Title above its buttons, buttons sharing the width. */
    .pm-shot .insights-title-row {
        flex-direction: column;
        align-items: stretch;
        gap: 0.6rem;
        padding-left: 0.25rem;
        padding-right: 0.25rem;
    }

    .pm-shot .insights-title-row > .d-flex {
        width: 100%;
    }

    .pm-shot .insights-title-row > .d-flex > * {
        flex: 1 1 0;
        justify-content: center;
    }

    /* On a phone the toggles drop their descriptions and tighten up. */
    .pm-shot .create-worksheet-toggle,
.pm-shot .create-group-insights-toggle {
        padding: 0.55rem 0.5rem;
    }

    .pm-shot .create-worksheet-toggle small,
.pm-shot .create-group-insights-toggle small {
        display: none;
    }

    /* Movement rows: the level chips drop under the name. */
    .pm-shot .ps-move {
        flex-wrap: wrap;
        row-gap: 0.15rem;
    }

    .pm-shot .ps-move-change {
        flex-basis: 100%;
        padding-left: 1.5rem;
    }

    .pm-shot .ps-move-go {
        display: none;
    }

    .pm-shot .ih-collapse {
        padding: 0.5rem 0.6rem;
    }

    .pm-shot .ih-bar-head {
        padding-right: 3.5rem;
        font-size: 0.78rem;
    }

    .pm-shot .ih-title > small {
        flex-basis: 100%;
        margin-left: 0;
        padding-left: 0;
        border-left: 0;
    }

    .pm-shot .ih-title {
        flex-wrap: wrap;
        row-gap: 0.15rem;
    }

    .pm-shot .focus-card {
        flex: 1 1 100%;
    }

    .pm-shot .focus-cta-btn {
        flex-wrap: wrap;
        text-align: center;
    }

    .pm-shot .tier-section {
        padding: 0.75rem 0.75rem 0.85rem;
    }
}

/* ── Reduced motion ──
   Every entrance, sweep, spin and pulse on the page, off in one place. Confetti and smooth
   scrolling are guarded in JS. */
@media (prefers-reduced-motion: reduce) {
    .pm-shot .tier-card,
.pm-shot .focus-card,
.pm-shot .card-indicator,
.pm-shot .card-badge,
.pm-shot .card-next,
.pm-shot .ps-chip,
.pm-shot .ih-tierbar,
.pm-shot .ih-legend-item,
.pm-shot .mastery-shine,
.pm-shot .tier-card:hover .mastery-shine,
.pm-shot .perfect-score-badge i,
.pm-shot .insights-accent-strip,
.pm-shot .group-insights-mode-indicator.show,
.pm-shot .worksheet-mode-indicator.show,
.pm-shot .confetti-piece,
.pm-shot .signal,
.pm-shot #insights-title,
.pm-shot .level-up-banner,
.pm-shot #performance-levels-container.is-settling {
        animation: none !important;
    }

    .pm-shot .tier-card,
.pm-shot .focus-card,
.pm-shot .tier-section,
.pm-shot .ih-collapse i,
.pm-shot .ps-move,
.pm-shot .focus-cta-btn {
        transition: none !important;
    }

    .pm-shot .tier-card:hover {
        transform: none;
    }
}

/* ── Filter renders don't replay the entrances ──
   Typing in the search or toggling a filter rebuilds the same board. `renderFilteredResults`
   sets this on <body> for those renders so nothing flies in again; a data render (page
   load, a new student) clears it and the entrances play. The board settles with one short
   fade instead, so the change still registers. */
.pm-shot.insights-no-entrance .tier-card,
.pm-shot.insights-no-entrance .focus-card,
.pm-shot.insights-no-entrance .card-indicator,
.pm-shot.insights-no-entrance .card-badge,
.pm-shot.insights-no-entrance .card-next,
.pm-shot.insights-no-entrance .ps-chip,
.pm-shot.insights-no-entrance .ih-tierbar,
.pm-shot.insights-no-entrance .ih-legend-item,
.pm-shot.insights-no-entrance .signal {
    animation: none;
}

@keyframes boardSettle {
    from { opacity: 0.55; }
    to { opacity: 1; }
}

.pm-shot #performance-levels-container.is-settling {
    animation: boardSettle 0.18s ease-out;
}

/* ── Mobile board: one tier at a time ──
   Below 992px the four columns stack, and 179 cards in one list put the tier a student
   wanted a long scroll away. A slim tab strip at the top of the board shows one tier; the
   summary's legend and the filters' Levels row switch tabs too, and a pick brings the tier
   to the top. Sticky so switching never means scrolling back up — ~44px, not a card. */
.pm-shot .tier-tabs {
    display: flex;
    gap: 0.4rem;
    overflow-x: auto;
    padding: 0.5rem 0.25rem;
    scrollbar-width: none;
}

.pm-shot .tier-tabs::-webkit-scrollbar { display: none; }

.pm-shot .tier-tab {
    flex: 0 0 auto;
    gap: 0.35rem;
}

.pm-shot .tier-tab-count {
    font-size: 0.72em;
    font-weight: 700;
    padding: 0.05rem 0.4rem;
    border-radius: 50px;
    background-color: rgba(0, 0, 0, 0.08);
    color: inherit;
    font-variant-numeric: tabular-nums;
}

.pm-shot .tier-tab.is-selected .tier-tab-count {
    background-color: rgba(255, 255, 255, 0.28);
}

/* ── The mobile board: ≤767.98px ──
   Where `col-md-6` gives out and the four tier columns really do stack into one list. From
   768 to 991 the board is a 2×2 grid, which needs no tabs — so the strip is `d-md-none` and
   that band keeps the filters card's Levels row as its level control. */
@media (max-width: 767.98px) {
    /* The tab strip is the one set of level controls here; the filters card's Levels row
       would be a second, identical one a screen above it. */
    .pm-shot #tier-filter {
        display: none;
    }

    .pm-shot .tier-tabs-col {
        position: sticky;
        top: 0;
        z-index: 5;
        background-color: #f8f9fa;
    }

    /* In tabbed mode only the active tier's column shows. */
    .pm-shot #performance-levels-container.is-tabbed > [class*="col-"]:not(.is-active-tab):not(.tier-tabs-col) {
        display: none;
    }

    /* The desktop spotlight's dimming has no meaning when one column is on screen. */
    .pm-shot .tier-section.is-dimmed {
        opacity: 1;
    }
}

/* ── The student's score story ──
   The page's card surface, with the one number a student and their parent actually talk
   about given the size it deserves. The score data was already loaded for the test filter's
   labels; this is what it was for. */
.pm-shot .student-hero {
    position: relative;
    border-radius: 1rem;
    background-color: var(--bs-body-bg);
    box-shadow:
        0 0 0 1px rgba(0, 0, 0, 0.05),
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 6px 16px -8px rgba(0, 0, 0, 0.08),
        0 16px 40px -20px rgba(0, 0, 0, 0.1);
    padding: 1rem 1.1rem 1.1rem;
    margin-bottom: 1rem;
}

.pm-shot .sh-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem 1.5rem;
}

.pm-shot .sh-score {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.pm-shot .sh-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color);
}

.pm-shot .sh-now {
    font-size: 2.4rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
    color: var(--bs-body-color);
}

.pm-shot .sh-change {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.82rem;
    font-weight: 600;
}

.pm-shot .sh-change.is-up { color: var(--tier-advanced-text); }
.pm-shot .sh-change.is-down { color: var(--tier-beginner-text); }
.pm-shot .sh-change.is-first { color: var(--bs-secondary-color); font-weight: 500; }

.pm-shot .sh-aside {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.4rem;
}

.pm-shot .sh-countdown {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.7rem;
    border-radius: 50px;
    background-color: var(--tier-intermediate-soft);
    color: var(--tier-intermediate-text);
    font-size: 0.8rem;
    white-space: nowrap;
}

.pm-shot .sh-countdown b { font-variant-numeric: tabular-nums; }

.pm-shot .sh-goal {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.pm-shot .sh-goal-value {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3rem;
    color: var(--tier-advanced-text);
    font-size: 0.82rem;
}

.pm-shot .sh-goal-value i { align-self: center; }
.pm-shot .sh-goal-value small { font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.68rem; }
.pm-shot .sh-goal-value b { font-size: 1.05rem; font-variant-numeric: tabular-nums; }

/* A goal just beaten. Same shape as the goal readout it replaces, in the mastery colors, so
   the win reads as an achievement rather than another status line. */
.pm-shot .sh-goal-won {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3rem;
    padding: 0.2rem 0.6rem;
    border-radius: 50px;
    background: var(--tier-mastery-gradient);
    color: #fff;
    font-size: 0.82rem;
    animation: badge-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.pm-shot .sh-goal-won i { align-self: center; }
.pm-shot .sh-goal-won small { font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.68rem; }
.pm-shot .sh-goal-won b { font-size: 1.05rem; font-variant-numeric: tabular-nums; }

.pm-shot .sh-goal-set,
.pm-shot .sh-goal-edit {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.7rem;
    border: 1.5px solid var(--tier-advanced);
    border-radius: 50px;
    background: none;
    color: var(--tier-advanced-text);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition-property: background-color, color;
    transition-duration: 0.15s;
}

.pm-shot .sh-goal-edit {
    border-width: 0;
    padding: 0.2rem 0.4rem;
    text-decoration: underline;
    text-underline-offset: 2px;
    color: var(--bs-secondary-color);
}

.pm-shot .sh-goal-set:hover,
.pm-shot .sh-goal-set:focus-visible {
    background-color: var(--tier-advanced);
    color: #fff;
}

.pm-shot .sh-goal-edit:hover,
.pm-shot .sh-goal-edit:focus-visible { color: var(--tier-advanced-text); }

.pm-shot .sh-goal-set:focus-visible,
.pm-shot .sh-goal-edit:focus-visible {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

/* A fixed height: Chart.js fills its container, and a responsive canvas with no height
   collapses to nothing. */
.pm-shot .sh-chart {
    position: relative;
    height: 160px;
    margin-top: 0.75rem;
}

/* A test below their best. Deliberately not red: the number is already on screen, and the job
   of this line is context, not a second alarm. */
.pm-shot .sh-dip {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin: 0.75rem 0 0;
    padding: 0.6rem 0.75rem;
    border-radius: 0.6rem;
    background: var(--bs-secondary-bg);
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
}

.pm-shot .sh-dip i { color: var(--bs-secondary-color); margin-top: 0.1rem; }
.pm-shot .sh-dip b { color: var(--bs-body-color); font-variant-numeric: tabular-nums; }

/* Their best, where the red loss used to be. */
.pm-shot .sh-change.is-best { color: var(--tier-mastery-text); }
.pm-shot .sh-change.is-best b { font-variant-numeric: tabular-nums; }

.pm-shot .sh-gap {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0.75rem 0 0;
    padding-top: 0.7rem;
    border-top: 1px solid var(--bs-border-color-translucent);
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}

.pm-shot .sh-gap i { color: var(--tier-advanced); }
.pm-shot .sh-gap b { color: var(--bs-body-color); font-variant-numeric: tabular-nums; }

/* ── What's within reach ── */
/* Reads as a reach, never a revision: the floor is the score they actually earned and the arrow
   points forward. Nothing in here can render a number below the floor — see insights-forecast.mjs
   for why that property is load-bearing rather than cosmetic. */
.pm-shot .sh-forecast {
    margin: 0.85rem 0 0;
    padding: 0.75rem 0.9rem;
    border-radius: 0.7rem;
    background: var(--bs-primary-bg-subtle);
    box-shadow: inset 0 0 0 1px var(--bs-primary-border-subtle);
}

.pm-shot .shf-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem 1rem;
}

.pm-shot .shf-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color);
}

.pm-shot .shf-band {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}

.pm-shot .shf-floor {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--bs-secondary-color);
}

.pm-shot .shf-arrow {
    font-size: 0.9rem;
    color: var(--bs-secondary-color);
}

.pm-shot .shf-reach {
    font-size: 1.65rem;
    font-weight: 800;
    color: var(--bs-primary-text-emphasis);
}

.pm-shot .shf-note {
    margin: 0.35rem 0 0;
    font-size: 0.84rem;
    color: var(--bs-body-color);
}

.pm-shot .shf-note b { font-variant-numeric: tabular-nums; }

.pm-shot .shf-drivers { font-weight: 600; }

.pm-shot .shf-basis {
    margin: 0.25rem 0 0;
    font-size: 0.76rem;
    color: var(--bs-secondary-color);
}

/* ── What the practice bought ── */
/* Sits in the hero, not on a card: this is the student's own effort reported back to them, and
   a chip in the corner of a card was not a report. Green because it is the one number on this
   page that is purely earned. */
.pm-shot .sh-payoff {
    margin: 0.85rem 0 0;
    padding: 0.75rem 0.9rem;
    border-radius: 0.7rem;
    background: var(--tier-advanced-soft, var(--bs-success-bg-subtle));
    box-shadow: inset 0 0 0 1px var(--bs-border-color-translucent);
}

.pm-shot .shx-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.pm-shot .shx-head i { color: var(--tier-advanced-text); }

.pm-shot .shx-title {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tier-advanced-text);
}

.pm-shot .shx-line {
    margin: 0.3rem 0 0;
    font-size: 0.9rem;
    color: var(--bs-body-color);
}

.pm-shot .shx-line b {
    font-variant-numeric: tabular-nums;
    font-weight: 800;
}

.pm-shot .shx-bar {
    height: 0.4rem;
    margin-top: 0.5rem;
    border-radius: 999px;
    background: var(--bs-border-color-translucent);
    overflow: hidden;
}

.pm-shot .shx-fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--tier-advanced, var(--bs-success));
}

.pm-shot .shx-note {
    margin: 0.4rem 0 0;
    font-size: 0.76rem;
    color: var(--bs-secondary-color);
}

/* ── The moment: what just got earned ── */
.pm-shot .level-up-banner {
    position: relative;
    border-radius: 1rem;
    padding: 1rem 1.1rem;
    margin-bottom: 1rem;
    background: linear-gradient(135deg, var(--tier-mastery-soft) 0%, var(--bs-body-bg) 65%);
    box-shadow: 0 0 0 1px var(--tier-mastery-soft), 0 8px 24px -14px rgba(106, 95, 224, 0.5);
    animation: cardFadeIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.pm-shot .lu-close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    display: flex;
    padding: 0.45rem;
    border: 0;
    background: none;
    color: var(--bs-secondary-color);
    cursor: pointer;
}

.pm-shot .lu-close:hover,
.pm-shot .lu-close:focus-visible { color: var(--bs-body-color); }

.pm-shot .lu-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-right: 2rem;
}

.pm-shot .lu-badge {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--tier-mastery-gradient);
    color: #fff;
    font-size: 1.2rem;
    box-shadow: 0 2px 8px rgba(106, 95, 224, 0.4);
}

.pm-shot .lu-title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--tier-mastery-text);
}

.pm-shot .lu-sub {
    margin: 0;
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
}

.pm-shot .lu-list {
    list-style: none;
    margin: 0.75rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.pm-shot .lu-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem 0.75rem;
    padding: 0.4rem 0.6rem;
    border-radius: 0.5rem;
    background-color: rgba(255, 255, 255, 0.6);
    font-size: 0.88rem;
}

.pm-shot .lu-move {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.pm-shot .lu-move i { font-size: 0.7rem; color: var(--bs-secondary-color); }
.pm-shot .lu-move .wn-band { padding: 0.15rem 0.5rem; font-size: 0.7rem; }

@media (max-width: 575.98px) {
    .pm-shot .sh-head { flex-direction: column; }
    .pm-shot .sh-aside { align-items: flex-start; flex-direction: row; flex-wrap: wrap; }
    .pm-shot .sh-now { font-size: 2rem; }
    .pm-shot .sh-chart { height: 140px; }
}


/* ══════════ public/css/topic-modal.css ══════════ */

/* ── inlined from tier-palette.css ── */
/* ── The four tier colors, defined once ──
   Every tier-colored thing on the insights page and in the topic modal reads from here:
   cards, section titles, the summary bar, level chips, the modal, the confetti. Change a
   color here and everything follows; a hex anywhere else is a mistake.

   Chosen as one family — similar weight, similar warmth — and so white text holds on all
   four: the old pure-orange #ffa500 failed contrast badly for white type.
   `-deep`  the darker end of a card's gradient and its tinted shadow
   `-text`  the tier as ink on a white surface (section titles, modal accents)
   `-soft`  the tier as a faint wash behind dark text */
:root {
    --tier-beginner: #e5484d;
    --tier-beginner-deep: #cc3d42;
    --tier-beginner-text: #c0393e;
    --tier-beginner-soft: rgba(229, 72, 77, 0.12);

    --tier-intermediate: #e8891d;
    --tier-intermediate-deep: #cf7714;
    --tier-intermediate-text: #b8650f;
    --tier-intermediate-soft: rgba(232, 137, 29, 0.14);

    --tier-advanced: #3ea24c;
    --tier-advanced-deep: #348a40;
    --tier-advanced-text: #2c7a38;
    --tier-advanced-soft: rgba(62, 162, 76, 0.12);

    --tier-mastery: #7c88f4;
    --tier-mastery-deep: #6a5fe0;
    --tier-mastery-text: #5a4fd1;
    --tier-mastery-soft: rgba(124, 136, 244, 0.14);
    --tier-mastery-gradient: linear-gradient(45deg, #6f8ef7 0%, #8b7bf3 100%);

    --tier-accent-strip: linear-gradient(90deg, var(--tier-beginner), var(--tier-intermediate), var(--tier-advanced), var(--tier-mastery-deep));

    /* Chip inks for the two signals that are not a tier: pace and staleness. Up/down/hard
       borrow the advanced/beginner/intermediate inks. */
    --signal-pace: #1d6fd6;
    --signal-stale: #5c6470;
}



/* Topic Modal Specific Styles */

/* Problem header override for modals (removes width:100%, sets margin-bottom:10px) */
.pm-shot #divModalTopic .problem-header,
.pm-shot #topicModal .problem-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
}

/* Performance Level Containers - Topic Modal Specific */
/* ── Tier header surface: the same one the board's cards wear ──
   A soft gradient from the tier color to its deep, one corner highlight. The flat fill and
   two corner blobs this replaces were the surface the cards had already left behind. */
.pm-shot #divModalTopic .beginner-container,
.pm-shot #divModalTopic .intermediate-container,
.pm-shot #divModalTopic .advanced-container,
.pm-shot #divModalTopic .mastery-container,
.pm-shot #topicModal .beginner-container,
.pm-shot #topicModal .intermediate-container,
.pm-shot #topicModal .advanced-container,
.pm-shot #topicModal .mastery-container {
    position: relative;
    overflow: hidden;
    background: linear-gradient(160deg, var(--tier-bg) 0%, var(--tier-deep) 100%);
}

.pm-shot #divModalTopic .beginner-container::before,
.pm-shot #divModalTopic .intermediate-container::before,
.pm-shot #divModalTopic .advanced-container::before,
.pm-shot #divModalTopic .mastery-container::before,
.pm-shot #topicModal .beginner-container::before,
.pm-shot #topicModal .intermediate-container::before,
.pm-shot #topicModal .advanced-container::before,
.pm-shot #topicModal .mastery-container::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 100% 0%, rgba(255, 255, 255, 0.22), transparent 55%);
    pointer-events: none;
}

.pm-shot #divModalTopic .beginner-container,
.pm-shot #topicModal .beginner-container { --tier-bg: var(--tier-beginner); --tier-deep: var(--tier-beginner-deep); }
.pm-shot #divModalTopic .intermediate-container,
.pm-shot #topicModal .intermediate-container { --tier-bg: var(--tier-intermediate); --tier-deep: var(--tier-intermediate-deep); }
.pm-shot #divModalTopic .advanced-container,
.pm-shot #topicModal .advanced-container { --tier-bg: var(--tier-advanced); --tier-deep: var(--tier-advanced-deep); }
.pm-shot #divModalTopic .mastery-container,
.pm-shot #topicModal .mastery-container {
    --tier-bg: var(--tier-mastery);
    --tier-deep: var(--tier-mastery-deep);
    background: var(--tier-mastery-gradient);
}

.pm-shot #divModalTopic .beginner-header,
.pm-shot #topicModal .beginner-header {
    background-color: var(--tier-beginner) !important;
    color: white !important;
}

.pm-shot #divModalTopic .intermediate-header,
.pm-shot #topicModal .intermediate-header {
    background-color: var(--tier-intermediate) !important;
    color: white !important;
}

.pm-shot #divModalTopic .advanced-header,
.pm-shot #topicModal .advanced-header {
    background-color: var(--tier-advanced) !important;
    color: white !important;
}

.pm-shot #divModalTopic .mastery-header,
.pm-shot #topicModal .mastery-header {
    background: var(--tier-mastery-gradient) !important;
    color: white !important;
}

/* Problem Item Styling - Topic Modal Specific */
.pm-shot #divModalTopic .problem-item,
.pm-shot #topicModal .problem-item {
    margin-bottom: 20px;
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.pm-shot #divModalTopic .problem-item.correct,
.pm-shot #topicModal .problem-item.correct {
    border-left: 5px solid var(--bs-success);
}

.pm-shot #divModalTopic .problem-item.incorrect,
.pm-shot #topicModal .problem-item.incorrect {
    border-left: 5px solid var(--bs-danger);
}

.pm-shot #divModalTopic .problem-info,
.pm-shot #topicModal .problem-info {
    flex-grow: 1;
}

.pm-shot #divModalTopic .problem-result,
.pm-shot #topicModal .problem-result {
    margin-left: 10px;
    font-weight: bold;
    font-size: 1.2rem;
}

.pm-shot #divModalTopic .problem-item.correct .problem-result,
.pm-shot #topicModal .problem-item.correct .problem-result {
    color: var(--bs-success);
}

.pm-shot #divModalTopic .problem-item.incorrect .problem-result,
.pm-shot #topicModal .problem-item.incorrect .problem-result {
    color: var(--bs-danger);
}

/* Stats Grid Styling - Topic Modal Specific */
.pm-shot #divModalTopic .stats-grid,
.pm-shot #topicModal .stats-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    text-align: center;
}

.pm-shot #divModalTopic .stat-item,
.pm-shot #topicModal .stat-item {
    background-color: #f8f9fa;
    padding: 15px;
    border-radius: 0.25rem;
}

.pm-shot #divModalTopic .stat-value,
.pm-shot #topicModal .stat-value {
    font-size: 1.2rem;
    font-weight: bold;
    color: #495057;
}

/* ==========================================================================
   Topic Performance Modal — modern, premium styling
   ========================================================================== */
.pm-shot .topic-performance-container {
    padding: 0.5rem 0.25rem;
}

.pm-shot .stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0.875rem;
    margin-top: 1rem;
    align-items: stretch;
}

.pm-shot .stat-item {
    background: #f8fafc;
    border: 1px solid rgba(15, 23, 42, 0.06);
    border-radius: 0.75rem;
    padding: 1.125rem 1rem;
    text-align: center;
    transition: border-color 0.2s ease-in-out;
}

.pm-shot .stat-item:hover {
    border-color: rgba(13, 110, 253, 0.25);
}

.pm-shot .stat-label {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #64748b;
    margin-bottom: 0.5rem;
}

.pm-shot .stat-value {
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.pm-shot .problem-list {
    margin-top: 1rem;
}

.pm-shot .problem-item {
    padding: 0.875rem 1rem;
    margin-bottom: 0.625rem;
    border-radius: 0.75rem;
    background: #f8fafc;
    border: 1px solid rgba(15, 23, 42, 0.06);
    display: flex;
    flex-direction: column;
    transition: border-color 0.2s ease-in-out;
}

.pm-shot .problem-item:hover {
    border-color: rgba(13, 110, 253, 0.25);
}

.pm-shot .problem-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    margin-bottom: 0.5rem;
}

.pm-shot .problem-item.correct {
    border-left: 4px solid #198754;
}

.pm-shot .problem-item.incorrect {
    border-left: 4px solid #dc3545;
}

.pm-shot .problem-info {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.pm-shot .problem-number {
    font-weight: 500;
}

.pm-shot .problem-result {
    font-size: 1.1rem;
    margin-left: 0.5rem;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    font-weight: bold;
}

.pm-shot .problem-item.correct .problem-result {
    color: #28a745;
}

.pm-shot .problem-item.incorrect .problem-result {
    color: #dc3545;
}

.pm-shot .problem-stats {
    color: #6c757d;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    padding-right: 0.5rem;
}

.pm-shot .time-taken {
    display: inline-flex;
    align-items: center;
    background-color: rgba(15, 23, 42, 0.06);
    padding: 0.25rem 0.625rem;
    border-radius: 999px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: #475569;
}

.pm-shot .time-taken::before {
    content: "\F41F";
    font-family: "bootstrap-icons";
    margin-right: 0.25rem;
    display: inline-block;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    vertical-align: -0.125em;
    -webkit-font-smoothing: antialiased;
}

.pm-shot .topic-link {
    color: #007bff;
    text-decoration: none;
    cursor: pointer;
}

.pm-shot .topic-link:hover {
    text-decoration: underline;
    color: #0056b3;
}

.pm-shot .problem-item .question-content {
    display: block;
    width: 100%;
    clear: both;
}

.pm-shot .performance-level-container {
    margin-bottom: 20px;
    padding: 15px;
    border-radius: 1rem;
    position: relative;
    overflow: hidden;
}

.pm-shot .performance-level-title {
    font-size: 1.4rem;
    margin-bottom: 10px;
    font-weight: bold;
    color: white;
    position: relative;
    z-index: 1;
}

.pm-shot .performance-level-description {
    color: white;
    font-weight: 500;
    margin-bottom: 0px;
}

/* ── Test by test ──
   The working behind a level: one row per sitting, newest first, with what it counts for.
   The card can only name the test a level leans on; this is where "why" lives. */
.pm-shot .tbt-list {
    margin: 0;
}

.pm-shot .tbt-row {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    padding: 0.5rem 0;
    font-size: 0.88rem;
}

.pm-shot .tbt-row + .tbt-row {
    border-top: 1px solid var(--bs-border-color-translucent);
}

.pm-shot .tbt-when {
    flex: 1 1 auto;
    color: var(--bs-secondary-color);
}

.pm-shot .tbt-score {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    font-variant-numeric: tabular-nums;
}

.pm-shot .tbt-score small {
    color: var(--bs-secondary-color);
}

.pm-shot .tbt-weight {
    flex: 0 0 auto;
    min-width: 6.5rem;
    text-align: right;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

/* The sitting carrying the level reads as the answer. */
.pm-shot .tbt-row.is-latest .tbt-when,
.pm-shot .tbt-row.is-latest .tbt-weight {
    color: var(--bs-body-color);
    font-weight: 600;
}

/* ── Which column this topic came from ──
   The board is four colored columns and the modal opens over all of them; without the level
   on the title a student loses their place the moment it opens. */
.pm-shot .topic-modal-level {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-left: 0.6rem;
    padding: 0.2rem 0.7rem 0.2rem 0.55rem;
    border-radius: 50px;
    font-size: 0.78rem;
    font-weight: 700;
    vertical-align: middle;
    color: #fff;
}

.pm-shot .topic-modal-level i {
    font-size: 0.5em;
    opacity: 0.85;
}

.pm-shot .topic-modal-level small {
    font-weight: 600;
    opacity: 0.85;
    font-variant-numeric: tabular-nums;
}

.pm-shot .topic-modal-level.beginner-level { background-color: var(--tier-beginner); }
.pm-shot .topic-modal-level.intermediate-level { background-color: var(--tier-intermediate); }
.pm-shot .topic-modal-level.advanced-level { background-color: var(--tier-advanced); }
.pm-shot .topic-modal-level.mastery-level { background: var(--tier-mastery-gradient); }

/* ── Answers stay hidden until asked for ──
   A student scrolling their own history to see WHICH questions they missed should not have
   every answer spoiled on the way past. Their own choice is always shown — that is their work,
   not the answer. */
.pm-shot .qb-choices {
    margin-bottom: 0.5rem;
}

.pm-shot .qb-choice {
    padding: 0.15rem 0;
}

.pm-shot .qb-choice.is-right,
.pm-shot .qb-yours.is-right {
    color: var(--bs-success-text-emphasis);
    font-weight: 700;
}

.pm-shot .qb-choice.is-wrong,
.pm-shot .qb-yours.is-wrong {
    color: var(--bs-danger-text-emphasis);
    font-weight: 700;
}

.pm-shot .qb-yours-tag {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 50px;
    font-size: 0.7rem;
    font-weight: 600;
}

.pm-shot .qb-choice.is-right .qb-yours-tag {
    background-color: var(--bs-success-bg-subtle);
    color: var(--bs-success-text-emphasis);
}

.pm-shot .qb-choice.is-wrong .qb-yours-tag {
    background-color: var(--bs-danger-bg-subtle);
    color: var(--bs-danger-text-emphasis);
}

/* Only once revealed does the right answer look like one. */
.pm-shot .qb-body.is-revealed .qb-choice.is-answer {
    color: var(--bs-success-text-emphasis);
    font-weight: 700;
}

.pm-shot .qb-body.is-revealed .qb-choice.is-answer::after {
    content: " ✓";
    color: var(--bs-success);
}



.pm-shot .qb-reveal {
    margin-top: 0.5rem;
}

.pm-shot .qb-reveal-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.8rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 50px;
    background-color: var(--bs-body-bg);
    color: var(--bs-secondary-color);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    transition-property: background-color, color, border-color;
    transition-duration: 0.15s;
}

.pm-shot .qb-reveal-btn:hover,
.pm-shot .qb-reveal-btn:focus-visible {
    border-color: var(--bs-primary);
    color: var(--bs-primary);
}

.pm-shot .qb-answer {
    margin: 0.5rem 0 0;
    color: var(--bs-success-text-emphasis);
    font-weight: 600;
}

/* ── While the topic loads ──
   The modal opens on the click and fills in afterwards, so the click always registers. This
   is what sits there in between. */
.pm-shot .topic-modal-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    min-height: 16rem;
    color: var(--bs-secondary-color);
}

.pm-shot .topic-modal-loading p {
    margin: 0;
    font-size: 0.9rem;
}
