html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ===========================
   Student runner � cypher font
   ===========================
   To enable:
   1) Add your cypher font files under wwwroot/fonts/ (e.g., OmniaCypher.woff2).
   2) Update the @font-face src URLs below.
   3) Ensure RunnerCurrentInteractionDTO.State.Presentation.UseCypher is true.
*/
@font-face {
    font-family: 'OmniaCypher';
    src: url('/fonts/OmniaCypher.woff2') format('woff2');
    font-weight: normal;
    font-style: normal;
}

.cypher-font {
    font-family: 'OmniaCypher', system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
}

/* ===========================
   Player option buttons (MCQ, navigation)
   Global so any renderer can use .mcq-option without component scoping.
   =========================== */

.mcq-option-group {
    margin: 2rem 0 1.2rem;
}

.mcq-horizontal {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.7rem;
}

.mcq-horizontal .mcq-option {
    flex: 0 0 calc((100% - 2.1rem) / 4);
    min-width: 0;
}

.mcq-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.7rem;
}

.mcq-vertical-half {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.55rem;
    max-width: 50%;
    margin-left: auto;
    margin-right: auto;
}

.mcq-vertical-full {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.55rem;
}

/* A lone navigation button (e.g. "Continue" on an end / informational screen)
   must NOT stretch full width — size it to its content (with a sensible minimum)
   and centre it. Global (not scoped) because nav buttons are rendered via
   RenderTreeBuilder, which scoped CSS does not reach. */
.nav-buttons-single {
    display: flex;
    justify-content: center;
}

.nav-buttons-single .mcq-option {
    width: auto;
    min-width: 16rem;
    max-width: 40rem;
    /* Nav buttons carry no .mcq-letter glyph, so drop the 3.6rem left indent and centre the label. */
    padding-left: 1rem;
    text-align: center;
}

.mcq-option {
    display: block;
    position: relative;
    min-height: 4.4rem;
    padding: 0.72rem 1rem 0.72rem 3.6rem;
    border: 3px solid var(--player-option-border, #111);
    border-radius: 0;
    background: var(--player-option-bg, #fff);
    color: var(--player-option-text, #111);
    font-size: calc(clamp(1.35rem, 1.55vw, 1.9rem) * var(--runner-font-scale, 1));
    font-weight: 400 !important;
    cursor: pointer;
    text-align: left;
    transition: border-color 0.12s, background 0.12s, color 0.12s;
    white-space: normal;
}

.mcq-option:hover:not(:disabled) {
    border-color: var(--player-accent);
}

.mcq-option:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.mcq-option:focus-visible {
    outline: 2px solid var(--player-accent);
    outline-offset: 2px;
}

.mcq-selected {
    background: var(--player-accent) !important;
    border-color: var(--player-accent) !important;
    color: #fff !important;
    font-weight: 600 !important;
}

.mcq-selected .mcq-letter {
    font-weight: 700;
}

.mcq-multi.mcq-selected::after {
    content: "\2713";
    position: absolute;
    right: 0.8rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.4em;
    font-weight: 700;
    color: #fff;
}

.mcq-audio-highlight {
    outline: 2px solid var(--player-audio-highlight, #f5a623);
    outline-offset: 4px;
}

.mcq-letter {
    position: absolute;
    left: 0.8rem;
    top: 50%;
    transform: translateY(-50%);
    font-weight: 400;
    min-width: 2.4rem;
    text-align: left;
}

.mcq-text {
    display: block;
    width: 100%;
    text-align: center;
    padding-right: 2rem;
}

@media (max-width: 1100px) {
    .mcq-horizontal .mcq-option {
        flex-basis: calc((100% - 0.7rem) / 2);
    }

    .mcq-vertical-half {
        max-width: 100%;
    }
}

@media (max-width: 768px) {
    .mcq-horizontal .mcq-option {
        flex-basis: 100%;
    }

    .mcq-grid {
        grid-template-columns: 1fr;
    }

    .mcq-option {
        min-height: 3rem;
        font-size: 1rem;
    }

    /* On phones a full-width button is conventional and avoids tight-fit overflow. */
    .nav-buttons-single .mcq-option {
        width: 100%;
        min-width: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .mcq-option {
        transition: none;
    }
}

/* ===========================
   Multi-row single-select pill buttons
   A Buttons line with .RadioSelect options + "Layout:Pills" in its Style renders
   as a responsive grid of pill buttons (one independent single-select row per
   Buttons line) instead of the Likert dot scale. Global because RenderButtons is
   RenderTreeBuilder output that Blazor CSS scoping does not reach.
   =========================== */

.radio-pill-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 0.9rem;
    max-width: 1160px;
    margin: 1.1rem auto;
}

.radio-pill {
    min-height: 4.6rem;
    padding: 0.7rem 1.1rem;
    border: 2px solid var(--player-option-border, #444);
    border-radius: 0.9rem;
    background: var(--player-option-bg, transparent);
    color: var(--player-option-text, inherit);
    font-size: calc(clamp(1.05rem, 1.25vw, 1.4rem) * var(--runner-font-scale, 1));
    line-height: 1.3;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.12s, background 0.12s, color 0.12s;
    white-space: normal;
}

.radio-pill:hover:not(:disabled):not(.radio-pill-selected) {
    border-color: var(--player-accent, #1cb6c9);
}

.radio-pill:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.radio-pill:focus-visible {
    outline: 2px solid var(--player-accent, #1cb6c9);
    outline-offset: 2px;
}

.radio-pill-selected {
    background: var(--player-accent, #1cb6c9) !important;
    border-color: var(--player-accent, #1cb6c9) !important;
    color: #fff !important;
    font-weight: 600;
}

@media (max-width: 768px) {
    .radio-pill-row {
        grid-template-columns: 1fr 1fr;
        gap: 0.5rem;
    }

    .radio-pill {
        min-height: 3.4rem;
        font-size: 1rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .radio-pill {
        transition: none;
    }
}

/* ===========================
   Pinned-question mode (long multi-select MCQ)
   The stem + selected-answer chips stick to the top of .player-content-area
   (the runner scroll container) while the option list scrolls beneath.
   Global for the same reason as the other .mcq-* styles: parts of the header
   are RenderTreeBuilder output that Blazor CSS scoping does not reach.
   =========================== */

.mcq-pinned-header {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--player-bg, #fff);
    padding-bottom: 0.35rem;
    /* Soft bottom fade so options sliding underneath read as "behind" the question. */
    box-shadow: 0 10px 10px -8px rgba(0, 0, 0, 0.3);
    margin-bottom: 0.8rem;
}

/* Inside the runner, .player-content-area (the scroll container) has a padding-top; a
   plain top:0 would stick the header below that padding, leaving a see-through strip
   where options show above the question. Pull the header up over the padding (negative
   top + margin) and give back the same amount as internal padding, so the resting
   layout is unchanged and the stuck header hugs the visible top with no gap. Scoped to
   the player because non-runner hosts (e.g. the /schema catalogue) have no such padding
   and the negative margin would overlap whatever precedes the question. Keep in sync
   with the .player-content-area padding-top clamp in PlayerShell.razor.css. */
.player-content-area .mcq-pinned-header {
    top: calc(-1 * clamp(1.2rem, 2.1vw, 2.4rem));
    margin-top: calc(-1 * clamp(1.2rem, 2.1vw, 2.4rem));
    padding-top: clamp(1.2rem, 2.1vw, 2.4rem);
}

.mcq-selected-strip {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.1rem 0 0.75rem;
}

.mcq-selected-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    max-width: min(28rem, 90vw);
    padding: 0.3rem 0.85rem;
    border: 2px solid var(--player-accent, #1cb6c9);
    border-radius: 1.4rem;
    background: var(--player-accent, #1cb6c9);
    color: #fff;
    font-size: calc(clamp(0.95rem, 1.1vw, 1.25rem) * var(--runner-font-scale, 1));
    line-height: 1.3;
    cursor: pointer;
    transition: filter 0.12s;
}

.mcq-selected-chip:hover:not(:disabled) {
    filter: brightness(0.9);
}

.mcq-selected-chip:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.mcq-selected-chip:focus-visible {
    outline: 2px solid var(--player-accent, #1cb6c9);
    outline-offset: 2px;
}

.mcq-chip-letter {
    font-weight: 700;
}

.mcq-chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mcq-chip-x {
    font-weight: 700;
    font-size: 1.15em;
    line-height: 1;
    opacity: 0.85;
}

@media (prefers-reduced-motion: reduce) {
    .mcq-selected-chip {
        transition: none;
    }
}

/* ===========================
   True/False row layout
   Global so flex layout is not blocked by Blazor CSS scoping.
   =========================== */

.tf-list {
    margin-top: 0.5rem;
}

.tf-row {
    display: flex !important;
    align-items: center;
    gap: 1.5rem;
    padding: 0.85rem 0;
    border-bottom: 1px solid color-mix(in srgb, var(--player-text, #111) 10%, transparent);
}

.tf-row:last-child {
    border-bottom: none;
}

.tf-statement {
    flex: 1 1 0;
    min-width: 0;
    font-size: calc(clamp(1.35rem, 1.55vw, 1.9rem) * var(--runner-font-scale, 1));
    white-space: normal;
}

.tf-buttons {
    display: flex;
    gap: 0.5rem;
    flex-shrink: 0;
}

.tf-choice-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    min-height: 2.8rem;
    padding: 0.45rem 1.1rem 0.45rem 0.85rem;
    border: 2px solid var(--player-option-border, #444);
    border-radius: 0;
    background: transparent;
    color: var(--player-text, #111);
    font-size: calc(clamp(1rem, 1.15vw, 1.3rem) * var(--runner-font-scale, 1));
    font-weight: 400;
    cursor: pointer;
    transition: border-color 0.12s, color 0.12s, background 0.12s;
    white-space: nowrap;
}

.tf-choice-btn::before {
    content: '';
    flex-shrink: 0;
    width: 1rem;
    height: 1rem;
    border: 2px solid currentColor;
    border-radius: 50%;
    transition: background 0.12s, border-color 0.12s;
}

.tf-choice-btn:hover:not(:disabled) {
    border-color: var(--player-accent, #1cb6c9);
    color: var(--player-accent, #1cb6c9);
}

.tf-selected {
    border-color: var(--player-accent, #1cb6c9);
    color: var(--player-accent, #1cb6c9);
}

.tf-selected::before {
    background: var(--player-accent, #1cb6c9);
    border-color: var(--player-accent, #1cb6c9);
}

.tf-choice-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.tf-choice-btn:focus-visible {
    outline: 2px solid var(--player-accent, #1cb6c9);
    outline-offset: 2px;
}

@media (max-width: 480px) {
    .tf-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.6rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tf-choice-btn {
        transition: none;
    }
}

/* ===========================
   ShortAnswer input font size
   !important ensures this wins over Bootstrap form-control (1rem)
   and any stale Blazor bundle values.
   Matches the stem clamp formula and respects --runner-font-scale.
   =========================== */

.shortanswer-textarea {
    font-size: calc(clamp(1.25rem, 1.55vw, 1.9rem) * var(--runner-font-scale, 1)) !important;
}

.shortanswer-line {
    font-size: calc(clamp(1.15rem, 1.35vw, 1.6rem) * var(--runner-font-scale, 1)) !important;
}

/* ═══════════════════════════════════════════
   Likert / RadioSelect scale
   In app.css so changes take effect on hard-refresh without rebuild.
   Mirrors InteractionSwitchRenderer.razor.css — remove from here once
   the scoped bundle is rebuilt and stable.
   ═══════════════════════════════════════════ */

.likert-scale-row {
    position: relative;
    display: flex !important;
    justify-content: space-between;
    align-items: flex-start;
    width: 100%;
    max-width: 720px;
    margin: 1.75rem auto 2.5rem !important;
    padding: 0 0.5rem;
}

.likert-track {
    position: absolute;
    top: 0.7rem;
    left: 1.5rem;
    right: 1.5rem;
    height: 2px;
    background: var(--player-option-border, #444);
    pointer-events: none;
    z-index: 0;
}

.likert-option {
    position: relative;
    z-index: 1;
    display: flex !important;
    flex-direction: column;
    align-items: center;
    gap: 0.55rem;
    background: none !important;
    border: none !important;
    padding: 0 !important;
    cursor: pointer;
    flex: 0 0 auto;
    min-width: 3rem;
    transition: opacity 0.15s;
}

.likert-dot {
    display: block;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    border: 2px solid var(--player-option-border, #444);
    background: var(--player-bg, #f0f0f0);
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}

.likert-label {
    font-size: calc(clamp(0.8rem, 0.95vw, 1.05rem) * var(--runner-font-scale, 1));
    color: var(--player-text, #111);
    text-align: center;
    white-space: normal;
    max-width: 5.5rem;
    line-height: 1.25;
    transition: color 0.2s ease;
}

.likert-option:hover:not(:disabled) .likert-dot {
    border-color: var(--player-accent, #1cb6c9);
    transform: scale(1.15);
}

.likert-option:hover:not(:disabled) .likert-label {
    color: var(--player-accent, #1cb6c9);
}

.likert-option.selected .likert-dot {
    background: var(--player-accent, #1cb6c9) !important;
    border-color: var(--player-accent, #1cb6c9);
    transform: scale(1.3);
}

.likert-option.selected .likert-label {
    color: var(--player-accent, #1cb6c9);
    font-weight: 600;
}

.likert-option:focus-visible .likert-dot {
    outline: 2px solid var(--player-accent, #1cb6c9);
    outline-offset: 3px;
}

.likert-option:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ═══════════════════════════════════════════
   Assessment Completion Screen
   ═══════════════════════════════════════════ */

.assessment-complete-screen {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 80vh;
    padding: 2rem;
}

.assessment-complete-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    max-width: 520px;
    width: 100%;
    color: var(--player-text, #111);
    animation: complete-fade-in 0.5s ease both;
}

@keyframes complete-fade-in {
    from { opacity: 0; transform: translateY(1.5rem); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Animated SVG check */
.complete-icon-wrap {
    margin-bottom: 2rem;
}

.complete-checkmark {
    width: 6rem;
    height: 6rem;
    stroke: var(--player-accent, #1cb6c9);
    stroke-width: 2.5;
}

.complete-checkmark-circle {
    stroke: var(--player-accent, #1cb6c9);
    stroke-dasharray: 166;
    stroke-dashoffset: 166;
    animation: complete-stroke 0.5s cubic-bezier(0.65, 0, 0.45, 1) 0.1s forwards;
}

.complete-checkmark-path {
    stroke: var(--player-accent, #1cb6c9);
    stroke-dasharray: 48;
    stroke-dashoffset: 48;
    animation: complete-stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.55s forwards;
}

@keyframes complete-stroke {
    to { stroke-dashoffset: 0; }
}

/* Typography */
.complete-heading {
    font-size: clamp(1.8rem, 3vw, 2.6rem);
    font-weight: 300;
    letter-spacing: 0.02em;
    margin: 0 0 0.5rem;
    color: var(--player-text, #111);
}

.complete-assessment-name {
    font-size: clamp(1rem, 1.4vw, 1.3rem);
    color: var(--player-accent, #1cb6c9);
    font-weight: 500;
    margin: 0 0 2rem;
}

/* Stats block */
.complete-stats {
    display: flex;
    gap: 3rem;
    justify-content: center;
    margin-bottom: 2rem;
}

.complete-stat-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
}

.complete-stat-value {
    font-size: clamp(2rem, 3.5vw, 3rem);
    font-weight: 600;
    color: var(--player-accent, #1cb6c9);
    line-height: 1;
}

.complete-stat-label {
    font-size: 0.9rem;
    color: color-mix(in srgb, var(--player-text, #111) 65%, transparent);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.complete-message {
    color: color-mix(in srgb, var(--player-text, #111) 70%, transparent);
    font-size: 1rem;
    margin-bottom: 2.5rem;
}

/* Return home button */
.complete-home-btn {
    display: inline-block;
    padding: 0.85rem 2.5rem;
    border: 2px solid var(--player-accent, #1cb6c9);
    border-radius: 0.5rem;
    color: var(--player-accent, #1cb6c9);
    font-size: 1rem;
    font-weight: 500;
    text-decoration: none;
    letter-spacing: 0.04em;
    transition: background 0.2s ease, color 0.2s ease;
}

.complete-home-btn:hover {
    background: var(--player-accent, #1cb6c9);
    color: #051217;
    text-decoration: none;
}

/* ═══════════════════════════════════════════
   PullDown (dropdown) — themed select
   ═══════════════════════════════════════════ */

.pulldown-select {
    display: block;
    width: 100%;
    max-width: 680px;
    margin: 0.5rem auto 0;
    padding: 1rem 3rem 1rem 1.4rem;
    font-size: calc(clamp(1.15rem, 1.4vw, 1.6rem) * var(--runner-font-scale, 1));
    font-family: inherit;
    color: var(--player-text);
    background-color: var(--player-option-bg, transparent);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%231cb6c9' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 1rem center;
    background-size: 1.2rem;
    border: 2px solid var(--player-option-border);
    border-radius: 0.5rem;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    transition: border-color 0.15s ease;
    line-height: 1.4;
}

.pulldown-select:focus {
    outline: none;
    border-color: var(--player-accent, #1cb6c9);
    box-shadow: 0 0 0 3px rgba(28, 182, 201, 0.25);
}

.pulldown-select:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.pulldown-select option {
    background-color: var(--player-option-bg, #fff);
    color: var(--player-option-text, #111);
}

/* ── AutoComplete (Text.AutoComplete PartCode) ──────────────────────────── */

.autocomplete-wrap {
    position: relative;
}

.autocomplete-input {
    font-size: calc(clamp(1.1rem, 1.3vw, 1.5rem) * var(--runner-font-scale, 1)) !important;
    background-color: var(--player-option-bg, #fff) !important;
    color: var(--player-text, #111) !important;
    border: 2px solid var(--player-option-border, #444) !important;
    border-radius: 8px;
    padding: 0.55rem 0.85rem;
    width: 100%;
    transition: border-color 0.15s ease;
}

.autocomplete-input:focus {
    outline: none !important;
    border-color: var(--player-accent, #1cb6c9) !important;
    box-shadow: 0 0 0 3px rgba(28, 182, 201, 0.2) !important;
}

.autocomplete-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 200;
    list-style: none;
    margin: 4px 0 0;
    padding: 4px 0;
    background-color: var(--player-option-bg, #fff);
    border: 1.5px solid var(--player-accent, #1cb6c9);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
    overflow: hidden;
}

.autocomplete-option {
    padding: 0.55rem 1rem;
    font-size: calc(clamp(1.05rem, 1.25vw, 1.4rem) * var(--runner-font-scale, 1));
    color: var(--player-text, #111);
    cursor: pointer;
    transition: background-color 0.1s ease;
}

.autocomplete-option:hover,
.autocomplete-option:focus {
    background-color: rgba(0, 188, 212, 0.12);
    color: var(--player-text, #111);
}

/* ── Schedule editor: Syncfusion date-picker popup styling ──
   The schedule dialog uses SfDatePicker (with CssClass="schedule-editor-datepicker")
   so we can highlight the in-range / selectable date cells. The popup
   renders outside the dialog's component scope (Syncfusion uses a body-
   level portal), so these rules live in global app.css rather than the
   ScheduleEditorDialog.razor.css.

   .e-cell is each day cell. .e-disabled marks days outside the Min/Max
   range — they stay plain. The non-disabled cells in the current month
   are the ones the operator can actually click, so we tint them a soft
   grey so they pop against the rest of the calendar. */
.e-datepicker.e-popup-open .e-calendar .e-cell:not(.e-disabled):not(.e-other-month):not(.e-selected):not(.e-today):not(.sched-today-local) {
    background: #cfcfcf;
}

.e-datepicker.e-popup-open .e-calendar .e-cell:not(.e-disabled):not(.e-other-month):hover {
    background: #a8a8a8;
}

/* Re-point the "today" outline to the SCHOOL's local day. Syncfusion marks
   today from the Blazor Server clock (UTC on Azure) and its per-component
   ServerTimezoneOffset override is obsolete in our version — so the dialog's
   OnRenderDayCell tags the school-local cell with .sched-today-local and we
   move the outline here. (The only SfDatePicker in the app is this schedule
   picker, so .e-datepicker scopes effectively — matching the rules above.)

   Suppress Syncfusion's native today outline on any cell that ISN'T the
   school-local today (i.e. the stray UTC day in the early-WA-morning window). */
.e-datepicker.e-popup-open .e-calendar .e-cell.e-today:not(.sched-today-local) span.e-day {
    border-color: transparent;
    box-shadow: none;
}

/* Draw the today outline on the school-local cell (mirrors the theme's
   round today ring). */
.e-datepicker.e-popup-open .e-calendar .e-cell.sched-today-local span.e-day {
    border: 1px solid var(--admin-accent, #0d6efd);
    box-shadow: inset 0 0 0 1px var(--admin-accent, #0d6efd);
    border-radius: 50%;
}

/* ──────────────────────────────────────────────────────────────────────────
   Line style tokens (sequence.Line.Style → cmr-*)
   Curated, documented vocabulary the runner renderers append verbatim onto each
   line/stem element. Single source of the token list: Contracts/PlanFlow/
   LineStyleCatalog.cs; reference: docs/InteractionLineStyles.md. Global (not
   scoped) so they apply across every runner renderer.
   ────────────────────────────────────────────────────────────────────────── */

/* Alignment — !important beats the runner's non-!important text-align:center. */
.cmr-left   { text-align: left !important; }
.cmr-center { text-align: center !important; }
.cmr-right  { text-align: right !important; }

/* Emphasis — independent; combine freely. */
.cmr-bold      { font-weight: 700 !important; }
.cmr-italic    { font-style: italic !important; }
.cmr-underline { text-decoration: underline !important; }

/* Font size — overrides the per-line --runner-font-scale that the renderers'
   font-size calc() already consumes, so it scales without fighting the stem's
   own !important sizing. (Replaces, not compounds with, the global A+/A- scale
   for this one line.) */
.cmr-larger  { --runner-font-scale: 1.3; }
.cmr-smaller { --runner-font-scale: 0.8; }

/* Block treatments. */
.cmr-quote {
    font-style: italic;
    border-left: 3px solid var(--player-accent, #4ec3e0);
    padding-left: 1rem;
    margin-left: 0.5rem;
    text-align: left !important;
}

.cmr-callout {
    border: 1px solid var(--player-option-border, #888);
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
    background: rgba(255, 255, 255, 0.04);
}

/* Text colour — values are tuned to stay readable on the runner's dark theme.
   Keep in sync with the Swatch hexes in LineStyleCatalog.cs. */
.cmr-red    { color: #ff6b6b !important; }
.cmr-gold   { color: #ffce5a !important; }
.cmr-green  { color: #4fd18b !important; }
.cmr-blue   { color: #4ec3e0 !important; }
.cmr-purple { color: #b794f6 !important; }

