/*
 * Dark-first base stylesheet (Konzept Kap. 8: dunkles Standard-Theme).
 * Deliberately plain: no framework, no hero patterns, no fake stats — just
 * a calm, readable page skeleton for the web tier (D12).
 *
 * Tokens/typography/radius follow docs/design/DESIGN-SPEC.md v1 (PK.3a
 * migration). Structure/layout (Ringfeld, board redesign, motion) is out of
 * scope here — PK.3b.
 */

@font-face {
  /*
   * Archivo (SIL OFL 1.1, self-hosted — no Google-Fonts CDN, Datenschutz-
   * Linie). Variable font, wght axis 100–900; a single face declaration
   * with a font-weight range lets the browser interpolate every weight we
   * use (400/600/700/800) from one file. License: ./fonts/OFL.txt.
   */
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/archivo-variable-latin.woff2") format("woff2");
}

/* ===========================================================================
 * FARBWELTEN × MODI  (DESIGN-SPEC Nachtrag „App-Anmutung" §3, Konzept 3.14)
 * ---------------------------------------------------------------------------
 * Zwei vollständige Farbwelten, gleiche Struktur, gleiche Token-Namen, andere
 * Werte: „Flutlicht" (Orange, warmer heller Grund — Default) und „Nachtfahrt"
 * (Pink, kühler heller Grund). Je Farbwelt zwei Modi.
 *
 *   Farbwelt = Attribut am Wurzelelement (`<html data-color-world="…">`).
 *              In DIESEM Paket fest auf „flutlicht" verdrahtet (layout.eta) —
 *              Umschaltfläche und Kanal-Vertrag sind PKG-ANMUT-VERTRAG.
 *   Modus    = Gerätesache, `prefers-color-scheme`. Nie eine Produkt-Option.
 *
 * Aufteilung der Blöcke:
 *   1. `:root` / `@media light :root`  — MODUS-Token, in beiden Farbwelten
 *      IDENTISCH (Match-Grün, Fehler, Radien, Schrift, Baustein-Schleier).
 *      Match-Grün ist damit theme-fest und semantisch (§3, Konzept 3.14).
 *   2. je Farbwelt ein dunkler Block (gilt in BEIDEN Modi) und ein heller
 *      Media-Block, der nur die im Hellen abweichenden Werte überschreibt.
 *      Was im hellen Block fehlt, gilt bewusst in beiden Modi — allen voran
 *      die Karten-Token („Die Karte bleibt Abend", §2).
 *
 * Zwei Akzentstufen im HELLEN Modus (§3):
 *   --accent      Neonstufe — Flächen und Grafik (CTA, Wortmarken-Punkt,
 *                 Chips, Fokus). Erreicht ≥ 3:1 gegen den Grund (WCAG 1.4.11).
 *   --accent-ink  abgedunkelte Ink-Stufe desselben Farbtons für TEXT (≥ 4.5:1).
 *   --ring        Ringfüllung — im Hellen eigens abgedunkelt, damit die
 *                 dünnen Ringe als Grafik ≥ 3:1 tragen.
 * Im dunklen Modus fallen alle drei zusammen.
 *
 * Neon sitzt NUR an den benannten Stellen: Ringfüllung, CTA, Wortmarken-Punkt,
 * Kartentönung. Nie auf Fließtext, Grund, Linien, Nebentext.
 *
 * ZWEI Linien, zwei Aufgaben (PKG-BACKLOG-2, Backlog 21.07.2026 zu WCAG
 * 1.4.11) — die alte `--line` trug beides und war für das zweite zu schwach:
 *   --line          Flächentrennung: Baustein-Kante (--hairline), Zeilen- und
 *                   Abschnitts-Trenner, Panel-Rahmen. Kein Bedienelement,
 *                   keine 3:1-Pflicht — an der Baustein-Haarlinie ausdrücklich
 *                   am Bild abgenommen (Nachtrag „App-Anmutung" §1).
 *   --line-control  UMRISS eines Bedienelements: Eingabefelder, Wochentags-
 *                   Chips, Segment-Umschalter, Notiz-Chip, Melde-Feld. Die
 *                   Füllung dieser Elemente unterscheidet sich vom Nachbarn
 *                   nicht (hell: 1,04:1 weiß auf Creme) — der Umriss IST das
 *                   Erkennungsmerkmal und trägt deshalb ≥ 3:1 gegen BEIDE
 *                   Nachbarfarben, in jeder Farbwelt und in beiden Modi.
 * Gerechnete Zahlen stehen an den Token-Zeilen. „Baustein" heißt dabei die
 * FERTIG gemischte Fläche aus `.block--raised` (im Dunkeln --surface plus
 * 5-%-Schleier), nicht --surface allein — der Schleier hellt auf, und gegen die
 * hellere Fläche ist der Umriss schwächer. Die alten Zahlen an den
 * dunklen --line-control-Zeilen waren gegen --surface gerechnet und damit zu
 * gut; die tatsächlichen 2,70:1 fielen erst mit `test/web-color-contrast.test.ts`
 * auf (30.07.2026). Beide dunklen Werte sind seither eine Stufe heller.
 *
 * Kontrast-Zusage: WCAG AA in JEDER Kombination aus Farbwelt und Modus. Die
 * gerechnete Tabelle (alle Paare, 4 Kombinationen) liegt im Paket-Bericht
 * PKG-ANMUT-TOKENS; Zahlen an den Token-Zeilen sind die Kurzfassung.
 * =========================================================================== */

/* --- 1. Modus-Token (theme-fest, in BEIDEN Farbwelten identisch) ---------- */

:root {
  color-scheme: dark;

  /*
   * Match-Grün: AUSSCHLIESSLICH „Runde steht" und in beiden Farbwelten
   * identisch (§3 „Match-Grün ist theme-fest und semantisch"). Ein Theme
   * ändert nie Bedeutung, nur den Akzent.
   */
  --match: #52d18d;
  /* ≥ 9.7:1 gegen --bg, ≥ 7.7:1 gegen den Baustein in beiden Farbwelten. */
  --error: #e37e6e;
  /* ≥ 5.3:1 gegen jeden dunklen Grund/Baustein beider Farbwelten. */

  /*
   * Baustein-Schleier (§1): im DUNKLEN Modus hebt sich die angehobene Fläche
   * zusätzlich über einen 5-%-Schleier aus --fg vom Grund ab — der Schatten
   * allein verschwindet auf dunklem Grund. Im Hellen ist der Schleier 0 und
   * die Trennung übernimmt die Haarlinie (unten).
   */
  --raised-veil: 5%;
  /*
   * Haarlinie nur im HELLEN Modus (§1): Fläche und Grund liegen dort bei rund
   * 1,04:1 (Flutlicht) bzw. 1,20:1 (Nachtfahrt) — der Schatten allein trennt
   * nicht sicher. Es ist dieselbe Linie, die Mitglieder-Zeilen trennt. Im
   * Dunkeln bleibt die Kante transparent, die Geometrie aber gleich (1px).
   */
  --hairline: transparent;

  /*
   * Mischbasis der Avatar-Kreise (s. `.member-avatar`): die deterministische
   * Stufe mischt den Akzent gegen eine HELLE Basis, damit die dunkle Initiale
   * auf jeder Stufe AA trägt. Im Dunkeln ist das die Kreide, im Hellen das
   * Papierweiß der Bausteine.
   */
  --avatar-base: var(--fg);

  /*
   * Radien (§1: „Radius max. 8 px" ist aufgehoben — Bausteine tragen 12 px).
   *   --radius          Bausteine, Identitätskarte, CTA, Panels
   *   --radius-control  Eingabefelder, Chips, Segmente (bleiben bei 8 px:
   *                     ein Textfeld ist kein Baustein)
   *   --radius-sm       Inline-Kleinteile (Notiz-Slot, Swatch)
   */
  --radius: 12px;
  --radius-control: 8px;
  --radius-sm: 6px;

  /*
   * Absenkung der Link-Unterstreichung im Ruhezustand (PKG-VIS 20.07.2026).
   * Ein Wert für alle Flächen — s. die gemeinsame Regel am Ende dieser Datei.
   */
  --underline-veil: 45%;

  --font-sans: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;
    --match: #17693c;
    /* ≥ 5.5:1 gegen --bg, ≥ 6.7:1 gegen den Baustein in beiden Farbwelten. */
    --error: #b3402a;
    /* ≥ 4.7:1 gegen --bg, ≥ 5.7:1 gegen --surface. */
    --raised-veil: 0%;
    --hairline: var(--line);
    --avatar-base: var(--surface);
  }
}

/* --- 2a. Farbwelt „Flutlicht" (Default, hier fest verdrahtet) ------------- */

:root,
:root[data-color-world="flutlicht"] {
  /* Dunkel — Grund „Pflaume", Akzent elektrisiertes Orange. */
  --bg: #180f16;
  --surface: #251824;
  --line: #3d2a3a;
  --line-control: #7e6b75;
  /* Umriss von Bedienelementen — 3,80:1 gegen --bg, 3,03:1 gegen den Baustein. */
  --fg: #f7f0ec;
  /* 16,7:1 gegen --bg, 13,3:1 gegen den Baustein. */
  --muted: #b5a0a6;
  /* 7,6:1 gegen --bg, 6,1:1 gegen den Baustein. */
  --accent: #ff8a2a;
  --accent-ink: #ff8a2a;
  --accent-fg: #2b1403;
  --ring: #ff8a2a;
  /* 7,4:1 accent-fg auf accent; 8,0:1 Akzent-Text gegen --bg. */
  --raise: 0 1px 2px rgb(0 0 0 / 50%), 0 12px 30px rgb(0 0 0 / 45%);

  /*
   * Die Abend-Karte (§2 „Die Identitätskarte bleibt dunkel"): sie mischt
   * ihren Akzent IMMER in die Nachtfläche (--card-deep), nie in --surface.
   * Deshalb stehen diese vier Token NUR hier und werden im hellen Block
   * bewusst NICHT überschrieben — hell wie dunkel derselbe Block. Grund:
   * `accent 16 %` auf Weiß ergibt zwangsläufig einen pastelligen Ton.
   * Im hellen Modus ist die Karte damit der kräftige Farbträger der Fläche.
   */
  --card-deep: #482a25;
  --card-fg: #f7f0ec;
  /* 11,4:1 auf --card-deep, 6,9:1 auf der hellsten Tönungsstufe. */
  --card-muted: #d9c6bd;
  /* 7,8:1 auf --card-deep, 4,7:1 auf der hellsten Tönungsstufe. */
  --card-accent: #ff8a2a;
  /* 5,5:1 auf --card-deep — Bögen/Felder sind Grafik (≥ 3:1). */
  --card-scrim: 42, 26, 17;
}

@media (prefers-color-scheme: light) {
  :root,
  :root[data-color-world="flutlicht"] {
    /* Hell — der alte warme Grund (JD 25.07.2026: das Creme war nie die
     * Ursache, die Pfirsich-Karte davor war es). */
    --bg: #fff9f4;
    --surface: #ffffff;
    --line: #eddfd3;
    --line-control: #9d8c82;
    /* Umriss von Bedienelementen — 3,09:1 gegen --bg, 3,23:1 gegen --surface. */
    --fg: #2a1a13;
    /* 16,0:1 gegen --bg. */
    --muted: #705e54;
    /* 5,9:1 gegen --bg, 6,1:1 gegen --surface. */
    --accent: #e86800;
    /* Neon: 3,14:1 gegen --bg — Grafik/Flächen (WCAG 1.4.11). */
    --accent-ink: #a34500;
    /* Ink: 5,9:1 gegen --bg — Text. */
    --accent-fg: #2b1403;
    /* 5,3:1 auf --accent. */
    --ring: #cc5b00;
    /* 4,0:1 gegen --bg — die dünnen Ringe tragen als Grafik. */
    --raise: 0 1px 2px rgb(64 33 12 / 8%), 0 10px 28px rgb(64 33 12 / 13%);
  }
}

/* --- 2b. Farbwelt „Nachtfahrt" (zweite freie Farbwelt) ------------------- */

:root[data-color-world="nachtfahrt"] {
  --bg: #150f1d;
  --surface: #201731;
  --line: #38294e;
  --line-control: #786a8d;
  /* Umriss von Bedienelementen — 3,80:1 gegen --bg, 3,05:1 gegen den Baustein. */
  --fg: #f5f0f7;
  /* 16,7:1 gegen --bg, 13,4:1 gegen den Baustein. */
  --muted: #ac9ec2;
  /* 7,5:1 gegen --bg, 6,0:1 gegen den Baustein. */
  --accent: #ff4fa3;
  --accent-ink: #ff4fa3;
  --accent-fg: #2b0517;
  --ring: #ff4fa3;
  /* 6,1:1 accent-fg auf accent; 6,2:1 Akzent-Text gegen --bg. */
  --raise: 0 1px 2px rgb(0 0 0 / 50%), 0 12px 30px rgb(0 0 0 / 45%);

  --card-deep: #442043;
  --card-fg: #f5f0f7;
  /* 12,2:1 auf --card-deep, 8,0:1 auf der hellsten Tönungsstufe. */
  --card-muted: #d9c2d2;
  /* 8,2:1 auf --card-deep, 5,4:1 auf der hellsten Tönungsstufe. */
  --card-accent: #ff4fa3;
  /* 4,5:1 auf --card-deep — Grafik (≥ 3:1). */
  --card-scrim: 21, 15, 29;
}

@media (prefers-color-scheme: light) {
  :root[data-color-world="nachtfahrt"] {
    /* Hell — kühler Grund; die Abend-Karte trägt die Farbe. */
    --bg: #ece9ee;
    --surface: #ffffff;
    --line: #d8d0dc;
    --line-control: #8d8094;
    /* Umriss von Bedienelementen — 3,09:1 gegen --bg, 3,72:1 gegen --surface. */
    --fg: #231627;
    /* 14,4:1 gegen --bg. */
    --muted: #6e6076;
    /* 4,9:1 gegen --bg, 5,8:1 gegen --surface. */
    --accent: #f0248f;
    /* Neon: 3,26:1 gegen --bg. */
    --accent-ink: #b01371;
    /* Ink: 5,5:1 gegen --bg. */
    --accent-fg: #2b0517;
    /* 4,7:1 auf --accent. */
    --ring: #d81a7e;
    /* 4,0:1 gegen --bg. */
    --raise: 0 1px 2px rgb(10 5 15 / 10%), 0 10px 28px rgb(10 5 15 / 13%);
  }
}

* {
  box-sizing: border-box;
}

/*
 * Autoritativer `hidden`-Guard. Author-Klassen mit eigenem `display`
 * (.board-cta, .app-hint, .field, …) haben höhere Spezifität als die UA-Regel
 * `[hidden] { display: none }` und würden ein per JS (`element.hidden = true`)
 * ausgeblendetes Element sonst sichtbar lassen — beide CTAs gleichzeitig, der
 * App-Hinweis bei 0 Check-ins usw. Das `!important` macht das `hidden`-Attribut
 * über alle Author-`display`-Regeln autoritativ (Standard-Muster, vgl.
 * normalize.css). Toggle-Sichtbarkeit läuft ausschließlich über `hidden`.
 */
[hidden] {
  display: none !important;
}

html {
  height: 100%;
  /*
   * Control-Politur (Nachtrag „App-Anmutung"): was eine Fläche „nach App"
   * statt „nach Dokument" anfühlen lässt, ohne Funktion zu ändern.
   *  - kein grauer System-Blitz beim Antippen (der Druck-Feedback der Knöpfe
   *    ist der `scale(0.97)`-Press aus §6, nicht ein UA-Rechteck),
   *  - Nutzer-Schriftgrößen skalieren weiter (text-size-adjust: 100 %, NICHT
   *    `none` — das würde die dynamische Schriftgröße aushebeln).
   */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

/*
 * Textselektion in der Produktfarbe statt im Systemblau — und Chrome-Text
 * (Labels, Knöpfe, Wortmarke, Ringfeld, Avatare) ist gar nicht erst
 * selektierbar: ein langer Druck auf einen Knopf markiert in einer App keine
 * Buchstaben. Inhalt (Namen, Notizen, Links, Codes, Fließtext) bleibt
 * ausdrücklich selektierbar — die Code-Anzeige trägt sogar `user-select: all`.
 */
::selection {
  background: var(--accent);
  color: var(--accent-fg);
}

button,
summary,
label,
legend,
.board-wordmark,
.board-label,
.board-context,
.member-avatar,
.board-identity-art,
.rf {
  -webkit-user-select: none;
  user-select: none;
}

/*
 * Tap-Verzögerung/Doppeltipp-Zoom auf allen echten Bedienelementen aus —
 * Scroll und Pinch-Zoom bleiben unangetastet (`manipulation`, nicht `none`).
 */
button,
summary,
label,
a,
input,
select,
textarea {
  touch-action: manipulation;
}

input,
textarea {
  -webkit-user-select: text;
  user-select: text;
}

/*
 * EINE Fokus-Sprache (Nachtrag „App-Anmutung", Control-Politur). Die Regel in
 * einem Satz:
 *
 *   **Der Fokusring liegt in der Neonstufe (`--accent`) — außer auf einem
 *   Element, das selbst eine gefüllte Fläche trägt; dort liegt er in
 *   `currentColor`.**
 *
 * Der Grund für die eine Ausnahme ist keine Geschmacksfrage: ein Accent-Ring
 * um den gefüllten Accent-CTA, um einen gewählten Wochentag-Chip oder um ein
 * aktives Segment wäre Farbe auf derselben Farbe, also unsichtbar. Auf einer
 * gefüllten Fläche IST `currentColor` die Neonstufe-Gegenfarbe. Dieselbe
 * Sprache, zwei Fälle — nicht zwei Sprachen.
 *
 * Betroffen von der Ausnahme sind genau: `button`, `.weekday-chip`,
 * `.seg-option`, `.board-wordmark`. Alles andere — Eingabefelder, Links, die
 * als <a> gebauten CTAs — nimmt diese Regel hier bzw. ihren Accent-Zwilling.
 * Diese Deklaration ist die letzte Instanz: Elemente mit eigener Fokus-Regel
 * gewinnen über höhere Spezifität.
 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Häkchen/Schieber der nativen Controls in der Produktfarbe. */
input,
textarea,
select {
  accent-color: var(--accent);
}

/*
 * min-height statt height (Craft-Fix, Rettung 19.07.2026): mit fester Höhe
 * schob `justify-content: center` überlange Seiten (z. B. /new mit offenen
 * Wochentagen + Reset) über die obere Viewport-Kante hinaus — der Kopf war
 * abgeschnitten und UNERREICHBAR (Overflow oberhalb des Scroll-Ursprungs).
 * Mit min-height wächst der Body mit dem Inhalt: kurze Seiten bleiben exakt
 * wie bisher zentriert, lange beginnen oben und scrollen normal.
 */
body {
  min-height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/*
 * Board-Seite oben verankern (JD-Fund): die Tafel ändert ihre Höhe je Zustand
 * (leere vs. volle Runde). Mit der vertikalen Zentrierung des `body` (oben) würde
 * der Top-Abstand mitspringen — leere Tafel schwebt mittig, volle klebt oben. Für
 * die kurzen Formularseiten (home, /account/login, /c/:slug, /new) bleibt die
 * Zentrierung richtig; nur der Board-Kontext hebt den Zentrier-Anteil auf, sodass
 * Kopfzeile/Identitätskarte in JEDEM Zustand auf derselben Höhe sitzen. Der
 * konstante Top-Abstand kommt aus dem unveränderten `.page`-Padding (2rem oben).
 * `:has()` ist in allen aktuellen Browsern inkl. iOS-Safari verfügbar.
 */
body:has(.page-board) {
  justify-content: flex-start;
}

/*
 * Startseite eigener Layout-Fall (Nachzug B, Fable/JD-Fund „Cluster in der
 * Mitte"): `.page`'s einfache Body-Zentrierung hängte den gesamten Block
 * (Signet+Hero+CTA+leiser Pfad) optisch mittig im Viewport auf, während die
 * Fußzeile direkt darunter klebte — wirkte wie ein Klumpen in der Mitte statt
 * einer geführten Vorraum-Seite. Grid mit vier Zeilen: variabler Puffer oben
 * (min 2rem) · der Content-Block (Reihe 2) · ein GRÖSSERER variabler Puffer
 * darunter (1.6fr vs. 1fr oben, min 3rem) · Fußzeile fix an Reihe 4 (= am
 * Viewport-Boden, wächst der Puffer, bleibt sie unten). Nettoeffekt: der
 * Content-Block sitzt bei ~38 % Höhe (goldener Schnitt) statt bei 50 %.
 * `min-height: 100svh` (nicht 100vh) wegen mobiler Adressleisten.
 */
body:has(.page-home) {
  display: grid;
  grid-template-rows: minmax(2rem, 1fr) auto minmax(3rem, 1.6fr) auto;
  justify-items: center;
  align-items: start;
  min-height: 100svh;
}

body:has(.page-home) .page-home {
  grid-row: 2;
}

body:has(.page-home) .site-footer {
  grid-row: 4;
  margin-top: 0;
}

/* ===========================================================================
 * BAUSTEIN — die angehobene Fläche
 * (DESIGN-SPEC Nachtrag „App-Anmutung" §1, Konzept 3.14)
 * ---------------------------------------------------------------------------
 * „Zusammengehöriges sitzt in einer angehobenen Fläche: Surface-Farbe, Radius
 * 12 px, weicher Schatten. Im hellen Modus zusätzlich eine Haarlinie in
 * `--line` — dort liegen Fläche und Grund bei rund 1,04:1, der Schatten allein
 * trennt nicht."
 *
 * Das ist die wiederverwendbare Utility; PKG-ANMUT-WEB wendet sie nur noch an
 * (Meta als Kartenunterschrift, Selbst-Baustein, …) und baut keine eigenen
 * Flächen. Regeln für Anwender:
 *  - Ein Baustein ist eine SINN-Gruppe, keine Dekoration. Kein Baustein im
 *    Baustein.
 *  - Kein Kleintext steht frei auf dem Grund — er gehört in seinen Baustein
 *    oder wird Unterschrift seiner Karte.
 *  - Die Kante ist in beiden Modi 1px breit (im Dunkeln transparent), damit
 *    Innenmaße und Rhythmus modusunabhängig sind.
 * =========================================================================== */

.block {
  border-radius: var(--radius);
  padding: 0.75rem 1rem; /* 12/16 auf der Abstands-Skala */
  text-align: left;
}

.block--raised {
  /* Fallback für Engines ohne color-mix: reine Surface-Fläche. */
  background: var(--surface);
  background: color-mix(in srgb, var(--fg) var(--raised-veil), var(--surface));
  border: 1px solid var(--hairline);
  box-shadow: var(--raise);
}

/*
 * Kopfzeile eines Bausteins in der Labels-Rolle (§3: 11px Versalien, +6 %
 * Sperrung): links die Sache, rechts optional ihre Zahl (tabular-nums, damit
 * Zählstände beim Live-Update nicht wackeln).
 */
.block-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 0.75rem;
  margin: 0 0 0.25rem;
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.block-head-count {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}

/* Bausteine untereinander: 16 auf der Abstands-Skala. */
.block + .block {
  margin-top: 1rem;
}

.page {
  max-width: 32rem;
  padding: 2rem;
  text-align: center;
}

.page-form {
  text-align: left;
  width: 100%;
}

/*
 * Page headings (Interim-Wortmarke on home, form/board headings elsewhere).
 * DESIGN-SPEC §3 "Kanaltitel" role (21px Bold) is the closest defined role
 * for a page-level heading outside the Hero-Frage/Ringfeld context.
 */
.page h1 {
  margin: 0 0 0.5rem;
  font-size: 1.3125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Sub-headings (e.g. "Mitglieder", "Konto") — no dedicated spec role; sits
 * between Kanaltitel and body text. */
.page h2 {
  margin: 0 0 0.5rem;
  font-size: 1.125rem;
  font-weight: 700;
}

.page .tagline {
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

/*
 * Startseite (DESIGN-SPEC Nachtrag „Trichter v1", Variante B; JD-Abnahme-
 * Korrekturen: keine eigene Wortmarke mehr — Ring-Signet + Hero „Kannste
 * heute?" führen allein, sonst stünde „kannste" doppelt; Erklärsatz
 * ERSATZLOS gestrichen, Rhythmus jetzt Signet ·24· Hero ·32· CTA ·16·
 * leiser Pfad). Kein Trichter-Kopf — reine Vorraum-Seite, eigener Layout-Fall
 * `.page-home` (s. `body:has(.page-home)` oben) statt der einfachen `.page`-
 * Zentrierung. Hero-Frage/Accent-Wort/Ringfeld-K-Text sind bewusst auf
 * `.board-stand--empty`/`.board-hero-accent`/`.rf-k` gemappt statt neu
 * definiert — dieselbe Signatur-Sprache wie die Tafel, eine Quelle je Rolle.
 */

/* Leeres Ring-Signet: stilles Zeichen, KEINE Zustandsanzeige — dieselbe
 * Ring-Geometrie wie das Ringfeld (board-logic.js: r=55, Schritt 32 statt
 * 16 — nur 3 statt bis zu 8 Ringe, größere Sprünge), kleiner dargestellt
 * (~96px statt 190px). Die viewBox in home.eta ist auf den gezeichneten
 * Bereich zugeschnitten (nicht die volle 400×400 Ringfeld-viewBox), sonst
 * blieb bei dieser Darstellungsgröße ringsum toter Rand. `margin-bottom`
 * bewusst 0: der Abstand zur Hero-Frage kommt allein aus dem
 * `.page-home .board-stand--empty`-Override unten (eine Quelle, kein
 * doppelter Rhythmus).
 */
.home-signet {
  display: block;
  width: 6rem;
  height: 6rem;
  margin: 0 auto;
}

/* Rhythmus-Override (Nachzug B: Signet ·24· Hero ·32· CTA, ohne den
 * gestrichenen Erklärsatz) — ersetzt `.board-stand--empty`'s Board-Werte
 * (0.75rem/2rem) nur auf der Startseite; die Tafel selbst bleibt unberührt. */
.page-home .board-stand--empty {
  margin: 1.5rem auto 2rem; /* 24 Signet→Hero, 32 Hero→CTA */
}

.home-cta {
  margin: 0 0 1rem; /* 16 CTA→leiser Pfad */
}

.home-invited {
  margin: 0;
}

/*
 * Form elements (P2.1: /new, /c/:inviteSlug). Relative units throughout so
 * user font-size preferences scale the whole form (product-ux.md:
 * "dynamische Schriftgrößen"); contrast checked against both themes.
 */
.field {
  margin: 0 0 1.25rem;
  border: none;
  padding: 0;
}

.field label,
.field legend {
  display: block;
  margin: 0 0 0.375rem;
  font-weight: 600;
}

.field input[type="text"],
.field input[type="number"],
.field input[type="email"] {
  width: 100%;
  font: inherit;
  font-size: 1rem;
  padding: 0.625rem 0.75rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line-control);
  background: var(--bg);
  color: var(--fg);
}

/* Eingabefelder tragen keine gefüllte Fläche → Neonstufe (Fokus-Sprache, s.
 * `:focus-visible` oben). Vorher sprachen sie zwei Sprachen: die
 * formular-gescopten Felder Accent, die übrigen (Teilen-Link, Gerätecode,
 * Kapazität, Titel, Notiz, Melde-Feld) die Textfarbe. */
.field input[type="text"]:focus,
.field input[type="number"]:focus,
.field input[type="email"]:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.field .choice {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0 1.25rem 0.5rem 0;
  font-weight: 400;
}

.hint {
  margin: 0.375rem 0 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

/*
 * /new-Formular in drei Sinn-Gruppen (DESIGN-SPEC Nachtrag „Trichter v1",
 * W2): dünne `--line`-Trenner statt Karten/Gruppen-Überschriften — Runde /
 * Spielregeln / Du.
 */
.form-divider {
  height: 0;
  margin: 1.5rem 0;
  border: none;
  border-top: 1px solid var(--line);
}

/*
 * Kompakte Zahlenfelder (Schwelle/Kapazität/Reset-Uhrzeit, Trichter v1):
 * kurzes Label links (die Erklärung steht in der `.hint`-Zeile darunter,
 * nicht im Label selbst — konsistent für alle drei Zeilen), Feld rechts in
 * einer Zeile — dasselbe `.board-setting--inline`-Muster wie board.eta's
 * Kapazitäts-Einstellzeile. `flex-wrap: nowrap` + `justify-content:
 * space-between` (übersteuert `.board-setting--inline`'s `wrap`) hält das
 * Feld auch bei langem/umbrechendem Label IMMER rechts in derselben Zeile —
 * das Label darf intern umbrechen, das Feld rutscht nie darunter.
 */
.field-inline {
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
}

.field-inline label {
  margin: 0;
  flex: 1 1 auto;
}

/*
 * `.field input[type="number"] { width: 100% }` (oben) hat dieselbe
 * Spezifität (Klasse + Attribut-Selektor) wie eine reine `.board-capacity-
 * input`-Regel — ohne diese Übersteuerung würde das Feld trotz
 * `.board-capacity-input` auf volle Breite gezogen. Quellreihenfolge macht
 * diese Regel (später im Stylesheet) zur gewinnenden.
 */
.field-inline input[type="number"] {
  width: 4.5rem;
  flex: 0 0 auto;
}

/*
 * Wochentage als flache Tag-Chips (Trichter v1): die Checkbox bleibt die
 * Funktions-Trägerin (new.js liest weiterhin `input[name="weekday"]:checked`)
 * — rein visuell auf Klemmengröße verborgen (nicht `display:none`, bleibt
 * fokussierbar/klickbar über das Label). Gewählter Zustand über `:has()`,
 * dasselbe Muster wie `body:has(.page-board)`.
 */
.weekday-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/*
 * Craft-Fix (Rettung 19.07.2026): `.weekday-chip-row > .weekday-chip` statt
 * `.weekday-chip` — dieselbe Spezifitäts-Lecke wie beim Segment-Umschalter
 * (`.field label` 0-1-1 schlug 0-1-0: Text klebte oben im Chip, tote Fläche
 * darunter). 0-2-0 gewinnt; margin explizit 0.
 */
.weekday-chip-row > .weekday-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0 0.75rem;
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
}

.weekday-chip-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.weekday-chip:has(.weekday-chip-input:checked) {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}

.weekday-chip:has(.weekday-chip-input:focus-visible) {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/*
 * Teilen-Schritt (Trichter v1): Primär-CTA „Link kopieren" + Sekundär
 * „Teilen" (Web Share, nur wenn verfügbar) vertikal gestapelt mit Abstand —
 * `.board-cta` selbst trägt keinen Vertical-Gap (board.eta zeigt seine zwei
 * CTAs nie gleichzeitig, hier stehen beide parallel).
 */
.share-actions {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

/*
 * OS-Number-Spinner global töten (W2b): die kompakten Zahlenfelder (Ringfeld-
 * Picker „Ab"/„Plätze", Reset, board.eta-Kapazität) tragen ihre Werte zentriert
 * bzw. rechtsbündig — die UA-Spinner-Pfeile stören Layout und Zentrierung. Die
 * Felder bleiben `type="number"` (Tastatur-Pfeile + inputmode="numeric").
 */
input[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/*
 * Felder-Skin der Trichter-Formulare (W2b /new, W3 /c/:slug, W4 Konto):
 * Text-/Zahlen-/E-Mail-Felder auf `--surface`, Fokus als `--accent`-Outline,
 * Feld-Labels in der Versalien-Labels-Rolle (§3) statt 600-Bold. Auf
 * `.new-form`/`.join-form`/`.account-form` gescopt — der Teilen-Schritt
 * bleibt unberührt.
 */
.new-form .field input[type="text"],
.new-form .field input[type="number"],
.join-form .field input[type="text"],
.account-form .field input[type="email"] {
  background: var(--surface);
}

.new-form .field input[type="text"]:focus,
.new-form .field input[type="number"]:focus,
.join-form .field input[type="text"]:focus,
.account-form .field input[type="email"]:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/*
 * … AUSSER im Baustein: dort ist `--surface` die Fläche des Bausteins selbst,
 * ein Feld in derselben Farbe verschwände darauf (hell: weiß auf weiß). Auf
 * einer angehobenen Fläche liegt das Feld eingesenkt im Grundton — dieselbe
 * Logik wie beim Titel-Feld der Tafel. Gleiche Spezifität wie die Regel
 * oben, gewinnt über die Quellreihenfolge.
 */
.block--raised .field input[type="text"],
.block--raised .field input[type="number"],
.block--raised .field input[type="email"] {
  background: var(--bg);
}

.new-form .field > label,
.new-form .field > legend,
.join-form .field > label,
.account-form .field > label {
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Öffentlicher Tagesstand auf der Einladung (IR2): dieselbe Stand-Typografie
 * wie die Tafel, kompakt zwischen Identitätskarte und Beitrittsformular. */
.join-stand {
  margin: 1.5rem 0;
  padding: 1rem 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.join-stand .board-stand {
  margin: 0;
  font-size: 1rem;
  line-height: 1.5;
}

.join-stand-member {
  white-space: normal;
}

.join-stand-match {
  margin: 0.25rem 0 0;
  color: var(--match);
  font-size: 0.8125rem;
  font-weight: 700;
}

/*
 * Beitritts-Baustein und Bestands-Baustein der Einladung (§1). Das Polster
 * kommt vom Baustein; das letzte Kind gibt sein Außenmaß ab, damit unten
 * nicht zwei Abstände stehen.
 */
.join-block > :last-child,
.join-entries > :last-child {
  margin-bottom: 0;
}

.join-block > p:first-child {
  margin-top: 0;
}

/*
 * Die zwei Bestands-Wege stehen untereinander in EINER Flucht — dieselbe
 * gestapelte Aktionsliste wie im Selbst-Panel, inklusive des aus der Flucht
 * geschobenen `.board-quiet`-Polsters.
 */
.join-entries {
  margin-top: 1rem;
}

.join-entries .join-existing {
  margin: 0 0 0 -0.25rem;
  /* Im Baustein steht die Liste links in EINER Flucht (die freistehende
   * Bestandszeile war zentriert — im Baustein wäre das eine zweite Achse). */
  text-align: left;
}

.join-conflict {
  margin-top: 1.5rem;
}

.join-conflict-actions {
  display: grid;
  gap: 0.75rem;
}

.join-existing {
  margin: 0.75rem 0 0;
  text-align: center;
}

@media (min-width: 28rem) {
  .join-conflict-actions {
    grid-template-columns: 1fr 1fr;
  }
}

/* Titel in Kanaltitel-Typo (§3: 21px Bold) — man tippt den Tafel-Titel. */
.field-title {
  font-size: 1.3125rem;
  font-weight: 700;
}

/*
 * Segmentierter Rhythmus-Umschalter (W2b): Accent-Füllung fürs aktive Segment
 * als Skin über den echten (visuell verborgenen, aber fokussier-/klickbaren)
 * Radios `name="rhythm"`. Gewählter Zustand via `:has()` — dasselbe Muster wie
 * die Wochentag-Chips.
 */
.seg-field {
  margin-bottom: 1.25rem;
}

.seg {
  display: flex;
  margin: 0.375rem 0 0;
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  overflow: hidden;
}

/*
 * Craft-Fix (Rettung 19.07.2026): `.seg > .seg-option` statt `.seg-option` —
 * die globale `.field label`-Regel (0-1-1: display:block + margin-bottom)
 * schlug das nackte `.seg-option` (0-1-0) und brach Zentrierung + Bündigkeit
 * (Accent-Füllung endete über der Container-Unterkante, Text klebte oben).
 * 0-2-0 gewinnt; margin explizit 0.
 */
.seg > .seg-option {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  min-height: 2.75rem;
  padding: 0 0.75rem;
  font-size: 0.9375rem;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
}

.seg > .seg-option:not(:first-child) {
  border-left: 1px solid var(--line-control);
}

.seg-option input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.seg-option:has(input:checked) {
  background: var(--accent);
  color: var(--accent-fg);
}

.seg-option:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/*
 * Ringfeld-Picker (W2b-Rettung 19.07.2026, DESIGN-SPEC „Trichter v1"): das
 * Ringfeld der Tafel wird hier zum Control für Schwelle UND Kapazität. Gebaut
 * über dieselbe Pipeline (board-logic.js `buildRingfieldSvg`) — darum greifen
 * `.rf`/`.rf-k` wie auf der Tafel. Darunter die Stand-Zeile aus `describeMeta`
 * und die zwei sichtbaren kompakten Zahlenfelder „Ab"/„Plätze" (A11y-Wahrheit).
 * Rhythmus der Gruppe auf der 4/8/…-Skala: Ring ·12· Stand ·16· Felder ·24·.
 * KEIN Titel-Echo, KEIN Hint-Absatz mehr (Rettung: das Control erklärt sich
 * über Affordanz oder gar nicht — die Zahlenfelder bleiben der klare Weg).
 */
.rf-picker-group {
  /* Picker-Ring-Stufen (Rettung): Deckkräfte theme-abhängig — dunkel braucht
   * mehr, weil es hier nie gefüllte Accent-Ringe gibt, die das Feld tragen. */
  --rf-pflicht-o: 0.22;
  --rf-extra-o: 0.13;
  margin-bottom: 1.5rem;
}

@media (prefers-color-scheme: light) {
  .rf-picker-group {
    --rf-pflicht-o: 0.2;
    --rf-extra-o: 0.08;
  }
}

.rf-picker {
  display: flex;
  justify-content: center;
  margin: 0;
  line-height: 0;
  touch-action: none;
}

/* 12.5rem statt 15rem (Rettung): das Feld stellt zwei kleine Zahlen ein —
 * es darf nicht das dominanteste Element der Seite sein (das ist der CTA). */
.rf-picker .rf {
  width: 12.5rem;
  height: 12.5rem;
  max-width: 80vw;
  cursor: pointer;
  user-select: none;
}

.rf-picker .rf-k {
  font-family: var(--font-sans);
  font-weight: 800;
}

/*
 * Drei Ring-Stufen (Rettung, nur im Picker — die Tafel bleibt bei ihren
 * Präsentations-Attributen aus board-logic.js; CSS-Klassen schlagen die
 * Attribute, darum reicht dieses Override ohne board.js-Änderung):
 *  - Pflicht (unterhalb der Schwelle): fg, deutlich sichtbar — „bis hier
 *    muss sich das Feld füllen".
 *  - Schwelle: gestrichelt Accent, aber LEISER als der CTA (0.55, dünner,
 *    feinerer Dash) — vorher war der Dash-Ring das lauteste Orange des
 *    Screens und las sich als Spinner.
 *  - Extra (zwischen Schwelle und Kapazität): fast still.
 */
.rf-picker .rf-pflicht {
  stroke: var(--fg);
  stroke-opacity: var(--rf-pflicht-o);
}

.rf-picker .rf-schwelle {
  stroke: var(--accent);
  stroke-opacity: 0.55;
  stroke-width: 5.5;
  stroke-dasharray: 9 8;
}

.rf-picker .rf-extra {
  stroke: var(--fg);
  stroke-opacity: var(--rf-extra-o);
}

/* Deckel-Griff (Kapazitäts-Griff am Feldrand) — Greif-Cursor. */
.rf-deckel {
  cursor: grab;
}

/* Stand-Zeile des Pickers (describeMeta): 16px, mittig, --muted (kein Zustand,
 * nur die eingestellte Regel — grün/„steht" gibt es im Picker nie). */
.rf-stand {
  margin: 0.75rem 0 1rem;
  text-align: center;
  font-size: 1rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.rf-numrow {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  margin: 0;
}

.rf-numcell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
}

.rf-numcell label {
  margin: 0;
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.rf-num {
  width: 5rem;
  font: inherit;
  font-size: 1.1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: center;
  padding: 0.45rem 0.5rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line-control);
  background: var(--surface);
  color: var(--fg);
}

.rf-num:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/*
 * Reset-Uhrzeit als Uhrzeit (Rettung): bordered Gruppe „5:00" — die Stunde
 * bleibt das echte #reset-hour-Number-Input (Submit-Wert 0–23), das „:00"
 * ist statisches Suffix. Der Rahmen sitzt auf der Gruppe, das Input darin
 * ist rahmenlos; Fokus als focus-within auf der Gruppe (ein Feld, ein Ring).
 */
.reset-time {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  background: var(--surface);
  padding-right: 0.625rem;
}

.reset-time:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.new-form .field-inline .reset-time input[type="number"] {
  width: 2.6rem;
  border: none;
  background: transparent;
  text-align: right;
  padding: 0.45rem 0.1rem 0.45rem 0.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.new-form .field-inline .reset-time input[type="number"]:focus {
  outline: none;
}

.reset-time-suffix {
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}

.form-error {
  margin: 0 0 1rem;
  color: var(--error);
  font-weight: 600;
}

/*
 * Generic button (UI/Buttons role: 15-16px Semibold). The filled --accent
 * CTA treatment + single-primary-CTA rule from DESIGN-SPEC §5.4 is a board
 * layout concern (CTA-Redesign) — PK.3b. This is only the token/typo/radius
 * migration of the existing fg-on-bg button skin.
 */
button {
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  padding: 0.625rem 1.25rem;
  border-radius: var(--radius-control);
  border: none;
  background: var(--fg);
  color: var(--bg);
  cursor: pointer;
}

button:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

button + button {
  margin-left: 0.75rem;
}

/*
 * Board (P2.2). Zustände A/B (Konzept Kap. 3): the count line doubles as
 * the empty-state invite copy ("Heute noch nichts — Bock?") when there are
 * no check-ins yet, so it shares one element/style instead of two. Sized
 * to the Hero-Frage role (26-28px ExtraBold) since it carries that copy;
 * tabular-nums for the "3 von 4" count state. Splitting this into a
 * dedicated Hero-Frage element plus a separate Stand-Zeile is the Ringfeld
 * work (PK.3b).
 */
.page-board {
  max-width: 32rem;
  width: 100%;
}

/*
 * Tafel-Layout (DESIGN-SPEC §5 + §5.6 „Bühne und Rand"): zweiseitige Kopfzeile
 * · Regel · Kanaltitel + Meta · Ringfeld + Stand/Hero · Mitglieder · Notiz ·
 * EIN CTA · Fußzeile-Caption (= Bühne + leiser Boden), darunter erst die Rand-
 * Zone. Flat-grafisch, keine Karten; Gliederung nur über dünne 1px-`--line`-
 * Linien (§5.6.1). Abstands-Skala 4/8/12/16/24/32 px = 0.25/0.5/0.75/1/1.5/2 rem.
 * Rhythmus: Kopfzeile ·16· Regel ·24· Titel ·8· Meta ·24· Ringfeld ·(8/12)·
 * Stand/Hero ·16· Mitglieder ·24· Notiz-Label ·12· Platte ·12· CTA ·12·
 * Caption ·32· Rand.
 */
.board-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
}

/*
 * Auch als <a href="/"> genutzt (Trichter-Kopf, W1: partials/trichter-header)
 * — board.eta selbst rendert sie weiter als <p> (kein Sinn, auf der eigenen
 * Tafel zu sich selbst zu verlinken). color/text-decoration sind No-Ops auf
 * <p>, machen den Link aber unlink-artig (keine blaue Systemfarbe/Unterstreichung).
 */
.board-wordmark {
  margin: 0;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
  color: inherit;
  text-decoration: none;
}

.board-wordmark:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* Accent-Punkt an der Wortmarke (§5.6+): hochgestellt an Versalhöhe, 8px
 * (0.5em), 2px Abstand zum „e", --accent. Typografie, kein Logo-Ersatz —
 * der einzige Accent-Punkt oberhalb des CTA. */
.board-wordmark-dot {
  margin-left: 2px;
  font-size: 0.5em;
  vertical-align: 0.62em;
  color: var(--accent);
}

/*
 * Rechte Kopf-Seite (Nachtrag „App-Anmutung" §6): Tagesangabe + Avatar. Der
 * Avatar ist der Zugang zum Persönlichen; die Tagesangabe bleibt daneben
 * stehen, weil sie seit Konzept 3.8 tragend ist.
 */
.board-header-side {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

/*
 * Avatar-Knopf: dieselbe Kreis-Sprache wie die Mitglieder-Zeilen, eine Spur
 * größer (30px), volle Akzentfüllung — er steht für EINE Person, trägt also
 * keine deterministische Stufe. `min-height` bewusst NICHT auf 44px: der
 * Knopf sitzt in der Kopfzeile, sein Trefferfeld wächst über das Padding des
 * Kopfes, nicht über eine hohe Zeile.
 */
.board-self-avatar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.875rem;
  height: 1.875rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

/*
 * Selbst-Panel (§6). Modal über der Tafel: der Hintergrund tritt zurück, der
 * Fokus bleibt drin (board.js). Flache Deck-Fläche, kein Verlauf.
 */
/*
 * Deckfläche. Dunkel: der Grund selbst, deckend genug, dass die Tafel
 * zurücktritt. Hell muss sie die GEGENRICHTUNG nehmen (Review-Fund): `--bg`
 * über einem hellen Grund senkt zwar den Kontrast der Tafel, nicht aber ihre
 * Helligkeit — die Tafel las nicht zurückgetreten, sondern ausgebleicht bzw.
 * deaktiviert, während das fast weiße Panel vor fast gleich hellem Umfeld
 * stand. Weniger Deckkraft macht das schlimmer, nicht besser. Im Hellen ist
 * die Deckfläche deshalb ein dunkles Tuch aus `--fg`; erst dadurch entsteht
 * die Ebene, vor der das Papierweiß des Panels überhaupt eine Ebene ist.
 * Der genaue Wert (30–40 %) ist eine JD-Bildentscheidung, die Richtung nicht.
 */
.board-self-backdrop {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--bg);
  opacity: 0.72;
}

@media (prefers-color-scheme: light) {
  .board-self-backdrop {
    background: var(--fg);
    opacity: 0.35;
  }
}

/*
 * Das Panel gehört seinem AUSLÖSER, nicht dem Viewport (Review-Fund: gegen
 * den Viewport gerechnet landete es auf dem Desktop komplett neben der
 * Inhaltsspalte im leeren rechten Rand — es las als zugeflogener Toast statt
 * als das, was der Avatar geöffnet hat). Deshalb absolut IM Kopf verankert:
 * rechte Panelkante = rechte Kante der Inhaltsspalte, Oberkante unter dem
 * Kopf (24 = 16 Kopf→Regel + 8 Regel→Panel, die Regel bleibt frei).
 * Auf 390px deckt sich die Spaltenkante mit der Kartenkante — dieselbe
 * Flucht wie Karte und CTA.
 */
.board-header {
  position: relative;
}

.board-self-panel {
  position: absolute;
  z-index: 21;
  top: calc(100% + 1.5rem);
  right: 0;
  width: min(22rem, 100%);
  /* Lange Panels scrollen in sich, statt die Seite darunter zu bewegen. */
  max-height: calc(100svh - 8rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Kopf des Panels: Statuszeile (= sein Name) links, Schließen rechts. */
.board-self-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}

.board-self-head .board-hint {
  margin: 0;
  min-width: 0;
}

/*
 * „Schließen" bündig mit der ERSTEN Zeile der Statuszeile. `.board-quiet`
 * bringt `min-height: 2.75rem` (Touch-Ziel) und zentriert seinen Text darin —
 * bei zweizeiliger Statuszeile hing das Wort dadurch an deren zweiter Zeile.
 * Das Trefferfeld bleibt 44px, nur sein Inhalt sitzt oben.
 */
.board-self-head .board-quiet {
  flex: 0 0 auto;
  align-items: flex-start;
  margin-right: -0.25rem;
}

/* Aktionszeilen im Panel: leise Aktionen untereinander statt in einer Zeile —
 * im Panel ist Platz, und gestapelte Zeilen sind auf dem Handy die
 * verlässlichere Trefferfläche. */
.board-self-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.board-self-actions .board-quiet + .board-quiet {
  margin-left: 0;
}

/*
 * EINE Innenflucht im Panel. `.board-quiet` trägt `padding: 0 0.25rem` — in
 * der flachen Rand-Zeile nie aufgefallen, in der gestapelten Liste ergab es
 * drei verschiedene Textanfänge (Statuszeile 37 · Aktionen 44 · Aufklapper
 * 41). Das Polster bleibt (Trefferfeld), es wird nur nach links aus der
 * Flucht geschoben; das Aufklapp-Zeichen bekommt eine feste Kastenbreite,
 * damit die Seitenlage des „+" die Flucht nicht mehr verschiebt.
 */
.board-self-panel .board-self-actions,
.board-self-panel .board-actions {
  margin-left: -0.25rem;
}

.board-self-panel .board-manage-summary::before {
  display: inline-block;
  width: 0.75rem;
  margin-right: 0.25rem;
  text-align: left;
}

/*
 * Zweite Ebene „Dein Zugang" (§6): dasselbe Aufklapp-Muster wie „Verwalten" —
 * kein zweiter Bildschirm, kein Zurück-Weg, der verloren gehen kann. Drei Taps
 * bis „Runde verlassen": Avatar · Dein Zugang · Runde verlassen.
 */
.board-self-access {
  margin-top: 0.5rem;
  border-top: 1px solid var(--line);
  padding-top: 0.25rem;
}

.board-self-access-body {
  padding-top: 0.25rem;
}

/* Rechtes Kontext-Label der Kopfzeile („Tafel · heute"). */
.board-context {
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

/* Volle 1px-Regel unter der Kopfzeile: 16 Kopfzeile→Regel, 24 Regel→Titel. */
.board-rule {
  height: 0;
  margin: 1rem 0 1.5rem; /* 16 Kopfzeile→Regel, 24 Regel→Identitätskarte */
  border: none;
  border-top: 1px solid var(--line);
}

/* ===========================================================================
 * IDENTITÄTSKARTE — „Die Karte bleibt Abend"
 * (DESIGN-SPEC Nachtrag „App-Anmutung" §2, Konzept 3.14, Kap. 12 #19)
 * ---------------------------------------------------------------------------
 * Die Karte mischt ihren Akzent IMMER in die Nachtfläche (--card-deep), nie in
 * --surface. Das ERSETZT die Tönungsregel aus „Nachtrag Board v2". Grund:
 * `accent 16 %` auf Weiß ergibt zwangsläufig einen pastelligen Ton — jeder
 * helle Grund holt ihn zurück, solange die Karte so gebildet wird. Hell wie
 * dunkel trägt die Karte denselben Block; im hellen Modus ist sie damit der
 * kräftige Farbträger der Fläche.
 *
 * Die Gruppen-Tönung bleibt erhalten (vier Stufen IN die Nachtfläche) — sie
 * unterscheidet die Gruppen voneinander und trägt später die Chips.
 * =========================================================================== */

.board-identity {
  position: relative;
  width: 100%;
  /*
   * 120px ist die RUHEHÖHE, nicht die Deckelung (bildlos = Band statt
   * halbleeres Poster; ~180px gilt für die spätere Bild-Variante).
   *
   * `min-height` statt `height`, weil sonst vier Größen überbestimmt sind:
   * feste 120px · Kanaltitel-Rolle 21px · beidseitiges 16px-Polster · ein
   * Titel bis 60 Zeichen ohne Beschneidung. In die 120px passen bei 21px/1.2
   * genau drei Zeilen (107,6px); der Vollfall braucht vier. Mit fester Höhe
   * fraß `align-items: flex-end` dann das OBERE Polster auf — die Karte las
   * oben angeschlagen und unten gepolstert.
   *
   * Aufgelöst wird die Überbestimmung an der Höhe, nicht am Text: Beschneiden
   * würde der Karte den Namen der Gruppe nehmen (und zwar hinten, wo bei
   * „… e. V. Abt. Nord" das Unterscheidende steht), Verkleinern würde die
   * Kanaltitel-Rolle brechen. Das Wachstum ist eng begrenzt — vier Zeilen
   * sind der harte Anschlag (60 Zeichen / ~17 pro Zeile), also höchstens
   * 133px. Ein- und zweizeilige Titel, also der Alltag, ergeben exakt 120px.
   */
  min-height: 120px;
  margin: 0 0 0.5rem; /* 8 Karte → Meta */
  padding: 1rem;
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  color: var(--card-fg);
  box-shadow: var(--raise);
  /* Fallback für Engines ohne color-mix: die ungetönte Nachtfläche. */
  background: var(--card-deep);
  background: color-mix(in srgb, var(--card-accent) var(--identity-tint, 16%), var(--card-deep));
}

/*
 * Gruppen-Tönungsstufe + Kartenmotiv-Variante in EINER deterministischen
 * Klasse (Index = hash(channelPublicId) mod 4, board-logic.js
 * `identityTintIndex`; Server-Port in src/routes/web.ts). Als Klassen statt
 * Inline-style, weil die CSP kein style-Attribut erlaubt (style-src 'self').
 * board.js/new.js setzen dieselbe Klasse — ein Weg für alle drei Flächen
 * (Tafel, Teilen-Schritt, /c/:slug), damit eine Gruppe überall „ihre" Karte
 * hat. Die Stufen 10/16/22/28 % sind aus der Board-v2-Fassung übernommen,
 * gemischt wird jetzt aber in --card-deep statt in --surface.
 *
 * --art-rot/--art-scale drehen und skalieren den Ringzug um seinen (außerhalb
 * der Karte liegenden) Bogenmittelpunkt: eine Geometrie, vier Auszüge. Damit
 * ist die Kartengrafik deterministisch aus der Gruppen-ID, ohne dass Server
 * und Browser je eine zweite Zufallsquelle synchron halten müssten.
 */
.board-identity--tint-0 {
  --identity-tint: 10%;
  --art-rot: 0deg;
  --art-scale: 1;
}

.board-identity--tint-1 {
  --identity-tint: 16%;
  --art-rot: -13deg;
  --art-scale: 0.9;
}

.board-identity--tint-2 {
  --identity-tint: 22%;
  --art-rot: 10deg;
  --art-scale: 0.96;
}

.board-identity--tint-3 {
  --identity-tint: 28%;
  --art-rot: 23deg;
  --art-scale: 0.86;
}

/*
 * Kanaltitel auf der Karte (21px Bold): immer die Kreide-Farbe der Nachtfläche
 * (--card-fg), nie --fg — im hellen Modus wäre --fg auf der dunklen Karte
 * unlesbar. Unten links verankert, die Karte wächst nicht mit.
 *
 * Die Typo steht hier EXPLIZIT und nicht über das Heading-Level: die Karte ist
 * auf der Tafel und der Einladung ein `<h1>`, im Teilen-Schritt ein `<h2>` —
 * über `.page h1`/`.page h2` trug dieselbe Klasse damit zwei Schriftgrößen
 * (21px gegen 18px). Die Rolle „Kanaltitel" (DESIGN-SPEC §3: 21px Bold) hängt
 * an der Karte, nicht an der Dokumentgliederung. `.page`-Präfix nur wegen der
 * Spezifität von `.page h1` (0-1-1).
 *
 * `max-width: 65%` ist ein KONSTRUKTIONSMASS, kein Geschmackswert: der
 * Titelblock muss links des Bogenbandes der Kartengrafik enden (x ≥ 267 von
 * 400 = das rechte Kartendrittel, identity-art.eta). Bei 65 % endet er mobil
 * wie auf dem Desktop rund 13px davor. Wer den einen Wert ändert, ändert den
 * anderen mit. Die Höhe ist KEIN Gegenspieler mehr — die Karte wächst im
 * Vollfall mit (s. `min-height` oben), der Titel wird nie beschnitten.
 */
.page .board-channel-title {
  position: relative;
  z-index: 2;
  /*
   * Das Konstruktionsmaß gehört dem TITEL, nicht der Gruppe (Review-Fund:
   * an der Gruppe deckelte es auch die Unterschrift und zwang sie mobil in
   * einen Umbruch, den die Geometrie gar nicht verlangt — und der
   * Teilen-Schritt, dessen Karte gar keine Unterschrift hat, verlor sein Maß
   * ganz und lief unter das Bogenband). Der Titel ist der 21px-Block, der bei
   * langen Namen nach oben wächst; er muss links des Bandes enden.
   */
  max-width: 65%;
  margin: 0;
  color: var(--card-fg);
  font-size: 1.3125rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
 * Die fünf Kartenbehandlungen (§2)
 * ---------------------------------------------------------------------------
 * Vollfarbe · Bild mit Scrim · Ringzug · Farbfelder · Duoton. Sie sind eine
 * Wahl der GRUPPE, nicht des Designs. **Standard ist Ringzug** und in diesem
 * Paket fest verdrahtet (`board-identity--card-arcs` im Markup) — ohne Zutun
 * sieht nichts leer aus. Die übrigen vier stehen hier vorbereitet, sind aber
 * ohne den Kanal-Vertrag (`cardStyle`, PKG-ANMUT-VERTRAG) nicht erreichbar:
 * es gibt in diesem Paket bewusst KEINE Auswahl-UI.
 *
 * Die zwei bildgebundenen Behandlungen (Bild+Scrim, Duoton) warten auf
 * `--card-image`, das erst mit demselben Vertrag entsteht; ohne Bild fallen
 * sie sichtbar auf die getönte Nachtfläche zurück, brechen also nicht.
 * ------------------------------------------------------------------------- */

/* Grafik-Ebene (Ringzug/Farbfelder). Rein dekorativ (aria-hidden im Markup). */
.board-identity-art {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Beide Motiv-Gruppen liegen im selben SVG und werden von der Behandlung
 * freigeschaltet — genau eine ist je sichtbar, im Default der Ringzug. */
.board-identity-arcs,
.board-identity-fields {
  display: none;
}

/*
 * (1) Ringzug — angeschnittene Bögen aus der Ringfeld-Sprache.
 *
 * Zwei Gruppen, mit Absicht: die ÄUSSERE trägt das Clip-Band (rechtes
 * Kartenband, x ≥ 298 — es hält den Kanaltitel konstruktiv frei, siehe
 * partials/identity-art.eta), die INNERE dreht und skaliert. `clip-path` gilt
 * im Benutzerkoordinatensystem des eigenen Elements; läge es auf derselben
 * Gruppe wie die Transformation, würde das Band mitrotieren und die
 * Freihaltung wieder aufheben.
 */
.board-identity--card-arcs .board-identity-arcs {
  display: block;
}

.board-identity--card-arcs .board-identity-arcs-turn {
  transform-box: view-box;
  transform-origin: 470px -40px; /* der Bogenmittelpunkt, außerhalb der Karte */
  transform: rotate(var(--art-rot, 0deg)) scale(var(--art-scale, 1));
}

/* (2) Farbfelder — flache Komposition aus Kreis, Feld und Bogen. */
.board-identity--card-fields .board-identity-fields {
  display: block;
}

/* (3) Vollfarbe — eine Fläche in der theme-festen Kartenfarbe. Bewusst
 * --card-accent (nicht --accent): die Karte gehört zur Abend-Ebene und sieht
 * in beiden Modi gleich aus. */
.board-identity--card-solid {
  background: var(--card-accent);
  color: var(--accent-fg);
}

.page .board-identity--card-solid .board-channel-title {
  color: var(--accent-fg);
}

/* (4) Bild mit Scrim (§5.2) und (5) Duoton teilen sich die Bild-Ebene. */
.board-identity--card-photo::before,
.board-identity--card-duo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--card-image, none);
  background-size: cover;
  background-position: center;
}

/* Bild mit Scrim: unten voll in die Grund-Nacht auslaufend, bis ~60 %
 * Kartenhöhe. Der Scrim ist die eine erlaubte Verlaufs-Ausnahme (§7). */
.board-identity--card-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    180deg,
    rgb(var(--card-scrim) / 0%) 32%,
    rgb(var(--card-scrim) / 86%) 100%
  );
}

/* Duoton: das Gruppenbild über die Rampe Nachtfläche → Akzent gezogen, damit
 * es zu jeder Farbwelt passt und beim Wechsel mitgeht. */
.board-identity--card-duo::before {
  filter: grayscale(1) contrast(1.1);
}

.board-identity--card-duo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--card-accent);
  mix-blend-mode: color;
}

/*
 * Kanal-Meta als UNTERSCHRIFT ihrer Karte (Nachtrag „App-Anmutung" §1: „Kein
 * Kleintext steht frei auf dem Grund", Meta wird Unterschrift ihrer Karte —
 * ein Baustein, eine Kante). Vorher lag die Zeile als 11px-Versalien-Text
 * frei auf `--bg` unter der Karte; jetzt teilt sie Fläche, linke Flucht und
 * Kante mit dem Titel. Labels-Rolle (§3) in der Kreide-Nebenfarbe der
 * Nachtfläche — `--muted` wäre auf der dunklen Karte falsch.
 */
.board-identity-caption {
  position: relative;
  z-index: 2;
  /*
   * Die Gruppe selbst trägt KEIN Maß — sie spannt die Kartenfläche auf, damit
   * die Prozentmaße von Titel und Unterschrift beide gegen die Karte rechnen
   * (und nicht gegeneinander: eine max-width hier hätte die 65 % des Titels
   * auf 65 % DIESER Gruppe zusammengezogen).
   */
  width: 100%;
}

.board-channel-meta {
  margin: 0.25rem 0 0; /* 4 Titel → Unterschrift, innerhalb der Karte */
  /*
   * EIGENES Maß, nicht das des Titels (Review-Fund MAJOR-5): die Unterschrift
   * ist eine 11px-Zeile am unteren Kartenrand, kein wachsender Block, und darf
   * näher an das Bogenband heran als der Titel.
   *
   * 68 % ist gemessen, nicht geschätzt. Das Band liegt bei viewBox x = 267/400
   * und wandert mit der `slice`-Skalierung, also mit dem SEITENVERHÄLTNIS der
   * Karte. Auf der Ruhehöhe (120px) gemessen:
   *   390er-Viewport  Karte 326×120 → Bandkante bei 69,5 % der Innenbreite
   *   Desktop         Karte 448×120 → Bandkante bei 68,0 %  ← das Minimum
   * 68 % ist damit der Wert, der in JEDER Breite links des Bandes endet; bei
   * höheren Karten (langer Titel) wächst der Abstand.
   *
   * Damit steht die Unterschrift auf dem Desktop einzeilig. Auf 390px braucht
   * „Ab 2 steht die Runde · bis 05:00" 203,4px und hat bis zur Bandkante
   * 204,4px — die Zeile passt dort also nur mit unter 1px Luft. Das ist keine
   * Konstruktion, sondern ein Zufall, und wird nicht als solche gebaut: sie
   * bricht auf 390px am „·", und die geschützten Leerzeichen in texts.de.ts
   * halten dabei „Ab 2", „max. 2 Plätze" und „bis 05:00" jeweils zusammen.
   */
  max-width: 68%;
  color: var(--card-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Auf dem Vollfarbe-Kartenstil trägt die Unterschrift die Gegenfarbe mit. */
.board-identity--card-solid .board-channel-meta {
  color: var(--accent-fg);
}

/* Der Rhythmus, den die Meta-Zeile bisher nach unten aufgespannt hat, hängt
 * jetzt an der Karte selbst: 24 Karte → Ringfeld. */
.board-identity {
  margin-bottom: 1.5rem;
}

.board-live {
  text-align: center;
}

/*
 * Labels-Rolle (§3: 11px Versalien, +6% Sperrung) für die stillen
 * Sektionslabels der Rand-Zone (NOTIZ, EINLADUNG, MAX. PLÄTZE) und den
 * Verwalten-Aufklapper. Der Quelltext bleibt normal geschrieben, die
 * Versalisierung macht das CSS (wie bei .member-tag/.account-membership-badge).
 */
.board-label {
  margin: 0;
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/*
 * „Leise Aktion" — die 3. Button-Stufe (§5.6.2): 13px Semibold `--fg`, keine
 * Fläche, kein Rand, KEIN `--accent`. `min-height:44px` als Touch-Ziel. Für
 * ALLE Rand-Aktionen (Kopieren/Teilen/Speichern/Entfernen/Verstanden/Konto
 * einrichten). Der gefüllte Orange-CTA + der `--line`-Sekundär bleiben allein
 * der Bühne. Überschreibt die generische `button`-Skin (--fg auf --bg).
 */
.board-quiet {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 0.25rem;
  background: none;
  border: none;
  border-radius: 0;
  color: var(--fg);
  font-size: 0.8125rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.board-quiet + .board-quiet {
  margin-left: 0.5rem;
}

/*
 * App-Hinweis am Zusage-Moment (PKG-HINT-MOMENT, Konzept 3.12): unter dem
 * CTA, ohne Trennlinie. Nutzt die .board-hint-Stimme; erscheint direkt
 * nach der eigenen Browser-Zusage und bleibt — wie der Konto-Moment — über
 * Reloads sichtbar, bis er aktiv weggeklickt wird. 16px unter dem CTA.
 *
 * Layout als bewusstes Zwei-Zeilen-Gefüge statt des generischen
 * .board-hint-Flex-Umbruchs: Zeile 1 Aufmacher („Sag ich dir Bescheid …"),
 * Zeile 2 der leisere Lockscreen-Nachsatz, das Wegklick-× oben rechts am
 * Block (align-start). Ohne dieses Grid bräche das × auf 390px als
 * verwaister Einzelknopf in eine dritte Zeile um. Compound-Selektor, damit
 * die Regel das später definierte .board-hint-Flex sicher überstimmt.
 */
/*
 * Rand-Botschaften in KACHELFORM (Nachtrag „App-Anmutung": „Die Botschaften
 * bekommen die Kachelform der Identitätskarte statt nackter Textzeilen").
 * Sie tragen im Markup `.block .block--raised` — dieselbe angehobene Fläche
 * mit Radius 12, weichem Schatten und (hell) Haarlinie wie jeder andere
 * Baustein. Nackte Textzeilen im Rand waren der Rest der Dokument-Anatomie.
 *
 * An der LOGIK ändert das nichts: es bleibt bei der Verdrängungs-Sequenz
 * (eine aktive Botschaft, Sicherung vor App-Hinweis, Nachrücken erst beim
 * nächsten Render-Anlass). Ein späterer Stapel bekäme genau diese Kacheln
 * gestapelt — deshalb sitzt die Form an der Botschaft, nicht am Rand-Container.
 */
/*
 * EIN Kachel-Raster für BEIDE Rand-Botschaften (Review-Fund: zwei Kacheln,
 * zwei Orte fürs Wegklicken — das × des App-Hinweises saß oben rechts an der
 * Kachelkante, das des Konto-Moments inline hinter „Konto einrichten" mit
 * 300px Leere dahinter; auf dem Desktop las es als drittes Bedienelement
 * statt als Schließen). Jetzt: Text und Aktion in Spalte 1 untereinander,
 * das × in Spalte 2 oben rechts. Beide Kacheln klickt man an derselben
 * Stelle weg.
 */
.board-hint.board-app-hint,
.board-hint.board-account-moment {
  margin-top: 1rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 0.75rem; /* 12, wie das .board-hint-Spalten-Gap */
  row-gap: 0.25rem; /* 4, wie das .board-hint-Zeilen-Gap */
}

.board-hint.board-app-hint > span,
.board-hint.board-account-moment > span,
.board-hint.board-account-moment > a {
  grid-column: 1;
  /* Als Rasterzelle würde die leise Aktion sonst auf Spaltenbreite gedehnt
   * (und ihre Unterstreichung mit ihr); links bündig mit dem Text darüber. */
  justify-self: start;
  margin-left: -0.25rem;
}

.board-hint.board-app-hint > button,
.board-hint.board-account-moment > button {
  grid-column: 2;
  grid-row: 1;
  align-self: start;
  justify-self: end;
  margin-right: -0.25rem; /* das .board-quiet-Polster aus der Kachelflucht */
}

/*
 * Rand-Zone (Iteration 3): NUR der Verwalten-Aufklapper (Ersteller). Beginnt
 * 32px nach dem CTA (bzw. App-Hinweis) mit der ersten `--line`-Linie (border-top
 * des ersten sichtbaren Kindes) — nur, wenn es etwas gibt: `hidden` Kinder
 * (display:none) tragen keine Linie, ein Mitglied ohne Verwalten endet nach dem
 * CTA still. `padding-top` statt `margin-top` vermeidet Margin-Collapse.
 */
.board-rand {
  padding-top: 2rem; /* 32 CTA → Rand, die eine Zäsur */
  text-align: left;
}

.board-rand > * {
  margin: 0;
  padding: 1rem 0; /* 16 ober-/unterhalb der Trennlinie */
  border-top: 1px solid var(--line);
}

/* Ringfeld (§4/§5): das Signatur-Zentrum. SVG ist aria-hidden — der Zustand
 * lebt lesbar in der Stand-Zeile darunter. 24 Meta→Ringfeld kommt aus
 * .board-channel-meta, 8 Ringfeld→Stand aus dem margin-bottom hier (Hero: 12,
 * über den margin-top von .board-stand--empty). */
.board-ringfield {
  margin: 0 auto 0.5rem; /* 8 Ringfeld → Stand */
  line-height: 0;
}

.board-ringfield .rf {
  width: 11.875rem;
  height: 11.875rem;
  max-width: 100%;
}

.board-ringfield .rf-k {
  font-family: var(--font-sans);
  font-weight: 800;
}

/* Stand-Zeile (§4, hart barrierefrei) — trägt „3/4 — einer fehlt noch".
 * Aktiv/voll/Match: 18px Bold, tabular-nums; 8 Ringfeld→Stand (aus dem
 * ringfield-margin), 16 Stand→Mitglieder. */
.board-stand {
  font-size: 1.125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin: 0 0 1rem;
  /*
   * Die Stand-Zeile trägt den Akzent als TEXT, also die Ink-Stufe (Nachtrag
   * „App-Anmutung" §3; im dunklen Modus fällt sie mit der Neonstufe zusammen).
   * Sie und die Hero-Frage teilen sich ein Element — deshalb setzen die zwei
   * Zustandsklassen unten die Farbe zurück bzw. weiter: `--empty` ist die
   * Hero-Frage und bleibt Kreide mit EINEM Akzentwort, `--match` gewinnt
   * ohnehin. Das ist die Entflechtung, die PKG-ANMUT-TOKENS hierher verwiesen
   * hat; beide Klassen stehen NACH dieser Regel und schlagen sie.
   */
  color: var(--accent-ink);
}

/* Hero-Frage im Leerzustand (§5.6+): 28px ExtraBold, line-height 1.15, --fg,
 * ausbalanciert auf ~16ch, zentriert auf der Ringfeld-Achse. 12 Ringfeld→Hero
 * (margin-top, kollabiert mit dem 8er-ringfield-margin zu max=12), 32 Hero→
 * Notiz (die leere Mitgliederliste trägt dann keinen Abstand, s. :empty). */
.board-stand--empty {
  color: var(--fg);
  max-width: 16ch;
  margin: 0.75rem auto 2rem;
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.15;
  text-wrap: balance;
}

/* Das eine Accent-Wort der Hero-Frage (§5.6+, „Bock?" → zeigt auf den CTA).
 * TEXT, also die Ink-Stufe — die Neonstufe gehört Flächen und Grafik
 * (Nachtrag „App-Anmutung" §3). Im dunklen Modus sind beide identisch. */
.board-hero-accent {
  color: var(--accent-ink);
}

/*
 * Match-Zustand (§5.5/§5.6.8): die Stand-Zeile färbt auf `--match` („Text in
 * --match", wörtlich). Das frühere `--surface`-Banner ist aufgelöst — grün
 * bleibt match-only, nie Deko, und der Zustand steht ohnehin lesbar in dieser
 * Zeile (aria-live) statt doppelt in einem Banner.
 */
.board-stand--match {
  color: var(--match);
}

/*
 * Visually-hidden helper: hält ein Element im Accessibility-Tree, aber aus dem
 * Bild. Trägt heute die stillen `h1` der Seiten, deren sichtbare Überschrift
 * anders gesetzt ist (/new, /account, /account/login, Teilen-Schritt). Der
 * inerte Match-Banner-Träger, der das früher ebenfalls nutzte, ist am
 * 29.07.2026 entfernt worden (PKG-BACKLOG-3, siehe board.eta).
 */
.board-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Mitglieder (§5.3): flache Zeilen, dünne --line-Trennlinien, KEINE
 * umrandeten Karten. Avatar-Kreis 26px, Name Semibold, Notiz --muted. */
.board-members {
  list-style: none;
  margin: 0 0 1.5rem; /* 24 Mitglieder → Notiz-Label */
  padding: 0;
  text-align: left;
}

/* Leere Mitgliederliste erzeugt KEINEN Zusatzabstand (§5.6+): im Leerzustand
 * kommt der Abstand zur Notiz allein aus der Hero-Frage (--empty). */
.board-members:empty {
  margin: 0;
}

/*
 * Fünf Elemente teilen sich die Zeile: Avatar · Name · Notiz · Nachrücker-Tag
 * · „seit"-Zeit. Als Flex-Umbruch (Bestand) waren sie gleichrangig — bei
 * langem Namen plus Notiz rutschte die Zeit bündig links unter den Avatar,
 * ohne Einzug, und die optischen Gewichte kippten. §1 verlangt definierte
 * Ausrichtung und vorhersehbares Verhalten, geprüft mit LANGEN Namen.
 *
 * Deshalb ein Raster mit KÜRZUNGSSTRATEGIE statt Kompression:
 *   Zeile 1  Avatar | Name (kürzt mit Auslassung) | Tag | Zeit (rechts)
 *   Zeile 2  Notiz, eingerückt in die Namensspalte
 * Der Name gibt als einziges nach — Tag und Zeit sind kurz, gesetzt und
 * dürfen nie umbrechen. Existiert keine Notiz, entsteht Zeile 2 gar nicht.
 */
.board-members li {
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--line);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  column-gap: 0.5rem;
  row-gap: 0.125rem;
  align-items: center;
}

.board-members li:last-child {
  border-bottom: none;
}

.member-avatar {
  grid-column: 1;
  grid-row: 1;
  flex: 0 0 auto;
  width: 1.625rem;
  height: 1.625rem;
  border-radius: 50%;
  /*
   * Kreis-Farbe = --accent in einer deterministischen Stufe (--avatar-mix,
   * gesetzt von board.js aus der Member-publicId). Fallback voll --accent für
   * Engines ohne color-mix. Die Initiale bleibt voll --accent-fg.
   *
   * PKG-ANMUT-TOKENS-Korrektur: gemischt wird gegen --avatar-base (hell:
   * Papierweiß, dunkel: Kreide) statt gegen `transparent`. Der alte Weg ließ
   * den Kreis im DUNKLEN Modus mit sinkender Deckkraft in den Grund absaufen —
   * die Initiale kam auf den unteren Stufen nur noch auf 2,3:1 und brach die
   * AA-Zusage (Bestandsfehler, mit den alten Tokens genauso). Gegen eine helle
   * Basis wird die Stufe heller statt dunkler: die dunkle Initiale trägt auf
   * JEDER Stufe (≥ 7,4:1) und der Kreis hebt sich auch unten noch vom Grund ab.
   */
  background: var(--accent);
  background: color-mix(in srgb, var(--accent) var(--avatar-mix, 100%), var(--avatar-base));
  color: var(--accent-fg);
  font-size: 0.75rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Der Name ist das einzige Element, das nachgibt — eine Zeile, Auslassung
 * statt Umbruch. `min-width: 0` ist Pflicht, sonst wächst die Rasterspalte
 * über ihren Anteil hinaus und schiebt die Zeit aus der Zeile. */
.member-name {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-weight: 600;
}

.member-since {
  grid-column: 4;
  grid-row: 1;
  justify-self: end;
  white-space: nowrap;
}

/* Die Notiz bekommt ihre eigene Zeile, eingerückt in die Namensspalte —
 * eigene wie fremde. Sie darf umbrechen, sie hat die Breite dafür. */
.member-note,
.member-note-slot {
  grid-column: 2 / -1;
  grid-row: 2;
  min-width: 0;
}

.member-note,
.member-since {
  color: var(--muted);
  font-size: 0.8125rem;
}

/* Nachrücker-Marker (§5.5: „voll · N Nachrücker"). Labels-Rolle (§3). Fehlt
 * er, fällt die Rasterspalte auf 0 zusammen — kein Loch in der Zeile. */
.member-tag {
  grid-column: 3;
  grid-row: 1;
  white-space: nowrap;
  color: var(--muted);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.member--waitlisted .member-name {
  color: var(--muted);
}

/*
 * Notiz an der eigenen Mitgliederzeile (Iteration 3, additiv zur §5.3-Zeile):
 * der eigene Notiz-Slot trägt eine stille „+ Notiz"-Affordanz bzw. die eigene
 * Notiz als antippbaren Text — beides leise (13px --muted), kompakt (die
 * board-quiet-Touch-Höhe würde die Zeile aufblähen, hier bewusst zurückgenommen).
 * Tap öffnet einen Inline-Input an Ort und Stelle.
 */
.member-note-slot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.375rem;
}

/*
 * PKG-VIS (Livetest-Befund 20.07., JD): die frühere rein textliche Affordanz
 * war stimmlich IDENTISCH mit den passiven Meta-Texten der Zeile („seit …",
 * fremde Notizen) — ein Testnutzer hat die Funktion nicht gefunden. Fix über
 * Affordanz statt Lautstärke: der eigene Notiz-Slot trägt jetzt den RAHMEN
 * des Inline-Inputs, in den er sich beim Tap verwandelt (§5.6.1 „Inputs
 * behalten Rahmen (Affordanz)" — der Slot IST ein kollabiertes Eingabefeld).
 * Stimme bleibt leise (13px --muted wie zuvor); fremde Notizen bleiben
 * rahmenlos — eigen/antippbar vs. fremd/passiv ist damit unterscheidbar.
 */
.member-note-add,
.member-note-edit {
  min-height: 1.75rem;
  padding: 0.0625rem 0.5rem;
  border: 1px solid var(--line-control);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 400;
  text-align: left;
}

.member-note-add:hover,
.member-note-edit:hover {
  border-color: var(--muted);
}

.member-note-input {
  font: inherit;
  font-size: 1rem; /* 16px — iOS-Zoom-Schutz */
  max-width: 12rem;
  padding: 0.125rem 0.375rem;
  border: 1px solid var(--line-control);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--fg);
}

.member-note-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.member-note-counter {
  color: var(--muted);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
}

/*
 * CTA (§5.4): volle Breite, flach --accent, Radius 8px, 56px, --accent-fg
 * Bold. Genau EIN Primär-CTA; nach eigenem Check-in Sekundär-Stil
 * (transparent, --line-Rand) fürs Zurückziehen.
 */
/*
 * Auch als <a> genutzt (Trichter-Nachtrag: Startseite-CTA „Runde anlegen"
 * → /new, PK.4-Serie auf allen Trichter-Seiten) — text-align/text-decoration/
 * cursor sind No-Ops auf <button>, machen den Link aber CTA-artig statt wie
 * einen Systemlink (unterstrichen, linksbündig).
 */
.board-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 3.5rem;
  padding: 0.875rem 1.25rem;
  /* Bausteinradius (§1): der CTA ist eine Fläche der Bühne, kein Textfeld. */
  border-radius: var(--radius);
  font-size: 1rem;
  font-weight: 700;
  border: 1px solid transparent;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: transform 80ms ease-out;
  box-sizing: border-box;
}

.board-cta + .board-cta {
  margin-left: 0;
}

.board-cta--primary {
  background: var(--accent);
  color: var(--accent-fg);
}

/*
 * Der Sekundär-CTA trägt KEINE Fläche — sein Umriss ist das einzige, was ihn
 * als Bedienelement ausweist, und damit ein Fall für `--line-control`
 * (WCAG 1.4.11, PKG-BACKLOG-2 Runde 1).
 *
 * Die erste Fassung hatte ihn ausgenommen mit der Begründung „steht neben
 * einem gefüllten Primär-CTA und wird über das Paar erkannt". Die Annahme
 * trägt an drei von sechs Aufrufstellen nicht: „Zurückziehen" und „Bin dabei"
 * schließen einander aus (board.js setzt sie gegenläufig auf `hidden`) — im
 * eingecheckten Zustand steht der Knopf ALLEIN auf der Fläche; die beiden
 * Knöpfe des „Bist das du?"-Panels (/c/:slug) und „Nein, jemand anderes"
 * (/discord/link) stehen ganz ohne Primär-CTA, weil das Formular mit dem
 * Submit-Knopf dabei ausgeblendet ist.
 */
.board-cta--secondary {
  background: transparent;
  color: var(--fg);
  border-color: var(--line-control);
}

.board-cta:active {
  transform: scale(0.97);
}

/*
 * „Stand teilen" (PKG-SHARE-STATUS, Konzept 3.12 / Kap. 6.5): leise Aktion
 * (§5.6.2) direkt unter dem CTA-Paar, zentriert — die Bühne endet weiter mit
 * dem CTA als lautestem Element, diese Zeile ist ihre stille dritte Stufe.
 * Schrift/Touch-Ziel (13px Semibold, 44px) kommen aus .board-quiet; hier nur
 * Block-Zentrierung + 8px-Zäsur (Abstands-Skala). Kein Rand, keine Fläche.
 */
.board-share-stand {
  display: flex;
  width: max-content;
  margin: 0.5rem auto 0;
}

/*
 * Flache Hinweis-Zeile: rahmenlos, Text 13px `--muted` linksbündig, Aktionen
 * dahinter (umbrechend) als leise Aktionen/Links. KEINE `--surface`-Box, kein
 * `--line`-Rahmen. Genutzt vom App-Hinweis unter dem CTA und vom
 * Ersteller-Sicherungshinweis auf dem Teilen-Schritt (share-securing).
 */
.board-hint {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem; /* 4/12 */
  color: var(--muted);
  font-size: 0.8125rem;
}

/*
 * Eigene Identitäts-Zeile im Rand (PKG-RENAME): Container-DIV als Rand-Kind
 * (border-top/padding kommen aus .board-rand > *), innen die .board-hint-
 * Stimme plus die zwei aufklappbaren Selbst-Flows. Die inneren Absätze
 * verlieren ihre UA-Margen — der 16er-Rhythmus des Rands bleibt.
 */
.board-self .board-hint {
  margin: 0;
}

/* In der Statuszeile trennt schon das .board-hint-Gap — das generische
 * Nachbar-Margin der leisen Aktionen würde beim Umbruch auf 360px einen
 * schiefen Zusatz-Einzug erzeugen. Die .board-actions-Paare (Speichern/
 * Abbrechen, Ja, verlassen/Abbrechen) behalten das Bestandsmargin. */
.board-self .board-hint .board-quiet + .board-quiet {
  margin-left: 0;
}

/* Inline-Editor fürs Selbst-Umbenennen: Rahmen-Input (Titel-Skin) + leise
 * Aktionen dahinter, bei 360px umbrechend. 8px unter der Statuszeile. */
.board-self-edit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem; /* 4/8 */
  margin-top: 0.5rem;
}

/* Gerät hinzufügen (Konzept 3.7, Kap. 12 #11): Aufklapp-Panel in der
 * Selbst-Zeile, 8px unter der Statuszeile — gleicher Rhythmus wie der
 * Rename-Editor. */
.board-self-device-add {
  margin-top: 0.5rem;
}

/* Der erzeugte Code groß + lesbar (Archivo), weit gesperrt, auswählbar. Die
 * Gruppierung „47Q K2M" macht board.js; hier nur Typo + Abstand. */
.board-device-code {
  margin: 0.25rem 0;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.75rem;
  letter-spacing: 0.18em;
  font-variant-numeric: tabular-nums;
  user-select: all;
}

/*
 * Code-EINGABEFELD (PKG-CODE-INPUT, JD-Gerätefund): das Feld übernimmt die
 * Stimme der Code-ANZEIGE (.board-device-code), damit Tippen und Anzeige
 * zusammenpassen — Archivo, groß, gesperrt, zentriert; `text-transform:
 * uppercase` stellt die Eingabe live versal dar, OHNE den .value zu verändern
 * (Normalisierung passiert beim Senden/serverseitig, kein Cursor-Sprung). Der
 * `.field`-Rahmen/Hintergrund bleibt (Titel-Input-Skin); nur Typo überschrieben.
 * Gewinnt per SPEZIFITÄT (zusätzliche Klasse gegenüber `.field
 * input[type="text"]`), nicht per Quellposition — umsortieren ist safe.
 * Identisch auf /c/:slug und /discord-link.
 */
.field input[type="text"].board-device-code-input {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.5rem;
  letter-spacing: 0.15em;
  text-align: center;
  text-transform: uppercase;
  /* Ziffernbreiten-Parität zur Code-Anzeige (.board-device-code). */
  font-variant-numeric: tabular-nums;
  padding: 0.5rem 0.5rem;
}

/* Platzhalter „ABR PPZ" in der gedimmten Stimme (erbt uppercase vom Feld). */
.board-device-code-input::placeholder {
  color: var(--muted);
  font-weight: 400;
  letter-spacing: 0.15em;
}

/*
 * Einladungs-Baustein des Teilen-Schritts: der Baustein trägt das Polster,
 * seine Kinder verlieren ihr Außenmaß an den Kanten (Feld oben, Nachsatz
 * unten) — sonst summierten sich Blockpolster und Bestandsmargen.
 */
.share-invite > .field:first-child {
  margin-bottom: 0.75rem;
}

.share-invite > .share-actions:last-child,
.share-invite > .hint:last-child {
  margin-bottom: 0;
}

/*
 * Ersteller-Sicherungshinweis auf dem Teilen-Schritt (Iteration 3), seit
 * PKG-ANMUT-WEB in Kachelform. Die leise Aktion bekommt eine eigene Zeile
 * unter dem Text und dieselbe linke Flucht wie er (das `.board-quiet`-Polster
 * aus der Kachelflucht schieben) — im Fließ-Umbruch stand sie sonst mal
 * hinter, mal unter dem Text.
 */
.share-securing {
  margin-top: 1rem;
}

.share-securing.block > span {
  flex: 1 0 100%;
}

.share-securing.block > .board-quiet {
  margin-left: -0.25rem;
}

/*
 * Verwalten-Aufklapper (§5.6.9): Teilen + Kapazität hinter EINER leisen
 * „Verwalten"-Zeile (`<details>`/`<summary>`). Text-„+/−" statt Icon-Set.
 * Zugeklappt ist die Ersteller-Tafel bis auf diese Zeile identisch mit der
 * Mitglieder-Tafel.
 */
.board-manage-summary {
  display: flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
  list-style: none;
}

.board-manage-summary::-webkit-details-marker {
  display: none;
}

.board-manage-summary::before {
  content: "+";
  margin-right: 0.5rem;
  font-size: 0.875rem;
}

/* Das Aufklapp-Zeichen gehört dem Muster, nicht einer einzelnen Fläche —
 * „Verwalten" und „Dein Zugang" (Selbst-Panel, §6) teilen es sich. */
details[open] > .board-manage-summary::before {
  content: "\2212"; /* Minuszeichen − */
}

.board-manage-body {
  padding-top: 0.5rem;
}

/* ---------------------------------------------------------------------------
 * Verwalten in BAUSTEINEN (§1, Review-Fund MAJOR-1)
 * ---------------------------------------------------------------------------
 * Der Verwalten-Bereich war die größte verbliebene Fläche mit losem Kleintext
 * auf `--bg` — Labels, Einladungs-URL, Zähltag-Zeile und Mitglieder-Unterzeilen
 * frei zwischen `--line`-Strichen. Jede benannte Gruppe ist jetzt ein Baustein
 * (`.block.block--raised` im Markup), ihr Label die Kopfzeile (`.block-head`).
 * Hier stehen nur noch die Regeln, die aus dem BAUSTEIN-Kontext folgen; die
 * Fläche selbst kommt unverändert aus der Utility.
 * ------------------------------------------------------------------------- */

/* Erstes Kind eines Bausteins beginnt bündig — das 16er-Margin von
 * `.board-setting` gilt ZWISCHEN Einstellzeilen, nicht an der Blockkante. */
.board-manage-block > .board-setting:first-child,
.board-manage-block > .block-head + .board-setting {
  margin-top: 0;
}

/*
 * Labelspalte der Einstellungen (Review-Fund MINOR-4: drei Eingabezeilen,
 * drei Feldanfänge — Titel bei 462, Ab bei 443, Max. Plätze bei 505). Ein
 * Raster mit fester Labelspalte gibt allen Zeilen EINEN Feldanfang; die
 * Steuerelemente einer Zeile stehen in `.board-setting-control` zusammen und
 * dürfen dort untereinander umbrechen (Speichern/Entfernen, Fehlerzeile),
 * ohne die Flucht zu verlassen.
 */
.board-manage-block--fields .board-setting--inline {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  align-items: center;
  column-gap: 0.75rem;
  row-gap: 0.5rem;
}

.board-setting-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  min-width: 0;
}

/* Die Fehlerzeile gehört unter ihr Feld, nicht daneben. */
.board-setting-control > .board-error-line {
  flex: 1 0 100%;
  margin: 0;
}

/*
 * Kanal löschen: die leise SCHLUSSZEILE unter dem Baustein-Stapel, ohne
 * eigene Fläche (Review-Fund MINOR-7 — Begründung im Markup). Sie flieht wie
 * der „Verwalten"-Aufklapper an der Spaltenkante, nicht an der Innenkante der
 * Bausteine: das `.board-quiet`-Polster wird aus der Flucht geschoben.
 */
.board-delete > .board-quiet {
  margin-left: -0.25rem;
}

/* Naht zum späteren Theme-Paket (§5.2): stiller Baustein mit dem aktuellen
 * Tönungs-Swatch in der Kopfzeile, kein Interaktionsversprechen. */
.board-look .block-head {
  justify-content: flex-start;
  align-items: center;
  gap: 0 0.5rem;
}

.board-look .board-look-note {
  margin: 0;
}

.board-look-swatch {
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  border-radius: 0.25rem;
  /* Spiegelt exakt die Karte (Nachtfläche + Gruppen-Tönung), damit der
   * Swatch zeigt, was oben steht — nicht eine zweite Wahrheit. */
  background: var(--card-deep);
  background: color-mix(in srgb, var(--card-accent) var(--identity-tint, 16%), var(--card-deep));
}

.board-look-note {
  color: var(--muted);
  font-size: 0.8125rem;
}

/* Einstellzeile (§5.6.5/§5.6.6): Label · Wert/Aktionen, kein Formular, keine
 * Karte. 12 Label→Feld im Sinn-Paar. */
.board-setting {
  margin-top: 1rem; /* 16 zwischen den Einstellzeilen */
}

.board-setting:first-child {
  margin-top: 0;
}

.board-setting--inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem; /* 8/12 */
}

.board-admin-members {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
}

.board-admin-member {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.25rem 0.75rem;
  align-items: center;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--line);
}

.board-admin-member:last-child {
  border-bottom: none;
}

/* Wie in `.board-members li`: der Name gibt als einziges nach. */
.board-admin-member-name {
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-weight: 600;
}

/*
 * Die Unterzeile läuft über die VOLLE Breite (Review-Fund MINOR-8: ohne
 * eigene Platzierung fiel sie in Zeile 2 Spalte 1 — also in die vom
 * „Entfernen"-Knopf verengte Spalte, und brach dort auf zwei Zeilen, während
 * die Nachbarzeile ohne Aktion einzeilig blieb. Zwei Höhen, die kein Inhalt
 * erklärt). Dieselbe Lösung wie `.member-note` auf der Tafel: die Aktion
 * belegt nur Zeile 1, die Unterzeile spannt darunter durch.
 */
.board-admin-member-activity {
  grid-column: 1 / -1;
  grid-row: 2;
  color: var(--muted);
  font-size: 0.8125rem;
}

/*
 * „Entfernen" auf Höhe des NAMENS, nicht über beide Zeilen zentriert
 * (Review-Fund: über `grid-row: 1 / span 2` landete es optisch an der
 * Unterzeile und kippte damit genau die Gewichtung, die die Tafel-Zeile
 * gerade repariert hat). Dasselbe Raster wie `.member-since` dort: Zeile 1,
 * rechts.
 */
.board-admin-member-action {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
}

.board-admin-member-confirm {
  grid-column: 1 / -1;
  margin-top: 0.25rem;
}

.board-admin-member-confirm p {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 600;
}

/* Einladungs-URL (§5.6.5): einzeilig gekürzt als 13px `--muted`-Text, KEIN
 * Input-Feld, kein Rahmen — die URL bleibt sichtbar (D18-Re-Anzeige). */
.board-share-url {
  margin: 0.5rem 0; /* 8 Label→URL / URL→Aktionen */
  color: var(--muted);
  font-size: 0.8125rem;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/*
 * W5.1: 3-Schritt-Anleitung im Discord-Code-Panel — ruhige nummerierte Liste,
 * 13px, Ziffern in --muted. Schritt 3 trägt Kommando (.board-share-url) und
 * Rechte-Hinweis (.board-look-note) als eigene Zeilen mit kleinem Abstand.
 */
.board-discord-steps {
  margin: 0.5rem 0 0.75rem;
  padding-left: 1.25rem;
  display: grid;
  gap: 0.5rem;
  font-size: 0.8125rem;
}

.board-discord-steps li {
  /* Grid-Items schrumpfen sonst nicht unter die nowrap-Kommandozeile
   * (.board-share-url) — min-width:0 hält die Liste in der Spaltenbreite,
   * die Kommandozeile kürzt per ellipsis statt die Nachbarn zu clippen. */
  min-width: 0;
}

.board-discord-steps li::marker {
  color: var(--muted);
}

/* Der Invite-Link ist Schritt 1 selbst: als Inline-Link in der Zeile, nicht
 * als 44px-Aktionsblock (der würde den Listen-Marker aus der Flucht drücken).
 * Bewusst nur <a> (W5.2): der Kopieren-Button in Schritt 3 behält die normale
 * .board-quiet-Affordanz — er steht unter der Kommandozeile, nicht in der
 * Marker-Zeile. */
.board-discord-steps a.board-quiet {
  display: inline;
  min-height: 0;
  padding: 0;
}

.board-discord-steps .board-share-url,
.board-discord-steps .board-look-note {
  margin: 0.25rem 0 0;
}

.board-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

/* Kompaktes Kapazitäts-Input (§5.6.6): ~4,5rem, rechtsbündig, tabular-nums.
 * Behält seinen Rahmen (Affordanz, §5.6.1). Steht nicht in einer `.field`,
 * darum die vollständige Input-Skin hier. */
/*
 * 6rem statt 4.5rem (PKG-ANMUT-WEB): der Platzhalter „unbegrenzt" wurde im
 * 4,5rem-Feld auf „unbegre…" abgeschnitten, mobil wie auf dem Desktop — ein
 * Wort, das die wichtigste Voreinstellung dieser Zeile benennt. Der Text
 * bleibt unangetastet, das Feld bekommt das Maß, das er braucht; zusätzlich
 * trägt der Platzhalter (und nur er) die 14px-Stufe. Zahlen stehen weiter
 * rechtsbündig mit tabular-nums, die Zeile bleibt kompakt.
 */
.board-capacity-input {
  width: 6rem;
  font: inherit;
  font-size: 1rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  padding: 0.375rem 0.5rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line-control);
  background: var(--bg);
  color: var(--fg);
}

.board-capacity-input::placeholder {
  font-size: 0.875rem;
}

.board-capacity-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Kapazitäts-Fehler (§5.6.6): nur im Fehlerfall, `--error`-Zeile (13px) unter
 * der Einstellzeile — kein Dauer-Hint im Ruhezustand. */
.board-error-line {
  flex-basis: 100%;
  margin: 0.25rem 0 0; /* 4 unter der Zeile */
  color: var(--error);
  font-size: 0.8125rem;
  font-weight: 600;
}

/*
 * Die W6-Trenner (`.board-manage-divider`) sind ERSATZLOS entfallen: die
 * Sinn-Gruppen des Verwalten-Bereichs sind seit PKG-ANMUT-WEB Bausteine, und
 * ein Strich zwischen zwei Flächen wäre eine zweite Trennung derselben Naht.
 */

/* Titel-Umbenennen (W6): Textfeld in der Inline-Einstellzeile — wie das
 * Kapazitäts-Feld geskinnt, aber linksbündig und wachsend (Titel sind Wörter,
 * keine Zahl). min-width:0 hält die Zeile bei 360px zusammen. */
.board-title-input {
  flex: 1 1 8rem;
  min-width: 0;
  font: inherit;
  font-size: 1rem;
  padding: 0.375rem 0.5rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line-control);
  background: var(--bg);
  color: var(--fg);
}

.board-title-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Rhythmus-Gruppe (W6): nackter fieldset-Reset — Segment-Umschalter + Chips
 * kommen 1:1 aus der /new-Skin (.seg/.seg-option/.weekday-chip). */
.board-manage-rhythm {
  margin: 0;
  padding: 0;
  border: none;
}

.board-manage-weekdays {
  margin-top: 0.5rem;
}

/* Zähltag-Ende (W6): dieselbe „5:00"-Uhrzeit-Gruppe wie /new — die Input-Skin
 * dort ist auf .new-form gescopt, hier der Board-Zwilling. */
.board-manage-body .reset-time input[type="number"] {
  width: 2.6rem;
  border: none;
  background: transparent;
  text-align: right;
  padding: 0.45rem 0.1rem 0.45rem 0.5rem;
  font: inherit;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}

.board-manage-body .reset-time input[type="number"]:focus {
  outline: none;
}

/*
 * Zweistufen-Bestätigung inline (W6, Slug-Rotation + Löschen): Warnzeile in
 * 13px — neutral (--muted) bei der Rotation, --error nur beim Löschen (die
 * Gefahr sitzt in Farbe + Position, nicht in Lautstärke). Kein Modal, kein
 * window.confirm (blockiert den automatisierten Klickpfad, s. .confirm-panel).
 */
.board-confirm-note {
  margin: 0.25rem 0 0;
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 600;
}

.board-confirm-note--danger {
  color: var(--error);
}

/* Destruktive leise Aktion (W6: Kanal löschen) — Board-Zwilling von
 * .account-danger; steht nach .board-quiet, gewinnt also die Farbe. */
.board-danger {
  color: var(--error);
}

/* Ring-Pop je neu gefülltem Ring + einmaliger Match-Puls (§6). Die SVG-Kreise
 * skalieren um ihr eigenes Zentrum (transform-box: fill-box). */
@keyframes rf-pop {
  from {
    transform: scale(0.6);
  }
  to {
    transform: scale(1);
  }
}

.rf-ring--pop {
  transform-box: fill-box;
  transform-origin: center;
  animation: rf-pop 200ms ease-out;
}

@keyframes rf-pulse {
  from {
    opacity: 0.5;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(1.28);
  }
}

.rf-pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: rf-pulse 600ms ease-out forwards;
}

/*
 * Konto-Strecke (W4, Trichter-Sprache): dieselbe Vokabel wie Board/Trichter —
 * Trichter-Kopf, flache Zonen mit dünnen --line-Trennern (Ent-Boxen §5.6.1),
 * Versalien-Sektionslabels, leise Zeilen-Aktionen, genau EIN Primär-CTA nur
 * dort, wo eine Hauptaktion existiert (login/verify/news-confirm — die
 * Konto-Seite selbst hat bewusst keinen).
 */

/* Ein Satz, was das Konto bringt (login) — normale Stimme, kein Hero. */
.account-lead {
  margin: 0 0 0.5rem;
  font-size: 1rem;
  font-weight: 600;
}

/* Ruhige Neben-/Zustandstexte (Intro, „Mail ist unterwegs"-Body,
 * abgelaufen/verbraucht, leere Liste): 14px --muted. */
.account-sub {
  margin: 0 0 1.25rem;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.45;
}

/* Bestätigen-CTA der Button→POST-Landings (verify/news-confirm): Abstand
 * zur Intro-Zeile — der Button ist die Bühne dieser Seiten. */
.account-confirm-cta {
  margin-top: 1.5rem;
}

/* Träger-Zeile für leise Link-Aktionen (Neuen Link anfordern / Zum Konto /
 * Zur Startseite): kein zusätzlicher Absatz-Rhythmus. */
.account-quiet-row {
  margin: 0;
}

/* Sektionen der Konto-Seite: flache Zonen, dünne --line-Trenner statt
 * Karten/Boxen; die erste Zone beginnt ohne Linie direkt unterm Kopf. */
.account-section {
  margin: 0;
  padding: 1.25rem 0;
  border-top: 1px solid var(--line);
}

#account-content > .account-section:first-child {
  border-top: none;
  padding-top: 0;
}

/* Sektionslabels in der Versalien-Labels-Rolle (§3) — h2 bleibt h2
 * (Semantik/SR), nur die Stimme wird leise. */
.page h2.account-label {
  margin: 0 0 0.75rem;
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/*
 * Zeilen-Aktionen der Mitgliedschaften (account-page.js erzeugt Button/Link
 * OHNE Klassen — der Skin kommt bewusst rein über dieses Scoping, damit die
 * JS-Logik unangetastet bleibt): leise Aktion am Zeilenende.
 */
.account-memberships li button,
.account-memberships li a {
  margin-left: auto;
  min-height: 2.75rem;
  padding: 0 0.25rem;
  background: none;
  border: none;
  border-radius: 0;
  color: var(--fg);
  font-size: 0.8125rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

/* Checkbox-Zeile des News-Opt-ins: flache Zeile, Accent-Haken — die Checkbox
 * bleibt ein echtes, NICHT vorangekreuztes Input (D22c: den Zustand setzt
 * allein der Server-Wert via JS). Auf #account-root gescopt, damit die
 * `.choice`-Zeile der Tafel (Discord-Toggle, W5) unberührt bleibt. */
#account-root .choice {
  display: inline-flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.9375rem;
  cursor: pointer;
}

#account-root .choice input[type="checkbox"] {
  flex: 0 0 auto;
  width: 1.0625rem;
  height: 1.0625rem;
  margin: 0.125rem 0 0;
  accent-color: var(--accent);
}

/* „Du bekommst Produkt-News." + leises Abbestellen in einer Zeile. */
.account-news-on {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  margin: 0;
}

/* Destruktive Rand-Aktion (Konto löschen / Ja, löschen): leise Stufe in
 * --error — klar als Gefahr lesbar, nie als verlockender Primär-CTA.
 * Steht nach .board-quiet im Stylesheet, gewinnt also die Farbe. */
.account-danger {
  color: var(--error);
}

/*
 * Account page (P3.4, Konzept 6.4). Tokens only, same list/hint vocabulary
 * as the board members list above.
 */
.account-memberships {
  list-style: none;
  margin: 0;
  padding: 0;
}

.account-memberships li {
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}

.account-memberships li:last-child {
  border-bottom: none;
}

.account-membership-title {
  font-weight: 600;
}

.account-membership-name {
  color: var(--muted);
  font-size: 0.8125rem;
}

/* Labels role (DESIGN-SPEC §3: 11px versals, +6% tracking) — the creator/
 * role badge is the one existing "label"-shaped piece of UI. */
.account-membership-badge {
  color: var(--muted);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/*
 * In-page confirmation panel (P3.4): replaces `window.confirm`/`window.alert`
 * everywhere a destructive or state-changing action needs a confirm step
 * (account deletion, claim-collision "umstellen") — a native confirm dialog
 * blocks Playwright's automated click path (P3.5), so every confirmation in
 * this product is this same in-DOM pattern instead.
 */
.confirm-panel {
  margin: 0.75rem 0 1.25rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--error);
  border-radius: var(--radius);
}

.confirm-panel p {
  margin: 0 0 0.75rem;
  font-weight: 600;
}

/* Kollisions-Panel (D22/D26g „Umstellen"): Zustandswechsel, nicht destruktiv —
 * neutraler --line-Rahmen statt des --error-Rahmens der Lösch-Bestätigung.
 * MUSS nach dem `.confirm-panel`-Block stehen (W5-Fix): bei gleicher
 * Spezifität gewinnt die Quellordnung, und der `border`-Shorthand oben würde
 * eine früher notierte border-color sonst wieder auf --error zurücksetzen —
 * so stand die Regel bis W5 wirkungslos VOR dem Shorthand. */
.confirm-panel--neutral {
  border-color: var(--line);
}

/*
 * Discord-Link-Seite (W5, D26): Trichter-Skin über der unveränderten
 * P4.4-Logik (discord-link.js toggelt nur `hidden`). Im Kollisions-Zustand
 * (D26g: #switch-wrap sichtbar) ist der „Umstellen"-CTA im neutralen
 * confirm-panel der EINE Primär-CTA der Seite; der weiterhin sichtbare
 * „Verknüpfen und dabei sein"-Button tritt rein visuell in die
 * Sekundär-Stufe zurück (--line-Rand, keine Fläche) — CSS-Demotion statt
 * JS-Änderung. `:has()` wie bei body:has(.page-board) verfügbar.
 */
.page-discord-link:has(#switch-wrap:not([hidden])) #link-confirm {
  background: transparent;
  color: var(--fg);
  border-color: var(--line);
}

/*
 * prefers-reduced-motion (DESIGN-SPEC §6, product-ux.md a11y rule): ALLE
 * Signatur-Animationen aus (Ring-Pop, Match-Puls, CTA-Press), harte
 * Zustandswechsel. board.js unterdrückt zusätzlich das Auslösen der Pops/des
 * Puls-Rings, dieser Block ist die CSS-seitige Garantie.
 */
@media (prefers-reduced-motion: reduce) {
  .page-board * {
    transition: none !important;
    animation: none !important;
  }

  .board-cta:active {
    transform: none;
  }
}

/*
 * Site footer (M5-Vorarbeit): DSGVO-Pflichtlinks (Impressum/Datenschutz) auf
 * jeder Seite, bewusst leise — kleine Schrift, --muted, keine Fläche/Linie,
 * lenkt nicht von der Tafel ab. Sitzt außerhalb von `.page`, im normalen
 * body-flex-Fluss (body zentriert seinen Inhalt vertikal; die Fußzeile ist
 * ein zweites Flex-Kind darunter, kein position:fixed — bleibt so auch bei
 * langem Board-Inhalt am Seitenende statt über dem Content zu schweben).
 *
 * Sonderfall Startseite (Nachzug B): `body:has(.page-home)` oben schaltet den
 * body auf ein 4-Zeilen-Grid um und weist der Fußzeile explizit Reihe 4 zu
 * (= fix am Viewport-Boden statt direkt unter dem Content-Block) — ihr
 * eigener `margin-top` wird dort auf 0 überschrieben, weil der Grid-Puffer
 * (Reihe 3) den Abstand bereits herstellt.
 */
.site-footer {
  flex-shrink: 0;
  /*
   * LEISE Fußzeile (Nachtrag „App-Anmutung", Diagnose-Befund „die Seiten-
   * Anatomie ist die eines Dokuments"): Rechtstexte unter jedem Screen lesen
   * als Website. Sie bleiben vollständig erreichbar — DSGVO-Pflicht und
   * CLAUDE.md Prinzip 3 —, treten aber zurück: mehr Abstand nach oben (die
   * Fußzeile ist nicht mehr Teil des Inhalts, sondern liegt hinter ihm), 11px
   * statt 12px und eine abgesenkte Unterstreichung statt einer vollen. Die
   * Affordanz bleibt (die Linie verschwindet NICHT — sie zieht auf Hover und
   * Fokus voll auf); dieselbe Absenkung wie bei `a.board-quiet`.
   */
  margin-top: 3rem;
  padding: 1rem 2rem 2rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.6875rem;
}

.site-footer a,
.site-footer .site-footer-link {
  color: var(--muted);
}

.site-footer a:hover,
.site-footer a:focus-visible,
.site-footer .site-footer-link:hover,
.site-footer .site-footer-link:focus-visible {
  color: var(--fg);
}

/*
 * Abgesenkte Link-Unterstreichung — EINE Regel (PKG-BACKLOG-2; Backlog
 * 21.07.2026: „bei einer dritten Stelle in eine gemeinsame Regel ziehen").
 * Die dritte Stelle kam mit der leisen Fußzeile der Anmutungs-Welle; eine
 * vierte, halbe Kopie lag am Discord-Schritt-1-Link, die den `text-decoration`-
 * Shorthand neu setzte und damit die Absenkung wieder auf eine volle Linie
 * zurückdrehte. Beide Abweichungen sind hier aufgelöst.
 *
 * Bedeutung unverändert (PKG-VIS 20.07.2026): leise Navigations-LINKS brauchen
 * ein Interaktions-Signal, ohne laut zu werden — die Linie liegt im
 * Ruhezustand abgesenkt und zieht auf Hover/Fokus voll auf. Weiterhin nur
 * <a>-Elemente (plus der als Link gestaltete Fußzeilen-Knopf); die leisen
 * Verb-Buttons der Rand-Zone (Kopieren, Speichern, Entfernen …) bleiben
 * rahmenlos (§5.6.2).
 *
 * DER WERT ist `--underline-veil: 45%` (Modus-Block oben) — die Zahl aus
 * PKG-VIS. Die Fußzeile stand bis zur Zusammenführung auf 40 % und widersprach
 * damit ihrem eigenen Kommentar („dieselbe Absenkung wie bei a.board-quiet");
 * das war Drift, kein zweiter Entwurf. Wer eine Fläche künftig anders will,
 * überschreibt den Token in ihrem Scope und schreibt den Grund dazu, statt
 * eine weitere Kopie der Deklaration anzulegen.
 *
 * Steht am Ende des Stylesheets, und dafür zählt genau EIN Selektor:
 * `.account-memberships li a` setzt oben `text-decoration: none` und ist mit
 * dem gleichlautenden Selektor hier spezifitätsgleich (0-1-2) — dort
 * entscheidet allein die Quellordnung. Gegen `.board-quiet` (0-1-0) gewinnt
 * `a.board-quiet` (0-1-1) dagegen schon über die Spezifität; die Position ist
 * dafür nicht nötig.
 */
a.board-quiet,
.account-memberships li a,
.site-footer a,
.site-footer .site-footer-link {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor var(--underline-veil), transparent);
  text-underline-offset: 0.15em;
}

a.board-quiet:hover,
a.board-quiet:focus-visible,
.account-memberships li a:hover,
.account-memberships li a:focus-visible,
.site-footer a:hover,
.site-footer a:focus-visible,
.site-footer .site-footer-link:hover,
.site-footer .site-footer-link:focus-visible {
  text-decoration-color: currentColor;
}

/*
 * PKG-BUG "Problem melden": der Fußzeilen-Trigger ist ein <button>, sieht aber
 * aus wie die anderen Fußzeilen-Links (--muted, unterstrichen) — kein CTA, kein
 * Rand, keine Fläche. Reine Rand-Aktion im Stil der übrigen Fußzeile.
 */
.site-footer-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

/*
 * Leises Inline-Formular unter der Fußzeile (kein Modal, Konzept 6.6). Schmal,
 * zentriert wie die Fußzeile. Erscheint erst auf Tap des Triggers (hidden via
 * [hidden]).
 *
 * PKG-ANMUT-TOKENS: das Panel war schon eine Fläche mit Rand und Radius — es
 * bezieht seine Skin jetzt aus der Baustein-Utility (`.block--raised` im
 * Markup) statt aus eigenen Werten. Hier bleiben nur Breite, Lage und die
 * abweichende Innenpolsterung; Fläche, Radius, Schatten und die Haarlinie des
 * hellen Modus kommen aus einer Quelle. Damit ist die angehobene Fläche auf
 * JEDER Seite belegbar, ohne dass dieses Paket die Tafel umbaut
 * (das ist PKG-ANMUT-WEB).
 */
.bug-report-panel {
  /*
   * Breite an der Inhaltsspalte, nicht am Viewport: `.page` ist 32rem breit
   * mit 2rem Innenabstand, seine Textspalte also 28rem. Das Panel liegt aber
   * AUSSERHALB von `.page` (eigenes Flex-Kind des Body) und hat kein eigenes
   * Seitenpolster — mit `max-width: 28rem` allein lief es auf einem 390px-
   * Viewport beidseitig über die Spalte hinaus, seine Kante stand 8px links
   * von allem darüber. Solange die Fläche unsichtbar war, fiel das nicht auf;
   * mit Haarlinie und Schatten wird es zur schiefen Kante (§1: definierte
   * Ausrichtung, gleiche optische Gewichte links und rechts).
   * `calc(100% - 4rem)` spiegelt das Seitenpolster von `.page`, `28rem`
   * deckelt auf dieselbe Spaltenbreite — beide Fälle decken sich exakt.
   */
  width: calc(100% - 4rem);
  max-width: 28rem;
  margin: 0 auto 2rem;
  padding: 1rem 1.25rem 1.25rem;
}

.bug-report-label {
  display: block;
  color: var(--fg);
  font-size: 0.8125rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.bug-report-textarea {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: 1rem; /* 16px — iOS-Zoom-Schutz, wie .member-note-input */
  padding: 0.5rem 0.625rem;
  border: 1px solid var(--line-control);
  /* Eingabefeld → Control-Radius (8px). `--radius-sm` ist den Inline-
   * Kleinteilen vorbehalten (Notiz-Slot, Swatch), s. Rollen-Definition oben. */
  border-radius: var(--radius-control);
  background: var(--bg);
  color: var(--fg);
  resize: vertical;
}

.bug-report-textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.bug-report-privacy {
  margin: 0.625rem 0 0;
  color: var(--muted);
  font-size: 0.6875rem;
  line-height: 1.4;
}

.bug-report-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.bug-report-error {
  margin: 0.625rem 0 0;
  color: var(--error);
  font-size: 0.75rem;
}

.bug-report-result {
  color: var(--fg);
  font-size: 0.8125rem;
}

/*
 * Legal pages (Impressum/Datenschutz, M5-Vorarbeit): wider than the compact
 * `.page` forms (~65ch statt 32rem) — this is dense DSGVO-Fließtext, not a
 * short form, so it gets the room to breathe while staying left-aligned and
 * readable. `text-align:left` overrides `.page`'s centered default; `.page`
 * itself still supplies the vertical body padding/rhythm.
 */
.page-legal {
  max-width: 42rem;
  text-align: left;
}

.legal-header {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 0 0 1.5rem;
}

.legal-updated {
  margin: -1rem 0 2rem;
  color: var(--muted);
  font-size: 0.8125rem;
}

.page-legal h2 {
  margin: 2rem 0 0.5rem;
  font-size: 1.0625rem;
  font-weight: 700;
}

.page-legal h2:first-of-type {
  margin-top: 0;
}

.page-legal p,
.page-legal ul {
  margin: 0 0 1rem;
  line-height: 1.55;
}

.page-legal ul {
  padding-left: 1.25rem;
}

.page-legal a {
  color: var(--fg);
}

.page-legal a:hover,
.page-legal a:focus-visible {
  /* Text → Ink-Stufe (Nachtrag „App-Anmutung" §3). */
  color: var(--accent-ink);
}
