/* ERZEUGT von scripts/abgleich_schuldialogplus.py aus app/templates/base.html von
   SchulDialogPlus — nicht von Hand ändern (eigene Regeln: app/static/seiten/app.css). */
    /* Selbst-gehostete Inter (SIL OFL 1.1, app/static/fonts/inter/LICENSE).
       Variable-Font in einem File je Subset. ACHTUNG, seit 2026-09-23 um eine
       Gewichtsstufe verschoben (*.plus100.woff2, erzeugt von
       scripts/build-inter-plus100.py): jede font-weight N rendert wie N+100 —
       body { font-weight: 300 } ergibt also Regular, font-semibold ergibt
       Bold, 800/900 ergeben Black. So gilt die Vorgabe „Inter eine Stufe
       dicker" für jede Angabe in der App, ohne ~790 font-weight-Werte und
       die Tailwind-Klassen anzufassen. Latin deckt Deutsch inkl. ä/ö/ü/ß
       und „ " ab; Latin-Ext + Kursiv laden nur bei Bedarf (unicode-range/style). */
    @font-face {
      font-family: 'Inter';
      font-style: normal;
      font-display: swap;
      font-weight: 100 900;
      src: url(/static/fonts/inter/inter-latin-wght-normal.plus100.woff2) format('woff2-variations');
      unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
      font-family: 'Inter';
      font-style: normal;
      font-display: swap;
      font-weight: 100 900;
      src: url(/static/fonts/inter/inter-latin-ext-wght-normal.plus100.woff2) format('woff2-variations');
      unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
    }
    @font-face {
      font-family: 'Inter';
      font-style: italic;
      font-display: swap;
      font-weight: 100 900;
      src: url(/static/fonts/inter/inter-latin-wght-italic.plus100.woff2) format('woff2-variations');
      unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }

    .border {
      border-color: var(--border);
    }

    /* PWA-Splash-Overlay (weiß, zentriertes Logo + Ladehinweis).
       Standardmäßig versteckt; nur sichtbar, wenn das frühe Head-Skript
       html.sdp-show-splash setzt (installierte PWA, Kaltstart). */
    #sdp-splash { display: none; }
    html.sdp-show-splash #sdp-splash {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: 2147483647;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 1.25rem;
      background: #ffffff;
      opacity: 1;
      transition: opacity 350ms ease;
    }
    #sdp-splash.sdp-splash-hide { opacity: 0; }
    #sdp-splash img {
      width: 40vmin;
      max-width: 220px;
      height: auto;
      user-select: none;
      -webkit-user-select: none;
    }
    #sdp-splash .sdp-splash-text {
      font-size: 0.95rem;
      color: #475569;
      letter-spacing: 0.01em;
    }
    #sdp-splash .sdp-splash-dots::after {
      content: '';
      animation: sdp-splash-dots 1.4s steps(4, end) infinite;
    }
    @keyframes sdp-splash-dots {
      0% { content: ''; }
      25% { content: '.'; }
      50% { content: '..'; }
      75% { content: '...'; }
      100% { content: ''; }
    }
    @media (prefers-reduced-motion: reduce) {
      #sdp-splash { transition: none; }
      #sdp-splash .sdp-splash-dots::after { animation: none; content: '…'; }
    }

    /* Layout-Modus: "wide" hebt die max-w-5xl Page-Shell-Begrenzung auf.
       Sicher, weil alle .max-w-5xl Vorkommen im Projekt Page-Shell-Container sind. */
    html[data-layout="wide"] .max-w-5xl {
      max-width: none !important;
    }
    .nav-summary { list-style: none; display: flex; align-items: center; gap: 0.35rem; }
    .nav-summary::-webkit-details-marker { display: none; }
    .nav-summary svg.nav-icon { width: 14px; height: 14px; flex-shrink: 0; }

    /* KI Assistenz menu sparkle + shimmer */
    @keyframes ki-sparkle {
      0%, 100% { opacity: 1; transform: scale(1); }
      50% { opacity: .55; transform: scale(.82); }
    }
    @keyframes ki-shimmer {
      0%   { background-position: -100% 0; }
      100% { background-position: 200% 0; }
    }
    .ki-nav-sparkle { animation: ki-sparkle 2.8s ease-in-out infinite; will-change: opacity, transform; }
    .ki-nav-shimmer {
      background: linear-gradient(90deg, currentColor 30%, #6366f1 50%, currentColor 70%);
      background-size: 200% 100%;
      -webkit-background-clip: text;
      background-clip: text;
      -webkit-text-fill-color: transparent;
      animation: ki-shimmer 4s ease-in-out infinite;
      will-change: background-position;
    }
    /* Hervorgehobener Untermenue-Link "KI Assistenz" */
    .ki-nav-sub-link {
      display: inline-flex;
      align-items: center;
      gap: 0.3rem;
      width: fit-content;
      padding: 2px 8px;
      margin-left: -2px;
      border-radius: 6px;
      font-weight: 600;
      background: linear-gradient(90deg, rgba(99,102,241,0.06), rgba(168,85,247,0.03));
      border: 1px solid rgba(99,102,241,0.12);
    }
    .ki-nav-sub-link svg.ki-nav-icon-sm {
      width: 12px;
      height: 12px;
      flex-shrink: 0;
      color: #6366f1;
    }

    /* Dashboard-Card-Link-Stil — auch im Header-Menue genutzt */
    .dash-link {
      font-weight: 700;
      text-decoration: none;
      color: var(--text);
      font-size: 0.8125rem;
      line-height: 1.2rem;
    }
    .dash-link::before {
      content: "› ";
      font-weight: 700;
    }
    .dash-link:hover,
    .dash-link:focus-visible {
      color: var(--text);
      text-decoration: underline;
    }
    button.dash-link {
      background: transparent;
      border: 0;
      padding: 0;
      cursor: pointer;
      font-family: inherit;
    }
    button.dash-link:disabled,
    button.dash-link[disabled] {
      opacity: 0.45;
      cursor: not-allowed;
    }
    button.dash-link:disabled:hover,
    button.dash-link[disabled]:hover {
      text-decoration: none;
    }
    .dash-link-row {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.5rem;
    }
    .dash-link-row .dash-link-sep {
      color: var(--muted);
      user-select: none;
    }
    .dash-link.dash-link-danger {
      color: #dc2626;
      display: inline-flex;
      align-items: center;
      gap: 0.35rem;
    }
    .dash-link.dash-link-danger::before {
      content: none;
    }
    .dash-link.dash-link-danger:hover,
    .dash-link.dash-link-danger:focus-visible {
      color: #dc2626;
      text-decoration: underline;
    }
    .dash-link.dash-link-with-icon {
      display: inline-flex;
      align-items: center;
      gap: 0.35rem;
    }
    .dash-link.dash-link-with-icon::before {
      content: none;
    }
    .dash-link-icon {
      width: 1rem;
      height: 1rem;
      flex-shrink: 0;
    }

    /* Orientierung: Breadcrumb-Zeile + Zurück-Link in der Titelbox
       (partials/category_backlink.html). Dezent in Slate (var(--muted)); die
       aktuelle Seite in Textfarbe. Liegt innerhalb der hellen Titel-Card. */
    .title-breadcrumb {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.25rem 0.5rem;
      margin-bottom: 0.6rem;
      font-size: 0.75rem;
      line-height: 1.2;
      color: var(--muted);
      opacity: 0.8;
    }
    .title-breadcrumb a {
      color: var(--muted);
      text-decoration: none;
    }
    .title-breadcrumb a:hover,
    .title-breadcrumb a:focus-visible {
      color: var(--text);
      text-decoration: underline;
      text-underline-offset: 2px;
    }
    .title-back-link {
      font-weight: 600;
      display: inline-flex;
      align-items: center;
      gap: 0.25rem;
      white-space: nowrap;
    }
    .title-breadcrumb-sep { opacity: 0.5; user-select: none; }
    .title-breadcrumb-trail {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.25rem 0.35rem;
      list-style: none;
      margin: 0;
      padding: 0;
      min-width: 0;
    }
    .title-breadcrumb-trail li {
      display: inline-flex;
      align-items: center;
      min-width: 0;
    }
    .title-breadcrumb-cat {
      display: inline-flex;
      align-items: center;
      gap: 0.25rem;
    }
    .title-breadcrumb-cat svg { width: 0.9rem; height: 0.9rem; }
    .title-breadcrumb-chevron { opacity: 0.55; user-select: none; }
    .title-breadcrumb [aria-current="page"] {
      color: var(--text);
      font-weight: 600;
    }

    /* Kind-Info-Modal — auch ausserhalb von /anwesenheit nutzbar (z.B. Befehlssuche) */
    [data-attendance-info-modal] {
      position: fixed;
      inset: 0;
      z-index: 80;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 1rem;
      background: var(--overlay);
    }
    [data-attendance-info-dialog] {
      width: min(28rem, 100%);
      max-width: calc(100% - 2rem);
      max-height: calc(100dvh - 4rem);
      overflow-y: auto;
    }
    /* Kind-Info-Karte: zweite Seite per Swipe/Maus-Ziehen/Punkt-Klick */
    [data-childinfo-carousel] {
      overflow: hidden;
    }
    [data-childinfo-track] {
      display: flex;
      overflow-x: auto;
      scroll-snap-type: x mandatory;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: none;
      cursor: grab;
    }
    [data-childinfo-track]::-webkit-scrollbar { display: none; }
    [data-childinfo-track].is-dragging { cursor: grabbing; scroll-snap-type: none; }
    [data-childinfo-track] > [data-childinfo-page] {
      flex: 0 0 100%;
      width: 100%;
      min-width: 100%;
      scroll-snap-align: start;
    }
    .childinfo-dot {
      width: 0.55rem;
      height: 0.55rem;
      border-radius: 9999px;
      background: var(--border);
      transition: background 150ms ease, transform 150ms ease;
    }
    .childinfo-dot.is-active {
      background: var(--primary-line);
      transform: scale(1.15);
    }

    .notification-icon {
      width: 0.8rem;
      height: 0.8rem;
      color: #f43f5e;
      flex-shrink: 0;
    }

    .notification-icon--menu {
      width: 1rem;
      height: 1rem;
      position: absolute;
      top: -0.2rem;
      right: -0.2rem;
    }

    /* Kleiner roter Ungelesen-Punkt hinter Menue-Woertern (Mitteilungen/Chat). */
    .nav-unread-dot {
      display: inline-block;
      width: 0.5rem;
      height: 0.5rem;
      border-radius: 9999px;
      background: #ef4444;
      flex-shrink: 0;
    }
    .nav-dot-sep { color: var(--muted); opacity: 0.7; }

    /* Roter Eckpunkt mit weisser Glocke – prominenter Ungelesen-Hinweis an
       der oberen rechten Ecke einer Kachel. Der Host (Kachel) muss
       position:relative sein (Dashboard-Mini-Kachel + .dashboard-card sind es). */
    .notify-corner-badge {
      position: absolute;
      top: 0.5rem;
      right: 0.5rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.5rem;
      height: 1.5rem;
      border-radius: 9999px;
      background: #ef4444;
      color: #fff;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
      z-index: 2;
    }
    .notify-corner-badge svg {
      width: 0.95rem;
      height: 0.95rem;
    }
  /* Hover-Hintergrund ohne Inline-Handler (vorher onmouseenter/-leave mit
     style.background; die strenge CSP blockiert sie, csp-architecture.md).
     !important schlägt Inline-Stile. */
  [data-sdp-hover]:hover { background: var(--focus-soft) !important; }
    :root {
      color-scheme: light;
      --bg: hsl(214 24% 76%);
      --surface: #ffffff;
      --surface-glass: hsl(0 0% 100% / 1);
      --surface-muted: #f8fafc;
      --border: #e2e8f0;
      --text: #070f1a;
      --muted: #283548;
      --focus: rgba(15, 23, 42, 0.16);
      --focus-soft: rgba(15, 23, 42, 0.08);
      /* Hervorhebung der Trefferzeilen in der Befehlssuche (Hover/Auswahl):
         ein blauer Ton statt --focus-soft, damit sie sich von der grauen Zeile
         „Zuletzt erstellte Inhalte" abhebt (User-Vorgabe 2026-09-22). */
      --cmd-item-hover: rgba(37, 99, 235, 0.11);
      /* Antwort-/Rueckfrage-Karten der Befehlssuche: dezenter violetter Grund
         (die Assistenz spricht), damit sie sich als eigener Bereich von der
         Aktionsliste und der grauen Korb-Zeile abheben (User-Vorgabe 2026-09-22). */
      --cmd-answer-bg: rgba(139, 92, 246, 0.07);
      /* Zeile „Neue Nachrichten" (ungelesene Mitteilungen + Chats) in der
         Befehlssuche: dezentes Rot statt des Graus der Korb-Zeile (User-Vorgabe
         2026-09-23). */
      --cmd-news-bg: rgba(220, 38, 38, 0.08);
      --input-bg: #f8fafc;
      --input-border: #d7dce3;
      --input-border-focus: #94a3b8;
      --input-bg-focus: #ffffff;
      --header-bg: rgba(255, 255, 255, 0.92);
      --header-border: rgba(15, 23, 42, 0.08);
      --overlay: rgba(15, 23, 42, 0.35);
      /* Staerker abgedunkelter Backdrop fuer die Befehlssuche (User-Vorgabe
         2026-09-22) — das grosse, zentrale Overlay soll den Hintergrund
         deutlicher zuruecknehmen als ein gewoehnliches Modal. */
      --overlay-strong: rgba(15, 23, 42, 0.58);
      --shadow: 0 22px 52px -28px rgba(15, 23, 42, 0.6);
      /* Seit Entwurf A liegen die schwebenden Elemente (E-Mail-Kacheln) auf
         heller Flaeche statt auf dem dunklen Hintergrundbild — Rand + weicher
         Schatten statt des frueheren tiefen Schlagschattens. */
      --shadow-desktop-modern: 0 0 0 1px rgba(15, 23, 42, 0.08), 0 12px 32px -14px rgba(15, 23, 42, 0.28);
      /* Einheitlicher vertikaler Gap zwischen Content-Karten.
         Ersetzt ad-hoc space-y-3/4/6 in neuen Templates. Wird per Media
         Query auf Tablet/Mobile reduziert, siehe @media-Regeln unten. */
      --card-gap: 1rem;
      --dashboard-card-bg: var(--surface-glass);
      --dashboard-card-shadow: 0 24px 50px -20px rgba(15, 23, 42, 0.45);
      --bg-image: url("/static/images/background_light.jpg");
      --bg-position: right top;
      --bg-size: cover;
      --bg-attachment: fixed;
      --bg-shade: rgba(7, 12, 25, 0.55);
      --bg-grid: none;
      --particle-opacity: 0.9;
      --particle-color-1: rgba(255, 255, 255, 0.84);
      --particle-color-2: rgba(255, 255, 255, 0.76);
      --particle-color-3: rgba(255, 255, 255, 0.68);
      --particle-color-4: rgba(255, 255, 255, 0.6);
      --particle-link: rgba(255, 255, 255, 0.4);
      --code-bg: #f6f8fa;
      --code-text: #0f172a;
      /* Punkt fuer "hier ist etwas Neues" (Erinnerungen, Antworten der Eltern).
         Im Dark-Mode bewusst heller: #dc2626 faellt dort gegen die dunkle Karte
         unter 3:1 (WCAG 1.4.11 fuer nicht-textliche Elemente). */
      --notify-dot: #dc2626;
      /* Diagramm-Serienfarben (Umfragen-Auswertung).
         Feste Reihenfolge, NIE zyklisch weitergedreht: eine Serie behaelt ihre
         Farbe ueber alle Diagrammtypen hinweg, weil der Index aus der
         Aggregat-Reihenfolge kommt. Beide Modi sind gegen die Flaechenfarben
         dieses Projekts geprueft (Helligkeitsband, Chroma, Farbfehlsichtigkeit,
         Normalsicht, Kontrast). Drei Hell-Toene liegen unter 3:1 gegen Weiss —
         deshalb traegt jedes Diagramm zusaetzlich eine Legende mit Beschriftung
         und Wert; Identitaet haengt nie allein an der Farbe. */
      --chart-1: #2a78d6;
      --chart-2: #eb6834;
      --chart-3: #1baf7a;
      --chart-4: #eda100;
      --chart-5: #e87ba4;
      --chart-6: #008300;
      --chart-7: #4a3aa7;
      --chart-8: #e34948;
      --chart-empty: #e2e8f0;
    }

    html[data-theme="dark"] {
      color-scheme: dark;
      --bg: #0b111b;
      --surface: #111827;
      --surface-glass: hsla(222, 46%, 14%, 0.88);
      --surface-muted: #1f2937;
      --border: #2f3747;
      --text: #e2e8f0;
      --muted: #cbd5e1;
      --focus: rgba(148, 163, 184, 0.35);
      --focus-soft: rgba(148, 163, 184, 0.22);
      --cmd-item-hover: rgba(96, 165, 250, 0.22);
      --cmd-answer-bg: rgba(167, 139, 250, 0.12);
      --cmd-news-bg: rgba(248, 113, 113, 0.14);
      --input-bg: #0f172a;
      --input-border: #2a3342;
      --input-border-focus: #64748b;
      --input-bg-focus: #111827;
      --header-bg: rgba(255, 255, 255, 0.12);
      --header-border: rgba(148, 163, 184, 0.2);
      --overlay: rgba(2, 6, 23, 0.65);
      --overlay-strong: rgba(2, 6, 23, 0.82);
      --shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.8);
      --shadow-desktop-modern: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 12px 32px -14px rgba(0, 0, 0, 0.7);
      --dashboard-card-bg: var(--surface-glass);
      --dashboard-card-shadow: 0 28px 60px -24px rgba(0, 0, 0, 0.6);
      --bg-image: url("/static/images/background_light.jpg");
      --bg-position: right top;
      --bg-size: cover;
      --bg-attachment: fixed;
      /* Dunkler Seitengrund hinter den Kacheln (2026-09-23, vorher
         rgba(0,0,0,0.5) → mittelgrau über dem hellen Standardbild). Slate-Ton
         passend zu den Glas-Kacheln; bei 0.84 verschwänden die Kacheln im Grund. */
      --bg-shade: rgba(2, 6, 23, 0.76);
      --particle-opacity: 0.78;
      --particle-color-1: rgba(56, 189, 248, 0.62);
      --particle-color-2: rgba(96, 165, 250, 0.6);
      --particle-color-3: rgba(45, 212, 191, 0.52);
      --particle-color-4: rgba(251, 191, 36, 0.4);
      --particle-link: rgba(125, 211, 252, 0.3);
      --code-bg: #0b1220;
      --code-text: #e2e8f0;
      --notify-dot: #f87171;
      /* Eigene Stufen fuer die dunkle Flaeche — kein automatisches Umdrehen. */
      --chart-1: #3987e5;
      --chart-2: #d95926;
      --chart-3: #199e70;
      --chart-4: #c98500;
      --chart-5: #d55181;
      --chart-6: #008300;
      --chart-7: #9085e9;
      --chart-8: #e66767;
      --chart-empty: #2f3747;
    }

    /* ===== Optik-Tokens (Auffrischung, Usability-Review Abschnitt 6, 2026-09-25) =====
       Eine Quelle für Primärfarbe, Radius, Überschriften und Status-Farben.
       Globale Regeln der Auffrischung lesen NUR diese Tokens — nur so kann der
       Block darunter die Anwesenheitserfassung auf die bisherige Optik
       zurücksetzen. Regel: .claude/rules/optik-tokens.md */
    :root {
      --primary: #243b63;
      --primary-hover: #1c2f50;
      --primary-border: transparent;
      --on-primary: #ffffff;
      /* Linie in Primärfarbe: aktiver Reiter, Fokus. */
      --primary-line: #243b63;
      /* Ausgewählte Zeile, aktiver Menüpunkt. */
      --primary-soft: rgba(36, 59, 99, 0.08);
      --focus-ring: 0 0 0 3px rgba(36, 59, 99, 0.25);
      --radius-sm: 0.5rem;
      --radius: 0.75rem;
      --radius-lg: 1rem;
      --h1: 1.625rem;
      --h2: 1.125rem;
      --sheet-title: 1.25rem;
      --ok: #15803d;
      --ok-soft: #ecfdf3;
      --info: #1d4ed8;
      --info-soft: #eff6ff;
      --warn: #b45309;
      --warn-soft: #fffbeb;
      --danger: #b91c1c;
      --danger-soft: #fef2f2;
      --neutral: #475569;
      --neutral-soft: #f1f5f9;
    }
    @media (min-width: 1025px) {
      :root { --h1: 1.75rem; }
    }
    /* Hintergrund hinter Fenstern: immer halbtransparent (--overlay), nie
       deckend. Ersetzt die Tailwind-Klassen bg-slate-900/40 … /70 und das
       volldeckende bg-slate-900 (Schwarzes Brett). Bildbetrachter (Lightbox)
       bleiben dunkel. */
    .sdp-overlay-bg { background: var(--overlay); }
    /* Linien-Symbol aus macros/icon.html (Phase 6): so groß wie die Schrift,
       auf der Grundlinie des Texts daneben. Eigene Klassen setzen die Größe
       selbst. */
    .sdp-icon {
      display: inline-block;
      width: 1.1em;
      height: 1.1em;
      flex-shrink: 0;
      vertical-align: -0.2em;
    }
    /* Status-Farbe eines Symbols (z. B. Ja/Nein/Enthaltung einer Abstimmung). */
    .sdp-icon--ok { color: var(--ok); }
    .sdp-icon--info { color: var(--info); }
    .sdp-icon--warn { color: var(--warn); }
    .sdp-icon--danger { color: var(--danger); }
    .sdp-icon--neutral { color: var(--neutral); }
    /* Dunkel: heller Primärknopf mit dunkler Schrift (User-Entscheidung
       2026-09-25, löst „Primärknopf bleibt in beiden Themes dunkel" ab). */
    html[data-theme="dark"] {
      --primary: #8fa8d8;
      --primary-hover: #a9bde3;
      --primary-border: transparent;
      --on-primary: #0b111b;
      --primary-line: #8fa8d8;
      --primary-soft: rgba(143, 168, 216, 0.14);
      --focus-ring: 0 0 0 3px rgba(143, 168, 216, 0.35);
      --ok: #4ade80;
      --ok-soft: rgba(74, 222, 128, 0.12);
      --info: #93c5fd;
      --info-soft: rgba(147, 197, 253, 0.12);
      --warn: #fbbf24;
      --warn-soft: rgba(251, 191, 36, 0.12);
      --danger: #f87171;
      --danger-soft: rgba(248, 113, 113, 0.12);
      --neutral: #cbd5e1;
      --neutral-soft: #1f2937;
    }

    /* Seitentitel in EINER Größe (--h1, ab 1025 px etwas größer). Erfasst die
       Titel mit den üblichen Tailwind-Größen (text-lg/-xl/-2xl, dazu der
       Tippfehler text-l im Artikel-Editor). Eigene Titel — Begrüßung der
       Startseite, KI-Seitenleiste, öffentliche Eltern-Seiten, Druck — tragen
       eigene Klassen und bleiben, die Anwesenheitserfassung ist ausgenommen. */
    @media screen {
      #page-main h1:is(.text-lg, .text-xl, .text-2xl, .text-l):where(:not([data-sdp-bestandsoptik] *)) {
        font-size: var(--h1);
        line-height: 1.2;
      }
    }

    /* Anwesenheitserfassung (/anwesenheit) behält die bisherige Optik
       (User-Entscheidung 2026-09-25). Das Attribut tragen dort die Wurzel und
       jedes Fenster, das an <body> hängt. Die Werte sind der Stand vor der
       Auffrischung. Regeln ohne Token (H1-Größe) schließen den Bereich mit
       :not(:where([data-sdp-bestandsoptik] *)) aus. */
    [data-sdp-bestandsoptik] {
      --primary: #0f172a;
      --primary-hover: #1e293b;
      --primary-border: transparent;
      --on-primary: #ffffff;
      --primary-line: var(--text);
      --primary-soft: var(--focus-soft);
      --focus-ring: 0 0 0 2px var(--text);
      --radius-sm: 0.375rem;
      --radius: 0.5rem;
      --radius-lg: 1rem;
      /* Fenster-Hintergrund: war dort fest (auch im Dunkeln). */
      --overlay: rgba(15, 23, 42, 0.85);
    }
    html[data-theme="dark"] [data-sdp-bestandsoptik] {
      --primary: #1e293b;
      --primary-hover: #334155;
      --primary-border: #3b4658;
      --on-primary: #f8fafc;
    }

    /* ===== Adaptive Textfarbe für Texte direkt auf dem Seitenhintergrund =====
       Mechanismus (abstrahiert): body[data-bg-contrast] wird clientseitig aus
       Theme + Overlay-Schleier + Bildhelligkeit gesetzt (sdpApplyBackgroundContrast
       / window.sdpBackgroundIsDark in body). Daraus ergeben sich --on-bg-text und
       --on-bg-shadow. Jeder Text, der NICHT in einer Karte, sondern direkt auf dem
       Hintergrund liegt, bekommt die Utility-Klasse .on-bg-text und ist damit
       automatisch kontraststark — egal welcher Hintergrund eingestellt ist.
       Default (vor JS / unbekannt): dunkler Grund → heller Text. */
    :root {
      --on-bg-text: #ffffff;
      --on-bg-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 2px rgba(0, 0, 0, 0.4);
    }
    body[data-bg-contrast="light"] {
      --on-bg-text: #0f172a;
      --on-bg-shadow: 0 1px 1px rgba(255, 255, 255, 0.85), 0 0 2px rgba(255, 255, 255, 0.6);
    }
    .on-bg-text {
      color: var(--on-bg-text);
      text-shadow: var(--on-bg-shadow);
    }

    /* ── Entwurf / Auto-Save (sdpDraftAutosave) ──────────────────────────────
       Wiederherstellen-Banner + dezenter Speicher-Status. Bewusst zurückhaltend
       gestaltet (amber = Hinweis, kein Fehler) und Dark-Mode-tauglich. */
    .sdp-draft-restore {
      display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.9rem;
      justify-content: space-between;
      margin-bottom: 1rem; padding: 0.7rem 0.95rem;
      border: 1px solid rgba(217, 119, 6, 0.30);
      background: rgba(217, 119, 6, 0.09);
      border-radius: 0.75rem;
      font-size: 0.85rem; color: var(--text);
    }
    .sdp-draft-restore-msg { display: inline-flex; align-items: center; gap: 0.4rem; }
    .sdp-draft-restore-msg svg { flex-shrink: 0; color: #d97706; }
    .sdp-draft-restore-actions { display: inline-flex; gap: 0.5rem; flex-shrink: 0; }
    .sdp-draft-restore-btn, .sdp-draft-discard-btn {
      border-radius: var(--radius); padding: 0.32rem 0.8rem;
      font-size: 0.8rem; font-weight: 600; cursor: pointer;
      border: 1px solid var(--border); background: var(--surface); color: var(--text);
      transition: background 120ms ease, opacity 120ms ease;
    }
    .sdp-draft-restore-btn { background: var(--primary); color: var(--on-primary); border-color: var(--primary-border); }
    .sdp-draft-restore-btn:hover { opacity: 0.92; }
    .sdp-draft-discard-btn:hover { background: var(--focus-soft); }

    .sdp-draft-status {
      display: inline-flex; align-items: center; gap: 0.35rem;
      font-size: 0.75rem; color: var(--muted); white-space: nowrap;
      opacity: 0; transition: opacity 200ms ease;
    }
    .sdp-draft-status.is-visible { opacity: 1; }
    .sdp-draft-status[data-tone="saved"]::before {
      content: "\2713"; color: #16a34a; font-weight: 700;
    }

    * {
      -webkit-font-smoothing: antialiased;
      text-rendering: optimizeLegibility;
    }

    /* Bounce-/Rubber-Band-Effekt am oberen/unteren Rand beim vertikalen
       Scrollen unterbinden (App-weit, User-Wunsch). */
    html {
      overscroll-behavior-y: none;
    }

    /* ===== Schriftgroessen-Regler (Dashboard-Titelkachel) =====
       Drei Stufen zu je 1pt ueber der Standardgroesse. Bewusst `calc(100% + Npt)`
       statt fester pt-Werte: das `100%` ist die im Browser eingestellte
       Grundschrift — eine feste Angabe wuerde eine dort vergroesserte Schrift
       wieder einkassieren. Die Oberflaeche misst fast durchgaengig in rem,
       deshalb traegt die Wurzel die Einstellung auf alle Seiten. */
    html[data-font-scale="1"] { font-size: calc(100% + 1pt); }
    html[data-font-scale="2"] { font-size: calc(100% + 2pt); }
    html[data-font-scale="3"] { font-size: calc(100% + 3pt); }

    body {
      overscroll-behavior-y: none;
      font-family: "Inter", system-ui, -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
      font-weight: 300;
      color: var(--text);
      background-color: var(--bg);
      background-image:
        linear-gradient(var(--bg-shade), var(--bg-shade)),
        var(--bg-grid, none),
        var(--bg-image);
      background-position: 0 0, 0 0, var(--bg-position, center);
      background-size: cover, auto, var(--bg-size, cover);
      background-repeat: no-repeat, repeat, no-repeat;
      background-attachment: var(--bg-attachment, fixed);
      letter-spacing: -0.01em;
      line-height: 1.35;
      position: relative;
      isolation: isolate;
      overflow-x: hidden;
    }

    @media (max-width: 768px), (hover: none) {
      body {
        --bg-position: center top;
        background-position: 0 0, 0 0, center top;
        background-attachment: scroll;
      }

    }

    html[data-effects="reduced"] header {
      backdrop-filter: none;
    }

    main {
      position: relative;
      z-index: 3;
    }

    footer {
      position: relative;
      z-index: 2;
    }

    /* Link auf die Datenschutzinformationen für Seiten ohne Fusszeile
       (hide_header_footer, Befund M27) — partials/oeffentlicher_fusszeilen_link.html.
       Seiten, die ihn in ihr eigenes Layout setzen, passen ihn mit einer eigenen
       Klasse an (Chat-Hülle, Office-Ansicht). */
    .sdp-ds-fuss {
      position: relative;
      z-index: 2;
      box-sizing: border-box;
      max-width: 64rem;
      margin: 0 auto;
      padding: 1.25rem var(--sdp-mobile-gutter, 1rem) 1.5rem;
      font-size: 0.75rem;
      line-height: 1.4;
      color: var(--muted);
    }
    .sdp-ds-fuss--inline {
      display: inline;
      max-width: none;
      margin: 0;
      padding: 0;
      font-size: inherit;
      color: inherit;
    }
    .sdp-ds-fuss .sdp-ds-link {
      color: inherit;
      text-decoration: underline;
      text-underline-offset: 2px;
    }
    .sdp-ds-fuss .sdp-ds-link:hover { color: var(--text); }
    @media print { .sdp-ds-fuss { display: none !important; } }

    .font-mono,
    code,
    pre,
    .markdown-body code,
    .markdown-body pre {
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
    }

    header {
      background: var(--header-bg) !important;
      background-color: var(--header-bg) !important;
      border-color: var(--header-border);
      backdrop-filter: blur(10px);
    }

    main {
      padding-top: 0.75rem;
      padding-bottom: 1.5rem;
      color: #f1f5f9;
    }

    a {
      text-underline-offset: 3px;
    }

    /* ── Barrierefreiheit: Link-Unterscheidbarkeit (WCAG 1.4.1) ── */
    .markdown-body a,
    main .prose a {
      color: #2563eb;
      text-decoration: underline;
    }
    html[data-theme="dark"] .markdown-body a,
    html[data-theme="dark"] main .prose a {
      color: #60a5fa;
    }

    /* ── Barrierefreiheit: Skip-Link ── */
    .sdp-skip-link {
      position: absolute;
      left: -9999px;
      top: auto;
      width: 1px;
      height: 1px;
      overflow: hidden;
      z-index: 100;
      padding: 0.75rem 1.5rem;
      background: var(--surface);
      color: var(--text);
      border: 2px solid var(--text);
      border-radius: 0.5rem;
      font-size: 0.875rem;
      font-weight: 600;
      text-decoration: none;
    }
    .sdp-skip-link:focus {
      position: fixed;
      top: 0.75rem;
      left: 0.75rem;
      width: auto;
      height: auto;
      clip: auto;
    }

    .bg-white.border.rounded-2xl {
      /* background-color statt background-Shorthand: das Shorthand wuerde
         background-image (z.B. den .ki-cat-accent-Verlauf) auf none zuruecksetzen */
      background-color: var(--surface-glass);
      box-shadow: var(--shadow);
    }

    /* Dashboard-Karten teilen denselben Dropshadow wie die Titel-/Standardkarten
       (statt einer eigenen Variante). Den Hintergrund setzen sie inline. In den
       optimized-Modi greifen weiter unten die gemeinsamen .dashboard-card-Regeln
       (Desktop: --shadow-desktop-modern, Mobile: kein Schatten). */
    .dashboard-card.border.rounded-2xl {
      box-shadow: var(--shadow);
    }

    .rounded-2xl { border-radius: 0.5rem; }
    .rounded-xl  { border-radius: 0.5rem; }
    .rounded-lg  { border-radius: 0.375rem; }
    /* Ein Radius-Set (Optik-Tokens, optik-tokens.md): Knöpfe, Eingaben und
       Listenzeilen --radius, kleine Elemente --radius-sm. Die drei Regeln
       darüber gelten nur noch in der Anwesenheitserfassung
       ([data-sdp-bestandsoptik]); :where hält die Spezifität bei (0,1,0),
       damit Komponenten-Regeln weiter gewinnen. */
    :is(.rounded-2xl, .rounded-xl):where(:not([data-sdp-bestandsoptik], [data-sdp-bestandsoptik] *)) {
      border-radius: var(--radius);
    }
    :is(.rounded-lg, .rounded-md, .rounded):where(:not([data-sdp-bestandsoptik], [data-sdp-bestandsoptik] *)) {
      border-radius: var(--radius-sm);
    }
    /* Kleine Textknöpfe (text-xs) mit --radius-sm: mit 12 px wirkten sie wie
       Pillen (User-Entscheidung 2026-09-25). Das Makro btn_*(size="sm") setzt
       dafür selbst rounded-lg. */
    :is(button, a, [role="button"]).text-xs:is(.rounded-xl, .rounded-2xl):where(:not([data-sdp-bestandsoptik], [data-sdp-bestandsoptik] *)) {
      border-radius: var(--radius-sm);
    }

    .border.rounded-2xl,
    .border.rounded-xl {
      color: var(--text);
    }

    /* Auf dem Telefon (<= 640 px) gibt es keine schwebenden Karten mehr: der
       Block „Mobile Vollbildansicht" am Ende dieses Stylesheets macht aus den
       Boxen Abschnitte auf einer deckenden Flaeche. */
    /* Basis-Klasse .card-modern: theme-bewusste, wiederverwendbare Karte.
       Drop-in-Alternative zu `bg-white border rounded-2xl`. Nimmt am
       Schreibtisch im `optimized`-Modus automatisch den modernen Look an
       (siehe Media-Query unten). Reicht fuer Legacy-Look per se. */
    .card-modern {
      background: var(--surface-glass);
      border: 1px solid var(--border);
      border-radius: 1rem;
    }

    /* Utility-Klasse .card-stack: vertikaler Container fuer Karten mit
       einheitlichem Abstand via --card-gap. Drop-in-Ersatz fuer
       `space-y-3/4/6` in neuen Templates, erlaubt spaeter globale
       Feinjustierung nur an einer Stelle. */
    .card-stack > :not([hidden]) ~ :not([hidden]) {
      margin-top: var(--card-gap);
    }

    /* === Modernes Desktop-Design ===
       Nur aktiv bei Viewport >= 641 px UND KEIN User-Flag gesetzt.
       Default. Karten sind sanft gerundet, haben keinen harten Rand und heben
       sich ueber einen hellen Dropshadow vom (typischerweise dunklen)
       Seitenhintergrund ab. Modals behalten ihren klassischen Look,
       damit der Overlay-Kontrast erhalten bleibt. */
    @media (min-width: 641px) {
      /* Standard-Karten: gerundet, heller Dropshadow, kein harter Rand */
      html[data-desktop-ui="optimized"] .bg-white.border.rounded-2xl,
      html[data-desktop-ui="optimized"] .dashboard-card.border.rounded-2xl,
      html[data-desktop-ui="optimized"] .card-modern {
        border-radius: 0.75rem;
        border-color: transparent;
        box-shadow: var(--shadow-desktop-modern);
      }

      /* Step-Surface-Boxen (E-Mail-Kacheln): feine Linie statt Schatten
         (optische Auffrischung, Phase 5 — User-Entscheidung 2026-09-25). */
      html[data-desktop-ui="optimized"] [class*="step-surface-"] {
        border-radius: 0.75rem;
        border-color: var(--border);
        box-shadow: none;
      }

      /* Kleinere rounded-xl/lg Elemente (Buttons, Inputs, Sub-Karten) behalten
         ihre normale, sanfte Rundung (Basis-Werte aus base.html) — kein extra
         Schatten, kein Quadratisch-Override mehr. */

      /* Modals: klassischer Look bleibt erhalten (Overlay-Kontrast).
         Border + klassischer Schatten werden wiederhergestellt; die Rundung
         erben sie aus der Standard-Karten-Regel oben (bzw. ihrem Inline-Radius).
         Spezifitaet ueberschreibt die obigen Regeln. */
      html[data-desktop-ui="optimized"] [role="dialog"] .bg-white.border.rounded-2xl,
      html[data-desktop-ui="optimized"] [data-sdp-modal] .bg-white.border.rounded-2xl,
      html[data-desktop-ui="optimized"] [role="dialog"] .dashboard-card.border.rounded-2xl,
      html[data-desktop-ui="optimized"] [data-sdp-modal] .dashboard-card.border.rounded-2xl,
      html[data-desktop-ui="optimized"] [role="dialog"] .card-modern,
      html[data-desktop-ui="optimized"] [data-sdp-modal] .card-modern {
        border: 1px solid var(--border);
        box-shadow: var(--shadow);
      }

      /* Inline-Hilfe-Icons dezent: klein, halbtransparent, randlos.
         Erst beim Hover/aktiv bekommen sie den blauen Akzent zurueck.
         Opacity 0.75 statt 0.55, damit WCAG AA 4.5:1 gegen --surface erreicht wird. */
      html[data-desktop-ui="optimized"] .sdp-help-icon {
        width: 0.95rem;
        height: 0.95rem;
        min-width: 0.95rem;
        min-height: 0.95rem;
        border-color: transparent;
        background: transparent;
        color: var(--muted);
        opacity: 0.75;
      }
      html[data-desktop-ui="optimized"] .sdp-help-icon:hover,
      html[data-desktop-ui="optimized"] .sdp-help-icon[aria-expanded="true"] {
        opacity: 1;
        color: #2563eb;
        border-color: transparent;
        background: transparent;
      }

      /* Der Hilfe-Knopf der Kopfzeile war hier frueher blau gefuellt. Seit
         Entwurf A (2026-09-24) ist er auf allen Breiten ein schlichter Kreis
         wie auf dem Telefon (Block „Kopfzeile" der Vollflaechigen Ansicht). */
    }

    /* === Tablet-Breakpoint (641–1024 px) ===
       Hybrid-Layout: uebernimmt Desktop-Modern-Karten (wegen gemeinsamer
       `min-width: 641px` Regel oben), ergaenzt aber explizite Seiten-Gutter
       und etwas engeres Card-Spacing. So liegen Karten auf dem iPad nicht
       mehr randlos am Viewport, wirken aber kompakter als auf Desktop. */
    /* === Textkante (Seiten-Gutter), alle Breiten ===
       Seit der Vollflaechigen Ansicht (Block am Ende des Stylesheets) liegen
       die Inhalte als Abschnitte OHNE eigenen seitlichen Innenabstand auf der
       Flaeche — der Gutter IST der Textrand, die Trennlinien zwischen den
       Abschnitten sind buendig mit dem Text eingerueckt. Die Variable heisst
       aus historischen Gruenden „mobile" (zuerst nur das Telefon), gilt aber
       auf allen Breiten: Telefon 1rem (wie im Kind-Fenster), Tablet 2rem,
       Schreibtisch 2.5rem.
       Kopfzeile und Footer bekommen denselben Wert: beide sind eigene
       max-w-5xl-Container ausserhalb von #page-main, und eine Kopfzeile, die
       weiter innen beginnt als der Text darunter, faellt sofort auf.
       Templates, die den Gutter bewusst ganz aufheben (Chat, KI Assistenz,
       Dateiablage-Editor/-Notiz, oeffentlicher Wochenplan), tun das per
       !important und bleiben unberuehrt. */
    :root { --sdp-mobile-gutter: 2.5rem; }
    #page-main,
    header > div.max-w-5xl,
    footer.max-w-5xl {
      padding-left: var(--sdp-mobile-gutter);
      padding-right: var(--sdp-mobile-gutter);
    }
    @media (min-width: 641px) and (max-width: 1024px) {
      :root {
        --card-gap: 0.875rem;
        --sdp-mobile-gutter: 2rem;
      }
      /* Vertikale Gaps zwischen Bloecken etwas kompakter als Desktop. */
      main .space-y-8 > :not([hidden]) ~ :not([hidden]) {
        margin-top: 0.9rem;
      }
      main .space-y-6 > :not([hidden]) ~ :not([hidden]) {
        margin-top: 0.85rem;
      }
      /* Modal-Panels nicht ueber den Viewport hinaus spreizen. */
      [role="dialog"] .max-w-5xl,
      [data-sdp-modal] .max-w-5xl {
        max-width: min(62rem, calc(100vw - 2.5rem));
      }
    }
    @media (max-width: 640px) {
      :root {
        --card-gap: 0.75rem;
        /* Textkante auf dem Telefon (siehe „Textkante" oben). Als Variable,
           damit eine einzelne Seite sie mit einer Zeile weiten kann. */
        --sdp-mobile-gutter: 1rem;
      }
    }

    input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]),
    textarea {
      background: transparent;
      border-color: var(--input-border);
      box-shadow: 0 0 0 2px var(--focus-soft);
      transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
    }

    select {
      background: transparent;
      border-color: var(--input-border);
      box-shadow: 0 0 0 2px var(--focus-soft);
      transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
    }

    input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):focus,
    textarea:focus,
    select:focus {
      outline: none;
      border-color: var(--input-border-focus);
      box-shadow: 0 0 0 3px var(--focus);
      background: transparent;
    }

    /* ── Barrierefreiheit: Globaler Focus-Indicator ── */
    :focus-visible {
      outline: 2px solid var(--primary-line);
      outline-offset: 2px;
    }
    input:focus-visible, textarea:focus-visible, select:focus-visible {
      outline: none;
    }

    button,
    a,
    input,
    textarea,
    select {
      transition: all 0.15s ease;
    }

    /* Primary-Button: Farben aus den Optik-Tokens (hell Tintenblau, dunkel
       Hellblau mit dunkler Schrift). Ersetzt hartcodierte `bg-slate-900
       text-white` und `background: var(--text)`. Die Anwesenheitserfassung
       bekommt über [data-sdp-bestandsoptik] die bisherigen Werte. */
    .btn-primary {
      background: var(--primary);
      color: var(--on-primary);
      border: 1px solid var(--primary-border);
    }
    .btn-primary:hover:not(:disabled) {
      background: var(--primary-hover);
    }
    .btn-primary:disabled {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* Secondary-Button: transparenter Rand, theme-bewusst.
       Ergaenzt .btn-primary fuer sekundaere Aktionen. */
    .btn-secondary {
      background: transparent;
      color: var(--text);
      border: 1px solid var(--border);
    }
    .btn-secondary:hover:not(:disabled) {
      background: var(--focus-soft);
    }
    .btn-secondary:disabled {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* Danger-Button: roter Akzent, subtiler Hover. */
    .btn-danger {
      background: transparent;
      color: var(--danger);
      border: 1px solid var(--border);
    }
    .btn-danger:hover:not(:disabled) {
      background: var(--danger-soft);
      border-color: rgba(220, 38, 38, 0.35);
    }
    .btn-danger:disabled {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* Tertiär-Button: Textlink mit Symbol, ohne Rahmen und Füllung. Das
       Symbol trägt die Kategoriefarbe der Seite (--cat-icon), sonst die
       Sekundärfarbe. Basis für btn_tertiary() aus button.html. */
    .btn-tertiary {
      background: transparent;
      color: var(--text);
      border: 1px solid transparent;
      font-weight: 600;
    }
    .btn-tertiary svg { color: var(--cat-icon, var(--muted)); }
    .btn-tertiary:hover:not(:disabled) {
      background: var(--focus-soft);
    }
    .btn-tertiary:disabled {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* Status-Chips (Optik-Tokens): ok, info, warn, danger, neutral. Die Pille
       ist Status-Chips vorbehalten; Rot nur für Fehler, Löschen, „Grund offen". */
    .sdp-chip {
      display: inline-flex;
      align-items: center;
      gap: 0.25rem;
      padding: 0.125rem 0.5rem;
      border-radius: 999px;
      font-size: 0.75rem;
      font-weight: 600;
      line-height: 1.35;
      white-space: nowrap;
      color: var(--neutral);
      background: var(--neutral-soft);
    }
    .sdp-chip svg { width: 0.9em; height: 0.9em; flex: none; }
    .sdp-chip--ok { color: var(--ok); background: var(--ok-soft); }
    .sdp-chip--info { color: var(--info); background: var(--info-soft); }
    .sdp-chip--warn { color: var(--warn); background: var(--warn-soft); }
    .sdp-chip--danger { color: var(--danger); background: var(--danger-soft); }
    .sdp-chip--neutral { color: var(--neutral); background: var(--neutral-soft); }

    /* Hinweis im Info-Stil (z. B. Notiz zu einem Kind): Symbol + Text auf
       zarter Fläche statt fettem Rot. */
    .sdp-note {
      display: flex;
      gap: 0.4rem;
      align-items: flex-start;
      padding: 0.3rem 0.55rem;
      border-radius: var(--radius-sm);
      color: var(--text);
      background: var(--info-soft);
    }
    .sdp-note > svg { flex: none; width: 1em; height: 1em; margin-top: 0.15em; color: var(--info); }

    /* Farbton einer Hinweis-Box (Abstände und Radius bringt die Box selbst mit). */
    .sdp-callout--warn {
      color: var(--text);
      background: var(--warn-soft);
      border: 1px solid color-mix(in srgb, var(--warn) 30%, transparent);
    }
    .sdp-callout--info {
      color: var(--text);
      background: var(--info-soft);
      border: 1px solid color-mix(in srgb, var(--info) 30%, transparent);
    }
    /* „… ist an deiner Schule noch nicht eingerichtet" (macros/ki_hinweis.html,
       2026-11-05): ein Baustein statt sechs Formen. */
    .sdp-ki-hinweis:not([hidden], .hidden) { display: flex; align-items: flex-start; gap: 0.5rem; max-width: 64rem; }
    /* Leerzustand einer Liste (2026-11-05): kurzer Satz, gedämpft, linksbündig,
       darunter höchstens ein umrandeter Knopf („Erste … anlegen"). Vorher drei
       Formen (zentriert, gestrichelter Kasten, Überschrift + Text + Knopf). */
    .sdp-leer:not(.hidden, [hidden]) { display: flex; flex-direction: column; align-items: flex-start; gap: 0.75rem; padding-block: 0.5rem; font-size: 0.875rem; color: var(--muted); }
    .sdp-ki-hinweis > svg { flex: none; width: 1.05em; height: 1.05em; margin-top: 0.15em; }

    /* Icon-Only-Button: quadratisch, Basis fuer .btn_icon() aus button.html. */
    .btn-icon {
      background: transparent;
      color: var(--muted);
      border: 1px solid transparent;
    }
    .btn-icon:hover:not(:disabled) {
      background: var(--focus-soft);
      color: var(--text);
    }
    .btn-icon:disabled {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* iOS-artiger Switch (toggle). Genutzt von macros/switch.html. */
    .sdp-switch {
      position: relative;
      display: inline-flex;
      align-items: center;
      vertical-align: middle;
      cursor: pointer;
      user-select: none;
      width: 36px;
      height: 20px;
      flex: 0 0 auto;
    }
    .sdp-switch input {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      margin: 0;
      opacity: 0;
      cursor: pointer;
    }
    .sdp-switch-track {
      position: absolute;
      inset: 0;
      border-radius: 999px;
      background: var(--surface-muted);
      border: 1px solid var(--border);
      transition: background 150ms ease, border-color 150ms ease;
      pointer-events: none;
    }
    .sdp-switch-thumb {
      position: absolute;
      top: 50%;
      left: 2px;
      width: 14px;
      height: 14px;
      border-radius: 999px;
      background: #ffffff;
      transform: translate(0, -50%);
      transition: transform 150ms ease, background 150ms ease;
      box-shadow: 0 1px 2px rgba(15, 23, 42, 0.25);
    }
    .sdp-switch input:checked + .sdp-switch-track {
      background: #2563eb;
      border-color: #2563eb;
    }
    .sdp-switch input:checked + .sdp-switch-track .sdp-switch-thumb {
      transform: translate(16px, -50%);
    }
    .sdp-switch input:focus-visible + .sdp-switch-track {
      outline: 2px solid var(--focus);
      outline-offset: 2px;
    }
    .sdp-switch input:disabled ~ .sdp-switch-track {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* ===== Upload-Komponente (D4: vereinheitlichte Upload-UI) =====
       Wird vom macros/uploader.html und static/uploader.js verwendet.
       Stylt Dropzone, Item-Liste mit Status, Progress-Bars konsistent. */
    .upload-dropzone {
      border: 2px dashed var(--border);
      border-radius: 1rem;
      padding: 2rem;
      text-align: center;
      transition: border-color 120ms ease, background 120ms ease;
      cursor: pointer;
      background: transparent;
    }
    .upload-dropzone:hover,
    .upload-dropzone:focus-within {
      border-color: var(--focus);
      background: var(--focus-soft);
    }
    .upload-dropzone.is-dragover {
      border-color: var(--focus);
      background: var(--focus-soft);
    }
    .upload-dropzone__hint {
      color: var(--muted);
      font-size: 0.875rem;
      margin: 0;
    }
    .upload-dropzone__sub {
      color: var(--muted);
      font-size: 0.75rem;
      margin: 0.25rem 0 0;
    }
    .upload-status {
      list-style: none;
      padding: 0;
      margin: 0.75rem 0 0;
      display: flex;
      flex-direction: column;
      gap: 0.5rem;
    }
    .upload-item {
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 0.625rem 0.75rem;
      background: var(--surface);
    }
    .upload-item__row {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      justify-content: space-between;
    }
    .upload-item__name {
      font-size: 0.8125rem;
      color: var(--text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      flex: 1 1 auto;
      min-width: 0;
    }
    .upload-item__size {
      font-size: 0.75rem;
      color: var(--muted);
      flex-shrink: 0;
    }
    .upload-item__remove {
      background: transparent;
      border: none;
      color: var(--muted);
      cursor: pointer;
      font-size: 1.125rem;
      line-height: 1;
      padding: 0.125rem 0.375rem;
      border-radius: 0.25rem;
    }
    .upload-item__remove:hover { color: #dc2626; }
    .upload-item__status {
      font-size: 0.75rem;
      color: var(--muted);
      margin-top: 0.25rem;
    }
    .upload-item__progress {
      height: 4px;
      background: var(--focus-soft);
      border-radius: 999px;
      overflow: hidden;
      margin-top: 0.375rem;
    }
    .upload-item__progress-fill {
      height: 100%;
      width: 0%;
      background: var(--primary);
      transition: width 150ms ease;
    }
    .upload-item--done .upload-item__progress-fill { background: #16a34a; }
    .upload-item--error .upload-item__progress-fill { background: #dc2626; }
    .upload-item--error .upload-item__status { color: #dc2626; }
    .upload-item--done .upload-item__status { color: #16a34a; }
    /* Bei "done" und "pending" wird der Progressbalken ausgeblendet (visuelles Rauschen). */
    .upload-item--done .upload-item__progress,
    .upload-item--pending .upload-item__progress { display: none; }

    /* ===== Command-Palette (D3): globale Befehlssuche, Cmd/Strg+K ===== */
    .cmd-palette-panel {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
      box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.45), 0 8px 24px -10px rgba(0, 0, 0, 0.25);
      overflow: hidden;
    }
    .cmd-palette-search {
      display: flex;
      align-items: center;
      gap: 0.625rem;
      padding: 0.875rem 1rem;
      border-bottom: 1px solid var(--border);
    }
    .cmd-palette-search-icon {
      width: 1.125rem;
      height: 1.125rem;
      color: var(--muted);
      flex-shrink: 0;
    }
    .cmd-palette-input {
      flex: 1;
      border: none;
      outline: none;
      background: transparent;
      color: var(--text);
      font-size: 1rem;
      padding: 0;
      min-width: 0;
    }
    .cmd-palette-input::placeholder { color: var(--muted); opacity: 0.7; }
    /* Gesperrt, solange eine Rückfrage offen ist: dort steht ein eigenes
       Antwortfeld, und getippt wird nur noch darin. Sichtbar stumm, damit man
       nicht ins Leere tippt. */
    .cmd-palette-input:disabled { opacity: 0.45; cursor: not-allowed; }
    .cmd-palette-mic {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      border-radius: 9999px;
      border: 1px solid var(--border);
      background: transparent;
      color: var(--muted);
      flex-shrink: 0;
      cursor: pointer;
      transition: background 120ms ease, color 120ms ease;
    }
    .cmd-palette-mic:hover, .cmd-palette-mic:focus-visible { background: var(--focus-soft); color: var(--text); }
    .cmd-palette-mic svg { width: 1.125rem; height: 1.125rem; }
    .cmd-palette-hint {
      font-size: 0.6875rem;
      color: var(--muted);
      border: 1px solid var(--border);
      border-radius: 0.25rem;
      padding: 0.0625rem 0.375rem;
      font-family: inherit;
      flex-shrink: 0;
    }
    /* Dezenter Schliessen-Knopf oben in der Suchzeile — vor allem fuer Touch,
       wo weder Esc noch Strg/Cmd+K zur Verfuegung stehen. */
    .cmd-palette-close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.5rem;
      height: 1.5rem;
      flex-shrink: 0;
      border: none;
      background: transparent;
      color: var(--muted);
      border-radius: 9999px;
      opacity: 0.55;
      cursor: pointer;
      transition: opacity 120ms ease, background 120ms ease, color 120ms ease;
    }
    .cmd-palette-close:hover,
    .cmd-palette-close:focus-visible {
      opacity: 1;
      background: var(--focus-soft);
      color: var(--text);
    }
    .cmd-palette-close svg { width: 0.8125rem; height: 0.8125rem; }
    .cmd-palette-list {
      list-style: none;
      margin: 0;
      padding: 0.375rem;
      max-height: 50vh;
      overflow-y: auto;
    }
    .cmd-palette-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 0.75rem;
      padding: 0.5rem 0.75rem;
      border-radius: 0.5rem;
      cursor: pointer;
      transition: background 100ms ease;
    }
    .cmd-palette-item--active,
    .cmd-palette-item:hover {
      background: var(--cmd-item-hover);
    }
    .cmd-palette-item__main {
      display: flex;
      align-items: baseline;
      gap: 0.5rem;
      min-width: 0;
      flex: 1 1 auto;
    }
    .cmd-palette-item__label {
      color: var(--text);
      font-size: 0.875rem;
      font-weight: 500;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* Die Gruppe nimmt nur den REST der Zeile und kürzt darin mit „…" — der Name
       kürzt erst, wenn er allein zu breit ist. Mit `flex-shrink: 0` schob eine
       lange Gruppe („Wissensartikel · Kategorie/…", „Termin · Mi, 07.10.2026,
       15:00 Uhr") den Namen auf dem Telefon auf null Breite, und die Markierung
       scrollte die Liste waagerecht. Basis 0 statt hohem Schrumpf-Faktor: siehe
       cmd-palette-fragen.md (Beispielsatz auf dem Telefon). */
    .cmd-palette-item__group {
      color: var(--muted);
      font-size: 0.75rem;
      flex: 1 1 0;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* Erster Eintrag: Volltextsuche im Schulwissen — gesamtes Label kursiv */
    .cmd-palette-search-label {
      font-style: italic;
      color: var(--muted);
      white-space: normal;
    }
    /* Suchbegriff innerhalb des Labels — fett + kursiv */
    .cmd-palette-search-term {
      font-weight: 700;
      font-style: italic;
      color: var(--text);
    }
    /* Antwort- und Auswahlkarten der Aktionen. Bewusst dieselbe Bildsprache wie
       die Trefferliste darunter: gleiche Zeilenhoehe, gleicher Hover, gleiche
       Muted-Farbe — die Karte soll wie ein Teil der Liste wirken, nicht wie ein
       eingeklebter Dialog. */
    .cmd-palette-answer {
      background: var(--cmd-answer-bg);
      border-bottom: 1px solid var(--border);
      max-height: 22rem;
      overflow-y: auto;
    }
    .cmd-palette-answer__card { padding: 0.625rem 0.5rem 0.75rem; }
    .cmd-palette-answer__kicker {
      padding: 0 0.25rem;
      font-size: 0.75rem;
      font-weight: 600;
      color: var(--muted);
      letter-spacing: 0.01em;
    }
    .cmd-palette-answer__text,
    .cmd-palette-answer__question {
      margin: 0.125rem 0 0;
      padding: 0 0.25rem;
      font-size: 0.9375rem;
      line-height: 1.45;
      color: var(--text);
    }
    .cmd-palette-answer__question { font-weight: 500; }
    .cmd-palette-answer__list {
      margin: 0.5rem 0 0;
      padding: 0;
      list-style: none;
    }
    .cmd-palette-answer__list > li,
    .cmd-palette-answer__line {
      display: flex;
      gap: 0.5rem;
      padding: 0.3125rem 0.75rem;
      border-radius: 0.5rem;
      font-size: 0.8125rem;
      color: var(--muted);
    }
    /* Zebra statt Aufzaehlungspunkten — ruhiger und besser lesbar, wenn jede
       Zeile ein „Montag: …" ist. */
    .cmd-palette-answer__list > li:nth-child(odd) { background: var(--focus-soft); }
    .cmd-palette-answer__note {
      margin-top: 0.5rem;
      padding: 0.375rem 0.75rem;
      border-radius: 0.5rem;
      background: var(--focus-soft);
      font-size: 0.8125rem;
      color: var(--text);
    }
    .cmd-palette-answer__error { color: #dc2626; }

    /* Auswahl (Kinder, Klassen) — optisch identisch zu .cmd-palette-item, damit
       „welches Kind?" sich wie die Trefferliste bedienen laesst. */
    .cmd-palette-answer__choices {
      margin: 0.375rem 0 0;
      padding: 0;
      list-style: none;
    }
    .cmd-palette-answer__choice {
      display: flex;
      width: 100%;
      align-items: baseline;
      justify-content: space-between;
      gap: 0.75rem;
      padding: 0.5rem 0.75rem;
      border: 0;
      border-radius: 0.5rem;
      background: transparent;
      color: var(--text);
      font-size: 0.875rem;
      font-weight: 500;
      text-align: left;
      cursor: pointer;
      transition: background 100ms ease;
    }
    .cmd-palette-answer__choice:hover,
    .cmd-palette-answer__choice:focus-visible { background: var(--cmd-item-hover); }
    .cmd-palette-answer__choice-name {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .cmd-palette-answer__choice-class {
      flex-shrink: 0;
      font-size: 0.75rem;
      font-weight: 400;
      color: var(--muted);
    }

    /* Rückfrage: eigenes Textfeld unter der Frage (User-Vorgabe 2026-09-18).
       Hier wird die Antwort getippt oder hineindiktiert — die Suchzeile ist so
       lange gesperrt. */
    .cmd-palette-answer__reply {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.375rem;
      margin-top: 0.5rem;
      padding: 0 0.25rem;
    }
    .cmd-palette-answer__input {
      flex: 1 1 9rem;
      min-width: 0;
      padding: 0.3125rem 0.625rem;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--surface);
      color: var(--text);
      font-size: 0.875rem;
      outline: none;
    }
    .cmd-palette-answer__input:focus {
      border-color: var(--muted);
      box-shadow: 0 0 0 3px var(--focus-soft);
    }
    .cmd-palette-answer__input::placeholder { color: var(--muted); opacity: 0.7; }

    .cmd-palette-answer__actions {
      display: flex;
      flex-wrap: wrap;
      gap: 0.375rem;
      margin-top: 0.625rem;
      padding: 0 0.25rem;
    }
    .cmd-palette-answer__btn {
      display: inline-flex;
      align-items: center;
      padding: 0.3125rem 0.75rem;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: transparent;
      color: var(--text);
      font-size: 0.8125rem;
      font-weight: 500;
      text-decoration: none;
      cursor: pointer;
      transition: background 100ms ease, border-color 100ms ease;
    }
    .cmd-palette-answer__btn:hover,
    .cmd-palette-answer__btn:focus-visible { background: var(--focus-soft); }
    .cmd-palette-answer__btn--primary {
      border-color: transparent;
      background: var(--focus-soft);
    }
    /* „Trotzdem entlassen" bei der Entlassungsfenster-Warnung — sichtbar anders,
       ohne die ruhige Bildsprache zu verlassen. */
    .cmd-palette-answer__btn--warn {
      border-color: #dc2626;
      color: #dc2626;
    }
    .cmd-palette-answer__btn--warn:hover { background: rgba(220, 38, 38, 0.08); }
    .cmd-palette-answer__btn[disabled] { opacity: 0.5; cursor: default; }
    .cmd-palette-item__example {
      margin-top: 0.125rem;
      font-size: 0.75rem;
      color: var(--muted);
    }
    .cmd-palette-empty {
      padding: 1.5rem 1rem;
      text-align: center;
      color: var(--muted);
      font-size: 0.875rem;
    }
    .cmd-palette-footer {
      display: flex;
      flex-wrap: wrap;
      gap: 0.875rem;
      padding: 0.5rem 0.875rem;
      border-top: 1px solid var(--border);
      font-size: 0.6875rem;
      color: var(--muted);
    }
    .cmd-palette-footer kbd {
      background: var(--focus-soft);
      border: 1px solid var(--border);
      border-radius: 0.25rem;
      padding: 0.0625rem 0.3125rem;
      margin: 0 0.0625rem;
      font-family: inherit;
    }
    /* Trigger-Button im Header — nur sichtbar wenn JS aktiv */
    .cmd-palette-trigger {
      background: transparent;
      border: 1px solid var(--border);
      color: var(--muted);
      border-radius: 0.5rem;
      padding: 0.25rem 0.5rem;
      font-size: 0.75rem;
      display: inline-flex;
      align-items: center;
      gap: 0.375rem;
      cursor: pointer;
      transition: background 120ms ease, color 120ms ease;
    }
    .cmd-palette-trigger:hover { background: var(--focus-soft); color: var(--text); }
    .cmd-palette-trigger kbd {
      background: var(--focus-soft);
      border: 1px solid var(--border);
      border-radius: 0.1875rem;
      padding: 0 0.25rem;
      font-size: 0.625rem;
      font-family: inherit;
    }
    @media (max-width: 640px) {
      .cmd-palette-trigger kbd { display: none; }
      /* Aktions-Vorschlaege auf dem Telefon: der Beispielsatz rueckt HINTER
         die Aktion statt an den rechten Zeilenrand, bleibt einzeilig und
         bekommt bei Platzmangel "…" (User-Vorgabe 2026-09-17).
         Der Haken ist data-action-example — nur Aktionszeilen tragen es, die
         Seiten-/Kinder-Treffer behalten ihr rechtsbuendiges group-Etikett.
         Ohne flex-start schoebe space-between den Satz wieder nach rechts. */
      .cmd-palette-item[data-action-example] {
        justify-content: flex-start;
        align-items: baseline;
      }
      /* Das "…" soll IMMER der Beispielsatz tragen, nie die Aktion. Deshalb
         `flex: 1 1 0` am Satz: seine Basis ist 0, er nimmt also nur den Rest
         der Zeile ein und kuerzt darin — geschrumpft wird nichts, solange die
         Aktion passt. Erst wenn schon die Aktion allein zu breit ist, greift
         deren eigene Ellipse (`flex-shrink: 1` am __main). Ein blosser
         Schrumpf-Faktor am Satz reichte NICHT: Flexbox gewichtet das Schrumpfen
         mit der Inhaltsbreite, also kuerzte bei 390 px auch die Aktion mit
         (gemessen an „Arbeitsblatt erstellen"). */
      .cmd-palette-item[data-action-example] > .cmd-palette-item__main {
        flex: 0 1 auto;
      }
      .cmd-palette-item[data-action-example] > .cmd-palette-item__example {
        flex: 1 1 0;
        min-width: 0;
        margin-top: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }

    /* --- Pull-to-Search: ueber den Seitenanfang hinaus nach oben scrollen laesst
       die Befehlssuche langsam ausfahren. Der Fortschritt steckt in --cmd-peek
       (0 .. 1) und wird von command-palette.js pro Frame gesetzt. Waehrend des
       Ausfahrens bleibt die Seite bedienbar (pointer-events: none) — erst beim
       vollstaendigen Oeffnen wird regulaer geoeffnet. Die Suchzeile bekommt
       den Fokus erst dann und nur an Maus/Trackpad (openPalette in
       command-palette.js; [data-sdp-no-autofocus] haelt sdpOpenModal heraus).
       --- */
    #cmd-palette-modal.cmd-palette-peeking {
      display: flex !important;
      pointer-events: none;
    }
    #cmd-palette-modal.cmd-palette-peeking [data-cmd-palette-backdrop] {
      opacity: calc(var(--cmd-peek, 0) * 0.8);
    }
    #cmd-palette-modal.cmd-palette-peeking .cmd-palette-panel {
      transform-origin: top center;
      /* 10vh Abstand von oben + eigene Hoehe + 5rem Zugabe: ohne die Zugabe
         steht die Unterkante bei 0 exakt am Viewport-Rand und der Dropshadow
         (0 24px 60px -20px) bleibt als dunkler Streifen sichtbar. */
      transform: translateY(calc((var(--cmd-peek, 0) - 1) * (10vh + 100% + 5rem)))
                 scale(calc(0.94 + 0.06 * var(--cmd-peek, 0)));
      opacity: calc(0.4 + 0.6 * var(--cmd-peek, 0));
    }
    @media (prefers-reduced-motion: reduce) {
      #cmd-palette-modal.cmd-palette-peeking .cmd-palette-panel {
        transform: none;
        opacity: var(--cmd-peek, 0);
      }
    }

    /* ===== Chat-Assistenz (assistent.js): Korb-Zeile in der Befehlssuche +
       Popover-Variante des Modals. Der Vogel setzt die Modifier-Klasse
       `cmd-palette-modal--assistent` VOR SDPCommandPalette.open() und räumt sie
       bei `sdp:cmd-palette-close` wieder ab; Strg/⌘+K, Kopfzeile und Wischgeste
       setzen sie nie. command-palette.js bleibt unangetastet. ===== */
    .sdp-assistent-recent { border-bottom: 1px solid var(--border); }
    .sdp-assistent-recent.hidden { display: none; }
    /* Mit der Trefferliste ausgeblendet, solange eine Karte allein steht
       (assistent.js beobachtet #cmd-palette-list). */
    .sdp-assistent-recent.is-suppressed { display: none; }
    .sdp-assistent-recent__toggle {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      width: 100%;
      padding: 0.625rem 0.875rem;
      background: var(--focus-soft);
      color: var(--text);
      font-size: 0.875rem;
      font-weight: 700;
      border: 0;
      border-radius: 0;
      text-align: left;
      cursor: pointer;
      transition: filter 120ms ease;
    }
    .sdp-assistent-recent__toggle:hover,
    .sdp-assistent-recent__toggle:focus-visible { filter: brightness(0.96); }
    .sdp-assistent-recent__icon { width: 1.1rem; height: 1.1rem; flex-shrink: 0; }
    .sdp-assistent-recent__count {
      min-width: 1.25rem;
      height: 1.25rem;
      padding: 0 0.35rem;
      border-radius: 999px;
      background: var(--primary);
      color: var(--on-primary);
      font-size: 0.7rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }
    .sdp-assistent-recent__chevron {
      margin-left: auto;
      width: 1rem;
      height: 1rem;
      flex-shrink: 0;
      transition: transform 120ms ease;
    }
    .sdp-assistent-recent__toggle[aria-expanded="true"] .sdp-assistent-recent__chevron { transform: rotate(180deg); }
    .sdp-assistent-recent__list[hidden] { display: none; }
    .sdp-assistent-recent__list #sdp-korb-list { max-height: 14rem; }
    /* „Neue Nachrichten" über der Korb-Zeile: dieselbe Zeilenform (Klasse
       .sdp-assistent-recent, auch für Popover-Flex und is-suppressed), aber mit
       dezentem Rot statt Grau. Die Liste baut assistent.js per DOM aus
       GET /api/ui/assistent-neuigkeiten. Etwas niedriger gedeckelt als die
       Korb-Liste, damit im Popover beide aufgeklappt Platz haben. */
    #sdp-assistent-news .sdp-assistent-recent__toggle { background: var(--cmd-news-bg); }
    #sdp-assistent-news .sdp-assistent-recent__count { background: #dc2626; }
    .sdp-assistent-news__list { max-height: min(14rem, 32vh); overflow-y: auto; padding: 0.35rem 0.45rem; }
    .sdp-assistent-news__heading {
      padding: 0.35rem 0.45rem 0.15rem;
      font-size: 0.68rem;
      font-weight: 700;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      color: var(--muted);
    }
    .sdp-assistent-news__item {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      padding: 0.45rem;
      border-radius: 0.5rem;
      color: var(--text);
      text-decoration: none;
      transition: background 120ms ease;
    }
    .sdp-assistent-news__item:hover,
    .sdp-assistent-news__item:focus-visible { background: var(--cmd-news-bg); }
    .sdp-assistent-news__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
    .sdp-assistent-news__title,
    .sdp-assistent-news__sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sdp-assistent-news__title { font-size: 0.82rem; font-weight: 600; }
    .sdp-assistent-news__sub { font-size: 0.7rem; color: var(--muted); }
    .sdp-assistent-news__unread {
      flex-shrink: 0;
      min-width: 1.1rem;
      height: 1.1rem;
      padding: 0 0.3rem;
      border-radius: 999px;
      background: #dc2626;
      color: #fff;
      font-size: 0.65rem;
      font-weight: 700;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }
    .sdp-assistent-news__more {
      display: block;
      padding: 0.3rem 0.45rem 0.4rem;
      font-size: 0.72rem;
      color: var(--muted);
      text-decoration: underline;
      text-underline-offset: 2px;
    }
    .sdp-assistent-news__more:hover { color: var(--text); }
    .sdp-assistent-news__note { padding: 0.45rem; font-size: 0.78rem; color: var(--muted); }
    /* „Mein Tag" (persönlicher Assistent, ki-assistent-mein-tag.md): Tageskarte
       über „Neue Nachrichten" im Ton der Antwortkarten (--cmd-answer-bg), mit
       Zeitleiste. Gebaut von assistent.js aus GET /api/ki-assistent/tag. */
    .sdp-assistent-tag {
      margin: 0.5rem 0.5rem 0.25rem;
      padding: 0.75rem 0.75rem 0.6rem;
      border-radius: var(--radius);
      background: var(--cmd-answer-bg);
      color: var(--text);
      overflow-y: auto;
      max-height: min(26rem, 52vh);
    }
    .sdp-assistent-tag.hidden,
    .sdp-assistent-tag.is-suppressed { display: none; }
    .sdp-mt__kopf { display: flex; align-items: flex-start; gap: 0.5rem; }
    .sdp-mt__kopftext { flex: 1 1 auto; min-width: 0; }
    .sdp-mt__datum { font-size: 0.75rem; color: var(--muted); }
    .sdp-mt__gruss { font-size: 1rem; font-weight: 700; line-height: 1.3; }
    .sdp-mt__wahl {
      flex-shrink: 0;
      display: inline-flex;
      padding: 2px;
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      background: var(--surface);
    }
    .sdp-mt__wahl button {
      border: 0;
      background: transparent;
      color: var(--muted);
      font: inherit;
      font-size: 0.75rem;
      font-weight: 600;
      padding: 0.2rem 0.55rem;
      border-radius: calc(var(--radius-sm) - 2px);
      cursor: pointer;
    }
    .sdp-mt__wahl button[aria-pressed="true"] { background: var(--primary); color: var(--on-primary); }
    .sdp-mt__liste { list-style: none; margin: 0.6rem 0 0; padding: 0; }
    .sdp-mt__eintrag { display: grid; grid-template-columns: 3.1rem 0.75rem minmax(0, 1fr); column-gap: 0.5rem; }
    .sdp-mt__zeit {
      padding-top: 0.45rem;
      text-align: right;
      font-size: 0.75rem;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .sdp-mt__spur { display: flex; flex-direction: column; align-items: center; }
    .sdp-mt__spur::before, .sdp-mt__spur::after { content: ""; width: 2px; background: var(--border); }
    .sdp-mt__spur::before { height: 0.55rem; }
    .sdp-mt__spur::after { flex: 1 1 auto; }
    .sdp-mt__eintrag:first-child .sdp-mt__spur::before,
    .sdp-mt__eintrag:last-child .sdp-mt__spur::after { visibility: hidden; }
    .sdp-mt__punkt {
      width: 0.6rem;
      height: 0.6rem;
      flex-shrink: 0;
      border-radius: 999px;
      border: 2px solid var(--primary-line);
      background: var(--surface);
    }
    .sdp-mt__inhalt { min-width: 0; padding: 0.25rem 0.4rem 0.5rem; border-radius: var(--radius-sm); }
    .sdp-mt__zeile { display: flex; align-items: flex-start; gap: 0.35rem; }
    .sdp-mt__titelblock { flex: 1 1 auto; min-width: 0; }
    .sdp-mt__titel { font-size: 0.85rem; font-weight: 700; overflow-wrap: anywhere; }
    .sdp-mt__chip {
      display: inline-block;
      margin-left: 0.3rem;
      padding: 0 0.4rem;
      border-radius: 999px;
      font-size: 0.65rem;
      font-weight: 700;
      vertical-align: 0.1em;
      background: var(--info-soft);
      color: var(--info);
    }
    .sdp-mt__chip--neutral { background: var(--neutral-soft); color: var(--neutral); }
    .sdp-mt__meta { font-size: 0.75rem; color: var(--muted); overflow-wrap: anywhere; }
    .sdp-mt__meta strong { color: var(--text); font-weight: 600; }
    .sdp-mt__fehlt { font-size: 0.75rem; color: #6d28d9; }
    html[data-theme="dark"] .sdp-mt__fehlt { color: #c4b5fd; }
    .sdp-mt__link { font-size: 0.75rem; font-weight: 600; color: var(--primary-line); text-decoration: underline; text-underline-offset: 2px; }
    .sdp-mt__knopf {
      flex-shrink: 0;
      width: 1.6rem;
      height: 1.6rem;
      padding: 0;
      border: 0;
      border-radius: var(--radius-sm);
      background: transparent;
      color: var(--muted);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
    }
    .sdp-mt__knopf:hover, .sdp-mt__knopf:focus-visible, .sdp-mt__knopf[aria-expanded="true"] { background: var(--focus-soft); color: var(--text); }
    .sdp-mt__knopf svg { width: 0.95rem; height: 0.95rem; }
    .sdp-mt__warum {
      margin-top: 0.3rem;
      padding: 0.35rem 0.5rem;
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      background: var(--surface);
      font-size: 0.72rem;
      color: var(--muted);
    }
    .sdp-mt__warum[hidden] { display: none; }
    .sdp-mt__eintrag.is-naechstes .sdp-mt__inhalt { background: var(--cmd-item-hover); }
    .sdp-mt__eintrag.is-naechstes .sdp-mt__zeit { color: var(--info); }
    .sdp-mt__eintrag.is-naechstes .sdp-mt__punkt { background: var(--info); border-color: var(--info); }
    .sdp-mt__eintrag.is-vergangen { opacity: 0.6; }
    .sdp-mt__eintrag.is-vergangen .sdp-mt__punkt { border-color: var(--border); }
    .sdp-mt__hinweis, .sdp-mt__rueck { margin-top: 0.5rem; font-size: 0.78rem; color: var(--muted); }
    /* Gedächtnis (Etappe A5): Einladung und Durchsicht in der Karte. */
    /* Stimmung des Tages (A6b) und Tipp des Tages (A6). */
    .sdp-mt__stimmung { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; margin-top: 0.45rem; font-size: 0.78rem; color: var(--muted); }
    .sdp-mt__stimmung-reihe { display: inline-flex; gap: 0.15rem; }
    .sdp-mt__stimmung.is-zu { margin-top: 0.3rem; gap: 0.35rem; }
    .sdp-mt__stimmung-wahl { display: inline-flex; align-items: center; gap: 0.3rem; }
    .sdp-mt__stimmung-emoji { font-size: 0.95rem; line-height: 1; }
    .sdp-mt__stimmung-aendern { border: 0; background: none; padding: 0; color: var(--muted); font-size: 0.72rem; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
    .sdp-mt__gesicht { border: 1px solid transparent; background: none; border-radius: 999px; width: 1.9rem; height: 1.9rem; font-size: 1.05rem; line-height: 1; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; filter: grayscale(0.35); }
    @media (hover: hover) { .sdp-mt__gesicht:hover { background: var(--focus-soft); filter: none; } }
    .sdp-mt__gesicht[aria-pressed="true"] { border-color: var(--primary-line); background: var(--primary-soft); filter: none; }
    @media (pointer: coarse) { .sdp-mt__gesicht { width: 2.5rem; height: 2.5rem; } }
    .sdp-mt__ruhig { margin-top: 0.5rem; padding: 0.45rem 0.6rem; border-radius: var(--radius-sm); background: var(--ok-soft); color: var(--text); font-size: 0.8rem; }
    .sdp-mt__tipp { margin-top: 0.5rem; padding: 0.5rem 0.6rem; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface); font-size: 0.8rem; }
    .sdp-mt__tipp-kopf { display: flex; align-items: center; gap: 0.4rem; }
    .sdp-mt__tipp-kopf > button:last-child { margin-left: auto; }
    .sdp-mt__tipp-ki { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.04em; padding: 0.05rem 0.35rem; border-radius: var(--radius-sm); background: var(--info-soft); color: var(--info); }
    .sdp-mt__tipp-text { margin: 0.25rem 0 0; color: var(--text); }
    .sdp-mt__tipp-woher { border: 0; background: none; padding: 0; margin-top: 0.25rem; color: var(--muted); font-size: 0.72rem; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
    .sdp-mt__tipp-quellen { margin-top: 0.3rem; font-size: 0.72rem; color: var(--muted); }
    .sdp-mt__tipp-quellen ul { margin: 0.1rem 0 0.3rem 1rem; list-style: disc; }
    .sdp-mt__tipp-quelle { font-weight: 600; color: var(--text); }
    .sdp-mt__gd { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-top: 0.5rem; padding: 0.45rem 0.55rem; border-radius: var(--radius-sm); background: var(--surface); border: 1px solid var(--border); font-size: 0.78rem; }
    .sdp-mt__gd-text { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; }
    .sdp-mt__gd-los, .sdp-mt__gd-knoepfe button {
      font: inherit; font-size: 0.75rem; font-weight: 600; border: 0; border-radius: var(--radius-sm);
      padding: 0.2rem 0.6rem; background: var(--primary); color: var(--on-primary); cursor: pointer;
    }
    .sdp-mt__gd-knoepfe { display: flex; gap: 0.3rem; }
    .sdp-mt__gd-knoepfe button.is-leise { background: transparent; color: var(--muted); border: 1px solid var(--border); }
    /* Wochenausblick (Etappe A4). */
    .sdp-mt__voll { margin: 0.5rem 0 0; padding: 0.3rem 0.55rem; border-radius: var(--radius-sm); background: var(--warn-soft); color: var(--warn); font-size: 0.75rem; font-weight: 600; }
    .sdp-mt__woche { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-direction: column; }
    .sdp-mt__wtag { display: grid; grid-template-columns: 5.2rem minmax(0, 1fr); gap: 0.5rem; padding: 0.4rem 0.2rem; border-top: 1px solid var(--border); }
    .sdp-mt__wtag:first-child { border-top: 0; }
    .sdp-mt__wtag-label { font-size: 0.78rem; font-weight: 700; }
    .sdp-mt__wtag.is-heute .sdp-mt__wtag-label { color: var(--info); }
    .sdp-mt__wtag.is-vergangen { opacity: 0.6; }
    .sdp-mt__wtag.is-voll .sdp-mt__wtag-label { color: var(--warn); }
    .sdp-mt__wtag-inhalt { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
    .sdp-mt__wtag-inhalt .sdp-mt__frei { margin-top: 0; align-self: flex-start; }
    .sdp-mt__wtermin { font-size: 0.75rem; display: flex; gap: 0.4rem; overflow-wrap: anywhere; }
    .sdp-mt__wzeit { flex-shrink: 0; font-weight: 700; font-variant-numeric: tabular-nums; }
    .sdp-mt__wthemen { margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.35rem; }
    /* Stundenvorbereitung (Etappe A3): Knöpfe an der Stunde, Thema nachtragen. */
    .sdp-mt__aktionen { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.35rem; }
    .sdp-mt__aktion {
      font-size: 0.72rem;
      font-weight: 600;
      text-decoration: none;
      color: var(--primary-line);
      background: var(--surface);
      border: 1px solid var(--input-border);
      border-radius: var(--radius-sm);
      padding: 0.15rem 0.5rem;
    }
    .sdp-mt__aktion:first-child { background: var(--primary); color: var(--on-primary); border-color: transparent; }
    .sdp-mt__aktion:hover, .sdp-mt__aktion:focus-visible { filter: brightness(0.96); }
    .sdp-mt__eintragen {
      font: inherit;
      font-size: 0.72rem;
      font-weight: 600;
      color: #6d28d9;
      background: var(--surface);
      border: 1px dashed #a78bfa;
      border-radius: var(--radius-sm);
      padding: 0.05rem 0.45rem;
      cursor: pointer;
    }
    html[data-theme="dark"] .sdp-mt__eintragen { color: #c4b5fd; }
    .sdp-mt__thema-edit {
      margin-top: 0.4rem;
      padding: 0.5rem;
      border: 1px solid var(--input-border);
      border-radius: var(--radius-sm);
      background: var(--surface);
      display: flex;
      flex-direction: column;
      gap: 0.4rem;
    }
    .sdp-mt__thema-edit[hidden] { display: none; }
    .sdp-mt__eintrag > .sdp-mt__thema-edit { grid-column: 1 / -1; margin: 0.1rem 0 0.6rem; }
    .sdp-mt__thema-label { font-size: 0.75rem; font-weight: 700; }
    .sdp-mt__thema-zeile { display: flex; flex-wrap: wrap; gap: 0.3rem; }
    .sdp-mt__thema-feld {
      flex: 1 1 9rem;
      min-width: 0;
      font: inherit;
      font-size: 0.8rem;
      padding: 0.3rem 0.5rem;
      border: 1px solid var(--input-border);
      border-radius: var(--radius-sm);
      background: var(--input-bg);
      color: var(--text);
    }
    .sdp-mt__thema-zeile button {
      font: inherit;
      font-size: 0.75rem;
      font-weight: 600;
      border: 0;
      border-radius: var(--radius-sm);
      padding: 0.25rem 0.6rem;
      background: var(--primary);
      color: var(--on-primary);
      cursor: pointer;
    }
    .sdp-mt__thema-zeile button.is-leise { background: transparent; color: var(--muted); border: 1px solid var(--border); }
    .sdp-mt__vorschlaege { display: flex; flex-wrap: wrap; gap: 0.3rem; }
    .sdp-mt__vorschlag {
      display: inline-flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 0.05rem;
      font: inherit;
      text-align: left;
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      background: var(--surface);
      color: var(--text);
      padding: 0.2rem 0.5rem;
      cursor: pointer;
    }
    .sdp-mt__vorschlag:hover, .sdp-mt__vorschlag:focus-visible { background: var(--focus-soft); }
    .sdp-mt__vorschlag-text { font-size: 0.75rem; font-weight: 600; }
    .sdp-mt__vorschlag-quelle { font-size: 0.65rem; color: var(--muted); }
    .sdp-mt__fehler { font-size: 0.72rem; color: var(--danger); margin: 0; }
    .sdp-mt__fehler:empty { display: none; }
    /* Fristen (Etappe A2): aufklappbare Zeile unter der Zeitleiste. */
    .sdp-mt__fristen { margin-top: 0.5rem; }
    .sdp-mt__fristen-kopf {
      display: inline-flex;
      align-items: center;
      gap: 0.3rem;
      padding: 0.2rem 0.6rem;
      border: 0;
      border-radius: 999px;
      background: var(--neutral-soft);
      color: var(--neutral);
      font: inherit;
      font-size: 0.75rem;
      font-weight: 700;
      cursor: pointer;
    }
    .sdp-mt__fristen-kopf.is-ueberfaellig { background: var(--warn-soft); color: var(--warn); }
    /* „Neu für dich" (A7): Info-Ton statt Warnfarbe — eine Einladung, keine Frist. */
    .sdp-mt__klapp--neu { margin-top: 0.3rem; }
    .sdp-mt__klapp--neu .sdp-mt__fristen-kopf { background: var(--info-soft); color: var(--info); }
    /* Module und AGs (A8c): Info-Ton wie „Neu für dich", eigener Abstand. */
    .sdp-mt__klapp--modul { margin-top: 0.3rem; }
    .sdp-mt__klapp--modul .sdp-mt__fristen-kopf { background: var(--surface-muted); color: var(--text); }
    /* Klassenleitung (A8b): Ok-Ton. */
    .sdp-mt__klapp--klasse { margin-top: 0.3rem; }
    .sdp-mt__klapp--klasse .sdp-mt__fristen-kopf { background: var(--ok-soft); color: var(--ok); }
    /* Gremien vor der Sitzung (A8a): Primär-Ton. */
    .sdp-mt__klapp--gremium { margin-top: 0.3rem; }
    .sdp-mt__klapp--gremium .sdp-mt__fristen-kopf { background: var(--primary-soft); color: var(--primary-line); }
    /* Wissenslücken (A7b, nur Administration/Schulleitung): neutral. */
    .sdp-mt__klapp--luecke { margin-top: 0.3rem; }
    .sdp-mt__klapp--luecke .sdp-mt__fristen-kopf { background: var(--neutral-soft); color: var(--text); }
    .sdp-mt__fristen-kopf svg { width: 0.85rem; height: 0.85rem; transition: transform 120ms ease; }
    .sdp-mt__fristen-kopf[aria-expanded="true"] svg { transform: rotate(180deg); }
    .sdp-mt__fristen-liste { list-style: none; margin: 0.4rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
    .sdp-mt__fristen-liste[hidden] { display: none; }
    .sdp-mt__frist { padding: 0.35rem 0.45rem; border-radius: var(--radius-sm); background: var(--surface); border-left: 3px solid var(--border); }
    .sdp-mt__frist.is-ueberfaellig { border-left-color: var(--warn); }
    .sdp-mt__fristlink { color: var(--text); text-decoration: none; }
    .sdp-mt__fristlink:hover, .sdp-mt__fristlink:focus-visible { text-decoration: underline; text-underline-offset: 2px; }
    .sdp-mt__bestaetigen { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-top: 0.35rem; font-size: 0.75rem; color: var(--muted); }
    .sdp-mt__bestaetigen[hidden] { display: none; }
    .sdp-mt__bestaetigen button {
      font: inherit;
      font-size: 0.75rem;
      font-weight: 600;
      border: 0;
      border-radius: var(--radius-sm);
      padding: 0.15rem 0.55rem;
      background: var(--primary);
      color: var(--on-primary);
      cursor: pointer;
    }
    .sdp-mt__bestaetigen button.is-leise { background: transparent; color: var(--muted); border: 1px solid var(--border); }
    @media (prefers-reduced-motion: reduce) { .sdp-mt__fristen-kopf svg { transition: none; } }
    .sdp-mt__frei {
      display: inline-block;
      margin-top: 0.5rem;
      padding: 0.1rem 0.55rem;
      border-radius: 999px;
      background: var(--ok-soft);
      color: var(--ok);
      font-size: 0.75rem;
      font-weight: 700;
    }
    .sdp-mt__rueck { display: flex; align-items: center; gap: 0.5rem; }
    .sdp-mt__rueck button, .sdp-mt__fuss button {
      font: inherit;
      font-size: 0.75rem;
      font-weight: 600;
      border: 1px solid var(--border);
      background: var(--surface);
      color: var(--primary-line);
      border-radius: var(--radius-sm);
      padding: 0.15rem 0.55rem;
      cursor: pointer;
    }
    .sdp-mt__rueck button { margin-left: auto; }
    .sdp-mt__fuss { display: flex; justify-content: flex-end; margin-top: 0.4rem; }
    .sdp-mt__fuss button { border: 0; background: none; color: var(--muted); text-decoration: underline; text-underline-offset: 2px; padding: 0; }
    #sdp-assistent-einstellungen + #sdp-assistent-hide { margin-left: 0.9rem; }
    #cmd-palette-modal.cmd-palette-modal--assistent .sdp-assistent-tag { flex: 0 1 auto; min-height: 0; }
    /* Steht die Karte, gibt im Popover zuerst die Aktionsliste nach (bis auf
       gut zwei Zeilen) — sonst schrumpften beide gleich und am Telefon blieb
       von der Karte nur ein Eintrag (im Browser gemessen: 200 px bei 390 px). */
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-panel:has(.sdp-assistent-tag:not(.hidden):not(.is-suppressed)) .cmd-palette-list {
      flex-shrink: 1000;
      min-height: 5.5rem;
    }
    @media (max-width: 640px) {
      .sdp-mt__knopf { width: 2.25rem; height: 2.25rem; }
    }
    @media (prefers-reduced-motion: reduce) {
      .sdp-assistent-news__item { transition: none; }
    }
    .sdp-assistent-hide {
      display: none;
      margin-left: auto;
      background: none;
      border: 0;
      padding: 0;
      color: var(--muted);
      text-decoration: underline;
      text-underline-offset: 2px;
      cursor: pointer;
      font: inherit;
    }
    .sdp-assistent-hide:hover, .sdp-assistent-hide:focus-visible { color: var(--text); }
    /* Der Ausblenden-Knopf haengt am Oeffnungsweg (via Vogel), nicht an der
       Popover-Klasse — mobil ohne Popover (Vogel oben) muss er trotzdem da sein. */
    #cmd-palette-modal[data-assistent-open] .sdp-assistent-hide { display: inline; }
    @media (prefers-reduced-motion: reduce) {
      .sdp-assistent-recent__chevron { transition: none; }
    }
    /* Popover am Vogel. Die Innenabstände kommen als px-Variablen aus assistent.js
       (Lage des Vogels); `#id.class` schlaegt die Tailwind-Utilities des Modals ohne
       !important. KEIN `display` in dieser Regel — `.hidden` muss weiter gewinnen.
       Ob die Klasse ueberhaupt gesetzt wird, entscheidet assistent.js: am
       Schreibtisch immer, mobil NUR, wenn der Vogel im unteren Drittel steht
       (User-Vorgabe 2026-09-22) — sonst bleibt es das Modal von oben. */
    #cmd-palette-modal.cmd-palette-modal--assistent {
      padding: var(--sdp-assistent-pad-top, 1rem) var(--sdp-assistent-pad-right, 1rem)
               var(--sdp-assistent-pad-bottom, 5rem) var(--sdp-assistent-pad-left, 1rem);
      align-items: flex-end;
      justify-content: flex-end;
    }
    #cmd-palette-modal.cmd-palette-modal--assistent[data-assistent-vpos="top"] { align-items: flex-start; }
    #cmd-palette-modal.cmd-palette-modal--assistent[data-assistent-side="left"] { justify-content: flex-start; }
    /* Der Backdrop bleibt auch im Popover abgedunkelt (User-Vorgabe 2026-09-22) —
       bewusst KEINE Regel dafuer. (Wer ihn je aufhellen will: er traegt ein
       Inline-background, geht also nur per opacity, nicht per background.) */
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-panel {
      max-width: 26rem;
      max-height: 100%;
      display: flex;
      flex-direction: column;
    }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-search,
    #cmd-palette-modal.cmd-palette-modal--assistent .sdp-assistent-recent,
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-empty,
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-footer { flex: 0 0 auto; }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-answer { flex: 0 1 auto; min-height: 0; }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-list { flex: 1 1 auto; min-height: 0; max-height: none; }
    /* Das Popover ist so schmal wie ein Telefon: fuer Aktionszeilen gilt deshalb
       dieselbe Regel wie unter 640 px — der Beispielsatz steht HINTER der Aktion
       und kuerzt sich mit "…", die Aktion nie (im Browser gesehen: mit der
       rechtsbuendigen Schreibtisch-Fassung wurde "Hinweis zu ei…" daraus). */
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item[data-action-example] {
      justify-content: flex-start;
      align-items: baseline;
    }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item[data-action-example] > .cmd-palette-item__main {
      flex: 0 1 auto;
    }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item[data-action-example] > .cmd-palette-item__example {
      flex: 1 1 0;
      min-width: 0;
      margin-top: 0;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    /* Das Fenster geht aus dem Vogel auf: kurz aus seiner Ecke heraus wachsen. */
    @keyframes sdp-assistent-aufgehen {
      from { opacity: 0; transform: translateY(12px) scale(0.92); }
      to { opacity: 1; transform: none; }
    }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-panel {
      transform-origin: bottom right;
      animation: sdp-assistent-aufgehen 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
    }
    #cmd-palette-modal.cmd-palette-modal--assistent[data-assistent-side="left"] .cmd-palette-panel { transform-origin: bottom left; }
    #cmd-palette-modal.cmd-palette-modal--assistent[data-assistent-vpos="top"] .cmd-palette-panel { transform-origin: top right; }
    #cmd-palette-modal.cmd-palette-modal--assistent[data-assistent-vpos="top"][data-assistent-side="left"] .cmd-palette-panel { transform-origin: top left; }
    @media (prefers-reduced-motion: reduce) {
      #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-panel { animation: none; }
    }
    /* Kompakte Liste der Funktionen und Seiten im Fenster des Vogels
       (User-Vorgabe 2026-11-03): kleinere Schrift, weniger Zeilenhöhe — so
       steht mehr unter „Mein Tag" im Bild. Strg/⌘+K bleibt wie gehabt. */
    /* Suchfeld im Fenster des Vogels: kleinere Schrift, Luft im Feld (der Kasten
       ist der Fokusrahmen — vorher klebte der Text daran). Auf Touch hält die
       app-weite iOS-Zoom-Regel die Schrift bei mindestens 1rem; dort wirkt nur
       der Innenabstand. */
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-input {
      font-size: 0.875rem;
      padding: 0.45rem 0.7rem;
      border-radius: var(--radius-sm);
    }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item { padding: 0.3rem 0.6rem; gap: 0.5rem; }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item__label { font-size: 0.8125rem; }
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item__group,
    #cmd-palette-modal.cmd-palette-modal--assistent .cmd-palette-item__example { font-size: 0.7rem; }
    /* Mobil (der Vogel steht dann im unteren Drittel): das Fenster reicht vom
       Vogel bis kurz unter die Kopfzeile (User-Vorgabe 2026-11-03, vorher auf 70vh
       gedeckelt) — die Kopfzeile bleibt sichtbar. `--sdp-header-height` misst
       base.html live; ohne Kopfzeile (Kiosk, Vollbildseiten) ein fester Rand. */
    @media (max-width: 640px) {
      #cmd-palette-modal.cmd-palette-modal--assistent:not([data-assistent-vpos="top"]) {
        padding-top: calc(var(--sdp-header-height, 0px) + 0.5rem);
      }
      #cmd-palette-modal.cmd-palette-modal--assistent:not([data-assistent-vpos="top"]) .cmd-palette-panel { height: 100%; max-height: 100%; }
    }
    /* Suchzeile UNTEN im Fenster des Vogels (User 2026-11-06): am Telefon mit
       dem Daumen erreichbar. Nur per `order` in der Flex-Spalte — das Markup
       (und damit command-palette.js im SW-Precache) bleibt unverändert. Steht
       das Fenster UNTER dem Vogel (Vogel oben, vpos=top), bleibt die Suchzeile
       oben am Vogel. Fußzeile direkt darüber. */
    #cmd-palette-modal.cmd-palette-modal--assistent:not([data-assistent-vpos="top"]) .cmd-palette-footer { order: 1; }
    #cmd-palette-modal.cmd-palette-modal--assistent:not([data-assistent-vpos="top"]) .cmd-palette-search {
      order: 2;
      border-bottom: 0;
      border-top: 1px solid var(--border);
    }
    /* Im Fenster des Vogels keine Tastatur-Hinweise (↑↓ navigieren, Enter
       öffnen, Strg+Enter in neuem Tab; User 2026-11-06) — die Fußzeile trägt dort
       nur noch „Mein Assistent" und das Ausblenden. Gilt für jeden Öffnungsweg
       über den Vogel, auch ohne Popover. */
    #cmd-palette-modal[data-assistent-open] .cmd-palette-footer__taste { display: none; }
    /* „Zuletzt erstellte Inhalte" (und die gleich gebaute Zeile „Neue
       Nachrichten") in der Schriftgröße der Aktionen im Fenster des Vogels. */
    #cmd-palette-modal.cmd-palette-modal--assistent .sdp-assistent-recent__toggle { font-size: 0.8125rem; }
    /* „Beispiele möglicher Aktionen:" über der Aktionsliste — nur über den
       Vogel geöffnet, ohne Suchtext, solange die Liste sichtbar ist und mit
       einer Aktion beginnt (ohne Eingabe stehen die Aktionen oben). */
    .sdp-assistent-aktionen-titel {
      display: none;
      flex: 0 0 auto;
      padding: 0.6rem 0.975rem 0.1rem;
      font-size: 0.75rem;
      font-weight: 600;
      color: var(--muted);
    }
    #cmd-palette-modal[data-assistent-open] .cmd-palette-panel:has(#cmd-palette-input:placeholder-shown):has(#cmd-palette-list:not(.hidden) > .cmd-palette-item[data-action-key]:first-child) .sdp-assistent-aktionen-titel {
      display: block;
    }

    /* ===== Globales Toast-System (B4) =====
       EINE feste Stelle (Optik-Tokens, Phase 4): Telefon unten mittig über der
       Safe-Area, ab 641 px unten rechts ÜBER dem Assistent-Vogel (Vogel:
       rechts 1rem, unten 1rem + Safe-Area, 3.1rem hoch). toast.js zeigt nie
       zwei gleichzeitig — ein neuer ersetzt den alten. Farben aus den
       Status-Tokens. */
    .sdp-toast-container {
      position: fixed;
      right: 1rem;
      bottom: calc(4.85rem + env(safe-area-inset-bottom, 0px));
      /* Über allen Fenstern (Blätter 50, Vollbild-Fenster bis 1210). */
      z-index: 1300;
      display: flex;
      flex-direction: column;
      gap: 0.5rem;
      max-width: calc(100vw - 2rem);
      pointer-events: none;
    }
    @media (max-width: 640px) {
      .sdp-toast-container {
        right: auto;
        left: 50%;
        /* Über der Daumen-Leiste (--sdp-bnav-h, sonst 0). */
        bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px) + var(--sdp-bnav-h, 0px));
        transform: translateX(-50%);
        width: min(24rem, calc(100vw - 1.5rem));
        max-width: none;
      }
    }
    .sdp-toast {
      pointer-events: auto;
      display: flex;
      align-items: center;
      gap: 0.625rem;
      min-width: 16rem;
      max-width: 24rem;
      padding: 0.625rem 0.75rem 0.625rem 0.75rem;
      border-radius: var(--radius);
      background: var(--surface);
      color: var(--text);
      border: 1px solid var(--border);
      box-shadow: 0 12px 28px -10px rgba(0, 0, 0, 0.35), 0 4px 12px -4px rgba(0, 0, 0, 0.18);
      font-size: 0.875rem;
      line-height: 1.4;
      opacity: 0;
      transform: translateY(8px);
      transition: opacity 200ms ease, transform 200ms ease;
    }
    @media (max-width: 640px) {
      .sdp-toast { min-width: 0; max-width: none; }
    }
    .sdp-toast.is-visible {
      opacity: 1;
      transform: translateY(0);
    }
    .sdp-toast.is-leaving {
      opacity: 0;
      transform: translateY(8px);
    }
    .sdp-toast__icon {
      flex-shrink: 0;
      width: 1.125rem;
      height: 1.125rem;
    }
    .sdp-toast__icon svg { width: 100%; height: 100%; }
    .sdp-toast__message {
      flex: 1 1 auto;
      min-width: 0;
      word-wrap: break-word;
    }
    .sdp-toast__action {
      display: inline-block;
      margin-top: 0.375rem;
      font-weight: 600;
      color: var(--text);
      text-decoration: underline;
      text-underline-offset: 2px;
    }
    .sdp-toast__action:hover { opacity: 0.8; }
    /* Aktion als Knopf (z. B. „Rückgängig"): steht in der Zeile, rechts vom
       Text, in der Primär-Linie. */
    button.sdp-toast__action {
      flex-shrink: 0;
      align-self: center;
      margin-top: 0;
      padding: 0.25rem 0.5rem;
      border: 0;
      border-radius: var(--radius-sm);
      background: transparent;
      color: var(--primary-line);
      font-size: 0.8125rem;
      cursor: pointer;
    }
    button.sdp-toast__action:hover { background: var(--primary-soft); opacity: 1; }
    .sdp-toast__close {
      flex-shrink: 0;
      background: transparent;
      border: none;
      color: var(--muted);
      font-size: 1.125rem;
      line-height: 1;
      padding: 0 0.25rem;
      cursor: pointer;
      border-radius: var(--radius-sm);
    }
    .sdp-toast__close:hover { color: var(--text); }
    /* Knöpfe im Toast bleiben sichtbar klein — die globale 44-px-Touch-Regel
       (0,9,1) machte den Toast am Telefon 71 px hoch; die Tippfläche wächst
       stattdessen unsichtbar über ::before. Bewusst OHNE eigene Touch-Media-
       Query: die erste im Stylesheet muss die globale Regel sein
       (test_base_template_invariants), und mit Maus schadet die Fläche nicht. */
    :is(.sdp-toast__close, button.sdp-toast__action) {
      position: relative;
      min-width: 0 !important;
      min-height: 0 !important;
    }
    :is(.sdp-toast__close, button.sdp-toast__action)::before {
      content: "";
      position: absolute;
      inset: -0.625rem -0.25rem;
    }
    /* Type-Akzente: linke 4px-Border (subtil) + Icon-Farbe */
    .sdp-toast--success { border-left: 4px solid var(--ok); }
    .sdp-toast--success .sdp-toast__icon { color: var(--ok); }
    .sdp-toast--error { border-left: 4px solid var(--danger); }
    .sdp-toast--error .sdp-toast__icon { color: var(--danger); }
    .sdp-toast--warning { border-left: 4px solid var(--warn); }
    .sdp-toast--warning .sdp-toast__icon { color: var(--warn); }
    .sdp-toast--info { border-left: 4px solid var(--info); }
    .sdp-toast--info .sdp-toast__icon { color: var(--info); }
    @media (prefers-reduced-motion: reduce) {
      .sdp-toast { transition: opacity 80ms ease; transform: none; }
      .sdp-toast.is-leaving { transform: none; }
    }

    @media (hover: none) and (pointer: coarse) {
      /*
       * iOS Safari zooms focused form controls below 16px.
       * Keep mobile editable controls at >=16px instead of disabling user zoom.
       */
      input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):not([type="range"]):not([type="button"]):not([type="submit"]):not([type="reset"]),
      textarea,
      select,
      [contenteditable]:not([contenteditable="false"]),
      .toastui-editor-ww-container .ProseMirror,
      .toastui-editor-contents,
      .toastui-editor-popup-body input,
      .toastui-editor-popup-body textarea {
        font-size: max(16px, 1rem) !important;
      }

      /* WCAG 2.5.5 Touch-Target-Groesse: 44x44 px Mindestflaeche auf
         Touch-Primaer-Geraeten (Phones, Tablets). Desktop mit Maus bleibt
         unveraendert, damit dichte Tabellen/Icon-Toolbars kompakt bleiben.
         Opt-out: Klasse `.icon-btn-compact` (z.B. Inline-Actions in
         dichten Listen, wo 44 px den Flow sprengen wuerde).
         Ausgenommen: reine Text-Links, `button`-Elemente innerhalb von
         Fliesstext (z.B. `<button class="underline">`) sowie die
         Sticky-Sub-Nav-Pills, die bewusst kompakt bleiben.
         Ebenfalls ausgenommen: `.sdp-help-icon` — die inline Hilfe-Icons sitzen
         mitten im Fliesstext/in Labels und haben eine feste quadratische
         Groesse. Mit `min-height: 2.75rem` wuerde aus dem Kreis ein hohes Oval
         (20x44), weil nur die Hoehe waechst. Die Hilfe bleibt ueber den
         Header-(?)-Button und das Hilfe-Panel vollstaendig erreichbar.
         Ausgenommen: `.toastui-editor-toolbar-icons` — die bekommen ihre
         44-px-Flaeche gleich darunter, siehe dortige Begruendung.
         Ausgenommen: `.sdp-action-primary` (Titelbox-Hauptaktion) — sichtbar
         2 rem hoch, die 44-px-Flaeche kommt ueber ::before (title-actions.md). */
      button:not(.icon-btn-compact):not(.underline):not(.text-red-600):not([data-inline-action]):not(.step-nav-pill):not(.profile-sub-nav-pill):not(.sdp-help-icon):not(.sdp-desc-toggle):not(.toastui-editor-toolbar-icons):not(.sdp-action-primary),
      a[role="button"]:not(.icon-btn-compact):not(.step-nav-pill):not(.profile-sub-nav-pill),
      [role="button"]:not(.icon-btn-compact):not(.step-nav-pill):not(.profile-sub-nav-pill),
      .icon-btn:not(.icon-btn-compact) {
        min-height: 2.75rem;
      }
      /* Icon-Only-Buttons (keine Textkinder, hauptsaechlich SVG):
         zusaetzlich Mindestbreite, damit Tap-Area quadratisch wird.
         Fuer die runden Knoepfe der Kopfzeile (Suche, Hilfe, Sprachsteuerung)
         ist die Klasse `icon-only` PFLICHT: mit `min-height` allein waechst nur
         die Hoehe, und aus dem Kreis wird ein Oval (gemessen 34x44). Quadratisch
         plus `rounded-full` ergibt wieder einen Kreis — und zwar einen groesseren
         mit voller 44px-Tap-Flaeche, statt sie wie `.icon-btn-compact` zu
         verkleinern. */
      .icon-btn:not(.icon-btn-compact),
      button.icon-only:not(.icon-btn-compact),
      a[role="button"].icon-only:not(.icon-btn-compact) {
        min-width: 2.75rem;
      }

      /* Toast UI (jeder WYSIWYG-Editor der App) zeichnet ALLE Symbole seiner
         Werkzeugleiste aus EINER Sprite-Grafik: die Schaltflaeche ist 32x32 und
         zeigt ueber `background-position` ihren Ausschnitt. Die Regel oben zog
         sie auf 44 px hoch — dadurch rutschte die naechste Sprite-Zeile ins Bild
         (auf dem Telefon als doppelte, angeschnittene Symbolreihe sichtbar).
         Deshalb ist sie oben ausgenommen und bekommt ihre Tap-Flaeche hier:
         44 px hoch ueber Innenabstand, das Sprite-Fenster per `content-box`
         wieder auf seine 30x30-Zelle beschnitten. Der Aussenabstand wird von
         7 px auf 1 px gekuerzt, damit die Leiste nicht hoeher wird.
         Die Breite bleibt bei Toasts 32 px — waechst sie, blutet die
         Nachbarspalte des Sprites ein (nachgemessen). Ein 44x44-Quadrat ist
         hier bewusst nicht das Ziel: die Symbole stehen dicht an dicht,
         breitere Flaechen wuerden die Leiste umbrechen lassen.
         Der Selektor liegt eine Klasse ueber Toasts eigener Regel
         (`.toastui-editor-defaultUI-toolbar button`) und gewinnt damit
         unabhaengig davon, wann dessen Stylesheet nachgeladen wird.
         Der Innenabstand ist aus der Hoehe GERECHNET: 2.75rem sind nur bei
         Schriftstufe 0 genau 44 px (Stufe 1: 47,7 px). Ein fester Wert von
         6 px liess das Sprite-Fenster dort 33,7 statt 30 px hoch werden —
         die naechste Sprite-Zeile blitzte wieder als blaue Reihe durch.
         (2.75rem − 32px) / 2 ergibt bei 1 px Rand immer genau 30 px Inhalt. */
      .toastui-editor-defaultUI-toolbar button.toastui-editor-toolbar-icons {
        box-sizing: border-box;
        height: 2.75rem;
        padding: calc((2.75rem - 32px) / 2) 0;
        margin: 1px 5px;
        background-origin: content-box;
        background-clip: content-box;
      }
    }

    /* Keep dropdown menu text uniformly sized (matches text-sm links like Anleitung/Logout). */
    #header-nav,
    #header-nav .text-sm,
    #header-nav .text-xs {
      font-size: calc(0.875rem + 2pt);
      line-height: 1.45rem;
    }

    /* Untermenuepunkte 2pt kleiner als Top-Level-Eintraege. */
    #header-nav details > div.pl-3 a,
    #header-nav details > div.pl-3 span {
      font-size: 0.875rem;
      line-height: 1.25rem;
    }

    /* Menü scrollbar machen, wenn es nicht in die Viewport-Höhe passt.
       Das genaue max-height wird beim Öffnen von toggleHeaderNav() gesetzt
       (basierend auf der Button-Position); diese Regel ist Fallback. */
    #header-nav {
      max-height: calc(100vh - 5rem);
      overflow-y: auto;
      overscroll-behavior: contain;
    }

    ::placeholder {
      color: var(--muted);
    }

    :where(.space-y-8) > :not([hidden]) ~ :not([hidden]) {
      margin-top: 1.1rem;
    }

    :where(.space-y-6) > :not([hidden]) ~ :not([hidden]) {
      margin-top: 0.95rem;
    }

    :where(.space-y-4) > :not([hidden]) ~ :not([hidden]) {
      margin-top: 0.55rem;
    }

    :where(.space-y-3) > :not([hidden]) ~ :not([hidden]) {
      margin-top: 0.4rem;
    }

    :where(.gap-4) {
      gap: 0.6rem;
    }

    :where(.gap-3) {
      gap: 0.4rem;
    }

    :where(.p-6) {
      padding: 1rem;
    }

    :where(.p-5) {
      padding: 0.9rem;
    }

    :where(.p-4) {
      padding: 0.75rem;
    }

    :where(.px-4) {
      padding-left: 0.75rem;
      padding-right: 0.75rem;
    }

    :where(.py-4) {
      padding-top: 0.75rem;
      padding-bottom: 0.75rem;
    }

    :where(.px-3) {
      padding-left: 0.6rem;
      padding-right: 0.6rem;
    }

    :where(.py-2) {
      padding-top: 0.35rem;
      padding-bottom: 0.35rem;
    }

    /* GitHub Markdown CSS baseline + small tweaks for our layout */
    .markdown-body { background: transparent; color: var(--text); }
    .markdown-body pre { overflow: auto; border-radius: 0.5rem; padding: 0.75rem; background: var(--code-bg); }
    .markdown-body code,
    .markdown-body tt { background: var(--code-bg); color: var(--code-text); border-radius: 0.25rem; }
    .markdown-body pre code { background: transparent; }
    .markdown-body table { display: block; overflow-x: auto; }
    .markdown-body table tr,
    .markdown-body table th,
    .markdown-body table td { background-color: transparent; border-color: var(--border); }
    .markdown-body table tr:nth-child(2n) { background-color: transparent; }
    .markdown-body ul { list-style-type: disc; }
    .markdown-body ol { list-style-type: decimal; }

    /* === Math rendering (KI Assistenz / KI Agent) === */
    .sdp-math-inline { font-family: "Times New Roman", Times, serif; font-style: italic; }
    .sdp-math-display { display: block; text-align: center; margin: 0.6em 0; font-family: "Times New Roman", Times, serif; font-style: italic; font-size: 1.05em; }
    .sdp-frac { display: inline-flex; flex-direction: column; align-items: center; vertical-align: middle; line-height: 1.3; font-size: 0.95em; font-style: normal; }
    .sdp-frac-n { border-bottom: 1px solid currentColor; padding: 0 0.25em 0.1em; text-align: center; min-width: 0.5em; }
    .sdp-frac-d { padding: 0.1em 0.25em 0; text-align: center; min-width: 0.5em; }
    .sdp-sqrt-b { border-top: 1px solid currentColor; padding: 0 0.15em; margin-left: 0.05em; }

    .step-surface-1 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-2 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-3 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-4 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-5 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-6 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-7 { background-color: hsl(0 0% 100% / 0.96); }
    .step-surface-8 { background-color: hsl(0 0% 100% / 0.96); }

    .step-surface-1,
    .step-surface-2,
    .step-surface-3,
    .step-surface-4,
    .step-surface-5,
    .step-surface-6,
    .step-surface-7,
    .step-surface-8 {
      box-shadow: var(--shadow);
    }

    /*
     * Page background is always dark (image + shade overlay), so text
     * OUTSIDE surface cards in <main> must be light.  Scoped to main
     * so header / footer keep their own colours on white-ish bg.
     * Inside .bg-white cards the restore rules bring dark text back.
     */
    /* Graustufen app-weit eine Stufe kontrastreicher (2026-09-23): der
       Tailwind-Grundwert gilt überall dort, wo keine der Kontext-Regeln
       unten greift (Kopfzeile, Menü, an <body> gehängte Modals). Gleiche
       Spezifität wie tailwind.css, gewinnt über die Quellreihenfolge und
       verliert gegen jede Kontext-Regel. Die Kontext-Maps unten sind
       ebenfalls um eine Stufe verschoben (hell: dunkler, dunkel: heller). */
    .text-slate-400 { color: #64748b; }
    .text-slate-500 { color: #475569; }
    .text-slate-600 { color: #334155; }
    .text-slate-700 { color: #1e293b; }

    main .text-slate-400 { color: #cbd5e1; }
    main .text-slate-500 { color: #cbd5e1; }
    main .text-slate-600 { color: #e2e8f0; }
    main .text-slate-700 { color: #f1f5f9; }
    main .text-slate-800 { color: #f1f5f9; }
    main .text-slate-900 { color: #f8fafc; }

    main .hover\:text-slate-700:hover,
    main .hover\:text-slate-800:hover,
    main .hover\:text-slate-900:hover { color: #f8fafc; }

    main .hover\:bg-slate-50:hover  { background-color: rgba(255, 255, 255, 0.12); }

    main .border-slate-200,
    main .border-slate-300 { border-color: rgba(255, 255, 255, 0.15); }

    /* Inside surface cards (light mode): restore dark text & borders */
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .text-slate-400 { color: #64748b; }
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .text-slate-500 { color: #475569; }
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .text-slate-600 { color: #334155; }
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .text-slate-700 { color: #1e293b; }
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .text-slate-800 { color: #1e293b; }
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .text-slate-900 { color: #0f172a; }

    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .hover\:text-slate-700:hover,
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .hover\:text-slate-800:hover,
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .hover\:text-slate-900:hover { color: #0f172a; }

    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .border-slate-200 { border-color: #e2e8f0; }
    html[data-theme="light"] :is(.bg-white, .border.rounded-2xl, .border.rounded-xl) .border-slate-300 { border-color: #cbd5e1; }

    html[data-theme="light"] .dashboard-card a.border:hover,
    html[data-theme="light"] .dashboard-card button.border:hover,
    html[data-theme="light"] .dashboard-card [role="link"].border:hover {
      background-color: rgba(255, 255, 255, 0.95);
      border-color: #cbd5e1;
      box-shadow: 0 12px 28px -18px rgba(15, 23, 42, 0.35);
    }

    /* Hover auf klickbaren Kacheln (Menue-Mini-Kacheln, Uebersichts-Kacheln):
       die Kachel hebt sich leicht ab (Lift), statt transparenter zu werden. */
    a.dashboard-card {
      position: relative;
      transition: transform 140ms ease, box-shadow 140ms ease;
    }
    a.dashboard-card:hover {
      transform: translateY(-3px);
      box-shadow: 0 14px 28px -14px rgba(2, 6, 23, 0.5) !important;
    }
    @media (prefers-reduced-motion: reduce) {
      a.dashboard-card:hover { transform: none; }
    }

    /* Dezente Kategorie-Farbakzente auf den Dashboard-Kacheln.
       Pastell-Verlauf am linken Rand, der nach rechts ins Transparente
       ausläuft. Aktiv über die Klasse .has-category-accents (global per
       Admin-Grundkonfiguration + pro User abschaltbar). Der Inline-
       background-color der Kachel bleibt erhalten — hier wird nur ein
       zusätzliches background-image gesetzt. */
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category] {
      background-image: linear-gradient(to right, var(--cat-accent, transparent) 0%, transparent 1rem);
      background-repeat: no-repeat;
      background-size: 1rem 100%;
      /* Verlauf bis an die echte Kachelkante ziehen und den 1px-Rand links
         transparent schalten — sonst bleibt dort eine helle Linie sichtbar. */
      background-origin: border-box;
      border-left-color: transparent;
    }
    /* Kachel-Icons greifen die Kategorie-Randfarbe auf, aber in einer
       kräftigen, voll deckenden Variante (--cat-icon). Hohe Spezifität
       (ID + Klassen) übersteuert die hartkodierten text-*-Klassen. */
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category] > div > h2 > .shrink-0 {
      color: var(--cat-icon, inherit);
    }
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="wissen"] {
      --cat-accent: rgba(110, 231, 183, 0.9);
      --cat-icon: #059669;
    }
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="ki"] {
      --cat-accent: rgba(196, 181, 253, 0.9);
      --cat-icon: #7c3aed;
    }
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="kommunikation"] {
      --cat-accent: rgba(252, 211, 77, 0.85);
      --cat-icon: #d97706;
    }
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="organisation"] {
      --cat-accent: rgba(125, 211, 252, 0.9);
      --cat-icon: #0284c7;
    }
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="austausch"] {
      --cat-accent: rgba(216, 180, 226, 0.9);
      --cat-icon: #7e3a8a;
    }
    #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="intern"] {
      --cat-accent: rgba(190, 242, 100, 0.85);
      --cat-icon: #4d7c0f;
    }
    html[data-theme="dark"] #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="wissen"] {
      --cat-accent: rgba(52, 211, 153, 0.42);
      --cat-icon: #34d399;
    }
    html[data-theme="dark"] #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="ki"] {
      --cat-accent: rgba(167, 139, 250, 0.45);
      --cat-icon: #a78bfa;
    }
    html[data-theme="dark"] #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="kommunikation"] {
      --cat-accent: rgba(251, 191, 36, 0.4);
      --cat-icon: #fbbf24;
    }
    html[data-theme="dark"] #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="organisation"] {
      --cat-accent: rgba(56, 189, 248, 0.42);
      --cat-icon: #38bdf8;
    }
    html[data-theme="dark"] #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="austausch"] {
      --cat-accent: rgba(186, 104, 200, 0.42);
      --cat-icon: #d49be0;
    }
    html[data-theme="dark"] #dashboard-cards.has-category-accents .dashboard-card[data-dashboard-category="intern"] {
      --cat-accent: rgba(132, 204, 22, 0.42);
      --cat-icon: #a3e635;
    }

    /* Dieselben Kategorie-Akzente auch ausserhalb des Dashboards
       (Menue-Uebersichtsseiten /uebersicht/...): ueber die Container-Klasse
       .dashboard-accents statt der ID #dashboard-cards. Zusaetzlich die
       neutrale Kategorie "verwaltung" (Admin-Gruppen).
       `.dashboard-cat-icons` nutzt dieselbe Palette NUR fuer die Symbolfarbe
       (--cat-icon), ohne den Farbstreifen — Symbolreihe des Dashboards auf dem
       Telefon (index.html, dashboard-heute-mobil.md). */
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category] {
      background-image: linear-gradient(to right, var(--cat-accent, transparent) 0%, transparent 1rem);
      background-repeat: no-repeat;
      background-size: 1rem 100%;
      background-origin: border-box;
      border-left-color: transparent;
    }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category] > div > h2 > .shrink-0 {
      color: var(--cat-icon, inherit);
    }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="wissen"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="wissen"] { --cat-accent: rgba(110, 231, 183, 0.9); --cat-icon: #059669; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="ki"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="ki"] { --cat-accent: rgba(196, 181, 253, 0.9); --cat-icon: #7c3aed; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="kommunikation"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="kommunikation"] { --cat-accent: rgba(252, 211, 77, 0.85); --cat-icon: #d97706; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="organisation"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="organisation"] { --cat-accent: rgba(125, 211, 252, 0.9); --cat-icon: #0284c7; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="austausch"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="austausch"] { --cat-accent: rgba(216, 180, 226, 0.9); --cat-icon: #7e3a8a; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="intern"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="intern"] { --cat-accent: rgba(190, 242, 100, 0.85); --cat-icon: #4d7c0f; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="verwaltung"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="verwaltung"] { --cat-accent: rgba(148, 163, 184, 0.9); --cat-icon: #475569; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="schulorganisation"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="schulorganisation"] { --cat-accent: rgba(94, 234, 212, 0.85); --cat-icon: #0d9488; }
    .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="dateiablage"], .dashboard-cat-icons .dashboard-card[data-dashboard-category="dateiablage"] { --cat-accent: rgba(165, 180, 252, 0.9); --cat-icon: #4f46e5; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="wissen"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="wissen"] { --cat-accent: rgba(52, 211, 153, 0.42); --cat-icon: #34d399; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="ki"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="ki"] { --cat-accent: rgba(167, 139, 250, 0.45); --cat-icon: #a78bfa; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="kommunikation"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="kommunikation"] { --cat-accent: rgba(251, 191, 36, 0.4); --cat-icon: #fbbf24; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="organisation"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="organisation"] { --cat-accent: rgba(56, 189, 248, 0.42); --cat-icon: #38bdf8; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="austausch"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="austausch"] { --cat-accent: rgba(186, 104, 200, 0.42); --cat-icon: #d49be0; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="intern"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="intern"] { --cat-accent: rgba(132, 204, 22, 0.42); --cat-icon: #a3e635; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="verwaltung"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="verwaltung"] { --cat-accent: rgba(100, 116, 139, 0.45); --cat-icon: #94a3b8; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="schulorganisation"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="schulorganisation"] { --cat-accent: rgba(45, 212, 191, 0.42); --cat-icon: #2dd4bf; }
    html[data-theme="dark"] .dashboard-accents.has-category-accents .dashboard-card[data-dashboard-category="dateiablage"], html[data-theme="dark"] .dashboard-cat-icons .dashboard-card[data-dashboard-category="dateiablage"] { --cat-accent: rgba(129, 140, 248, 0.42); --cat-icon: #818cf8; }

    /* Tabs (macros/tabs.html, data-sdp-tablist): der aktive Tab ist app-weit
       fett und unterstrichen (User-Vorgabe 2026-08-24, Standard für alle Tabs).
       Bewusst niedrige Spezifität — seitenlokale .booking-tab-Regeln gewinnen
       bei Gleichstand durch ihre spätere Position im Dokument. */
    [data-sdp-tablist] > [role="tab"] {
      color: var(--muted);
      border-bottom: 2px solid transparent;
    }
    [data-sdp-tablist] > [role="tab"].is-active,
    [data-sdp-tablist] > [role="tab"][aria-selected="true"] {
      color: var(--text);
      font-weight: 600;
      border-bottom-color: var(--primary-line);
    }
    /* Symbol vor der Beschriftung (Makro-Parameter icon), z. B. KI-Sparkles */
    [data-sdp-tablist] > [role="tab"] .sdp-tab-icon {
      display: inline-block;
      width: 1em;
      height: 1em;
      margin-right: 0.35em;
      vertical-align: -0.15em;
    }
    [data-sdp-tablist] > [role="tab"] .sdp-tab-icon svg { width: 100%; height: 100%; }

    /* ===== Seitenleiste (Entwurf A, seit 2026-09-24) =====
       Ab 641 px steht links eine feste Leiste ueber die volle Hoehe: Logo und
       Portalname, Suche, Startseite, die Menue-Gruppen (Unterpunkte klappen in
       der Leiste auf, immer nur eine Gruppe offen) und unten das Profil. Sie
       ersetzt die fruehere Schnellnav-Leiste aus Einzelkacheln (erst ab
       1300 px) und das Menue-Raster der Startseite. Auf dem Telefon bleibt
       es beim Menue in der Kopfzeile.
         >= 1025 px   16.5rem breit, mit Titeln
         641–1024 px  4.5rem Symbolleiste; ein Klick auf eine Gruppe klappt
                      die Leiste als Overlay auf (.is-expanded), Klick daneben
                      oder Esc klappt sie wieder zu.
       Gerendert nur, wenn es Menue-Gruppen gibt (nicht fuer Eltern-
       vertreter:innen, Kiosk, Offline-Snapshots, Seiten ohne Kopfzeile);
       dann traegt <body> die Klasse sdp-has-sidebar und macht Platz.
       Offline (body.sdp-offline) verschwindet die Leiste: ihre Links
       funktionieren dort nicht. Regel: .claude/rules/vollflaechige-ansicht.md. */
    .sdp-side-rail { display: none; }
    @media screen and (min-width: 641px) {
      body.sdp-has-sidebar:not(.sdp-offline) {
        --sdp-sidebar-w: 16.5rem;
        padding-left: var(--sdp-sidebar-w);
      }
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        width: var(--sdp-sidebar-w);
        --sdp-rail-pad-x: 0.75rem;
        padding: 0.75rem var(--sdp-rail-pad-x) 0.625rem;
        background: var(--surface);
        border-right: 1px solid var(--border);
        /* Kopf (Logo, Suche) und Profil stehen fest, nur die Gruppen
           dazwischen scrollen (.sdp-rail-groups). */
        overflow: hidden;
        z-index: 35;
      }
      /* Kopfzeile neben der Leiste: Logo, Portalname und Suche stehen in
         der Leiste — die Kopfzeile traegt nur noch Hilfe, Sprachsteuerung
         und das Menue. Im Menue entfallen die Gruppen-Links (stehen links). */
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-app-header :is(.sdp-portal-link, #header-search-button) { display: none; }
      /* Die Kopfzeile ist hier nur ein schmaler Streifen ueber dem Inhalt —
         in der Farbe der Flaeche wie die Leiste (auf dem Telefon bleibt sie
         im Dunkelmodus eine Stufe heller, --sdp-mobile-header-bg). */
      body.sdp-has-sidebar:not(.sdp-offline) > header.sdp-app-header {
        background: var(--surface) !important;
        background-color: var(--surface) !important;
      }
      body.sdp-has-sidebar:not(.sdp-offline) [data-menu-nav-group] { display: none; }
      /* Das Menue-Raster/die Symbolreihe der Startseite: die Leiste zeigt
         dieselben Gruppen. */
      body.sdp-has-sidebar:not(.sdp-offline) .dashboard-mini-row { display: none !important; }
    }
    @media screen and (min-width: 641px) and (max-width: 1024px) {
      body.sdp-has-sidebar:not(.sdp-offline) { --sdp-sidebar-w: 4.5rem; }
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail {
        --sdp-rail-pad-x: 0.625rem;
        transition: width 160ms ease, box-shadow 160ms ease;
      }
      /* Zugeklappt: nur Symbole. Die Titel bleiben fuer Screenreader im
         Baum (visuell versteckt, nie display:none). */
      .sdp-side-rail:not(.is-expanded) :is(.sdp-side-rail-title, .sdp-rail-brand-name, .sdp-rail-search-label, .sdp-rail-profile-text) {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
      }
      .sdp-side-rail:not(.is-expanded) :is(.sdp-side-rail-chevron, .sdp-rail-search kbd) { display: none; }
      .sdp-side-rail:not(.is-expanded) .sdp-side-rail-sub { display: none; }
      .sdp-side-rail:not(.is-expanded) .sdp-side-rail-group.is-current > .sdp-side-rail-toggle { background: var(--focus-soft); }
      .sdp-side-rail:not(.is-expanded) :is(.sdp-side-rail-tile, .sdp-side-rail-toggle, .sdp-rail-brand, .sdp-rail-search, .sdp-rail-profile) { justify-content: center; }
      .sdp-side-rail:not(.is-expanded) :is(a.sdp-side-rail-tile, .sdp-side-rail-toggle, .sdp-rail-search, .sdp-rail-profile) { padding-left: 0; padding-right: 0; }
      .sdp-side-rail:not(.is-expanded) .sdp-rail-search { border-color: transparent; background: transparent; }
      .sdp-side-rail:not(.is-expanded) .notify-corner-badge { position: absolute; top: 0.125rem; right: 0.125rem; width: 1.125rem; height: 1.125rem; margin: 0; }
      .sdp-side-rail:not(.is-expanded) .notify-corner-badge svg { width: 0.7rem; height: 0.7rem; }
      /* Aufgeklappt: die volle Leiste als Overlay ueber dem Inhalt. */
      .sdp-side-rail.is-expanded {
        width: 16.5rem !important;
        --sdp-rail-pad-x: 0.75rem !important;
        box-shadow: 0 0 0 100vmax var(--overlay), 1rem 0 2.5rem -1rem rgba(2, 6, 23, 0.4);
      }
    }
    /* Schreibtisch mit Maus: die Leiste tritt zurueck, bis man auf sie
       zeigt oder per Tastatur hineinspringt — der Blick gehoert dem
       Seiteninhalt. Verblassen nur die TEXTE der Menue-Eintraege (samt
       Pfeilen und aufgeklappten Unterpunkten); die farbigen Symbole, die
       Ungelesen-Hinweise, der Kopf (Logo, Portalname, Suche) und die
       Profilzeile unten bleiben voll sichtbar. Das Ausblenden setzt verzoegert ein,
       damit ein kurzes Hinausrutschen nicht flackert. Ohne Maus
       (hover: none) und bei erhoehtem Kontrast bleibt alles voll sichtbar. */
    @media screen and (min-width: 1025px) and (hover: hover) and (pointer: fine) and (not (prefers-contrast: more)) {
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail {
        border-right-color: transparent;
        transition: border-color 200ms ease 180ms;
      }
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail :is(.sdp-side-rail-title, .sdp-side-rail-chevron, .sdp-side-rail-sub) {
        opacity: 0.45;
        transition: opacity 200ms ease 180ms;
      }
      /* Die KI Assistenz tritt nicht mit zurück. */
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail .sdp-rail-ki .sdp-side-rail-title { opacity: 1; }
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail:is(:hover, :focus-within) {
        border-right-color: var(--border);
        transition-delay: 0s;
      }
      body.sdp-has-sidebar:not(.sdp-offline) .sdp-side-rail:is(:hover, :focus-within) :is(.sdp-side-rail-title, .sdp-side-rail-chevron, .sdp-side-rail-sub) {
        opacity: 1;
        transition-delay: 0s;
      }
    }
    /* Schreibtisch, auf Wunsch der Seite (body.sdp-rail-compact — bisher die
       Arbeitsblatterstellung, dort braucht die Blattansicht den Platz): dieselbe
       schmale Symbolleiste wie auf dem Tablet, der Inhalt gewinnt 12rem. Zeigen
       mit der Maus oder Tastaturfokus klappt sie als Overlay auf (.is-expanded,
       Skript unten) — ohne den Inhalt zu verschieben und ohne abzudunkeln.
       Touch-Geräte dieser Breite wie das Tablet: Tippen auf eine Gruppe. */
    @media screen and (min-width: 1025px) {
      body.sdp-has-sidebar.sdp-rail-compact:not(.sdp-offline) { --sdp-sidebar-w: 4.5rem; }
      body.sdp-has-sidebar.sdp-rail-compact:not(.sdp-offline) .sdp-side-rail {
        --sdp-rail-pad-x: 0.625rem;
        transition: width 160ms ease, box-shadow 160ms ease;
      }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) :is(.sdp-side-rail-title, .sdp-rail-brand-name, .sdp-rail-search-label, .sdp-rail-profile-text) {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
      }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) :is(.sdp-side-rail-chevron, .sdp-rail-search kbd) { display: none; }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) .sdp-side-rail-sub { display: none; }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) .sdp-side-rail-group.is-current > .sdp-side-rail-toggle { background: var(--focus-soft); }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) :is(.sdp-side-rail-tile, .sdp-side-rail-toggle, .sdp-rail-brand, .sdp-rail-search, .sdp-rail-profile) { justify-content: center; }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) :is(a.sdp-side-rail-tile, .sdp-side-rail-toggle, .sdp-rail-search, .sdp-rail-profile) { padding-left: 0; padding-right: 0; }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) .sdp-rail-search { border-color: transparent; background: transparent; }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) .notify-corner-badge { position: absolute; top: 0.125rem; right: 0.125rem; width: 1.125rem; height: 1.125rem; margin: 0; }
      body.sdp-rail-compact .sdp-side-rail:not(.is-expanded) .notify-corner-badge svg { width: 0.7rem; height: 0.7rem; }
      body.sdp-has-sidebar.sdp-rail-compact:not(.sdp-offline) .sdp-side-rail.is-expanded {
        width: 16.5rem;
        --sdp-rail-pad-x: 0.75rem;
        border-right-color: var(--border);
        box-shadow: 1rem 0 2.5rem -1rem rgba(2, 6, 23, 0.35);
      }
    }
    /* Breite Arbeitsfläche (body.sdp-main-wide, zusammen mit sdp-rail-compact:
       Raster und Editoren wie Kalender, Planungswand, Raumbuchung): die
       Begrenzung von #page-main (max-w-5xl) entfällt, die Ränder bleiben. */
    @media screen { body.sdp-main-wide main#page-main { max-width: none; } }
    /* Volle Breite als Standard (2026-11-05): am Schreibtisch ziehen Kopfzeile
       und Footer mit — sonst stünden Hilfe und Menü in der alten 64rem-Spalte,
       weit links von der rechten Kante des Inhalts. Innere Seitenhüllen
       (`<div class="max-w-4xl mx-auto …">` als oberstes Element einer Seite)
       verlieren ihre Begrenzung ebenfalls, damit Titel und Inhalt aller Seiten
       an derselben Kante beginnen und enden. Schmale Formularhüllen bis
       max-w-2xl bleiben (Eingabefelder über 1300 px lesen sich schlecht) — sie
       stehen linksbündig an der Textkante. Unter 1025 px gilt alles wie zuvor. */
    @media screen and (min-width: 1025px) {
      body.sdp-main-wide header > div.max-w-5xl,
      body.sdp-main-wide footer.max-w-5xl { max-width: none; }
      /* Feste Inhaltsspalte (layout_fest, Startseite): Kopfzeile und Footer
         ziehen trotzdem mit, die Spalte steht an derselben Textkante links. */
      body.sdp-kopf-breit header > div.max-w-5xl,
      body.sdp-kopf-breit footer.max-w-5xl { max-width: none; }
      body.sdp-kopf-breit main#page-main { margin-left: 0; margin-right: 0; }
      body.sdp-main-wide main#page-main > :is(.max-w-3xl, .max-w-4xl, .max-w-5xl, .max-w-6xl, .max-w-7xl) { max-width: none; }
      body.sdp-main-wide main#page-main > :is(.max-w-md, .max-w-lg, .max-w-xl, .max-w-2xl).mx-auto { margin-left: 0; margin-right: 0; }
      /* Rechts Platz für Vogel und Hilfe-Lasche (2026-11-05): beide schweben
         am rechten Rand (Vogel x ≈ 1849–1903 bei 1920 px). Auf voller Breite
         stehen dort Zeilenaktionen, Zähler und Status — beim Scrollen lagen
         sie darunter („Bearbeiten" der Benutzerverwaltung, „⋯" der Gremien).
         Der Inhalt endet deshalb 2.25rem früher; Seiten mit eigenem
         randlosem Layout (padding: 0 !important) regeln das selbst. */
      body.sdp-main-wide main#page-main { padding-right: calc(var(--sdp-mobile-gutter) + 2.25rem); }
      /* Beschreibung unter dem Seitentitel höchstens ~90 Zeichen je Zeile
         (2026-11-05): auf voller Breite liefen manche über 1750 px. */
      body.sdp-main-wide #page-main h1 ~ p { max-width: 64rem; }
      /* Absendezeilen von Formularen links (2026-11-05, passend zur Hauptaktion
         vorn in der Titelleiste): „Projekt anlegen", „Beschluss eintragen" u. a.
         standen per justify-end bzw. text-right ganz rechts — auf 1920 px bis zu
         1500 px vom Formularanfang. Blätter und Dialoge behalten ihre Zeile
         rechts unten (.sdp-sheet-actions, Rückfragen). */
      body.sdp-main-wide #page-main form :is(.justify-end, .text-right):has(> :is(button[type="submit"], button.btn-primary, input[type="submit"])):not(.sdp-sheet-actions):not(:where(.sdp-sheet, [role="dialog"], [data-sdp-modal]) *) {
        justify-content: flex-start;
        text-align: left;
      }
    }
    /* Tabellenköpfe in Satzschreibung statt VERSALIEN (2026-11-05, alle Breiten,
       nur Bildschirm): zehn Vorlagen setzten `uppercase` an thead/tr/th, die
       übrigen nicht — wie seit Phase 6 der optischen Auffrischung überall sonst. */
    @media screen {
      #page-main :is(thead.uppercase, thead .uppercase, .mod-table th) { text-transform: none; letter-spacing: normal; }
    }
    /* Bausteine gegen leere Flächen auf breiten Bildschirmen (2026-11-05).
       Die volle Breite allein lässt einspaltige Seiten auf 16:9/16:10 leer
       wirken: Eingabefelder über 1800 px, Kartenzeilen mit dem Datum weit
       rechts, Liste und Anlege-Formular untereinander. Deshalb:
       · einzeilige Eingabefelder und Auswahllisten höchstens 48rem breit
         (mehrzeilige Felder, Chat-Eingaben und Editoren bleiben frei;
         `.sdp-feld-breit` nimmt ein Feld aus);
       · .sdp-breit-zwei  — zwei gleich breite Spalten (Abschnitte nebeneinander);
       · .sdp-breit-haupt — Hauptspalte + Seitenspalte (z. B. Liste + Formular);
       · .sdp-breit-raster — Karten in so vielen Spalten, wie Platz ist.
       Alles erst ab 1280 px (Felder ab 1025 px) und nur mit sdp-main-wide —
       Tablet, Telefon und Druck bleiben unverändert einspaltig. */
    @media screen and (min-width: 1025px) {
      body.sdp-main-wide #page-main input:is([type="text"], [type="email"], [type="url"], [type="search"], [type="password"], [type="tel"], :not([type])):not(.sdp-feld-breit) { max-width: 48rem; }
      /* Feldbreite nach Inhalt (2026-11-05): ein Datum, eine Uhrzeit, eine
         Zahl oder eine Farbe brauchen keine 48rem — gemessen waren Datumsfelder
         880 px, Farbfelder 860 px, Dateifelder 1320 px breit. Auswahllisten
         bekommen 32rem (lange Gremien- und Modellnamen passen noch). */
      body.sdp-main-wide #page-main input:is([type="date"], [type="time"], [type="datetime-local"], [type="month"], [type="week"], [type="number"]):not(.sdp-feld-breit) { max-width: 16rem; }
      body.sdp-main-wide #page-main input[type="color"]:not(.sdp-feld-breit) { max-width: 6rem; }
      body.sdp-main-wide #page-main select:not(.sdp-feld-breit, [multiple]) { max-width: 32rem; }
      body.sdp-main-wide #page-main input[type="file"]:not(.sdp-feld-breit) { max-width: 36rem; }
      /* Ein Feld mit w-full stand bisher allein durch seine Breite auf eigener
         Zeile (<label><span>Titel</span><input class="w-full">). Mit Höchstbreite
         rutschte es neben die Beschriftung (Schulprojekte: „Zieldatum") —
         display: block hält es darunter, wie vorher. */
      body.sdp-main-wide #page-main :is(input, select).w-full { display: block; }
      /* .sdp-breit-links: Filter- und Werkzeugzeilen, die auf schmalen Breiten
         rechts stehen (ml-auto, justify-end), am Schreibtisch direkt links
         neben bzw. über ihrem Bezug — auf 1920 px lagen sie sonst bis zu
         1500 px entfernt (Schulprojekte, Leseübungen, Rahmenlehrpläne). */
      body.sdp-main-wide .sdp-breit-links { margin-left: 0; justify-content: flex-start; }
    }
    @media screen and (min-width: 1280px) {
      body.sdp-main-wide .sdp-breit-zwei,
      body.sdp-main-wide .sdp-breit-haupt,
      body.sdp-main-wide .sdp-breit-raster {
        display: grid;
        column-gap: 2.5rem;
        align-items: start;
      }
      body.sdp-main-wide .sdp-breit-zwei { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
      body.sdp-main-wide .sdp-breit-haupt { grid-template-columns: minmax(0, 1.7fr) minmax(22rem, 1fr); }
      body.sdp-main-wide .sdp-breit-raster { grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr)); row-gap: 0.75rem; }
      /* :not([hidden]) hebt die Spezifität über Tailwinds space-y-* (0,3,0). */
      body.sdp-main-wide :is(.sdp-breit-zwei, .sdp-breit-haupt, .sdp-breit-raster) > :not([hidden]) { margin-top: 0; min-width: 0; }
      body.sdp-main-wide :is(.sdp-breit-zwei, .sdp-breit-haupt, .sdp-breit-raster) > .sdp-breit-ganz { grid-column: 1 / -1; }
      /* Seitenspalte: steht immer rechts (auch wenn sie im Quelltext — und damit
         auf Telefon/Tablet — zuerst kommt), Formulare darin einspaltig. */
      body.sdp-main-wide .sdp-breit-haupt > * { order: 1; }
      body.sdp-main-wide .sdp-breit-haupt > .sdp-breit-seite { order: 2; }
      body.sdp-main-wide .sdp-breit-seite :is(.sm\:grid-cols-2, .sm\:grid-cols-3, .md\:grid-cols-2, .md\:grid-cols-3, .lg\:grid-cols-2) { grid-template-columns: minmax(0, 1fr); }
      body.sdp-main-wide .sdp-breit-seite :is(.sm\:grid-cols-2, .sm\:grid-cols-3, .md\:grid-cols-2, .md\:grid-cols-3, .lg\:grid-cols-2) > * { grid-column: 1 / -1; }
      /* Listen am breiten Bildschirm — einheitlich nach Art (User-Entscheidung
         2026-11-05), statt Zeilen über die ganze Breite mit den Aktionen ganz rechts:
         · .sdp-karten  — SAMMLUNGEN, die man öffnet (Quiz, Umfragen, Termin-
           vereinbarungen, Materiallisten, Podcasts, Planungswände): jeder Eintrag
           eine Karte im Raster, Aktionen unten in der Karte;
         · .sdp-zeilen-spalten — ARBEITSLISTEN mit vielen gleichartigen Zeilen
           (Kinder, Vorgänge, Kontakte): Zeilen bleiben Zeilen, fließen aber in
           Spalten, Status und Knopf stehen nah am Namen.
         Echte Tabellen bleiben Tabellen. Unter 1280 px unverändert. */
      body.sdp-main-wide .sdp-karten {
        display: grid !important;
        grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
        gap: 1rem;
        align-items: stretch;
      }
      body.sdp-main-wide #page-main .sdp-karten > :not(.sdp-breit-ganz) {
        margin: 0 !important;
        min-width: 0;
        border: 1px solid var(--border) !important;
        border-radius: 0.75rem !important;
        padding: 1rem 1.125rem !important;
        background: var(--surface) !important;
        box-shadow: none !important;
        display: flex !important;
        flex-direction: column;
        align-items: stretch;
        justify-content: space-between;
        gap: 0.75rem;
      }
      body.sdp-main-wide #page-main .sdp-karten > :not(.sdp-breit-ganz)::before { display: none !important; }
      /* Zeilen-CSS bringt oft `flex: 1 1 18rem` mit — in der Spalte wäre das eine Höhe. */
      body.sdp-main-wide #page-main .sdp-karten > :not(.sdp-breit-ganz) > * { flex: 0 0 auto !important; max-width: 100%; }
      /* Aktionen unten links in der Karte, nicht mehr an den rechten Rand geschoben. */
      body.sdp-main-wide #page-main .sdp-karten > :not(.sdp-breit-ganz) > :last-child:not(:first-child) { justify-content: flex-start !important; margin-left: 0 !important; }
      /* Karte = Link in einem Listenpunkt (<li><a …>): die innere Umrandung entfällt. */
      body.sdp-main-wide #page-main .sdp-karten > li > a:only-child { border: 0 !important; padding: 0 !important; flex: 1 1 auto; display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; gap: 0.75rem; }
      body.sdp-main-wide .sdp-zeilen-spalten {
        display: grid !important;
        grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr));
        column-gap: 2.5rem;
        align-content: start;
      }
      body.sdp-main-wide .sdp-zeilen-spalten > :not([hidden]) { margin-top: 0; min-width: 0; }
      body.sdp-main-wide :is(.sdp-karten, .sdp-zeilen-spalten) > .sdp-breit-ganz { grid-column: 1 / -1; }
      /* Gruppenköpfe über Karten/Spalten bündig mit der Textkante (2026-11-05):
         ihr Innenabstand passte zu den Zeilen der Telefon-Liste, über Karten
         stand „Überfällig 8" um 4 px eingerückt. */
      body.sdp-main-wide :is(.sdp-karten, .sdp-zeilen-spalten) > .sdp-breit-ganz { padding-left: 0; padding-right: 0; }
    }
    @media print { .sdp-side-rail { display: none !important; } }
    /* Offline-Snapshot: gar nicht erst gerendert; offline (sdp-offline) weg. */
    body[data-offline-snapshot] .sdp-side-rail,
    body.sdp-offline .sdp-side-rail { display: none !important; }

    /* Kopf der Leiste: Logo + Portalname, darunter die Suche. */
    .sdp-rail-top { flex: none; display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.75rem; }
    .sdp-rail-brand {
      display: flex;
      align-items: center;
      gap: 0.625rem;
      min-height: 2.5rem;
      padding: 0 0.5rem;
      border-radius: 0.5rem;
      color: var(--text);
      text-decoration: none;
      font-size: 0.875rem;
      font-weight: 600;
      line-height: 1.2;
    }
    .sdp-rail-brand img { height: 1.5rem; width: auto; flex-shrink: 0; }
    .sdp-rail-brand-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sdp-rail-search {
      display: flex;
      align-items: center;
      gap: 0.625rem;
      width: 100%;
      min-height: 2.375rem;
      padding: 0 0.625rem 0 0.75rem;
      border: 1px solid var(--border);
      border-radius: 0.625rem;
      background: var(--surface-muted);
      color: var(--muted);
      font: inherit;
      font-size: 0.8125rem;
      text-align: left;
      cursor: pointer;
    }
    .sdp-rail-search:hover { color: var(--text); }
    .sdp-rail-search svg { width: 1rem; height: 1rem; flex-shrink: 0; }
    .sdp-rail-search-label { flex: 1 1 auto; min-width: 0; }
    .sdp-rail-search kbd {
      flex-shrink: 0;
      font: inherit;
      font-size: 0.6875rem;
      font-weight: 500;
      padding: 0.0625rem 0.375rem;
      border: 1px solid var(--border);
      border-radius: 0.375rem;
      color: var(--muted);
    }
    .sdp-rail-groups {
      flex: 1 1 auto;
      min-height: 0;
      display: flex;
      flex-direction: column;
      gap: 0.125rem;
      /* Scrollbereich bis an den Leistenrand, damit die Hover-Flaechen nicht
         abgeschnitten werden und der Balken aussen sitzt. */
      margin: 0 calc(-1 * var(--sdp-rail-pad-x, 0.75rem));
      padding: 0 var(--sdp-rail-pad-x, 0.75rem) 0.5rem;
      overflow-y: auto;
      overscroll-behavior: contain;
      scrollbar-width: thin;
    }

    /* Eintraege: flache Zeilen mit farbigem Symbol — keine Kacheln mehr.
       Die Tiles tragen weiter .dashboard-card (Kategorie-Palette fuer
       --cat-icon); deren Farbstreifen, Rahmen, Schatten und das Anheben
       beim Ueberfahren werden hier zurueckgenommen. */
    .sdp-side-rail .sdp-side-rail-tile {
      position: relative;
      flex-shrink: 0;           /* nie schrumpfen, die Leiste scrollt */
      display: flex;
      align-items: center;
      gap: 0.75rem;
      min-height: 2.375rem;
      padding: 0 0.625rem;
      border: 0;
      border-radius: 0.5rem;
      background: transparent !important;
      box-shadow: none !important;
      color: var(--text);
      text-decoration: none;
      font-size: 0.875rem;
      font-weight: 400;
      line-height: 1.25;
      transform: none !important;
    }
    .sdp-side-rail a.sdp-side-rail-tile:hover,
    .sdp-side-rail .sdp-side-rail-toggle:hover { background: var(--focus-soft) !important; }
    .sdp-side-rail .sdp-side-rail-tile[aria-current="page"] {
      background: var(--primary-soft) !important;
      font-weight: 600;
    }
    .sdp-side-rail-title { min-width: 0; flex: 1 1 auto; }
    .sdp-side-rail .sdp-side-rail-group {
      flex-direction: column;
      align-items: stretch;
      padding: 0;
    }
    .sdp-side-rail-toggle {
      display: flex;
      align-items: center;
      gap: 0.75rem;
      width: 100%;
      min-height: 2.375rem;
      padding: 0 0.625rem;
      border: 0;
      border-radius: 0.5rem;
      background: none;
      color: inherit;
      font: inherit;
      text-align: left;
      cursor: pointer;
    }
    .sdp-side-rail-group.is-current > .sdp-side-rail-toggle { font-weight: 600; }
    .sdp-side-rail-group.is-current:not(.is-open) > .sdp-side-rail-toggle { background: var(--focus-soft); }
    .sdp-side-rail-chevron {
      margin-left: auto;
      flex-shrink: 0;
      display: inline-flex;
      color: var(--muted);
      transition: transform 140ms ease;
    }
    .sdp-side-rail-chevron svg { width: 0.8rem; height: 0.8rem; }
    .sdp-side-rail-group.is-open .sdp-side-rail-chevron { transform: rotate(180deg); }
    .sdp-side-rail .notify-corner-badge {
      position: static;
      flex-shrink: 0;
      width: 1.25rem;
      height: 1.25rem;
      margin-left: auto;
      box-shadow: none;
    }
    .sdp-side-rail .notify-corner-badge + .sdp-side-rail-chevron,
    .sdp-side-rail .sdp-side-rail-chevron + .notify-corner-badge { margin-left: 0.25rem; }
    .sdp-side-rail .notify-corner-badge svg { width: 0.8rem; height: 0.8rem; }
    @media (prefers-reduced-motion: reduce) {
      .sdp-side-rail-chevron, .sdp-side-rail, .sdp-side-rail :is(.sdp-side-rail-title, .sdp-side-rail-sub) { transition: none !important; }
    }
    .sdp-side-rail-sub {
      list-style: none;
      margin: 0.125rem 0 0.375rem 1.4375rem;
      padding: 0 0 0 0.5rem;
      border-left: 1px solid var(--border);
    }
    .sdp-side-rail-sub[hidden] { display: none; }
    .sdp-side-rail-sub a {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      min-height: 2rem;
      padding: 0.25rem 0.5rem;
      border-radius: 0.4375rem;
      color: var(--muted);
      text-decoration: none;
      font-size: 0.8125rem;
      line-height: 1.25;
    }
    .sdp-side-rail-sub a:hover,
    .sdp-side-rail-sub a:focus-visible { background: var(--focus-soft); color: var(--text); }
    .sdp-side-rail-sub a[aria-current="page"] {
      background: var(--primary-soft);
      color: var(--text);
      font-weight: 600;
    }
    .sdp-side-rail-sub-icon { display: none; }
    .sdp-side-rail-sub-label { min-width: 0; }
    .sdp-side-rail-sub-count { color: #dc2626; font-weight: 600; }
    html[data-theme="dark"] .sdp-side-rail-sub-count { color: #f87171; }
    .sdp-side-rail-sub-dot {
      flex-shrink: 0;
      margin-left: auto;
      width: 0.45rem;
      height: 0.45rem;
      border-radius: 9999px;
      background: #ef4444;
    }
    .sdp-side-rail-sub-overview { margin-top: 0.125rem; }
    .sdp-side-rail .sdp-side-rail-sub .sdp-side-rail-sub-overview a { font-weight: 500; }
    /* Einstieg der Gruppe („Klassenübersicht" unter Meine Klassen): immer fett. */
    .sdp-side-rail .sdp-side-rail-sub a.sdp-side-rail-sub-lead { font-weight: 600; color: var(--text); }
    .sdp-side-rail .dashboard-mini-icon { display: inline-flex; align-items: center; color: var(--muted); flex-shrink: 0; }
    .sdp-side-rail .dashboard-mini-icon svg { width: 1.125rem; height: 1.125rem; }
    .sdp-side-rail.has-category-accents .sdp-side-rail-tile[data-dashboard-category] .dashboard-mini-icon {
      color: var(--cat-icon, var(--muted));
    }
    .sdp-side-rail .sdp-rail-home .dashboard-mini-icon { color: var(--text); }
    /* KI Assistenz: eigener Eintrag unter der Startseite mit kräftigem Symbol
       und violetter Schrift — sie übernimmt viele Aufgaben im Portal. Seit
       2026-11-05 OHNE Hinterlegung und Rahmen (User: „nicht farblich
       hinterlegt"); Hover und aktive Seite wie bei allen Einträgen. Farbe aus
       --ki-cat-icon (hell/dunkel), auch ohne Kategorie-Farben. */
    .sdp-side-rail .sdp-side-rail-tile.sdp-rail-ki {
      margin: 0.125rem 0;
      color: color-mix(in srgb, var(--ki-cat-icon) 55%, var(--text));
      font-weight: 600;
    }
    .sdp-side-rail .sdp-side-rail-tile.sdp-rail-ki .dashboard-mini-icon { color: var(--ki-cat-icon); }
    /* Dasselbe im Menü der Kopfzeile (Telefon-Seiten ohne Daumen-Leiste). */
    #header-nav a[data-menu-nav-group][href="/ki-assistenz"] {
      color: color-mix(in srgb, var(--ki-cat-icon) 55%, var(--text)) !important;
      background: color-mix(in srgb, var(--ki-cat-icon) 9%, transparent);
      border-radius: var(--radius-sm);
    }
    #header-nav a[data-menu-nav-group][href="/ki-assistenz"] svg { color: var(--ki-cat-icon); }
    .sdp-side-rail .dashboard-mini-badge {
      font-size: 9px;
      padding: 1px 4px;
      border-radius: 4px;
      background: #ffedd5;
      color: #9a3412;
      font-weight: 600;
      vertical-align: middle;
      margin-left: 0.15rem;
    }

    /* Profil unten in der Leiste. */
    .sdp-rail-profile {
      flex: none;
      display: flex;
      align-items: center;
      gap: 0.625rem;
      padding: 0.625rem 0.5rem 0.125rem;
      border-top: 1px solid var(--border);
      color: var(--text);
      text-decoration: none;
    }
    .sdp-rail-profile:hover .sdp-rail-profile-name { text-decoration: underline; text-underline-offset: 3px; }
    .sdp-rail-avatar {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      border-radius: 9999px;
      overflow: hidden;
      background: var(--surface-muted);
      border: 1px solid var(--border);
      color: var(--muted);
      font-size: 0.75rem;
      font-weight: 600;
    }
    .sdp-rail-avatar img { width: 100%; height: 100%; object-fit: cover; }
    .sdp-rail-profile-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
    .sdp-rail-profile-name { font-size: 0.8125rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sdp-rail-profile-sub { font-size: 0.75rem; color: var(--muted); }

    /* Kategorie-Farbakzent fuer die Titelboxen von Seiten, die von einer
       Dashboard-Kachel verlinkt werden — analog zur Kachel selbst:
       Pastell-Verlauf am linken Rand, der nach 1rem ins Transparente
       ausläuft, plus zusätzlicher Abstand zum linken Rand.
       border-color: transparent entfernt den 1px-Rand der Titelbox komplett
       (nicht nur links) — Accent-Boxen sollen randlos sein.
       Pro Kategorie wird nur die Farbe (--cat-accent-color) gesetzt. */
    :root {
      --ki-cat-accent: rgba(167, 139, 250, 0.9);
      --kommunikation-cat-accent: rgba(251, 191, 36, 0.9);
      --wissen-cat-accent: rgba(110, 231, 183, 0.9);
      --organisation-cat-accent: rgba(125, 211, 252, 0.9);
      --austausch-cat-accent: rgba(216, 180, 226, 0.9);
      --intern-cat-accent: rgba(190, 242, 100, 0.85);
      --verwaltung-cat-accent: rgba(148, 163, 184, 0.9);
      --schulorganisation-cat-accent: rgba(94, 234, 212, 0.9);
      --dateiablage-cat-accent: rgba(165, 180, 252, 0.9);
      /* Volldeckende Icon-Farbe je Kategorie (wie auf den Kacheln, --cat-icon). */
      --ki-cat-icon: #7c3aed;
      --kommunikation-cat-icon: #d97706;
      --wissen-cat-icon: #059669;
      --organisation-cat-icon: #0284c7;
      --austausch-cat-icon: #7e3a8a;
      --intern-cat-icon: #4d7c0f;
      --verwaltung-cat-icon: #475569;
      --schulorganisation-cat-icon: #0d9488;
      --dateiablage-cat-icon: #4f46e5;
    }
    html[data-theme="dark"] {
      --ki-cat-accent: rgba(139, 92, 246, 0.5);
      --kommunikation-cat-accent: rgba(245, 158, 11, 0.5);
      --wissen-cat-accent: rgba(52, 211, 153, 0.42);
      --organisation-cat-accent: rgba(56, 189, 248, 0.42);
      --austausch-cat-accent: rgba(186, 104, 200, 0.42);
      --intern-cat-accent: rgba(132, 204, 22, 0.42);
      --verwaltung-cat-accent: rgba(100, 116, 139, 0.45);
      --schulorganisation-cat-accent: rgba(45, 212, 191, 0.42);
      --dateiablage-cat-accent: rgba(129, 140, 248, 0.42);
      --ki-cat-icon: #a78bfa;
      --kommunikation-cat-icon: #fbbf24;
      --wissen-cat-icon: #34d399;
      --organisation-cat-icon: #38bdf8;
      --austausch-cat-icon: #d49be0;
      --intern-cat-icon: #a3e635;
      --verwaltung-cat-icon: #94a3b8;
      --schulorganisation-cat-icon: #2dd4bf;
      --dateiablage-cat-icon: #818cf8;
    }
    .ki-cat-accent { --cat-accent-color: var(--ki-cat-accent); --cat-icon: var(--ki-cat-icon); }
    .kommunikation-cat-accent { --cat-accent-color: var(--kommunikation-cat-accent); --cat-icon: var(--kommunikation-cat-icon); }
    .wissen-cat-accent { --cat-accent-color: var(--wissen-cat-accent); --cat-icon: var(--wissen-cat-icon); }
    .organisation-cat-accent { --cat-accent-color: var(--organisation-cat-accent); --cat-icon: var(--organisation-cat-icon); }
    .austausch-cat-accent { --cat-accent-color: var(--austausch-cat-accent); --cat-icon: var(--austausch-cat-icon); }
    .intern-cat-accent { --cat-accent-color: var(--intern-cat-accent); --cat-icon: var(--intern-cat-icon); }
    .verwaltung-cat-accent { --cat-accent-color: var(--verwaltung-cat-accent); --cat-icon: var(--verwaltung-cat-icon); }
    .schulorganisation-cat-accent { --cat-accent-color: var(--schulorganisation-cat-accent); --cat-icon: var(--schulorganisation-cat-icon); }
    .dateiablage-cat-accent { --cat-accent-color: var(--dateiablage-cat-accent); --cat-icon: var(--dateiablage-cat-icon); }
    /* Symbol der Unterkategorie vor der Überschrift auf den Übersichtsseiten
       (gleiche Kategoriefarbe wie die Mini-Kachel auf dem Dashboard). */
    .uebersicht-title-icon { display: inline-flex; align-items: center; color: var(--cat-icon, var(--text)); }
    .uebersicht-title-icon svg { width: 1.75rem; height: 1.75rem; }
    .ki-cat-accent,
    .kommunikation-cat-accent,
    .wissen-cat-accent,
    .organisation-cat-accent,
    .austausch-cat-accent,
    .intern-cat-accent,
    .verwaltung-cat-accent,
    .schulorganisation-cat-accent,
    .dateiablage-cat-accent {
      background-image: linear-gradient(to right, var(--cat-accent-color) 0%, transparent 1rem);
      background-repeat: no-repeat;
      background-size: 1rem 100%;
      background-origin: border-box;
      border-color: transparent;
      padding-left: 2rem;
    }
    @media (min-width: 640px) {
      .ki-cat-accent,
      .kommunikation-cat-accent,
      .wissen-cat-accent,
      .organisation-cat-accent,
      .austausch-cat-accent,
      .intern-cat-accent,
      .verwaltung-cat-accent,
      .schulorganisation-cat-accent,
      .dateiablage-cat-accent { padding-left: 2.25rem; }
    }
    /* In den Sidebar-Layouts (KI Assistenz / KI Agent) sitzt der Akzent nur
       am Titel-Header — die Sidebar behält ihre Breite. Eigene linke
       Polsterung (Header-Grundwert 0.75rem + 1rem) statt der Card-Werte.
       Spezifität 0,2,0 schlägt sowohl .ki-cat-accent als auch die
       template-eigene .ki-sidebar-header-Regel. */
    .ki-sidebar-header.ki-cat-accent {
      padding-left: 1.75rem;
    }
    /* Eingeklappte Sidebar: kein Titel sichtbar → kein Akzent. */
    .ki-card[data-sidebar="collapsed"] .ki-sidebar-header.ki-cat-accent {
      background-image: none;
    }

    html[data-theme="light"] button.hover\\:bg-slate-100:hover,
    html[data-theme="light"] a.hover\\:bg-slate-100:hover,
    html[data-theme="light"] [role="button"].hover\\:bg-slate-100:hover {
      background-color: #f8fafc;
    }

    html[data-theme="light"] button.hover\\:bg-slate-50:hover,
    html[data-theme="light"] a.hover\\:bg-slate-50:hover,
    html[data-theme="light"] [role="button"].hover\\:bg-slate-50:hover {
      background-color: #ffffff;
    }

    html[data-theme="light"] button.hover\\:bg-slate-50\\/40:hover,
    html[data-theme="light"] a.hover\\:bg-slate-50\\/40:hover,
    html[data-theme="light"] [role="button"].hover\\:bg-slate-50\\/40:hover,
    html[data-theme="light"] button.hover\\:bg-slate-50\\/60:hover,
    html[data-theme="light"] a.hover\\:bg-slate-50\\/60:hover,
    html[data-theme="light"] [role="button"].hover\\:bg-slate-50\\/60:hover {
      background-color: rgba(255, 255, 255, 0.9);
    }

    html[data-theme="light"] button.hover\\:bg-white:hover,
    html[data-theme="light"] a.hover\\:bg-white:hover,
    html[data-theme="light"] [role="button"].hover\\:bg-white:hover {
      background-color: #ffffff;
    }

    html[data-theme="dark"] .step-surface-1 { background-color: hsl(222 24% 16% / 0.82); }
    html[data-theme="dark"] .step-surface-2 { background-color: hsl(222 23% 17% / 0.82); }
    html[data-theme="dark"] .step-surface-3 { background-color: hsl(223 22% 18% / 0.82); }
    html[data-theme="dark"] .step-surface-4 { background-color: hsl(223 21% 19% / 0.82); }
    html[data-theme="dark"] .step-surface-5 { background-color: hsl(224 20% 20% / 0.82); }
    html[data-theme="dark"] .step-surface-6 { background-color: hsl(224 19% 21% / 0.82); }
    html[data-theme="dark"] .step-surface-7 { background-color: hsl(224 18% 22% / 0.82); }
    html[data-theme="dark"] .step-surface-8 { background-color: hsl(224 17% 23% / 0.82); }

    #tip-overlay {
      background: var(--overlay);
    }

    body.break-overlay-open {
      overflow: hidden;
    }

    .break-overlay {
      position: fixed;
      inset: 0;
      z-index: 50;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 1.5rem;
    }

    .break-overlay.hidden {
      display: none;
    }

    .break-overlay__backdrop {
      position: absolute;
      inset: 0;
      background: rgba(2, 6, 23, 0.88);
    }

    .break-overlay__panel {
      position: relative;
      z-index: 1;
      width: min(92vw, 720px);
      text-align: center;
      color: #ffffff;
    }

    .break-overlay__title {
      font-size: clamp(1.8rem, 3vw, 2.5rem);
      font-weight: 700;
      letter-spacing: -0.02em;
      margin-bottom: 1rem;
    }

    .break-overlay__options {
      display: flex;
      flex-direction: column;
      gap: 0.65rem;
      margin-bottom: 1.25rem;
    }

    .break-overlay__option {
      border: 1px solid rgba(255, 255, 255, 0.45);
      border-radius: 999px;
      padding: 0.55rem 1.3rem;
      background: rgba(255, 255, 255, 0.08);
      color: #ffffff;
      font-weight: 600;
    }

    .break-overlay__option:hover {
      background: rgba(255, 255, 255, 0.18);
    }

    .break-overlay__option.is-active {
      background: rgba(255, 255, 255, 0.25);
      border-color: rgba(255, 255, 255, 0.7);
    }

    .break-overlay__content {
      max-height: 55vh;
      overflow-y: auto;
      padding: 1.1rem 1.25rem;
      border-radius: 0.75rem;
      border: 1px solid rgba(255, 255, 255, 0.22);
      background: rgba(15, 23, 42, 0.35);
      text-align: left;
    }

    .break-overlay__content.markdown-body {
      color: #ffffff;
    }

    .break-overlay__content.markdown-body blockquote {
      color: rgba(255, 255, 255, 0.86);
      border-left-color: rgba(255, 255, 255, 0.35);
    }

    .break-overlay__content.markdown-body a {
      color: #bae6fd;
    }

    .break-overlay__content.markdown-body code,
    .break-overlay__content.markdown-body pre {
      background: rgba(15, 23, 42, 0.55);
      color: #ffffff;
    }

    .break-overlay__close {
      position: absolute;
      top: 1.5rem;
      right: 1.5rem;
      z-index: 2;
      border: 1px solid rgba(255, 255, 255, 0.5);
      border-radius: 999px;
      padding: 0.4rem 0.85rem;
      background: rgba(15, 23, 42, 0.4);
      color: #ffffff;
      font-size: 0.85rem;
    }

    .break-overlay__close:hover {
      background: rgba(15, 23, 42, 0.65);
    }

    html[data-theme="dark"] .bg-white {
      background-color: var(--surface-glass);
    }

    html[data-theme="dark"] .bg-slate-50 {
      background-color: var(--surface-muted);
    }

    html[data-theme="dark"] .bg-slate-100 {
      background-color: #0f172a;
    }

    html[data-theme="dark"] .bg-slate-200 {
      background-color: #1f2937;
    }

    html[data-theme="dark"] .bg-slate-300 {
      background-color: #1f2937;
    }

    html[data-theme="dark"] .text-slate-900,
    html[data-theme="dark"] .text-slate-800 {
      color: var(--text);
    }

    /* 2026-09-23 eine Stufe heller (vorher 700 #cbd5e1, 500 #93a3b8,
       400 #7b8aa1; 600 folgt --muted, das dieselbe Anhebung bekam). */
    html[data-theme="dark"] .text-slate-700 {
      color: #e2e8f0;
    }

    html[data-theme="dark"] .text-slate-600 {
      color: var(--muted);
    }

    html[data-theme="dark"] .text-slate-500 {
      color: #b4c0d0;
    }

    html[data-theme="dark"] .text-slate-400 {
      color: #9eadc1;
    }

    html[data-theme="dark"] .border-slate-100,
    html[data-theme="dark"] .border-slate-200 {
      border-color: var(--border);
    }

    html[data-theme="dark"] .border-slate-300 {
      border-color: #3b4658;
    }

    html[data-theme="dark"] .border-t-emerald-300 {
      border-top-color: #6ee7b7;
    }

    html[data-theme="dark"] .border-t-orange-300 {
      border-top-color: #fdba74;
    }



    html[data-theme="dark"] .hover\\:bg-slate-100:hover,
    html[data-theme="dark"] .hover\\:bg-white:hover {
      background-color: var(--surface-muted);
    }

    html[data-theme="dark"] .hover\\:bg-slate-400:hover {
      background-color: #334155;
    }

    html[data-theme="dark"] .hover\\:border-slate-300:hover {
      border-color: #3b4658;
    }

    html[data-theme="dark"] .hover\\:text-slate-700:hover,
    html[data-theme="dark"] .hover\\:text-slate-900:hover {
      color: var(--text);
    }

    html[data-theme="dark"] [class~="bg-white/80"] {
      background-color: rgba(17, 24, 39, 0.85);
    }

    html[data-theme="dark"] [class~="bg-white/70"] {
      background-color: rgba(17, 24, 39, 0.7);
    }

    html[data-theme="dark"] [class~="bg-slate-50/40"] {
      background-color: rgba(15, 23, 42, 0.6);
    }

    html[data-theme="dark"] [class~="bg-slate-50/70"] {
      background-color: rgba(15, 23, 42, 0.75);
    }

    html[data-theme="dark"] [class~="border-slate-200/80"] {
      border-color: rgba(51, 65, 85, 0.8);
    }

    html[data-theme="dark"] .bg-amber-50 {
      background-color: rgba(120, 83, 9, 0.15);
    }

    html[data-theme="dark"] .bg-amber-100 {
      background-color: rgba(120, 83, 9, 0.22);
    }

    html[data-theme="dark"] .text-amber-900,
    html[data-theme="dark"] .text-amber-800,
    html[data-theme="dark"] .text-amber-700 {
      color: #fbbf24;
    }

    html[data-theme="dark"] .text-amber-600 {
      color: #fcd34d;
    }

    html[data-theme="dark"] .border-amber-200 {
      border-color: rgba(245, 158, 11, 0.3);
    }

    html[data-theme="dark"] .border-amber-400 {
      border-color: rgba(245, 158, 11, 0.45);
    }

    html[data-theme="dark"] .bg-green-50 {
      background-color: rgba(22, 101, 52, 0.15);
    }

    html[data-theme="dark"] .bg-green-100 {
      background-color: rgba(22, 101, 52, 0.22);
    }

    html[data-theme="dark"] .bg-emerald-50 {
      background-color: rgba(6, 95, 70, 0.15);
    }

    html[data-theme="dark"] .bg-emerald-100 {
      background-color: rgba(6, 95, 70, 0.22);
    }

    html[data-theme="dark"] .text-green-900,
    html[data-theme="dark"] .text-green-800,
    html[data-theme="dark"] .text-green-700 {
      color: #4ade80;
    }

    html[data-theme="dark"] .text-green-600 {
      color: #86efac;
    }

    html[data-theme="dark"] .text-emerald-900,
    html[data-theme="dark"] .text-emerald-800,
    html[data-theme="dark"] .text-emerald-700 {
      color: #34d399;
    }

    html[data-theme="dark"] .text-emerald-600 {
      color: #6ee7b7;
    }

    html[data-theme="dark"] .border-green-100,
    html[data-theme="dark"] .border-green-200 {
      border-color: rgba(22, 163, 74, 0.3);
    }

    html[data-theme="dark"] .border-emerald-200 {
      border-color: rgba(16, 185, 129, 0.3);
    }

    html[data-theme="dark"] .border-l-red-500 {
      border-left-color: #f87171;
    }

    /* WYSIWYG-Editor (Toast UI): der Text im Editor (Bearbeiten + Vorschau)
       nutzt das normale Schriftgewicht statt der globalen Light-300-Schrift
       aus body — Light 300 ist beim Schreiben schwer zu lesen. */
    .toastui-editor-contents,
    .toastui-editor-defaultUI .ProseMirror {
      font-weight: 400;
    }

    html[data-theme="dark"] .toastui-editor-defaultUI {
      background-color: var(--surface);
      border-color: var(--border);
      color: var(--text);
    }

    html[data-theme="dark"] .toastui-editor-toolbar {
      background-color: var(--surface);
      border-bottom-color: var(--border);
    }

    html[data-theme="dark"] .toastui-editor-toolbar-divider {
      background-color: var(--border);
    }

    html[data-theme="dark"] .toastui-editor-toolbar-icons {
      filter: invert(1) hue-rotate(180deg);
      opacity: 0.9;
    }

    html[data-theme="dark"] .toastui-editor-toolbar button:hover,
    html[data-theme="dark"] .toastui-editor-toolbar button.active {
      background-color: var(--surface-muted);
    }

    html[data-theme="dark"] .toastui-editor-ww-container,
    html[data-theme="dark"] .toastui-editor-md-container {
      background-color: var(--input-bg);
      color: var(--text);
    }

    html[data-theme="dark"] .toastui-editor-contents,
    html[data-theme="dark"] .toastui-editor-contents p,
    html[data-theme="dark"] .toastui-editor-contents li,
    html[data-theme="dark"] .toastui-editor-contents table,
    html[data-theme="dark"] .toastui-editor-contents pre,
    html[data-theme="dark"] .toastui-editor-contents blockquote,
    html[data-theme="dark"] .toastui-editor-ww-container .ProseMirror {
      color: var(--text);
    }

    html[data-theme="dark"] .toastui-editor-ww-container .ProseMirror {
      background-color: var(--input-bg);
    }

    html[data-theme="dark"] .toastui-editor-mode-switch {
      background-color: var(--surface);
      border-top-color: var(--border);
    }

    html[data-theme="dark"] .toastui-editor-mode-switch .tab-item {
      color: var(--muted);
    }

    html[data-theme="dark"] .toastui-editor-mode-switch .tab-item.active {
      color: var(--text);
      background-color: var(--surface-muted);
      border-color: var(--border);
    }

    /* Toast-UI-Popups (z.B. Heading-Auswahl) haben keine eigene Textfarbe und
       wuerden die helle main-Textfarbe (#f1f5f9) erben — auf dem weissen
       Popup-Hintergrund waere der Text unsichtbar. Explizit dunkel setzen. */
    .toastui-editor-popup {
      color: #111827;
    }

    html[data-theme="dark"] .toastui-editor-popup {
      background-color: var(--surface);
      color: var(--text);
      border-color: var(--border);
      box-shadow: var(--shadow);
    }

    html[data-theme="dark"] .toastui-editor-popup-body input,
    html[data-theme="dark"] .toastui-editor-popup-body textarea {
      background: var(--input-bg);
      border-color: var(--input-border);
      color: var(--text);
    }

    html[data-theme="dark"] .toastui-editor-toolbar .toastui-editor-toolbar-group {
      background-color: transparent;
    }

    html[data-theme="dark"] .toastui-editor-toolbar button {
      color: var(--text);
    }

    html[data-theme="dark"] .toastui-editor-toolbar button:hover,
    html[data-theme="dark"] .toastui-editor-toolbar button:focus {
      background-color: var(--surface-muted);
    }

    html[data-theme="dark"] .toastui-editor-dropdown-toolbar {
      background-color: var(--surface);
      border-color: var(--border);
      color: var(--text);
    }

    /* Sitzungs-Warnung an der Stelle der Toasts (über dem Assistent-Vogel,
       Telefon unten mittig) — vorher lag der Vogel (z-90) darüber. */
    .session-toast {
      position: fixed;
      right: 1rem;
      bottom: calc(4.85rem + env(safe-area-inset-bottom, 0px));
      max-width: min(92vw, 360px);
      background: var(--surface);
      color: var(--text);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
      padding: 0.85rem 1rem;
      opacity: 0;
      transform: translateY(10px) scale(0.98);
      transition: opacity 0.25s ease, transform 0.25s ease;
      pointer-events: none;
      z-index: 1100;
    }

    .session-toast.is-visible {
      opacity: 1;
      transform: translateY(0) scale(1);
      pointer-events: auto;
    }

    .session-toast__title {
      font-weight: 600;
      font-size: 0.92rem;
    }

    .session-toast__message {
      margin-top: 0.25rem;
      font-size: 0.82rem;
      color: var(--muted);
    }

    .session-toast__actions {
      margin-top: 0.65rem;
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .session-toast__action {
      border: 1px solid var(--border);
      background: var(--surface-muted);
      color: var(--text);
      padding: 0.35rem 0.75rem;
      border-radius: var(--radius-sm);
      font-size: 0.82rem;
      font-weight: 600;
    }
    @media (max-width: 640px) {
      .session-toast {
        right: auto;
        left: 50%;
        bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px) + var(--sdp-bnav-h, 0px));
        width: min(24rem, calc(100vw - 1.5rem));
        max-width: none;
        transform: translate(-50%, 10px) scale(0.98);
      }
      .session-toast.is-visible { transform: translate(-50%, 0); }
    }

    .pwa-install-banner {
      position: fixed;
      right: 1rem;
      bottom: calc(1rem + env(safe-area-inset-bottom) + var(--sdp-bnav-h, 0px));
      max-width: min(92vw, 360px);
      background: var(--surface);
      color: var(--text);
      border: 1px solid var(--border);
      border-radius: 0.75rem;
      box-shadow: var(--shadow);
      padding: 0.85rem 1rem;
      display: none;
      z-index: 70;
    }

    .pwa-install-banner.is-visible {
      display: block;
    }

    /* Push-Opt-in-Banner über dem PWA-Install-Banner stapeln, falls beide sichtbar sind. */
    .sdp-push-optin-banner {
      bottom: calc(7.5rem + env(safe-area-inset-bottom) + var(--sdp-bnav-h, 0px));
      z-index: 71;
    }

    .pwa-install-title {
      font-weight: 600;
      font-size: 0.9rem;
    }

    .pwa-install-text {
      margin-top: 0.25rem;
      font-size: 0.82rem;
      color: var(--muted);
    }

    .pwa-install-actions {
      margin-top: 0.65rem;
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .pwa-install-button {
      border: 1px solid var(--border);
      background: var(--surface-muted);
      color: var(--text);
      padding: 0.35rem 0.75rem;
      border-radius: 0.5rem;
      font-size: 0.82rem;
      font-weight: 600;
    }

    .pwa-dismiss-button {
      background: transparent;
      border: none;
      color: var(--muted);
      font-size: 0.8rem;
      text-decoration: underline;
      padding: 0.35rem 0.4rem;
    }

    @media (max-width: 640px) {
      .pwa-install-banner {
        left: 1rem;
        right: 1rem;
        max-width: calc(100vw - 2rem);
      }
    }

    .confetti-container {
      position: fixed;
      inset: 0;
      pointer-events: none;
      overflow: hidden;
      z-index: 80;
    }

    .confetti-piece {
      position: absolute;
      top: -12vh;
      width: var(--size, 10px);
      height: calc(var(--size, 10px) * 1.4);
      background: var(--color, #38bdf8);
      opacity: 0.9;
      border-radius: 2px;
      transform: translate3d(0, -10vh, 0) rotate(0deg);
      animation: confetti-fall var(--duration, 3.4s) ease-out forwards;
    }

    @keyframes confetti-fall {
      0% {
        opacity: 0;
        transform: translate3d(0, -10vh, 0) rotate(0deg);
      }
      10% {
        opacity: 1;
      }
      100% {
        opacity: 0;
        transform: translate3d(var(--drift, 0px), 110vh, 0) rotate(720deg);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .confetti-piece {
        animation: none;
      }
    }

    /* ── Contextual help system ────────────────────────────── */
    .sdp-help-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.125rem;
      height: 1.125rem;
      /* min-* explizit mitfuehren: sonst kann eine generische Regel (z.B. die
         44px-Touch-Target-Regel) allein die Hoehe hochziehen und aus dem Kreis
         wird ein Oval. */
      min-width: 1.125rem;
      min-height: 1.125rem;
      padding: 0;
      line-height: 1;
      border-radius: 9999px;
      border: 1.5px solid #3b82f6;
      color: #2563eb;
      background: rgba(59, 130, 246, 0.08);
      cursor: pointer;
      transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
      vertical-align: middle;
      margin-left: 0.25rem;
      flex-shrink: 0;
    }
    .sdp-help-icon:hover,
    .sdp-help-icon[aria-expanded="true"] {
      color: #1d4ed8;
      border-color: #1d4ed8;
      background: rgba(59, 130, 246, 0.15);
    }
    html.sdp-help-icons-hidden .sdp-help-icon {
      display: none;
    }
    /* Einzelne Icons bleiben sichtbar, auch wenn der Hilfe-Modus aus ist. */
    html.sdp-help-icons-hidden .sdp-help-icon.sdp-help-icon-always {
      display: inline-flex;
    }

    /* Auf Mobile: Inline-Hilfe-Icons (nur in der Seite, nicht der Header-
       Button #sdp-help-mode-btn) ohne Rahmen und Hintergrund. Nur das
       blaue "?" bleibt sichtbar. Muss nach dem Default-Block stehen, sonst
       uebersteuert der Default die Regel wieder. */
    @media (max-width: 640px) {
      .sdp-help-icon {
        border: 0;
        background: transparent;
      }
      .sdp-help-icon:hover,
      .sdp-help-icon[aria-expanded="true"] {
        border: 0;
        background: transparent;
      }
    }
    /* Dauerhaft sichtbare Icons (always=True) behalten in JEDEM UI-Modus den
       vollen blauen Akzent und sind etwas groesser — sie stehen allein da und
       muessen ohne den Hilfe-Modus als Info-Symbol erkennbar sein. Muss NACH
       dem "optimized"- und dem Mobile-Block stehen, sonst wirkungslos. */
    html .sdp-help-icon.sdp-help-icon-always {
      width: 1.25rem;
      height: 1.25rem;
      min-width: 1.25rem;
      min-height: 1.25rem;
      opacity: 1;
      border: 1.5px solid #2563eb;
      color: #2563eb;
      background: rgba(37, 99, 235, 0.12);
    }
    html .sdp-help-icon.sdp-help-icon-always:hover,
    html .sdp-help-icon.sdp-help-icon-always[aria-expanded="true"] {
      border-color: #1d4ed8;
      color: #1d4ed8;
      background: rgba(37, 99, 235, 0.22);
    }
    html .sdp-help-icon.sdp-help-icon-always svg {
      width: 0.875rem;
      height: 0.875rem;
    }

    .sdp-help-popover {
      position: absolute;
      z-index: 1100;
      max-width: 20rem;
      /* Hilfetexte duerfen Absaetze (\n) enthalten, z. B. Kurzanleitungen
         je Plattform; Leerzeichen werden weiter normal kollabiert. */
      white-space: pre-line;
      padding: 0.75rem 1rem;
      border-radius: 0.5rem;
      border: 1px solid var(--border);
      background: var(--surface);
      color: var(--text);
      box-shadow: var(--shadow);
      font-size: 0.8125rem;
      line-height: 1.5;
      animation: sdp-help-fadein 150ms ease;
    }
    @keyframes sdp-help-fadein {
      from { opacity: 0; transform: translateY(4px); }
      to   { opacity: 1; transform: translateY(0); }
    }
    /* Page-level help panel */
    .sdp-help-panel {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      width: 22rem;
      max-width: 90vw;
      z-index: 50;
      background: var(--surface);
      border-left: 1px solid var(--border);
      box-shadow: -8px 0 30px rgba(0,0,0,0.12);
      transform: translateX(100%);
      transition: transform 250ms ease;
      overflow-y: auto;
      padding: 1.5rem;
    }
    .sdp-help-panel.is-open {
      transform: translateX(0);
    }
    .sdp-help-panel-backdrop {
      position: fixed;
      inset: 0;
      z-index: 49;
      background: var(--overlay);
      opacity: 0;
      transition: opacity 250ms ease;
      pointer-events: none;
    }
    .sdp-help-panel-backdrop.is-open {
      opacity: 1;
      pointer-events: auto;
    }
    /* Help edge tab (rechter Bildschirmrand, kleiner als die Werkzeuge-Lasche auf der Bearbeiten-Seite) */
    .sdp-help-edge-tab {
      position: fixed;
      top: 35%;
      right: 0;
      transform: translateY(-50%);
      z-index: 40;
      background: var(--surface);
      color: var(--text);
      border: 1px solid var(--border);
      border-right: 0;
      border-radius: 0.625rem 0 0 0.625rem;
      padding: 0.625rem 0.375rem;
      cursor: pointer;
      font-weight: 600;
      font-size: 0.75rem;
      box-shadow: var(--shadow);
      writing-mode: vertical-rl;
      text-orientation: mixed;
      display: inline-flex;
      align-items: center;
      gap: 0.3rem;
      transition: opacity 200ms ease, visibility 200ms ease;
    }
    .sdp-help-edge-tab:hover,
    .sdp-help-edge-tab:focus-visible {
      font-weight: 800;
    }
    .sdp-help-edge-tab.is-hidden {
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
    }
    .sdp-help-edge-tab svg {
      width: 0.75rem;
      height: 0.75rem;
    }
    /* Am Telefon gibt es die Lasche nicht (User-Entscheidung 2026-09-25): die
       fixierte Lasche lag dort über rechtsbündigen Bedienelementen – u. a. fing
       sie jeden Tipp auf das ⋮-Klassenmenü der Abwesenheiten ab (Demo-Durchgang
       2026-09-24). Die Hilfe öffnet dort der (?)-Knopf der Kopfzeile. */
    @media (max-width: 640px) {
      .sdp-help-edge-tab { display: none; }
    }
    /* Hilfe-Modus: die Symbole tragen einen ruhigen Fokusring statt zu
       pulsieren (optische Auffrischung Phase 7, „Ruhe statt Effekt"). */
    html.sdp-help-mode .sdp-help-icon {
      border-color: #2563eb;
      color: #2563eb;
      box-shadow: var(--focus-ring);
    }

    /* Der Hilfe-Knopf der Kopfzeile pulsiert nicht mehr blau — er ist ein
       Geister-Kreis wie Suche und Menü (Optik-Tokens, Phase 4). */

    /* Auto-Öffnen der Hilfe beim ersten Aufruf: der Schließen-Knopf trägt
       einen ruhigen Fokusring in der Primärfarbe, damit ersichtlich ist, wie
       man schließt — kein dicker, pulsierender blauer Ring mehr (Phase 7). */
    #sdp-help-panel-close.sdp-help-close-attention {
      color: var(--primary-line);
      border-radius: 9999px;
      box-shadow: var(--focus-ring);
    }

    /* ── Unsichtbare Tabellen-Beschriftungen im Bild halten ──────────────
       .sr-only ist absolut positioniert. Steckt eine breite Tabelle in einem
       overflow-x-Scroller, der selbst kein Containing Block ist, entkommt so
       ein Text (typisch der Spaltenkopf „Aktionen" ganz rechts) dem Clipping
       — am Telefon wurde dadurch die GANZE Seite so breit wie die Tabelle
       (Rahmenlehrpläne 1.020 px, Berechtigungsmatrix 1.067 px), die Kopfzeile
       rutschte mitten in den Inhalt. An die linke Kante gesetzt bleibt der
       Text im Bild; sehen kann man ihn ohnehin nicht. */
    :is(th, td) .sr-only { left: 0; }

    /* ── Titelbox-Beschreibung: auf Mobile auf 2 Zeilen kuerzen ──────────
       Spart Platz und laesst die Titelboxen aller Seiten aehnlich hoch
       ausfallen. Der Rest wird per Klick auf den Text (oder den
       "mehr"-Schalter) eingeblendet. Verdrahtung: sdpTitleDescClamp-IIFE
       am Ende von base.html — die Struktur (Wrapper + Schalter) baut das
       Skript zur Laufzeit, damit nicht ~140 Templates angefasst werden
       muessen. `screen` ist bewusst gesetzt: im Druck nie kuerzen. */
    /* Standardmaessig unsichtbar — auch im Druck und auf Desktop, wo der
       Wrapper nach einem Resize noch im DOM stehen kann. Sichtbar wird der
       Schalter ausschliesslich durch die Regel im @media-Block unten. */
    .sdp-desc-toggle {
      display: none;
      align-items: center;
      gap: 0.2rem;
      margin-top: 0.15rem;
      padding: 0;
      border: 0;
      background: transparent;
      font-family: inherit;
      font-size: 0.6875rem;
      font-weight: 600;
      line-height: 1.1;
      color: var(--muted);
      cursor: pointer;
    }
    .sdp-desc-toggle svg {
      width: 0.75rem;
      height: 0.75rem;
      transition: transform 150ms ease;
    }
    .sdp-desc-toggle:hover,
    .sdp-desc-toggle:focus-visible {
      color: var(--text);
    }
    .sdp-desc-collapsible {
      position: relative;
    }
    @media screen and (max-width: 640px) {
      /* Eingeklappt: genau zwei Zeilen. `padding-right` haelt am rechten Rand
         Platz frei, in dem der "mehr"-Schalter absolut in der ZWEITEN Zeile
         sitzt — er braucht so keine eigene Zeile und die Box bleibt exakt
         zwei Zeilen hoch. `--sdp-desc-lh` setzt das Skript aus der gemessenen
         Zeilenhoehe der Beschreibung, damit der Schalter genau auf der
         letzten Zeile sitzt (Beschreibungen sind mal text-sm, mal text-xs). */
      .sdp-desc-collapsible.is-clamped > .sdp-desc-text {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
        cursor: pointer;
        padding-right: 3.25rem;
      }
      .sdp-desc-collapsible.is-clamped > .sdp-desc-toggle {
        display: inline-flex;
        position: absolute;
        right: 0;
        bottom: 0;
        margin-top: 0;
        line-height: var(--sdp-desc-lh, 1.1);
      }
      /* Ausgeklappt: voller Textfluss, Schalter wieder normal darunter. */
      .sdp-desc-collapsible.is-clamped.is-expanded > .sdp-desc-text {
        display: block;
        overflow: visible;
        -webkit-line-clamp: unset;
        line-clamp: unset;
        padding-right: 0;
      }
      .sdp-desc-collapsible.is-clamped.is-expanded > .sdp-desc-toggle {
        position: static;
        margin-top: 0.15rem;
        line-height: 1.1;
      }
      .sdp-desc-collapsible.is-expanded > .sdp-desc-toggle svg {
        transform: rotate(180deg);
      }
    }

    /* ===== "Mehr …" in den Uebersichts-Kacheln =====
       Blendet das Beispiel einer Kachel (macros/overview_tile.html) erst auf
       Klick ein. Der Schalter ist bewusst ein <span role="button"> — die
       Kachel selbst ist ein <a>, und ein <button> darin waere ungueltiges
       Markup. Deshalb greift auch die 44px-Touch-Regel fuer Buttons hier
       nicht; der Schalter sitzt inline am Ende der Beschreibung. */
    .ov-more {
      margin-left: 0.35rem;
      font-size: 0.75rem;
      font-weight: 400;
      white-space: nowrap;
      cursor: pointer;
      text-decoration: underline;
      text-decoration-style: dotted;
      text-underline-offset: 0.15em;
    }
    .ov-more:hover,
    .ov-more:focus-visible {
      color: var(--text);
    }
    .ov-example[hidden] { display: none; }

    /* Das Frosted-Glass-Design (Milchglas-Boxen ueber dem Hintergrundbild,
       Umschalter im Footer) ist mit Entwurf A (2026-09-24) entfallen: auf
       allen Breiten gilt die Vollflaechige Ansicht am Ende dieses
       Stylesheets. Regel: .claude/rules/vollflaechige-ansicht.md. */

    /* ✕ fuer Vollbild-Blaetter (macros/modal.html → sheet_close): nur auf
       dem Telefon IN einer Blatt-Kopfzeile sichtbar (Mobil-Block unten). */
    .sdp-sheet-x { display: none; }

    /* ===== Titelbox-Aktionen (seit 2026-09-24, title-actions.md) =====
       EINE Leiste unter Titel und Beschreibung: Werkzeuge | gedämpfte
       Verwaltung | Hauptaktion rechts (am Schreibtisch ab 1025 px vorn). Markup über macros/title_actions.html.
       Das Skript am Ende dieser Seite setzt die Stufen: erst verlieren die
       gedämpften Aktionen ihren Text (lv1), dann alle Werkzeuge (lv2), zuletzt
       die Hauptaktion (lv3) — immer nur so weit, bis die Zeile passt. Ab 7
       Aktionen wandert der Rest in „Mehr" (Schreibtisch: Menü, Telefon:
       Aktionsblatt). Ohne Skript bricht die Leiste einfach um. */
    .sdp-actions {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.125rem;
      margin: 0.6rem 0 0 -0.45rem;
      min-width: 0;
    }
    .sdp-actions.is-fitted { flex-wrap: nowrap; }
    .sdp-actions-group {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      min-width: 0;
    }
    /* Gemessen wird der Überlauf der LEISTE: Gruppen dürfen dafür nicht
       schrumpfen — sonst überlappen die Knöpfe still und scrollWidth sieht
       nichts (gemessen: 6 Aktionen übereinander auf 390 px). */
    .sdp-actions.is-fitted .sdp-actions-group { flex-wrap: nowrap; flex-shrink: 0; min-width: auto; }
    /* Leere Gruppen (alles per Rechte-Bedingung weg oder versteckt) fallen raus;
       der Trennstrich steht nur, wenn VOR der Gruppe schon etwas sichtbar ist. */
    .sdp-actions-group:not(:has(> :not(.hidden, [hidden]))) { display: none; }
    .sdp-actions-group:has(> :not(.hidden, [hidden])) ~ .sdp-actions-group::before {
      content: "";
      flex: none;
      width: 1px;
      height: 1rem;
      margin: 0 0.3rem;
      background: var(--border);
    }
    /* Gleiche Falle wie im Kind-Fenster (vollflaechige-ansicht.md): die display-Regeln
       unten stehen NACH tailwind.css und schlügen .hidden — Knöpfe, die ein
       Skript per .hidden/[hidden] ausblendet (Auswahl-Aktionen der
       Dateiablage), blieben sonst sichtbar. */
    .sdp-actions :is(.hidden, [hidden]),
    .sdp-actions-menu-list :is(.hidden, [hidden]) { display: none !important; }
    .sdp-action-form { display: contents; }
    .sdp-action-wrap { position: relative; display: inline-flex; flex: none; }
    .sdp-action {
      position: relative;
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      height: 1.75rem;
      padding: 0 0.45rem;
      border: 0;
      border-radius: var(--radius-sm);
      background: transparent;
      color: var(--text);
      font-family: inherit;
      font-size: 0.8125rem;
      font-weight: 700;
      line-height: 1;
      white-space: nowrap;
      text-decoration: none;
      cursor: pointer;
      transition: background 120ms ease;
    }
    .sdp-action:hover,
    .sdp-action:focus-visible,
    .sdp-action[aria-expanded="true"] {
      background: var(--focus-soft);
      color: var(--text);
      text-decoration: none;
    }
    .sdp-action:disabled,
    .sdp-action[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
    .sdp-action-icon {
      width: 0.95rem;
      height: 0.95rem;
      flex: none;
      color: var(--sdp-actions-cat, var(--text));
    }
    .sdp-action-label {
      display: inline-block;
      overflow: hidden;
      max-width: 18rem;
      margin-left: 0.3rem;
    }
    .sdp-action-count { margin-left: 0.2rem; font-weight: 600; color: var(--muted); }
    .sdp-action-chevron { width: 0.75rem; height: 0.75rem; margin-left: 0.15rem; flex: none; color: var(--muted); }
    .sdp-action--quiet { color: var(--muted); font-weight: 600; }
    .sdp-action--quiet:hover,
    .sdp-action--quiet:focus-visible { color: var(--text); }
    .sdp-action--quiet .sdp-action-icon { color: var(--muted); }
    .sdp-action--danger,
    .sdp-action--danger:hover,
    .sdp-action--danger:focus-visible { color: #dc2626; font-weight: 600; }
    .sdp-action--danger .sdp-action-icon { color: currentColor; }
    html[data-theme="dark"] .sdp-action--danger,
    html[data-theme="dark"] .sdp-action--danger:hover,
    html[data-theme="dark"] .sdp-action--danger:focus-visible { color: #f87171; }
    /* Hauptaktion: so hoch wie die übrigen, gefüllt in der Primärfarbe (wie .btn-primary). */
    .sdp-action-primary {
      position: relative;
      flex: none;
      margin-left: auto;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      height: 1.75rem;
      padding: 0 0.625rem 0 0.45rem;
      border: 1px solid var(--primary-border);
      border-radius: var(--radius-sm);
      background: var(--primary);
      color: var(--on-primary);
      font-family: inherit;
      font-size: 0.8125rem;
      font-weight: 700;
      line-height: 1;
      white-space: nowrap;
      text-decoration: none;
      cursor: pointer;
      transition: background 120ms ease;
    }
    .sdp-action-primary:hover:not(:disabled),
    .sdp-action-primary:focus-visible { background: var(--primary-hover); color: var(--on-primary); text-decoration: none; }
    .sdp-action-primary:disabled { opacity: 0.55; cursor: not-allowed; }
    .sdp-action-primary .sdp-action-icon { width: 0.875rem; height: 0.875rem; color: currentColor; }
    .sdp-action-primary .sdp-action-label { margin-left: 0.25rem; }
    /* Stufen (kumulativ gesetzt: lv2 trägt auch lv1). */
    .sdp-actions--lv1 .sdp-actions-group--quiet .sdp-action-label,
    .sdp-actions--lv1 .sdp-actions-group--quiet .sdp-action-count,
    .sdp-actions--lv2 .sdp-actions-group .sdp-action-label,
    .sdp-actions--lv2 .sdp-actions-group .sdp-action-count,
    .sdp-actions--lv3 .sdp-action-primary .sdp-action-label {
      max-width: 0;
      margin-left: 0;
      opacity: 0;
    }
    .sdp-actions--lv2 .sdp-actions-group .sdp-action-chevron { display: none; }
    .sdp-actions--lv3 .sdp-action-primary { padding: 0 0.45rem; }
    /* Schreibtisch (ab 1025 px, volle Breite): die Hauptaktion steht VORN
       statt ganz rechts (User 2026-11-05) — auf 1920 px lag „Neues Quiz"
       sonst eine Bildschirmbreite vom Titel entfernt. Nur die Reihenfolge
       ändert sich (order), das Markup und die Tab-Reihenfolge bleiben;
       margin-left gleicht den negativen Leistenrand aus, damit die gefüllte
       Fläche bündig mit dem Titel beginnt. Tablet und Telefon: rechts. */
    @media screen and (min-width: 1025px) {
      .sdp-actions > .sdp-action-primary,
      .sdp-actions > .sdp-action-form > .sdp-action-primary,
      .sdp-actions > .sdp-action-wrap:has(> .sdp-action-primary) {
        order: -1;
        margin-left: 0.45rem;
        margin-right: 0.5rem;
      }
    }
    /* Touch: 44 px Fingerfläche. Die Hauptaktion bleibt sichtbar schlank
       (2 rem) und bekommt die Fläche über einen unsichtbaren Rand — sie ist
       deshalb in der globalen min-height-Regel ausgenommen. */
    @media (hover: none) and (pointer: coarse) {
      .sdp-action { min-height: 2.75rem; }
      .sdp-action-primary { height: 2rem; }
      .sdp-action-primary::before {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: -0.375rem;
        bottom: -0.375rem;
      }
    }
    /* Telefon, Symbolstufe: Symbole gleichmäßig über die Breite verteilt. */
    @media screen and (max-width: 640px) {
      .sdp-actions { margin-left: 0; }
      .sdp-actions--lv2 { gap: 0; }
      .sdp-actions--lv2 .sdp-actions-group { display: contents; }
      /* Höchstbreite: bei nur zwei, drei Symbolen stünden sie sonst über die
         halbe Zeile verteilt (gemessen: 115 px je Symbol in der
         Quiz-Bibliothek); so rücken sie zusammen, die Hauptaktion bleibt rechts. */
      .sdp-actions--lv2 .sdp-actions-group .sdp-action,
      .sdp-actions--lv2 .sdp-actions-group .sdp-action-wrap {
        flex: 1 1 0;
        min-width: 2.25rem;
        max-width: 3.25rem;
        padding: 0;
      }
      .sdp-actions--lv2 .sdp-action-wrap > .sdp-action { width: 100%; }
      .sdp-actions--lv2 .sdp-actions-group .sdp-action-icon { width: 1.1rem; height: 1.1rem; }
      .sdp-actions--lv2 .sdp-action-primary { margin-left: 0.4rem; }
    }
    /* „Mehr": Menü am Schreibtisch, Aktionsblatt auf dem Telefon. Hängt an
       <body> (sonst im Stacking-Context von #page-main gefangen). */
    .sdp-actions-menu {
      position: absolute;
      z-index: 60;
      min-width: 14rem;
      max-width: calc(100vw - 1rem);
      padding: 0.35rem;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
    }
    .sdp-actions-menu[hidden],
    .sdp-actions-scrim[hidden] { display: none; }
    .sdp-actions-menu-head { display: none; }
    .sdp-actions-menu .sdp-action-form,
    .sdp-actions-menu .sdp-action-wrap { display: block; }
    .sdp-actions-menu .sdp-action,
    .sdp-actions-menu .sdp-action-primary {
      display: flex;
      width: 100%;
      height: auto;
      min-height: 2.25rem;
      margin: 0;
      padding: 0.4rem 0.6rem;
      justify-content: flex-start;
      border-radius: var(--radius-sm);
      font-size: 0.875rem;
      font-weight: 600;
    }
    .sdp-actions-menu .sdp-action-label,
    .sdp-actions-menu .sdp-action-count { max-width: none; opacity: 1; }
    .sdp-actions-menu .sdp-action-label { margin-left: 0.6rem; }
    .sdp-actions-menu .sdp-action-chevron { display: none; }
    .sdp-actions-scrim { position: fixed; inset: 0; z-index: 59; background: var(--overlay); }
    @media print {
      .sdp-actions,
      .sdp-actions-menu,
      .sdp-actions-scrim { display: none !important; }
    }
    @media screen and (min-width: 641px) {
      .sdp-actions-scrim { display: none; }
    }
    @media screen and (max-width: 640px) {
      .sdp-actions-menu {
        position: fixed;
        left: 0 !important;
        right: 0;
        top: auto !important;
        bottom: 0;
        max-width: none;
        max-height: 80dvh;
        overflow-y: auto;
        padding: 0.5rem 1rem calc(1rem + env(safe-area-inset-bottom));
        border-width: 1px 0 0;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
      }
      .sdp-actions-menu-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.75rem;
        padding: 0.25rem 0 0.5rem;
        margin-bottom: 0.25rem;
        border-bottom: 1px solid var(--border);
      }
      .sdp-actions-menu-title { font-size: 1rem; font-weight: 700; color: var(--text); }
      .sdp-actions-menu-close {
        width: 2.75rem;
        height: 2.75rem;
        border-radius: 999px;
        border: 1px solid var(--border);
        background: transparent;
        color: var(--text);
        display: inline-flex;
        align-items: center;
        justify-content: center;
      }
      .sdp-actions-menu .sdp-action,
      .sdp-actions-menu .sdp-action-primary { min-height: 3rem; font-size: 1rem; }
    }

    /* ===== Zeilenmenü „⋯" (Phase 1b der optischen Auffrischung) =====
       Markup über macros/row_menu.html bzw. window.sdpRowMenu (Skript unten).
       Seltene und gefährliche Aktionen einer Listenzeile — allen voran
       Löschen — stehen hier statt als roter Rahmenknopf in jeder Zeile. Das
       Menü bleibt im DOM der Zeile und liegt per position: fixed über allem,
       was die Zeile beschneidet (overflow-x der Tabellen). */
    .sdp-row-menu { position: relative; display: inline-flex; flex: none; vertical-align: middle; }
    .sdp-row-menu-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      padding: 0;
      border: 1px solid transparent;
      border-radius: var(--radius-sm);
      background: transparent;
      color: var(--muted);
      cursor: pointer;
    }
    .sdp-row-menu-btn:hover,
    .sdp-row-menu-btn[aria-expanded="true"] { background: var(--focus-soft); color: var(--text); }
    .sdp-row-menu-icon { width: 1.25rem; height: 1.25rem; flex: none; }
    .sdp-row-menu-list {
      position: fixed;
      z-index: 70;
      min-width: 12rem;
      max-width: calc(100vw - 1rem);
      padding: 0.3rem;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
      text-align: left;
    }
    .sdp-row-menu-list[hidden] { display: none !important; }
    .sdp-row-menu-list :is(.hidden, [hidden]) { display: none !important; }
    .sdp-row-menu-form { display: contents; }
    .sdp-row-menu-item {
      position: relative;
      display: flex;
      align-items: center;
      gap: 0.6rem;
      width: 100%;
      min-height: 2.25rem;
      margin: 0;
      padding: 0.4rem 0.6rem;
      border: 0;
      border-radius: var(--radius-sm);
      background: transparent;
      color: var(--text);
      font: inherit;
      font-size: 0.875rem;
      font-weight: 600;
      line-height: 1.25;
      text-align: left;
      text-decoration: none;
      white-space: nowrap;
      cursor: pointer;
    }
    .sdp-row-menu-item:hover,
    .sdp-row-menu-item:focus-visible { background: var(--focus-soft); color: var(--text); text-decoration: none; }
    .sdp-row-menu-item:disabled { opacity: 0.5; cursor: not-allowed; }
    .sdp-row-menu-item-icon { width: 1rem; height: 1rem; flex: none; color: var(--muted); }
    .sdp-row-menu-item--danger,
    .sdp-row-menu-item--danger:hover,
    .sdp-row-menu-item--danger:focus-visible { color: var(--danger); }
    .sdp-row-menu-item--danger .sdp-row-menu-item-icon { color: currentColor; }
    /* Löschen steht zuletzt, abgesetzt durch eine feine Linie. */
    .sdp-row-menu-list > .sdp-row-menu-item--danger:not(:first-child),
    .sdp-row-menu-list > .sdp-row-menu-form:not(:first-child) > .sdp-row-menu-item--danger { margin-top: 0.5rem; }
    .sdp-row-menu-list > .sdp-row-menu-item--danger:not(:first-child)::before,
    .sdp-row-menu-list > .sdp-row-menu-form:not(:first-child) > .sdp-row-menu-item--danger::before {
      content: "";
      position: absolute;
      left: 0.35rem;
      right: 0.35rem;
      top: -0.3rem;
      height: 1px;
      background: var(--border);
      pointer-events: none;
    }
    @media (hover: none) and (pointer: coarse) {
      .sdp-row-menu-item { min-height: 2.75rem; font-size: 1rem; }
    }
    @media print {
      .sdp-row-menu { display: none !important; }
    }

    /* Knopfhöhe (Phase 1b): Text-Knöpfe mit Rahmen oder Füllung stehen am
       Schreibtisch mindestens 40 px hoch — die Standardgröße hat das schon
       (41 px), angehoben werden die mittleren (py-1.5, ohne Größenklasse:
       33–39 px). Auf Touch gilt die globale 44-px-Regel. Kleine Knöpfe
       (text-xs) bleiben kompakt; Links nur, wenn sie ihren Text per Flex
       zentrieren (sonst säße er oben im höheren Kasten). */
    :is(button, input[type="submit"], a.inline-flex, a.flex):is(.btn-primary, .btn-secondary, .btn-danger):not(.text-xs):where(:not([data-sdp-bestandsoptik], [data-sdp-bestandsoptik] *)) {
      min-height: 2.5rem;
    }

    /* ===== Vollflächige Ansicht (alle Breiten, seit 2026-09-24) =====
       Zuerst fuer das Telefon gebaut (Vorbild Kind-Fenster, kind-fenster-
       design.md), seit Entwurf A (User-Entscheidung 2026-09-24) auf Tablet
       und Schreibtisch uebernommen: eine deckende Flaeche statt des
       Hintergrundbilds, die Inhalte untereinander, getrennt durch eine feine
       Linie buendig mit dem Text, kein Milchglas. Links steht ab 641 px die
       Seitenleiste (Block „Seitenleiste" weiter unten). Regel:
       .claude/rules/vollflaechige-ansicht.md.

       „Abschnitt" heisst: eine OBERSTE Box in #page-main — also nicht in
       einer anderen Box, nicht in einem Fenster. Verschachtelte Boxen bleiben
       Items (duenner Rand, kein Schatten). Eine Seite mit schon eigenem
       Vollbild-Design nimmt sich mit der Klasse `sdp-mobil-eigen` an ihrem
       Wurzelelement heraus (oeffentlicher Wochenplan). Die Liste der Box-Klassen steht in
       jeder Regel unten gleich; :where() haelt die Spezifitaet der Ausschluesse
       bei null, damit die Sonderregeln (Titelbox, Aufklapp-Abschnitte) mit
       derselben Grundform gewinnen koennen. Steht bewusst am ENDE des
       Stylesheets: sie muss die Karten-, Akzent- und Dark-Theme-Regeln davor
       bei gleicher Spezifitaet schlagen. Nur @media screen: im Druck gilt
       weiter das Karten-Design. */
    @media screen {
      /* 1. Milchglas aus — global, auch fuer Kopfzeile, Sticky-Leisten und
            Fenster-Hintergruende. */
      *, *::before, *::after {
        -webkit-backdrop-filter: none !important;
        backdrop-filter: none !important;
      }

      /* 2. Deckende Flaeche statt Hintergrundbild. !important gegen Tailwinds
            .bg-slate-50 am <body> und die Bildschichten der Body-Regel. */
      body {
        background-color: var(--surface) !important;
        background-image: none !important;
      }

      /* 3. Kopfzeile deckend (ohne Unschaerfe schiene der Inhalt beim
            Scrollen durch die halbtransparente Kopfzeile). */
      :root { --sdp-mobile-header-bg: #ffffff; }
      html[data-theme="dark"] {
        --sdp-mobile-header-bg: #1f2937;
        /* Wetter-Hinweise im Dashboard (Inline-Farbe über diese Variablen):
           die Standardtöne #0369a1/#dc2626 sind auf der dunklen Fläche zu
           dunkel — bisher setzte nur der Glas-Block die hellen Töne. */
        --sdp-weather-info: #7dd3fc;
        --sdp-weather-alert: #f87171;
      }
      body > header.sdp-app-header {
        background: var(--sdp-mobile-header-bg) !important;
        background-color: var(--sdp-mobile-header-bg) !important;
      }

      /* 4. Text auf der Flaeche: die Regeln fuer „Text direkt auf dem dunklen
            Seitengrund" gelten nicht mehr — alles in <main> steht jetzt wie
            in einer Karte. Helles Theme: die Karten-Werte; das dunkle Theme
            regelt die Graustufen ohnehin global (0,2,1). */
      main { color: var(--text); }
      body,
      body[data-bg-contrast] {
        --on-bg-text: var(--muted);
        --on-bg-shadow: none;
      }
      html[data-theme="light"] main .text-slate-400 { color: #64748b; }
      html[data-theme="light"] main .text-slate-500 { color: #475569; }
      html[data-theme="light"] main .text-slate-600 { color: #334155; }
      html[data-theme="light"] main .text-slate-700 { color: #1e293b; }
      html[data-theme="light"] main .text-slate-800 { color: #1e293b; }
      html[data-theme="light"] main .text-slate-900 { color: #0f172a; }
      html[data-theme="light"] main :is(.hover\:text-slate-700, .hover\:text-slate-800, .hover\:text-slate-900):hover { color: #0f172a; }
      html[data-theme="light"] main .hover\:bg-slate-50:hover { background-color: #f8fafc; }
      html[data-theme="light"] main .border-slate-200 { border-color: #e2e8f0; }
      html[data-theme="light"] main .border-slate-300 { border-color: #cbd5e1; }
      /* <header>-Elemente IN Karten erben sonst den Kopfzeilen-Grund der
         globalen header-Regel (!important) und stehen als Streifen da. */
      main header {
        background: transparent !important;
        background-color: transparent !important;
      }
      /* Das geschlossene Hilfe-Panel liegt per translateX(100%) rechts neben
         dem Bildschirm — sein Schatten (30px) faellt aber hinein. Auf dem
         dunklen Hintergrundbild unsichtbar, auf der Flaeche ein grauer
         Streifen am rechten Rand jeder Seite mit Hilfe. */
      .sdp-help-panel:not(.is-open) { box-shadow: none; }

      /* Zwei Masse, die auseinanderfallen koennen:
         --sdp-mobile-gutter = die Textkante (Telefon 1rem, Tablet 2rem,
                               Schreibtisch 2.5rem — :root, trotz des Namens
                               auf allen Breiten), und
         --sdp-page-gutter   = der TATSAECHLICHE Innenabstand von #page-main.
         Normal sind beide gleich. Seiten mit eigenem randlosen Mobil-Layout
         (Chat, KI Assistenz/Agent, Dateiablage-Editor, oeffentlicher
         Wochenplan) heben den Gutter auf und setzen dazu
         `--sdp-page-gutter: 0px` — dann bekommen die Abschnitte die Textkante
         als eigenen Innenabstand, und die randlosen Streifen ziehen nichts
         ueber den Bildschirmrand. */
      #page-main {
        --sdp-page-gutter: var(--sdp-mobile-gutter);
        --sdp-section-pad-x: calc(var(--sdp-mobile-gutter) - var(--sdp-page-gutter));
        /* Wie weit randlose Abschnitte (Regel 6) über die Textkante ragen:
           normal bis an den Rand von #page-main (= Bildschirmrand). */
        --sdp-bleed: var(--sdp-page-gutter);
      }
      /* Volle Breite am Schreibtisch (User 2026-11-05): randlose Listen
         (Wissensartikel, Kategorien der Dateiablage) liefen bis x = 1920 —
         Zähler und Autor lagen unter Hilfe-Lasche und Vogel. Dort ragen sie
         nur noch 0.75rem über die Textkante (Hover-Fläche, Bänder). */
      @media (min-width: 1025px) {
        body.sdp-main-wide #page-main { --sdp-bleed: min(var(--sdp-page-gutter), 0.75rem); }
      }

      /* 5. Oberste Boxen → Abschnitte: deckend wie die Flaeche, ohne Rand,
            Rundung und Schatten (143 Karten tragen ein Inline-box-shadow →
            !important), seitlich ohne Innenabstand (der Gutter ist der
            Textrand), ohne Aussenabstand — die Luft kommt aus dem eigenen
            Innenabstand, dazwischen die feine Linie. Deckend statt
            transparent: es gibt klebende Karten (Anwesenheit). */
      #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl, .arb-card, .pm-card, .detail-card):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *) {
        --dashboard-card-bg: var(--surface);
        --dashboard-card-shadow: none;
        background-color: var(--surface) !important;
        background-image: none;
        border: 0 !important;
        border-bottom: 1px solid var(--border) !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        padding-left: var(--sdp-section-pad-x) !important;
        padding-right: var(--sdp-section-pad-x) !important;
        margin-top: 0 !important;
        margin-bottom: 0 !important;
      }
      /* Raster/Flex-Stapel aus Abschnitten: kein Zeilenabstand, die Linie
         trennt. (Das Masonry des Dashboards stapelt ueber margin-bottom —
         das nimmt die Regel oben schon weg.) */
      #page-main :has(> :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl, .arb-card, .pm-card, .detail-card):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *)) {
        row-gap: 0 !important;
      }
      /* 5b. Luft zwischen den Bereichen am Schreibtisch (User 2026-11-05: „die
             Bereiche kleben zu dicht aneinander und sind kaum voneinander zu
             trennen"). Bei voller Breite trägt die feine Linie allein nicht —
             Abschnitte mit eigener Überschrift (h1/h2, also echte Bereiche)
             bekommen oben und unten deutlich mehr Innenabstand. Listenzeilen
             (Projekte, Artikel, Kontakte …) tragen keine h1/h2 und bleiben
             kompakt. Telefon/Tablet und /anwesenheit (ohne sdp-main-wide)
             unverändert. */
      @media (min-width: 1025px) {
        body.sdp-main-wide #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl, .arb-card, .pm-card, .detail-card):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *):has(h1, h2) {
          padding-top: 1.75rem !important;
          padding-bottom: 2rem !important;
        }
      }

      /* 6. Boxen, deren Polsterung in den KINDERN liegt (<details>-Karten:
            Kopfzeile px-5; Tab-Karten mit overflow-hidden: Tab-Leiste px-4,
            Zeilen px-4) — am Gutter stuende deren Text doppelt eingerueckt.
            Erkannt an ZWEI Signalen: die Box selbst hat keine p-/px-Klasse
            (oder p-0/px-0) UND ein direktes Kind hat eine. Das zweite Signal
            ist Pflicht: Karten mit Polsterung aus einer EIGENEN CSS-Klasse
            (.gremien-card) haben auch keine p-Klasse — randlos gemacht stand
            ihr Text am Bildschirmrand (gemessen auf /gremien). Inline-Padding
            (style="padding: …") zaehlt auf beiden Seiten wie eine p-Klasse
            (Gremium-Detail: Unterbloecke mit style-Padding in einer
            overflow-hidden-Box).
            Solche Abschnitte werden randlos; die Polsterung der direkten
            Kinder rueckt auf die Textkante (px-5/p-6 → 1rem). Die Trennlinie
            ist eine Hintergrundschicht, damit sie trotz Randlosigkeit buendig
            bleibt. */
      #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl):not([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):has(> :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .hidden, [hidden])):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *),
      #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl):is([class~="p-0"], [class~="px-0"]):has(> :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .hidden, [hidden])):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *) {
        width: auto !important;
        max-width: none !important;
        margin-left: calc(-1 * var(--sdp-bleed)) !important;
        margin-right: calc(-1 * var(--sdp-bleed)) !important;
        border-bottom: 0 !important;
        background-image: linear-gradient(var(--border), var(--border));
        background-size: calc(100% - 2 * (var(--sdp-bleed) + var(--sdp-section-pad-x))) 1px;
        background-position: center bottom;
        background-repeat: no-repeat;
      }
      #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl):not([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):has(> :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .hidden, [hidden])):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *) > :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"]),
      #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl):is([class~="p-0"], [class~="px-0"]):has(> :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .hidden, [hidden])):not(:where(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card, .arb-card, .pm-card, .detail-card, [role="dialog"], [data-sdp-modal], .fixed, .sdp-sheet, .sdp-mobil-eigen) *) > :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"]) {
        padding-left: calc(var(--sdp-bleed) + var(--sdp-section-pad-x)) !important;
        padding-right: calc(var(--sdp-bleed) + var(--sdp-section-pad-x)) !important;
      }

      /* 7. Titelbox: mobil OHNE Farbrand (User-Vorgabe 2026-09-24: „nicht
            modern und clean genug") — den Verlauf und die Extra-Polsterung
            der *-cat-accent-Klasse nimmt die Abschnittsregel (5) schon weg.
            Statt der Brotkrumen-Zeile steht oben nur EIN Zurueck-Link, optisch
            wie beim E-Mailversand (dort seit 2026-09-23 so): „← [Symbol]
            Oberkategorie". Zurueck-Link und Oberkategorie fuehren auf Seiten
            ohne Detail ohnehin auf dieselbe Uebersicht; „Dashboard ›" und die
            aktuelle Seite (= der Titel darunter) entfallen. Das 3. <li> ist
            laut partials/category_backlink.html die Oberkategorie; ihr Symbol
            traegt die Kategoriefarbe (--cat-icon, von der Akzent-Klasse).
            Detailseiten (title-breadcrumb--detail, z. B. ein Gremium) zeigen
            stattdessen die Liste, zu der sie gehoeren („← Gremien & Bereiche",
            das 5. <li> — dasselbe Ziel wie ihr Zurueck-Link, aber mit Namen). */
      #page-main .title-breadcrumb {
        flex-wrap: nowrap;
        margin-bottom: 0.375rem;
        min-width: 0;
      }
      #page-main .title-breadcrumb :is(.title-back-link, .title-breadcrumb-sep),
      #page-main .title-breadcrumb:not(.title-breadcrumb--detail) .title-breadcrumb-trail > li:not(:nth-child(3)),
      #page-main .title-breadcrumb--detail .title-breadcrumb-trail > li:not(:nth-child(5)) {
        display: none;
      }
      #page-main .title-breadcrumb-trail { flex-wrap: nowrap; min-width: 0; }
      #page-main .title-breadcrumb:not(.title-breadcrumb--detail) .title-breadcrumb-cat,
      #page-main .title-breadcrumb--detail .title-breadcrumb-trail > li:nth-child(5) > a {
        font-weight: 600;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      #page-main .title-breadcrumb-cat > span {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      #page-main .title-breadcrumb:not(.title-breadcrumb--detail) .title-breadcrumb-cat::before,
      #page-main .title-breadcrumb--detail .title-breadcrumb-trail > li:nth-child(5) > a::before {
        content: "\2190";
        content: "\2190" / "";
        margin-right: 0.25rem;
      }
      #page-main .title-breadcrumb-cat > svg { color: var(--cat-icon, currentColor); }
      /* Kein Farbrand auch dort, wo die Akzent-Klasse nicht an der Karte,
         sondern an einem Element DARIN haengt (Kopf der Klassenpinnwand,
         Seitenleisten-Kopf des KI Agent). Die Abschnittsregeln (5)/(6) sind
         spezifischer und behalten ihre eigene Hintergrundschicht (Linie). */
      #page-main :is(.ki-cat-accent, .kommunikation-cat-accent, .wissen-cat-accent, .organisation-cat-accent, .austausch-cat-accent, .intern-cat-accent, .verwaltung-cat-accent, .schulorganisation-cat-accent, .dateiablage-cat-accent) {
        background-image: none;
      }
      /* Der KI-Seitenleisten-Kopf hatte links 1rem extra fuer den Verlauf. */
      #page-main .ki-sidebar-header.ki-cat-accent { padding-left: 0.75rem; }
      /* Die Uebersichtsseiten (/uebersicht/*) haben keine Brotkrume, sondern
         einen „› Startseite"-Link — mobil in derselben Optik: „← Startseite". */
      #page-main .dash-link.uebersicht-backlink {
        font-size: 0.75rem;
        line-height: 1.2;
        font-weight: 600;
        color: var(--muted);
        margin-bottom: 0.375rem !important;
      }
      #page-main .dash-link.uebersicht-backlink::before {
        content: "\2190";
        content: "\2190" / "";
        margin-right: 0.25rem;
        font-weight: 600;
      }

      /* 8. Verschachtelte Boxen bleiben Items: duenner Rand, sanfte Rundung,
            kein (Inline-)Schatten — der schwere Karten-Schatten wirkt auf der
            flachen Flaeche wie ein Fremdkoerper. */
      #page-main :is(.bg-white.border.rounded-2xl, .card-modern, .dashboard-card.border.rounded-2xl) :is(.bg-white.border.rounded-2xl, .card-modern):not(:where([role="dialog"], [data-sdp-modal], .fixed) *):not([role="dialog"], [data-sdp-modal]) {
        border: 1px solid var(--border);
        border-radius: 0.75rem;
        box-shadow: none !important;
      }

      /* Offenes Blatt (html.sdp-sheet-open, gesetzt vom Skript bei
         sdpOpenModal — Telefon: Vollbild-Blatt, ab 641 px: Seitenblatt):
         #page-main ueber Kopfzeile (z-30) und Seitenleiste (z-35) heben — ein
         Fenster darin ist sonst in dessen Stacking-Context gefangen —, die
         Seite dahinter nicht mitscrollen, schwebende Knoepfe weg. Toasts
         (z-60/70) bleiben sichtbar. */
      html.sdp-sheet-open #page-main { z-index: 45; }
      html.sdp-sheet-open body { overflow: hidden; }
      html:is(.sdp-sheet-open, .sdp-modal-open, .sdp-actions-sheet-open) #sdp-help-edge-tab { display: none !important; }
      /* Über den Vogel geöffnet (html.sdp-assistent-offen) bleibt er sichtbar —
         er „bringt" das Fenster hervor (User-Vorgabe 2026-11-03). */
      html:is(.sdp-sheet-open, .sdp-modal-open, .sdp-actions-sheet-open):not(.sdp-assistent-offen) #sdp-assistent-bubble { display: none !important; }
    }

    @media screen and (max-width: 640px) {
      /* Reiterleisten (macros/tabs.html: flex, Reiter whitespace-nowrap):
         mit langen Beschriftungen breiter als das Telefon — Chrome weitet
         dann das ganze Layout-Viewport auf (gemessen /verleih: 405 statt
         390 px, jedes Blatt dort 15 px zu breit). Mobil wischbar statt
         ueberlaufend. */
      [data-sdp-tablist] {
        overflow-x: auto;
        scrollbar-width: none;
      }
      [data-sdp-tablist]::-webkit-scrollbar { display: none; }

      /* 9. Ausnahme E-Mail-Kacheln: die wischbaren Schritt-Kacheln leben vom
            Hereinragen der Nachbarkarten und bleiben Kacheln (ohne Glas, mit
            dem bisherigen Mobil-Look). Das html[data-mobile-ui]-Praefix haelt
            die Spezifitaet der frueheren Regel (0,2,1) bzw. (0,3,1) — sonst
            gewaennen Template-Regeln von email_send.html, die vorher verloren. */
      html[data-mobile-ui] [class*="step-surface-"] {
        border: 1px solid var(--border);
        border-radius: 0.75rem;
        box-shadow: none;
      }
      html[data-mobile-ui] [class*="step-surface-"] + [class*="step-surface-"] {
        margin-top: 0.5rem;
      }

      /* 10. Chat-Bubbles in voller Breite, eigene Nachrichten etwas schmaler
             (unveraendert aus dem frueheren Mobil-Block uebernommen). */
      .max-w-\[85\%\],
      .max-w-\[90\%\] {
        max-width: 100% !important;
      }
      .flex.justify-end > .max-w-\[85\%\],
      .flex.justify-end > .max-w-\[90\%\] {
        max-width: 92% !important;
      }

    }

    /* 11. Fenster als Blatt (User-Entscheidung 2026-09-24, Vorbild
           Kind-Fenster). Opt-in per Klasse am PANEL: .sdp-sheet — die
           Fenster der App haben zu verschiedene Huellen fuer eine
           Heuristik (Backdrop als Geschwister oder als Overlay-Grund,
           data-sdp-modal mal am Overlay, mal am Panel). position:fixed am
           Panel ist von der Huelle unabhaengig; das Overlay muss dafuer an
           <body> haengen (modal-stacking-context.md) oder html.sdp-sheet-open
           hebt #page-main an. Kurze Rueckfragen tragen statt dessen
           data-sdp-compact am Overlay und bleiben mittige Dialoge. Ein Test
           verlangt, dass sich jedes data-sdp-modal fuer eins von beiden
           entscheidet.
             Telefon (<= 640 px): Vollbild-Blatt, faehrt von unten ein.
             ab 641 px (Entwurf A): Seitenblatt am rechten Rand, volle Hoehe,
                                    in der Breite, die das Fenster selbst
                                    angibt (Klasse/Inline), faehrt von rechts ein.
             .sdp-sheet-head    klebt oben (Titel + ✕), Linie darunter
             .sdp-sheet-actions klebt unten, Linie darueber
           Innenabstand: seitlich die Textkante (im Blatt: 1rem bzw. 1.5rem).
           Panels, deren Polsterung in den KINDERN liegt (Kopf p-5, Inhalt
           p-5 …), erkennt dieselbe Zwei-Signal-Regel wie bei den
           Abschnitten (6). */
    @media screen {
      .sdp-sheet {
        --sdp-sheet-pad-x: var(--sdp-mobile-gutter);
        position: fixed !important;
        z-index: 1;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        margin: 0 !important;
        border: 0 !important;
        border-radius: 0 !important;
        background: var(--surface) !important;
        color: var(--text);
        overflow-x: hidden !important;
        overflow-y: auto !important;
        overscroll-behavior: contain;
        padding: 0 var(--sdp-sheet-pad-x) calc(1.5rem + env(safe-area-inset-bottom, 0px)) !important;
      }
      @media (prefers-reduced-motion: reduce) {
        .sdp-sheet { animation: none !important; }
      }
      .sdp-sheet:not([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):has(> :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .hidden, [hidden])) {
        --sdp-sheet-pad-x: 0px;
      }
      .sdp-sheet:not([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]) > :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .sdp-sheet-head, .sdp-sheet-actions) {
        padding-left: var(--sdp-mobile-gutter) !important;
        padding-right: var(--sdp-mobile-gutter) !important;
      }
      /* Kopfzeile/Knopfleiste IN einem gepolsterten Kind-Block eines solchen
         Panels: um die Textkante nach aussen, damit Linie und Grund randlos
         bleiben (z. B. Abo-Fenster des Kalenders: Titel in einer Zone px-6). */
      .sdp-sheet:not([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]) > :is([class*=" p-"], [class^="p-"], [class*=" px-"], [class^="px-"], [style*="padding"]):not([class~="p-0"], [class~="px-0"], .sdp-sheet-head, .sdp-sheet-actions) > :is(.sdp-sheet-head, .sdp-sheet-actions) {
        --sdp-sheet-pad-x: var(--sdp-mobile-gutter);
      }
      .sdp-sheet .sdp-sheet-head:not(.hidden, [hidden]) {
        position: sticky;
        top: 0;
        z-index: 3;
        display: flex;
        align-items: center;
        gap: 0.75rem;
        margin: 0 calc(-1 * var(--sdp-sheet-pad-x)) 1rem !important;
        padding: calc(0.625rem + env(safe-area-inset-top, 0px)) var(--sdp-mobile-gutter) 0.625rem !important;
        background: var(--surface);
        border-bottom: 1px solid var(--border);
      }
      .sdp-sheet .sdp-sheet-head > :is(h1, h2, h3) {
        flex: 1 1 auto;
        min-width: 0;
        margin: 0 !important;
      }
      /* Blatt-Titel in einer Größe (Optik-Tokens); Anwesenheitserfassung ausgenommen. */
      .sdp-sheet .sdp-sheet-head > :is(h1, h2, h3):where(:not([data-sdp-bestandsoptik] *)) {
        font-size: var(--sheet-title);
        line-height: 1.3;
      }
      .sdp-sheet .sdp-sheet-head :is([aria-label*="chließen"], [data-sdp-sheet-close]) {
        flex-shrink: 0;
        margin-left: auto;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2.75rem;
        height: 2.75rem;
        border-radius: 9999px;
        border: 1px solid var(--border);
        background: transparent;
        color: var(--text);
      }
      /* Schließen im Blatt: EIN Stil (Optik-Tokens, Phase 4) — 36-px-Kreis,
         1 px Rand, graues ✕, kein Schatten, immer rechts in der Kopfzeile
         (order + position: relative holen absolut gesetzte ✕ in den Fluss).
         Die Vorlagen bauen den Knopf verschieden (SVG, ✕, &times;, Schatten,
         Innenabstand) — die Regel gleicht alles an. Farbe, Rand, Fläche und
         Schatten mit !important: Graustufen-Klassen am Knopf (text-slate-*)
         gewinnen sonst über die Kontext-Regeln (0,4,1), ein Seiten-Stil nahm
         den Rand. min-* ebenso: die globale 44-px-Touch-Regel (0,9,1) zöge den
         Kreis sonst zum Oval; die Tippfläche wächst auf Touch-Geräten
         unsichtbar über ::before. Die Anwesenheitserfassung behält ihren Knopf. */
      .sdp-sheet .sdp-sheet-head :is([aria-label*="chließen"], [data-sdp-sheet-close]):where(:not([data-sdp-bestandsoptik] *)) {
        position: relative;
        inset: auto;
        order: 99;
        width: 2.25rem;
        height: 2.25rem;
        min-width: 0 !important;
        min-height: 0 !important;
        padding: 0;
        border: 1px solid var(--border) !important;
        border-radius: 9999px;
        background: transparent !important;
        box-shadow: none !important;
        color: var(--muted) !important;
        font-size: 1.125rem;
        font-weight: 400;
        line-height: 1;
      }
      .sdp-sheet .sdp-sheet-head :is([aria-label*="chließen"], [data-sdp-sheet-close]):where(:not([data-sdp-bestandsoptik] *)):hover {
        background: var(--focus-soft) !important;
        color: var(--text) !important;
      }
      .sdp-sheet .sdp-sheet-head :is([aria-label*="chließen"], [data-sdp-sheet-close]):where(:not([data-sdp-bestandsoptik] *)) svg {
        width: 1.125rem;
        height: 1.125rem;
      }
      @media (hover: none) and (pointer: coarse) {
        .sdp-sheet .sdp-sheet-head :is([aria-label*="chließen"], [data-sdp-sheet-close]):where(:not([data-sdp-bestandsoptik] *))::before {
          content: "";
          position: absolute;
          inset: -0.25rem;
        }
      }
      .sdp-sheet:has(.sdp-sheet-actions) {
        padding-bottom: 0 !important;
      }
      .sdp-sheet .sdp-sheet-actions:not(.hidden, [hidden]) {
        position: sticky;
        bottom: 0;
        z-index: 3;
        display: flex;
        flex-wrap: wrap;
        align-items: stretch;
        gap: 0.5rem;
        margin: 1.25rem calc(-1 * var(--sdp-sheet-pad-x)) 0 !important;
        padding: 0.75rem var(--sdp-mobile-gutter) calc(0.75rem + env(safe-area-inset-bottom, 0px)) !important;
        background: var(--surface);
        border-top: 1px solid var(--border);
      }
      /* Innere Scroll-Boxen: als Dialog deckelten sie die Hoehe
         (max-h-[60vh] …); im Blatt waeren sie ein Scroller im Scroller.
         Das Blatt scrollt selbst. */
      .sdp-sheet :is([class*="max-h-"], [style*="max-height"]) {
        max-height: none !important;
      }
      /* Boxen IM Blatt: Items wie verschachtelte Boxen auf den Seiten. */
      .sdp-sheet :is(.bg-white.border.rounded-2xl, .card-modern) {
        border: 1px solid var(--border);
        border-radius: 0.75rem;
        box-shadow: none !important;
      }
    }

    /* Telefon: Vollbild-Blatt, Knoepfe der Aktionsleiste gleich breit. */
    @media screen and (max-width: 640px) {
      .sdp-sheet {
        inset: 0 !important;
        width: auto !important;
        max-width: none !important;
        box-shadow: none !important;
        animation: sdp-sheet-hoch 220ms ease-out;
      }
      .sdp-sheet .sdp-sheet-actions :is(button, a, input[type="submit"]) {
        flex: 1 1 8rem;
        justify-content: center;
        text-align: center;
      }
      /* Knopfgruppen in der Leiste (z. B. „Abbrechen | Speichern" rechts,
         „Löschen" links): jede Gruppe eine volle Zeile, darin gleich breit. */
      .sdp-sheet .sdp-sheet-actions > :is(div, span):not(.hidden, [hidden]) {
        flex: 1 1 100%;
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        margin: 0 !important;
      }
    }
    @keyframes sdp-sheet-hoch {
      from { transform: translateY(1.25rem); opacity: 0.6; }
      to { transform: none; opacity: 1; }
    }

    /* Tablet und Schreibtisch: Seitenblatt am rechten Rand. Breite: die des
       Fensters selbst (Tailwind-Klasse oder Inline-max-width gewinnen gegen
       das :where() unten, Spezifitaet 0); fehlt sie, 48rem. Knoepfe der
       Aktionsleiste in natuerlicher Breite rechtsbuendig. Die Textkante im
       Blatt ist 1.5rem (--sdp-mobile-gutter lokal ueberschrieben — die
       Seiten-Textkante von 2.5rem waere im Blatt zu breit). */
    @media screen and (min-width: 641px) {
      .sdp-sheet {
        --sdp-mobile-gutter: 1.5rem;
        top: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        left: auto !important;
        min-width: min(30rem, 100vw);
        border-left: 1px solid var(--border) !important;
        box-shadow: -1.5rem 0 3.5rem -1.5rem rgba(2, 6, 23, 0.35) !important;
        animation: sdp-sheet-rein 220ms ease-out;
      }
      :where(.sdp-sheet) {
        width: 100%;
        max-width: min(48rem, calc(100vw - 4.5rem));
      }
      .sdp-sheet .sdp-sheet-head :is([aria-label*="chließen"], [data-sdp-sheet-close]) {
        width: 2.25rem;
        height: 2.25rem;
      }
      .sdp-sheet .sdp-sheet-actions:not(.hidden, [hidden]) {
        justify-content: flex-end;
      }
      .sdp-sheet .sdp-sheet-actions > :is(div, span):not(.hidden, [hidden]) {
        margin: 0 !important;
      }
    }
    @keyframes sdp-sheet-rein {
      from { transform: translateX(2rem); opacity: 0.6; }
      to { transform: none; opacity: 1; }
    }
  
    /* Offline-Modus: Navigations-Einstiege ausblenden, da die Links offline nicht
       funktionieren. Die Offline-Seiten verlinken untereinander über eigene Kacheln.
       Gesteuert über die JS-Klasse `sdp-offline` (echte Konnektivität), damit die
       Seite /offline/notfallinformationen online normal navigierbar bleibt. */
    body.sdp-offline #header-search-button,
    body.sdp-offline [aria-controls="header-nav"],
    body.sdp-offline #header-nav { display: none !important; }

    /* Kopfzeile: nur der Portalname gibt nach, die Symbole behalten ihre Breite.
       Unterhalb von `sm` ist die Reihe `flex-nowrap` — ohne diese Regeln schiebt
       ein langer Portalname die Symbole aus dem Bild, statt selbst zu kuerzen.
       Der Selektor liegt bei gleicher Spezifitaet wie Tailwinds `.shrink-0`,
       gewinnt aber ueber die Dokumentreihenfolge (dieser Block steht nach dem
       Stylesheet im <head>). */
    .sdp-header-row > * { flex-shrink: 0; }
    .sdp-portal-link { min-width: 0; }
    .sdp-portal-link img { flex-shrink: 0; }
    .sdp-portal-name { font-size: calc(0.75rem - 0.75pt); }

    /* Kompakte Kopfzeile (2026-09-23): 75 % der früheren Höhe, alle Elemente
       im selben Verhältnis verkleinert (User-Vorgabe) — Innenabstand
       0.75rem → 0.5rem, runde Knöpfe 37 → 29 px, Symbole 1rem → 0.75rem, Logo
       1.75rem → 1.3125rem, Portalname 16 → 12 px (calc(1rem - 1pt) × 0.75).
       Gemessen am Schreibtisch 63,6 → 47,x px.

       Auf Touch-Geräten bleiben die Knöpfe bei 44 px (WCAG 2.5.5) — dort holt
       nur der kleinere Innenabstand die Höhe herunter (74,7 → ~56 px). Die
       IDs im Selektor sind nötig: die globale 44-px-Regel trägt neun
       :not()-Klauseln (Spezifität 0,9,1) und liefe in rem (bei Schriftstufe 1
       = 47,7 px) — eine Klassen-Regel käme nicht dagegen an. */
    .sdp-app-header { --sdp-header-pad-y: 0.5rem; --sdp-header-ctl: 1.7rem; }
    .sdp-header-inner {
      padding-top: var(--sdp-header-pad-y);
      padding-bottom: var(--sdp-header-pad-y);
    }
    .sdp-app-header .sdp-portal-link img { height: 1.3125rem; }
    .sdp-header-ctl {
      width: var(--sdp-header-ctl);
      height: var(--sdp-header-ctl);
      padding: 0;
    }
    .sdp-header-ctl > svg:not(.notification-icon) { width: 0.75rem; height: 0.75rem; }
    /* Vier gleich gebaute Geister-Kreise (Optik-Tokens, Phase 4): kein Rand,
       keine Fläche, kein Schatten, Symbol in --muted; ein Rand erst beim
       Fokus. Hilfe nicht mehr blau, das Menü rund statt eckig. Gedrückt
       (Hilfe-Modus) bzw. offen (Menü) in der Auswahlfarbe. */
    .sdp-header-ctl {
      border: 1px solid transparent;
      border-radius: 9999px;
      background: transparent;
      box-shadow: none;
      color: var(--muted);
    }
    .sdp-header-ctl:hover { background: var(--focus-soft); color: var(--text); }
    .sdp-header-ctl:focus-visible { border-color: var(--primary-line); }
    .sdp-header-ctl:is([aria-pressed="true"], [aria-expanded="true"]) {
      background: var(--primary-soft);
      color: var(--primary-line);
    }
    .sdp-app-header .notification-icon--menu { width: 0.8rem; height: 0.8rem; }
    @media (hover: none) and (pointer: coarse) {
      .sdp-app-header { --sdp-header-pad-y: 0.3rem; }
      :is(#header-search-button, #sdp-help-mode-btn, #header-voice-button, #sdp-header-menu-btn) {
        min-width: 44px;
        min-height: 44px;
      }
      .sdp-header-slot { min-width: 44px; min-height: 44px; }
    }
    .sdp-header-slot { display: inline-block; visibility: hidden; }
    @media (min-width: 640px) {
      .sdp-header-slot { display: none; }
    }

    /* Demo-Hinweis: liegt als Overlay am unteren Innenrand des Headers, NICHT
       als eigener Streifen darunter und NICHT in der Symbolreihe — die ist auf
       390 px randvoll (nur .sdp-portal-name darf dort nachgeben, siehe die
       flex-shrink-Regel oben). Der Container reserviert per padding-bottom
       genau die Hoehe, damit der Text die runden Symbole nie ueberdeckt.
       Bewusst OHNE z-index: der Header ist ein eigener Stacking-Context, und
       ein z-index hier wuerde ausgerechnet das Dropdown #header-nav (z-50)
       untergraben. */
    .sdp-demo-banner {
      position: absolute;
      left: 1rem;                      /* deckungsgleich mit px-4 des Containers */
      right: 1rem;
      bottom: 0.25rem;
      text-align: center;
      font-size: calc(0.875rem - 2pt); /* 2 pt kleiner als text-sm (= bisher) */
      line-height: 1.25;
      color: var(--muted);
      pointer-events: none;            /* darf keinen Klick auf den Header fressen */
    }
    .sdp-header--demo { padding-bottom: calc(var(--sdp-header-pad-y, 0.5rem) + 1.05rem); }

    @media (max-width: 639.98px) {
      /* Zwei Zeilen sind hier der Normalfall (113 Zeichen). Umbrechen statt
         kuerzen — ein gekuerzter Rechtshinweis ist keiner. */
      .sdp-header--demo { padding-bottom: calc(var(--sdp-header-pad-y, 0.5rem) + 2.1rem); }
    }

    @media (max-width: 639.98px) {
      /* Seit der kompakten Kopfzeile dieselbe Größe wie am Schreibtisch
         (12 px) — noch 1 pt kleiner wäre auf dem Telefon zu klein. */
      .sdp-portal-name {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      /* Erst hier darf der Name schrumpfen: Flexbox kuerzt ihn genau dann, wenn
         die Reihe sonst ueberliefe — sonst bleibt er vollstaendig stehen. */
      .sdp-header-row > .sdp-portal-link { flex-shrink: 1; }
    }

    /* Sehr schmale Geraete (iPhone SE u. ae.): Symbole und Abstaende brauchen
       dort bereits die ganze Zeile, der Name bliebe als 6-px-Stummel stehen
       (gemessen bei 320 px). Das Logo weicht und gibt 36 px frei — eine feste
       Mindestbreite fuer den Namen waere der falsche Weg, sie wuerde die Zusage
       "die Symbole passen immer" wieder brechen. */
    @media (max-width: 359.98px) {
      .sdp-portal-link img { display: none; }
    }

    /* Durchsichtige Kopfzeile am Schreibtisch (2026-09-25, User-Wunsch):
       Die Kopfzeile bleibt sticky, deckt aber nur noch links (Logo und
       Portalname — neben der Seitenleiste stehen die ohnehin in der Leiste)
       und rechts (Hilfe, Mikrofon, Menü). Im breiten Leerraum dazwischen
       bleibt der Seitentext beim Scrollen sichtbar, und Klicks gehen dort
       an die Seite durch (pointer-events). Die Symbolgruppe ist unterhalb
       von 1025 px `display: contents`, dort bleibt alles wie bisher.
       Der zweite Selektor hält die Spezifität der Seitenleisten-Regel
       (0,3,2), die sonst die deckende Fläche zurückbrächte. */
    .sdp-header-tools { display: contents; }
    @media screen and (min-width: 1025px) {
      body > header.sdp-app-header,
      body.sdp-has-sidebar:not(.sdp-offline) > header.sdp-app-header {
        background: transparent !important;
        background-color: transparent !important;
        border-bottom-color: transparent !important;
        pointer-events: none;
      }
      .sdp-app-header :is(.sdp-portal-link, .sdp-header-tools) {
        pointer-events: auto;
        background: var(--surface);
        border-radius: 9999px;
      }
      .sdp-app-header .sdp-header-tools {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        /* Fläche etwas über die Kreise hinaus, ohne sie zu verschieben. */
        padding: 0.25rem;
        margin: -0.25rem;
      }
      .sdp-app-header .sdp-portal-link {
        padding: 0.25rem 0.75rem 0.25rem 0.25rem;
        margin: -0.25rem -0.75rem -0.25rem -0.25rem;
      }
      /* Suche direkt neben dem Portalnamen (nur ohne Seitenleiste sichtbar):
         eigene deckende Fläche; beim Hover gilt die Hover-Farbe. */
      .sdp-app-header #header-search-button { pointer-events: auto; }
      .sdp-app-header #header-search-button:not(:hover) { background: var(--surface); }
      /* Demo-Hinweis: kein Streifen über die ganze Breite mehr, sondern eine
         schmale deckende Marke in der Mitte. */
      .sdp-app-header .sdp-demo-banner {
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        width: max-content;
        max-width: calc(100% - 2rem);
        padding: 0 0.5rem;
        border-radius: 0.375rem;
        background: var(--surface);
      }
    }

    /* ===== Daumen-Leiste am Telefon (Entwurf B, 2026-10-08) =====
       Unten „Heute", bis zu drei Lieblingsfunktionen und „Alle" (Blatt mit Suche,
       zuletzt benutzten Seiten und allen Bereichen). Ersetzt am Telefon das Menü
       der Kopfzeile: dort stehen stattdessen der Bereich der Seite (öffnet das
       Blatt bei den Nachbarseiten) und die Glocke. Nur ≤ 640 px — darüber gibt es
       die Seitenleiste. Seiten mit eigenem Vollbild (KI Assistenz/Agent,
       Dateiablage-Editor/-Notiz) setzen `bnav_aus` — dann gibt es weder Leiste
       noch Blatt, und das Menü bleibt. KI Assistenz und KI Agent setzen
       `bnav_umschalten`: dort blendet der Menü-Knopf die Leiste ein und aus. --sdp-bnav-h ist die Höhe der Leiste (0, solange sie
       fehlt oder die Bildschirmtastatur offen ist) — alles, was unten schwebt
       (Toasts, Vogel, Korb, Erinnerungen), rechnet damit.
       Regel: .claude/rules/daumen-leiste-mobil.md */
    :root { --sdp-bnav-h: 0px; }
    .sdp-bnav, .sdp-bnav-bereich, .sdp-bnav-glocke { display: none; }
    [data-bnav-cat="wissen"] { --bnav-kat: #059669; }
    [data-bnav-cat="ki"] { --bnav-kat: #7c3aed; }
    [data-bnav-cat="kommunikation"] { --bnav-kat: #d97706; }
    [data-bnav-cat="organisation"] { --bnav-kat: #0284c7; }
    [data-bnav-cat="austausch"] { --bnav-kat: #7e3a8a; }
    [data-bnav-cat="intern"] { --bnav-kat: #4d7c0f; }
    [data-bnav-cat="verwaltung"] { --bnav-kat: #475569; }
    [data-bnav-cat="schulorganisation"] { --bnav-kat: #0d9488; }
    [data-bnav-cat="dateiablage"] { --bnav-kat: #4f46e5; }
    html[data-theme="dark"] [data-bnav-cat="wissen"] { --bnav-kat: #34d399; }
    html[data-theme="dark"] [data-bnav-cat="ki"] { --bnav-kat: #a78bfa; }
    html[data-theme="dark"] [data-bnav-cat="kommunikation"] { --bnav-kat: #fbbf24; }
    html[data-theme="dark"] [data-bnav-cat="organisation"] { --bnav-kat: #38bdf8; }
    html[data-theme="dark"] [data-bnav-cat="austausch"] { --bnav-kat: #d49be0; }
    html[data-theme="dark"] [data-bnav-cat="intern"] { --bnav-kat: #a3e635; }
    html[data-theme="dark"] [data-bnav-cat="verwaltung"] { --bnav-kat: #94a3b8; }
    html[data-theme="dark"] [data-bnav-cat="schulorganisation"] { --bnav-kat: #2dd4bf; }
    html[data-theme="dark"] [data-bnav-cat="dateiablage"] { --bnav-kat: #818cf8; }
    .sdp-bnav-kat { color: var(--muted); }
    .sdp-bnav-farbig .sdp-bnav-kat[data-bnav-cat] { color: var(--bnav-kat, var(--muted)); }
    .sdp-bnav-punkt {
      position: absolute;
      top: 0.125rem;
      right: 0.75rem;
      width: 0.5rem;
      height: 0.5rem;
      border-radius: 9999px;
      background: #dc2626;
      box-shadow: 0 0 0 2px var(--sdp-mobile-header-bg, var(--surface));
    }

    @media screen and (max-width: 640px) {
      body.sdp-has-bnav {
        --sdp-bnav-h: calc(3.875rem + env(safe-area-inset-bottom, 0px));
        padding-bottom: var(--sdp-bnav-h);
      }
      html.sdp-bnav-tastatur body.sdp-has-bnav { --sdp-bnav-h: 0px; }
      body.sdp-has-bnav .sdp-bnav {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 30;  /* wie die Kopfzeile: unter Blättern, Fenstern und Menüs */
        display: flex;
        align-items: stretch;
        box-sizing: border-box;
        min-height: calc(3.875rem + env(safe-area-inset-bottom, 0px));
        padding: 0.25rem 0.25rem env(safe-area-inset-bottom, 0px);
        background: var(--sdp-mobile-header-bg, var(--surface));
        border-top: 1px solid var(--border);
      }
      html.sdp-bnav-tastatur .sdp-bnav { display: none !important; }
      /* Der Menü-Knopf weicht der Glocke; seine Inhalte stehen im Blatt „Alle".
         Das Menü selbst bleibt im DOM (Befehlssuche und Blatt-Werkzeuge lesen es). */
      body.sdp-has-bnav:not(.sdp-bnav-umschalten) #sdp-header-menu-btn { display: none; }
      /* KI Assistenz/Agent (bnav_umschalten): Vollbild-Chat — die Leiste ist erst
         da, wenn der Menü-Knopf sie einblendet (daumen-leiste.js setzt
         sdp-bnav-sichtbar). Die schwebende Kopfzeile dort bleibt ohne Glocke. */
      body.sdp-has-bnav.sdp-bnav-umschalten:not(.sdp-bnav-sichtbar) { --sdp-bnav-h: 0px; }
      body.sdp-has-bnav.sdp-bnav-umschalten:not(.sdp-bnav-sichtbar) .sdp-bnav { display: none; }
      body.sdp-bnav-umschalten .sdp-bnav-glocke { display: none !important; }
      body.sdp-has-bnav .sdp-bnav-glocke {
        display: inline-flex;
        position: relative;
        align-items: center;
        justify-content: center;
      }
      .sdp-bnav-glocke .sdp-bnav-punkt { top: 18%; right: 18%; }
      /* Unterseite: der Bereich steht an der Stelle des Portalnamens. */
      body.sdp-has-bnav .sdp-header-row:has(> .sdp-bnav-bereich) > .sdp-portal-link { display: none; }
      body.sdp-has-bnav .sdp-header-row > .sdp-bnav-bereich {
        display: inline-flex;
        flex-shrink: 1;
        min-width: 0;
        align-items: center;
        gap: 0.375rem;
        min-height: 2.75rem;
        margin: 0 0 0 -0.375rem;
        padding: 0 0.375rem;
        border: 0;
        border-radius: var(--radius-sm);
        background: transparent;
        color: var(--text);
        font: inherit;
        font-size: 0.875rem;
        font-weight: 600;
        cursor: pointer;
      }
      .sdp-bnav-bereich:focus-visible { outline: none; box-shadow: var(--focus-ring); }
      .sdp-bnav-bereich-icon { display: inline-flex; flex: none; }
      .sdp-bnav-bereich-icon svg { width: 1.125rem !important; height: 1.125rem !important; }
      .sdp-bnav-bereich-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
      .sdp-bnav-bereich-pfeil { flex: none; width: 0.875rem; height: 0.875rem; color: var(--muted); transition: transform 150ms ease; }
      .sdp-bnav-bereich[aria-expanded="true"] .sdp-bnav-bereich-pfeil { transform: rotate(180deg); }
      /* „← Bereich" in der Titelbox führt dorthin, wo jetzt die Kopfzeile hinführt.
         Detailseiten behalten ihr „← Liste". */
      body.sdp-has-bnav #page-main .title-breadcrumb:not(.title-breadcrumb--detail) { display: none; }
      /* Die Symbolreihe der Startseite war die Navigation des Telefons. */
      body.sdp-has-bnav .dashboard-mini-row { display: none !important; }
    }
    @media (hover: none) and (pointer: coarse) {
      #sdp-bnav-glocke { min-width: 44px; min-height: 44px; }
    }

    .sdp-bnav-item {
      position: relative;
      flex: 1 1 0;
      min-width: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 0.1875rem;
      margin: 0;
      padding: 0.25rem 0;
      border: 0;
      background: transparent;
      color: var(--muted);
      font: inherit;
      text-decoration: none;
      cursor: pointer;
      -webkit-tap-highlight-color: transparent;
    }
    .sdp-bnav-icon {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 3.25rem;
      height: 1.875rem;
      border-radius: var(--radius);
      transition: background-color 150ms ease, color 150ms ease;
    }
    .sdp-bnav .sdp-bnav-icon svg { width: 1.375rem !important; height: 1.375rem !important; stroke-width: 1.7; }
    .sdp-bnav-label {
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 0.65625rem;  /* 10,5 px: „Wochenpläne" passt bei 390 px in den Platz */
      line-height: 0.875rem;
    }
    .sdp-bnav-item:is([aria-current="page"], .is-hier, [aria-expanded="true"]) { color: var(--primary-line); }
    .sdp-bnav-item:is([aria-current="page"], .is-hier, [aria-expanded="true"]) .sdp-bnav-icon { background: var(--primary-soft); }
    .sdp-bnav-item:is([aria-current="page"], .is-hier, [aria-expanded="true"]) .sdp-bnav-label { font-weight: 600; }
    .sdp-bnav-item:focus-visible { outline: none; }
    .sdp-bnav-item:focus-visible .sdp-bnav-icon { box-shadow: var(--focus-ring); }
    /* KI Assistenz als Favorit: immer in zarter violetter Fläche (auch wenn das
       Skript die Leiste neu zeichnet — daher am Pfad, nicht an einer Klasse). */
    .sdp-bnav-item[data-bnav-pfad="/ki-assistenz"] { color: var(--ki-cat-icon); }
    .sdp-bnav-item[data-bnav-pfad="/ki-assistenz"] .sdp-bnav-icon { background: color-mix(in srgb, var(--ki-cat-icon) 13%, transparent); }
    .sdp-bnav-item[data-bnav-pfad="/ki-assistenz"] .sdp-bnav-label { font-weight: 600; }
    .sdp-bnav-item[data-bnav-pfad="/ki-assistenz"][aria-current="page"] .sdp-bnav-icon { background: color-mix(in srgb, var(--ki-cat-icon) 24%, transparent); }

    /* Blatt „Alle": von unten, Kopf mit ✕ (Esc über data-modal-close). */
    .sdp-bnav-schleier:not([hidden]) {
      position: fixed;
      inset: 0;
      z-index: 61;
      background: var(--overlay);
      opacity: 0;
      transition: opacity 200ms ease;
    }
    .sdp-bnav-schleier.is-offen { opacity: 1; }
    .sdp-bnav-blatt:not([hidden]) {
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 62;
      display: flex;
      flex-direction: column;
      height: calc(100dvh - 3rem);
      max-width: 40rem;
      margin: 0 auto;
      background: var(--surface);
      color: var(--text);
      border-radius: var(--radius-lg) var(--radius-lg) 0 0;
      box-shadow: 0 -0.5rem 1.5rem rgba(2, 6, 23, 0.18);
      transform: translateY(100%);
      transition: transform 240ms ease;
      outline: none;
    }
    .sdp-bnav-blatt.is-offen { transform: none; }
    .sdp-bnav-blatt.is-ziehen { transition: none; }
    @media (prefers-reduced-motion: reduce) {
      .sdp-bnav-schleier:not([hidden]), .sdp-bnav-blatt:not([hidden]) { transition: none; }
    }
    html.sdp-bnav-offen, html.sdp-bnav-offen body { overflow: hidden; }
    html.sdp-bnav-offen :is(#sdp-assistent-bubble, #sdp-korb-bubble, #sdp-help-edge-tab, #reminder-banner-stack) { display: none !important; }
    .sdp-bnav-griff[data-bnav-griff] {
      flex: none;
      width: 2.25rem;
      height: 0.25rem;
      margin: 0.5rem auto 0;
      border-radius: 9999px;
      background: var(--border);
    }
    .sdp-bnav-kopf {
      flex: none;
      display: flex;
      align-items: center;
      gap: 0.25rem;
      min-height: 3.25rem;
      padding: 0 1rem 0 0.375rem;
    }
    .sdp-bnav-zurueck:not([hidden]) {
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.75rem;
      height: 2.75rem;
      padding: 0;
      border: 0;
      border-radius: 9999px;
      background: transparent;
      color: var(--text);
      cursor: pointer;
    }
    .sdp-bnav-zurueck svg { width: 1.375rem; height: 1.375rem; }
    .sdp-bnav-kopf-icon:not([hidden]) {
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      border-radius: var(--radius-sm);
      background: var(--surface-muted);
    }
    .sdp-bnav-farbig .sdp-bnav-kopf-icon[data-bnav-cat] { background: color-mix(in srgb, var(--bnav-kat) 12%, transparent); }
    .sdp-bnav-kopf-icon svg { width: 1.125rem !important; height: 1.125rem !important; stroke-width: 1.7; }
    .sdp-bnav-titel {
      flex: 1 1 auto;
      min-width: 0;
      margin: 0;
      padding-left: 0.625rem;
      font-size: var(--sheet-title, 1.25rem);
      font-weight: 700;
      line-height: 1.3;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      outline: none;
    }
    .sdp-bnav-zurueck:not([hidden]) ~ .sdp-bnav-titel { padding-left: 0.375rem; }
    .sdp-bnav-zu {
      position: relative;
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.25rem;
      height: 2.25rem;
      padding: 0;
      border: 1px solid var(--border);
      border-radius: 9999px;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
    }
    .sdp-bnav-zu::before { content: ""; position: absolute; inset: -0.25rem; }
    .sdp-bnav-zu svg { width: 1rem; height: 1rem; }
    :is(.sdp-bnav-zu, .sdp-bnav-zurueck, .sdp-bnav-stern):focus-visible { outline: 2px solid var(--primary-line); outline-offset: 2px; }
    .sdp-bnav-suche:not([hidden]) { flex: none; display: block; padding: 0 1rem 0.75rem; }
    .sdp-bnav-suchfeld {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      min-height: 2.75rem;
      padding: 0 0.75rem;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--surface-muted);
      color: var(--muted);
    }
    .sdp-bnav-suchfeld:focus-within { border-color: var(--primary-line); box-shadow: var(--focus-ring); }
    .sdp-bnav-suchfeld svg { flex: none; width: 1.125rem; height: 1.125rem; }
    .sdp-bnav-suchfeld input[data-bnav-eingabe] {
      flex: 1 1 auto;
      min-width: 0;
      height: 2.625rem !important;
      margin: 0 !important;
      padding: 0 !important;
      border: 0 !important;
      border-radius: 0 !important;
      background: transparent !important;
      box-shadow: none !important;
      outline: none;
      color: var(--text);
      font-size: 1rem;
    }
    .sdp-bnav-inhalt {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    }
    .sdp-bnav-ansicht[hidden] { display: none; }
    .sdp-bnav-zwischentitel {
      margin: 0.25rem 1rem 0.5rem;
      font-size: 0.8125rem;
      font-weight: 600;
      color: var(--muted);
    }
    .sdp-bnav-chips {
      display: flex;
      gap: 0.5rem;
      overflow-x: auto;
      scrollbar-width: none;
      padding: 0 1rem 0.875rem;
    }
    .sdp-bnav-chips::-webkit-scrollbar { display: none; }
    .sdp-bnav-chip {
      flex: none;
      display: inline-flex;
      align-items: center;
      gap: 0.4375rem;
      min-height: 2.25rem;
      padding: 0 0.75rem;
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      background: var(--surface);
      color: var(--text);
      font-size: 0.8125rem;
      font-weight: 500;
      text-decoration: none;
      white-space: nowrap;
    }
    .sdp-bnav-chip-punkt { width: 0.5rem; height: 0.5rem; border-radius: 9999px; background: var(--muted); }
    .sdp-bnav-farbig .sdp-bnav-chip-punkt[data-bnav-cat] { background: var(--bnav-kat, var(--muted)); }
    .sdp-bnav-kacheln {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 0.5rem;
      padding: 0 1rem 1rem;
    }
    .sdp-bnav-kachel {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 0.5rem;
      min-height: 5.75rem;
      margin: 0;
      padding: 0.75rem 0.375rem 0.625rem;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--surface);
      color: var(--text);
      font: inherit;
      text-align: center;
      text-decoration: none;
      cursor: pointer;
    }
    .sdp-bnav-kachel:is([data-bnav-hier], [aria-current="page"]) { border-color: var(--primary-line); }
    .sdp-bnav-kachel:focus-visible { outline: 2px solid var(--primary-line); outline-offset: 2px; }
    .sdp-bnav-kachel-icon {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.5rem;
      height: 2.5rem;
      border-radius: var(--radius);
      background: var(--surface-muted);
    }
    .sdp-bnav-farbig .sdp-bnav-kachel-icon[data-bnav-cat] { background: color-mix(in srgb, var(--bnav-kat) 12%, transparent); }
    .sdp-bnav-kachel-icon svg { width: 1.375rem !important; height: 1.375rem !important; stroke-width: 1.7; }
    .sdp-bnav-kachel-icon .sdp-bnav-punkt { top: -0.125rem; right: -0.125rem; box-shadow: 0 0 0 2px var(--surface); }
    .sdp-bnav-kachel-name {
      font-size: 0.78125rem;
      line-height: 1.25;
      font-weight: 500;
      hyphens: manual;  /* feste Trennstellen aus mobile_nav.kachelnamen */
      overflow-wrap: anywhere;
    }
    /* KI Assistenz: breite Kachel über den Bereichen, violett getönt. */
    .sdp-bnav-kachel.sdp-bnav-kachel--ki {
      grid-column: 1 / -1;
      flex-direction: row;
      gap: 0.75rem;
      min-height: 0;
      padding: 0.75rem 0.875rem;
      text-align: left;
      border-color: color-mix(in srgb, var(--ki-cat-icon) 28%, transparent);
      background: color-mix(in srgb, var(--ki-cat-icon) 8%, var(--surface));
    }
    .sdp-bnav-kachel--ki[aria-current="page"] { border-color: var(--ki-cat-icon); }
    .sdp-bnav-kachel--ki .sdp-bnav-kachel-icon {
      flex: none;
      color: var(--ki-cat-icon);
      background: color-mix(in srgb, var(--ki-cat-icon) 14%, transparent);
    }
    .sdp-bnav-kachel-text { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
    .sdp-bnav-kachel--ki .sdp-bnav-kachel-name { font-size: 0.875rem; font-weight: 600; }
    .sdp-bnav-kachel-sub { font-size: 0.75rem; line-height: 1.3; color: var(--muted); }
    .sdp-bnav-hinweis { margin: 0 1rem 0.625rem; font-size: 0.8125rem; color: var(--muted); }
    .sdp-bnav-liste { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); }
    .sdp-bnav-liste[hidden] { display: none; }
    .sdp-bnav-zeile { display: flex; align-items: center; border-bottom: 1px solid var(--border); }
    .sdp-bnav-zeile-link {
      flex: 1 1 auto;
      min-width: 0;
      display: flex;
      align-items: center;
      gap: 0.75rem;
      min-height: 3.25rem;
      padding: 0.375rem 0.25rem 0.375rem 1rem;
      color: var(--text);
      text-decoration: none;
    }
    .sdp-bnav-zeile-link:focus-visible { outline: 2px solid var(--primary-line); outline-offset: -2px; }
    .sdp-bnav-zeile-icon { flex: none; display: inline-flex; }
    .sdp-bnav-zeile-icon svg { width: 1.25rem !important; height: 1.25rem !important; stroke-width: 1.6; }
    .sdp-bnav-zeile-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
    .sdp-bnav-zeile-titel { font-size: 0.9375rem; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sdp-bnav-zeile-link[aria-current="page"] .sdp-bnav-zeile-titel { font-weight: 600; }
    .sdp-bnav-zeile-gruppe { font-size: 0.75rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    [data-bnav-ansicht="gruppe"] .sdp-bnav-zeile-gruppe { display: none; }
    .sdp-bnav-zeile-punkt { flex: none; width: 0.5rem; height: 0.5rem; border-radius: 9999px; background: #dc2626; }
    .sdp-bnav-hier {
      flex: none;
      padding: 0.1875rem 0.5rem;
      border-radius: 9999px;
      background: var(--primary-soft);
      color: var(--primary-line);
      font-size: 0.6875rem;
      font-weight: 600;
      white-space: nowrap;
    }
    .sdp-bnav-stern {
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 3.25rem;
      min-height: 3.25rem;
      margin: 0;
      padding: 0;
      border: 0;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
    }
    .sdp-bnav-stern svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 1.6; }
    .sdp-bnav-stern[aria-pressed="true"] { color: var(--primary-line); }
    .sdp-bnav-stern[aria-pressed="true"] svg { fill: currentColor; }
    .sdp-bnav-leer { margin: 0.75rem 1rem; font-size: 0.875rem; color: var(--muted); }
    .sdp-bnav-leer[hidden] { display: none; }
    .sdp-bnav-ueberall:not([hidden]) {
      display: flex;
      align-items: center;
      gap: 0.75rem;
      width: 100%;
      min-height: 3.25rem;
      margin: 0;
      padding: 0.375rem 1rem;
      border: 0;
      border-bottom: 1px solid var(--border);
      background: transparent;
      color: var(--primary-line);
      font: inherit;
      font-size: 0.9375rem;
      font-weight: 500;
      text-align: left;
      cursor: pointer;
    }
    .sdp-bnav-ueberall svg { flex: none; width: 1.25rem; height: 1.25rem; }
    .sdp-bnav-konto { margin-top: 0.25rem; padding: 0.75rem 1rem 0; border-top: 1px solid var(--border); }
    .sdp-bnav-profil {
      display: flex;
      align-items: center;
      gap: 0.75rem;
      min-height: 3.25rem;
      color: var(--text);
      text-decoration: none;
    }
    .sdp-bnav-avatar {
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.5rem;
      height: 2.5rem;
      overflow: hidden;
      border-radius: 9999px;
      background: var(--primary-soft);
      color: var(--primary-line);
      font-size: 0.875rem;
      font-weight: 700;
    }
    .sdp-bnav-avatar img { width: 100%; height: 100%; object-fit: cover; }
    .sdp-bnav-profil-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
    .sdp-bnav-profil-name { font-size: 0.9375rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sdp-bnav-profil-sub { font-size: 0.8125rem; color: var(--muted); }
    .sdp-bnav-profil-pfeil { flex: none; width: 1rem; height: 1rem; color: var(--muted); }
    .sdp-bnav-werkzeuge { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.625rem; }
    .sdp-bnav-werkzeug:not([hidden]) {
      flex: 1 1 calc(50% - 0.25rem);
      min-width: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 0.375rem;
      min-height: 2.75rem;
      margin: 0;
      padding: 0 0.5rem;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--surface);
      color: var(--text);
      font: inherit;
      font-size: 0.8125rem;
      font-weight: 500;
      text-decoration: none;
      cursor: pointer;
    }
    .sdp-bnav-werkzeug svg { flex: none; width: 1.125rem; height: 1.125rem; }
    @media print {
      .sdp-bnav, .sdp-bnav-blatt, .sdp-bnav-schleier { display: none !important; }
    }
  
    .dap-chip{display:inline-flex;align-items:center;gap:0.2rem;padding:0.15rem 0.5rem;border-radius:var(--radius-sm);font-size:0.7rem;border:1px solid var(--border);background:transparent;cursor:pointer;transition:all 120ms ease;color:var(--text)}
    .dap-chip:hover,.dap-chip.active{background:var(--focus-soft);border-color:var(--text);font-weight:600}
    .dap-lock{width:0.8rem;height:0.8rem;flex:none;color:var(--muted)}
    .dap-page-btn{display:inline-flex;align-items:center;justify-content:center;min-width:1.75rem;height:1.75rem;border-radius:var(--radius-sm);font-size:0.75rem;color:var(--muted);border:1px solid var(--border);background:transparent;cursor:pointer;transition:all 120ms ease}
    .dap-page-btn:hover{background:var(--focus-soft);color:var(--text)}
    .dap-page-btn.active{background:var(--primary-soft);color:var(--primary-line);font-weight:600;border-color:var(--primary-line)}
    .dap-row:hover td{background:var(--focus-soft)}
    .dap-cat-wrap{display:flex;flex-wrap:wrap;gap:0.375rem;flex-basis:100%}
  
    /* Fällige Erinnerung: EINE einzeilige Pille (reminders.js). Am Schreibtisch im
       leeren Band der Kopfzeile, am Telefon unten über dem Assistent-Vogel — oben
       deckte sie dort Portalname und Suche ab. */
    #reminder-banner-stack { position: fixed; left: 50%; top: 14px; transform: translateX(-50%); z-index: 59;
      display: flex; justify-content: center; width: max-content; max-width: min(36rem, calc(100vw - 24px)); pointer-events: none; }
    @media (max-width: 640px) {
      #reminder-banner-stack { top: auto; bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px) + var(--sdp-bnav-h, 0px)); }
      html.sdp-erinnerung-offen #page-main::after { content: ""; display: block; height: 3.5rem; }
    }
    .sdp-erinnerung { pointer-events: auto; display: flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%;
      padding: 6px 8px 6px 14px; font-size: 13px; font-weight: 700; border-radius: 9999px;
      background: var(--surface); color: var(--text); border: 1px solid var(--border); box-shadow: var(--shadow); }
    .sdp-erinnerung-punkt { width: 8px; height: 8px; border-radius: 50%; background: #dc2626; flex: 0 0 auto; }
    .sdp-erinnerung-text { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .sdp-erinnerung-mehr { flex: 0 0 auto; padding: 1px 8px; border-radius: 9999px; border: 1px solid var(--border);
      background: var(--surface-muted); color: var(--text); font-size: 12px; font-weight: 700; cursor: pointer; }
    .sdp-erinnerung-zu { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 9999px; background: transparent;
      border: none; color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer; }
    .sdp-erinnerung-mehr:hover, .sdp-erinnerung-zu:hover { background: var(--focus-soft); }
    /* Kompakter Notiz-Editor (Toast UI wird beim ersten Öffnen nachgeladen). */
    #ne-note-editor .toastui-editor-defaultUI { border-radius: 0.75rem; }
    #ne-note-editor .toastui-editor-mode-switch { display: none; }
    .ne-note-fallback { min-height: 220px; width: 100%; border-radius: 0.75rem; border: 1px solid var(--input-border); padding: 0.65rem; font-size: 0.875rem; line-height: 1.5; }
    .note-version-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; padding: 0.5rem 0; border-top: 1px solid var(--border); }
    .note-version-row:first-child { border-top: 0; }
    .note-version-preview { font-size: 0.8125rem; color: var(--muted); overflow-wrap: anywhere; }
    /* Wochentags-Auswahl der wiederkehrenden Erinnerungen: Checkbox + Pille. */
    .reminder-day { position: relative; display: inline-flex; }
    .reminder-day-pill { display: inline-flex; align-items: center; justify-content: center; min-width: 2.6rem; height: 2.25rem; padding: 0 0.6rem; border-radius: 9999px; border: 1px solid var(--input-border); background: var(--input-bg); color: var(--text); font-size: 0.8125rem; font-weight: 600; cursor: pointer; user-select: none; }
    .reminder-day input:checked + .reminder-day-pill { background: #2563eb; border-color: #2563eb; color: #ffffff; }
    .reminder-day input:focus-visible + .reminder-day-pill { outline: 2px solid #2563eb; outline-offset: 2px; }
    @media (hover: none) and (pointer: coarse) { .reminder-day-pill { height: 2.75rem; min-width: 2.75rem; } }
  
        #sdp-password-notice[hidden] { display: none !important; }
        @media print { #sdp-password-notice { display: none !important; } }
        #sdp-password-notice {
          display: flex; align-items: flex-start; gap: 0.5rem;
          border: 1px solid var(--border); background: var(--focus-soft);
          color: var(--text); border-radius: 0.75rem;
          padding: 0.5rem 0.75rem; margin-bottom: 0.75rem; font-size: 0.75rem;
        }
        #sdp-password-notice a { text-decoration: underline; font-weight: 600; color: inherit; }
        #sdp-password-notice-close {
          flex-shrink: 0; border: none; background: none; cursor: pointer;
          color: var(--muted); font-size: 1rem; line-height: 1; padding: 0.1rem 0.25rem;
        }
        #sdp-password-notice-close:hover { color: var(--text); }
      
