/* =====================================================================
   nsai-graph - Gestaltung nach "Brilliant Glas"
   ---------------------------------------------------------------------
   HERKUNFT: Stefans Design-Projekt "Designsystem mit Testmustern",
   gelesen am 2026-09-01. Werte aus `tokens/colors.css`,
   `typography.css`, `spacing.css`, `glass.css`, `motion.css` und der
   Glasrezeptur aus `css/surfaces.css`. Zitiert, nicht nacherfunden.

   WAS DIESE DATEI TUT: Sie gibt den Tailwind-Klassennamen, die die
   auth-bundle-Vorlagen fuehren, die Bedeutung des Glassystems. Kein
   Bundle-Markup wird angefasst - die Rezeptur haengt an `::before` und
   `::after`, und die gibt es an jedem Element.

   VIER ENTSCHEIDUNGEN, Stefan am 2026-09-01, zwei davon ausdruecklich
   gegen meine Empfehlung - beide sind hier vollstaendig umgesetzt:

     1. Schriften vom Google-CDN, wie im Design-Projekt. Ich hatte
        Selbsthosten empfohlen (kein fremder Host im Betrieb). Auflage
        des Koordinators, umgesetzt: JEDE Familie hat einen
        vollstaendigen Rueckfallstapel, damit ein CDN-Ausfall das System
        haesslicher macht und nicht kaputt.
     2. Kuehle Verlaufsfelder als Hintergrund, kein Foto.
     3. DUNKEL ist die Vorgabe. Der Drei-Wege-Schalter bleibt.
     4. Die Auto-Toenung kommt mit, volle Rezeptur.

   ZWEI BEFUNDE ZU (4), die beim Bauen herauskamen:

     a) Der Abtaster in `brilliant-glas.js` sucht ein HINTERGRUNDBILD
        (`url(...)`). Bei Verlaufsfeldern findet er keines und faellt auf
        `--bg-tint-fallback` zurueck. Entscheidung 2 und 4 heben sich
        insoweit auf - das Skript bleibt trotzdem noetig, denn es spritzt
        den SVG-Brechungsfilter ein, den `--bg-lens` braucht.
     b) DESHALB IST DIE LINSE BEDINGT. Bleibt das Skript aus (Fehler,
        blockiert, CSP), zeigte `backdrop-filter: url(#bg-lens)` auf einen
        Filter, den es nicht gibt. Die Linse steht deshalb nur unter
        `[data-bg-lens="ready"]`, das erst das Skript setzt. Ohne Skript
        bleibt das Glas ungetoent statt zu brechen - die Auflage aus dem
        CSRF-Fund, auf diesen Fall angewandt.

   UND EINE UMKEHR, die ins Register gehoert: `backdrop-filter` kehrt in
   die Kopfleiste zurueck. Ich hatte ihn heute frueh entfernt, weil er
   dort nichts zu zeigen hatte und in Chromium eine Naht erzeugte. Unter
   diesem System liegt ein Verlaufsfeld dahinter, er hat eine Aufgabe.
   Die Entfernung war damals richtig und ist es jetzt nicht mehr.

   ABDECKUNG: `tools/gestaltung-abdeckung.sh` zaehlt weiter jede in einer
   Vorlage benutzte Klasse gegen dieses Blatt.
   ===================================================================== */

/* Schriften: Stefans Wahl. Material Symbols wird NICHT geladen - keine
   Vorlage fuehrt ein Symbol, und was niemand benutzt, laedt niemand.
   Damit stellt sich die Ligaturen-Frage hier nicht: Faellt das CDN aus,
   kann kein Ligaturtext in einem Knopf stehen, weil kein Knopf ein
   Symbol traegt. Sobald Symbole kommen (Bundle-PR), gehoert die
   Degradation dort geloest, nicht hier vorweggenommen. */
@import url("https://fonts.googleapis.com/css2?family=Inter+Tight:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap");

/* ------------------------------------------------------------------ *
 * 1. Marken - Werte aus dem Design-Projekt, dunkel ist die Vorgabe
 * ------------------------------------------------------------------ */

:root {
    color-scheme: dark;

    --bg-page:   #070810;
    --bg-page-2: #0D0F1C;

    --bg-ink-1: #F4F6FF;
    --bg-ink-2: #B9BFD6;
    --bg-ink-3: #858BA5;
    --bg-ink-4: #5A6079;

    --bg-edge:        rgba(255, 255, 255, .22);
    --bg-edge-strong: rgba(255, 255, 255, .38);
    --bg-highlight:   rgba(255, 255, 255, .35);
    --bg-shade:       rgba(0, 0, 0, .10);

    --bg-fill:        rgba(255, 255, 255, .02);
    --bg-fill-inset:  rgba(0, 0, 0, .25);
    --bg-fill-opaque: #171A2B;

    /* Akzente. Kein rohes Rot und kein rohes Gruen - Gefahr ist Magenta,
       Erfolg Limette, Info Cyan, Warnung Bernstein. */
    /* ORBIT-FARBWELT (Stefans Nachentscheid 2026-09-01): "Will es etwas
       mehr nach dem Namen (Orbit) von der Farbe her aussehen lassen."
       Leitakzent ist damit INDIGO, die Toenung Cyan - beides Werte, die
       er ausdruecklich behalten wollte. Magenta bleibt im System, tritt
       aber vom Leitakzent zurueck auf seine eigentliche Rolle: Gefahr.
       Das macht es sogar eindeutiger - "Gefahr ist Magenta" stimmt jetzt
       ohne Ausnahme, weil Magenta sonst nirgends mehr steht. */
    --bg-accent:       #614cc4;
    --bg-accent-magenta: #FF3EA5;
    --bg-accent-cyan:  #3FE0FF;
    --bg-accent-lime:  #9FFF7A;
    --bg-accent-amber: #FFC85B;
    --bg-accent-ink:   #FFFFFF;

    --bg-tint-fallback: #3FE0FF;
    --bg-tint: var(--bg-tint-auto, var(--bg-tint-fallback));
    --bg-tint-strength: .12;

    --bg-focus: var(--bg-tint);
    --bg-link: var(--bg-tint);
    --bg-link-hover: var(--bg-ink-1);

    /* Die Verlaufsfelder, kuehl (Entscheidung 2). Nie eine flache Farbe
       hinter Glas - ohne etwas zu brechen verschwindet der Effekt. */
    --bg-feld-1: rgba(63, 224, 255, .22);
    --bg-feld-2: rgba(120, 86, 255, .26);
    --bg-feld-3: rgba(255, 62, 165, .16);
    --bg-gitter: rgba(255, 255, 255, .05);
    --bg-card-fill: rgba(10, 14, 28, .24);
    --bg-card-shadow: 0 18px 48px rgba(3, 6, 18, .30), var(--bg-inner);
    --bg-card-tint: 0;
    --bg-line: rgba(255, 255, 255, .14);
    --bg-fill-hi: color-mix(in srgb, var(--bg-ink-1) 12%, transparent);

    --bg-font-display: "Inter Tight", "Inter", ui-sans-serif, system-ui,
                       -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --bg-font-body:    "Inter", ui-sans-serif, system-ui,
                       -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --bg-font-mono:    "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono",
                       Menlo, Consolas, "Liberation Mono", monospace;

    --bg-text-display: 56px;
    --bg-text-h1: 40px;
    --bg-text-h2: 28px;
    --bg-text-h3: 18px;
    --bg-text-body: 14px;
    --bg-text-sm: 13px;
    --bg-text-xs: 11px;

    --bg-leading-tight: 1.05;
    --bg-leading-snug: 1.3;
    --bg-leading-body: 1.7;

    --bg-tracking-display: -.035em;
    --bg-tracking-tight: -.02em;
    --bg-tracking-eyebrow: .08em;

    --bg-radius-sm: 8px;
    --bg-radius-md: 12px;
    --bg-radius-lg: 16px;
    --bg-radius-xl: 24px;
    --bg-radius-pill: 999px;
    --bg-pad-card: 22px;
    --bg-container: 1280px;
    --bg-hairline: 1px;

    /* Raum (ng#833). `--bg-space-5` stand vor diesem Block nur als Aufruf
       in `.nsai-kopf-innen` und war nirgends definiert - es griff immer
       der Fallback 20px. Es zeigt jetzt auf die Skala, also 24px. */
    --bg-raum-1: 4px;
    --bg-raum-2: 8px;
    --bg-raum-3: 12px;
    --bg-raum-4: 16px;
    --bg-raum-5: 24px;
    --bg-raum-6: 40px;
    /* Eine Stufe im Faden (ng#874). Auf dem Telefon rueckt nichts ein -
       dort traegt die Leiste die Ebene; die Breite kommt ab 640px. */
    --bg-faden-stufe: 0px;
    --bg-faden-leiste: 2px;
    --bg-space-5: var(--bg-raum-5);

    /* Rinne und Kachelradius des Bento-Rasters. Die Rinne waechst mit der
       Breite, der Radius bleibt der der Glasrezeptur. */
    --bg-rinne: var(--bg-raum-3);
    --bg-radius-kachel: var(--bg-radius-lg);
    --bg-kopf: 60px;

    --bg-blur: 28px;
    --bg-blur-subtle: calc(var(--bg-blur) * .43);
    --bg-blur-heavy: calc(var(--bg-blur) * 1.7);
    --bg-saturate: 130%;
    --bg-brightness: 102%;
    --bg-lens: url(#bg-lens);
    --bg-lens-scale: 14;
    --bg-edge-fade: 10px;

    --bg-drop: 0 1px 3px rgba(0, 0, 0, .22);
    --bg-drop-lifted: 0 12px 32px -12px rgba(0, 0, 0, .45);
    --bg-inner: inset 0 1px 0 var(--bg-highlight), inset 0 -1px 0 var(--bg-shade);

    --bg-dur-fast: 120ms;
    --bg-dur: 200ms;
    --bg-dur-slow: 320ms;
    --bg-ease-out: cubic-bezier(.2, .8, .25, 1);
    /* Nur Verschiebung, keine Skalierung: Eine gebrochene Skalierung
       setzt Text auf halbe Pixel und laesst ihn beim Ueberfahren neu und
       unscharf rastern. Tiefe kommt aus dem Schatten. So steht es in
       `tokens/motion.css`; die `readme.md` nennt noch 1.01 - die Token
       sind der Vertrag. */
    --bg-lift: translateY(-2px);
    --bg-press: translateY(1px);
}

/* Hell, wenn das System es sagt - ausser der Besucher hat dunkel gewaehlt. */
@media (prefers-color-scheme: light) {
    :root:not([data-bg-theme="dark"]) {
        color-scheme: light;
        --bg-page: #F2F4FA;
        --bg-page-2: #E7EBF5;
        --bg-ink-1: #10131F;
        --bg-ink-2: #3A3F55;
        --bg-ink-3: #6B7089;
        --bg-ink-4: #A4A8BC;
        --bg-edge: rgba(255, 255, 255, .65);
        --bg-edge-strong: rgba(255, 255, 255, .85);
        --bg-highlight: rgba(255, 255, 255, .85);
        --bg-shade: rgba(20, 24, 45, .06);
        /* 55 % Weiss, nicht 2 %: Helles Glas muss dunkle Tinte ueber
           beliebigem Untergrund tragen. */
        --bg-fill: rgba(255, 255, 255, .55);
        --bg-fill-inset: rgba(20, 24, 45, .05);
        --bg-fill-opaque: #FFFFFF;
        --bg-accent: #4d3ba0;
        --bg-accent-magenta: #C4176F;
        --bg-accent-cyan: #0B6A80;
        --bg-accent-lime: #2E6B12;
        --bg-accent-amber: #7A5106;
        --bg-accent-ink: #FFFFFF;
        /* NICHT #C4176F wie im Design-Projekt - und der Grund gehoert dazu:
       Der Ersatzwert ist dort ein NOTBEHELF fuer den Fall, dass der
       Abtaster kein Bild findet. Bei uns ist er der DAUERZUSTAND, weil
       hinter dem Glas Verlaufsfelder liegen und kein Foto (Entscheidung 2).
       Magenta bei 12 % ueber 55 % Weiss laesst die Karte als rosa Karte
       lesen statt als Scheibe - genau der Fehlerfall, den das System
       beschreibt. Gesetzt ist deshalb, was der Abtaster GEFUNDEN HAETTE:
       Unser Feld ist cyan-dominant. Stefans Palette, andere Stelle. */
    --bg-tint-fallback: #0B6A80;
        --bg-drop: 0 8px 30px -10px rgba(20, 24, 45, .28);
        --bg-drop-lifted: 0 18px 44px -14px rgba(20, 24, 45, .34);
        /* Kraeftiger als im Dunkeln, und das ist kein Zufall: Helles Glas
           traegt 55 % Weiss plus 12 % Toenung. Ueber einem BLASSEN Grund
           hat es nichts zu brechen, die Toenung dominiert, und die Karte
           liest sich als farbige Karte statt als Scheibe - genau der
           Fehlerfall, den das System bei >20 % Toenung beschreibt. Die
           Antwort ist mehr Substanz im Grund, nicht weniger Toenung.
           Stefans Token bleiben unangetastet; geaendert ist nur, WAS
           hinter dem Glas liegt - und das ist Entscheidung 2, nicht 1. */
        --bg-feld-1: rgba(11, 106, 128, .30);
        --bg-feld-2: rgba(120, 86, 255, .26);
        --bg-feld-3: rgba(196, 23, 111, .16);
        --bg-gitter: rgba(16, 19, 31, .06);
        --bg-card-fill: rgba(255, 255, 255, .46);
        --bg-line: rgba(15, 20, 34, .12);
    }
}

/* Und hell, wenn der Besucher es ausdruecklich gewaehlt hat. */
:root[data-bg-theme="light"] {
    color-scheme: light;
    --bg-page: #F2F4FA;
    --bg-page-2: #E7EBF5;
    --bg-ink-1: #10131F;
    --bg-ink-2: #3A3F55;
    --bg-ink-3: #6B7089;
    --bg-ink-4: #A4A8BC;
    --bg-edge: rgba(255, 255, 255, .65);
    --bg-edge-strong: rgba(255, 255, 255, .85);
    --bg-highlight: rgba(255, 255, 255, .85);
    --bg-shade: rgba(20, 24, 45, .06);
    --bg-fill: rgba(255, 255, 255, .55);
    --bg-fill-inset: rgba(20, 24, 45, .05);
    --bg-fill-opaque: #FFFFFF;
    --bg-accent: #4d3ba0;
    --bg-accent-magenta: #C4176F;
    --bg-accent-cyan: #0B6A80;
    --bg-accent-lime: #2E6B12;
    --bg-accent-amber: #7A5106;
    --bg-accent-ink: #FFFFFF;
    --bg-tint-fallback: #0B6A80;
    --bg-drop: 0 8px 30px -10px rgba(20, 24, 45, .28);
    --bg-drop-lifted: 0 18px 44px -14px rgba(20, 24, 45, .34);
    --bg-feld-1: rgba(11, 106, 128, .30);
    --bg-feld-2: rgba(120, 86, 255, .26);
    --bg-feld-3: rgba(196, 23, 111, .16);
    --bg-gitter: rgba(16, 19, 31, .06);
    --bg-card-fill: rgba(255, 255, 255, .46);
    --bg-line: rgba(15, 20, 34, .12);
}

@media (prefers-reduced-motion: reduce) {
    :root { --bg-lift: none; --bg-press: none;
            --bg-dur: 1ms; --bg-dur-fast: 1ms; --bg-dur-slow: 1ms; }
}

/* ------------------------------------------------------------------ *
 * 2. Grundlage
 * ------------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: var(--bg-page);
    /* Die Verlaufsfelder. `fixed`, damit sie beim Blaettern stehen
       bleiben - Glas ueber einem mitscrollenden Grund wirkt wie Farbe. */
    background-image:
        repeating-linear-gradient(0deg, var(--bg-gitter) 0 1px, transparent 1px 48px),
        repeating-linear-gradient(90deg, var(--bg-gitter) 0 1px, transparent 1px 48px),
        radial-gradient(60rem 42rem at 10% -10%, var(--bg-feld-1), transparent 60%),
        radial-gradient(52rem 40rem at 92% 4%,   var(--bg-feld-2), transparent 62%),
        radial-gradient(46rem 34rem at 58% 104%, var(--bg-feld-3), transparent 58%);
    background-attachment: fixed;
    color: var(--bg-ink-1);
    font-family: var(--bg-font-body);
    font-size: var(--bg-text-body);
    line-height: var(--bg-leading-body);
    -webkit-font-smoothing: antialiased;
    text-wrap: pretty;
}

h1, h2, h3, h4 {
    margin: 0;
    font-family: var(--bg-font-display);
    font-weight: 600;
    line-height: var(--bg-leading-snug);
    letter-spacing: var(--bg-tracking-tight);
    text-wrap: balance;
}

p { margin: 0; }

a { color: var(--bg-link); text-decoration: none;
    transition: color var(--bg-dur) var(--bg-ease-out); }
a:hover { color: var(--bg-link-hover); }

input, select, textarea, button { font: inherit; color: inherit; }
input, select, textarea { border: var(--bg-hairline) solid transparent; }
input::placeholder, textarea::placeholder { color: var(--bg-ink-4); }
button { background: none; border: 0; }

table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; }

code, pre { font-family: var(--bg-font-mono); }
hr { border: 0; border-top: var(--bg-hairline) solid var(--bg-edge); margin: 0; }

/* Fokus: 2px, Versatz 2px, auf jedem bedienbaren Element. Nie entfernt,
   nie durch einen Schatten ersetzt - so steht es im System, und die
   Vorlagen setzen an vielen Stellen `focus:outline-none`. */
:focus-visible,
.focus\:outline-none:focus-visible {
    outline: 2px solid var(--bg-focus);
    outline-offset: 2px;
}

.nsai-sprung {
    position: absolute;
    left: 12px; top: -80px; z-index: 50;
    padding: 10px 14px;
    border-radius: var(--bg-radius-sm);
    background: var(--bg-fill-opaque);
    color: var(--bg-ink-1);
    border: var(--bg-hairline) solid var(--bg-edge);
    transition: top var(--bg-dur) var(--bg-ease-out);
}
.nsai-sprung:focus { top: 12px; text-decoration: none; box-shadow: var(--bg-drop-lifted); }

/* ------------------------------------------------------------------ *
 * 3. Die Glasrezeptur
 * ------------------------------------------------------------------
 * Eine Rezeptur, an `.bg-white` gehaengt: Jede Karte der Vorlagen traegt
 * `bg-white dark:bg-gray-800`, und sonst traegt es nichts. `shadow-sm`
 * taugte nicht als Anker - das steht auch auf dem Absende-Knopf.
 * ------------------------------------------------------------------ */

.bg-white {
    position: relative;
    isolation: isolate;
    border-radius: var(--bg-radius-lg);
    border: var(--bg-hairline) solid var(--bg-edge);
    background: var(--bg-card-fill);
    color: var(--bg-ink-1);
    box-shadow: var(--bg-card-shadow);
}

/* Toenungsschicht */
.bg-white::before {
    content: "";
    position: absolute;
    inset: var(--bg-hairline);
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background: var(--bg-tint);
    opacity: var(--bg-card-tint);
    backdrop-filter: saturate(var(--bg-saturate));
    -webkit-backdrop-filter: saturate(var(--bg-saturate));
}

/* Die Brechung kommt NUR dazu, wenn das Skript den Filter gesetzt hat.
   Sonst zeigte `url(#bg-lens)` ins Leere.

   UND NUR AN EINER FLAECHE: der unter dem Zeiger oder mit Fokus. Das
   Attribut setzt `brilliant-glas.js`, eine Kachel nach der anderen; wer
   keine Bewegung will, bekommt es nie gesetzt und sieht alles still
   (ng#833 Punkt 3). */
[data-bg-lens="ready"] .bg-white[data-bg-linse="an"]::before {
    backdrop-filter: var(--bg-lens) saturate(var(--bg-saturate));
    -webkit-backdrop-filter: var(--bg-lens) saturate(var(--bg-saturate));
}

/* Weichzeichnung, Kanten ausblendend, damit der Rand als echter Rahmen liest */
.bg-white::after {
    content: "";
    position: absolute;
    inset: var(--bg-hairline);
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    backdrop-filter: blur(var(--bg-surface-blur, var(--bg-blur))) brightness(var(--bg-brightness));
    -webkit-backdrop-filter: blur(var(--bg-surface-blur, var(--bg-blur))) brightness(var(--bg-brightness));
    --e: min(var(--bg-edge-fade), calc(50% - var(--bg-hairline)));
    mask-image:
        linear-gradient(to right, transparent 0, #000 var(--e), #000 calc(100% - var(--e)), transparent 100%),
        linear-gradient(to bottom, transparent 0, #000 var(--e), #000 calc(100% - var(--e)), transparent 100%);
    -webkit-mask-composite: source-over;
    mask-composite: add;
}

.bg-white > * { position: relative; }

/* Rueckfall: ohne backdrop-filter kein Glas - deckend werden, lesbar bleiben. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .bg-white { background: var(--bg-fill-opaque); }
    .bg-white::before, .bg-white::after { display: none; }
}

/* Vertiefte Mulde: Eingabefelder, Kennzahlen, ruhige Hinweisflaechen. */
.bg-gray-100, .bg-gray-50, .dark\:bg-gray-700, .dark\:bg-gray-900\/40 {
    border-radius: var(--bg-radius-sm);
    background: var(--bg-fill-inset);
    border: var(--bg-hairline) solid var(--bg-edge);
    box-shadow: inset 0 1px 2px var(--bg-shade);
    backdrop-filter: blur(var(--bg-blur-subtle)) saturate(var(--bg-saturate));
    -webkit-backdrop-filter: blur(var(--bg-blur-subtle)) saturate(var(--bg-saturate));
}

/* ------------------------------------------------------------------ *
 * 4. Die Rahmung
 * ------------------------------------------------------------------
 * KEINE GEZEICHNETE MARKE MEHR. Das System sagt es ausdruecklich: "There
 * is no logo in any source. Wherever a mark would go, set the brand name
 * in Inter Tight. Do not draw one." Mein Knoten-und-Kante-Zeichen aus
 * der ersten Fassung faellt damit weg - es war meine Erfindung, nicht
 * seine. Der Name steht jetzt fuer sich.
 * ------------------------------------------------------------------ */

.nsai-kopf {
    position: sticky;
    top: 0;
    z-index: 20;
    padding: var(--bg-raum-3) var(--bg-raum-3) 0;
}

/* Orbit-Prototyp: nsai-graph/bericht/2026-10-11-orbit-glas-prototyp */
.nsai-kopf-innen {
    position: relative;
    isolation: isolate;
    max-width: calc(var(--bg-container) - 2 * var(--bg-raum-5));
    margin: 0 auto;
    padding: var(--bg-raum-2) var(--bg-raum-3) var(--bg-raum-2) var(--bg-raum-5);
    min-height: var(--bg-kopf);
    display: flex;
    align-items: center;
    gap: var(--bg-raum-2);
    border-radius: var(--bg-radius-lg);
    border: var(--bg-hairline) solid var(--bg-edge);
    background: var(--bg-card-fill);
    box-shadow: var(--bg-card-shadow);
}
.nsai-kopf-innen::before {
    content: "";
    position: absolute;
    inset: var(--bg-hairline);
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background: var(--bg-tint);
    opacity: var(--bg-card-tint);
    backdrop-filter: saturate(var(--bg-saturate));
    -webkit-backdrop-filter: saturate(var(--bg-saturate));
}
.nsai-kopf-innen::after {
    content: "";
    position: absolute;
    inset: var(--bg-hairline);
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    backdrop-filter: blur(var(--bg-blur)) brightness(var(--bg-brightness));
    -webkit-backdrop-filter: blur(var(--bg-blur)) brightness(var(--bg-brightness));
    --e: min(var(--bg-edge-fade), calc(50% - var(--bg-hairline)));
    mask-image:
        linear-gradient(to right, transparent 0, #000 var(--e), #000 calc(100% - var(--e)), transparent 100%),
        linear-gradient(to bottom, transparent 0, #000 var(--e), #000 calc(100% - var(--e)), transparent 100%);
    mask-composite: add;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .nsai-kopf-innen { background: var(--bg-fill-opaque); }
    .nsai-kopf-innen::before, .nsai-kopf-innen::after { display: none; }
}

.nsai-marke {
    font-family: var(--bg-font-display);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: var(--bg-tracking-display);
    color: var(--bg-ink-1);
    white-space: nowrap;
}
.nsai-marke:hover { color: var(--bg-ink-1); text-decoration: none; }

.nsai-nav { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.nsai-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--bg-raum-4);
    border: var(--bg-hairline) solid transparent;
    border-radius: var(--bg-radius-md);
    font-size: var(--bg-text-body);
    font-weight: 500;
    color: var(--bg-ink-2);
    white-space: nowrap;
    transition: color var(--bg-dur) var(--bg-ease-out),
                background-color var(--bg-dur) var(--bg-ease-out),
                border-color var(--bg-dur) var(--bg-ease-out);
}
.nsai-nav a:hover { color: var(--bg-ink-1); background: color-mix(in srgb, var(--bg-ink-1) 8%, transparent); text-decoration: none; }
.nsai-nav a[aria-current="page"] { color: var(--bg-ink-1); background: color-mix(in srgb, var(--bg-ink-1) 12%, transparent); border-color: var(--bg-edge); font-weight: 600; }

.nsai-inhalt {
    flex: 1;
    width: 100%;
    max-width: var(--bg-container);
    margin: 0 auto;
    padding: 40px 20px 64px;
}

.nsai-fuss {
    border-top: var(--bg-hairline) solid var(--bg-edge);
    color: var(--bg-ink-3);
    font-size: var(--bg-text-xs);
    font-family: var(--bg-font-mono);
}
.nsai-fuss-innen {
    max-width: var(--bg-container);
    margin: 0 auto;
    padding: 18px 20px;
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px 20px;
}
.nsai-fuss a { color: var(--bg-ink-3); }
.nsai-fuss a:hover { color: var(--bg-ink-1); }
.nsai-fuss-rechts { margin-left: auto; }

/* Der Drei-Wege-Schalter bleibt - nur die Vorgabe ist jetzt dunkel. */
.nsai-thema {
    display: inline-flex; align-items: center; gap: 2px; padding: 3px;
    margin-left: var(--bg-raum-2);
    border: var(--bg-hairline) solid var(--bg-line);
    border-radius: var(--bg-radius-md);
}
.nsai-thema button {
    min-height: 36px;
    padding: 0 10px;
    border: var(--bg-hairline) solid transparent;
    border-radius: var(--bg-radius-sm);
    font-size: var(--bg-text-sm);
    color: var(--bg-ink-2);
    cursor: pointer;
    transition: color var(--bg-dur-fast) var(--bg-ease-out),
                background-color var(--bg-dur-fast) var(--bg-ease-out);
}
.nsai-thema button:hover { color: var(--bg-ink-1); background: color-mix(in srgb, var(--bg-ink-1) 8%, transparent); }
.nsai-thema button[aria-pressed="true"] {
    background: color-mix(in srgb, var(--bg-ink-1) 12%, transparent);
    border-color: var(--bg-edge);
    color: var(--bg-ink-1);
    font-weight: 600;
}

.nsai-thema button { text-transform: capitalize; }

.nsai-kopf-konto {
    display: flex;
    align-items: center;
    gap: var(--bg-raum-2);
    margin-left: auto;
}
.nsai-menue { order: 1; }
.nsai-mandant {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 0 var(--bg-raum-3);
    border: var(--bg-hairline) solid var(--bg-line);
    border-radius: var(--bg-radius-pill);
    font-family: var(--bg-font-mono);
    font-size: var(--bg-text-xs);
    color: var(--bg-ink-2);
    white-space: nowrap;
}
.nsai-mandant:hover { color: var(--bg-ink-1); border-color: var(--bg-edge-strong); text-decoration: none; }
.nsai-profil {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: var(--bg-hairline) solid var(--bg-line);
    border-radius: var(--bg-radius-md);
    color: var(--bg-ink-1);
    transition: background-color var(--bg-dur) var(--bg-ease-out);
}
.nsai-profil:hover { background: color-mix(in srgb, var(--bg-ink-1) 8%, transparent); color: var(--bg-ink-1); }
.nsai-profil[aria-current="page"] { background: color-mix(in srgb, var(--bg-ink-1) 12%, transparent); }

.nsai-kacheln { display: grid; gap: 20px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.nsai-inhalt.justify-center { min-height: 70vh; }

/* ------------------------------------------------------------------ *
 * 4b. Bento-Raster und Kopfleiste, mobile-first (ng#833 Block A)
 * ------------------------------------------------------------------
 * Die Spannweite traegt Bedeutung: `--breit` ist die Hauptaufgabe der
 * Seite, `--voll` eine Seite mit genau einer Aussage, ohne Modifikator
 * eine Kennzahl oder Nebenaktion. Kein Dekor ohne Aussage.
 *
 * Die Glasrezeptur bleibt an `.bg-white`; eine Kachel traegt beides und
 * regelt hier nur Raster und Innenabstand. Block H kann die Linse je
 * Kachel setzen, ohne dass hier etwas umgebaut wird.
 * ------------------------------------------------------------------ */
.nsai-bento {
    display: grid;
    gap: var(--bg-rinne);
    /* `minmax(0, 1fr)`, nicht `1fr`: Ein Grid-Item ist sonst mindestens so
       breit wie sein laengstes unbrechbares Wort und sprengt den Container
       (ng#833, gefunden an einer Kennung ohne Trennzeichen). */
    grid-template-columns: minmax(0, 1fr);
}
/* `break-word`, nicht `anywhere`: Ein Wort bricht erst, wenn es sonst
   ueberliefe - `anywhere` nahm es aus der Mindestbreite und zerlegte
   deshalb auch kurze Woerter wie "Mandant" (ng#859). Kennungen tragen
   `anywhere` selbst. */
.nsai-kachel { padding: var(--bg-pad-card); border-radius: var(--bg-radius-kachel); overflow-wrap: break-word; }
.nsai-kachel--breit, .nsai-kachel--hoch, .nsai-kachel--voll { grid-column: 1 / -1; }

/* Das Menue am Telefon. Ein GESCHLOSSENES `<details>` rendert seine Kinder
   ausser `<summary>` nicht, und `display: contents` aendert daran nichts
   (gemessen, Chrome 149) - die Zeile auf dem Schreibtisch braucht deshalb
   `open`. Das setzt `thema.js` samt `data-menue="breit"`.

   DESHALB HAENGT DAS VERSTECKEN DES KNOPFES AM ATTRIBUT, NICHT AN DER
   BREITE: Bleibt das Skript aus (Fehler, blockiert, CSP), steht der Knopf
   da und oeffnet das Menue. Dasselbe Muster wie die Linse unter
   `[data-bg-lens="ready"]`. */
.nsai-menue { width: 100%; }
.nsai-menue > summary {
    display: inline-flex; align-items: center; gap: var(--bg-raum-2);
    min-height: 44px;
    padding: var(--bg-raum-2) var(--bg-raum-3);
    border: var(--bg-hairline) solid var(--bg-edge);
    border-radius: var(--bg-radius-pill);
    color: var(--bg-ink-2);
    font-size: var(--bg-text-sm);
    cursor: pointer;
    list-style: none;
}
.nsai-menue > summary::-webkit-details-marker { display: none; }
.nsai-menue > summary:hover { color: var(--bg-ink-1); }
.nsai-menue[open] > summary { color: var(--bg-ink-1); border-color: var(--bg-edge-strong); }
.nsai-menue[data-menue="breit"] { display: contents; }
.nsai-menue[data-menue="breit"] > summary { display: none; }

.nsai-baum { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--bg-raum-5); }
.nsai-baum > * { min-width: 0; }
.nsai-baum-leiste > summary {
    display: inline-flex; align-items: center;
    min-height: 44px;
    padding: var(--bg-raum-2) var(--bg-raum-3);
    border: var(--bg-hairline) solid var(--bg-edge);
    border-radius: var(--bg-radius-pill);
    color: var(--bg-ink-2);
    font-size: var(--bg-text-sm);
    cursor: pointer;
    margin-bottom: var(--bg-raum-3);
}
.nsai-baum-leiste[data-menue="breit"] > summary { display: none; }
.nsai-baum-ebene { list-style: none; margin: 0; padding-left: var(--bg-raum-4); }
.nsai-baum-leiste nav > .nsai-baum-ebene { padding-left: 0; }
.nsai-baum-ebene li { overflow-wrap: break-word; min-width: 0; padding: var(--bg-raum-1) 0; }

/* Basis ist das Telefon: Kopf und Fuss stapeln, der Inhalt bekommt die
   kleine Rinne. Die Zeilenform kommt per `min-width` dazu. */
.nsai-kopf-innen { height: auto; padding: var(--bg-raum-3); flex-wrap: wrap; gap: var(--bg-raum-2) var(--bg-raum-3); }
.nsai-nav { margin-left: 0; width: 100%; flex-wrap: wrap; gap: var(--bg-raum-1); margin-top: var(--bg-raum-3); }
.nsai-inhalt { padding: var(--bg-raum-5) var(--bg-raum-3) var(--bg-raum-6); }
.nsai-fuss-innen { padding: var(--bg-raum-4) var(--bg-raum-3); }
.nsai-fuss-rechts { margin-left: 0; }

/* ------------------------------------------------------------------ *
 * 4c. Tabellen: erst Liste, dann Tabelle (ng#833 Block B)
 * ------------------------------------------------------------------
 * Am Telefon ist jede Zeile eine Karte, die Spaltenbeschriftung steht
 * aus `data-spalte` davor. Ab 768px steht die Tabelle. `overflow-x-auto`
 * bleibt als Rueckfall fuer breite Inhalte, ist aber nicht mehr die
 * einzige Antwort.
 * ------------------------------------------------------------------ */
.nsai-tabelle { width: 100%; text-align: left; font-size: var(--bg-text-sm); }
.nsai-tabelle thead {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.nsai-tabelle, .nsai-tabelle tbody, .nsai-tabelle tr, .nsai-tabelle td { display: block; }
.nsai-tabelle tr {
    padding: var(--bg-raum-3) 0;
    border-bottom: var(--bg-hairline) solid var(--bg-edge);
}
.nsai-tabelle tr:last-child { border-bottom: 0; }
.nsai-tabelle td { padding: var(--bg-raum-1) 0; overflow-wrap: break-word; }
/* Eine Kennung hat keine Wortgrenzen; sie darf ueberall brechen (ng#859). */
.nsai-tabelle td[data-nsai-kennung], .nsai-kennung { overflow-wrap: anywhere; }
.nsai-tabelle td::before {
    content: attr(data-spalte);
    display: block;
    font-size: var(--bg-text-xs);
    text-transform: uppercase;
    letter-spacing: var(--bg-tracking-eyebrow);
    color: var(--bg-ink-3);
}
/* Eine Zelle ohne Beschriftung soll keinen leeren Streifen setzen. */
.nsai-tabelle td:not([data-spalte])::before { content: none; }
/* Zwoelf Felder und drei Formulare machen eine Zeile am Telefon rund 1000px
   hoch (gemessen 19.09. auf /admin/access bei 360px). Die selten gebrauchten
   liegen deshalb hinter "Mehr" - sichtbar bleibt, was man im Vorbeigehen
   braucht. Ab 768px steht die Tabelle, dort stoert die Hoehe nicht (ng#845). */
/* Nur wo `:has()` trägt: sonst bliebe das Verstecken unbedingt stehen, und
   der Schalter zeigte nichts - eine Liste ohne halbe Auskunft ist besser als
   eine lange (ng#845). */
@supports selector(tr:has(.nsai-mehr[open])) {
    .nsai-tabelle td[data-nsai-selten] { display: none; }
    .nsai-tabelle tr:has(.nsai-mehr[open]) td[data-nsai-selten] { display: block; }
}
/* Neben der Nummer, nicht darunter: eine eigene Zeile kostet 44px, die an
   jeder Karte anfallen (ng#845). */
.nsai-mehr { display: inline-block; }
.nsai-mehr > summary {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--bg-ink-2);
    cursor: pointer;
}
.nsai-mehr > summary::-webkit-details-marker { display: none; }

.nsai-zeile-aktionen { display: flex; flex-wrap: wrap; gap: var(--bg-raum-2); }
.nsai-zeile-aktionen > * { flex: 1 1 100%; }
.nsai-wahl { display: flex; align-items: center; gap: var(--bg-raum-2); min-height: 44px; }
.nsai-wahl input[type="checkbox"] { width: 20px; height: 20px; }

/* ------------------------------------------------------------------ *
 * 4e. Die Seiten des auth-bundle (ng#833 Block G)
 *
 * Ihr Markup gehoert dem Bundle und bleibt unberuehrt; hier steht nur,
 * wie das Blatt es liest. Gemessen an v0.6.1 bei 360px.
 * ------------------------------------------------------------------ */

/* Eine Tabelle in einem Kasten mit `overflow-hidden` wird ABGESCHNITTEN,
   nicht gescrollt: auf /admin/users 752px Tabelle in 287px Kasten, die
   Spalte "Aktionen" war am Telefon unerreichbar. */
.overflow-hidden:has(> table) { overflow-x: auto; }

/* Eine Filterzeile ist eine Flex-Reihe ohne Umbruch: auf /admin/users schob
   sie die Seite auf 503px auf, weil Feld, Knopf und Link nebeneinander
   bleiben wollten. */
form.flex, form .flex { flex-wrap: wrap; }

/* Die Reiterleiste im Profil schob die Seite auf 378px auf. */
#profileTabs { overflow-x: auto; scrollbar-width: none; }
#profileTabs::-webkit-scrollbar { display: none; }
.tab-btn { flex: 0 0 auto; min-height: 44px; }

/* Fingerziele im fremden Markup: Absendeknopf 36px, Eingabefeld 42px,
   Kaestchen 16px, der Knopf "Anzeigen" im Passwortfeld 18px. */
button[type="submit"],
select,
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"] { min-height: 44px; }
input[type="checkbox"] { width: 20px; height: 20px; }
button[data-toggle-password] { min-height: 44px; min-width: 44px; }

/* Der Erklaerungsabsatz der Fehlerseiten stand mit einem Wort ohne
   Trennzeichen auf 367px bei 360px (Nebenbefund zu Block E). Nur Absaetze:
   am Behaelter zerlegt dieselbe Regel auch die Beschriftung von Knoepfen -
   gemessen 41px breit und 304px hoch auf /admin/users. */
.nsai-inhalt p { overflow-wrap: break-word; }

/* ------------------------------------------------------------------ *
 * 4d. Unternavigation als Chipband (ng#833 Block C)
 * ------------------------------------------------------------------ */
.nsai-chips {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    /* Das Band scrollt, die Seite nicht - deshalb steht `overflow-x` hier
       und nirgends am Inhalt. */
    scrollbar-width: none;
    width: fit-content;
    max-width: 100%;
    padding: 6px;
    margin-bottom: var(--bg-raum-6);
    border: var(--bg-hairline) solid var(--bg-edge);
    border-radius: var(--bg-radius-pill);
    background: var(--bg-card-fill);
    box-shadow: var(--bg-card-shadow);
    backdrop-filter: blur(var(--bg-blur)) saturate(var(--bg-saturate));
    -webkit-backdrop-filter: blur(var(--bg-blur)) saturate(var(--bg-saturate));
}
.nsai-chips::-webkit-scrollbar { display: none; }
.nsai-chips > *,
.nsai-filter a {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: var(--bg-raum-2) var(--bg-raum-4);
    border: var(--bg-hairline) solid var(--bg-edge);
    border-radius: var(--bg-radius-pill);
    font-size: var(--bg-text-sm);
    color: var(--bg-ink-2);
    white-space: nowrap;
}
.nsai-chips > * { border-color: transparent; }
.nsai-chips a:hover { color: var(--bg-ink-1); background: color-mix(in srgb, var(--bg-ink-1) 8%, transparent); text-decoration: none; }
.nsai-filter a:hover { color: var(--bg-ink-1); border-color: var(--bg-edge-strong); }
.nsai-chips [aria-current="page"],
.nsai-filter [aria-current="page"] {
    background: color-mix(in srgb, var(--bg-ink-1) 12%, transparent);
    border-color: var(--bg-edge);
    color: var(--bg-ink-1);
    font-weight: 600;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .nsai-chips { background: var(--bg-fill-opaque); }
}

/* Ein Steuerelement in einer Liste ist am Telefon ein Fingerziel. Gemessen
   am 19.09. auf /admin/access: Auswahl 18px, Eingabefeld 20px, Kaestchen
   13px, Knopf 41px. Ab 768px steht dieselbe Liste als Tabelle da und wird
   mit dem Zeiger bedient - dort nimmt sie ihre kompakte Hoehe zurueck
   (ng#833). */
.nsai-tabelle select,
.nsai-tabelle input:not([type="checkbox"]):not([type="hidden"]),
.nsai-tabelle .btn,
.nsai-tabelle label { min-height: 44px; }
.nsai-tabelle label { display: flex; align-items: center; gap: var(--bg-raum-2); }
.nsai-tabelle input[type="checkbox"] { width: 20px; height: 20px; }

/* ------------------------------------------------------------------ *
 * 4f. Die Zugangskarte (ng#859)
 * ------------------------------------------------------------------
 * Eine Zeile auf /admin/access ist kein Datenpunkt, sondern ein
 * Formular (ng#856). Zwoelf Spalten teilten dafuer 1086px in Zellen von
 * 28 bis 94px - gemessen am 20.09. bei 1180, 1280 und 1600px, ohne
 * Unterschied. Die Karte ist auf allen Breiten dieselbe.
 * ------------------------------------------------------------------ */
.nsai-karten { display: grid; gap: var(--bg-rinne); grid-template-columns: minmax(0, 1fr); }

.nsai-karte-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--bg-raum-2) var(--bg-raum-3); }
/* Ein Flex-Kind ist ohne `min-width: 0` mindestens so breit wie sein
   laengstes Wort - `break-word` zaehlt dabei NICHT mit. Ohne diese
   Zeile schob eine Bezeichnung aus 51 Zeichen die Seite bei 360px auf
   513px auf (gemessen 20.09., ng#859). */
.nsai-karte-kopf > * { min-width: 0; }
.nsai-karte-titel { font-family: var(--bg-font-display); font-size: var(--bg-text-h3); line-height: 1.25; color: var(--bg-ink-1); }
.nsai-karte-kopf .nsai-abzeichen { margin-left: auto; }
/* Feste Reihenfolge, Mandant zuerst: Was Karten schlechter koennen als
   Spalten, ist vergleichen - senkrecht an derselben Stelle zu stehen ist
   das Gegenmittel. */
.nsai-karte-meta { margin-top: var(--bg-raum-2); font-size: var(--bg-text-sm); color: var(--bg-ink-3); }
.nsai-karte-block { margin-top: var(--bg-raum-3); padding-top: var(--bg-raum-3); border-top: var(--bg-hairline) solid var(--bg-edge); }
.nsai-karte-block--reihe { display: flex; flex-wrap: wrap; align-items: center; gap: var(--bg-raum-2) var(--bg-raum-3); }
.nsai-karte-block--reihe > .nsai-eyebrow { margin-bottom: 0; }
.nsai-karte-gitter { display: grid; gap: var(--bg-raum-4); grid-template-columns: minmax(0, 1fr); }
/* Rolle und Aufrufgrenze aendert man selten. Offen war die Karte bei
   1280px 496px hoch; hinter dem Schalter bleibt sie unter 320px, ohne dass
   die Rechte darueber verschwinden (ng#859). Das Dreieck bleibt sichtbar:
   es sagt, ob zu oder offen. */
.nsai-karte-mehr { margin-top: 0; }
/* `display: list-item` behalten: mit `flex` nimmt Chrome dem Schalter
   sein Dreieck, und er sieht aus wie Text (gesehen 20.09., ng#859). */
.nsai-karte-mehr > summary { display: list-item; padding: var(--bg-raum-3) 0; color: var(--bg-ink-2); font-size: var(--bg-text-sm); cursor: pointer; }
.nsai-karte-mehr[open] > summary { color: var(--bg-ink-1); }
.nsai-karte-mehr .nsai-karte-gitter { margin-top: var(--bg-raum-3); }
.nsai-karte-fuss { display: flex; flex-wrap: wrap; gap: var(--bg-raum-2); margin-top: var(--bg-raum-3); padding-top: var(--bg-raum-3); border-top: var(--bg-hairline) solid var(--bg-edge); }
.nsai-karte-fuss .btn-primary { margin-left: auto; }

/* Ein Gespraech ist eine Folge, kein Gitter: eine Spalte, die Ebene als
   Leiste links. Verschachtelte Kaesten waeren auf 360px unlesbar (ng#874,
   Konzept aus ng#833). */
.nsai-faden { display: grid; gap: var(--bg-rinne); grid-template-columns: minmax(0, 1fr); }
.nsai-faden-zeile { min-width: 0; }
.nsai-faden-zeile[data-nsai-stufe="1"] { margin-left: calc(1 * var(--bg-faden-stufe)); }
.nsai-faden-zeile[data-nsai-stufe="2"] { margin-left: calc(2 * var(--bg-faden-stufe)); }
.nsai-faden-zeile[data-nsai-stufe="3"] { margin-left: calc(3 * var(--bg-faden-stufe)); }
.nsai-faden-zeile[data-nsai-stufe="4"] { margin-left: calc(4 * var(--bg-faden-stufe)); }
/* Die Leiste steht auf jeder Ebene ausser der Wurzel - sie ist auf dem
   Telefon das EINZIGE Zeichen der Ebene. */
.nsai-faden-zeile:not([data-nsai-stufe="0"]) > .nsai-kachel {
    border-left: var(--bg-faden-leiste) solid var(--bg-edge);
    padding-left: var(--bg-raum-4);
}
/* Die angeklickte Nachricht: der Rand, nicht die Schriftfarbe - ein
   Gespraech soll gleich gut lesbar bleiben. */
.nsai-faden-zeile--hier > .nsai-kachel { border-color: var(--bg-tint); }

.nsai-eyebrow { display: block; margin-bottom: var(--bg-raum-2); font-size: var(--bg-text-xs); text-transform: uppercase; letter-spacing: var(--bg-tracking-eyebrow); color: var(--bg-ink-3); }
.nsai-abzeichen { display: inline-flex; align-items: center; gap: var(--bg-raum-1); min-height: 24px; padding: 0 10px; border: var(--bg-hairline) solid var(--bg-line); border-radius: var(--bg-radius-pill); font-size: 12px; color: var(--bg-ink-2); }
.nsai-abzeichen[class*="bg-"] { background: transparent; }

/* Rechte als abwaehlbare Chips: Ein Zugang ist ein Schluessel, und was
   er aufschliesst, liest sich als Reihe kurzer Chips. Der Name haelt sie
   von der Wortmarke `.nsai-marke` im Seitenkopf getrennt. */
.nsai-wahlchips { display: flex; flex-wrap: wrap; gap: var(--bg-raum-2); }
.nsai-wahlchip { display: inline-flex; align-items: center; gap: var(--bg-raum-2); min-height: 44px; padding: var(--bg-raum-2) var(--bg-raum-4); border: var(--bg-hairline) solid var(--bg-edge); border-radius: var(--bg-radius-pill); font-family: var(--bg-font-mono); font-size: var(--bg-text-xs); color: var(--bg-ink-2); cursor: pointer; }
/* Das Kaestchen verschwindet erst da, wo der gewaehlte Zustand am
   Chip selbst ablesbar ist - ohne `:has()` stuende eine Reihe gleich
   aussehender Chips da, und niemand saehe, was gilt. */
@supports selector(label:has(input:checked)) {
    .nsai-wahlchip input[type="checkbox"] { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); }
    .nsai-wahlchip:has(input:checked) { background: var(--bg-accent); border-color: var(--bg-accent); color: var(--bg-accent-ink); }
    /* Sonst traegt das verborgene Kaestchen den Fokusring mit sich fort. */
    .nsai-wahlchip:has(input:focus-visible) { outline: 2px solid var(--bg-accent); outline-offset: 2px; }
}

/* Ein Filterband ist kein Menue: es scrollt nicht, es bricht um - man
   uebersieht sonst den halben Bestand (ng#859). */
.nsai-filter { display: flex; flex-wrap: wrap; align-items: center; gap: var(--bg-raum-2) var(--bg-raum-3); margin-bottom: var(--bg-raum-3); }
.nsai-filter > .nsai-eyebrow { margin-bottom: 0; }
.nsai-kennzahl { font-family: var(--bg-font-mono); font-size: 48px; font-weight: 500; line-height: 1.1; color: var(--bg-ink-1); }
/* Eine Kachel, die selbst ein Verweis ist (ng#860): ohne diese Zeile
   traegt sie den Unterstrich des Links und bleibt inline. */
a.nsai-kachel { display: block; text-decoration: none; }
a.nsai-kachel:hover { border-color: var(--bg-edge-strong); }
.nsai-kachel > .nsai-eyebrow { font-size: var(--bg-text-body); text-transform: none; letter-spacing: 0; color: var(--bg-ink-2); }
[data-nsai-ordnerleiste] {
    width: fit-content;
    max-width: 100%;
    padding: 6px;
    border: var(--bg-hairline) solid var(--bg-edge);
    border-radius: var(--bg-radius-lg);
    background: var(--bg-card-fill);
    box-shadow: var(--bg-card-shadow);
    backdrop-filter: blur(var(--bg-blur)) saturate(var(--bg-saturate));
    -webkit-backdrop-filter: blur(var(--bg-blur)) saturate(var(--bg-saturate));
}
[data-nsai-ordnerleiste] > .btn { background: transparent; border-color: transparent; }
[data-nsai-ordnerleiste] > .btn:hover { background: color-mix(in srgb, var(--bg-ink-1) 8%, transparent); }
[data-nsai-ordnerleiste] > [aria-current="page"] { min-height: 44px; padding: 0 var(--bg-raum-4); border-radius: var(--bg-radius-md); background: var(--bg-fill-hi); color: var(--bg-ink-1); font-size: var(--bg-text-body); font-weight: 600; }
[data-nsai-ordnerzahl] { font-family: var(--bg-font-mono); font-size: var(--bg-text-sm); color: var(--bg-ink-3); }
@media (prefers-reduced-transparency: reduce) {
    .bg-white, .card, .nsai-kopf-innen, .nsai-chips, [data-nsai-ordnerleiste] { background: var(--bg-fill-opaque); backdrop-filter: none; -webkit-backdrop-filter: none; }
    .bg-white::before, .bg-white::after, .card::before, .card::after, .nsai-kopf-innen::before, .nsai-kopf-innen::after { display: none; }
}
/* Das Anlegen liegt hinter seinem Knopf; das Dreieck daneben waere ein
   zweites Bedienzeichen am selben Element. */
.nsai-neu { margin-bottom: var(--bg-raum-6); }
.nsai-neu > summary { display: inline-flex; align-items: center; list-style: none; cursor: pointer; }
.nsai-neu > summary::-webkit-details-marker { display: none; }

/* Was nur die Vorlesestimme braucht: die Beschriftung eines Wertes, der
   fuer das Auge schon in seiner Zeile steht. */
.nsai-verborgen { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

@media (min-width: 768px) {
    .nsai-tabelle { display: table; border-collapse: collapse; }
    .nsai-tabelle thead {
        position: static; width: auto; height: auto; margin: 0;
        overflow: visible; clip-path: none; white-space: normal;
        display: table-header-group;
    }
    .nsai-tabelle tbody { display: table-row-group; }
    .nsai-tabelle tr { display: table-row; padding: 0; }
    .nsai-tabelle td { display: table-cell; padding: var(--bg-raum-2) var(--bg-raum-4) var(--bg-raum-2) 0; }
    /* Ab hier ist die Zeile eine Tabellenzeile: alles steht nebeneinander,
       und der Schalter hat nichts mehr zu verbergen (ng#845). */
    .nsai-tabelle td[data-nsai-selten] { display: table-cell; }
    .nsai-mehr { display: none; }
    .nsai-tabelle select,
    .nsai-tabelle input:not([type="checkbox"]):not([type="hidden"]),
    .nsai-tabelle .btn,
    .nsai-tabelle label { min-height: 0; }
    .nsai-tabelle label { display: inline-flex; gap: var(--bg-raum-1); }
    .nsai-tabelle th {
        padding: var(--bg-raum-2) var(--bg-raum-4) var(--bg-raum-2) 0;
        font-size: var(--bg-text-xs);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: var(--bg-tracking-eyebrow);
        color: var(--bg-ink-3);
        border-bottom: var(--bg-hairline) solid var(--bg-edge);
    }
    .nsai-tabelle td::before { content: none; }
    .nsai-zeile-aktionen > * { flex: 0 0 auto; }
}

@media (min-width: 640px) {
    :root { --bg-rinne: var(--bg-raum-4); --bg-faden-stufe: var(--bg-raum-5); }
    .nsai-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .nsai-karte-gitter { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .nsai-kachel--breit { grid-column: span 2; }
    .nsai-kachel--hoch { grid-column: auto; grid-row: span 2; }
    .nsai-inhalt { padding: var(--bg-raum-6) var(--bg-raum-5); }
    .nsai-fuss-innen { padding: var(--bg-raum-4) var(--bg-raum-5); }
    .nsai-fuss-rechts { margin-left: auto; }
    .nsai-kopf { padding: var(--bg-raum-4) var(--bg-raum-5) 0; }
}

@media (min-width: 1024px) {
    :root { --bg-rinne: var(--bg-raum-5); }
    .nsai-bento { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-flow: dense; }
    .nsai-karten { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .nsai-kachel--breit { grid-column: span 2; }
    .nsai-kopf-innen { padding: var(--bg-raum-2) var(--bg-raum-3) var(--bg-raum-2) var(--bg-raum-5); flex-wrap: nowrap; gap: var(--bg-raum-2); }
    .nsai-nav { margin-left: var(--bg-raum-4); flex: 1 1 auto; width: auto; flex-wrap: nowrap; margin-top: 0; }
    .nsai-thema { margin-left: auto; }
    .nsai-menue[data-menue="breit"]::details-content { flex: 1 1 auto; min-width: 0; }
    .nsai-baum { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
}

@media (min-width: 1440px) {
    .nsai-karten { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ------------------------------------------------------------------ *
 * 5. Bausteine - die Klassennamen der Vorlagen, neue Bedeutung
 * ------------------------------------------------------------------
 * DIE `dark:`-KLASSEN SIND HIER ALIASSE, KEINE UEBERSCHREIBUNGEN. Das
 * folgt aus dem Token-System: `--bg-ink-1` kippt mit dem Thema, also
 * meinen `text-gray-900` und `dark:text-white` DASSELBE. Damit faellt
 * die ganze Klasse Fehler weg, die mir heute frueh den blauen
 * Markennamen beschert hat - eine Dunkelregel, die nach Reihenfolge
 * gewinnt statt nach Absicht, gibt es nicht mehr.
 * ------------------------------------------------------------------ */

/* Aufbau -------------------------------------------------------------- */
.block { display: block; }
.inline { display: inline; }
.inline-block { display: inline-block; }
.flex { display: flex; }
.inline-flex { display: inline-flex; }
.grid { display: grid; }
.hidden { display: none; }
.relative { position: relative; }
.absolute { position: absolute; }
.overflow-hidden { overflow: hidden; }

.flex-col { flex-direction: column; }
.flex-1 { flex: 1 1 0%; }
.min-w-0 { min-width: 0; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.items-end { align-items: flex-end; }
.justify-between { justify-content: space-between; }
.justify-center { justify-content: center; }

.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-cols-\[max-content_1fr\] { grid-template-columns: max-content minmax(0, 1fr); }
@media (min-width: 768px) { .md\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.gap-1 { gap: 4px; }
.gap-2 { gap: 8px; }
.gap-x-6 { column-gap: 24px; }
.gap-y-1 { row-gap: 4px; }
.gap-3 { gap: 12px; }
.gap-4 { gap: 16px; }

.space-x-1 > * + * { margin-left: 4px; }
.space-x-3 > * + * { margin-left: 12px; }
.space-y-1 > * + * { margin-top: 4px; }
.space-y-4 > * + * { margin-top: 16px; }
.space-y-5 > * + * { margin-top: 20px; }

.divide-y > * + * { border-top-width: var(--bg-hairline); border-top-style: solid; }
.divide-gray-200 > * + *, .dark\:divide-gray-700 > * + * { border-top-color: var(--bg-edge); }

.top-1\/2 { top: 50%; }
.right-3 { right: 12px; }
.-translate-y-1\/2 { transform: translateY(-50%); }

/* Groessen ------------------------------------------------------------ */
.w-0 { width: 0; }
.w-3 { width: 12px; }
.w-4 { width: 16px; }
.w-8 { width: 32px; }
.w-16 { width: 64px; }
.w-48 { width: 192px; }
.w-full { width: 100%; }
.h-1 { height: 4px; }
.h-1\.5 { height: 6px; }
.h-3 { height: 12px; }
.h-4 { height: 16px; }
.h-8 { height: 32px; }
.h-16 { height: 64px; }
.h-48 { height: 192px; }
.h-full { height: 100%; }
.min-h-\[75vh\] { min-height: 75vh; }
.min-h-\[44px\] { min-height: 44px; }

.max-w-md { max-width: 448px; }
.max-w-lg { max-width: 512px; }
.max-w-2xl { max-width: 672px; }
.max-w-3xl { max-width: 768px; }
.max-w-4xl { max-width: 896px; }
.max-w-6xl { max-width: 1152px; }
.max-w-7xl { max-width: var(--bg-container); }
.mx-auto { margin-left: auto; margin-right: auto; }

/* Abstaende - 4px-Raster, Kartenpolster 22px ------------------------- */
.p-2 { padding: 8px; }
.p-4 { padding: 16px; }
.p-6 { padding: var(--bg-pad-card); }
.p-8 { padding: var(--bg-pad-card); }
.px-1 { padding-left: 4px; padding-right: 4px; }
.px-2 { padding-left: 8px; padding-right: 8px; }
.px-3 { padding-left: 12px; padding-right: 12px; }
.px-4 { padding-left: 16px; padding-right: 16px; }
.px-5 { padding-left: 20px; padding-right: 20px; }
.px-6 { padding-left: 24px; padding-right: 24px; }
.py-0\.5 { padding-top: 2px; padding-bottom: 2px; }
.py-1 { padding-top: 4px; padding-bottom: 4px; }
.py-2 { padding-top: 8px; padding-bottom: 8px; }
.py-3 { padding-top: 12px; padding-bottom: 12px; }
.py-4 { padding-top: 16px; padding-bottom: 16px; }
.py-8 { padding-top: 32px; padding-bottom: 32px; }
.py-10 { padding-top: 40px; padding-bottom: 40px; }
.pt-4 { padding-top: 16px; }
.pb-3 { padding-bottom: 12px; }
.pl-4 { padding-left: 16px; }
.pr-4 { padding-right: 16px; }
.pr-10 { padding-right: 40px; }
.pr-20 { padding-right: 80px; }

.mb-1 { margin-bottom: 4px; }
.mb-2 { margin-bottom: 8px; }
.mb-3 { margin-bottom: 12px; }
.mb-4 { margin-bottom: 16px; }
.mb-5 { margin-bottom: 20px; }
.mb-6 { margin-bottom: 24px; }
.mb-8 { margin-bottom: 32px; }
.mt-0\.5 { margin-top: 2px; }
.mt-1 { margin-top: 4px; }
.mr-2 { margin-right: 8px; }
.my-6 { margin-top: 24px; margin-bottom: 24px; }
.mt-2 { margin-top: 8px; }
.mt-4 { margin-top: 16px; }
.mt-6 { margin-top: 24px; }
.mt-8 { margin-top: 32px; }

/* Schrift ------------------------------------------------------------- */
.text-xs { font-size: var(--bg-text-xs); line-height: 1.45; }
.text-sm { font-size: var(--bg-text-sm); line-height: 1.55; }
.text-lg { font-size: var(--bg-text-h3); line-height: var(--bg-leading-snug); }
.text-xl { font-size: 22px; line-height: var(--bg-leading-snug);
           font-family: var(--bg-font-display); letter-spacing: var(--bg-tracking-tight); }
.text-2xl { font-size: var(--bg-text-h2); line-height: var(--bg-leading-snug);
            font-family: var(--bg-font-display); letter-spacing: var(--bg-tracking-tight); }
.text-3xl { font-size: var(--bg-text-h1); line-height: var(--bg-leading-tight);
            font-family: var(--bg-font-display); letter-spacing: var(--bg-tracking-display); }

.font-normal { font-weight: 400; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
/* Kennungen, Hashes und Pfade stehen in dieser Schrift - sie tragen oft kein
   Trennzeichen, an dem der Browser von sich aus umbraeche (ng#833). */
.font-mono { font-family: var(--bg-font-mono); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

.text-left { text-align: left; }
.text-center { text-align: center; }
.uppercase { text-transform: uppercase; }
.tracking-wide { letter-spacing: .025em; }
.tracking-widest { letter-spacing: var(--bg-tracking-eyebrow); }
.underline { text-decoration: underline; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.font-sans { font-family: var(--bg-font-body); }
.whitespace-nowrap { white-space: nowrap; }
/* Kopfzeile, Abzeichen und Knopf tragen ein Wort, das ganz bleibt:
   zerlegt liest es sich als "Man dan t" oder "off en" (ng#859). */
th, .nsai-abzeichen, .btn { white-space: nowrap; }
/* Der Volltext einer Nachricht behaelt seine Absaetze (ng#853). */
.whitespace-pre-line { white-space: pre-line; }
.whitespace-pre-wrap { white-space: pre-wrap; }
.break-all { word-break: break-all; }
.select-all { user-select: all; }
.cursor-pointer { cursor: pointer; }
.opacity-75 { opacity: .75; }

/* Tinte - jede Stufe kippt mit dem Thema, deshalb sind hell und dunkel
   hier DASSELBE. --------------------------------------------------- */
.text-gray-900, .dark\:text-white,
.dark\:text-gray-100, .dark\:text-gray-200 { color: var(--bg-ink-1); }
.text-gray-800 { color: var(--bg-ink-1); }
.text-gray-700, .dark\:text-gray-300 { color: var(--bg-ink-2); }
.text-gray-600 { color: var(--bg-ink-2); }
.text-gray-500, .dark\:text-gray-400 { color: var(--bg-ink-3); }
.text-gray-400 { color: var(--bg-ink-4); }

/* Auf dem Akzent steht die Akzenttinte, nicht Weiss. */
.text-white { color: var(--bg-accent-ink); }

/* Semantik ohne rohes Rot und Gruen: Gefahr Magenta, Erfolg Limette,
   Info Cyan, Warnung Bernstein. Dieselben Klassennamen, andere Rolle. */
.text-red-600, .text-red-700, .text-red-800, .dark\:text-red-400 { color: var(--bg-accent-magenta); }
.text-green-700, .text-green-800, .dark\:text-green-400 { color: var(--bg-accent-lime); }
.text-yellow-600, .text-yellow-700, .text-yellow-800,
.text-amber-800, .dark\:text-yellow-400 { color: var(--bg-accent-amber); }
.text-orange-800 { color: var(--bg-accent-amber); }
.text-blue-600, .text-blue-700, .dark\:text-blue-400 { color: var(--bg-link); }
.text-indigo-500, .text-indigo-600, .text-indigo-700,
.dark\:text-indigo-300, .dark\:text-indigo-400 { color: var(--bg-accent); }

/* Flaechen ------------------------------------------------------------ */
.bg-gray-200, .dark\:bg-gray-600 { background-color: var(--bg-fill-inset); }
.bg-gray-400 { background-color: var(--bg-ink-4); }
.dark\:bg-gray-800 { background-color: var(--bg-fill); }

.bg-blue-600, .bg-indigo-600 { background-color: var(--bg-accent); color: var(--bg-accent-ink); }
.bg-green-500, .bg-green-600 { background-color: var(--bg-accent-lime); color: var(--bg-accent-ink); }
.bg-red-600 { background-color: var(--bg-accent-magenta); color: #fff; }
.bg-green-400 { background-color: var(--bg-accent-lime); }

/* Meldeflaechen: getoente Muldenwaesche, nicht Pastellblock. Gefahr und
   Leitakzent tragen jetzt verschiedene Farben - das war vorher dieselbe. */
.bg-red-50, .bg-red-100, .dark\:bg-red-900 {
    background-color: color-mix(in srgb, var(--bg-accent-magenta) 16%, transparent);
}
.bg-indigo-50, .bg-indigo-100, .dark\:bg-indigo-900, .dark\:bg-indigo-900\/20 {
    background-color: color-mix(in srgb, var(--bg-accent) 16%, transparent);
}
.bg-green-100 { background-color: color-mix(in srgb, var(--bg-accent-lime) 16%, transparent); }
.bg-yellow-50, .bg-yellow-100, .dark\:bg-yellow-900,
.bg-amber-50, .bg-amber-100, .bg-orange-100 { background-color: color-mix(in srgb, var(--bg-accent-amber) 16%, transparent); }
.bg-blue-100, .dark\:bg-blue-900 { background-color: color-mix(in srgb, var(--bg-accent-cyan) 16%, transparent); }

/* Kanten -------------------------------------------------------------- */
.border { border: var(--bg-hairline) solid var(--bg-edge); }
.border-t { border-top: var(--bg-hairline) solid var(--bg-edge); }
.border-b { border-bottom: var(--bg-hairline) solid var(--bg-edge); }
.border-b-2 { border-bottom: 2px solid var(--bg-edge); }
.border-l-2 { border-left: 2px solid var(--bg-edge); }

/* Zustaende: ein abgeschalteter Knopf soll auch so aussehen (ng#753). */
.disabled\:opacity-50:disabled { opacity: .5; }
.disabled\:cursor-not-allowed:disabled { cursor: not-allowed; }
.target\:border-blue-500:target { border-color: var(--bg-link); }
.border-transparent { border-color: transparent; }
.border-gray-200, .border-gray-300,
.dark\:border-gray-600, .dark\:border-gray-700 { border-color: var(--bg-edge); }
.border-red-200, .border-red-400, .border-red-600,
.dark\:border-red-900 { border-color: var(--bg-accent-magenta); }
.border-indigo-300, .border-indigo-600, .dark\:border-indigo-700 { border-color: var(--bg-accent); }
.border-green-400 { border-color: var(--bg-accent-lime); }
.border-yellow-300, .border-yellow-400 { border-color: var(--bg-accent-amber); }
.border-blue-400, .border-blue-600 { border-color: var(--bg-accent-cyan); }

.rounded { border-radius: var(--bg-radius-sm); }
.rounded-lg { border-radius: var(--bg-radius-sm); }
.rounded-xl { border-radius: var(--bg-radius-lg); }
.rounded-full { border-radius: var(--bg-radius-pill); }
.rounded-t-lg { border-top-left-radius: var(--bg-radius-md); border-top-right-radius: var(--bg-radius-md); }

/* Zwei Schattenstufen, mehr gibt es nicht. Die inneren Linien sind
   baulich, nicht schmueckend: Sie geben der Scheibe Dicke. */
.shadow-sm { box-shadow: var(--bg-drop), var(--bg-inner); }
.shadow-lg { box-shadow: var(--bg-drop-lifted), var(--bg-inner); }

/* Bewegung - koerperlich und kurz ------------------------------------- */
.transition { transition: color var(--bg-dur) var(--bg-ease-out),
                          background-color var(--bg-dur) var(--bg-ease-out),
                          border-color var(--bg-dur) var(--bg-ease-out),
                          box-shadow var(--bg-dur) var(--bg-ease-out),
                          transform var(--bg-dur) var(--bg-ease-out),
                          opacity var(--bg-dur) var(--bg-ease-out); }
.transition-all { transition: all var(--bg-dur) var(--bg-ease-out); }
.transition-colors { transition: color var(--bg-dur) var(--bg-ease-out),
                                 background-color var(--bg-dur) var(--bg-ease-out),
                                 border-color var(--bg-dur) var(--bg-ease-out); }
.duration-200 { transition-duration: var(--bg-dur); }
.duration-300 { transition-duration: var(--bg-dur); }

@keyframes nsai-ping { 75%, 100% { transform: scale(2); opacity: 0; } }
.animate-ping { animation: nsai-ping 1s var(--bg-ease-out) infinite; }
@media (prefers-reduced-motion: reduce) { .animate-ping { animation: none; } }

.tab-btn { cursor: pointer; }
.tab-pane { display: block; }
.tab-pane.hidden { display: none; }

/* Ueberfahren: Glas hebt, Knoepfe hellen ihre Fuellung auf. Nichts
   aendert seine Groesse ausser durch das Anheben. ------------------- */
a.bg-white, .hover\:bg-gray-50 {
    transition: transform var(--bg-dur) var(--bg-ease-out),
                box-shadow var(--bg-dur) var(--bg-ease-out),
                background-color var(--bg-dur) var(--bg-ease-out);
}
a.bg-white:hover, .hover\:bg-gray-50:hover {
    transform: var(--bg-lift);
    box-shadow: var(--bg-drop-lifted), var(--bg-inner);
}
.hover\:bg-blue-50:hover, .hover\:bg-indigo-50:hover,
.dark\:hover\:bg-indigo-900\/20:hover { background-color: color-mix(in srgb, var(--bg-accent) 12%, transparent); }
.hover\:bg-red-50:hover, .dark\:hover\:bg-red-900\/20:hover { background-color: color-mix(in srgb, var(--bg-accent-magenta) 14%, transparent); }
.dark\:hover\:bg-gray-700:hover { background-color: var(--bg-fill-inset); }
.dark\:hover\:bg-blue-900:hover { background-color: color-mix(in srgb, var(--bg-accent-cyan) 18%, transparent); }

.hover\:bg-blue-700:hover, .hover\:bg-indigo-700:hover {
    background-color: color-mix(in srgb, var(--bg-accent) 82%, #fff);
    box-shadow: var(--bg-drop-lifted), var(--bg-inner);
}
.hover\:bg-red-700:hover {
    background-color: color-mix(in srgb, var(--bg-accent-magenta) 82%, #fff);
    box-shadow: var(--bg-drop-lifted), var(--bg-inner);
}
.hover\:bg-green-700:hover {
    background-color: color-mix(in srgb, var(--bg-accent-lime) 82%, #fff);
    box-shadow: var(--bg-drop-lifted), var(--bg-inner);
}

.hover\:underline:hover { text-decoration: underline; }
.hover\:text-blue-500:hover, .hover\:text-indigo-800:hover,
.hover\:text-red-800:hover, .hover\:text-yellow-900:hover { color: var(--bg-link-hover); }
.hover\:text-gray-600:hover, .hover\:text-gray-700:hover,
.dark\:hover\:text-gray-200:hover { color: var(--bg-ink-1); }

/* Fokus: immer der Rahmen, nie ein Schatten. ------------------------- */
.focus\:outline-none:focus { outline: none; }
.focus\:border-blue-500:focus { border-color: var(--bg-focus); }
.focus\:ring-2:focus { outline: 2px solid var(--bg-focus); outline-offset: 2px; }
.focus\:ring-offset-2:focus { outline-offset: 2px; }
.focus\:ring-blue-500:focus, .focus\:ring-indigo-500:focus { outline-color: var(--bg-focus); }
.focus\:ring-red-500:focus { outline-color: var(--bg-accent-magenta); }

/* ------------------------------------------------------------------ *
 * 6. auth-bundle v0.2.0: die nachgezogenen Klassen
 * ------------------------------------------------------------------
 * Der Sprung von `dev-main` (April) auf v0.2.0 brachte fuenf neue
 * Seiten mit - Einladungsverwaltung, invite_only, 2FA-Abfrage - und der
 * Abdeckungszaehler hat beim ersten Lauf danach 36 Klassen gemeldet,
 * fuer die es hier keine Regel gab. Ohne ihn waeren sie LAUTLOS
 * ausgefallen: Die Seiten haetten gerendert, nur falsch ausgesehen.
 *
 * ELF DAVON SIND BOOTSTRAP-IDIOM (`btn`, `card`, `alert`, `container`,
 * `form-control`, `text-muted` ...) und stehen in denselben Vorlagen wie
 * die Tailwind-Namen. Das ist eine Uneinheitlichkeit IM BUNDLE, nicht
 * hier - gemeldet als Kandidat fuer einen Bundle-PR. Bis dahin gilt
 * dieselbe Regel wie fuer alle anderen Namen: Was sie bedeuten,
 * bestimmen wir. Sie bekommen deshalb die Brilliant-Glas-Entsprechung
 * und nicht Bootstraps Aussehen.
 * ------------------------------------------------------------------ */

/* Bootstrap-Idiom, uebersetzt --------------------------------------- */
.container {
    width: 100%;
    max-width: var(--bg-container);
    margin-left: auto;
    margin-right: auto;
    padding-left: 20px;
    padding-right: 20px;
}

/* `card` ist dieselbe Scheibe wie `bg-white` - eine Rezeptur, zwei Namen. */
.card {
    position: relative;
    isolation: isolate;
    border-radius: var(--bg-radius-lg);
    border: var(--bg-hairline) solid var(--bg-edge);
    background: var(--bg-card-fill);
    color: var(--bg-ink-1);
    box-shadow: var(--bg-card-shadow);
}
.card::before, .card::after {
    content: "";
    position: absolute;
    inset: var(--bg-hairline);
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}
.card::before { background: var(--bg-tint); opacity: var(--bg-card-tint); }
[data-bg-lens="ready"] .card[data-bg-linse="an"]::before {
    backdrop-filter: var(--bg-lens) saturate(var(--bg-saturate));
    -webkit-backdrop-filter: var(--bg-lens) saturate(var(--bg-saturate));
}
.card::after {
    backdrop-filter: blur(var(--bg-surface-blur, var(--bg-blur))) brightness(var(--bg-brightness));
    -webkit-backdrop-filter: blur(var(--bg-surface-blur, var(--bg-blur))) brightness(var(--bg-brightness));
}
.card > * { position: relative; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .card { background: var(--bg-fill-opaque); }
    .card::before, .card::after { display: none; }
}
.card-body { padding: var(--bg-pad-card); }

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 var(--bg-raum-4);
    border-radius: var(--bg-radius-md);
    border: var(--bg-hairline) solid var(--bg-edge);
    background: var(--bg-fill-hi);
    color: var(--bg-ink-1);
    font-size: var(--bg-text-body);
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: color var(--bg-dur) var(--bg-ease-out),
                background-color var(--bg-dur) var(--bg-ease-out),
                border-color var(--bg-dur) var(--bg-ease-out),
                box-shadow var(--bg-dur) var(--bg-ease-out),
                transform var(--bg-dur) var(--bg-ease-out);
}
.btn:hover { text-decoration: none; transform: var(--bg-lift); }

.btn-primary {
    background: var(--bg-ink-1);
    color: var(--bg-page);
    border-color: transparent;
    font-weight: 600;
}
.btn-primary:hover {
    background: color-mix(in srgb, var(--bg-ink-1) 86%, var(--bg-page));
    color: var(--bg-page);
}

/* Randloser Knopf: bleibt randlos und nimmt Tinte plus eine leise
   Innenfuellung auf - so beschreibt es das System fuer `ghost`. */
.btn-outline-secondary {
    background: var(--bg-fill-hi);
    color: var(--bg-ink-1);
    border-color: var(--bg-edge);
}
.btn-outline-secondary:hover {
    background: color-mix(in srgb, var(--bg-ink-1) 18%, transparent);
    color: var(--bg-ink-1);
}

/* Endgueltiges Loeschen traegt die Gefahrfarbe des Systems - Magenta, kein
   rohes Rot; randlos wie die anderen Nebenknoepfe (ng#871). */
.btn-danger {
    background: transparent;
    color: var(--bg-accent-magenta);
    border-color: var(--bg-accent-magenta);
}
.btn-danger:hover {
    background: color-mix(in srgb, var(--bg-accent-magenta) 16%, transparent);
    color: var(--bg-ink-1);
}

.alert {
    display: block;
    padding: 14px 16px;
    border-radius: var(--bg-radius-md);
    border: var(--bg-hairline) solid var(--bg-edge);
    font-size: var(--bg-text-sm);
}
/* Gefahr ist Magenta, Warnung Bernstein - kein rohes Rot, kein Gelb. */
.alert-danger {
    background: color-mix(in srgb, var(--bg-accent-magenta) 16%, transparent);
    border-color: var(--bg-accent-magenta);
    color: var(--bg-ink-1);
}
.alert-warning {
    background: color-mix(in srgb, var(--bg-accent-amber) 16%, transparent);
    border-color: var(--bg-accent-amber);
    color: var(--bg-ink-1);
}

.nsai-auffangnetz {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 50;
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-width: 480px;
    margin-left: auto;
    min-width: 0;
}
.nsai-auffangnetz .alert {
    min-width: 0;
    overflow-wrap: break-word;
    background: var(--bg-fill-opaque);
    color: var(--bg-ink-1);
    box-shadow: 0 8px 24px var(--bg-shade);
}

.form-label {
    display: block;
    margin-bottom: 6px;
    font-size: var(--bg-text-sm);
    font-weight: 500;
    color: var(--bg-ink-2);
}
.form-control {
    width: 100%;
    padding: 12px 16px;
    border-radius: var(--bg-radius-sm);
    background: var(--bg-fill-inset);
    border: var(--bg-hairline) solid var(--bg-edge);
    box-shadow: inset 0 1px 2px var(--bg-shade);
    color: var(--bg-ink-1);
}

.text-muted { color: var(--bg-ink-3); }
.small { font-size: var(--bg-text-sm); }
.h4 {
    font-family: var(--bg-font-display);
    font-size: var(--bg-text-h3);
    font-weight: 600;
    letter-spacing: var(--bg-tracking-tight);
    margin: 0;
}
.w-100 { width: 100%; }
.shadow { box-shadow: var(--bg-drop), var(--bg-inner); }
.my-4 { margin-top: 16px; margin-bottom: 16px; }
.mt-3 { margin-top: 12px; }
.pt-3 { padding-top: 12px; }
.py-5 { padding-top: 20px; padding-bottom: 20px; }

/* Tailwind-Namen, die v0.2.0 neu fuehrt --------------------------- */
.py-6 { padding-top: 24px; padding-bottom: 24px; }
.py-16 { padding-top: 64px; padding-bottom: 64px; }
.text-right { text-align: right; }
.justify-end { justify-content: flex-end; }
.overflow-x-auto { overflow-x: auto; }
.min-w-full { min-width: 100%; }
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
@media (min-width: 768px) {
    .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* Bezeichnung braucht mehr Platz als der Mandantenschluessel -
       ein Feld fuer 190 Zeichen neben einem fuer 32. */
    .md\:col-span-2 { grid-column: span 2 / span 2; }
}

.text-amber-700, .dark\:text-amber-400 { color: var(--bg-accent-amber); }
.border-amber-600 { border-color: var(--bg-accent-amber); }
.border-indigo-200 { border-color: var(--bg-edge); }
.dark\:text-indigo-200 { color: var(--bg-ink-2); }
.hover\:bg-amber-50:hover,
.dark\:hover\:bg-amber-900\/20:hover { background-color: color-mix(in srgb, var(--bg-accent-amber) 14%, transparent); }

/* --- Aenderungsprotokoll (ng#90) -------------------------------------------
   Der Markdown-Renderer erzeugt nackte Tags ohne Klassen - absichtlich, damit
   er nichts ueber die Oberflaeche wissen muss. Die Gestaltung sitzt deshalb
   hier, an genau einer Stelle, und greift nur innerhalb des Kastens. */
.nsai-protokoll h1 { font-size: 1.5rem; margin: 0 0 12px; }
.nsai-protokoll h2 { font-size: 1.25rem; margin: 28px 0 8px; padding-top: 20px; border-top: 1px solid var(--bg-edge); }
.nsai-protokoll h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.nsai-protokoll h3 { font-size: 1rem; margin: 20px 0 6px; color: var(--bg-ink-2); }
.nsai-protokoll p { margin: 0 0 12px; line-height: 1.6; }
.nsai-protokoll ul { margin: 0 0 16px; padding-left: 22px; list-style: disc; }
.nsai-protokoll li { margin-bottom: 8px; line-height: 1.6; }
.nsai-protokoll code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; background: var(--bg-fill-inset); padding: 1px 5px; border-radius: 4px; }
.nsai-protokoll hr { border: 0; border-top: 1px solid var(--bg-edge); margin: 24px 0; }
