/*
 * h_da Corporate Design für Study Monitoring
 * Farben: extrahiert aus docs/design/CD-Dokumentation.pdf (h_da Farbenpool)
 * Schrift: HDADINOff (h_da Hausschrift), abgelegt unter core/static/core/fonts/
 */

/* ---------------------------------------------------------------------------
 * TomSelect ↔ Tabler-Brücke
 * Die vendorierte tom-select.bootstrap5-Theme referenziert Bootstraps --bs-*-
 * Variablen. Tabler benennt diese in --tblr-* um, sodass --bs-* sonst
 * undefiniert bleiben → das Widget rendert blass/unvollständig. Hier mappen wir
 * die von der Theme genutzten Variablen auf Tablers Werte (mit Fallback).
 * ------------------------------------------------------------------------- */
:root {
    /* Formular-Hintergrund (weiß), wie Tablers .form-control — NICHT der
       gräuliche Seiten-Hintergrund (--tblr-body-bg). */
    --bs-body-bg: var(--tblr-bg-forms, #ffffff);
    --bs-body-color: var(--tblr-body-color, #1a2234);
    --bs-border-color: var(--tblr-border-color, #dadfe5);
    --bs-border-color-translucent: var(--tblr-border-color-translucent, rgba(0, 0, 0, 0.1));
    --bs-border-width: var(--tblr-border-width, 1px);
    --bs-border-radius: var(--tblr-border-radius, 4px);
    --bs-border-radius-lg: var(--tblr-border-radius-lg, 6px);
    --bs-border-radius-sm: var(--tblr-border-radius-sm, 3px);
    --bs-box-shadow-inset: var(--tblr-box-shadow-inset, inset 0 1px 1px rgba(0, 0, 0, 0.075));
    --bs-secondary-bg: var(--tblr-secondary-bg, #f5f7fb);
    --bs-tertiary-bg: var(--tblr-tertiary-bg, #f0f2f5);
    --bs-form-invalid-color: var(--tblr-danger, #d63939);
    --bs-form-valid-color: var(--tblr-success, #2fb344);
}

/* ---------------------------------------------------------------------------
 * Hausschrift HDADINOff
 * ------------------------------------------------------------------------- */
@font-face {
    font-family: "HDA DIN";
    src: url("../fonts/HDADINOff-Regular.ttf") format("truetype");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "HDA DIN";
    src: url("../fonts/HDADINOff-Medium.ttf") format("truetype");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "HDA DIN";
    src: url("../fonts/HDADINOff-Bold.ttf") format("truetype");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* ---------------------------------------------------------------------------
 * Farbvariablen (h_da Farbenpool → Tabler/Bootstrap)
 * ------------------------------------------------------------------------- */
:root {
    --hda-orange:      #E98011;  /* h_da Orange 2081 */
    --hda-orange-dark: #CF6F0C;
    --hda-bordeaux:    #5D0613;  /* h_da Orange 9901 */
    --hda-red:         #AC1B21;  /* h_da Rot 5005 */
    --hda-yellow:      #FCCB06;  /* h_da Gelb 1051 */
    --hda-green:       #9DC41E;  /* h_da Grün */
    --hda-green-dark:  #719E3E;
    /* Primär-/Akzentfarbe der App = h_da Orange. Die gesamte Chrome läuft über
       diesen Slot (--hda-brand*), nicht über eine konkrete Palettenfarbe. */
    --hda-brand:       #E98011;  /* = --hda-orange */
    --hda-brand-dark:  #CF6F0C;  /* Hover-/Link-Ton */
    --hda-brand-rgb:   233, 128, 17;   /* für rgba()-Tints, damit sie mitfärben */
    --hda-orange-rgb:  233, 128, 17;
    --hda-blue:        #519CDB;  /* h_da Blau 1169 */
    --hda-blue-rgb:    81, 156, 219;
    --hda-blue-dark:   #102D5C;  /* h_da Blau 8190 */
    --hda-purple:      #A04AA3;  /* h_da Violett 2197 */
    --hda-purple-rgb:  160, 74, 163;
    --hda-anthracite:  #231F20;  /* h_da Schwarz */

    /* Hausschrift als Standard-Schriftfamilie */
    --hda-font-sans: "HDA DIN", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --tblr-font-sans-serif: var(--hda-font-sans);
    --bs-body-font-family: var(--hda-font-sans);

    /* Tabler-Primärfarbe = h_da Orange */
    --tblr-primary: #E98011;
    --tblr-primary-rgb: 233, 128, 17;
    --tblr-primary-darken: #CF6F0C;

    /* Namensfarben (steuern u. a. die bg-*-lt Badges) auf h_da mappen */
    --tblr-red: #AC1B21;        --tblr-red-rgb: 172, 27, 33;
    --tblr-orange: #E98011;     --tblr-orange-rgb: 233, 128, 17;
    --tblr-yellow: #FCCB06;     --tblr-yellow-rgb: 252, 203, 6;
    --tblr-green: #7BAD26;      --tblr-green-rgb: 123, 173, 38;
    --tblr-blue: #519CDB;       --tblr-blue-rgb: 81, 156, 219;
    --tblr-purple: #A04AA3;     --tblr-purple-rgb: 160, 74, 163;

    /* Links */
    --tblr-link-color: #CF6F0C;
    --tblr-link-color-rgb: 207, 111, 12;
    --bs-link-color: #CF6F0C;
}

/* Hausschrift greifbar machen (Tabler setzt font-family teils fix auf body) */
body {
    font-family: var(--hda-font-sans);
}

/* ---------------------------------------------------------------------------
 * Komponenten (kompilierte Tabler-Werte explizit überschreiben)
 * ------------------------------------------------------------------------- */
.btn-primary {
    --tblr-btn-color: #fff;
    --tblr-btn-bg: var(--hda-brand);
    --tblr-btn-border-color: var(--hda-brand);
    --tblr-btn-hover-bg: var(--hda-brand-dark);
    --tblr-btn-hover-border-color: var(--hda-brand-dark);
    --tblr-btn-active-bg: var(--hda-brand-dark);
    --tblr-btn-active-border-color: var(--hda-brand-dark);
    background-color: var(--hda-brand);
    border-color: var(--hda-brand);
    color: #fff;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
    background-color: var(--hda-brand-dark);
    border-color: var(--hda-brand-dark);
    color: #fff;
}

/* Icon→Text-Abstand (app-weite Regel): jeder Text-Button trägt ein führendes
   Tabler-Icon, gefolgt von einem kleinen Abstand von 0.40em. Tabler-.btn ist
   inline-flex mit White-space-Collapsing, d. h. ein bloßes Leerzeichen im Markup
   wird am Flex-Item-Rand getrimmt — der Abstand muss daher als margin am Icon
   gesetzt werden. Icon-only-Buttons (.btn-icon) sind ausgenommen. */
.btn:not(.btn-icon) > .ti:first-child { margin-inline-end: 0.40em; }

/* Buttons flach halten: Tablers Ruhe-Schatten (--tblr-shadow-button) erzeugt eine
   dünne dunkle Akzentlinie am unteren Button-Rand — die wollen wir nicht. Nur den
   Ruhe-Zustand entschärfen; der Fokus-Rahmen läuft über --tblr-btn-focus-box-shadow
   und bleibt für die Barrierefreiheit erhalten. */
.btn { --tblr-btn-box-shadow: none; box-shadow: none; }

.text-primary { color: var(--hda-brand) !important; }
.bg-primary { background-color: var(--hda-brand) !important; }
a { color: var(--hda-brand-dark); }
a:hover { color: var(--hda-brand); }

/* Navbar: heller h_da-Look. Kein durchgehender Trennstrich, damit der
   aktive Menüpunkt nicht mit einer Randlinie kollidiert — die Aktiv-Kachel
   markiert den Zustand eigenständig. */
.navbar {
    /* Header dauerhaft sichtbar am oberen Fensterrand (app-weit, beide Layouts). */
    position: sticky;
    top: 0;
    z-index: 1030;
    background-color: #fff;
    border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
    box-shadow: 0 1px 2px rgba(35, 31, 32, 0.04);
}
.navbar-brand .fw-bold { color: var(--hda-anthracite); }

/* Menüpunkte: dezente, abgerundete Hover-/Aktiv-Fläche statt Unterstreichung */
.navbar .navbar-nav { gap: 0.25rem; }
.navbar .navbar-nav .nav-link {
    padding: 0.4rem 0.75rem;
    border-radius: 8px;
    transition: background-color 0.15s ease, color 0.15s ease;
}
/* Tablers native Aktiv-Unterstreichung (::after) abschalten — die Kachel ersetzt sie */
.navbar .navbar-nav .nav-link::after { display: none !important; }
.navbar .navbar-nav .nav-link:hover {
    background-color: rgba(var(--hda-brand-rgb), 0.08);   /* Primärfarbe, sehr dezent */
    color: var(--hda-brand-dark);
}
.navbar .nav-item.active .nav-link {
    background-color: rgba(var(--hda-brand-rgb), 0.12);
    color: var(--hda-brand-dark);
    font-weight: 600;
}

/* Tabs im Verwaltungsbereich */
.nav-tabs .nav-link.active {
    color: var(--hda-brand);
    border-bottom-color: var(--hda-brand);
}

/* Fokus-/Formzustände */
.form-control:focus,
.form-select:focus {
    border-color: var(--hda-brand);
    box-shadow: 0 0 0 0.25rem rgba(var(--hda-brand-rgb), 0.25);
}

/* App-weiter Tooltip-Hinweis: ein unterstrichener Begriff, der beim Hovern eine
   gestylte dunkle Box mit Erklärtext zeigt. Nutzung:
     <span class="hint" data-tooltip="Erklärung">Begriff</span>
   (``.org-unit-tooltip`` ist das Alt-Alias aus dem Lifecycle-Modal — gleiche Optik). */
.hint,
.org-unit-tooltip {
    cursor: help;
    border-bottom: 1px dotted var(--tblr-border-color, #adb5bd);
}
.hint:hover::after,
.org-unit-tooltip:hover::after {
    content: attr(data-tooltip);
    position: fixed;
    background: var(--hda-anthracite, #231F20);
    color: #fff;
    padding: .4rem .6rem;
    border-radius: 6px;
    font-size: .72rem;
    white-space: nowrap;
    z-index: 9999;
    transform: translateY(1.5rem);
    pointer-events: none;
}

/* Oberen Hero-Abstand app-weit angleichen: Seiten im Lifecycle-Layout
   (lifecycle/base.html) rendern eine <section class="content-header">, die
   leer (padding 15px oben+unten = 30px) den Hero ~10px tiefer schiebt als das
   Tabler-Layout (layouts/base.html mit .page-body margin-top = 1.25rem). Ist der
   content-header leer, klappen wir ihn ein und geben dem Content denselben
   oberen Abstand wie Tabler → identische Hero-Oberkante auf allen Seiten. */
.content-header:empty { padding: 0; }
.content-header:empty + .content { padding-top: var(--tblr-content-padding, 1.25rem); }

/* ---------------------------------------------------------------------------
   Studienfortschrittsplanung — Semester-Grid
   Horizontal scrollbares Raster; Module als CP-proportionale Blöcke.
   --------------------------------------------------------------------------- */
.planning-grid {
    display: flex;
    gap: 0.75rem;
    overflow-x: auto;
    padding-bottom: 0.5rem;
    align-items: stretch;
}
.planning-semester {
    flex: 1 0 150px;
    min-width: 150px;
    display: flex;
    flex-direction: column;
}
.planning-semester-head {
    text-align: center;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid var(--hda-brand);
    margin-bottom: 0.5rem;
}
.planning-courses {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    min-height: 420px;
}
.planning-course {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0.5rem 0.4rem 1.1rem;
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 6px;
    background: #fff;
    font-size: 0.85rem;
    line-height: 1.15;
}
.planning-course-slug {
    font-weight: 600;
}
.planning-course-cp {
    position: absolute;
    bottom: 3px;
    right: 6px;
    font-size: 0.65rem;
    color: var(--tblr-muted, #6c757d);
}
.planning-course-attempts {
    margin-top: 0.25rem;
    font-size: 0.6rem;
}
/* Statusfarben (dezente Flächen, an h_da-Farbenpool angelehnt) */
.planning-course-done {
    background: rgba(123, 173, 38, 0.16);   /* h_da Grün */
    border-color: rgba(123, 173, 38, 0.5);
}
.planning-course-pvl {
    background: rgba(81, 156, 219, 0.16);    /* h_da Blau */
    border-color: rgba(81, 156, 219, 0.5);
}
.planning-course-open {
    background: #fff;
}

/* ---------------------------------------------------------------------------
   Lifecycle-Hub — Phasen-Spalten & Einträge (Struktur aus der Lifecycle-App,
   im h_da-/Tabler-Theme dieser App gehalten).
   --------------------------------------------------------------------------- */
.lc-phase-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 0.75rem;
}
.lc-phase-col-header {
    font-size: 0.8125rem;
    font-weight: 600;
    text-align: center;
    padding: 0.4rem 0.5rem;
    border-radius: 6px;
    background: var(--tblr-bg-surface-secondary, #f4f5f7);
    border-bottom: 2px solid var(--hda-brand);
    margin-bottom: 0.5rem;
}
.lc-phase-entries {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.lc-entry {
    cursor: pointer;
}
.lc-entry .card-body {
    padding: 0.625rem 0.75rem;
}
.lc-type {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-weight: 600;
    color: var(--hda-brand);
}
.lc-entry-name {
    font-weight: 600;
    font-size: 0.9rem;
    margin-top: 0.15rem;
}
.lc-entry-desc {
    font-size: 0.8rem;
    color: var(--tblr-secondary, #6c757d);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 0.15rem;
}
.lc-phase-empty {
    font-size: 0.75rem;
    color: #bbb;
    text-align: center;
    padding: 0.75rem;
    font-style: italic;
}

/* ---------------------------------------------------------------------------
   Chatbot (studierendenseitig) — Struktur aus der Lifecycle-Bot-App,
   im h_da-/Tabler-Theme dieser App.
   --------------------------------------------------------------------------- */
.chat-window {
    height: 60vh;
    min-height: 340px;
    overflow-y: auto;
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.chat-msg {
    max-width: 78%;
    padding: 0.6rem 0.85rem;
    border-radius: 12px;
    font-size: 0.9rem;
    line-height: 1.4;
    white-space: pre-line;
}
.chat-msg-bot {
    align-self: flex-start;
    background: var(--tblr-bg-surface-secondary, #f4f5f7);
    border-bottom-left-radius: 3px;
}
.chat-msg-user {
    align-self: flex-end;
    background: rgba(157, 196, 30, 0.14); /* h_da Grün, dezent */
    border-bottom-right-radius: 3px;
}
.chat-welcome {
    text-align: center;
    color: var(--tblr-secondary, #6c757d);
    padding: 1.5rem 1rem 0.5rem;
}
.chat-suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
    margin-top: 1rem;
}
.chat-suggestion {
    text-align: left;
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    background: #fff;
    border-radius: 8px;
    padding: 0.5rem 0.75rem;
    font-size: 0.82rem;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.chat-suggestion:hover {
    border-color: var(--hda-brand);
    background: rgba(157, 196, 30, 0.06);
}

/* Chat: zweispaltiges Layout (Chat + didaktisches Debug-Panel) */
.chat-layout {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 0.75rem;
    align-items: start;
}
@media (max-width: 992px) {
    .chat-layout { grid-template-columns: 1fr; }
}
.debug-context-bar {
    height: 0.5rem;
    background: #e9ecef;
    border-radius: 4px;
    overflow: hidden;
    margin-top: 0.5rem;
}
.debug-context-fill {
    height: 100%;
    width: 0;
    background: var(--hda-brand);
    transition: width 0.3s ease;
}
.debug-log {
    max-height: 34vh;
    overflow-y: auto;
}
.debug-log-entry {
    font-size: 0.78rem;
    border-left: 2px solid var(--hda-brand);
    padding: 0.3rem 0.5rem;
    margin-bottom: 0.35rem;
    background: var(--tblr-bg-surface-secondary, #f4f5f7);
    border-radius: 4px;
    line-height: 1.35;
}
.debug-help {
    cursor: pointer;
    color: var(--hda-brand);
    font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Umschalter + Kontrast-Theme (Schwarz auf Weiß)
   Die Klasse .theme-contrast auf <html> aktiviert eine kontrastreiche
   Schwarz-Weiß-Ansicht als Barrierefreiheits-Hilfe für sehbeeinträchtigte
   Personen — KEIN Dark-Mode. Reines Weiß als Grund, reines Schwarz für
   Text und Rahmen, keine Markenfarben, unterstrichene Links, kräftige Ränder.
   Umgesetzt durch Überschreiben der Tabler-/h_da-CSS-Variablen; dadurch
   ziehen die Standard-Komponenten automatisch mit.
   --------------------------------------------------------------------------- */

/* Umschalt-Button */
.hda-theme-toggle {
    border: 0;
    background: transparent;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
}
.hda-theme-toggle .icon { width: 1.4rem; height: 1.4rem; }
.theme-contrast .hda-theme-toggle { outline: 2px solid #000; outline-offset: 1px; }

/* Kern des Kontrast-Themes: Farbvariablen auf Schwarz/Weiß umbiegen.
   Markenfarben (Orange, Anthrazit, Grautöne) werden zu reinem Schwarz. */
.theme-contrast {
    --hda-brand:       #000;   /* Primärfarbe im Kontrast-Modus */
    --hda-brand-dark:  #000;
    --hda-orange:      #000;
    --hda-orange-dark: #000;
    --hda-anthracite:  #000;

    --tblr-primary: #000;
    --tblr-primary-rgb: 0, 0, 0;
    --tblr-primary-darken: #000;

    --tblr-body-bg: #fff;
    --tblr-body-color: #000;
    --tblr-secondary: #000;
    --tblr-muted: #000;
    --tblr-border-color: #000;
    --tblr-border-color-translucent: #000;
    --tblr-bg-surface: #fff;
    --tblr-bg-surface-secondary: #fff;
    --tblr-bg-surface-tertiary: #fff;

    --tblr-link-color: #000;
    --tblr-link-color-rgb: 0, 0, 0;

    --bs-body-bg: #fff;
    --bs-body-color: #000;
    --bs-link-color: #000;

    background-color: #fff;
    color: #000;
}

/* Grundflächen hart auf Weiß/Schwarz ziehen (auch dort, wo Tabler feste
   Farbwerte statt Variablen verwendet). */
.theme-contrast body,
.theme-contrast .page,
.theme-contrast .page-wrapper,
.theme-contrast .card,
.theme-contrast .navbar,
.theme-contrast .dropdown-menu,
.theme-contrast .table { background-color: #fff; color: #000; }

.theme-contrast .text-muted,
.theme-contrast .text-secondary,
.theme-contrast .small,
.theme-contrast small { color: #000 !important; }

/* Kräftige, durchgehend schwarze Ränder für klare Abgrenzung */
.theme-contrast .card,
.theme-contrast .dropdown-menu,
.theme-contrast .table td,
.theme-contrast .table th,
.theme-contrast .form-control,
.theme-contrast .form-select,
.theme-contrast .btn { border: 2px solid #000; }
.theme-contrast .navbar,
.theme-contrast .page-header { border-bottom: 2px solid #000; }

/* Links immer unterstrichen und schwarz */
.theme-contrast a,
.theme-contrast .nav-link { color: #000 !important; }
.theme-contrast a { text-decoration: underline; }
.theme-contrast .navbar-brand .fw-bold { color: #000; }

/* Primär-Buttons invertiert: schwarze Fläche, weißer Text, klarer Fokus */
.theme-contrast .btn-primary {
    --tblr-btn-color: #fff;
    --tblr-btn-bg: #000;
    --tblr-btn-border-color: #000;
    --tblr-btn-hover-color: #000;
    --tblr-btn-hover-bg: #fff;
    --tblr-btn-hover-border-color: #000;
    color: #fff;
    background-color: #000;
    border-color: #000;
}
.theme-contrast .btn-primary:hover { color: #000; background-color: #fff; }
.theme-contrast .btn:focus-visible,
.theme-contrast a:focus-visible { outline: 3px solid #000; outline-offset: 2px; }

/* Navigation: aktiver/gehoverter Zustand über Fläche statt Farbe deutlich machen */
.theme-contrast .navbar .navbar-nav .nav-link:hover {
    background-color: #000;
    color: #fff !important;
}
.theme-contrast .navbar .nav-item.active .nav-link {
    background-color: #000;
    color: #fff !important;
}

/* Studienplanungsraster: Zustände über Rahmenstärke/Muster statt Farbe */
.theme-contrast .planning-course,
.theme-contrast .planning-course-open,
.theme-contrast .planning-course-done,
.theme-contrast .planning-course-pvl {
    background: #fff;
    border: 2px solid #000;
    color: #000;
}
.theme-contrast .planning-course-done { border-width: 4px; }
.theme-contrast .planning-course-pvl { border-style: dashed; }

/* Chat */
.theme-contrast .chat-suggestion {
    background: #fff;
    border: 2px solid #000;
    color: #000;
}
.theme-contrast .chat-suggestion:hover { background: #000; color: #fff; }
.theme-contrast .chat-msg-user { background: #fff; border: 2px solid #000; }
.theme-contrast .debug-context-bar { background: #fff; border: 2px solid #000; }

/* ---------------------------------------------------------------------------
   Struktur-Editor (Studienabschnitt → Semester → Modul + Leistungsnummern)
   Split-View; portiert aus dem Referenz-monitoring-editor, an Tabler/h_da
   und den Dark-Mode angepasst.
   --------------------------------------------------------------------------- */
.split-view {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
}
.left-panel {
    flex: 1;
    min-width: 0;
    max-height: calc(100vh - 15rem);
    overflow-y: auto;
}
.right-panel {
    width: 300px;
    flex: 0 0 300px;
    position: sticky;
    top: 1rem;
    max-height: calc(100vh - 15rem);
    overflow-y: auto;
    background: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 8px;
    padding: 0.75rem;
}
@media (max-width: 992px) {
    .split-view { flex-direction: column; }
    .right-panel { width: 100%; flex-basis: auto; position: static; }
}
.unassigned-header {
    font-weight: 600;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid var(--hda-brand);
    margin-bottom: 0.5rem;
}

/* Studienabschnitt */
.structure-section {
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 8px;
    margin-bottom: 1rem;
    background: var(--tblr-bg-surface, #fff);
}
.structure-section-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    border-bottom: 2px solid var(--hda-brand);
}
.structure-section-head .section-name { max-width: 22rem; }
.section-actions { display: flex; gap: 0.35rem; margin-left: auto; }

/* Semester */
.semester-section {
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 6px;
    margin: 0.6rem 0.75rem;
    overflow: hidden;
}
.semester-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.6rem;
    background: var(--tblr-bg-surface-secondary, #f4f5f7);
    border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
}
.semester-title-input { max-width: 16rem; font-weight: 600; }
.semester-actions { display: flex; align-items: center; margin-left: auto; }
.semester-body { padding: 0.6rem; }
.semester-body.drag-over { background: rgba(157, 196, 30, 0.06); }

/* Modulkarte */
.module-card {
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 6px;
    padding: 0.5rem;
    margin-bottom: 0.5rem;
    background: var(--tblr-bg-surface, #fff);
    cursor: move;
}
.module-card.dragging { opacity: 0.5; border-color: var(--hda-brand); }
.module-card.drag-over-top { border-top: 3px solid var(--hda-brand); }
.module-card.drag-over-bottom { border-bottom: 3px solid var(--hda-brand); }
.module-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}
.module-name-input { font-weight: 600; }
.module-actions { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }
.module-actions .cp-input { width: 6rem; }
.required-toggle { white-space: nowrap; font-size: 0.8rem; }

/* PL-/PVL-Zonen */
.leistung-zones { display: flex; gap: 0.5rem; }
.leistung-zone {
    flex: 1;
    min-height: 3rem;
    padding: 0.4rem;
    border: 2px dashed var(--tblr-border-color, #e6e7e9);
    border-radius: 6px;
    background: var(--tblr-bg-surface-secondary, #f8f9fa);
}
.leistung-zone.drag-over { border-color: var(--hda-brand); background: rgba(157, 196, 30, 0.08); }
.leistung-zone-label {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--tblr-secondary, #6c757d);
    margin-bottom: 0.3rem;
}

/* Leistungs-Badge */
.leistung-badge {
    display: inline-block;
    padding: 0.15rem 0.45rem;
    margin: 0.15rem 0.15rem 0 0;
    border-radius: 4px;
    font-size: 0.78rem;
    font-family: var(--tblr-font-monospace, monospace);
    color: #fff;
    cursor: move;
}
.leistung-badge.dragging { opacity: 0.5; }
.leistung-badge.in-pl  { background: var(--hda-brand); }
.leistung-badge.in-pvl { background: var(--hda-blue); }
.leistung-badge.unassigned { background: var(--tblr-secondary, #6c757d); }

.add-module-btn-container {
    text-align: center;
    padding-top: 0.5rem;
    border-top: 1px dashed var(--tblr-border-color, #e6e7e9);
}

/* Nummern-Pool */
#pool-container.drag-over {
    outline: 2px dashed var(--hda-brand);
    outline-offset: 2px;
    border-radius: 6px;
}
.pool-item {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    margin-bottom: 0.35rem;
}
.pool-drag {
    cursor: grab;
    color: var(--tblr-secondary, #6c757d);
    padding: 0 0.15rem;
    user-select: none;
}
.pool-item .pool-num { width: 5.5rem; flex: 0 0 5.5rem; font-family: var(--tblr-font-monospace, monospace); }
.pool-item .pool-name { flex: 1; min-width: 0; }

/* Struktur-Editor im Kontrast-Theme */
.theme-contrast .right-panel,
.theme-contrast .structure-section,
.theme-contrast .module-card {
    background: #fff;
    border: 2px solid #000;
}
.theme-contrast .semester-header { background: #fff; border-bottom: 2px solid #000; }
.theme-contrast .leistung-zone { background: #fff; border: 2px solid #000; }

/* ---------------------------------------------------------------------------
   Interaktiver Studienplan (Studienplanung) — CP-proportionales Semester-Grid.
   Modulhöhe ∝ CP (Flexbox), native Drag&Drop-Zustände, leichtes Modal.
   --------------------------------------------------------------------------- */
.plan-grid {
    display: flex;
    gap: 0.5rem;
    overflow: hidden;           /* kein Scrollen — die Card wird stattdessen breiter */
    align-items: stretch;
}
.plan-semester {
    /* Spalten teilen sich die verfügbare Breite gleichmäßig (kein Scroll). */
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.plan-semester-head {
    border-bottom: 2px solid var(--hda-brand);
    padding-bottom: 0.4rem;
    margin-bottom: 0.5rem;
}
/* Aktuelles Semester dezent hervorheben */
.plan-semester-current {
    background: rgba(157, 196, 30, 0.06);
    border-radius: 6px;
}
.plan-semester-current .plan-sem-code { color: var(--hda-brand-dark); }
/* +/- Steuerspalten an den Enden (Semester hinzufügen/entfernen) */
.plan-control {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding-top: 0.1rem;
    align-self: flex-start;
}
.plan-ctl {
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    font-size: 1.1rem;
    line-height: 1;
    font-weight: 700;
}
.plan-courses {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    /* Nutzt die verfügbare vertikale Fläche (kein Innen-Scroll); Module teilen
       sie sich proportional zu ihren CP. */
    height: calc(100vh - 20rem);
    min-height: 460px;
}
.plan-course {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 2rem;
    padding: 0.35rem 0.4rem 1rem;
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 6px;
    background: var(--tblr-bg-surface, #fff);
    font-size: 0.8rem;
    line-height: 1.1;
    cursor: move;
    overflow: hidden;
}
.plan-course-name { font-weight: 600; max-width: 100%; overflow: hidden; }
.plan-add-course { border-style: dashed; }

/* QR-Kachel (Planung teilen) — weißer Grund, damit in jedem Theme scanbar */
.qr-tile {
    flex: 0 0 auto;
    background: #fff;
    padding: 4px;
    border-radius: 6px;
    line-height: 0;
}
.qr-tile svg, .qr-tile img { display: block; width: 96px; height: 96px; }
.plan-course-cp { position: absolute; bottom: 2px; right: 5px; font-size: 0.62rem; color: var(--tblr-muted, #6c757d); }
.plan-course-attempts { margin-top: 0.2rem; font-size: 0.6rem; }
.plan-course-done { background: rgba(123, 173, 38, 0.16); border-color: rgba(123, 173, 38, 0.5); }
.plan-course-pvl  { background: rgba(81, 156, 219, 0.16); border-color: rgba(81, 156, 219, 0.5); }
.plan-course.dragging { opacity: 0.5; }
.plan-course.drag-over-top { border-top: 3px solid var(--hda-brand); }
.plan-course.drag-over-bottom { border-bottom: 3px solid var(--hda-brand); }
.plan-courses.drag-over { outline: 2px dashed var(--hda-brand); outline-offset: 2px; border-radius: 6px; }
.plan-add-course { border-style: dashed; }

/* Leichtes eigenes Modal (unabhängig von Bootstrap-JS) */
.plan-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(35, 31, 32, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1080;
    padding: 1rem;
}
.plan-modal { width: 100%; max-width: 420px; margin: 0; }

/* Dark-Mode */
.theme-dark .plan-course { background: var(--tblr-bg-surface, #1a2332); border-color: var(--tblr-border-color, #2a3448); }
.theme-dark .plan-course-done { background: rgba(123, 173, 38, 0.24); }
.theme-dark .plan-course-pvl  { background: rgba(81, 156, 219, 0.24); }

/* Kontrast-Theme */
.theme-contrast .plan-course { background: #fff; border: 2px solid #000; color: #000; }
.theme-contrast .plan-course-done { background: #d7ecc0; }
.theme-contrast .plan-course-pvl  { background: #cfe4f6; }

/* ---------------------------------------------------------------------------
   Willkommens-Hero (.portal-welcome) — die Begrüßungsbox oben auf Hauptseiten.
   Verlaufsfläche, links Icon + Titel + Lead, rechts eine unDraw-Illustration
   (.portal-welcome-art, auf schmalen Breiten ausgeblendet), darunter optional
   die .portal-step-Kacheln als Einstiege.

   Die Fläche liegt bewusst in h_da-Orange statt in der Marken-/Primärfarbe:
   Anthrazit ergäbe einen grauen Verlauf ohne Signalwirkung. Icon-Kachel und
   Chrome bleiben über --hda-brand in der Primärfarbe.
   --------------------------------------------------------------------------- */
.portal-welcome {
    border-radius: 16px;
    padding: 1.75rem 1.9rem;
    background: linear-gradient(135deg,
        rgba(var(--hda-orange-rgb, 233, 128, 17), 0.13) 0%,
        rgba(var(--hda-orange-rgb, 233, 128, 17), 0.02) 62%);
    border: 1px solid rgba(var(--hda-orange-rgb, 233, 128, 17), 0.22);
}
/* Obere Zeile: Text links, Illustration rechts. Die Kacheln liegen bewusst
   ausserhalb davon und spannen darunter ueber die volle Breite. */
.portal-welcome-main {
    display: flex;
    align-items: center;
    gap: 2rem;
}
.portal-welcome-body { flex: 1 1 auto; min-width: 0; }
.portal-welcome-head { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.7rem; }
.portal-welcome-icon {
    flex-shrink: 0;
    width: 56px; height: 56px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 15px;
    background: var(--hda-brand, #E98011);
    color: #fff;
    box-shadow: 0 8px 20px rgba(var(--hda-brand-rgb, 233, 128, 17), 0.30);
}
.portal-welcome-icon i { font-size: 1.7rem; }
.portal-welcome h1,
.portal-welcome h2 {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--hda-anthracite, #231F20);
}
.portal-welcome-lead {
    margin: 0;
    max-width: 62ch;
    color: #5b6570;
    font-size: 1rem;
    line-height: 1.55;
}
.portal-welcome-art { flex-shrink: 0; width: 300px; }
.portal-welcome-art img { width: 100%; height: auto; }
/* Die Illustration ist Dekoration — sie weicht vor dem Text zurück. */
@media (max-width: 991.98px) { .portal-welcome-art { display: none; } }

/* Einstiegs-Kacheln unter dem Lead. Als <a> klickbar, als <div> rein
   beschreibend — die Optik ist identisch.
   ``auto-fit`` statt fester Spaltenzahl: die Zahl der Einstiege wächst mit den
   Funktionen der Anwendung, und eine vierte Kachel soll die Reihe füllen
   statt allein in einer zweiten Zeile zu stehen. */
.portal-steps {
    display: grid; gap: 0.9rem;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    margin-top: 1.4rem;
}
@media (max-width: 575.98px) { .portal-steps { grid-template-columns: 1fr; } }
.portal-step {
    display: flex; gap: 0.85rem;
    padding: 0.95rem 1.05rem;
    border-radius: 12px;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.07);
    text-decoration: none;
    color: inherit;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
/* Beim Überfahren hebt sich die Kachel leicht an — als Aufforderung genügt die
   Bewegung; eine Unterstreichung des Textes würde die Kachel wie einen Fließtext-
   Link aussehen lassen, obwohl die ganze Fläche klickbar ist. */
a.portal-step:hover,
a.portal-step:focus-visible {
    transform: translateY(-3px);
    box-shadow: 0 6px 18px rgba(35, 31, 32, 0.10);
    border-color: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.45);
    text-decoration: none;
    color: inherit;
}
a.portal-step:hover .portal-step-title,
a.portal-step:hover .portal-step-text { text-decoration: none; }

/* Wer „reduzierte Bewegung" eingestellt hat, bekommt nur die Umrandung. */
@media (prefers-reduced-motion: reduce) {
    .portal-step { transition: border-color .15s ease; }
    a.portal-step:hover, a.portal-step:focus-visible { transform: none; box-shadow: none; }
}
.portal-step-icon {
    flex-shrink: 0;
    width: 38px; height: 38px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 10px;
    /* Akzentfarbe je Kachel über --step-accent(-rgb); Default = Marke. */
    background: rgba(var(--step-accent-rgb, var(--hda-brand-rgb, 233, 128, 17)), 0.14);
    color: var(--step-accent, var(--hda-brand, #E98011));
}
.portal-step-title { font-weight: 600; font-size: 0.94rem; }
.portal-step-text { color: #7a828b; font-size: 0.84rem; line-height: 1.4; }

/* Kontrast-Modus: Verlauf und Farbtints weichen Schwarz-Weiß, die dekorative
   Illustration wird entsättigt. */
.theme-contrast .portal-welcome { background: #fff; border: 2px solid #000; }
.theme-contrast .portal-welcome-icon { background: #000; color: #fff; box-shadow: none; }
.theme-contrast .portal-welcome-lead,
.theme-contrast .portal-step-text { color: #000; }
.theme-contrast .portal-step { background: #fff; border: 2px solid #000; }
.theme-contrast .portal-step-icon { background: #fff; border: 2px solid #000; color: #000; }
.theme-contrast .portal-welcome-art img { filter: grayscale(1); }

/* ---------------------------------------------------------------------------
   Kompakte Hero-Variante (.portal-welcome--compact)
   Wird im eingeloggten Bereich (alle Arbeitsseiten außer dem Dashboard) an die
   portal-welcome-Box gehängt. Ziel: gleiche Breite, aber kleineres Icon/Bild/
   Text und spürbar weniger vertikale Höhe.
   Überschrieben wird mit doppeltem Klassen- bzw. Nachfahren-Selektor (höhere
   Spezifität) statt per !important.
   --------------------------------------------------------------------------- */
.portal-welcome.portal-welcome--compact {
    padding-top: 1.25rem;
    padding-bottom: 1.25rem;
}
.portal-welcome--compact .portal-welcome-head { margin-bottom: 0.5rem; }
.portal-welcome--compact .portal-welcome-icon {
    width: 46px; height: 46px; border-radius: 11px;
    box-shadow: 0 5px 14px rgba(var(--hda-brand-rgb, 233, 128, 17), 0.28);
}
.portal-welcome--compact .portal-welcome-icon i { font-size: 1.4rem; }
.portal-welcome--compact h2 { font-size: 1.35rem; }
.portal-welcome--compact .portal-welcome-lead {
    font-size: 0.92rem; line-height: 1.45; margin-bottom: 0.75rem;
}
.portal-welcome--compact .portal-welcome-art { width: 190px; }

/* ---------------------------------------------------------------------------
   Hero-Kontext (.hero-context) — die „aktuell selektiert / zugeordnet"-Zeile
   im Hero, app-weit einheitlich. Label + Chips: read-only als <span> oder
   navigierbar als <a class="hero-context-chip">; für Pfade Chevron-Trenner
   (.hero-context-sep). Farben über die Marken-Variablen (kippen im Staff-Theme
   automatisch auf Orange). Einzige Quelle — nicht pro Seite nachbauen.
   --------------------------------------------------------------------------- */
.hero-context { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.hero-context-label {
    font-size: 0.9rem; font-weight: 600; color: var(--hda-anthracite, #231F20);
    display: inline-flex; align-items: center; gap: 0.35rem;
}
.hero-context-chip {
    display: inline-flex; align-items: center; gap: 0.3rem;
    font-size: 0.82rem; font-weight: 600; padding: 0.2rem 0.7rem; border-radius: 999px;
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.14);
    color: var(--hda-brand-dark, #CF6F0C);
    text-decoration: none; transition: background .12s, color .12s;
}
a.hero-context-chip:hover {
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.24);
    color: var(--hda-brand-dark, #CF6F0C);
}
.hero-context-sep { color: var(--tblr-secondary, #97a0ad); font-size: 0.9rem; opacity: .7; }
.hero-context-none { font-size: 0.85rem; color: var(--tblr-secondary, #7a828b); font-style: italic; }

/* ---------------------------------------------------------------------------
   Dokument-Vorschau — extrahierter Text im Modal
   Die Zeilenstruktur des Extrakts bleibt erhalten (pre-wrap), weil sie bei
   Prüfungsordnungen und Modulhandbüchern bedeutungstragend ist. Lange Zeilen
   werden umbrochen statt horizontal zu scrollen.
   --------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   Studiengang-Chat (rechte Spalte der Detailseite)
   Das Fenster bleibt beim Scrollen stehen und begrenzt seine Höhe selbst — der
   Verlauf scrollt darin, nicht die Seite.
   --------------------------------------------------------------------------- */
@media (min-width: 992px) {
    .chat-panel {
        position: sticky;
        top: 5rem;                     /* unter der sticky Navbar */
        max-height: calc(100vh - 7rem);
        display: flex;
        flex-direction: column;
    }
}
.chat-verlauf {
    overflow-y: auto;
    min-height: 14rem;
    max-height: 60vh;
}
.chat-bubble {
    max-width: 92%;
    padding: 0.5rem 0.75rem;
    border-radius: 12px;
    font-size: 0.875rem;
    line-height: 1.45;
}
.chat-bubble-frage {
    background: var(--hda-brand, #E98011);
    color: #fff;
    border-bottom-right-radius: 3px;
}
.chat-bubble-antwort {
    background: var(--tblr-secondary-bg, #f5f7fb);
    color: var(--tblr-body-color, #1a2234);
    border-bottom-left-radius: 3px;
}
.chat-bubble-fehler {
    background: rgba(var(--tblr-red-rgb, 172, 27, 33), 0.12);
    color: var(--hda-red, #AC1B21);
    border-bottom-left-radius: 3px;
}
.chat-vorschlag { cursor: pointer; }

/* ---------------------------------------------------------------------------
   Bestandsrecherche (/chat/): Werkzeugprotokoll unter der Frage.
   Bewusst zurückhaltend gesetzt — es begleitet die Antwort, statt mit ihr um
   Aufmerksamkeit zu ringen. Der Verlauf darf höher werden als in den
   Seitenleisten-Chats, weil er hier die Hauptspalte füllt.
   --------------------------------------------------------------------------- */
.agent-verlauf { max-height: min(62vh, 40rem); }
.agent-vorschlag { cursor: pointer; }

.agent-protokoll {
    font-size: 0.8125rem;
    border-left: 2px solid var(--hda-orange, #E98011);
    padding-left: 0.75rem;
}
.agent-protokoll > summary {
    cursor: pointer;
    color: var(--tblr-secondary-color, #667382);
    list-style: none;
}
.agent-protokoll > summary::-webkit-details-marker { display: none; }
.agent-protokoll > summary::before {
    content: "▸";
    display: inline-block;
    margin-right: 0.35rem;
    transition: transform 0.15s ease;
}
.agent-protokoll[open] > summary::before { transform: rotate(90deg); }

.agent-schritte {
    margin: 0.5rem 0 0;
    padding-left: 1.25rem;
}
.agent-schritte > li + li { margin-top: 0.4rem; }
.agent-schritte code {
    background: var(--tblr-secondary-bg, #f5f7fb);
    padding: 0 0.25rem;
    border-radius: 3px;
}
.agent-argument {
    display: inline-block;
    margin-left: 0.35rem;
    padding: 0 0.3rem;
    border-radius: 3px;
    background: var(--tblr-secondary-bg, #f5f7fb);
    color: var(--tblr-secondary-color, #667382);
    font-family: var(--tblr-font-monospace, monospace);
    font-size: 0.75rem;
    overflow-wrap: anywhere;
}

/* Fundstellen der Volltextsuche: alle gelb, die gerade angesteuerte in Orange
   mit Rahmen — sonst wäre beim Durchsteppen nicht erkennbar, wo man steht. */
.doc-preview-text mark.doc-hit {
    background: var(--hda-yellow, #FCCB06);
    color: var(--hda-anthracite, #231F20);
    padding: 0 1px;
    border-radius: 2px;
}
.doc-preview-text mark.doc-hit-active {
    background: var(--hda-orange, #E98011);
    color: #fff;
    box-shadow: 0 0 0 2px var(--hda-orange-dark, #CF6F0C);
}

.doc-preview-text {
    margin: 0;
    padding: 0.75rem 1rem 1.5rem;
    background: transparent;
    border: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--tblr-body-color, #1a2234);
}

/* ---------------------------------------------------------------------------
   TomSelect – Höhe an .form-control/.form-select angleichen
   Tabler rechnet 0.5625rem Innenabstand + 1.25rem Zeilenhöhe + Rahmen = 40px,
   TomSelect bringt eigene 0.375rem mit und steht dadurch rund 5px niedriger.
   In einer Filterzeile stehen Textfeld, natives Select und TomSelect
   nebeneinander — ohne diese Angleichung fluchten sie nicht.
   --------------------------------------------------------------------------- */
.ts-wrapper .ts-control {
    padding: 0.5625rem 1rem;
    font-size: 0.875rem;
    line-height: 1.25rem;
    min-height: calc(1.25rem + 1.125rem + 2px);
}
.ts-wrapper.single .ts-control > .item,
.ts-wrapper .ts-control > input {
    font-size: 0.875rem;
    line-height: 1.25rem;
}
/* Mehrfachauswahl: Chips dürfen die Grundhöhe nicht sprengen. */
.ts-wrapper.multi.has-items .ts-control {
    padding: calc(0.5625rem - 1px) 1rem calc(0.5625rem - 4px);
}

/* ---------------------------------------------------------------------------
   TomSelect – Clear-Button („×" zum Abwählen) für Single-Selects
   Aktiviert in select-widgets.js (plugins: ["clear_button"]). Das × soll nur
   erscheinen, wenn wirklich etwas gewählt ist, und links vom Dropdown-Pfeil
   sitzen (nicht darüber).
   --------------------------------------------------------------------------- */
.ts-wrapper.single .clear-button {
    position: absolute;
    top: 50%;
    right: 1.9rem;                 /* links vom Dropdown-Caret */
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.15rem;
    height: 1.15rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--tblr-secondary, #667382);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.6;
    transition: opacity .12s, background .12s, color .12s;
}
.ts-wrapper.single .clear-button:hover {
    opacity: 1;
    color: var(--hda-brand-dark, #CF6F0C);
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.14);
}
/* Nur bei aktiver Auswahl zeigen (TomSelect setzt .has-items am Wrapper). */
.ts-wrapper.single:not(.has-items) .clear-button { display: none; }

/* ---------------------------------------------------------------------------
   Dual-List-Widget (.dual-list)
   Zwei-Spalten-Zuordnung per Verschieben (core/js/dual-list.js). Progressive
   Enhancement über ein <select multiple>; das native Select wird versteckt,
   bleibt aber für den Submit im DOM. Optik ausschließlich über --hda-*/Tabler.
   --------------------------------------------------------------------------- */
.dual-list__native { display: none !important; }

.dual-list {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 0.5rem;
    align-items: stretch;
}
.dual-list__pane {
    display: flex;
    flex-direction: column;
    min-width: 0;
    border: 1px solid var(--tblr-border-color, #dadfe5);
    border-radius: var(--bs-border-radius, 4px);
    background: var(--tblr-card-bg, #fff);
    overflow: hidden;
}
.dual-list__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.4rem 0.6rem;
    font-size: 0.8rem;
    font-weight: 600;
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.08);
    border-bottom: 1px solid var(--tblr-border-color, #dadfe5);
}
.dual-list__count {
    min-width: 1.4rem;
    padding: 0 0.4rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-align: center;
    color: var(--hda-brand-dark, #CF6F0C);
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.16);
    border-radius: 999px;
}
.dual-list__search { padding: 0.4rem 0.5rem; }
.dual-list__items {
    flex: 1 1 auto;
    min-height: 190px;
    max-height: 260px;
    overflow-y: auto;
    padding: 0.25rem;
}
.dual-list__item {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.34rem 0.55rem;
    border: 0;
    border-radius: var(--bs-border-radius-sm, 3px);
    background: transparent;
    color: inherit;
    font-size: 0.86rem;
    line-height: 1.3;
    cursor: pointer;
}
.dual-list__item:hover { background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.10); }
.dual-list__item.is-active {
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.20);
    color: var(--hda-brand-dark, #CF6F0C);
    font-weight: 600;
}
.dual-list__item.is-disabled { opacity: 0.45; cursor: not-allowed; }
.dual-list__empty {
    padding: 1rem 0.6rem;
    text-align: center;
    font-size: 0.82rem;
    color: var(--tblr-secondary, #667382);
}
.dual-list__controls {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.4rem;
}
.dual-list__ctl { flex: 0 0 auto; }

@media (max-width: 575.98px) {
    .dual-list { grid-template-columns: 1fr; }
    .dual-list__controls { flex-direction: row; justify-content: center; }
    .dual-list__controls .dual-list__ctl i { transform: rotate(90deg); }
}

/* Drag-&-Drop-Sortierung (sortable-rows.js): Greifpunkt + Zustand der gezogenen Zeile. */
.sortable-handle {
    cursor: grab;
    color: var(--hda-grey, #9aa4ad);
    touch-action: none;
}
.sortable-handle:active { cursor: grabbing; }
[data-sortable] .is-dragging {
    opacity: 0.55;
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.10);
}

/* ---------------------------------------------------------------------------
 * Hochschulkarte (Leaflet, siehe hda/js/hochschul-karte.js)
 * Farben laufen über den Marken-Slot, damit der Kontrastmodus automatisch
 * mitzieht — Leaflets eigene Cluster-Optik wird dafür ersetzt.
 * ------------------------------------------------------------------------- */
.hochschul-karte {
    height: 460px;
    width: 100%;
    /* Unter den abgerundeten Card-Ecken sonst sichtbare Kanten. */
    border-bottom-left-radius: var(--tblr-border-radius, 4px);
    border-bottom-right-radius: var(--tblr-border-radius, 4px);
    z-index: 0;  /* hält die Karte unter der sticky Navbar (z-index 1030) */
}

/* Cluster-Blase: eigene Optik statt der grün-gelben Standardfarben von
   MarkerCluster.Default.css. */
.hda-cluster {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.85);
    border: 2px solid #fff;
    box-shadow: 0 2px 6px rgba(35, 31, 32, 0.30);
    color: #fff;
    font-weight: 700;
    font-size: 0.85rem;
}
.marker-cluster-small,
.marker-cluster-medium,
.marker-cluster-large { background: none; }
.marker-cluster-small div,
.marker-cluster-medium div,
.marker-cluster-large div { background: none; }

.karte-popup strong { display: block; margin-bottom: 0.15rem; }
.leaflet-popup-content { font-family: var(--hda-font-sans); margin: 0.75rem 0.9rem; }

/* Kontrastmodus: Marker, Cluster und Kartenrahmen auf Schwarz-Weiß. Die
   Kacheln selbst werden entsättigt, damit die Punkte darauf lesbar bleiben. */
.theme-contrast .hochschul-karte { border: 2px solid #000; }
.theme-contrast .leaflet-tile-pane { filter: grayscale(1) contrast(1.1); }
.theme-contrast .hda-cluster {
    background: #000;
    border-color: #fff;
    box-shadow: none;
}

/* ---------------------------------------------------------------------------
 * Dokument-Volltext (GI-Empfehlungen, siehe hda/js/volltext-suche.js)
 * ------------------------------------------------------------------------- */
.gi-dokument {
    max-height: 70vh;
    overflow-y: auto;
    /* Eigener Scrollbereich: das Dokument ist mehrere Hundert Seiten lang und
       soll die Seitennavigation nicht aus dem Blickfeld schieben. */
    padding-inline-end: 0.5rem;
}
.gi-seite + .gi-seite { border-top: 1px dashed var(--tblr-border-color, #e6e7e9); margin-top: 1.25rem; }
.gi-seite-nr {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 0.35rem 0;
    background: var(--tblr-bg-surface, #fff);
    color: var(--tblr-muted, #6c757d);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.gi-seite-text {
    /* Der Text kommt roh aus der PDF-Extraktion: Zeilenumbrüche gehören zum
       Original und werden bewusst beibehalten, lange Zeilen dürfen aber
       umbrechen statt horizontal zu scrollen. */
    white-space: pre-wrap;
    word-break: break-word;
    font-family: var(--hda-font-sans);
    font-size: 0.9rem;
    line-height: 1.55;
    color: var(--tblr-body-color, #1a2234);
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
}
mark.gi-treffer {
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.35);
    color: inherit;
    padding: 0.05em 0.1em;
    border-radius: 3px;
}

.theme-contrast mark.gi-treffer {
    background: #000;
    color: #fff;
}
.theme-contrast .gi-seite-nr { background: #fff; color: #000; }

/* ---------------------------------------------------------------------------
 * Vergleichsansicht (/vergleich/)
 * Produktvergleich-Muster: Spalten sind die verglichenen Programme, Zeilen die
 * Kriterien. Die Kriteriumsspalte bleibt beim Scrollen stehen, damit bei
 * mehreren Studiengängen klar bleibt, was verglichen wird.
 * ------------------------------------------------------------------------- */
.vgl-tabelle { min-width: 720px; }
.vgl-tabelle thead th {
    vertical-align: bottom;
    background: var(--tblr-bg-surface, #fff);
}
/* Zwei feststehende Spalten: die Kriteriumsspalte und die Referenzspalte
   daneben. Ohne die zweite verschwände der Maßstab beim Querscrollen — und
   ohne Maßstab sind die Werte rechts nicht einzuordnen.
   Die Breite der ersten Spalte ist deshalb fest: ``left`` der zweiten muss ein
   konkreter Wert sein, keine Ableitung aus dem Inhalt. */
.vgl-tabelle {
    --vgl-spalte-1: 17rem;
}
.vgl-kriterium-spalte {
    position: sticky;
    left: 0;
    z-index: 3;
    width: var(--vgl-spalte-1);
    min-width: var(--vgl-spalte-1);
    max-width: var(--vgl-spalte-1);
    background: var(--tblr-bg-surface, #fff);
    font-weight: 600;
    white-space: normal;
    /* Trennt die Beschriftung sichtbar von den Werten, auch beim Querscrollen. */
    box-shadow: 1px 0 0 var(--tblr-border-color, #e6e7e9);
}
.vgl-kriterium-hinweis {
    font-weight: 400;
    font-size: 0.75rem;
    color: var(--tblr-muted, #6c757d);
    margin-top: 0.15rem;
}
.vgl-kopf-name { font-weight: 700; }
.vgl-kopf-meta { font-size: 0.75rem; font-weight: 400; color: var(--tblr-muted, #6c757d); }

/* Die Referenzspalte (GI-Empfehlung) ist der Maßstab und bleibt deshalb
   dauerhaft hervorgehoben — nicht bloß beim Überfahren. */
.vgl-referenz-spalte {
    position: sticky;
    left: var(--vgl-spalte-1);
    z-index: 2;
    min-width: 15rem;
    /* Deckender Hintergrund: Eine feststehende Spalte liegt über dem
       Scrollinhalt. Mit halbdurchlässiger Farbe schimmerten die
       durchlaufenden Zellen hindurch — deshalb weiße Grundfläche plus den
       Orangeschleier als eigene Ebene darüber. */
    background-color: var(--tblr-bg-surface, #fff) !important;
    background-image: linear-gradient(
        rgba(var(--hda-brand-rgb, 233, 128, 17), 0.07),
        rgba(var(--hda-brand-rgb, 233, 128, 17), 0.07)
    );
    border-inline: 1px solid rgba(var(--hda-brand-rgb, 233, 128, 17), 0.25);
}

/* Auf schmalen Geräten bliebe neben zwei festen Spalten kaum Platz für die
   Werte — dort scrollt die Referenzspalte mit. */
@media (max-width: 767.98px) {
    .vgl-tabelle { --vgl-spalte-1: 11rem; }
    .vgl-referenz-spalte { position: static; }
}

.vgl-zelle { vertical-align: top; min-width: 13rem; }
.vgl-wert { white-space: normal; line-height: 1.45; }
.vgl-quelle {
    margin-top: 0.35rem;
    font-size: 0.72rem;
    color: var(--tblr-muted, #6c757d);
}
.vgl-quelle .ti { margin-inline-end: 0.2em; }

/* Bewertung: ein schmaler Streifen am Zeilenanfang statt eingefärbter Fläche —
   die Farbe soll die Lesbarkeit des Textes nicht beeinträchtigen. */
.vgl-zelle--erfuellt { box-shadow: inset 3px 0 0 var(--tblr-green, #7BAD26); }
.vgl-zelle--knapp    { box-shadow: inset 3px 0 0 var(--tblr-yellow, #FCCB06); }
.vgl-zelle--verfehlt { box-shadow: inset 3px 0 0 var(--tblr-red, #AC1B21); }

.vgl-legende { display: inline-flex; align-items: center; gap: 0.35rem; }
.vgl-punkt { width: 0.7rem; height: 0.7rem; border-radius: 2px; display: inline-block; }
.vgl-punkt--erfuellt { background: var(--tblr-green, #7BAD26); }
.vgl-punkt--knapp    { background: var(--tblr-yellow, #FCCB06); }
.vgl-punkt--verfehlt { background: var(--tblr-red, #AC1B21); }

/* Auswahlleiste über der Tabelle. Die Matrix ist der breiteste Teil der Seite —
   die Auswahl liegt deshalb quer darüber statt in einer Seitenspalte, die der
   Tabelle ein Viertel der Breite nähme. */
.vgl-auswahl-zeile {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.vgl-auswahl-titel {
    flex: 0 0 auto;
    min-width: 11rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--tblr-muted, #6c757d);
}
.vgl-chips,
.vgl-kriterien-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    flex: 1 1 20rem;
    align-items: center;
}
.vgl-hinzufuegen { width: auto; min-width: 15rem; }

/* Umbrechende Schalter statt untereinander stehender Checkboxen — Tablers
   .form-selectgroup-item wirkt ohne den Gruppen-Wrapper sonst nicht. */
.vgl-kriterien-pills .form-selectgroup-item { margin: 0; }
.vgl-kriterien-pills .form-selectgroup-label {
    font-size: 0.82rem;
    padding: 0.3rem 0.6rem;
}

.vgl-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.55rem;
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 8px;
    max-width: 22rem;
}
.vgl-chip--referenz {
    border-color: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.45);
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.07);
}
/* Abgewählt: bleibt sichtbar, tritt aber zurück — sonst wäre der Weg zurück
   nicht auffindbar. */
.vgl-chip--aus {
    border-color: var(--tblr-border-color, #e6e7e9);
    background: none;
    opacity: 0.6;
}
.vgl-chip-body { min-width: 0; flex: 1; }
.vgl-chip-name { font-weight: 600; font-size: 0.85rem; line-height: 1.25; }
.vgl-chip-meta {
    font-size: 0.72rem;
    color: var(--tblr-muted, #6c757d);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Kontrastmodus: Bewertung über Musterstärke statt Farbe, Referenzspalte
   über einen kräftigen Rahmen. */
.theme-contrast .vgl-referenz-spalte {
    background: #fff !important;
    border-inline: 2px solid #000;
}
.theme-contrast .vgl-zelle--erfuellt { box-shadow: inset 4px 0 0 #000; }
.theme-contrast .vgl-zelle--knapp    { box-shadow: inset 4px 0 0 #666; }
.theme-contrast .vgl-zelle--verfehlt { box-shadow: inset 4px 0 0 #000, inset 8px 0 0 #fff, inset 12px 0 0 #000; }
.theme-contrast .vgl-punkt--erfuellt { background: #000; }
.theme-contrast .vgl-punkt--knapp    { background: #666; }
.theme-contrast .vgl-punkt--verfehlt { background: repeating-linear-gradient(45deg, #000, #000 2px, #fff 2px, #fff 4px); }

/* ---------------------------------------------------------------------------
   Feldherkunft (.herkunft-punkt)
   Kleiner farbiger Punkt neben einem Wert: woher stammt er, ist er bestätigt.
   Die Farbe kommt als Tabler-Utility (bg-green, bg-yellow, …) aus dem
   Read-Model — die Zuordnung Zustand → Farbe liegt in core/provenance.py und
   nicht hier, damit sie nicht an zwei Stellen gepflegt werden muss.
   --------------------------------------------------------------------------- */
/* Status-Icon hinter einem Feldwert. Als <button> ausgeführt, weil es
   anklickbar ist und per Tastatur erreichbar sein muss — optisch aber ein
   blosses Icon, deshalb ohne Rahmen und Hintergrund. */
.herkunft-icon {
    border: 0;
    background: none;
    padding: 0 0 0 0.35em;
    line-height: 1;
    font-size: 0.95em;
    cursor: pointer;
    vertical-align: baseline;
}
.herkunft-icon:hover { filter: brightness(0.8); }

/* Der Herkunfts-Tooltip trägt mehrere Zeilen samt Fundstelle aus der Quelle.
   Die Standardbreite von Bootstrap (200px) presst ein Zitat in zwanzig Zeilen;
   linksbündig, weil zentrierter Fließtext über mehrere Zeilen schwer zu lesen
   ist. */
/* Die Fundstelle in der Tabellenzeile: schmal gehalten, damit ein Zitat aus
   einer Prüfungsordnung die Spaltenbreiten nicht auseinanderzieht. Vollständig
   steht es im Modal hinter dem Statuspunkt. */
.herkunft-beleg-kurz {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--tblr-secondary, #6c757d);
    cursor: help;
}

/* Die Fundstelle im Herkunfts-Modal: als Zitat abgesetzt, damit sie nicht mit
   den Angaben darüber verschwimmt. Begrenzte Höhe, weil ein Abschnitt aus einer
   Prüfungsordnung sonst die Schaltflächen aus dem Modal schiebt. */
.herkunft-beleg {
    border-inline-start: 3px solid var(--hda-brand, #E98011);
    padding: 0.5rem 0.75rem;
    margin: 0;
    background: var(--tblr-bg-surface-secondary, rgba(0, 0, 0, 0.03));
    font-size: 0.875rem;
    line-height: 1.5;
    max-height: 11rem;
    overflow-y: auto;
}

/* Das Statuszeichen auf der Wertkarte im Herkunfts-Modal. Die Tabler-Icons sind
   Schrift-Icons und wachsen mit ``font-size``; die Utility-Klassen enden bei
   1,5 rem (``fs-1``) und wären hier zu klein — die Karte trägt eine einzige
   Aussage, und das Zeichen ist ihr Träger. ``line-height: 1`` hält es auf der
   Höhe des Werts daneben, statt es an der Zeilenhöhe hochzuschieben. */
.herkunft-status-icon {
    font-size: 2.75rem;
    line-height: 1;
}

.herkunft-tooltip .tooltip-inner {
    max-width: 26rem;
    text-align: start;
    line-height: 1.45;
}
.herkunft-icon:focus-visible { outline: 2px solid var(--hda-brand, #E98011); outline-offset: 2px; }

/* Im Kontrast-Modus trägt die Form, nicht die Farbe — die Icons sind bereits
   unterschiedlich geformt, also genügt es, sie alle auf Schwarz zu ziehen. */
.theme-contrast .herkunft-icon { color: #000 !important; }

.herkunft-punkt {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    /* Hebt den Punkt vom Text ab, ohne ihn auf die Grundlinie zu ziehen. */
    vertical-align: 0.1em;
    margin-inline-start: 0.4em;
    cursor: help;
}

/* Im Kontrast-Modus tragen die Punkte nicht mehr über die Farbe, sondern über
   die Form: gefüllt = bestätigt, offen = ungeprüft, gekreuzt = nicht vorhanden. */
.theme-contrast .herkunft-punkt { background: #fff !important; border: 2px solid #000; width: 10px; height: 10px; }
.theme-contrast .herkunft-punkt.bg-green { background: #000 !important; }
.theme-contrast .herkunft-punkt.bg-danger { background: repeating-linear-gradient(45deg, #000, #000 2px, #fff 2px, #fff 4px) !important; }

/* Klappbarer Auswahlbereich: Kopfzeile als Schaltfläche, Pfeil folgt dem Zustand. */
.vgl-auswahl-kopf {
    display: flex;
    align-items: center;
    cursor: pointer;
    user-select: none;
}
.vgl-auswahl-pfeil { transition: transform 0.2s ease; color: var(--tblr-muted, #6c757d); }
.vgl-auswahl-kopf.collapsed .vgl-auswahl-pfeil { transform: rotate(180deg); }

/* Vollbild (hda/js/fullscreen-toggle.js). Im echten Vollbild ist das Element
   der ganze Bildschirm — ohne eigene Hintergrundfarbe stünde es auf Schwarz. */
#vgl-matrix:fullscreen,
.is-pseudo-fullscreen {
    background: var(--tblr-bg-surface, #fff);
    padding: 1rem;
    overflow: auto;
}
#vgl-matrix:fullscreen .table-responsive,
.is-pseudo-fullscreen .table-responsive {
    /* Kopfzeile und Fußleiste der Karte abziehen, damit die Tabelle selbst
       scrollt und die Legende sichtbar bleibt. */
    max-height: calc(100vh - 9rem);
    overflow: auto;
}
.is-pseudo-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 1080;
    margin: 0;
    border-radius: 0;
}

/* Rückmeldungen zu einem Feld in der Prüfliste: kompakt unter dem Datensatz,
   damit sie die Zeile nicht sprengen, aber nicht zu übersehen sind. */
.herkunft-hinweis {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
    font-size: 0.85rem;
    padding: 0.2rem 0.4rem;
    border-inline-start: 3px solid var(--tblr-border-color, #dadfe5);
    background: rgba(0, 0, 0, 0.02);
    border-radius: 4px;
}

/* Auswahl-Modal des Vergleichs: scrollende Trefferliste mit Ankreuzfeldern. */
.vgl-auswahl-liste {
    max-height: 46vh;
    overflow-y: auto;
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: 8px;
}
.vgl-auswahl-eintrag {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.5rem 0.7rem;
    margin: 0;
    /* Standard: die Zeile ist nur bei den abgelesenen Kriterien als Ganzes
       anklickbar (dort ein <label>). Bei den Fragen ist sie ein <div>, weil der
       Fragetext bearbeitbar ist — ein Zeiger über dem ganzen Feld verspräche
       dort ein Umschalten, das der Klick nicht auslöst. */
    cursor: default;
}
label.vgl-auswahl-eintrag { cursor: pointer; }
.vgl-auswahl-eintrag + .vgl-auswahl-eintrag { border-top: 1px solid var(--tblr-border-color, #e6e7e9); }
.vgl-auswahl-eintrag:hover { background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.06); }
.vgl-auswahl-eintrag:has(input:checked) { background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.12); }

/* Fortschrittszeile über der Matrix, solange Antworten ausstehen. */
.vgl-fortschritt {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 1rem;
    border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.07);
    font-size: 0.875rem;
}

/* Zellen, deren Antwort noch aussteht, treten zurück — der Blick soll auf dem
   liegen, was schon da ist. */
.vgl-zelle-offen,
.vgl-zelle-wartet {
    background: repeating-linear-gradient(45deg, transparent, transparent 6px,
                                          rgba(0, 0, 0, 0.02) 6px, rgba(0, 0, 0, 0.02) 12px);
}

/* Die Frage ist der einzige Text der Zeile — entsprechend als Beschriftung
   gesetzt, nicht als Fußnote. Kursiv bleibt sie, damit erkennbar ist, dass hier
   ein Wortlaut steht und keine Rubrik. */
.vgl-frage {
    font-weight: 500;
    font-size: 0.82rem;
    line-height: 1.4;
    font-style: italic;
    white-space: normal;
}

/* Stand der Sprachmodell-Aufgaben im Seitenkopf. */
.worker-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0.6rem;
    margin-inline-end: 0.5rem;
    border-radius: 999px;
    background: rgba(var(--hda-brand-rgb, 233, 128, 17), 0.12);
    color: var(--hda-brand-dark, #CF6F0C);
    font-size: 0.8rem;
    white-space: nowrap;
}
.worker-status-chip--fehler {
    background: rgba(172, 27, 33, 0.10);
    color: var(--hda-red, #AC1B21);
}
.theme-contrast .worker-status-chip {
    background: #fff;
    border: 2px solid #000;
    color: #000;
}

.theme-contrast .vgl-fortschritt { background: #fff; border-bottom: 2px solid #000; }
.theme-contrast .vgl-auswahl-eintrag:has(input:checked) { background: #eee; }

/* ---------------------------------------------------------------------------
   Profil einer Studiengangsidee — formularartige Zweispalter
   Die Bezeichnungsspalte bleibt schmal und ruhig, damit die Werte die Seite
   tragen. Lange Texte brechen um, statt die Tabelle zu sprengen.
   --------------------------------------------------------------------------- */
.idee-profil th {
    vertical-align: top;
    padding-top: 0.6rem;
    font-size: 0.8125rem;
    line-height: 1.35;
    white-space: normal;
}
.idee-profil td {
    vertical-align: top;
    padding-top: 0.55rem;
    overflow-wrap: anywhere;
}
/* Das Inline-Feld füllt die Zelle, damit auch ein leeres Feld anklickbar ist. */
.idee-profil .inline-edit { min-height: 1.4em; }

/* Gutachten der GI-Prüfung: in Abschnitte gegliederter Klartext. Der Leerraum
   trägt die Gliederung, deshalb bleibt er erhalten. */
.gi-anmerkungen {
    white-space: pre-wrap;
    font-size: 0.9rem;
    line-height: 1.55;
    /* Lange Gutachten sollen die Spalte nicht endlos wachsen lassen. */
    max-height: 32rem;
    overflow-y: auto;
}

/* ===========================================================================
   Erschließung: Ablaufdiagramm und Schrittprotokoll (/erschliessung/<id>/)
   ===========================================================================

   Das Diagramm ist ein SVG, dessen Geometrie der Service rechnet (``_graph_layout``);
   hier steht nur, wie es aussieht. Die Farben der Feldknoten kommen aus derselben
   Statustabelle wie die Prüfliste (``STATUS_COLOR`` in provenance.py) — Graph und
   Liste sollen dieselbe Sprache sprechen. */

.ersch-svg {
    display: block;
    width: 100%;
    /* Über die ``viewBox`` skaliert es mit der Spalte; die Obergrenze verhindert,
       dass ein Diagramm aus vier Knoten auf einem breiten Schirm ins Plakathafte
       wächst. */
    max-width: 60rem;
    height: auto;
    margin: 0 auto;
    font-family: inherit;
}

.ersch-svg-kante {
    fill: none;
    stroke: var(--tblr-border-color, #dee2e6);
    stroke-width: 1.5;
}
.ersch-svg-spitze { fill: var(--tblr-border-color, #dee2e6); }

.ersch-svg-rahmen {
    fill: var(--tblr-bg-surface, #fff);
    stroke: var(--tblr-border-color, #dee2e6);
    stroke-width: 1;
}

/* Der Belegstand als linke Kante des Knotens. */
.ersch-svg-kennung--green     { fill: var(--tblr-green, #2fb344); }
.ersch-svg-kennung--yellow    { fill: var(--tblr-yellow, #f59f00); }
.ersch-svg-kennung--red,
.ersch-svg-kennung--danger    { fill: var(--tblr-red, #d63939); }
.ersch-svg-kennung--azure     { fill: var(--tblr-azure, #4299e1); }
.ersch-svg-kennung--secondary { fill: var(--tblr-border-color, #dee2e6); }

.ersch-svg-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    fill: var(--tblr-secondary, #6c757d);
}

/* Der gefundene Wert ist die Antwort auf „was hat der Agent ermittelt?" und
   deshalb das Auffälligste im Knoten. */
.ersch-svg-wert {
    font-size: 14px;
    font-weight: 600;
    fill: var(--tblr-body-color, #1a1a1a);
}

.ersch-svg-status { font-size: 11px; font-weight: 600; }

/* Der Laufzustand, unter dem Belegstand: „prüft die Quelle …". Leiser gesetzt,
   weil er sagt, was gerade geschieht, nicht was gilt. */
.ersch-svg-lauf {
    font-size: 10px;
    fill: var(--tblr-secondary, #6c757d);
}
.ersch-svg-status--green     { fill: var(--tblr-green, #2fb344); }
.ersch-svg-status--yellow    { fill: var(--tblr-yellow-fg, #b8860b); }
.ersch-svg-status--red,
.ersch-svg-status--danger    { fill: var(--tblr-red, #d63939); }
.ersch-svg-status--azure     { fill: var(--tblr-azure, #4299e1); }
.ersch-svg-status--secondary { fill: var(--tblr-secondary, #6c757d); }

/* Die Agenten sind keine Daten, sondern die Handelnden — sie tragen die
   Hausfarbe, damit man sie vom Belegten unterscheidet. */
.ersch-svg-knoten--agent .ersch-svg-rahmen {
    stroke: var(--hda-orange, #E98011);
    fill: rgba(var(--hda-orange-rgb, 233, 128, 17), 0.05);
}

/* Wo der Lauf gerade steht: der Rahmen tritt hervor, der Punkt pulsiert. */
.ersch-svg-knoten--aktiv .ersch-svg-rahmen {
    stroke: var(--hda-orange, #E98011);
    stroke-width: 2;
}
.ersch-svg-puls {
    fill: var(--hda-orange, #E98011);
    animation: ersch-puls 1.6s ease-in-out infinite;
}
@keyframes ersch-puls {
    0%, 100% { opacity: 1; r: 4; }
    50%      { opacity: 0.35; r: 6; }
}
@media (prefers-reduced-motion: reduce) {
    .ersch-svg-puls { animation: none; }
}

.ersch-svg-knoten--fertig .ersch-svg-rahmen { stroke: var(--tblr-green, #2fb344); }
.ersch-svg-knoten--fehler .ersch-svg-rahmen { stroke: var(--tblr-red, #d63939); }

/* Hier kommt die Automatik nicht weiter. Kräftiger als ein Fehler, weil ein
   Fehler ein Versuch war und dies eine Aufgabe ist: Jemand muss hinsehen. */
.ersch-svg-knoten--handarbeit .ersch-svg-rahmen {
    stroke: var(--tblr-red, #d63939);
    stroke-width: 2;
    stroke-dasharray: 5 3;
}
.ersch-svg-hand { fill: var(--tblr-red, #d63939); }

/* Ein Feldknoten führt ins Herkunfts-Modal — das soll man ihm ansehen. */
.ersch-svg-knoten--klickbar { cursor: pointer; }
.ersch-svg-knoten--klickbar:hover .ersch-svg-rahmen {
    stroke: var(--hda-orange, #E98011);
    stroke-width: 2;
}

/* Dieselben Felder noch einmal als Liste: mit der Tastatur erreichbar, für
   Screenreader lesbar — beides ist ein ``<g>`` im SVG nicht. */
.ersch-felder {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--tblr-border-color, #dee2e6);
}
.ersch-feld {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
    padding: 0.15rem 0;
}
.ersch-feld-name { font-weight: 600; min-width: 12rem; }
.ersch-feld-wert { flex: 1 1 auto; min-width: 0; }

/* ===========================================================================
   Aufgabenliste
   ===========================================================================

   Die Ergebnisspalte trägt Meldungen, in denen Adressen stehen — und eine
   Adresse hat keine Leerzeichen. Ohne Umbruch an beliebiger Stelle schiebt eine
   einzige 190 Zeichen lange URL die Tabelle über den rechten Rand hinaus, und
   ``table-responsive`` hilft dagegen nicht: Es macht die Tabelle scrollbar,
   nimmt ihr aber nicht die Mindestbreite. */
.aufgaben-ergebnis {
    max-width: 32rem;
    overflow-wrap: anywhere;
}
.aufgaben-ergebnis pre {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    margin-bottom: 0;
}
.aufgaben-datensatz {
    display: inline-block;
    max-width: 22rem;
    overflow-wrap: anywhere;
}

/* Ein Hand-Symbol je Angabe, die einen Menschen braucht — anklickbar, weil eine
   Zahl nicht weiß, welches Feld gemeint ist. */
.qs-hand {
    border: 0;
    background: transparent;
    padding: 0 0.1rem;
    line-height: 1;
    color: var(--tblr-red, #d63939);
    cursor: pointer;
}
.qs-hand:hover { color: var(--tblr-red-darker, #a62121); }
.qs-hand:focus-visible {
    outline: 2px solid var(--hda-orange, #E98011);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Studiengänge stehen eingerückt unter ihrer Hochschule — sie sind die zweite
   Hälfte derselben Arbeit, keine eigene Liste. Der Einzug und der leisere
   Hintergrund zeigen die Zugehörigkeit, ohne eine zweite Tabelle zu bauen. */
.qs-programm-zeile > td:first-child { padding-left: 2.25rem; }
.qs-programm-zeile > td {
    background: var(--tblr-bg-surface-secondary, rgba(0, 0, 0, 0.02));
    border-top: 0;
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
}
.qs-programm-name { font-size: 0.8125rem; text-decoration: none; }
.qs-programm-name:hover { text-decoration: underline; }

/* Die älteren Schritte: da, aber nicht im Weg. */
.ersch-aeltere > summary {
    cursor: pointer;
    font-size: 0.8125rem;
    color: var(--tblr-secondary, #6c757d);
    padding: 0.25rem 0;
}
.ersch-aeltere[open] > summary { margin-bottom: 0.5rem; }

/* Die Knöpfe je offenem Feld stehen nebeneinander und brechen um. */
.ersch-offen-feld { display: inline-block; }

/* Das Tor und der Ausblick sind noch nicht Bestand, sondern Aussicht. */
.ersch-svg-knoten--gate .ersch-svg-rahmen { stroke-dasharray: 4 3; }
.ersch-svg-knoten--ausblick { opacity: 0.55; }
.ersch-svg-knoten--ausblick .ersch-svg-rahmen { stroke-dasharray: 4 3; }
.ersch-svg-knoten--wartet:not(.ersch-svg-knoten--agent) { opacity: 0.75; }

/* ---- Die Belege unter dem Diagramm ---- */

.ersch-belege {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--tblr-border-color, #dee2e6);
    font-size: 0.8125rem;
}

.ersch-beleg {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: inherit;
    text-decoration: none;
}
.ersch-beleg:hover { text-decoration: underline; }
.ersch-beleg-feld { font-weight: 600; min-width: 9rem; }

/* ---- Das Schrittprotokoll ---- */

.ersch-zeitleiste {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 40rem;
    overflow-y: auto;
}

.ersch-schritt {
    display: flex;
    gap: 0.65rem;
    padding: 0.4rem 0 0.4rem 0.75rem;
    margin-left: 0.5rem;
    /* Wer den Schritt getan hat, trägt die Kante — der Wechsel zwischen Suchen
       und Prüfen ist die wichtigste Gliederung des Protokolls. */
    border-left: 2px solid var(--tblr-border-color, #dee2e6);
}
.ersch-schritt--search { border-left-color: var(--hda-orange, #E98011); }
.ersch-schritt--review { border-left-color: var(--tblr-azure, #4299e1); }
.ersch-schritt--system { border-left-color: var(--tblr-border-color, #dee2e6); }
.ersch-schritt--fehler { border-left-color: var(--tblr-red, #d63939); }

.ersch-schritt-icon {
    flex: 0 0 1.1rem;
    color: var(--tblr-secondary, #6c757d);
    font-size: 0.9rem;
    margin-top: 0.1rem;
}
.ersch-schritt--fehler .ersch-schritt-icon { color: var(--tblr-red, #d63939); }

.ersch-schritt-text { min-width: 0; flex: 1; }

.ersch-schritt-kopf {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    font-size: 0.8125rem;
}

.ersch-schritt-agent {
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--tblr-secondary, #6c757d);
}

.ersch-schritt-titel { overflow-wrap: anywhere; }

.ersch-schritt-dauer,
.ersch-schritt-zeit {
    font-size: 0.75rem;
    color: var(--tblr-secondary, #6c757d);
    white-space: nowrap;
}
.ersch-schritt-zeit { margin-left: auto; }

.ersch-schritt-detail {
    font-size: 0.8125rem;
    color: var(--tblr-secondary, #6c757d);
    margin-top: 0.15rem;
    overflow-wrap: anywhere;
}

.ersch-schritt-ergebnis { margin-top: 0.3rem; font-size: 0.75rem; }
.ersch-schritt-ergebnis summary {
    cursor: pointer;
    color: var(--tblr-secondary, #6c757d);
}
.ersch-schritt-ergebnis pre {
    margin: 0.3rem 0 0;
    padding: 0.5rem;
    background: var(--tblr-bg-surface-secondary, #f8f9fa);
    border-radius: var(--tblr-border-radius, 4px);
    max-height: 16rem;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* Ampelreihe der Qualitätssicherung: der Belegstand einer Hochschule auf einen
   Blick. Farben und Zeichen wie in der Prüfliste — wer Grün von Rot nicht
   unterscheidet, liest Haken und Kreuz. */
.qs-ampel {
    display: flex;
    gap: 0.25rem;
    align-items: center;
}

.qs-punkt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: var(--tblr-border-radius, 4px);
    font-size: 0.85rem;
    cursor: help;
}

.qs-punkt--green     { color: var(--tblr-green, #2fb344); background: rgba(47, 179, 68, 0.12); }
.qs-punkt--yellow    { color: var(--tblr-yellow-fg, #b8860b); background: rgba(245, 159, 0, 0.14); }
.qs-punkt--red,
.qs-punkt--danger    { color: var(--tblr-red, #d63939); background: rgba(214, 57, 57, 0.12); }
.qs-punkt--azure     { color: var(--tblr-azure, #4299e1); background: rgba(66, 153, 225, 0.12); }
.qs-punkt--secondary { color: var(--tblr-secondary, #6c757d); background: rgba(108, 117, 125, 0.10); }

/* „Was noch fehlt": je Stufe eine Zeile mit den offenen Feldern und dem Knopf,
   der genau sie anstößt. */
.ersch-offen {
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--tblr-border-color, #dee2e6);
}

.ersch-offen-zeile {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.35rem 0;
    font-size: 0.8125rem;
}
.ersch-offen-zeile + .ersch-offen-zeile {
    border-top: 1px solid var(--tblr-border-color, #dee2e6);
}

.ersch-offen-stufe {
    font-weight: 600;
    min-width: 12rem;
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

/* Die Felder nehmen den freien Raum, damit der Knopf rechts steht. */
.ersch-offen-felder {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}
