/* Loaded after bulma.min.css: overrides Bulma's CSS variables for the 42 palette, plus the bespoke components Bulma doesn't provide (sidebar, disclosure/tooltip/chart bits). */

/* Dark palette override. Also fixes Bulma's .is-light modifier: it's a fixed pale lightness that doesn't adapt to dark mode on its own. */
[data-theme="dark"] {
    --bulma-scheme-main: #1e1f22;
    --bulma-scheme-main-bis: #2b2d31;
    --bulma-scheme-main-ter: #313338;
    --bulma-border: #3a3c41;
    --bulma-border-weak: #35373c;
    --bulma-text: #dbdee1;
    --bulma-text-strong: #f2f3f5;
    --bulma-text-weak: #949ba4;
    --bulma-link: #58a6ff;
    --bulma-link-hover: #79b8ff;
    --bulma-link-text: #58a6ff;
    --bulma-light-l: 18%;
    --bulma-light-invert-l: 88%;

    /* Same is-light bug, for the danger-colored flavor (.button.is-danger.is-light). */
    --bulma-danger-light-l: 18%;
    --bulma-danger-light-invert-l: 85%;

    /* Same untuned-for-dark-mode bug for .notification.is-warning - dimmed to fit the theme, kept warning-colored. */
    --bulma-warning-l: 20%;
    --bulma-warning-invert-l: 85%;

    /* Desaturating only (not hue/lightness) softens Bulma's neon-vivid status hues to match the muted palette. */
    --bulma-danger-s: 68%;
    --bulma-info-s: 65%;
    --bulma-warning-s: 78%;
}

/* .has-text-warning reads off the darkened --bulma-warning-l too, illegible as bare text; reuse --bulma-warning-invert-l instead. */
[data-theme="dark"] .has-text-warning {
    color: hsl(var(--bulma-warning-h), var(--bulma-warning-s), var(--bulma-warning-invert-l)) !important;
}

body {
    -webkit-font-smoothing: antialiased;
}

/* A long repo URL/path/sha has no natural break point; site-wide since <code> can carry arbitrarily long values anywhere. */
code {
    overflow-wrap: break-word;
    word-break: break-all;
}

/* Underlined by default so plain-text-looking links read as clickable without relying on color alone. */
a {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.sidebar .menu-list a,
.button,
.tag,
.pagination-previous,
.pagination-next,
.report-btn,
.sort-link,
.tabs a,
.brand {
    text-decoration: none;
}

/* App shell: persistent sidebar + content area, custom since Bulma has no sidebar component (nav inside it is Bulma's .menu). */
.app-shell {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    width: 232px;
    flex-shrink: 0;
    background: #18191c;
    padding: 1.5rem 1rem;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.sidebar .menu-label {
    color: #80868e;
}

.sidebar .menu-list a {
    color: #b5bac1;
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.sidebar .menu-list a:hover {
    color: #f2f3f5;
    background: rgba(255, 255, 255, 0.06);
}

.sidebar .menu-list a.is-active {
    color: #f2f3f5;
    background: rgba(255, 255, 255, 0.09);
}

/* Inherits the link's color (stroke="currentColor" in nav_icon) so hover/active states tint the icon too. */
.nav-icon {
    flex-shrink: 0;
    opacity: 0.85;
}

/* margin-top: auto pushes this footer to the bottom of the sidebar's flex column. */
.sidebar-footer {
    margin-top: auto;
    padding: 1rem 0.5rem 0;
    border-top: 1px solid var(--bulma-border-weak);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* Segmented-control look (grouped pills) so this reads as a control with options, not stray links. */
.sidebar-locale {
    display: flex;
    gap: 0.25rem;
    padding: 0.2rem;
    background: rgba(0, 0, 0, 0.2);
    border-radius: 8px;
}

.sidebar-locale-option {
    flex: 1;
    text-align: center;
    padding: 0.3rem 0;
    border-radius: 6px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: #80868e;
    text-decoration: none;
}

.sidebar-locale-option:hover {
    color: #f2f3f5;
    background: rgba(255, 255, 255, 0.06);
}

.sidebar-locale-option.is-active {
    color: #18191c;
    background: #dbdee1;
}

.sidebar-login-status {
    color: #b5bac1;
    font-size: 0.85rem;
    margin-bottom: -0.4rem;
}

.sidebar-role-badge {
    align-self: flex-start;
    margin-bottom: -0.3rem;
}

/* Standalone full-page screen, not part of .app-shell/.sidebar, so its own centering rules. */
.login-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bulma-scheme-main);
    padding: 2rem;
}

.login-card {
    width: 100%;
    max-width: 380px;
    background: var(--bulma-scheme-main-bis);
    border: 1px solid var(--bulma-border);
    border-radius: 14px;
    padding: 2.5rem 2.25rem 2rem;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.4);
    text-align: center;
}

.login-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 1.75rem;
}

.login-brand-name {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--bulma-text-strong);
}

.login-card .title {
    margin-bottom: 0.5rem;
}

.login-lede {
    color: var(--bulma-text-weak);
    font-size: 0.85rem;
    line-height: 1.5;
    margin-bottom: 2rem;
}

.login-providers {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.login-provider-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    height: 2.75rem;
    font-weight: 600;
}

.login-provider-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.3rem;
    height: 1.3rem;
    flex-shrink: 0;
}

.login-provider-icon svg {
    width: 100%;
    height: 100%;
}

.login-provider-icon-fortytwo {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}

/* Keycloak button stays Bulma's default rather than .is-dark like 42's, so the two read as distinct providers. */
.login-provider-btn-keycloak {
    border-color: var(--bulma-border);
    color: var(--bulma-text-strong);
}

.brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
    font-size: 1.05rem;
    padding: 0 0.5rem;
    color: #f2f3f5;
}

.brand-tagline {
    padding: 0 0.5rem;
    margin-top: 0.35rem;
    color: #80868e;
    font-size: 0.78rem;
    line-height: 1.3;
}

.brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 0.35rem;
    background: #dbdee1;
    color: #18191c;
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}

/* Bigger than sidebar's .brand-mark: sole focal point of the login card. Ordered after .brand-mark to win the cascade (same specificity). */
.login-brand-mark {
    width: 4rem;
    height: 4rem;
    font-size: 1.6rem;
    border-radius: 0.85rem;
}

.content {
    flex: 1;
    min-width: 0;
    padding: 2rem 2.5rem 4rem;
    /* No max-width: data tables, not prose, so no readability reason to cap line length. */
}

@media (max-width: 860px) {
    .app-shell {
        flex-direction: column;
    }

    .sidebar {
        width: 100%;
        height: auto;
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 1rem;
        padding: 1rem;
    }

    .sidebar .menu {
        display: flex;
        flex-wrap: wrap;
        gap: 0.75rem;
    }

    .sidebar .menu-list {
        display: flex;
        flex-wrap: wrap;
        gap: 0.25rem;
    }

    .sidebar .menu-label {
        display: none;
    }

    .content {
        padding: 1.5rem;
    }
}

/* Health page (health.html) */
.health-check-description {
    color: var(--bulma-text-weak);
    font-size: 0.82rem;
    margin-top: 0.15rem;
}

.health-check-latency {
    color: var(--bulma-text-weak);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Page-level description under <h1>; not Bulma's .subtitle, which is a large heading-adjacent element, not a muted line. */
.page-lede {
    color: var(--bulma-text-weak);
    margin-bottom: 1.5rem;
}

/* htmx's htmx-request class driving Bulma's .is-loading spinner visuals, reusing its --bulma-loading-color token. */
.button.htmx-request {
    color: transparent !important;
    pointer-events: none;
    position: relative;
}

.button.htmx-request::after {
    animation: spinAround 0.5s linear infinite;
    border: 2px solid var(--bulma-loading-color, currentColor);
    border-right-color: transparent;
    border-top-color: transparent;
    border-radius: 9999px;
    content: "";
    display: block;
    height: 1em;
    width: 1em;
    position: absolute;
    left: calc(50% - 0.5em);
    top: calc(50% - 0.5em);
}

/* Native <details>/<summary> for open/close; htmx lazy-loads the body on first open only. */
details.disclosure {
    border: 1px solid var(--bulma-border);
    border-radius: var(--bulma-radius, 6px);
    margin-bottom: 0.5rem;
    overflow: hidden;
}

details.disclosure > summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.7rem 1rem;
    font-size: 0.9rem;
    user-select: none;
}

details.disclosure > summary::-webkit-details-marker {
    display: none;
}

details.disclosure > summary::after {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    margin-left: auto;
    border-right: 2px solid var(--bulma-text-weak);
    border-bottom: 2px solid var(--bulma-text-weak);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
    flex-shrink: 0;
}

details.disclosure[open] > summary::after {
    transform: rotate(45deg);
}

details.disclosure > summary:hover {
    background: var(--bulma-scheme-main-bis);
}

details.disclosure[open] > summary {
    border-bottom: 1px solid var(--bulma-border);
    background: var(--bulma-scheme-main-bis);
}

.disclosure-label {
    color: var(--bulma-text-weak);
    white-space: nowrap;
}

.disclosure-value {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.disclosure-body {
    padding: 1rem;
}

/* Empty-state placeholder, deliberately NOT .notification.is-light: its -h/-s aren't touched by the dark-theme override, reading blue-tinted and inconsistent. */
.empty-state {
    text-align: center;
    color: var(--bulma-text-weak);
}

.disclosure-body:empty {
    padding: 0;
}

.htmx-indicator {
    display: none;
}

.htmx-request.htmx-indicator,
.htmx-request .htmx-indicator {
    display: block;
}

/* Pure-CSS hover/focus tooltip for secondary info; required guidance stays as visible .help text. */
.info-tip {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 999px;
    background: var(--bulma-border);
    color: var(--bulma-text-weak);
    font-size: 0.68rem;
    font-weight: 700;
    font-style: italic;
    font-family: Georgia, "Times New Roman", serif;
    cursor: help;
    margin-left: 0.4rem;
    flex-shrink: 0;
}

.info-tip:hover,
.info-tip:focus {
    background: var(--bulma-link);
    color: var(--bulma-scheme-main);
    outline: none;
}

.info-tip-bubble {
    /* fixed, not absolute: escapes .table-container's overflow-y: hidden clipping. app.js's positionInfoTip() sets top/left since fixed can't be anchored via CSS. */
    position: fixed;
    width: max-content;
    max-width: 280px;
    background: var(--bulma-scheme-main-bis);
    border: 1px solid var(--bulma-border);
    color: var(--bulma-text);
    font-size: 0.8rem;
    font-weight: 400;
    font-style: normal;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    line-height: 1.45;
    padding: 0.65rem 0.85rem;
    border-radius: var(--bulma-radius, 6px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease;
    z-index: 9999;
    text-align: left;
}

.info-tip:hover .info-tip-bubble,
.info-tip:focus .info-tip-bubble {
    opacity: 1;
    visibility: visible;
}

/* Custom combobox (app.js): styled replacement for native <select>/<datalist>, which can't be restyled reliably. */
.combobox {
    position: relative;
}

.combobox.is-invalid .input {
    border-color: var(--bulma-danger);
}

.combobox-list {
    position: absolute;
    z-index: 30;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 0.25rem;
    max-height: 16rem;
    overflow-y: auto;
    background: var(--bulma-scheme-main-bis);
    border: 1px solid var(--bulma-border);
    border-radius: var(--bulma-radius, 6px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    padding: 0.25rem 0;
    list-style: none;
}

.combobox-list li {
    padding: 0.4rem 0.75rem;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combobox-list li:hover,
.combobox-list li.is-active {
    background: var(--bulma-scheme-main-ter);
}

/* File diff view (_diff_body.html) */
.diff-columns {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    flex-wrap: wrap;
}

.diff-pane {
    flex: 1;
    min-width: 280px;
    max-height: 70vh;
    overflow-y: auto;
}

/* Matches Bulma's ".content pre" specificity (0,1,1); a bare ".diff-code" alone would lose the cascade to it. */
#content .diff-code {
    white-space: pre-wrap;
    margin: 0;
    font-size: 0.82rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    color: var(--bulma-text);
}

.diff-line-highlight {
    display: inline-block;
    width: 100%;
    background: hsl(var(--bulma-warning-h), var(--bulma-warning-s), 15%);
}

.diff-legend {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.diff-legend-swatch {
    display: inline-block;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 0.2rem;
    background: hsl(var(--bulma-warning-h), var(--bulma-warning-s), 15%);
    flex-shrink: 0;
}

/* Commit timeline chart (_timeline_body.html) */
.timeline-chart {
    color: var(--bulma-text);
    margin-bottom: 1rem;
}

.timeline-chart svg {
    width: 100%;
    height: auto;
    max-width: 800px;
}

/* Bulma's .level-item defaults to flex-shrink: 0; these items can grow a wrapped explanation line and need to shrink to fit. */
.level-item {
    min-width: 0;
    flex-shrink: 1;
}
.level-item code {
    overflow-wrap: anywhere;
}

.repo-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.repo-card-stats {
    display: flex;
    gap: 1.5rem;
    font-size: 0.9rem;
    margin-bottom: 0.75rem;
}

.signal-card-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 0.5rem;
}

.signal-card-quiet {
    background: transparent;
    box-shadow: none;
    border: 1px dashed var(--bulma-border);
}

/* "How to use this" block (ML confidence model group): numbered list + inline shell command, unlike other settings groups' name/value tables. */
.setting-howto ol {
    margin: 0.75rem 0 0 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.setting-howto pre {
    background: var(--bulma-scheme-main-bis);
    border: 1px solid var(--bulma-border);
    border-radius: 6px;
    padding: 0.75rem;
    margin-top: 0.5rem;
    overflow-x: auto;
}

/* A clustered tab stacks several per-signal groups in one panel; this label is the only thing telling them apart. */
.setting-subgroup-label {
    font-weight: 600;
    color: #b5bac1;
    margin-bottom: 0.75rem;
}

.settings-search-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0.6;
}

/* Bulma gives .tabs/.box etc. an explicit display value that beats [hidden]'s UA-default on specificity - force [hidden] to always win. */
[hidden] {
    display: none !important;
}

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

.evidence-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.7rem 1rem;
    font-size: 0.9rem;
    border: 1px solid var(--bulma-border);
    border-radius: var(--bulma-radius, 6px);
}

/* Compare form (compare.html) */
.compare-side {
    height: 100%;
}

/* Zip drop zone (compare_archives.html): the real file input stays present
and reachable (opacity 0, not display:none/hidden) so the label-click
association, keyboard focus, and the browser's own required-field
validation bubble all keep working - only its visuals are replaced. */
.zip-drop-zone {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 1.75rem 1rem;
    border: 1.5px dashed var(--bulma-border);
    border-radius: var(--bulma-radius, 6px);
    background: var(--bulma-scheme-main-bis);
    color: var(--bulma-text-weak);
    cursor: pointer;
    text-align: center;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}

.zip-drop-zone input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.zip-drop-zone:hover,
.zip-drop-zone:focus-within,
.zip-drop-zone.is-dragover {
    border-color: var(--bulma-link);
    color: var(--bulma-text);
    background: var(--bulma-scheme-main-ter);
}

.zip-drop-zone.has-file {
    border-style: solid;
    color: var(--bulma-text-strong);
}

/* Wait page (compare_wait.html) */
.spinner {
    display: inline-block;
    width: 1.1rem;
    height: 1.1rem;
    border: 2px solid var(--bulma-border);
    border-top-color: var(--bulma-text);
    border-radius: 999px;
    animation: spinAround 0.7s linear infinite;
    vertical-align: -0.2rem;
    margin-right: 0.6rem;
}

.wait-step {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.9rem 0;
}

.wait-step + .wait-step {
    border-top: 1px solid var(--bulma-border);
}

/* Sortable headers opt out of the default underline - the sort icon already marks them clickable. */
.sort-link {
    color: var(--bulma-text-weak);
    font-weight: 600;
    white-space: nowrap;
}

.sort-link:hover {
    color: var(--bulma-text-strong);
    text-decoration: underline;
}

.sort-link.is-active {
    color: var(--bulma-text-strong);
}

.sort-icon {
    display: inline-block;
    margin-left: 0.3rem;
    opacity: 0.5;
    font-size: 0.85em;
}

.sort-link.is-active .sort-icon {
    opacity: 1;
}

.w-narrow {
    width: 4rem !important;
}

/* Neutral confirmation notice, not a Bulma color modifier: .is-warning reads as a problem, .is-info's vivid mid-tone clashes with the dark palette. */
.quiet-notification {
    background: var(--bulma-scheme-main-bis);
    border: 1px solid var(--bulma-link);
    color: var(--bulma-text);
}

.quiet-notification strong {
    color: var(--bulma-text-strong);
}

.quiet-notification code {
    word-break: break-all;
}

.secret-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.secret-row pre {
    flex: 1;
    min-width: 0;
    margin: 0;
}

/* Save confirmation (admin/_setting_row.html) - fades on its own, no JS needed. */
.save-confirmation {
    color: hsl(var(--bulma-success-h), var(--bulma-success-s), 55%);
    font-size: 0.85rem;
    margin-left: 0.5rem;
    animation: fade-out 1.5s ease forwards;
    animation-delay: 0.75s;
}

@keyframes fade-out {
    from { opacity: 1; }
    to { opacity: 0; }
}

/* For .tabs that overflow a narrow viewport. Bulma's default scrolls horizontally instead of wrapping; this wraps onto multiple rows so every tab stays reachable without scroll/page overflow. */
.wrapping-tabs {
    /* overflow-x alone isn't enough: per spec, overflow-x: visible with a non-visible overflow-y gets silently forced back to auto. */
    overflow: visible;
    white-space: normal;
}

.wrapping-tabs ul {
    /* Bulma's .tabs ul has flex-shrink: 0, sizing to content's max-content width; width: 100% constrains it so flex-wrap actually kicks in. */
    flex-wrap: wrap;
    flex-shrink: 1;
    width: 100%;
    row-gap: 0.5rem;
}

.settings-tabs li {
    white-space: nowrap;
}

/* table-layout: fixed makes column widths deterministic; auto layout let one column absorb leftover space unpredictably. */
.learners-table {
    table-layout: fixed;
}

.learners-table th:first-child,
.learners-table td:first-child {
    width: 25%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.learners-table th:not(:first-child),
.learners-table td:not(:first-child) {
    width: auto;
    white-space: nowrap;
}

.learners-table td:last-child,
.learners-table th:last-child {
    padding-right: 0.75rem;
}

.learners-table td:last-child,
.learners-table th:last-child {
    padding-right: 0.75rem;
}

/* Filled bar makes a raw value's relative size legible at a glance (exact number still printed). Label+value stacked, not side by side, to fit a narrow sidebar column. */
.feature-bars {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.feature-bar-row {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.feature-bar-heading {
    display: flex;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: 0.8rem;
}

.feature-bar-label {
    color: var(--bulma-text-weak);
}

.feature-bar-value {
    color: var(--bulma-text-weak);
    font-variant-numeric: tabular-nums;
}

.feature-bar-track {
    background: var(--bulma-border);
    border-radius: 4px;
    height: 0.55rem;
    overflow: hidden;
}

.feature-bar-fill {
    background: var(--bulma-link);
    height: 100%;
    border-radius: 4px;
}

.period-chart-card {
    margin-bottom: 1rem;
}

.period-chart-heading {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.period-chart-table-toggle {
    margin-top: 0.5rem;
}

.period-chart-table-toggle summary {
    cursor: pointer;
    color: var(--bulma-text-weak);
    font-size: 0.85rem;
}

/* A page-level collapsible section (e.g. campus_graph.html's Repeated
   pairing / Graph / Review timing) - a proper header you click, not a
   small "view details" link like .period-chart-table-toggle above. Full
   text contrast and real heading weight/size so it doesn't read as
   grayed-out or disabled. */
.section-toggle {
    margin-bottom: 1.5rem;
}

.section-toggle > summary {
    cursor: pointer;
    color: var(--bulma-text);
    font-size: 1.25rem;
    font-weight: 700;
    padding: 0.6rem 0;
    border-bottom: 1px solid var(--bulma-border);
    list-style: none;
}

.section-toggle > summary::-webkit-details-marker {
    display: none;
}

.section-toggle > summary::before {
    content: "▸";
    display: inline-block;
    width: 1.1rem;
    color: var(--bulma-link);
}

.section-toggle[open] > summary::before {
    content: "▾";
}

.section-toggle > summary:hover {
    color: var(--bulma-link);
}

.section-toggle > .box,
.section-toggle > .page-lede {
    margin-top: 1rem;
}

.graph-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    font-size: 0.8rem;
    color: var(--bulma-text-weak);
    margin-bottom: 0.75rem;
}

.graph-legend-sep {
    width: 1px;
    height: 0.8rem;
    background: var(--bulma-border);
}

/* Matches campus_graph.html's own script TIER_COLOR/TIER_WIDTH exactly -
   the graph's edge color/thickness legend, next to each flag_badge so
   the wording ties directly to the line it describes. */
.legend-line {
    display: inline-block;
    width: 1.5rem;
    margin-left: 0.4rem;
    vertical-align: middle;
    border-radius: 2px;
}

.legend-line-clean {
    height: 1px;
    background: #0ca30c;
    opacity: 0.5;
}

.legend-line-suspicious {
    height: 2px;
    background: #fab219;
    opacity: 0.7;
}

.legend-line-cheat {
    height: 3.5px;
    background: #d03b3b;
    opacity: 0.85;
}

#graph-container {
    width: 100%;
    height: 70vh;
    border-radius: 6px;
    overflow: hidden;
}

/* Overrides 3d-force-graph's own injected default tooltip style (a plain
   white box) to match .info-tip-bubble's look. Scoped under
   #graph-container and !important since the library injects its rule
   into <head> at runtime, after this stylesheet - a later same-specificity
   rule would otherwise win. */
#graph-container .float-tooltip-kap {
    background: var(--bulma-scheme-main-bis) !important;
    border: 1px solid var(--bulma-border) !important;
    color: var(--bulma-text) !important;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
    font-size: 0.8rem !important;
    padding: 0.5rem 0.7rem !important;
    border-radius: var(--bulma-radius, 6px) !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35) !important;
}

/* This .control has no label above the button, unlike its siblings; align-self pins it to the row's bottom to match their baseline. */
.filter-actions {
    display: flex;
    align-self: flex-end;
    gap: 0.5rem;
}

/* Summary cards are click-through filters, not just counts - a plain Bulma .box has no link styling to override. */
.stat-card {
    display: block;
    color: inherit;
    transition: box-shadow 0.15s ease;
}

.stat-card:hover {
    box-shadow: 0 0 0 1px var(--bulma-link);
}

.stat-card-active {
    box-shadow: 0 0 0 2px var(--bulma-link);
}

/* Fixed column widths so switching a filter doesn't visibly resize the table; auto layout sizes columns to whatever's currently visible. */
.dashboard-table {
    table-layout: fixed;
}

.dashboard-table th:nth-child(1),
.dashboard-table td:nth-child(1) {
    width: 5%;
}

.dashboard-table th:nth-child(2),
.dashboard-table td:nth-child(2) {
    width: 12%;
    overflow-wrap: break-word;
}

.dashboard-table th:nth-child(3),
.dashboard-table td:nth-child(3) {
    width: 10%;
    overflow-wrap: break-word;
}

.dashboard-table th:nth-child(4),
.dashboard-table td:nth-child(4) {
    width: 8%;
}

/* .tag and .sort-link force white-space: nowrap, so these columns need explicit width for their longest content rather than an even split. */
.dashboard-table th:nth-child(5),
.dashboard-table td:nth-child(5) {
    width: 13%;
}

.dashboard-table th:nth-child(6),
.dashboard-table td:nth-child(6) {
    width: 9%;
}

.dashboard-table th:nth-child(7),
.dashboard-table td:nth-child(7),
.dashboard-table th:nth-child(8),
.dashboard-table td:nth-child(8) {
    width: 11%;
}

.dashboard-table th:nth-child(9),
.dashboard-table td:nth-child(9) {
    width: 11%;
}

.dashboard-table th:nth-child(10),
.dashboard-table td:nth-child(10) {
    width: 10%;
    white-space: nowrap;
}
