/* @quelle tokens/colors.css */
/* ============================================================
   HaDiKo color system — "Academic Commons"
   Source of truth: hadiko.de CI green #3b773b (measured on the
   live 2026 site), portal form.css v2, design.md v3.
   Boundaries come from surface shifts, never 1px grey lines.
   ============================================================ */
:root {
  /* --- Brand greens (base ramp) --- */
  --green-050: #f0f7f0; /* wash — tinted panels, timeline bg */
  --green-100: #e2eee2; /* tint — selected rows, subtle fills */
  --green-300: #a0c2a0; /* disabled primary, quiet accents */
  --green-500: #3b773b; /* HaDiKo primary green (CI) */
  --green-600: #2f5f2f; /* Primaer-Hover -- Mockup-Wert, Daniels Entscheidung 2026-09-04 */
  --green-700: #224422; /* pressed; faerbt weiterhin a:hover */
  --green-900: #162c16; /* deep ink for on-green gradients, footer */

  /* --- Green alpha tints (ghost borders, hover washes) --- */
  --green-a04: rgba(59, 119, 59, 0.04); /* hover wash on light surfaces */
  --green-a08: rgba(59, 119, 59, 0.08); /* drag-over / active wash */
  --green-a12: rgba(59, 119, 59, 0.12); /* hairline on tinted panels */
  --green-a15: rgba(59, 119, 59, 0.15); /* focus halo */
  --green-a20: rgba(59, 119, 59, 0.20); /* ghost border (inputs) */
  --green-a30: rgba(59, 119, 59, 0.30); /* ghost border, dashed (dropzones) */

  /* --- Paper surfaces (the "stack of heavy paper") --- */
  --surface-base:   #ffffff; /* top sheet — cards, app canvas */
  --surface-lowest: #f8f9fa; /* just under the top sheet */
  --surface-low:    #eaeaea; /* desk — page bg, inset fields, inactive steps */

  /* --- Ink --- */
  --text-primary: #212529;
  --text-muted:   #6c757d;
  --text-on-brand: #ffffff;

  /* --- Feedback --- */
  /* Fehler-Rot. Das Mockup-Rot, seit Daniels Entscheidung vom 2026-08-28
     (Delta-Dokument §2.6). Vorher #d25f5d aus dem Design System; Anhang A des
     Frontend-Lastenhefts ist mit derselben Aenderung nachgezogen worden. */
  --danger: #a94442;
  --danger-bg: #fbeeee;

  /* --- Illustration palette (flat-vector campus artwork) --- */
  --ill-forest: #2a4030;
  --ill-pine:   #3c6048;
  --ill-moss:   #5d8161;
  --ill-sage:   #9cbc93;
  --ill-mist:   #dceaea;
  --ill-sand:   #e8dcc4;
  --ill-slate:  #606c78;

  /* --- Semantic aliases --- */
  --brand:        var(--green-500);
  --brand-strong: var(--green-600);
  --surface-page:  var(--surface-lowest); /* portal canvas */
  --surface-card:  var(--surface-base);
  --surface-inset: var(--surface-low);    /* fields, inactive chevrons */
  --border-ghost:        1px solid var(--green-a20);
  --border-ghost-dashed: 2px dashed var(--green-a30);
  --focus-ring: 0 0 0 5px var(--green-a15);
}

/* @quelle tokens/erweiterung.css */
/* ============================================================
   T7-Erweiterung des HaDiKo-Token-Systems
   ------------------------------------------------------------
   Warum es diese Datei gibt (Spec, Anhang A): das Design System
   wurde fuer einen Portal-Wizard geschrieben. Axiom 2 sagt "ein
   neuer Zustand braucht keine neue Farbe, sondern eine neue
   Dosis" -- eine DREISTUFIGE AMPEL laesst sich so nicht
   ausdruecken: Amber heisst Warnung, Gruen heisst gut.
   Der Mockup hat die Luecke mit sechzehn freien Hex-Werten
   gefuellt; hier bekommen sie Namen.
   Die Werte stammen aus "T7 Gruppeneinteilung.dc.html".
   Diese Rampen wandern zurueck ins Design System (Task 12).
   ============================================================ */
:root {
  /* --- Amber: die weiche Regel, die Warnung --- */
  --amber-050: #fdf6e7; /* Flaeche hinter einem Hinweis */
  --amber-100: #f5ead2; /* Chip-Fuellung */
  --amber-300: #e5d3a5; /* Ghost-Kante auf Amber-Flaeche */
  --amber-500: #c08a2d; /* die Ampelfarbe selbst */
  --amber-700: #8a6516; /* Schrift auf Amber-Flaeche */

  /* --- Grau-Leiter: Zwischentoene, die das System nicht kennt.
         Es hat nur --text-primary und --text-muted; ein Board
         braucht mehr Abstufungen fuer ruhige Meta-Angaben. --- */
  --grey-100: #f1f3f5;
  --grey-200: #dee2e6;
  --grey-300: #ced4da;
  --grey-500: #adb5bd;
  --grey-700: #495057;

  /* --- Die vier Werte des Mockups, fuer die das System keinen Namen hat.
         Beim Vergleich mit "T7 Gruppeneinteilung.dc.html" am 2026-08-27
         einzeln nachgeschlagen: alles andere aus dem Mockup liess sich auf
         ein vorhandenes Token abbilden, diese vier nicht. Sie gehen mit in
         die Rueckmeldung ans Designteam (Task 12). --- */
  --border-hairline: #e3e7e3;                       /* Kante um ziehbare Objekte */
  --green-a45: rgba(59, 119, 59, 0.45);             /* Chip-Kante beim Darueberfahren */
  --shadow-chip-hover: 0 3px 10px rgba(59, 119, 59, 0.08); /* enger als --shadow-ambient */
  --surface-raised: #fafbfa;                        /* zwischen --surface-base und --surface-lowest */

  /* Der Mockup faehrt seine Pillen in FUENF Groessen zwischen 0.66 und
     0.82rem; das System hat in dem Bereich zwei (--text-caption 0.82,
     --text-overline 0.72). Wir fahren zwei plus diese eine -- die kleinste
     Stufe braucht das Board wirklich, sonst sprengt der Badge-Cluster im
     Chip die Zeile. Auch das geht in die Rueckmeldung. */
  --text-badge: 0.68rem;

  /* Schleier hinter einem Seitenblatt. Der Mockup benutzt ihn dreimal,
     das System hat dafuer keinen Namen -- fuenfter Fund fuer Task 12. */
  --scrim: rgba(33, 37, 41, 0.25);

  /* Fuenfter Fund, seit dem 2026-09-04 ENTSCHIEDEN: der Mockup faehrt als
     Primaer-Hover #2f5f2f, das System fuhr --brand-strong = #224422. Daniel
     hat am Bildschirm fuer den Mockup-Wert entschieden -- er steht jetzt als
     --green-600 in colors.css, und --brand-strong zeigt darauf.
     --green-700 bleibt, was es war: der pressed-Ton und die Farbe von
     a:hover. Wer beide wieder zusammenlegt, dreht die Entscheidung um. */

  /* --- Semantische Ampel-Aliase: im Code steht nie eine Rampe --- */
  --ampel-ok:   var(--green-500);
  --ampel-warn: var(--amber-500);
  --ampel-hart: var(--danger);   /* seit 2026-08-28 das Mockup-Rot #a94442 */
}

/* @quelle tokens/typography.css */
/* ============================================================
   HaDiKo typography — two-voice system
   Dosis (UI voice): headings, nav, buttons, labels, numbers.
   Roboto Slab (content voice): paragraphs, descriptions, help.
   ============================================================ */
:root {
  --font-ui: 'Dosis', 'Helvetica Neue', Arial, sans-serif;
  --font-content: 'Roboto Slab', Georgia, 'Times New Roman', serif;

  /* Scale (16px root) */
  --text-display:    2.5rem;  /* 40px — step intros, page heroes */
  --text-title:      2rem;    /* 32px — confirmation titles */
  --text-heading:    1.6rem;  /* 25.6px — card titles */
  --text-subheading: 1.25rem; /* 20px — extension cards, sub-titles */
  --text-ui:         1.1rem;  /* 17.6px — buttons, stepper, nav */
  --text-body:       1rem;    /* 16px — long-form Roboto Slab */
  --text-small:      0.9rem;  /* 14.4px — hints, pills */
  --text-caption:    0.82rem; /* 13px — footnotes, meta */
  --text-overline:   0.72rem; /* 11.5px — uppercase section labels */

  /* Weights */
  --weight-ui-regular: 400;
  --weight-ui-medium:  600; /* Dosis semibold = default emphasis */
  --weight-ui-bold:    700;
  --weight-content-regular: 400;
  --weight-content-medium:  500;

  /* Rhythm */
  --leading-tight: 1.2;  /* display / titles */
  --leading-body:  1.5;  /* default */
  --leading-loose: 1.7;  /* confirmation prose */
  --tracking-overline: 0.12em; /* + uppercase */
  --tracking-wide: 0.015em;    /* large Dosis display */
}

/* @quelle tokens/fonts.css */
/* HaDiKo-Schriften — lokal statt CDN.
   Das Original des Design Systems importiert von der Google-Fonts-CDN.
   Fuer ein Werkzeug, das an einem AG-Tag traegt, hat eine Fremd-CDN im
   Ladepfad nichts verloren (Spec, Anhang A). Die Dateien kommen ueber
   @fontsource-Pakete und werden in main.ts importiert.

   ------------------------------------------------------------------
   WARUM HIER TOKENS STEHEN, DIE typography.css SCHON SETZT
   ------------------------------------------------------------------
   Das Design System schreibt selbst: "If offline use is needed, vendor
   the .ttf/.woff2 files and replace this import with local @font-face
   rules." Genau das haben wir getan -- aber @fontsource-variable
   registriert die Familien unter ANDEREN Namen:

       'Dosis'        (CDN)  ->  'Dosis Variable'        (@fontsource)
       'Roboto Slab'  (CDN)  ->  'Roboto Slab Variable'  (@fontsource)

   Die DS-Kopie `typography.css` nennt die CDN-Namen. Die trafen lokal
   ins Leere: die Oberflaeche lief von Task 4 bis zum 27.08.2026
   unbemerkt auf Helvetica und Georgia, das Axiom "zwei Stimmen" war
   nie zu sehen.

   Die Korrektur gehoert NICHT in typography.css -- die Datei ist eine
   wortgleiche Kopie aus dem Design System und bleibt es. Sie gehoert
   hierher, wo die lokale Abweichung ohnehin dokumentiert ist. Deshalb
   wird diese Datei in main.ts NACH typography.css geladen.

   Die CDN-Namen bleiben als zweite Stufe stehen: wer das Design System
   spaeter doch mit CDN-Schriften einbindet, faellt weich zurueck.
   ============================================================ */
:root {
  --font-ui: 'Dosis Variable', 'Dosis', 'Helvetica Neue', Arial, sans-serif;
  --font-content: 'Roboto Slab Variable', 'Roboto Slab', Georgia, 'Times New Roman', serif;
}

/* ============================================================
   DIE SCHRIFTDATEIEN SELBST
   ------------------------------------------------------------
   Bis zum 2026-09-04 standen hier nur die Familiennamen; die
   Dateien kamen aus npm-Paketen, die T7 in main.ts importierte.
   Das trug fuer T7 -- aber T5 und T9d sind je EINE index.html
   ohne npm und ohne Build. Sie haetten die Namen bekommen und
   keine Schriften, also Helvetica und Georgia: genau der Fehler,
   der bei T7 von Task 4 bis zum 27.08.2026 unbemerkt lief.

   Die Regeln stammen unveraendert aus @fontsource-variable, nur
   die Quellpfade sind umgebogen: `url(fonts/…)` loest gegen die
   URL des Stylesheets auf (/api/design/hadiko.css), ergibt also
   /api/design/fonts/… -- ohne jede Annahme ueber den Host.

   `unicode-range` bleibt erhalten: der Browser holt nur den
   Ausschnitt, den der Text wirklich braucht. Deshalb duerfen
   Kyrillisch, Griechisch und Vietnamesisch mitfahren, obwohl sie
   selten gebraucht werden -- bei internationalen Bewerbern sind
   sie keine Exoten und kosten zur Laufzeit nichts.
   ============================================================ */

/* dosis-vietnamese-wght-normal */
@font-face {
  font-family: 'Dosis Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(fonts/dosis-vietnamese-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

/* dosis-latin-ext-wght-normal */
@font-face {
  font-family: 'Dosis Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(fonts/dosis-latin-ext-wght-normal.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;
}

/* dosis-latin-wght-normal */
@font-face {
  font-family: 'Dosis Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(fonts/dosis-latin-wght-normal.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;
}

/* roboto-slab-cyrillic-ext-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-cyrillic-ext-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
}

/* roboto-slab-cyrillic-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-cyrillic-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

/* roboto-slab-greek-ext-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-greek-ext-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+1F00-1FFF;
}

/* roboto-slab-greek-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-greek-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
}

/* roboto-slab-vietnamese-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-vietnamese-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

/* roboto-slab-latin-ext-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-latin-ext-wght-normal.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;
}

/* roboto-slab-latin-wght-normal */
@font-face {
  font-family: 'Roboto Slab Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(fonts/roboto-slab-latin-wght-normal.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;
}

/* @quelle tokens/geometry.css */
/* ============================================================
   HaDiKo geometry — radius, spacing, elevation
   The 7px radius is a strict brand constant. Boundaries are
   made of background shifts + ambient shadows, not lines.
   ============================================================ */
:root {
  /* Radius */
  --radius: 7px;        /* THE radius — cards, buttons, inputs, zones */
  --radius-check: 3px;  /* custom checkboxes only */
  --radius-pill: 999px; /* file pills, capsules */

  /* Spacing — generous by default; when in doubt, go one step up */
  --space-2xs: 4px;
  --space-xs:  8px;
  --space-sm:  12px;
  --space-md:  16px;
  --space-lg:  24px;
  --space-xl:  32px;
  --space-2xl: 40px;
  --space-3xl: 56px;
  --space-4xl: 80px;

  /* Ambient shadows — large blur, 4–8% opacity, grey-green tint.
     Never harsh black drop shadows. */
  --shadow-ambient:       0px 15px 35px rgba(59, 119, 59, 0.06);
  --shadow-ambient-hover: 0px 20px 40px rgba(59, 119, 59, 0.08);
  --shadow-raised:        0px 4px 15px rgba(0, 0, 0, 0.05);   /* sticky header on scroll */
  --shadow-soft:          0px 4px 15px rgba(0, 0, 0, 0.03);   /* focused fields */
  --shadow-pill:          0px 4px 10px rgba(59, 119, 59, 0.20); /* small green chips */

  /* Layout constants */
  --header-height: 70px;
  --stepper-height: 56px;
  --content-max: 900px;   /* portal form column */
  --chevron-notch: 20px;  /* stepper arrow depth */
}

/* @quelle tokens/motion.css */
/* ============================================================
   HaDiKo motion — calm, editorial, never bouncy
   ============================================================ */
:root {
  --ease-editorial: cubic-bezier(0.16, 1, 0.3, 1); /* @kind other */ /* step slides, dropzone lift */
  --ease-standard:  cubic-bezier(0.4, 0, 0.2, 1);  /* @kind other */ /* labels, stepper, small UI */
  --duration-fast: 0.2s;   /* @kind other */ /* color/label shifts */
  --duration-base: 0.3s;   /* @kind other */ /* hovers, shadows, fills */
  --duration-slow: 0.5s;   /* @kind other */ /* wizard step slide-in */
  --hover-lift: translateY(-2px); /* @kind other */ /* buttons, dropzones */
  --hover-lift-subtle: translateY(-1px); /* @kind other */ /* fields */
}

/* @quelle tokens/base.css */
/* ============================================================
   HaDiKo base element defaults
   ============================================================ */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background-color: var(--surface-base);
  color: var(--text-primary);
  font-family: var(--font-content);
  font-size: 16px;
  line-height: var(--leading-body);
}

h1, h2, h3, h4, h5, h6, label, button, .ui-text {
  font-family: var(--font-ui);
}

h1, h2, h3, h4, h5, h6 { line-height: var(--leading-tight); margin: 0; }

a { color: var(--green-500); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--green-700); }

::selection { background: var(--green-100); color: var(--green-900); }

strong, b { font-weight: var(--weight-content-medium); }

/* @quelle hadiko.css */
/* ============================================================
   HaDiKo-Komponentenschicht — die geteilte Fassung
   ------------------------------------------------------------
   DIES IST DIE QUELLE. Sie liegt in py_ba_common und wird von
   allen Werkzeugen ueber /api/design/hadiko.css bezogen --
   frueher lag sie in T7 und wurde abgeschrieben. Genau daraus
   ist die Abdrift entstanden, die das Design System v2 behebt
   (Spec 2026-09-04-designsystem-v2-design.md, Abschnitt 1).

   Sie benutzt ausschliesslich Tokens, kein Tailwind und keine
   Vue-Besonderheit -- damit T5 und T9d sie benutzen koennen,
   die je EINE web/index.html ohne Build sind.
   Wache: py_ba_common/tests/test_design_waechter.py
   ============================================================ */

/* --- Blatt: das weisse Papier, angehoben --- */
.hd-sheet {
  background: var(--surface-card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-ambient);
  transition: box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}
.hd-sheet--hoverable:hover {
  box-shadow: var(--shadow-ambient-hover);
  transform: var(--hover-lift);
}

/* --- Inset: geht nach unten statt sich zu heben --- */
.hd-inset {
  background: var(--surface-inset);
  border-radius: var(--radius);
}

/* --- Overline: gefluesterte Beschilderung --- */
.hd-overline {
  font-family: var(--font-ui);
  font-size: var(--text-overline);
  font-weight: var(--weight-ui-bold);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* --- Knopf ---
   Groesse: --text-small, nicht --text-ui. Das Design System ist auf den
   Portal-Wizard kalibriert (1.1rem); der Mockup faehrt das Board auf 0.9rem.
   Entschieden 2026-08-27: die Komponentenschicht wandert mit, statt eine
   zweite Token-Gruppe einzufuehren. Login und Tagesauswahl werden dadurch
   mit kleiner -- bewusst in Kauf genommen. */
.hd-button {
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-bold);
  border-radius: var(--radius);
  padding: var(--space-xs) var(--space-md);
  border: none;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}
.hd-button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.hd-button:disabled { cursor: not-allowed; background: var(--green-300); }

.hd-button--primary { background: var(--brand); color: var(--text-on-brand); }
.hd-button--primary:hover:not(:disabled) { background: var(--brand-strong); transform: var(--hover-lift); }

.hd-button--secondary { background: var(--surface-card); color: var(--brand); border: var(--border-ghost); }
.hd-button--secondary:hover:not(:disabled) { background: var(--green-a04); }

.hd-button--ghost { background: transparent; color: var(--text-muted); }
.hd-button--ghost:hover:not(:disabled) { background: var(--green-a04); color: var(--brand); }

/* Loeschen muss aussehen wie Loeschen. Bewusst gefuellt statt nur roter Text:
   ein Knopf, der eine Gruppe aufloest, darf nicht wie ein Abbrechen wirken. */
.hd-button--gefahr { background: var(--danger); color: var(--text-on-brand); }
.hd-button--gefahr:hover:not(:disabled) { filter: brightness(0.92); transform: var(--hover-lift); }

/* --- Segmentierte Auswahl --- */
.hd-segment { display: inline-flex; background: var(--surface-inset); border-radius: var(--radius); padding: var(--space-2xs); }
.hd-segment__option {
  font-family: var(--font-ui); font-weight: var(--weight-ui-medium);
  border: none; background: transparent; color: var(--text-muted);
  border-radius: var(--radius); padding: var(--space-2xs) var(--space-sm); cursor: pointer;
}
.hd-segment__option[aria-pressed='true'] { background: var(--surface-card); color: var(--brand); box-shadow: var(--shadow-soft); }
.hd-segment__option:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* --- Feld: Mockup-Form ---
   Bis 2026-08-27 stand hier die Material-Form aus dem Portal-Wizard
   (graue Wanne, wanderndes Label, einfahrende Unterkante). Daniel hat sie
   fuer die Werkzeuge verworfen: der Mockup zeigt eine schlichte weisse Box
   mit grauer Kante und das Label als Overline darueber. Diese Form ist die
   neuere Entwurfsabsicht und geht so ins Design System zurueck.

   Der Fokus bleibt UNSER Entwurf -- gruene Kante plus weicher Halo. Der
   Mockup laesst dort nur `outline-color` stehen, das ist kein Zustand,
   den jemand gezeichnet hat, sondern ein nicht gesetzter Browser-Standard. */
.hd-field { display: flex; flex-direction: column; gap: var(--space-2xs); }
.hd-field__label {
  font-family: var(--font-ui);
  font-size: var(--text-overline);
  font-weight: var(--weight-ui-bold);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
}
.hd-field__input {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-medium);
  color: var(--text-primary);
  background: var(--surface-card);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  padding: var(--space-xs) var(--space-sm);
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}
.hd-field__input::placeholder { color: var(--text-muted); font-weight: var(--weight-ui-regular); }
.hd-field__input:focus { outline: none; border-color: var(--brand); box-shadow: var(--focus-ring); }
/* Fehler und Warnung sehen gleich aus und meinen Verschiedenes: `--fehler`
   heisst ungueltig, `--warnung` heisst gueltig und trotzdem auffaellig (ein
   doppelt vergebener Raum, Spec §2.3). Ein zweiter Rotton dafuer waere eine
   dritte Quelle -- getrennt sind die Klassen, nicht die Farbe. */
.hd-field--fehler .hd-field__input,
.hd-field--warnung .hd-field__input { border-color: var(--danger); }
.hd-field__fehler,
.hd-field__warnung { font-family: var(--font-ui); font-size: var(--text-caption); color: var(--danger); }

/* --- Checkbox: das einzige 3px-Eck im System --- */
.hd-check { display: inline-flex; align-items: center; gap: var(--space-xs); cursor: pointer; font-family: var(--font-ui); }
.hd-check__box {
  width: 20px; height: 20px; border-radius: var(--radius-check);
  background: var(--surface-inset); border: var(--border-ghost);
  display: grid; place-items: center; color: transparent;
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.hd-check__input:checked + .hd-check__box { background: var(--brand); color: var(--text-on-brand); }
.hd-check__input:focus-visible + .hd-check__box { box-shadow: var(--focus-ring); }
/* Waehrend der Zug nach RT laeuft: sichtbar wartend, nicht klickbar. */
.hd-check--wartet { opacity: 0.6; cursor: progress; }

/* --- Chip: eine Person ---
   Die Kante ist entschieden (Daniel, 2026-08-27): 1px Haarlinie wie im
   Mockup, statt Flaechenwechsel. Das ist die eine benannte Ausnahme vom
   Axiom "Grenzen sind keine Linien" -- begrenzt auf Dinge, die man anfassen
   kann. Alles andere im Board bleibt linienfrei. */
.hd-chip {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--surface-card);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius);
  padding: var(--chip-polster, var(--space-xs) var(--space-sm));
  cursor: grab;
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-medium);
  transition: background var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}
.hd-chip:hover { border-color: var(--green-a45); box-shadow: var(--shadow-chip-hover); }
.hd-chip:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.hd-chip--gewaehlt { background: var(--green-100); }
.hd-chip--schwebend { opacity: 0.6; cursor: progress; }
.hd-chip--ohne-ticket { background: var(--amber-050); color: var(--amber-700); }

/* Innerhalb einer Gruppenkarte sitzt der Chip auf weissem Grund und braucht
   die Kante erst beim Anfassen -- sonst gitterte die Karte zu. So macht es
   der Mockup auch (border: 1px solid transparent). */
.hd-chip--ruhig { border-color: transparent; }
.hd-chip--ruhig:hover { border-color: var(--green-a45); }
.hd-chip--gedaempft { background: var(--surface-raised); }

/* Der Name nimmt den Rest und kuerzt; was rechts steht, schrumpft NICHT mit.
   Ohne min-width:0 kuerzt ein Flex-Kind nicht -- seine Mindestbreite ist
   sonst die Inhaltsbreite, und dann bricht stattdessen die rechte Spalte um
   ("2,1 ." / "DE"). Genau das war der Fund an "Maximiliane von
   Hardtwald-Schmidt". */
.hd-chip__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hd-chip__vorn,
.hd-chip__hinten {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  flex-shrink: 0;
}
.hd-chip__meta { flex-shrink: 0; font-size: var(--text-caption); color: var(--grey-700); }

/* --- Board-Layout ---
   Warum das hier steht und nicht als Tailwind-Utilities auf der Seite: die
   Alternative waeren `w-[264px]`, `top-[82px]`, `gap-[14px]` -- also genau
   die harten Zahlen, gegen die diese Datei gebaut ist, nur an einem Ort, wo
   kein Waechter sie sieht. Getokenisiert und benannt ist ehrlicher, und
   Teil 2 baut das echte Board darauf. */
.hd-board {
  --board-gap: var(--space-md);
  --karte-polster: var(--space-sm);
  --chip-polster: var(--space-xs) var(--space-sm);
  display: flex;
  align-items: flex-start;
  gap: var(--space-lg);
  max-width: 1720px;
  margin: 0 auto;
  padding: var(--space-lg) var(--space-lg) var(--space-3xl);
  box-sizing: border-box;
}
/* Der Dichte-Schalter des Mockups. Ein Board, das am AG-Tag auf Laptop und
   Beamer laeuft, braucht ihn -- er ist kein Zierrat.
   Bis zum 2026-08-29 setzte er NUR --board-gap, und das wirkt an genau
   einer Stelle: der Schalter war unsichtbar und galt als kaputt. Dichte
   heisst Polster UND Abstaende, sonst spart sie keine Zeile. */
.hd-board--kompakt {
  --board-gap: var(--space-xs);
  --karte-polster: var(--space-xs);
  --chip-polster: var(--space-2xs) var(--space-xs);
}

.hd-board__leiste {
  position: sticky;
  top: calc(62px + var(--space-lg));
  width: 264px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-height: calc(100vh - 62px - var(--space-lg) * 2);
  overflow-y: auto;
}
.hd-board__gruppen {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  align-items: start;
  gap: var(--board-gap);
}

/* --- Das Tor: eine schmale Seite ohne Board dahinter ---------------------
   Tagesauswahl und (bis Welle 3/4) die Anzeige-Einstellungen. Beide
   benutzten diese Klassen seit jeher -- definiert waren sie NIE, in keiner
   Datei. Die Seiten liefen randlos ueber die volle Fensterbreite, und genau
   das war der Grund fuer "die Einstellungen sehen schrecklich aus"
   (Daniel, 2026-08-29). Gebaut wie LoginPage.vue:53, die gut aussieht. */
.hd-tor {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: var(--space-lg);
  background: var(--surface-page);
  box-sizing: border-box;
}
.hd-tor__blatt {
  width: 100%;
  max-width: 30rem;
  padding: var(--space-lg);
}

/* --- Kennzahl-Liste (Stand, Detail) --- */
.hd-stand { display: flex; flex-direction: column; gap: var(--space-2xs); font-family: var(--font-ui); }
.hd-stand > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-xs); }
.hd-stand dt { font-size: var(--text-small); font-weight: var(--weight-ui-medium); }
.hd-stand dd { font-size: var(--text-small); font-weight: var(--weight-ui-bold); text-align: right; }
.hd-stand__gruen { color: var(--brand); }
.hd-stand--leise dt,
.hd-stand--leise dd { color: var(--text-muted); }

.hd-legende { display: flex; flex-direction: column; gap: var(--space-2xs); margin-top: var(--space-md); }
.hd-legende > div { display: flex; align-items: center; gap: var(--space-xs); }
.hd-legende dd { font-family: var(--font-ui); font-size: var(--text-caption); color: var(--text-muted); }

/* --- Suchtreffer --- */
.hd-treffer {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: 100%;
  text-align: left;
  background: var(--surface-lowest);
  border: none;
  border-radius: var(--radius);
  padding: var(--space-xs) var(--space-sm);
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-medium);
}
.hd-treffer:hover { background: var(--green-a08); }
.hd-treffer:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Dieselbe Zeile, aber ohne Klick-Versprechen: sie traegt ihre Knoepfe
   selbst, statt als Ganzes eine Tat auszuloesen. Ein `cursor: pointer` auf
   einer Zeile, die auf einen Klick nicht reagiert, ist eine Luege. */
.hd-zeile {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: 100%;
  background: var(--surface-lowest);
  border-radius: var(--radius);
  padding: var(--space-xs) var(--space-sm);
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-medium);
}
.hd-zeile__fuellung { flex: 1; min-width: 0; }

/* --- Wartezeichen --- */
/* Grau, nicht gruen: Warten ist kein Zustand, den es zu betonen gilt.
   Die Flaeche allein sagt schon "hier fehlt noch etwas" -- der Schimmer
   ist ihre Betonung und faellt bei prefers-reduced-motion weg. */
.hd-laden { display: flex; flex-direction: column; gap: var(--space-2xs); width: 100%; }
.hd-laden__flaeche {
  display: block;
  height: 1em;
  border-radius: var(--radius);
  background: var(--surface-low);
}
.hd-laden__flaeche--block { height: 100%; width: 100%; }
@media (prefers-reduced-motion: no-preference) {
  .hd-laden__flaeche {
    background: linear-gradient(
      90deg,
      var(--surface-low) 0%,
      var(--surface-lowest) 50%,
      var(--surface-low) 100%
    );
    background-size: 300% 100%;
    animation: hd-schimmer 1.4s var(--ease-editorial) infinite;
  }
}
@keyframes hd-schimmer { from { background-position: 150% 0; } to { background-position: -150% 0; } }

/* Ein Nebenweg, keine Tat: Schriftgroesse einer Bildunterschrift, kein
   Knopf-Grund. Gruen bleibt der einen vollen Aktion je Ansicht vorbehalten. */
.hd-nachladen {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  color: var(--text-muted);
  text-decoration: underline;
}
.hd-nachladen:hover { color: var(--brand); }
.hd-nachladen:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius); }

/* --- Kleinkram --- */
.hd-trenner { border: none; height: 1px; background: var(--surface-low); margin: var(--space-2xs) 0; }
.hd-blattkopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-xs);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  font-weight: var(--weight-ui-bold);
}
.hd-blattkopf__zahl { font-size: var(--text-caption); color: var(--text-muted); }
.hd-blattkopf__rechts { display: flex; align-items: center; gap: var(--space-xs); }

/* Das Plus am Kopf der Pool-Karte (Welle 3/2). Bewusst schlicht: es steht
   neben einer Zahl, nicht zwischen Knoepfen -- ein hd-button waere hier
   zu laut. Die Trefferflaeche ist trotzdem 1.75rem, damit es am Tablet
   ohne Zielen erreichbar bleibt. */
.hd-plus {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--text-body);
  line-height: 1;
  color: var(--text-muted);
  border-radius: var(--radius);
}
.hd-plus:hover { color: var(--brand); background: var(--surface-lowest); }
.hd-plus:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.hd-hilfetext {
  font-family: var(--font-content);
  font-size: var(--text-caption);
  color: var(--text-muted);
  line-height: var(--leading-body);
  margin-top: var(--space-xs);
}
.hd-topbar__zurueck {
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-bold);
  color: var(--brand);
  text-decoration: none;
  white-space: nowrap;
}
.hd-topbar__zurueck:hover { color: var(--brand-strong); }

.hd-detail__name {
  font-family: var(--font-ui);
  font-size: var(--text-heading);
  font-weight: var(--weight-ui-bold);
  line-height: var(--leading-tight);
}
.hd-detail__prosa {
  font-family: var(--font-content);
  font-size: var(--text-small);
  line-height: var(--leading-loose);
  background: var(--surface-lowest);
  border-radius: var(--radius);
  padding: var(--space-sm) var(--space-md);
  margin-top: var(--space-xs);
}

/* --- Kopfzeile ---
   62px wie im Mockup. --header-height steht auf 70px und bleibt so: das
   Token gehoert dem Portal-Wizard. Task 12 meldet die Differenz. */
.hd-topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  height: 62px;
  padding: 0 var(--space-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-raised);
}
.hd-topbar__links { display: flex; align-items: center; gap: var(--space-md); min-width: 0; }
/* 26px -> 34px (Daniel, 2026-08-29: "das bitte auch etwas groesser").
   Die Kopfzeile bleibt bei 62px -- das Logo fuellt sie jetzt aus, statt
   darin zu schwimmen. */
.hd-topbar__logo { height: 34px; display: block; }

/* Wie .hd-gruppenkarte__titel: ein Knopf, der wie eine Ueberschrift
   aussieht. Die beiden duerfen nicht auseinanderlaufen. */
.hd-zykluskarte__name {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  text-align: left;
  display: block;
  width: 100%;
}
.hd-zykluskarte__name:hover { color: var(--brand); }
.hd-zykluskarte__name:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius);
}

/* Die Werkzeug-Kachel am Fuss der Leiste. Daniel, 2026-08-29: CSV und
   Anzeige "koennen auf einer kachel irgendwo ganz unten links im side
   board verschwinden". */
.hd-werkzeuge { display: flex; flex-direction: column; gap: var(--space-xs); }

/* Das Datum IST der Weg zum Tagwechsel (Welle 3/2). Es sieht aus wie die
   Overline, die es ersetzt -- nur eben anfassbar. Eine Stufe leichter als
   .hd-overline (medium statt bold), damit der Titel darueber der Anker
   bleibt. */
.hd-topbar__datum {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: var(--text-overline);
  font-weight: var(--weight-ui-medium);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
  text-decoration: none;
}
.hd-topbar__datum:hover { color: var(--brand); }
.hd-topbar__datum:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius);
}

/* Eigener Platz links von den Knoepfen: die Sync-Anzeige ist eine Angabe,
   keine Tat. Zwischen den Knoepfen sah sie 2026-08-27 aus wie einer. */
.hd-topbar__sync { display: flex; align-items: center; margin-left: var(--space-md); }

/* Setzt die zwei Tages-Taten von den zwei Werkzeugen ab -- vier Knoepfe in
   einer Reihe lesen sich sonst als eine Kette. */
.hd-topbar__trenner {
  width: 1px;
  align-self: stretch;
  margin: var(--space-xs) var(--space-2xs);
  background: var(--border-hairline);
}
.hd-topbar__titel {
  font-family: var(--font-ui);
  font-size: var(--text-subheading);
  font-weight: var(--weight-ui-bold);
  line-height: var(--leading-tight);
}
.hd-topbar__aktionen { display: flex; align-items: center; gap: var(--space-xs); flex-shrink: 0; }

/* --- Seitenblatt: faehrt von rechts ein --- */
/* Der Schleier trennt das Blatt vom Board und faengt den Klick daneben ab.
   Ohne ihn wirkt das Blatt wie ein Teil der Seite, und ein Klick auf eine
   Gruppenkarte dahinter loeste einen Zug aus, waehrend jemand liest. */
.hd-seitenblatt__schleier { position: fixed; inset: 0; z-index: 39; background: var(--scrim); }
.hd-seitenblatt {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 40;
  width: min(390px, 100vw);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  background: var(--surface-card);
  box-shadow: var(--shadow-ambient-hover);
  padding: var(--space-lg);
  overflow-y: auto;
}
.hd-seitenblatt:focus-visible { outline: none; }
.hd-seitenblatt__kopf { display: flex; align-items: center; justify-content: space-between; }
.hd-seitenblatt__schliessen {
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--text-subheading);
  line-height: 1;
  color: var(--text-muted);
  border-radius: var(--radius);
  padding: var(--space-2xs) var(--space-xs);
}
.hd-seitenblatt__schliessen:hover { color: var(--brand); background: var(--green-a04); }
.hd-seitenblatt__schliessen:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.hd-seitenblatt__inhalt { display: flex; flex-direction: column; gap: var(--space-md); }
@media (prefers-reduced-motion: no-preference) {
  .hd-seitenblatt { animation: hd-einfahren var(--duration-base) var(--ease-editorial); }
}
@keyframes hd-einfahren { from { transform: translateX(100%); } to { transform: none; } }

/* --- Gruppenkarte --- */
.hd-gruppenkarte {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--karte-polster, var(--space-sm));
}
/* Der Zeiger haelt etwas ueber dieser Karte. Zwei Selektoren, eine Regel: die
   Pool-Karte ist ein blankes HdSheet und keine Gruppenkarte, die Rueckmeldung
   soll aber dieselbe sein.

   ⚠️ **Der durchgezogene Ring ist Absicht -- die gestrichelte Kante des
   Mockups ist ausprobiert und verworfen.** Am 2026-09-04 habe ich sie auf
   Daniels Wunsch nachgebaut (`T7 Gruppeneinteilung.dc.html:201`: als
   `::after` mit `inset: 4px`, `2px dashed`, `pointer-events: none`), am
   Bildschirm gesehen und noch am selben Tag wieder zurueckgedreht: "das
   sieht kacke aus". **Nicht erneut anfangen**, auch nicht mit dem Argument
   "aber der Mockup macht es so" -- der Mockup ist an dieser einen Stelle
   gepruefte und abgelehnte Vorlage. Wer es doch will, holt vorher eine neue
   Entscheidung ein. */
.hd-gruppenkarte--ziel, .hd-sheet--ziel {
  background: var(--green-a08);
  box-shadow: 0 0 0 2px var(--green-a30);
}
.hd-gruppenkarte__kopf { display: flex; align-items: center; gap: var(--space-xs); }
.hd-gruppenkarte__titel {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  text-align: left;
  font-family: var(--font-ui);
  font-size: var(--text-subheading);
  font-weight: var(--weight-ui-bold);
  line-height: var(--leading-tight);
  white-space: nowrap;
  transition: color var(--duration-fast) var(--ease-standard);
}
.hd-gruppenkarte__titel:hover { color: var(--brand); }
.hd-gruppenkarte__titel:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius); }
/* Nimmt den Rest der Zeile, damit die Zahlen rechts anschlagen. min-width:0,
   sonst drueckt ein langer Raumname die Zahlen aus der Karte. */
/* Der Raum steht im Mockup in normaler Schrift und gruen, NICHT als
   Overline in Grossbuchstaben -- er ist eine Angabe, keine Rubrik. */
.hd-gruppenkarte__raum { flex: 1; min-width: 0; }
.hd-gruppenkarte__raum-text {
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-medium);
  color: var(--brand);
}
.hd-gruppenkarte__ampeln { display: flex; flex-wrap: wrap; gap: var(--space-2xs); }
.hd-gruppenkarte__inhalt { display: flex; flex-direction: column; gap: var(--space-2xs); }

/* --- Stepper: zwei Knoepfe um eine Zahl --- */
.hd-stepper { display: flex; flex-direction: column; gap: var(--space-2xs); }
.hd-stepper__label {
  font-family: var(--font-ui);
  font-size: var(--text-overline);
  font-weight: var(--weight-ui-bold);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
}
.hd-stepper__reihe { display: flex; align-items: center; gap: var(--space-xs); }
.hd-stepper__knopf {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: var(--radius);
  border: 1px solid var(--green-a30);
  background: var(--surface-card);
  color: var(--brand);
  font-family: var(--font-ui);
  font-size: var(--text-subheading);
  font-weight: var(--weight-ui-bold);
  line-height: 1;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard);
}
.hd-stepper__knopf:hover:not(:disabled) { background: var(--green-a04); }
.hd-stepper__knopf:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.hd-stepper__knopf:disabled { color: var(--green-300); cursor: not-allowed; }
.hd-stepper__wert {
  font-family: var(--font-ui);
  font-size: var(--text-heading);
  font-weight: var(--weight-ui-bold);
  min-width: 2ch;
  text-align: center;
}

/* --- Badge: die kleine Pille ---
   Der Mockup benutzt fuenf Groessen zwischen 0.66 und 0.82rem; das System
   hat zwei Stufen in dem Bereich. Wir fahren zwei -- Task 12 meldet die
   Spreizung als Befund, statt sie nachzubauen. */
.hd-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-ui);
  font-size: var(--text-overline);
  font-weight: var(--weight-ui-bold);
  letter-spacing: var(--tracking-wide);
  border-radius: var(--radius);
  padding: var(--space-2xs) var(--space-xs);
  white-space: nowrap;
}
.hd-badge--klein { font-size: var(--text-badge); padding: 2px var(--space-2xs); }

.hd-badge--neutral    { background: var(--grey-100);  color: var(--grey-700); }
.hd-badge--gruen      { background: var(--green-a12); color: var(--brand); }
.hd-badge--gruen-hell { background: var(--green-050); color: var(--brand); }
.hd-badge--amber      { background: var(--amber-050); color: var(--amber-700); }

/* --- Statuspunkt --- */
.hd-punkt {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}
.hd-punkt--ok    { background: var(--ampel-ok); }
.hd-punkt--warn  { background: var(--ampel-warn); }
.hd-punkt--hart  { background: var(--ampel-hart); }
/* Kein "transparent": ein leiser Ring sagt "geprueft, nichts zu melden" --
   transparent saehe aus wie "noch nicht geprueft". */
.hd-punkt--still { background: var(--surface-low); }
.hd-punkt--klein { width: 7px; height: 7px; }

/* --- Aufklappmenue -------------------------------------------------------
   Oeffnet nach OBEN: der einzige Verwender sitzt in der Werkzeug-Kachel am
   Fuss der Leiste, nach unten waere kein Platz. */
/* --- Klappe ---
   Der Pfeil, der eine Zyklus-Karte oder ihre Kontingente zuklappt (Daniel,
   2026-09-04). Ein blanker Knopf, kein `hd-button`: er steht neben einer
   Ueberschrift, nicht zwischen Knoepfen -- dieselbe Ueberlegung wie beim
   Plus am Kopf der Pool-Karte. Der Pfeil steht LINKS. */
.hd-klappe {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}
.hd-klappe--zeile { width: 100%; text-align: left; }
.hd-klappe:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius); }
/* Feste Breite, damit die Beschriftung beim Drehen nicht springt:
   `▸` und `▾` sind unterschiedlich breit. */
.hd-klappe__pfeil { flex: 0 0 auto; width: 0.9em; font-size: var(--text-caption); line-height: 1; }
.hd-zykluskarte__kopf { display: flex; align-items: center; gap: var(--space-2xs); }

/* --- Aufklapp-Sektion ---
   ⚠️ **Hier stand bis zum 2026-09-04 ein Overlay** -- `position: absolute`,
   `bottom: 100%`, `z-index: 30`, `--shadow-ambient`. Daniel hat es an der
   Live-Instanz gesehen und verworfen: `--shadow-ambient` ist ein
   6-%-Schatten, das weisse Blatt lag auf einer weissen Karte, und man sah
   keine Kante -- es schnitt die Karte darunter mitten durch eine Zeile und
   ragte einseitig ueber sie hinaus. Statt die Kante zu reparieren, ist die
   Ebene abgeschafft: der Abschnitt steht jetzt IM Fluss, die Kachel waechst.

   Damit gibt es nichts mehr zu ueberdecken, zu schichten oder wegzuklicken.
   **Nicht zum Overlay zurueckbauen**, ohne eine neue Entscheidung
   einzuholen. */
.hd-aufklapp__knopf {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  width: 100%;
  text-align: left;
}
/* Feste Breite, damit die Beschriftung beim Drehen des Pfeils nicht
   springt: `▸` und `▾` sind unterschiedlich breit. */
.hd-aufklapp__pfeil {
  flex: 0 0 auto;
  width: 0.9em;
  font-size: var(--text-caption);
  line-height: 1;
  color: var(--text-muted);
}
/* Der Bildschirm-Takt als EINE Zeile: "Neu laden alle [10] Sek." Vorher
   war er ein `HdNumber` mit eigener Beschriftung -- die einzige Zahl
   zwischen vier Schaltern, und sie brauchte drei Saetze Erklaerung. */
.hd-takt {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-ui);
  font-size: var(--text-small);
  color: var(--text-body);
}
.hd-takt__zahl { width: 4.5rem; flex: 0 0 auto; }

.hd-aufklapp__blatt {
  margin-top: var(--space-xs);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--border-hairline);
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* --- Ablagefläche ---
   Die Kante steht im Ruhezustand auf transparent statt zu fehlen: so bleibt
   ihr Platz im Layout reserviert und die Flaeche springt im Moment des
   Ziehens nicht um zwei Pixel. Der Mockup blendet sie ebenfalls erst beim
   Darueberziehen ein (sc-if g.isOver) -- dauerhaft sichtbar liess das Board
   wie ein Drahtgitter aussehen. */
.hd-drop {
  border: var(--border-ghost-dashed);
  border-color: transparent;
  border-radius: var(--radius);
  transition: background var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard);
}
.hd-drop--aktiv { background: var(--green-a08); border-color: var(--green-a30); }
/* Als Flaeche zeichnet es nichts selbst -- die umschlossene Karte hebt sich
   hervor (hd-gruppenkarte--ziel). Zwei Rahmen uebereinander waeren Doppelung. */
.hd-drop--flaeche, .hd-drop--flaeche.hd-drop--aktiv { border-color: transparent; background: none; }

/* Derselbe Ton wie der Punkt am Chip -- wer den Punkt sieht und darauf
   klickt, soll die Erklaerung wiedererkennen (Spec §2.6). */
/* Seit Welle 3/3 neutral statt amber. `--amber-050` ist im Token-Auszug
   ausdruecklich die "Flaeche hinter einem Hinweis" -- und ein Kommentar ist
   ab jetzt genau das nicht mehr. Stuende er weiter auf derselben Flaeche
   wie der Hinweis-Block direkt darueber, waere die ganze Unterscheidung
   zwischen Problem und Anmerkung nur noch im Zeichen sichtbar. */
.hd-kommentar { background: var(--surface-lowest); border-radius: var(--radius); padding: var(--space-sm); }

/* Sitzt in einer Gruppe, hat aber nicht zugesagt (Spec §4.4). Dieselbe
   Kante wie ein Fehlerfeld -- die Person ist nicht falsch, aber die Planung
   mit ihr ist es moeglicherweise. */
.hd-chip--widerrufen { border-color: var(--danger); }
.hd-chip--widerrufen .hd-chip__name { color: var(--danger); }

/* --- Ampel --- */
.hd-ampel { display: inline-flex; align-items: center; gap: var(--space-2xs); font-family: var(--font-ui); font-size: var(--text-caption); border-radius: var(--radius); padding: var(--space-2xs) var(--space-xs); }
.hd-ampel--ok   { color: var(--ampel-ok);   background: var(--green-a08); }
.hd-ampel--warn { color: var(--amber-700);  background: var(--amber-100); }
.hd-ampel--hart { color: var(--ampel-hart); background: var(--danger-bg); }

/* --- Kontingent-Balken --- */
.hd-meter { background: var(--surface-inset); border-radius: var(--radius-pill); overflow: hidden; height: var(--space-xs); }
.hd-meter__fuellung { height: 100%; background: var(--brand); transition: width var(--duration-base) var(--ease-standard); }
.hd-meter__fuellung--ueber { background: var(--ampel-warn); }

/* --- Toast: Papier, kein Alarm --- */
.hd-toast { background: var(--surface-card); border-radius: var(--radius); box-shadow: var(--shadow-ambient); padding: var(--space-sm) var(--space-md); font-family: var(--font-ui); }
.hd-toast--fehler { background: var(--danger-bg); color: var(--danger); }
.hd-toast--warn { background: var(--amber-050); color: var(--amber-700); }

/* --- Modal: gleitet herein, bounct nicht --- */
.hd-modal__schleier { position: fixed; inset: 0; background: var(--green-a12); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
.hd-modal__blatt { background: var(--surface-card); border-radius: var(--radius); box-shadow: var(--shadow-ambient); padding: var(--space-lg); }
@media (prefers-reduced-motion: no-preference) {
  .hd-modal__blatt { animation: hd-slide var(--duration-slow) var(--ease-editorial); }
}
@keyframes hd-slide { from { opacity: 0; transform: translateY(var(--space-md)); } to { opacity: 1; transform: none; } }

/* --- Sync-Anzeige --- */
.hd-sync { display: inline-flex; align-items: center; gap: var(--space-xs); font-family: var(--font-ui); font-size: var(--text-small); border-radius: var(--radius); padding: var(--space-2xs) var(--space-xs); }
.hd-sync--aktuell { color: var(--ampel-ok); background: var(--green-a08); }
.hd-sync--ausstehend { color: var(--grey-700); background: var(--grey-100); }
.hd-sync--angehalten { color: var(--ampel-hart); background: var(--danger-bg); }

/* --- Auswahl: natives select, damit Tastatur und Mobile gratis sind.
       Der Pfeil ist das Zeichen ▾ statt eines SVG-Data-URI -- ein Data-URI
       truege einen harten Farbwert und ist in dieser Datei verboten. --- */
.hd-select { display: flex; flex-direction: column; gap: var(--space-2xs); }
.hd-select__box { position: relative; display: block; }
.hd-select__input {
  width: 100%;
  box-sizing: border-box;
  appearance: none;
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-medium);
  color: var(--text-primary);
  background: var(--surface-card);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  padding: var(--space-xs) var(--space-xl) var(--space-xs) var(--space-sm);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}
.hd-select__input:focus { outline: none; border-color: var(--brand); box-shadow: var(--focus-ring); }
.hd-select--fehler .hd-select__input,
.hd-field--fehler .hd-select__input { border-color: var(--danger); }

/* Schlank: kein Kasten, gruen, buendig in einer Kopfzeile. Der Mockup
   setzt den Raum so -- als Text, der sich beim Anfassen als Auswahl
   zu erkennen gibt. */
.hd-select--schlank .hd-select__input {
  background: transparent;
  border-color: transparent;
  color: var(--brand);
  padding: var(--space-2xs) var(--space-lg) var(--space-2xs) 0;
}
.hd-select--schlank .hd-select__input:hover { border-color: var(--green-a45); }
.hd-select--schlank .hd-select__pfeil { right: var(--space-2xs); }
.hd-select__pfeil {
  position: absolute; right: var(--space-sm); top: 50%; transform: translateY(-50%);
  color: var(--grey-500); pointer-events: none; font-family: var(--font-ui); line-height: 1;
}

/* --- Check-in-Tisch --- */
/* Eine Spalte, mittig, breit genug fuer ein Gesicht und die Unterlagen
   daneben. Das Board ist die Uebersicht -- hier steht ein Mensch. */
.hd-tisch { max-width: 62rem; margin: 0 auto; padding: var(--space-lg) var(--space-md); display: flex; flex-direction: column; gap: var(--space-md); }
.hd-tisch__suche { padding: var(--space-md); }
.hd-tisch__blatt { padding: var(--space-md); display: flex; flex-direction: column; gap: var(--space-md); }
.hd-tisch__ruhe { text-align: center; padding: var(--space-xl) 0; }
/* Die Zeile traegt die groesste Schrift der Anwendung: sie ist das
   einzige, was am Tisch dauernd bedient wird. */
.hd-tisch__zeile {
  width: 100%;
  background: var(--surface-lowest);
  border: none;
  border-radius: var(--radius);
  padding: var(--space-sm) var(--space-md);
  font-family: var(--font-ui);
  font-size: var(--text-h2);
  font-weight: var(--weight-ui-medium);
  color: var(--text-strong);
}
.hd-tisch__zeile::placeholder { color: var(--text-muted); font-weight: var(--weight-ui-regular); }
.hd-tisch__zeile:focus { outline: none; box-shadow: var(--focus-ring); }
.hd-tisch__kopf { display: flex; align-items: flex-start; gap: var(--space-md); }
.hd-tisch__foto {
  width: 6rem; height: 6rem; flex: none;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-low);
  display: grid; place-items: center;
}
.hd-tisch__foto img { width: 100%; height: 100%; object-fit: cover; }
.hd-tisch__name { font-family: var(--font-ui); font-size: var(--text-h2); font-weight: var(--weight-ui-bold); color: var(--text-strong); }
.hd-tisch__spalten { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); }
.hd-tisch__gruppenwahl { width: 100%; }
@media (max-width: 48rem) {
  .hd-tisch__spalten { grid-template-columns: 1fr; }
}

/* --- Ticketnummer --- */
/* Gruen und unterstrichen: sie ist ein Weg nach draussen, kein Etikett.
   Keine volle gruene Flaeche -- die gehoert der einen Aktion je Ansicht. */
.hd-ticket {
  font-family: var(--font-ui);
  font-size: var(--text-small);
  font-weight: var(--weight-ui-bold);
  letter-spacing: 0.04em;
  color: var(--brand);
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* :not(.hd-ticket--tot), sonst gewinnt die Hover-Regel (Spezifitaet 0,2,0)
   gegen den toten Zustand (0,1,0) und der Text faerbt sich beim Hovern
   gruen, obwohl kein Klick etwas bewirkt. Gleiches Muster wie
   .hd-button--primary:hover:not(:disabled). */
.hd-ticket:hover:not(.hd-ticket--tot) { color: var(--brand-strong); }
.hd-ticket:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius); }
/* Ohne konfigurierte RT-URL: gleiche Stelle, gleiche Groesse, aber ohne
   das Versprechen eines Klicks. */
.hd-ticket--tot { color: var(--text-muted); text-decoration: none; }
