/* ── Setup form (pages/tools_grade_calculation.py) ────────────────── */
.gc-setup {
    display: flex;
    justify-content: center;
    padding: 32px 24px;
}

.gc-setup--hidden {
    display: none;
}

.gc-form {
    width: min(560px, 100%);
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 24px 28px;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
}

.gc-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.gc-field-label {
    font-size: 13px;
    font-weight: 700;
    color: var(--color-text-main);
}

.gc-range-sep {
    font-size: 12.5px;
    color: var(--color-text-muted);
}

.gc-mode-toggle {
    display: flex;
    gap: 4px;
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    padding: 3px;
}

.gc-mode-btn {
    flex: 1;
    padding: 6px 12px;
    background: none;
    border: none;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color 0.15s, background-color 0.15s, box-shadow 0.15s;
}

.gc-mode-btn.active {
    background-color: var(--color-bg-surface);
    color: var(--color-accent);
    box-shadow: 0 1px 3px rgba(var(--color-shadow-rgb), 0.15);
}

.gc-grade-list-field--hidden {
    display: none;
}

.gc-upload {
    height: 90px;
}

.gc-form .analysis-continue-btn {
    align-self: center;
    margin-top: 4px;
}

/* ── Results screen (post-Continue, same page) ─────────────────────── */
.gc-results--hidden {
    display: none;
}

/* ── Info bar: Calibration/Aggregation/model parameters ────────────── */
/* Reuses .pe-infobar-control's own look (components/analysis_pane.py's
   .pe-pane-toggle for the Calibration switch) — these fields live in the
   info bar next to File, available from the moment the page loads, not
   gated behind Continue, per explicit user request. */
.gc-param-field--hidden {
    display: none;
}

.gc-infobar-input {
    width: 64px;
    padding: 6px 8px;
    font-family: var(--font-family);
    font-size: 13px;
    background-color: var(--color-bg-page);
    color: var(--color-text-main);
    border: 1px solid var(--color-border);
    border-radius: 6px;
}

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

.gc-tiered-fields {
    display: flex;
    gap: 16px;
}

/* Higher-specificity compound selector, deliberately — .gc-tiered-fields'
   own display:flex above and this rule have equal specificity as separate
   single-class selectors, and whichever comes *later* in the file wins a
   tie; a compound selector here removes that fragility so hiding always
   wins regardless of source order (hit this exact bug once already: the
   plain .gc-param-field--hidden rule got silently overridden). */
.gc-tiered-fields.gc-param-field--hidden {
    display: none;
}

/* .gc-settings-slot wraps Include-self/Calibration/Aggregation/parameters
   wherever they currently live (setup form or info bar — see pages/tools_
   grade_calculation.py's _settings_controls). display:contents lets its
   children participate directly in whichever flex parent it's sitting in
   (the info bar's own row, or the form-specific wrapping row below)
   instead of being nested one level deeper as a single flex item. */
.gc-settings-slot {
    display: contents;
}

.gc-settings-slot.gc-form-settings-slot {
    display: flex;
    flex-wrap: wrap;
    gap: 14px 20px;
}

/* ── Results screen: table + graph + Groups sidebar ────────────────── */
.gc-results-body {
    display: grid;
    grid-template-columns: minmax(320px, 1fr) auto minmax(360px, 1.4fr) 250px;
    gap: 20px;
    padding: 20px 28px;
    height: calc(100vh - 122px);
}

.gc-results-divider {
    width: 1px;
    background-color: var(--color-border);
}

.gc-results-table-pane {
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    overflow-y: auto;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 14px;
}

.gc-results-graph-pane {
    min-height: 0;
}

/* The Groups sidebar reuses Project-Evaluation's whole .pe-sidebar look
   (see _groups_sidebar in pages/tools_grade_calculation.py) — only the
   filter panel's own framing and the Select all/Deselect all row are
   specific to this page. */
.gc-groups-sidebar .pe-sidebar-filters.open {
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    padding: 10px;
}

.gc-sidebar-select-row {
    display: flex;
    gap: 8px;
}

.gc-sidebar-select-btn {
    flex: 1;
    padding: 6px 0;
    font-family: var(--font-family);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--color-text-muted);
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.gc-sidebar-select-btn:hover {
    color: var(--color-accent);
    border-color: var(--color-accent-light);
}

/* Stops a double-click ("show only this group") from selecting the card's
   own text as a side effect. */
.gc-groups-sidebar .pe-sidebar-card {
    user-select: none;
}

/* ── Export button (info bar's right corner) + modal ───────────────── */
/* Same margin-left:auto push Project-Evaluation's own .pe-infobar-stats
   uses to land in the far right of the info bar's flex row. */
.gc-infobar-export-slot {
    margin-left: auto;
    display: flex;
    gap: 8px;
}

.gc-export-btn {
    padding: 8px 24px;
    font-size: 13px;
    font-weight: 700;
    color: white;
    background-color: var(--color-accent);
    border: none;
    border-radius: 999px;
    cursor: pointer;
    transition: opacity 0.15s;
}

.gc-export-btn:hover {
    opacity: 0.88;
}

/* Osiris has no modal to explain itself in, so the button carries the
   blocked state directly (reason in its title attribute). */
.gc-export-btn:disabled {
    background-color: var(--color-border);
    color: var(--color-text-muted);
    cursor: not-allowed;
}

.gc-export-btn:disabled:hover {
    opacity: 1;
}

/* Same hand-built overlay/dialog pattern as components/notes_modal.py
   (this app never loads Bootstrap CSS, so dbc.Modal renders unstyled) —
   own classes rather than reusing .notes-modal-* directly, since this is
   a page-scoped modal and "notes-modal-overlay" wrapping Export content
   would read as mislabeled to a future reader. */
.gc-export-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(0, 0, 0, 0.5);
}

.gc-export-modal-overlay--hidden {
    display: none;
}

.gc-export-modal-dialog {
    width: min(480px, calc(100vw - 48px));
    max-height: min(600px, calc(100vh - 48px));
    display: flex;
    flex-direction: column;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(var(--color-shadow-rgb), 0.3);
    overflow: hidden;
}

.gc-export-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    border-bottom: 1px solid var(--color-border);
}

.gc-export-modal-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--color-text-main);
}

.gc-export-modal-close-btn {
    padding: 2px 7px;
    background: none;
    border: none;
    border-radius: 4px;
    font-size: 18px;
    line-height: 1;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color 0.15s, background-color 0.15s;
}

.gc-export-modal-close-btn:hover {
    color: var(--color-accent);
    background-color: rgba(var(--color-accent-rgb), 0.08);
}

.gc-export-modal-body {
    min-height: 120px;
    padding: 16px 18px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Last section has nothing under it to separate from. */
.gc-export-modal-body .gc-export-section:last-of-type {
    padding-bottom: 0;
    border-bottom: none;
}

/* ── Export modal: the column picker ──────────────────────────────── */
.gc-export-section {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--color-border);
}

.gc-export-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-muted);
}

/* OrgDefinedId/Username — shown as a fixed, non-toggleable pair, since
   they're the only identity the export ever writes. */
.gc-export-fixed {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.gc-export-fixed-col {
    padding: 3px 9px;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-main);
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 999px;
}

.gc-export-option {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.gc-export-option-label {
    font-size: 13px;
    color: var(--color-text-main);
}

/* Sits under the Final Grade switch, indented past the switch itself. */
.gc-export-final-hint {
    margin-left: 44px;
}

.gc-export-final-hint:empty {
    display: none;
}

.gc-export-option-hint {
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--color-text-muted);
}

/* Indented so "Separate into Bonus and Malus" reads as belonging to the
   Bonus/Malus switch above it rather than as a third column choice. */
.gc-export-suboption {
    margin-left: 22px;
    padding-left: 12px;
    border-left: 2px solid var(--color-border);
}

.gc-export-name-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.gc-export-name-row--hidden {
    display: none;
}

.gc-export-name-label {
    flex: 0 0 96px;
    font-size: 12.5px;
    color: var(--color-text-muted);
}

/* The dropdown itself is already themed globally (.dash-dropdown in
   01_forms.css); this only has to make it fill the row. */
.gc-export-target-select {
    flex: 1;
    min-width: 0;
}

/* Overwrite warnings and unpicked/duplicate-column problems, under the
   dropdowns that produce them. Reuses the import status block's line
   colours so a warning reads the same wherever it appears. */
.gc-export-overwrite {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 4px;
}

.gc-export-overwrite:empty {
    display: none;
}

/* The literal header row the current options produce — same chips as the
   fixed identity pair, in export order. */
.gc-export-preview {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.gc-export-preview-col {
    padding: 3px 9px;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-accent);
    background-color: rgba(var(--color-accent-rgb), 0.12);
    border-radius: 999px;
}

.gc-export-scope {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.gc-export-download-btn {
    align-self: flex-end;
    padding: 9px 26px;
    font-family: var(--font-family);
    font-size: 13px;
    font-weight: 700;
    color: white;
    background-color: var(--color-accent);
    border: none;
    border-radius: 8px;
    cursor: pointer;
}

.gc-export-download-btn:hover:not(:disabled) {
    background-color: var(--color-accent-light);
}

.gc-export-download-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}


/* ── Info bubbles (Model/Calibration/Aggregation/parameters) ──────── */
.gc-field-label-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* The Grade list bubble's required-columns checklist (_info_children's
   `items`) — the only info bubble whose content is a list rather than an
   explanation plus a formula. */
.gc-info-list {
    margin: 8px 0 0;
    padding-left: 16px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.gc-info-list-term {
    font-weight: 700;
    color: var(--color-text-main);
}

/* ── Grade list upload: parse/match status ────────────────────────── */
.gc-grade-list-status:empty {
    display: none;
}

.gc-grade-list-status {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 8px;
}

.gc-grade-list-line {
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--color-text-muted);
}

.gc-grade-list-line--ok {
    color: var(--color-success);
}

.gc-grade-list-line--warn {
    color: var(--color-secondary);
}

.gc-grade-list-line--error {
    color: var(--color-error);
}

.gc-info-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-left: 4px;
}

.gc-info-btn {
    width: 16px;
    height: 16px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 50%;
    font-size: 10px;
    font-style: italic;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}

.gc-info-btn:hover {
    color: var(--color-accent);
    border-color: var(--color-accent-light);
}

.gc-info-popup {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 50;
    width: 260px;
    padding: 10px 12px;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(var(--color-shadow-rgb), 0.2);
    /* Field labels this sits next to are normal weight/size, but the
       popup itself needs to read clearly regardless of where it's
       anchored (info bar vs. setup form) — fixed, not inherited. */
    font-weight: 400;
    text-align: left;
    white-space: normal;
}

.gc-info-popup.open {
    display: block;
}

.gc-info-explain {
    margin: 0 0 6px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--color-text-main);
}

.gc-info-formula {
    margin: 0;
    padding: 6px 8px;
    background-color: var(--color-bg-page);
    border-radius: 6px;
    font-family: monospace;
    font-size: 11px;
    line-height: 1.4;
    color: var(--color-text-muted);
}

/* ── Grade list verification window ────────────────────────────────────
   Reuses the Export modal's overlay/dialog/header chrome above; only the
   content and the footer buttons are its own. It has no × button, so the
   footer is the only way out and always has to be reachable — hence the
   fixed footer with the body scrolling between it and the header. */
.gc-verify-modal-dialog {
    max-width: 620px;
    display: flex;
    flex-direction: column;
    max-height: 80vh;
}

.gc-verify-modal-body {
    overflow-y: auto;
    flex: 1;
    min-height: 0;
}

.gc-verify-summary {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--color-border);
}

.gc-verify-summary-file {
    font-size: 13px;
    color: var(--color-text-muted);
    word-break: break-word;
}

.gc-verify-section {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-top: 14px;
}

.gc-verify-section-title {
    font-weight: 600;
    font-size: 14px;
    color: var(--color-text-main);
}

/* The whole explanation for a list lives here, per explicit user
   instruction — never repeated per student, so the list below stays a
   plain list of names. */
.gc-verify-section-explain {
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--color-text-muted);
}

/* Capped rather than unbounded: a cohort-sized list would otherwise push
   Continue out of reach behind the whole page's scroll. */
.gc-verify-list {
    display: flex;
    flex-direction: column;
    margin-top: 4px;
    max-height: 190px;
    overflow-y: auto;
    border: 1px solid var(--color-border);
    border-radius: 6px;
}

/* Columns rather than a name and one trailing note: the group has to read
   as its own column so a "-" in it is unmistakably "no group". The name
   takes the slack, the rest size to their content. */
.gc-verify-entry {
    display: flex;
    gap: 12px;
    padding: 5px 10px;
    font-size: 13px;
}

.gc-verify-entry:nth-of-type(even) {
    background-color: var(--color-bg-page);
}

/* Sticky so the group/e-mail columns stay named while a long list scrolls
   inside its own box. */
.gc-verify-entry--head {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: var(--color-bg-surface);
    border-bottom: 1px solid var(--color-border);
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.gc-verify-cell {
    flex: 0 0 auto;
    min-width: 90px;
    text-align: right;
    color: var(--color-text-muted);
    font-size: 12px;
    word-break: break-word;
}

.gc-verify-cell--name {
    flex: 1 1 auto;
    min-width: 0;
    text-align: left;
    color: var(--color-text-main);
    font-size: 13px;
}

.gc-verify-entry--head .gc-verify-cell {
    font-size: 11.5px;
}

.gc-verify-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 12px 20px;
    border-top: 1px solid var(--color-border);
}

.gc-verify-btn {
    padding: 7px 16px;
    font-family: var(--font-family);
    font-size: 13px;
    font-weight: 600;
    border-radius: 6px;
    border: 1px solid var(--color-border);
    cursor: pointer;
}

.gc-verify-btn--cancel {
    background-color: transparent;
    color: var(--color-text-muted);
}

.gc-verify-btn--continue {
    background-color: var(--color-accent);
    border-color: var(--color-accent);
    color: var(--color-bg-surface);
}

.gc-verify-btn:hover {
    opacity: 0.88;
}

/* Reopens the window for an already-accepted file; sits under the upload
   box's status lines. */
.gc-verify-review-btn {
    align-self: flex-start;
    margin-top: 6px;
    padding: 0;
    background: none;
    border: none;
    font-family: var(--font-family);
    font-size: 12.5px;
    color: var(--color-accent);
    text-decoration: underline;
    cursor: pointer;
}

.gc-verify-review-btn--hidden {
    display: none;
}
