﻿/*
  SimaCloud Voice - Portal-Design

  Aufbau:
  1. Farbpaletten (hell und dunkel, an einer Stelle anpassbar)
  2. Grundlagen
  3. Rahmenlayout (Seitenleiste, Kopfzeile, Inhalt)
  4. Bausteine (Kacheln, Tabellen, Formulare, Kennzeichnungen)
  5. Anmeldeseiten
  6. Mobile Ansicht

  Das Farbschema ist bewusst zurückhaltend. Für ein eigenes Branding genügt es,
  die Variablen im Abschnitt 1 anzupassen - beide Paletten.
*/

/* 1. Farbpaletten ---------------------------------------------------------- */

/*
   Jede Farbe der Oberflaeche steht als Variable, und zwar nur hier. Der Rest des Blattes
   nennt keine Farbe mehr beim Namen. Genau das ist die Bedingung dafuer, dass sich das
   ganze Portal ueber ein Attribut am <html> umschalten laesst.

   Drei Faelle, in dieser Reihenfolge:

     :root                                 die helle Palette. Sie gilt immer und ist der
                                           Rueckfall, wenn nichts anderes zutrifft.
     :root[data-theme="dark"]              der Benutzer hat "Dunkel" gewaehlt.
     :root:not([data-theme="light"])
       unter prefers-color-scheme: dark    das Geraet steht auf dunkel, und der Benutzer
                                           hat nicht ausdruecklich "Hell" gewaehlt.

   Das Attribut setzt der Server aus der am Benutzerkonto gespeicherten Wahl, bevor die
   Seite ausgeliefert wird. Fehlt es (Anmeldeseite, niemand angemeldet), springt ein
   kurzes Skript im Kopf der Seite mit dem auf dem Geraet gespiegelten Wert ein. Fehlt
   auch der, entscheidet allein das Geraet.

   color-scheme ist dabei kein Beiwerk: Daran erkennen die Browser, wie sie ihre eigenen
   Bedienelemente malen sollen - die Abspieler unter <audio controls>, Bildlaufleisten,
   Dateiauswahl, Datums- und Zeitfelder. Ohne diese Angabe blieben sie hell und saessen
   als weisse Kloetze in der dunklen Seite.

   Die dunkle Palette steht unten zweimal, Wert fuer Wert gleich. CSS kennt keinen Weg,
   einen Satz Variablen unter zwei Bedingungen gelten zu lassen, ohne ihn aufzuschreiben.
   Wer eine Farbe aendert, aendert beide Bloecke.
*/

/* Masse und Schriften. Sie haengen nicht am Farbschema und stehen deshalb nur einmal. */
:root {
    --radius: 8px;
    --radius-sm: 6px;

    --sidebar-width: 248px;
    --topbar-height: 60px;

    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;

    /* Papierweiss. Bleibt in beiden Fassungen weiss: Der QR-Code des zweiten Faktors wird
       von Kameras nur zuverlaessig gelesen, wenn er hell hinterlegt ist und rundherum eine
       helle Zone hat. Das ist kein Gestaltungswunsch, sondern eine Lesebedingung. */
    --paper: #ffffff;

    /* Bruecke zu Bootstrap. Formularfelder, Verweise und Tabellen holen ihre Farben aus
       den --bs-*-Variablen; ohne diese Zeilen blieben sie in der dunklen Fassung hell.
       Die Werte zeigen auf unsere eigenen Variablen und folgen ihnen damit von selbst. */
    --bs-body-bg: var(--field-bg);
    --bs-body-color: var(--text-primary);
    --bs-border-color: var(--border-strong);
    --bs-secondary-bg: var(--surface-sunken);
    --bs-tertiary-bg: var(--surface-muted);
    --bs-secondary-color: var(--text-muted);
    --bs-emphasis-color: var(--text-primary);
    --bs-link-color: var(--brand-link);
    --bs-link-hover-color: var(--brand-link-hover);
}

/* Helle Palette */
:root {
    color-scheme: light;

    --brand-primary: #1f5faa;
    --brand-primary-dark: #164a86;
    --brand-primary-light: #e8f0fa;

    /* Die Marke als Textfarbe. In der hellen Fassung dieselbe wie die Flaeche, in der
       dunklen ein deutlich helleres Blau - eine Fuellfarbe, auf der Weiss lesbar bleibt,
       ist als Schrift auf dunklem Grund zu dunkel. Deshalb zwei Variablen. */
    --brand-link: #1f5faa;
    --brand-link-hover: #164a86;

    /* Schrift auf gefuellter Markenflaeche (Knopf, Kennzeichen "Neu", Markenzeichen). */
    --on-brand: #ffffff;
    --brand-accent: #0d9488;

    --surface: #ffffff;
    --surface-muted: #f5f7fa;
    --surface-sunken: #eef1f6;

    /* Eingabefelder. In der hellen Fassung wie die Karte, in der dunklen eine Spur
       tiefer - sonst waere ein Feld von seiner Karte nur am Rahmen zu unterscheiden. */
    --field-bg: #ffffff;

    /* Zeile oder Eintrag unter dem Zeiger. Immer die Richtung "eine Stufe heller als
       der Grund", in der dunklen Fassung also nicht --surface-muted. */
    --hover-bg: #f5f7fa;

    --sidebar-bg: #10243c;
    --sidebar-fg: #c8d6e5;
    --sidebar-fg-active: #ffffff;
    --sidebar-fg-subtle: #93a8bd;
    --sidebar-active-bg: rgba(255, 255, 255, 0.10);
    --sidebar-hover-bg: rgba(255, 255, 255, 0.06);
    --sidebar-border: rgba(255, 255, 255, 0.08);

    --text-primary: #16202c;
    --text-secondary: #4e5e6e;
    --text-muted: #5f6e7e;

    --border: #dfe4ec;
    --border-strong: #c5cdd9;

    --ok: #137036;
    --ok-bg: #e7f6ec;
    --ok-border: #b6ddc4;
    --warning: #975a06;
    --warning-bg: #fdf3e2;
    --warning-border: #e8cfa4;
    --danger: #b42318;
    --danger-bg: #fdecea;
    --danger-border: #f0c0bb;
    --danger-edge: #e0a09b;
    --info: #1f5faa;
    --info-bg: #e8f0fa;
    --info-border: #bcd0e8;
    --pause: #6b46c1;
    --pause-bg: #f0ebfb;

    --backdrop: rgba(16, 36, 60, 0.45);
    --shadow-sm: 0 1px 2px rgba(16, 36, 60, 0.06);
    --shadow: 0 2px 8px rgba(16, 36, 60, 0.08);
    --shadow-md: 0 8px 24px rgba(15, 23, 42, 0.12);

    --auth-bg: linear-gradient(160deg, #10243c 0%, #1f5faa 100%);
    --auth-shadow: 0 18px 40px rgba(8, 20, 35, 0.25);
    --auth-footer-fg: #dbe6f2;

    --bs-emphasis-color-rgb: 22, 32, 44;
}

/* Dunkle Palette, ausdruecklich gewaehlt */
:root[data-theme="dark"] {
    color-scheme: dark;

    --brand-primary: #2a72c9;
    --brand-primary-dark: #2d77d0;
    --brand-primary-light: #1c3149;
    --brand-link: #7db4f2;
    --brand-link-hover: #a6cdf8;
    --on-brand: #ffffff;
    --brand-accent: #2dd4bf;

    --surface: #1a2433;
    --surface-muted: #0f151e;
    --surface-sunken: #232f40;
    --field-bg: #131c28;
    --hover-bg: #232f40;

    --sidebar-bg: #172b45;
    --sidebar-fg: #b3c2d3;
    --sidebar-fg-active: #ffffff;
    --sidebar-fg-subtle: #94a6bb;
    --sidebar-active-bg: rgba(255, 255, 255, 0.13);
    --sidebar-hover-bg: rgba(255, 255, 255, 0.07);
    --sidebar-border: rgba(255, 255, 255, 0.12);

    --text-primary: #e8eef6;
    --text-secondary: #a8b6c6;
    --text-muted: #8c9bac;

    --border: #2e3b4d;
    --border-strong: #4a5a70;

    --ok: #5fcb8b;
    --ok-bg: #12301f;
    --ok-border: #2f6a48;
    --warning: #e3a84a;
    --warning-bg: #332512;
    --warning-border: #6d5324;
    --danger: #f2897f;
    --danger-bg: #3a1c1a;
    --danger-border: #7a3a34;
    --danger-edge: #8d443c;
    --info: #7db4f2;
    --info-bg: #17293e;
    --info-border: #33557f;
    --pause: #b79ef0;
    --pause-bg: #241d3a;

    --backdrop: rgba(0, 0, 0, 0.6);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
    --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.55);

    --auth-bg: linear-gradient(160deg, #0a111b 0%, #16324f 100%);
    --auth-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
    --auth-footer-fg: #a8b6c6;

    --bs-emphasis-color-rgb: 232, 238, 246;
    --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%238c9bac' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* Dunkle Palette, weil das Geraet es so haelt und der Benutzer nichts anderes verlangt hat.
   Dieselben Werte wie oben. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --brand-primary: #2a72c9;
        --brand-primary-dark: #2d77d0;
        --brand-primary-light: #1c3149;
        --brand-link: #7db4f2;
        --brand-link-hover: #a6cdf8;
        --on-brand: #ffffff;
        --brand-accent: #2dd4bf;

        --surface: #1a2433;
        --surface-muted: #0f151e;
        --surface-sunken: #232f40;
        --field-bg: #131c28;
        --hover-bg: #232f40;

        --sidebar-bg: #172b45;
        --sidebar-fg: #b3c2d3;
        --sidebar-fg-active: #ffffff;
        --sidebar-fg-subtle: #94a6bb;
        --sidebar-active-bg: rgba(255, 255, 255, 0.13);
        --sidebar-hover-bg: rgba(255, 255, 255, 0.07);
        --sidebar-border: rgba(255, 255, 255, 0.12);

        --text-primary: #e8eef6;
        --text-secondary: #a8b6c6;
        --text-muted: #8c9bac;

        --border: #2e3b4d;
        --border-strong: #4a5a70;

        --ok: #5fcb8b;
        --ok-bg: #12301f;
        --ok-border: #2f6a48;
        --warning: #e3a84a;
        --warning-bg: #332512;
        --warning-border: #6d5324;
        --danger: #f2897f;
        --danger-bg: #3a1c1a;
        --danger-border: #7a3a34;
        --danger-edge: #8d443c;
        --info: #7db4f2;
        --info-bg: #17293e;
        --info-border: #33557f;
        --pause: #b79ef0;
        --pause-bg: #241d3a;

        --backdrop: rgba(0, 0, 0, 0.6);
        --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
        --shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
        --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.55);

        --auth-bg: linear-gradient(160deg, #0a111b 0%, #16324f 100%);
        --auth-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
        --auth-footer-fg: #a8b6c6;

        --bs-emphasis-color-rgb: 232, 238, 246;
        --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%238c9bac' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    }
}

/* 2. Grundlagen ------------------------------------------------------------ */
html, body {
    height: 100%;
    margin: 0;
}

body {
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    line-height: 1.55;
    color: var(--text-primary);
    background: var(--surface-muted);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    color: var(--text-primary);
    font-weight: 600;
    margin: 0;
}

a {
    color: var(--brand-link);
    text-decoration: none;
}

a:hover {
    color: var(--brand-link-hover);
    text-decoration: underline;
}

.text-muted {
    color: var(--text-muted) !important;
}

.mono {
    font-family: var(--font-mono);
    font-size: 0.875em;
}

/* 3. Rahmenlayout ---------------------------------------------------------- */
.portal {
    display: flex;
    min-height: 100vh;
}

.portal-sidebar {
    width: var(--sidebar-width);
    flex: 0 0 var(--sidebar-width);
    background: var(--sidebar-bg);
    color: var(--sidebar-fg);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;

    /* In der dunklen Fassung liegen Leiste und Inhalt beide nahe an Schwarz. Der
       Helligkeitsabstand allein traegt dort nicht mehr weit, also kommt eine Kante
       dazu. In der hellen Fassung faellt sie auf dem dunklen Blau nicht auf. */
    border-right: 1px solid var(--sidebar-border);
}

.portal-brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1.1rem 1.25rem;
    border-bottom: 1px solid var(--sidebar-border);
}

.brand-mark {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-sm);
    background: var(--brand-primary);
    color: var(--on-brand);
    font-weight: 700;
    font-size: 0.8125rem;
    letter-spacing: 0.03em;
}

.brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
}

.brand-name {
    color: var(--sidebar-fg-active);
    font-weight: 600;
    font-size: 0.95rem;
}

.brand-product {
    color: var(--sidebar-fg);
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.portal-nav {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 0.75rem 0.65rem 1rem;
    overflow-y: auto;
}

.nav-section + .nav-section {
    margin-top: 1.1rem;
}

.nav-section-bottom {
    margin-top: auto;
    padding-top: 1rem;
    border-top: 1px solid var(--sidebar-border);
}

.nav-section-title {
    padding: 0 0.6rem 0.35rem;
    font-size: 0.6875rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--sidebar-fg-subtle);
}

.nav-item {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.6rem;
    border-radius: var(--radius-sm);
    color: var(--sidebar-fg);
    font-size: 0.875rem;
    text-decoration: none;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.nav-item:hover {
    background: var(--sidebar-hover-bg);
    color: var(--sidebar-fg-active);
    text-decoration: none;
}

.nav-item.active {
    background: var(--sidebar-active-bg);
    color: var(--sidebar-fg-active);
    font-weight: 500;
}

.nav-icon {
    display: inline-flex;
    opacity: 0.85;
}

.portal-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.portal-topbar {
    height: var(--topbar-height);
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0 1.5rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar-spacer {
    flex: 1;
}

.nav-toggle {
    display: none;
    flex-direction: column;
    gap: 4px;
    background: none;
    border: none;
    padding: 0.35rem;
    cursor: pointer;
}

.nav-toggle span {
    display: block;
    width: 20px;
    height: 2px;
    background: var(--text-secondary);
    border-radius: 2px;
}

.nav-backdrop {
    display: none;
}

.customer-selector .form-select {
    min-width: 220px;
    border-color: var(--border-strong);
}

.customer-name {
    font-weight: 600;
}

.user-menu {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.user-info {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.25;
}

.user-name {
    font-size: 0.875rem;
    font-weight: 600;
}

.user-role {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.user-avatar {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--brand-primary-light);
    color: var(--brand-link);
    font-size: 0.8125rem;
    font-weight: 600;
}

/* Wahl der Darstellung: drei Knoepfe in einer gemeinsamen Fassung, die gewaehlte hebt sich
   ab. Bewusst nicht nur ueber die Farbe - die gewaehlte Moeglichkeit traegt zusaetzlich eine
   eigene Flaeche und einen Rahmen, damit sie auch ohne Farbsehen zu erkennen ist. */
.scheme-choice {
    display: inline-flex;
    padding: 2px;
    gap: 2px;
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: 999px;
}

.scheme-option {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.45rem;
    border: 1px solid transparent;
    border-radius: 999px;
    background: none;
    color: var(--text-secondary);
    cursor: pointer;
    line-height: 1;
}

.scheme-option:hover {
    color: var(--text-primary);
}

.scheme-option.is-active {
    background: var(--surface);
    border-color: var(--border-strong);
    color: var(--brand-link);
}

.scheme-option:focus-visible {
    outline: 2px solid var(--brand-link);
    outline-offset: 1px;
}

.scheme-icon {
    display: inline-flex;
}

/* Auf der Kontoseite steht neben jedem Symbol sein Wort. In der Kopfzeile waere dafuer kein
   Platz; dort sagen es der Titel und die versteckte Beschriftung. */
.scheme-choice-wide {
    margin-top: 0.15rem;
    flex-wrap: wrap;
    border-radius: var(--radius);
}

.scheme-choice-wide .scheme-option {
    padding: 0.35rem 0.7rem;
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    font-weight: 500;
}

.logout-form {
    margin: 0;
}

.btn-logout {
    padding: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    text-decoration: none;
}

.btn-logout:hover {
    color: var(--danger);
}

.portal-content {
    flex: 1;
    padding: 1.75rem 1.5rem 3rem;
    max-width: 1400px;
    width: 100%;
}

/* 4. Bausteine ------------------------------------------------------------- */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.page-title {
    font-size: 1.375rem;
    letter-spacing: -0.01em;
}

.page-description {
    margin: 0.3rem 0 0;
    color: var(--text-secondary);
    font-size: 0.875rem;
    max-width: 68ch;
}

.page-actions {
    display: flex;
    gap: 0.5rem;
}

.toolbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
}

.search-input {
    max-width: 340px;
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 1rem;
    margin-bottom: 1.75rem;
}

.stat-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem 1.15rem;
    box-shadow: var(--shadow-sm);
    border-left: 3px solid var(--border-strong);
}

.stat-positive { border-left-color: var(--ok); }
.stat-warning { border-left-color: var(--warning); }
.stat-danger { border-left-color: var(--danger); }

.stat-label {
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.stat-value {
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.2;
    margin-top: 0.2rem;
}

.stat-hint {
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.card-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.25rem 1.35rem;
    box-shadow: var(--shadow-sm);
    margin-bottom: 1.5rem;
}

.panel-title {
    font-size: 1rem;
    margin-bottom: 1rem;
}

.panel-intro {
    color: var(--text-secondary);
    font-size: 0.875rem;
    margin-bottom: 1rem;
}

.empty-hint {
    color: var(--text-muted);
    font-size: 0.875rem;
    margin: 0;
}

.empty-state {
    background: var(--surface);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
    padding: 2.5rem 1.5rem;
    text-align: center;
    color: var(--text-secondary);
}

.empty-state p {
    margin-bottom: 1rem;
}

/* Eine Zeile Beiwerk unter dem Seitenkopf. Bewusst kein farbiger Kasten: Ein Hinweis, der
   nichts verlangt und nichts meldet, soll nicht aussehen wie einer, der beides tut. */
.page-note {
    margin: -0.25rem 0 1.25rem;
    font-size: 0.875rem;
    color: var(--text-secondary);
    max-width: 68ch;
}

/* Ein zugeklapptes <details> versteckt seine Kinder ueber das Standardblatt des Browsers.
   Diese Regel hat die schwaechste Herkunft, die es gibt: Jede eigene display-Angabe sticht
   sie aus. Genau das passiert hier, weil .form-grid display:grid setzt - der Block galt als
   zugeklappt (open war false), und die Felder standen trotzdem da. Aufgefallen ist es erst
   beim Nachzaehlen der sichtbaren Felder, im Bild sah es nach einem offenen Block aus.

   Deshalb ausdruecklich: Was nicht die Zusammenfassung ist, verschwindet im zugeklappten
   Zustand. Gilt fuer alle <details> des Portals, damit dieselbe Falle nicht beim naechsten
   Block wieder zuschlaegt. */
details:not([open]) > *:not(summary) {
    display: none !important;
}

/* Tabellen */
.table-wrapper {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow-x: auto;
    box-shadow: var(--shadow-sm);
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.data-table thead th {
    text-align: left;
    padding: 0.7rem 1rem;
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

.data-table tbody td {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.data-table tbody tr:last-child td {
    border-bottom: none;
}

.data-table tbody tr:hover {
    background: var(--hover-bg);
}

.data-table .numeric {
    text-align: right;
}

.data-table .actions {
    text-align: right;
    white-space: nowrap;
}

.data-table .actions .btn + .btn {
    margin-left: 0.35rem;
}

.table-link {
    font-weight: 600;
}

.table-subtext {
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.text-truncate-cell {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.row-muted {
    opacity: 0.6;
}

.row-highlight {
    background: var(--brand-primary-light);
}

/* Kennzeichnungen */
.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
}

.status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.status-open { background: var(--ok-bg); color: var(--ok); }
.status-closed { background: var(--surface-sunken); color: var(--text-secondary); }
.status-inactive { background: var(--surface-sunken); color: var(--text-muted); }
.status-override { background: var(--warning-bg); color: var(--warning); }
.status-vacation { background: var(--info-bg); color: var(--info); }
.status-holiday { background: var(--info-bg); color: var(--info); }
.status-pause { background: var(--pause-bg); color: var(--pause); }

.pill {
    display: inline-block;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    background: var(--surface-sunken);
    color: var(--text-secondary);
}

.pill-new { background: var(--brand-primary); color: var(--on-brand); }
.pill-ok { background: var(--ok-bg); color: var(--ok); }
.pill-warning { background: var(--warning-bg); color: var(--warning); }
.pill-danger { background: var(--danger-bg); color: var(--danger); }
.pill-muted { background: var(--surface-sunken); color: var(--text-muted); }

/* Mailbox-Karten */
.mailbox-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 1rem;
}

.mailbox-card {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem 1.1rem;
    background: var(--surface);
}

.mailbox-card-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 0.85rem;
}

.mailbox-name {
    font-size: 1rem;
}

.mailbox-numbers {
    margin: 0.15rem 0 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    font-family: var(--font-mono);
}

.mailbox-facts {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.5rem;
    margin: 0 0 0.9rem;
}

.mailbox-facts dt {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 400;
}

.mailbox-facts dd {
    margin: 0.1rem 0 0;
    font-size: 0.8125rem;
    font-weight: 500;
}

.mailbox-card-actions {
    display: flex;
    gap: 0.4rem;
}

/* Statusleiste */
.status-row {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.status-reason {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.status-next {
    margin-left: auto;
    font-size: 0.875rem;
    font-weight: 500;
}

.button-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Komponentenliste */
.component-list {
    display: flex;
    flex-direction: column;
}

.component-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0;
    border-bottom: 1px solid var(--border);
    font-size: 0.875rem;
}

.component-row:last-child {
    border-bottom: none;
}

.component-indicator {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex: 0 0 auto;
}

.component-indicator.ok { background: var(--ok); }
.component-indicator.pending { background: var(--text-muted); }

.component-name {
    font-weight: 500;
    min-width: 160px;
}

.component-description {
    color: var(--text-secondary);
}

/* Ausbaustufen */
.roadmap {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
}

.roadmap-item {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.9rem 1rem;
    background: var(--surface-muted);
}

.roadmap-item h3 {
    font-size: 0.9375rem;
    margin-bottom: 0.35rem;
}

.roadmap-item p {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* Formulare */
.form-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.35rem;
    box-shadow: var(--shadow-sm);
    margin-bottom: 1.5rem;
}

.inline-form {
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem 1.25rem;
}

.form-grid .span-2 {
    grid-column: span 2;
}

.form-field {
    display: flex;
    flex-direction: column;
}

.form-label {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-secondary);
    margin-bottom: 0.3rem;
}

.form-control,
.form-select {
    border-color: var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    padding: 0.45rem 0.65rem;
}

/* Der Pfeil eines Auswahlfelds liegt als Hintergrundbild rechts im Feld. Die gemeinsame
   Polsterung oben gilt auch fuer <select> und laesst ihm dort keinen Platz - der Pfeil
   legte sich ueber den letzten Buchstaben. Am deutlichsten bei der Kundenauswahl auf einem
   Telefon, wo das Feld ohnehin schmal ist. */
.form-select {
    padding-right: 2.25rem;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--brand-link);
    box-shadow: 0 0 0 3px var(--brand-primary-light);
}

/* Was Bootstrap selbst malt: Haken, Punkt und gesperrte Felder. Die Farben kommen ueber
   die --bs-*-Bruecke aus der Palette, diese drei Stellen sind dort fest verdrahtet. */
.form-control:disabled,
.form-select:disabled {
    background: var(--surface-sunken);
    color: var(--text-secondary);
}

.form-check-input:checked {
    background-color: var(--brand-primary);
    border-color: var(--brand-primary);
}

.form-check-input:focus {
    border-color: var(--brand-link);
    box-shadow: 0 0 0 3px var(--brand-primary-light);
}

.form-hint {
    margin-top: 0.3rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.field-error,
.validation-message {
    margin-top: 0.25rem;
    font-size: 0.8125rem;
    color: var(--danger);
}

.form-check {
    margin-top: 0.4rem;
}

.form-check-label {
    font-size: 0.875rem;
}

.form-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.35rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--border);
}

.detail-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.85rem;
    margin: 0 0 1rem;
}

.detail-list dt {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 400;
}

.detail-list dd {
    margin: 0.15rem 0 0;
    font-weight: 500;
}

/* Wochenplan */
.week-plan {
    margin-top: 1.25rem;
    border-top: 1px solid var(--border);
}

.week-day {
    display: grid;
    grid-template-columns: 130px 1fr auto;
    gap: 1rem;
    align-items: start;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--border);
}

.week-day-name {
    font-weight: 500;
    font-size: 0.875rem;
    padding-top: 0.35rem;
}

.week-day-ranges {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    padding-top: 0.35rem;
}

.time-range {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.time-range .form-control {
    width: auto;
    max-width: 120px;
}

.time-sep {
    color: var(--text-muted);
    font-size: 0.8125rem;
}

/* Schaltflächen */
.btn {
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.45rem 0.9rem;
}

.btn-sm {
    font-size: 0.8125rem;
    padding: 0.3rem 0.65rem;
}

.btn-primary {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
}

.btn-primary:hover,
.btn-primary:focus {
    background: var(--brand-primary-dark);
    border-color: var(--brand-primary-dark);
}

.btn-outline {
    background: var(--surface);
    border: 1px solid var(--border-strong);
    color: var(--text-primary);
}

.btn-outline:hover {
    background: var(--surface-sunken);
    color: var(--text-primary);
}

.btn-danger-outline {
    background: var(--surface);
    border: 1px solid var(--border-strong);
    color: var(--danger);
}

.btn-danger-outline:hover {
    background: var(--danger-bg);
    border-color: var(--danger);
    color: var(--danger);
}

.ms-auto {
    margin-left: auto;
}

/* Hinweisbereiche */
.alert {
    border-radius: var(--radius);
    border: 1px solid transparent;
    font-size: 0.875rem;
    padding: 0.75rem 1rem;
    margin-bottom: 1.25rem;
}

.alert-success { background: var(--ok-bg); border-color: var(--ok-border); color: var(--ok); }
.alert-danger { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger); }
.alert-warning { background: var(--warning-bg); border-color: var(--warning-border); color: var(--warning); }
.alert-info { background: var(--info-bg); border-color: var(--info-border); color: var(--info); }

/* 5. Anmeldeseiten --------------------------------------------------------- */
.auth-page {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    background: var(--auth-bg);
}

.auth-panel {
    width: 100%;
    max-width: 420px;
}

.auth-card {
    background: var(--surface);
    border-radius: 12px;
    padding: 2rem;
    box-shadow: var(--auth-shadow);
}

.auth-brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.75rem;
}

.auth-brand-mark {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: var(--radius-sm);
    background: var(--brand-primary);
    color: var(--on-brand);
    font-weight: 700;
    font-size: 0.875rem;
}

.auth-brand-name {
    font-weight: 600;
}

.auth-brand-claim {
    font-size: 0.75rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.auth-title {
    font-size: 1.25rem;
    margin-bottom: 1.25rem;
}

.auth-card .form-field {
    margin-bottom: 1rem;
}

.auth-hint {
    margin: 1.5rem 0 0;
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.auth-footer {
    margin-top: 1.5rem;
    color: var(--auth-footer-fg);
    font-size: 0.8125rem;
}

.auth-footer-sep {
    margin: 0 0.4rem;
}

/* Fehleranzeige von Blazor */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 0.75rem 1.25rem;
    background: var(--warning-bg);
    color: var(--warning);
    border-top: 1px solid var(--warning);
    font-size: 0.875rem;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 1rem;
    top: 0.75rem;
}

/* 6. Mobile Ansicht -------------------------------------------------------- */
@media (max-width: 900px) {
    .portal-sidebar {
        position: fixed;
        left: 0;
        top: 0;
        z-index: 40;
        transform: translateX(-100%);
        transition: transform 0.18s ease;
    }

    .portal-sidebar.is-open {
        transform: translateX(0);
        box-shadow: var(--shadow);
    }

    .nav-toggle {
        display: flex;
    }

    .nav-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 30;
        background: var(--backdrop);
    }

    .portal-content {
        padding: 1.25rem 1rem 3rem;
    }

    .form-grid {
        grid-template-columns: 1fr;
    }

    .form-grid .span-2 {
        grid-column: span 1;
    }

    .week-day {
        grid-template-columns: 1fr;
        gap: 0.5rem;
    }

    .user-info {
        display: none;
    }

    /* Die Kopfzeile eines Telefons traegt Navigationsknopf, Kundenauswahl, Darstellung und
       Abmeldung nebeneinander. Das passt bei 400 px nur, wenn drei Dinge zusammenruecken:
       die Zeile selbst, die Wahl der Darstellung - und vor allem die Kundenauswahl, die
       sonst mit ihrem Mindestmass die ganze Zeile ueber den Rand schiebt. Ein zu langer
       Kundenname wird abgeschnitten; das ist besser als eine Seite, die seitlich scrollt
       und die Abmeldung hinter den Rand legt. */
    .portal-topbar {
        gap: 0.5rem;
        padding: 0 0.75rem;
    }

    .portal-topbar .scheme-option {
        padding: 0.3rem;
    }

    .customer-selector {
        min-width: 0;
        flex: 0 1 auto;
    }

    .customer-selector .form-select {
        min-width: 0;
    }

    .status-next {
        margin-left: 0;
    }
}

/* 7. Ergänzungen ----------------------------------------------------------- */

/* Zweispaltige Anordnung, etwa auf der Kontoseite */
.two-column {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 1.5rem;
    align-items: start;
}

/* Einmalig angezeigte Zugangsdaten */
.credential-box {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0.4rem 0;
    padding: 0.5rem 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.credential-label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    min-width: 110px;
}

.credential-value {
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    user-select: all;
}

/* Umschaltung des Mailbox-Status */
.override-panel {
    margin-bottom: 1rem;
}

.override-choices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.6rem;
}

.override-choice {
    text-align: left;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease;
}

.override-choice:hover:not(:disabled) {
    border-color: var(--brand-link);
    background: var(--brand-primary-light);
}

.override-choice:disabled {
    opacity: 0.6;
    cursor: default;
}

.override-choice.is-active {
    border-color: var(--brand-link);
    background: var(--brand-primary-light);
    box-shadow: inset 0 0 0 1px var(--brand-link);
}

.override-choice-title {
    display: block;
    font-weight: 600;
    font-size: 0.875rem;
}

.override-choice-hint {
    display: block;
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-top: 0.15rem;
}

.override-duration {
    margin-top: 1rem;
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-muted);
}

.override-duration-title {
    font-weight: 600;
    font-size: 0.875rem;
    margin-bottom: 0.6rem;
}

.override-custom {
    margin-top: 0.9rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--border);
}

.override-custom .form-label {
    margin-bottom: 0.35rem;
}

/* Der Avatar führt zum eigenen Konto */
a.user-avatar {
    text-decoration: none;
}

a.user-avatar:hover {
    background: var(--brand-primary);
    color: var(--on-brand);
}

/* Hinweis auf eine aktive Übersteuerung in Listen */
.override-note {
    font-size: 0.8125rem;
    color: var(--warning);
}

/* Anzeige der gerade greifenden Ansage */
.greeting-info {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.greeting-name {
    font-size: 0.875rem;
}

.status-label {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

/* 8. Ansagen und Musikkatalog ---------------------------------------------- */

/* Vorschau der Master-Fassung in der Ansagenliste */
.audio-preview {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.5rem;
}

.audio-preview audio {
    height: 2rem;
    max-width: 11rem;
}

.audio-meta {
    font-size: 0.75rem;
    color: var(--text-secondary);
    white-space: nowrap;
}

/* Meldung einer fehlgeschlagenen Erzeugung, bewusst knapp gehalten */
.audio-error {
    margin-top: 0.4rem;
    font-size: 0.75rem;
    color: var(--danger);
    max-width: 22rem;
}

/* Auswahl der Audiodatei eines Musiktitels */
.music-upload {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.45rem;
    font-size: 0.75rem;
}

.music-upload input[type="file"] {
    max-width: 13rem;
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* Zwischenueberschriften und Einrichtungsschritte ------------------------ */

/* Zwischenüberschrift, wenn eine Seite mehrere Tabellen zeigt */
.section-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 1.75rem 0 0.75rem;
}

/* Nummerierte Einrichtungsschritte */
.setup-steps {
    margin: 0;
    padding-left: 1.5rem;
    display: grid;
    gap: 1.1rem;
    color: var(--text-secondary);
    line-height: 1.55;
}

.setup-steps > li > strong:first-child {
    display: block;
    margin-bottom: 0.2rem;
    color: var(--text-primary);
}

.setup-steps p {
    margin: 0.5rem 0 0;
}

/* Eingeklappte manuelle Einrichtung für Administratoren. Natives <details>, kein JavaScript. */
/* Ein eingeklappter Block am Fuss eines Formulars: alles, was selten gebraucht wird.
   Hiess frueher .setup-advanced, weil er zuerst nur unter der Einrichtungsanleitung des
   Agents vorkam. Inzwischen steht er auf acht Seiten, und ein Name nach der Herkunft
   fuehrt in die Irre. */
.form-advanced {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
    color: var(--text-secondary);
    line-height: 1.55;
}

.form-advanced > summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--text-primary);
}

.form-advanced > p {
    margin: 0.75rem 0 0;
}

/* Ohne diesen Abstand klebt das Raster direkt an der Beschriftung des Blocks. */
.form-advanced > .form-grid {
    margin-top: 0.85rem;
}

/* 9. Schnittstellen -------------------------------------------------------- */

/* Erläuterung zum Vorrang der Quellen, steht über allen Abschnitten */
.integration-intro p + p {
    margin-top: 0.6rem;
}

.integration-section + .integration-section {
    margin-top: 1.25rem;
}

/* Herkunft des geltenden Werts, direkt an der Beschriftung */
.integration-origin {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-transform: none;
    vertical-align: middle;
}

/* Aus Umgebung oder Secrets: gewinnt immer und ist hier nicht änderbar */
.origin-environment {
    background: var(--warning-bg);
    color: var(--warning);
}

/* Im Portal gepflegt */
.origin-database {
    background: var(--ok-bg);
    color: var(--ok);
}

/* Aus appsettings.json oder dem eingebauten Vorgabewert */
.origin-default {
    background: var(--surface-sunken);
    color: var(--text-muted);
}

.integration-locked {
    color: var(--warning);
}

.integration-reset {
    align-self: flex-start;
    margin-top: 0.45rem;
}

/* Ergebnis der Verbindungsprüfung, unterhalb der Schaltflächen */
.integration-check {
    margin-top: 1rem;
    margin-bottom: 0;
}

/* Zwei-Faktor-Anmeldung --------------------------------------------------- */

/* Die Einrichtungsseite braucht etwas mehr Breite als die Anmeldung, weil dort
   QR-Code, Schlüssel und Wiederherstellungscodes nebeneinander Platz finden müssen. */
.auth-panel:has(.auth-card-wide) {
    max-width: 560px;
}

/* Einleitender Satz über einem Formular der Anmeldewege */
.auth-intro {
    margin: 0 0 1.25rem;
    color: var(--text-secondary);
    font-size: 0.875rem;
}

/* Eingabefeld für den sechsstelligen Code. Bewusst groß und weit gesperrt,
   damit Ziffern beim Abtippen nicht verwechselt werden. */
.code-input {
    font-size: 1.35rem;
    letter-spacing: 0.35em;
    text-align: center;
}

/* Nummerierte Schritte der Einrichtung */
.setup-steps {
    margin: 0 0 1.5rem;
    padding-left: 1.25rem;
}

.setup-steps > li {
    margin-bottom: 1.5rem;
}

.setup-steps h2 {
    margin: 0 0 0.35rem;
}

/* QR-Code. Das SVG wird lokal erzeugt und enthält den Schlüssel des zweiten Faktors,
   deshalb wird es niemals als Datei abgelegt oder zwischengespeichert. */
.qr-code {
    width: 220px;
    max-width: 100%;
    margin: 0.75rem 0;
    padding: 0.5rem;
    background: var(--paper);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.qr-code svg {
    display: block;
    width: 100%;
    height: auto;
}

/* Einmalig angezeigte Wiederherstellungscodes */
.recovery-codes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0.35rem 1rem;
    margin: 0.75rem 0 0;
    padding: 0;
    list-style: none;
}

.recovery-codes li {
    padding: 0.3rem 0.5rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    letter-spacing: 0.05em;
    user-select: all;
}

/* Aktionen auf der Einrichtungsseite, jede in einem eigenen Formular */
.two-factor-actions {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.two-factor-actions form {
    margin: 0;
}

/* Rückweg und Abmeldung. Die Abmeldung bleibt immer erreichbar, damit bei
   erzwungener Einrichtung keine Sackgasse entsteht. */
.two-factor-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.two-factor-footer .logout-form {
    margin: 0;
}

/* 10. Nachbesserungen der Logikprüfung ------------------------------------ */

/* Nach jedem Seitenwechsel setzt FocusOnNavigate den Fokus auf die Überschrift,
   damit Vorlesewerkzeuge den neuen Inhalt ansagen. Der Browser malt dafür einen
   Fokusrahmen um die Überschrift – ein schwarzes Rechteck, das auf jeder Seite wie
   ein Fehler aussieht. Der Fokus bleibt (er ist der Zweck), nur der Rahmen fällt:
   Für Maus- und Tastaturnutzer trägt er hier nichts, weil eine Überschrift nicht
   bedienbar ist. */
.page-title:focus {
    outline: none;
}

/* Aufklappbare Zeilenaktionen in Tabellen.
   Bewusst das native <details>-Element: Es braucht kein JavaScript, funktioniert
   damit auch vor der Übernahme durch Blazor, schliesst sich per Escape und ist
   für Vorlesewerkzeuge ein bekanntes Muster. Hintergrund: In der Benutzerliste
   standen bis zu fünf Knöpfe nebeneinander und wurden am Tabellenrand
   abgeschnitten. Jetzt bleibt die häufigste Aktion sichtbar, die übrigen liegen
   hinter "Weitere". */
.row-menu {
    position: relative;
    display: inline-block;
    vertical-align: middle;
}

.row-menu > summary {
    list-style: none;
    cursor: pointer;
}

.row-menu > summary::-webkit-details-marker {
    display: none;
}

.row-menu > summary::after {
    content: " ▾";
    font-size: 0.8em;
}

.row-menu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + 0.3rem);
    z-index: 20;
    min-width: 14rem;
    padding: 0.35rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    text-align: left;
    white-space: normal;
}

.row-menu-panel .btn {
    display: block;
    width: 100%;
    margin: 0;
    text-align: left;
    border: none;
    box-shadow: none;
}

.row-menu-panel .btn + .btn {
    margin-top: 0.15rem;
}

.row-menu-panel .btn:hover {
    background: var(--hover-bg);
}

/* Trennlinie vor Aktionen, die einen Zugang sperren oder Faktoren löschen. */
.row-menu-panel .btn-danger-text {
    color: var(--danger);
}

/* Die Auswahlfelder der Tabellenfilter dürfen umbrechen, statt die Tabelle nach
   rechts zu schieben. */
@media (max-width: 900px) {
    .data-table .actions {
        white-space: normal;
    }
}

/* Auswahlfelder mit automatischer Breite (Filter über Tabellen und Zeitplänen).
   w-auto lässt das Feld auf die Textbreite schrumpfen; der Pfeil des Auswahlfelds
   liegt aber als Hintergrundbild rechts im Feld und überlagerte dann den letzten
   Buchstaben ("Vertrieb" wurde zu "Vertrie▾"). Rechts muss Platz für den Pfeil
   bleiben, und ein Mindestmass verhindert Felder, die bei kurzen Namen wie
   Knöpfe aussehen. */
.form-select.w-auto {
    padding-right: 2.6rem;
    min-width: 11rem;
}

/* Wählbare Tabellenzeilen (Zeitplanübersicht): Ein Klick auf die Zeile wählt die Mailbox
   zur Bearbeitung darunter aus. Die gewählte Zeile trägt einen Balken am linken Rand,
   damit sie auch ohne Farbsehen erkennbar bleibt. */
.row-selectable {
    cursor: pointer;
}

.row-selectable:hover {
    background: var(--hover-bg);
}

.row-selectable:focus-visible {
    outline: 2px solid var(--brand-link);
    outline-offset: -2px;
}

.row-selected,
.row-selectable.row-selected:hover {
    background: var(--brand-primary-light);
    box-shadow: inset 3px 0 0 var(--brand-link);
}

/* Endgültige Aktionen, die sich nicht rückgängig machen lassen (Kunde löschen). */
.danger-zone {
    border-color: var(--danger-edge);
}

.danger-zone .panel-title {
    color: var(--danger);
}

/* Wahl der Audioquelle einer Ansage: Text vorlesen lassen oder Datei hochladen. Nach dem
   Vorbild der Übersteuerungsauswahl als Karten, die gewählte hebt sich ab. */
.source-choices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0.6rem;
}

.source-choice {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 0.6rem;
    align-items: start;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease;
}

.source-choice:hover {
    border-color: var(--brand-link);
}

.source-choice:has(input:checked) {
    border-color: var(--brand-link);
    background: var(--brand-primary-light);
}

.source-choice input {
    margin-top: 0.2rem;
}

.source-choice-title {
    font-size: 0.875rem;
    font-weight: 600;
}

.source-choice-hint {
    grid-column: 2;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* Dateiauswahl für eine hochgeladene Ansage */
.greeting-upload input[type="file"] {
    font-size: 0.875rem;
}

/* Musikkatalog: Datei ersetzen liegt hinter einem Aufklapper, damit nicht in jeder
   Zeile dauerhaft ein Dateiauswahlfeld steht. */
.music-replace > summary {
    cursor: pointer;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin-top: 0.35rem;
}

.music-replace > summary:hover {
    color: var(--brand-link);
}

/* Bereitschaftsanzeige auf der Übersicht.

   Leitgedanke: Was erledigt ist, darf nicht lärmen. Offene Punkte bekommen Farbe und
   Gewicht, Hinweise und Erledigtes bleiben grau und klein. Bewusst ohne eigene Kasten-
   optik – der Kasten ist das vorhandene .card-panel. */
.readiness-ready {
    margin: 0;
    color: var(--ok);
    font-weight: 500;
}

.readiness-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.readiness-list + .readiness-list,
.readiness-list + .readiness-done {
    margin-top: 0.75rem;
}

.readiness-item {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.5rem 0;
    border-top: 1px solid var(--border);
}

.readiness-list > .readiness-item:first-child {
    border-top: none;
}

.readiness-marker {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-top: 0.45rem;
    flex: 0 0 auto;
    background: var(--text-muted);
}

.readiness-item.is-open .readiness-marker { background: var(--warning); }
.readiness-item.is-advice .readiness-marker { background: var(--info); }
.readiness-item.is-done .readiness-marker { background: var(--ok); }

.readiness-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
    flex: 1 1 auto;
}

.readiness-title {
    font-weight: 600;
    color: var(--text-primary);
}

.readiness-detail {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.readiness-action {
    flex: 0 0 auto;
    font-size: 0.875rem;
    white-space: nowrap;
    margin-top: 0.1rem;
}

/* Hinweise und Erledigtes treten zurück: kleinere, graue Zeilen ohne fettes Stichwort. */
.readiness-quiet .readiness-title {
    font-weight: 400;
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.readiness-quiet .readiness-detail {
    color: var(--text-muted);
    font-size: 0.8125rem;
}

.readiness-done > summary {
    cursor: pointer;
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.readiness-done > summary:hover {
    color: var(--brand-link);
}

.readiness-done[open] > summary {
    margin-bottom: 0.5rem;
}

@media (max-width: 640px) {
    .readiness-item {
        flex-wrap: wrap;
    }

    .readiness-action {
        margin-left: calc(8px + 0.65rem);
    }
}

/* Einrichtung einer Mailbox: vier Bausteine in fester Reihenfolge.

   Jeder Baustein hat eine Nummer, einen Stand und genau eine Handlung. Die Nummer sagt, dass
   es eine Reihenfolge gibt und wie viel vor einem liegt; der Stand steht neben dem Titel,
   damit man ihn beim Überfliegen findet. Erledigtes ist grün und ruhig, Offenes gelb,
   Freiwilliges grau – dieselben Farben wie in der Bereitschaftsanzeige, damit beide dasselbe
   meinen. */
.setup-list {
    display: flex;
    flex-direction: column;
}

.setup-block {
    display: flex;
    gap: 0.9rem;
    padding: 1.1rem 0;
    border-top: 1px solid var(--border);
}

.setup-list > .setup-block:first-child {
    border-top: none;
    padding-top: 0.25rem;
}

.setup-list > .setup-block:last-child {
    padding-bottom: 0.25rem;
}

.setup-number {
    flex: 0 0 auto;
    width: 1.85rem;
    height: 1.85rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8125rem;
    font-weight: 600;
    background: var(--surface-sunken);
    color: var(--text-secondary);
}

.setup-block.is-done .setup-number { background: var(--ok-bg); color: var(--ok); }
.setup-block.is-open .setup-number { background: var(--warning-bg); color: var(--warning); }

.setup-main {
    flex: 1 1 auto;
    min-width: 0;
}

.setup-head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.35rem;
}

.setup-title {
    font-size: 1rem;
    margin: 0;
}

.setup-state {
    display: inline-block;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    background: var(--surface-sunken);
    color: var(--text-muted);
}

.setup-block.is-done .setup-state { background: var(--ok-bg); color: var(--ok); }
.setup-block.is-open .setup-state { background: var(--warning-bg); color: var(--warning); }

.setup-body {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

/* Nur der Fliesstext wird in der Zeilenlaenge begrenzt. Die Ansageplaetze darunter brauchen
   die volle Breite, sonst rutscht die Marke mit dem Stand in eine eigene Zeile. */
.setup-body p {
    margin: 0 0 0.4rem;
    max-width: 72ch;
}

.setup-body p:last-child {
    margin-bottom: 0;
}

.setup-body strong {
    color: var(--text-primary);
    font-weight: 600;
}

/* Zugewiesene Rufnummern, jede in einer Zeile mit ihrem Beiwerk. */
.setup-numbers {
    list-style: none;
    margin: 0 0 0.5rem;
    padding: 0;
}

.setup-numbers li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    padding: 0.15rem 0;
}

.setup-numbers .mono {
    color: var(--text-primary);
    font-weight: 500;
}

.setup-numbers .btn-link {
    padding: 0;
    font-size: 0.8125rem;
}

/* Ansageplätze: Art, Name, Stand, Verweis – eine Zeile je Platz. */
.setup-slots {
    list-style: none;
    margin: 0;
    padding: 0;
}

.setup-slot {
    display: flex;
    align-items: center;
    gap: 0.5rem 0.75rem;
    flex-wrap: wrap;
    padding: 0.35rem 0;
}

.setup-slot + .setup-slot {
    border-top: 1px dashed var(--border);
}

.setup-slot-name {
    flex: 0 0 15rem;
    font-weight: 500;
    color: var(--text-primary);
}

.setup-slot-detail {
    color: var(--text-secondary);
}

.setup-slot-link {
    margin-left: auto;
    white-space: nowrap;
}

.setup-action {
    margin-top: 0.7rem;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.setup-action .form-label {
    margin: 0;
}

.setup-action .form-select {
    max-width: 22rem;
}

/* Die Einstellungen der Mailbox, eingeklappt unter den Bausteinen. Die Zusammenfassung sieht
   aus wie die Überschrift der anderen Kästen, damit der Block als gleichrangig gelesen wird
   und nicht als Fussnote. */
.mailbox-settings > summary {
    cursor: pointer;
    font-size: 1rem;
    font-weight: 600;
    list-style-position: inside;
}

.mailbox-settings[open] > summary {
    margin-bottom: 1rem;
}

/* Zwei Kacheln auf dem Dashboard des Kunden sollen nicht die ganze Breite füllen. */
.stat-grid-two {
    grid-template-columns: repeat(2, minmax(0, 320px));
}

/* „Noch offen: Rufnummer, Ansage“ auf der Mailbox-Karte – derselbe gelbe Punkt wie in der
   Bereitschaftsanzeige, damit das Auge beides als dasselbe erkennt. */
.mailbox-missing {
    margin: 0 0 0.9rem;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.mailbox-missing::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--warning);
    margin-right: 0.4rem;
    vertical-align: middle;
}

@media (max-width: 640px) {
    .setup-block {
        gap: 0.6rem;
    }

    .setup-slot-name {
        flex-basis: 100%;
    }

    .setup-slot-link {
        margin-left: 0;
    }
}

/* --- Ansagen und Zeitplaene --- */

/* Ein Satz unter der Ueberschrift eines Kastens, der sagt, wofuer der Kasten da ist.
   Gleiche Farbe wie die Seitenbeschreibung, damit er als Erklaerung gelesen wird und
   nicht als Inhalt. */
.panel-description {
    margin: -0.5rem 0 1rem;
    font-size: 0.875rem;
    color: var(--text-secondary);
}

/* Hinweis unter dem Knopf "Uebliche Geschaeftswoche uebernehmen": Der Knopf ist die
   Handlung, der Hinweis sagt, was er eintraegt. Ohne Abstand klebten beide aneinander. */
.schedule-empty .form-hint {
    margin-top: 0.75rem;
    max-width: 40rem;
    margin-left: auto;
    margin-right: auto;
}

/* Die Marke "Wird nicht abgespielt" unter der Art einer Ansage. */
.greeting-type-note {
    margin-top: 0.35rem;
}

/* --- Rufumleitung --- */

/* Das einmalig angezeigte Kennwort des Agents. Es steht in einem eigenen Block statt in der
   Fliesszeile: Es wird abgeschrieben oder kopiert, und beides misslingt, sobald der Browser
   umbricht oder Leerzeichen einstreut. */
.cf-code {
    margin: 0.6rem 0 0;
    padding: 0.6rem 0.8rem;
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;

    /* Umbrechen statt seitlich scrollen: Auf einem Telefon waere das Kennwort sonst nur zur
       Haelfte zu sehen, und genau dort steht der Kunde beim Einrichten. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.cf-token p {
    margin: 0;
}

/* Der Satz, der sagt, ob sich das Programm beim Kunden meldet. Er ist die erste Auskunft der
   Seite und traegt deshalb Farbe - gruen heisst laeuft, gelb heisst nachsehen. */
.cf-agent-state {
    margin: 0 0 0.75rem;
    font-weight: 500;
}

.cf-ok {
    color: var(--ok);
}

.cf-warn {
    color: var(--warning);
}

/* Meldung des Agents. Sie enthaelt bewusst niemals Zugangsdaten. */
.cf-error {
    margin: 0.5rem 0 0;
    color: var(--danger);
}

/* Eine Mailbox mit ihrer Umleitung. Mehrere stehen untereinander und brauchen Luft dazwischen. */
.cf-mailbox + .cf-mailbox {
    margin-top: 1rem;
}

/* Der Rest dieser Regel ging mit der fehlenden Klammer verloren; ohne Groessenangabe stand
   der Mailboxname als Ueberschrift in der Vorgabegroesse des Browsers und war doppelt so
   gross wie jede andere Kastenueberschrift. Dieselbe Groesse wie .panel-title. */
.cf-mailbox-name {
    margin: 0 0 0.35rem;
    font-size: 1rem;
}

/* --- Ansagen und Musik --- */

/* Ein Abspieler, der seine Breite selbst mitbringt. In der Tabelle war er auf die
   Spaltenbreite gequetscht und legte sich über die Nachbarzelle; jetzt bekommt er die volle
   Breite seiner Karte und hoert bei 22rem auf, damit er auf breiten Schirmen nicht
   davonlaeuft. */
.audio-player {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-top: 0.5rem;
}

.audio-player audio {
    width: 100%;
    max-width: 22rem;
    height: 2.25rem;
}

.audio-player-note {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* Die ruhige Zeile ueber der Liste: verbraucht und verbleibend. Kein Kasten mit Rahmen,
   damit sie nicht wie eine Warnung gelesen wird - gewarnt wird erst, wenn es eng wird. */
.quota-line {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.75rem;
    margin-bottom: 1rem;
    padding: 0.6rem 0.85rem;
    background: var(--surface-muted);
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.quota-line-alert {
    background: var(--warning-bg);
    color: var(--warning);
}

.quota-figures {
    font-weight: 600;
    color: var(--text-primary);
}

.quota-line-alert .quota-figures {
    color: inherit;
}

/* Hinweis an einem Feld, der noch kein Fehler ist: Der Text laesst sich speichern, die
   Aufnahme entsteht nur nicht. Deshalb die Warnfarbe und nicht die Fehlerfarbe. */
.field-warning {
    margin-top: 0.3rem;
    font-size: 0.8125rem;
    color: var(--warning);
}

/* Liste der Ansagen: je Ansage eine Karte ueber die volle Breite statt einer Tabellenzeile.
   Links Art, Bezeichnung und Text, rechts Stand der Aufnahme, Abspieler und Aktionen. */
.greeting-list,
.music-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.greeting-card,
.music-card {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1rem 1.5rem;
    padding: 1rem 1.25rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}

/* Eine stillgelegte Ansage bleibt lesbar, tritt aber zurueck. Nicht ausgrauen: Der Text
   ist der Grund, warum jemand sie ansieht. */
.greeting-card-muted,
.music-card-muted {
    background: var(--surface-muted);
    border-style: dashed;
}

/* Der Textteil darf schrumpfen (min-width: 0 verhindert, dass langer Text die Karte
   aufblaeht), der Audioteil haelt die Breite, die ein Abspieler braucht. */
.greeting-card-body,
.music-card-body {
    flex: 1 1 22rem;
    min-width: 0;
}

.greeting-card-audio,
.music-card-audio {
    flex: 0 1 24rem;
    min-width: 0;
}

.greeting-card-head,
.music-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.6rem;
}

.greeting-card-title,
.music-card-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary);
}

/* "Ist aus, weil die Mailbox geoeffnet ist." Der wichtigste Satz der Seite, deshalb vor der
   Auswahl und nicht als Hinweis darunter. */
.cf-state {
    margin: 0 0 1rem;
    color: var(--text-primary);
}

.cf-muted {
    color: var(--text-secondary);
}

/* Der Hinweis, dass die FRITZ!Box-Zugangsdaten beim Kunden bleiben. Kein farbiger Kasten:
   Er beruhigt, er warnt nicht. */
.cf-note {
    color: var(--text-secondary);
}

/* Die Pakete nebeneinander, auf schmalen Bildschirmen untereinander. */
.cf-downloads {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 0.75rem 0 0;
}

/* --- Rufnummern und Nachrichten --- */

/* Zwei Tabellen, in denen eine Zelle deutlich mehr Platz braucht als die uebrigen: die
   Notizen einer Rufnummer und der Abspieler einer Sprachnachricht. Ohne Zutun verteilt der
   Browser die Breite nach dem laengsten Inhalt je Spalte - "Aktiv" und "0:42" bekamen damit
   genauso viel wie das Feld, in das jemand einen ganzen Satz schreibt.

   Die kurzen Spalten schrumpfen deshalb auf ihren Inhalt (width: 1% zusammen mit nowrap ist
   der uebliche Weg dafuer), und was uebrig bleibt, faellt an die eine Spalte, die es
   braucht. */
.number-table td[data-spalte="Notizen"] {
    width: 100%;
}

.number-table td[data-spalte="Rufnummer"],
.number-table td[data-spalte="Mailbox"],
.number-table td[data-spalte="Zustand"] {
    white-space: nowrap;
    width: 1%;
}

/* Waehrend des Aenderns: Die Spalte "Umgeleitet von" ist so breit, wie ihr laengster
   angezeigter Wert sie macht - und wenn in allen Zeilen nichts drinsteht, ist das ein
   Gedankenstrich. Das Eingabefeld war dann schmaler als sein eigener Platzhalter. */
.number-table td input.form-control {
    min-width: 10rem;
}

.message-table td[data-spalte="Anhören"] {
    width: 100%;
    min-width: 12rem;
}

/* Die drei Knoepfe einer Nachricht duerfen umbrechen. Nebeneinander in einer Zeile brauchten
   sie mehr Platz, als die Tabelle hat; die Tabelle wurde dann breiter als die Seite, und der
   letzte Knopf lag hinter dem rechten Rand. Rechtsbuendig wie in allen anderen Tabellen. */
.message-table td.actions {
    white-space: normal;
}

.message-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.35rem;

    /* Das Mindestmass steht am Kasten und nicht als "width" an der Zelle: Die Spalte des
       Abspielers nimmt mit ihren 100 % alles, was sie kriegen kann, und drueckte die
       Knopfspalte auf die Breite des breitesten Knopfs - drei Knoepfe untereinander, die
       Zeile dreimal so hoch. Ein Mindestmass am Inhalt muss die Tabelle dagegen einhalten.
       13 rem reichen fuer zwei Knoepfe nebeneinander. */
    min-width: 13rem;
}

/* Der gemeinsame Abstand der Knoepfe kommt hier von "gap". Der Seitenabstand aus der
   Tabellenregel kaeme oben drauf und riss die umgebrochene Zeile auseinander. */
.message-actions .btn + .btn {
    margin-left: 0;
}

.message-table td[data-spalte="Eingang"],
.message-table td[data-spalte="Anrufer"],
.message-table td[data-spalte="Dauer"] {
    white-space: nowrap;
    width: 1%;
}

/* Der Abspieler fuellt seine Zelle. Die Eigenhoehe der Bedienleiste liegt je nach Browser
   bei rund 54 px und machte die Zeile hoeher als alle uebrigen; 2,25 rem reichen fuer die
   Knoepfe und halten die Zeile auf der Hoehe der anderen. */
.message-audio {
    display: block;
    width: 100%;
    height: 2.25rem;
}

/* Auf einem Telefon steht eine Zeile nicht mehr nebeneinander, sondern untereinander. Der
   waagerechte Ueberhang von .table-wrapper waere die Alternative - dann liegt aber der
   Abspieler ausserhalb des Bildes, und wer ihn sucht, muesste die Tabelle erst zur Seite
   schieben, ohne zu wissen, dass da noch etwas ist.

   Die Ueberschriften der Tabelle fallen dabei weg; ihren Dienst uebernimmt data-spalte vor
   der Zelle. Genau dafuer steht der Spaltenname dort und nicht nur im <th>. */
@media (max-width: 640px) {
    .number-table,
    .number-table tbody,
    .number-table tr,
    .number-table td,
    .message-table,
    .message-table tbody,
    .message-table tr,
    .message-table td {
        display: block;
        width: auto;
    }

    .number-table thead,
    .message-table thead {
        display: none;
    }

    .number-table tr,
    .message-table tr {
        padding: 0.4rem 0;
        border-bottom: 1px solid var(--border);
    }

    .number-table tr:last-child,
    .message-table tr:last-child {
        border-bottom: none;
    }

    /* Mit .data-table davor, sonst sticht ".data-table tbody td" diese Regel aus und unter
       jeder einzelnen Zelle bliebe ein Strich stehen. Getrennt werden sollen die Zeilen,
       nicht die Angaben innerhalb einer Zeile. */
    .data-table.number-table tbody td,
    .data-table.message-table tbody td {
        padding: 0.3rem 1rem;
        border-bottom: none;
        white-space: normal;
    }

    /* Die Breitenangaben von oben gelten hier nicht mehr: "width: 1 %" hiess dort "so
       schmal wie der Inhalt erlaubt", untereinander heisst es "so schmal wie irgend
       moeglich" - und dann steht "Heute, 18:13 Uhr" auf drei Zeilen. Dieselbe
       Genauigkeit wie die Regeln oben, aber weiter unten im Blatt, deshalb gewinnt sie. */
    .number-table td[data-spalte],
    .message-table td[data-spalte] {
        width: auto;
        min-width: 0;
    }

    .number-table td[data-spalte]::before,
    .message-table td[data-spalte]::before {
        content: attr(data-spalte);
        display: block;
        font-size: 0.75rem;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--text-muted);
    }

    /* Die Handlungen stehen zuletzt und linksbuendig wie alles andere. Rechtsbuendig sahen
       sie aus, als gehoerten sie zur naechsten Zeile. */
    .number-table td.actions,
    .message-table td.actions {
        text-align: left;
        white-space: normal;
    }

    /* Auf dem Telefon gibt es keine Spalte mehr, die ein Mindestmass durchsetzen muesste -
       und 13 rem waeren dort breiter als die Seite. */
    .message-actions {
        justify-content: flex-start;
        min-width: 0;
    }
}

.greeting-card-name {
    margin: 0.3rem 0 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* Der Ansagetext gekuerzt, aber lesbar: normale Schriftgroesse, Zeilenumbruch, keine
   abgeschnittene Zeile mit Auslassungspunkten. Gekuerzt wird im Code, nicht mit CSS -
   sonst haengt die Lesbarkeit an der Fensterbreite. */
.greeting-card-text,
.music-card-text {
    margin: 0.5rem 0 0;
    font-size: 0.875rem;
    line-height: 1.5;
    color: var(--text-primary);
    overflow-wrap: anywhere;
}

.music-card-licence {
    margin: 0.5rem 0 0;
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* Die Aktionen als sichtbare Knoepfe statt als Klappmenue: Das Menue legte sich ueber die
   Zeile darunter, und drei Knoepfe haben in der Karte Platz. */
.greeting-card-actions,
.music-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.6rem;
}

/* Unter 900 px steht der Audioteil unter dem Text. Ab hier zaehlt nur noch, dass nichts
   waagerecht scrollt - auch nicht bei 400 px. */
@media (max-width: 900px) {
    .greeting-card-body,
    .music-card-body,
    .greeting-card-audio,
    .music-card-audio {
        flex: 1 1 100%;
    }
}

@media (max-width: 480px) {
    .greeting-card,
    .music-card {
        padding: 0.85rem 0.9rem;
    }

    .audio-player audio {
        max-width: 100%;
    }

    /* Knoepfe ueber die volle Breite: nebeneinander waeren sie auf einem Telefon zu schmal
       zum Treffen. */
    .greeting-card-actions .btn,
    .music-card-actions .btn {
        flex: 1 1 100%;
    }

    .music-upload input[type="file"] {
        max-width: 100%;
    }
}

/* --- Dashboard --- */

/* Das Dashboard ist seit dem Umbau die Lageuebersicht und nicht mehr der Einstieg in die
   Einrichtung. Alles hier dient dem einen Zweck: weniger Kasten, mehr Zustand.

   Ausschliesslich vorhandene Variablen, keine festen Farben - hell und dunkel entstehen
   an einer Stelle, oben in :root, und nicht hier unten noch einmal. */

/* Eine Kachel soll nicht die ganze Breite fuellen: Eine einzelne Zahl, ueber 1400 px
   gezogen, sieht nach einer Ueberschrift aus und nicht nach einer Kennzahl. */
.stat-grid-one {
    grid-template-columns: minmax(0, 320px);
}

/* Ist alles eingerichtet, bleibt von der Bereitschaftsanzeige eine Zeile - ohne Kasten,
   ohne Ueberschrift. Der gruene Punkt davor traegt die Aussage; die Zeile selbst bleibt
   ruhig, damit der Blick an ihr vorbei auf die Mailbox-Karten faellt. */
.readiness-line {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0 0 1.5rem;
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.readiness-line::before {
    content: "";
    width: 9px;
    height: 9px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--ok);
}

/* Die Zeile zum Sprachsynthese-Kontingent unter der Komponentenliste. Sie gehoert in
   denselben Kasten - es ist derselbe Blick auf den Zustand der Plattform -, soll aber
   nicht wie eine weitere Komponente aussehen, die gruen oder grau sein koennte. */
.system-note {
    margin: 0.9rem 0 0;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border);
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* Vier Angaben je Mailbox-Karte statt drei: Was ein Anrufer hoert, ob die Rufumleitung an
   ist, was Neues da ist, wann sich das aendert. Bei festen drei Spalten stand die vierte
   allein in einer zweiten Zeile; auto-fit bricht sie stattdessen auf zwei mal zwei um.
   Die Zahl der Angaben schwankt ohnehin - ohne eingerichteten Agent fehlt die Umleitung. */
.mailbox-facts {
    grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
    gap: 0.6rem 0.5rem;
}

/* --- Stimmenauswahl --- */

/* Der Satz ueber der Stimmenauswahl, wenn dem Konto jede deutsche Stimme fehlt. Bewusst
   als Warnung und nicht als blasser Hinweis: Wer ihn ueberliest, waehlt eine Stimme, die
   den Ansagetext mit englischem Akzent vorliest, und hoert das erst an der fertigen
   Aufnahme. Farben ausschliesslich ueber die Variablen, damit der Kasten in der dunklen
   Fassung mitzieht. */
.voice-language-note {
    margin: 0 0 0.5rem;
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--warning-border);
    border-radius: var(--radius-sm);
    background: var(--warning-bg);
    color: var(--warning);
    font-size: 0.8125rem;
    line-height: 1.45;
}

/* Die Bibliothek im Abschnitt der Sprachsynthese. Sie steht unter den Feldern und dem
   Speichern-Knopf und ist deshalb durch eine Linie abgesetzt: Was darunter folgt, wird
   nicht mitgespeichert, sondern wirkt sofort beim Anbieter. */
.voice-library {
    margin-top: 1.5rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--border);
}

.voice-library-title {
    font-size: 0.9375rem;
    margin-bottom: 0.4rem;
}

/* Eine Stimme je Kasten. Die Hoerprobe braucht eine eigene Zeile - in einer Tabellenzelle
   sass der Abspieler frueher schon einmal zu eng. */
.voice-library-item {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    align-items: flex-start;
    margin-top: 0.75rem;
    padding: 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-muted);
}

.voice-library-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
}

.voice-library-name {
    font-weight: 600;
}

.voice-library-traits {
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.voice-library-description {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* --- Betriebsferien --- */

/* Das Enddatum der Betriebsferien. Anders als .override-custom steht es als Erstes im
   Kasten: Es ist nicht das "oder auch"-Feld neben einer Schnellauswahl, sondern die einzige
   Angabe. Deshalb ohne Trennlinie darueber - die trennte hier nichts. */
.override-vacation .form-label {
    margin-bottom: 0.35rem;
}

/* Bei 400 px stehen Datumsfeld und Schaltflaeche sonst nebeneinander und schieben die Zeile
   ueber den Rand. .time-range ist auf zwei schmale Uhrzeiten ausgelegt; hier traegt sie ein
   Datum und eine Schaltflaeche mit drei Woertern. */
@media (max-width: 480px) {
    .override-vacation .time-range {
        flex-wrap: wrap;
    }

    .override-vacation .time-range .form-control {
        max-width: none;
        flex: 1 1 100%;
    }
}

/* --- Gesetzliche Feiertage --- */

/* Die Liste der kommenden Feiertage. Keine Tabelle: Jede Zeile ist ein Haekchen mit drei
   kurzen Angaben, und eine Tabelle mit drei schmalen Spalten bricht bei 400 px unschoen um. */
.holiday-list {
    list-style: none;
    margin: 0.75rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.holiday-item {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    border-radius: 6px;
}

.holiday-item:nth-child(odd) {
    background: var(--surface-muted);
}

.holiday-label {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem 0.75rem;
    cursor: pointer;
}

/* Feste Breite, damit die Wochentage untereinander stehen und die Namen eine Kante bilden.
   Ohne sie tanzt die Spalte je nach Laenge des Datums. */
.holiday-date {
    font-variant-numeric: tabular-nums;
    min-width: 5.5rem;
}

.holiday-day {
    color: var(--text-muted);
    min-width: 5.5rem;
}

.holiday-name {
    font-weight: 600;
}

/* Abgewaehlt: Der Eintrag bleibt lesbar, tritt aber zurueck. Durchgestrichen waere zu viel –
   der Tag ist ja weiterhin ein Feiertag, nur einer mit geoeffnetem Betrieb. */
.holiday-item-off .holiday-date,
.holiday-item-off .holiday-day,
.holiday-item-off .holiday-name {
    color: var(--text-muted);
    font-weight: 400;
}

.holiday-options {
    margin-top: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.holiday-options .form-hint {
    margin-left: 1.75rem;
}

/* Bei 400 px steht das Datum allein in der Zeile und der Name darunter; die feste Breite
   der Spalten wuerde die Zeile sonst ueber den Rand schieben. */
@media (max-width: 480px) {
    .holiday-date,
    .holiday-day {
        min-width: 4.5rem;
    }

    .holiday-name {
        flex: 1 1 100%;
    }
}
