/* ── Info bar (below navbar) ──────────────────────────────────────── */
.pe-infobar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 24px;
    padding: 14px 28px;
    background-color: var(--color-bg-surface);
    border-bottom: 1px solid var(--color-border);
}

.pe-infobar-title {
    font-weight: 700;
    font-size: 16px;
    color: var(--color-text-main);
    white-space: nowrap;
    margin-right: 8px;
}

.pe-infobar-controls {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

.pe-infobar-control {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--color-text-muted);
    white-space: nowrap;
}

.pe-infobar-control .dash-dropdown {
    min-width: 190px;
    font-size: 13px;
}

/* A long filename crops (the dropdown's own ellipsis) instead of pushing
   the stats onto a second line; they only wrap once it's down to 140px. */
.pe-infobar-controls:has(.pe-infobar-control--file) {
    flex: 1 1 0;
    flex-wrap: nowrap;
}

.pe-infobar-control--file {
    flex: 0 1 auto;
    min-width: 0;
}

.pe-infobar-control--file .dash-dropdown {
    min-width: 140px;
}

/* ── Top-level Interface picker (mode_selector, pages/analysis_project_
   evaluation.py) — hand-built, not a dcc.Dropdown, since it needs to
   allow picking the same entity type twice (recreating "Student &
   Student"), which a real multi-select can't express. ─────────────── */
.pe-mode-selector {
    position: relative;
}

.pe-mode-toggle-btn {
    min-width: 190px;
    padding: 7px 10px;
    text-align: left;
    font-family: var(--font-family);
    font-size: 13px;
    color: var(--color-text-main);
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    cursor: pointer;
}

.pe-mode-toggle-btn:hover {
    border-color: var(--color-accent-light);
}

.pe-mode-panel {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 50;
    width: 220px;
    padding: 6px;
    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);
}

.pe-mode-panel.open {
    display: block;
}

.pe-mode-pinned {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 6px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--color-border);
}

.pe-mode-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.pe-mode-option {
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 13px;
    color: var(--color-text-main);
    cursor: pointer;
    transition: background-color 0.15s;
}

.pe-mode-option:hover {
    background-color: rgba(var(--color-accent-rgb), 0.08);
}

.pe-mode-option--pinned {
    color: var(--color-accent);
    font-weight: 700;
    background-color: rgba(var(--color-accent-rgb), 0.1);
}

.pe-mode-option--disabled {
    color: var(--color-text-muted);
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.pe-infobar-stats {
    display: flex;
    align-items: center;
    gap: 20px;
    margin-left: auto;
    flex-wrap: wrap;
}

.pe-infobar-stat {
    font-size: 13px;
    color: var(--color-text-muted);
    white-space: nowrap;
}

.pe-infobar-stat strong {
    color: var(--color-text-main);
    font-weight: 700;
}

/* ── Main layout grid ──────────────────────────────────────────────── */
.pe-layout {
    display: grid;
    gap: 16px;
    padding: 16px 24px;
    /* A real cap, not just a minimum: fills the rest of the viewport below
       the navbar (59px) + info bar (63px) and stays there regardless of
       content. `grid-template-rows: minmax(0, 1fr)` is what actually
       enforces that on the row itself — without it, an `auto` row still
       grows to fit whichever column's content is tallest (e.g. a 180+
       card sidebar list), which drags the whole row taller and stretches
       the plot panes along with it. `minmax(0, ...)` (not just `1fr`)
       overrides grid items' default `min-height: auto`, which otherwise
       stops them shrinking below their own content's intrinsic height —
       see `min-height: 0` on `.pe-sidebar`/`.pe-pane` below, needed for
       the same reason at the item level. */
    height: calc(100vh - 122px);
    grid-template-rows: minmax(0, 1fr);
}

/* Fallback only — every real (non-empty) selection now sets its own
   inline gridTemplateColumns (see _layout_plan in pages/analysis_
   project_evaluation.py), since a "years" side contributes only one
   column (no sidebar) where students/groups contribute two, and no
   single fixed template covers every combination the way the old
   4-fixed-mode system's did. These two rules just keep something
   reasonable on screen if that inline style is ever missing. */
.pe-layout--split {
    grid-template-columns: 260px 1fr auto 1fr 260px;
}

.pe-layout--single {
    grid-template-columns: 260px 1fr;
}

.pe-layout--empty {
    display: flex;
    align-items: center;
    justify-content: center;
}

.pe-layout-empty {
    font-size: 14px;
    color: var(--color-text-muted);
}

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

/* ── Sidebar (Students / Groups list) ─────────────────────────────── */
.pe-sidebar {
    min-height: 0;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.pe-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-muted);
}

.pe-sidebar-count {
    background-color: rgba(var(--color-accent-rgb), 0.12);
    color: var(--color-accent);
    font-size: 11px;
    font-weight: 700;
    padding: 1px 8px;
    border-radius: 999px;
}

/* The border/background that used to live on the bare <input> now lives on
   this wrapper, so the filter/reset icon buttons can sit inside the same
   visual "bar" instead of as separate controls next to it. */
.pe-sidebar-search-bar {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 0 4px 0 10px;
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 6px;
}

.pe-sidebar-search-bar:focus-within {
    border-color: var(--color-accent-light);
}

.pe-sidebar-search {
    flex: 1;
    min-width: 0;
    padding: 7px 0;
    background: none;
    border: none;
    outline: none;
    font-family: var(--font-family);
    font-size: 12.5px;
    color: var(--color-text-main);
}

.pe-sidebar-icon-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    background: none;
    border: none;
    border-radius: 5px;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color 0.15s, background-color 0.15s;
}

.pe-sidebar-icon-btn:hover {
    color: var(--color-accent);
    background-color: rgba(var(--color-accent-rgb), 0.08);
}

.pe-sidebar-icon-btn--reset {
    font-size: 14px;
    line-height: 1;
}

/* Funnel/filter glyph: three centered bars, decreasing width top to
   bottom, colored via currentColor so hover/theme are free. */
.pe-filter-icon {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
}

.pe-filter-icon-bar {
    display: block;
    height: 2px;
    border-radius: 1px;
    background-color: currentColor;
}

.pe-filter-icon-bar:nth-child(1) { width: 14px; }
.pe-filter-icon-bar:nth-child(2) { width: 9px; }
.pe-filter-icon-bar:nth-child(3) { width: 4px; }

/* Collapsed by default — toggled open by the filter icon button
   (toggle_filters_panel in callbacks/analysis_project_evaluation_
   callbacks.py). */
.pe-sidebar-filters {
    display: none;
    gap: 8px;
}

.pe-sidebar-filters.open {
    display: flex;
}

.pe-sidebar-filter {
    flex: 1;
    min-width: 0;
    font-size: 11.5px;
}

.pe-sidebar-filter .dash-dropdown-grid-container {
    padding: 4px 8px;
}

.pe-sidebar-list {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
    padding-bottom: 4px;
}

.pe-sidebar-empty {
    padding: 20px 12px;
    text-align: center;
    font-size: 12.5px;
    color: var(--color-text-muted);
}

.pe-sidebar-empty--hidden {
    display: none;
}

.pe-sidebar-card {
    text-align: left;
    padding: 10px 12px;
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s, background-color 0.15s;
}

.pe-sidebar-card:hover {
    border-color: var(--color-accent-light);
}

.pe-sidebar-card.selected {
    background-color: rgba(var(--color-accent-rgb), 0.1);
    border-color: var(--color-accent);
}

.pe-sidebar-card-top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
}

.pe-sidebar-card-name {
    font-size: 13px;
    font-weight: 700;
    color: var(--color-text-main);
}

.pe-sidebar-card-meta {
    font-size: 11px;
    color: var(--color-text-muted);
    white-space: nowrap;
}

.pe-sidebar-card-line {
    font-size: 11.5px;
    color: var(--color-text-muted);
}

.pe-sidebar-card-line.submitted {
    color: var(--color-success);
}

.pe-sidebar-card-line.withheld {
    color: var(--color-error);
}

/* Card body below the name/meta header: left ~third is the info column
   (Average on top, status pinned to the bottom, empty space between —
   `justify-content: space-between` on a 2-item flex column achieves that
   without a hardcoded empty grid row), right two-thirds is the badge
   grid, so status and the bottom badge row land on the same baseline. */
.pe-sidebar-card-body {
    display: grid;
    grid-template-columns: 1fr 1.6fr;
    gap: 8px;
    margin-top: 6px;
}

.pe-sidebar-card-info {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

/* Badges fill bottom-to-top within a column, starting at the lower-right
   corner, then wrap to a new column further left (max 3 tall, 2 columns)
   — the first badge in DOM order (= highest display priority, e.g.
   Dropout/Self-Inflation overrides) lands in the bottom-right-most, most
   prominent slot.

   `-reverse` on both axes swaps which physical edge counts as "start" for
   that axis, so `flex-start`/`flex-end` below both point at the opposite
   edge from what they'd mean on a plain row/column — easy to get backwards
   (this was wrong in a prior pass): with `column-reverse` the main-axis
   start is the *bottom*, so `justify-content: flex-start` is what anchors
   the group there (needed since the grid stretches this cell taller than
   its own content, to match the info column's height — without it the
   badges float near the top of that extra space instead). With
   `wrap-reverse` the cross-axis start is the *right*, so
   `align-content: flex-start` is what hugs the group against the right
   edge instead of the left. */
.pe-card-badges {
    display: flex;
    flex-direction: column-reverse;
    flex-wrap: wrap-reverse;
    align-content: flex-start;
    justify-content: flex-start;
    gap: 4px;
    max-height: 78px;
}

.pe-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    white-space: nowrap;
    background-color: rgba(var(--color-accent-rgb), 0.12);
    color: var(--color-accent);
}

/* ── Analysis pane (Student / Group main view) ────────────────────── */
.pe-pane {
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Three columns: identity info | controls (toggles + Interface) | badges —
   matches Sketches/Example_selectedCard.png. Previously stacked everything
   in one column; moving the toggles/Interface dropdown into their own
   middle column reads much more compactly. */
.pe-pane-header {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: 24px;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 14px 18px;
}

.pe-pane-header-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    white-space: nowrap;
}

.pe-pane-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--color-text-main);
}

.pe-pane-subtitle {
    font-size: 12.5px;
    color: var(--color-text-muted);
}

.pe-pane-stats {
    font-size: 12.5px;
    color: var(--color-text-muted);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.pe-pane-header-controls {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.pe-pane-toggles {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
}

.pe-pane-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: var(--color-text-muted);
}

.pe-pane-interface {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: var(--color-text-muted);
}

.pe-pane-interface .dash-dropdown {
    min-width: 180px;
    font-size: 12.5px;
}

/* No dcc.Dropdown prop removes "Select All"/"Deselect All" outright (only
   `labels` renames their text) — but this popup isn't portaled outside
   its own component tree (confirmed live: .dash-dropdown-content sits
   right under .pe-pane-interface), so it can be targeted directly. Scoped
   to just the Interface dropdown (both student and group panes share this
   class) — Heatmap/Boxplot's Questions selector and the sidebar Groups/
   Labels filters keep Select All. */
.pe-pane-interface .dash-dropdown-actions {
    display: none;
}

/* Outer wrapper now stacks [notes button, badges list] — the badges
   themselves moved into their own nested .pe-pane-badges-list so the
   notes button (a sibling, not a child) survives a card-selection
   callback overwriting pe-pane-badges' own `children` wholesale. */
.pe-pane-header-badges {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
}

.pe-pane-badges-list {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
}

.pe-notes-btn {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 4px 7px;
    background: none;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}

.pe-notes-btn:hover {
    color: var(--color-accent);
    border-color: var(--color-accent-light);
}

.pe-notes-count {
    font-size: 10.5px;
    font-weight: 700;
    color: var(--color-accent);
}

.pe-notes-count--hidden {
    display: none;
}

/* "Paper with a + badge" — a bordered rectangle with two inset lines
   standing in for text, same currentColor-inherits-hover technique as
   the sidebar's filter icon (.pe-filter-icon). */
.pe-notes-icon {
    position: relative;
    display: inline-block;
    width: 13px;
    height: 15px;
    border: 1.5px solid currentColor;
    border-radius: 2px;
}

.pe-notes-icon::before,
.pe-notes-icon::after {
    content: "";
    position: absolute;
    left: 2px;
    right: 2px;
    height: 1.5px;
    background-color: currentColor;
}

.pe-notes-icon::before { top: 4px; }
.pe-notes-icon::after { top: 8px; }

.pe-notes-plus {
    position: absolute;
    bottom: -5px;
    right: -5px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background-color: var(--color-accent);
    color: white;
    font-size: 8px;
    font-weight: 700;
    line-height: 10px;
    text-align: center;
}

/* ── Widget boxes (plots/tables inside a pane) ────────────────────── */
/* flex: 1 by default — a pane's plot/table widgets split whatever vertical
   space is left over after the (fixed-height) header, equally among
   however many are currently visible (1 when a "___ Only" Interface
   option is active, 2 when the combined option is). `.pe-widget--summary`
   opts back out for the Student Label Summary block, which stays a fixed,
   content-sized height pinned to the bottom instead. */
.pe-widget {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 14px 18px;
    box-shadow: 0 2px 10px rgba(var(--color-shadow-rgb), 0.06);
}

.pe-widget--hidden {
    display: none;
}

.pe-widget--summary {
    flex: 0 0 auto;
}

.pe-widget-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--color-border);
}

.pe-widget-title-group {
    display: flex;
    align-items: center;
    gap: 16px;
}

.pe-widget-title {
    font-size: 13.5px;
    font-weight: 700;
    color: var(--color-text-main);
}

.pe-widget-question {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--color-text-muted);
}

.pe-widget-question .dash-dropdown {
    min-width: 140px;
    font-size: 12px;
}

.pe-widget-placeholder {
    flex: 1;
    min-height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted);
    font-size: 13px;
    border-radius: 8px;
}

.pe-widget-graph {
    flex: 1;
    min-height: 200px;
}

/* ── Widget zoom/expand (assets/pe_widget_zoom.js) ────────────────── */
.pe-widget-body {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.pe-widget-zoom-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    background-color: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text-muted);
    cursor: pointer;
    opacity: 0.85;
    transition: color 0.15s, border-color 0.15s, opacity 0.15s;
}

.pe-widget-zoom-btn:hover {
    color: var(--color-accent);
    border-color: var(--color-accent);
    opacity: 1;
}

.pe-widget-zoom-icon {
    position: relative;
    width: 12px;
    height: 12px;
    display: inline-block;
}

.pe-widget-zoom-icon::before,
.pe-widget-zoom-icon::after {
    content: "";
    position: absolute;
    width: 6px;
    height: 6px;
    border: 1.5px solid currentColor;
}

.pe-widget-zoom-icon::before {
    top: 0;
    left: 0;
    border-right: none;
    border-bottom: none;
}

.pe-widget-zoom-icon::after {
    bottom: 0;
    right: 0;
    border-left: none;
    border-top: none;
}

/* ── Zoom modal (pages/analysis_project_evaluation.py's layout) ──────
   Enlarged clone of whichever plot's zoom button was clicked, entirely
   client-driven (assets/pe_widget_zoom.js) — no Dash callback backs it,
   it only ever mirrors an already-rendered Plotly figure. */
.pe-zoom-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);
}

.pe-zoom-modal-overlay--hidden {
    display: none;
}

.pe-zoom-modal-dialog {
    width: min(1100px, calc(100vw - 64px));
    height: min(760px, calc(100vh - 64px));
    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;
}

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

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

.pe-zoom-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;
}

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

.pe-zoom-modal-graph {
    flex: 1;
    min-height: 0;
    padding: 12px 18px 18px;
}

/* ── Motivation Table (persistent content container, see widget_box's
   content_id/content params) ─────────────────────────────────────── */
.pe-widget-content {
    flex: 1;
    min-height: 200px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
}

.pe-motivation-row {
    background-color: var(--color-bg-page);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    padding: 10px 12px;
}

.pe-motivation-giver {
    display: block;
    font-size: 12px;
    font-weight: 700;
    color: var(--color-text-main);
    margin-bottom: 4px;
}

.pe-motivation-text {
    margin: 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--color-text-muted);
}

.pe-widget-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.pe-widget-summary-empty {
    padding: 4px 0;
    font-size: 12.5px;
    color: var(--color-text-muted);
}