/* =============================================================================
 * Designtokens — die einzige Datei im Projekt, in der ein Farbliteral stehen
 * darf. Überall sonst ist das rot: tests/design-tokens.test.ts (Guard A).
 *
 * Drei Ebenen, in dieser Reihenfolge, und nichts als Custom Properties:
 *
 *   L0  Primitive  — Rohwerte. Sagen WAS sie sind, nie wozu.
 *   L1  Semantik   — sagen WOZU. Verweisen ausschließlich auf L0.
 *   L2  Identität  — ausschließlich --brand-*. Der einzige Abschnitt, der sich
 *                    zwischen Brain und Cockpit unterscheiden darf (Guard B).
 *
 * Komponenten referenzieren ausschließlich L1 (und --brand-* aus L2).
 * Wer in einer Komponente einen L0-Wert braucht, hat einen fehlenden L1-Token
 * gefunden — das ist ein Befund, keine Ausnahme.
 *
 * Die einzige Nicht-Custom-Property hier ist `color-scheme` auf :root, weil
 * light-dark() ohne sie nichts entscheiden kann. Die Umschaltklassen stehen in
 * base.css, weil sie Verhalten sind und kein Token.
 *
 * ADR-0024.
 * ========================================================================== */

/* =============================================================================
 * TOKEN-LAYER: L0
 *
 * Primitive. Rohwerte, Farben durchgehend in OKLCH.
 *
 * Die Neutralen sind nach ihrer OKLCH-Helligkeit benannt: --neutral-90 hat
 * L = 0.90. Das ist absichtlich stumpf. Eine Rampe mit erfundenen Stufennamen
 * (50/100/200…) behauptet eine Ordnung, die niemand nachrechnen kann, und die
 * erste Farbe, die dazwischenpasst, bricht sie. Die Helligkeit steht ohnehin
 * daneben, also ist sie der Name.
 *
 * Der leichte Chroma-Anteil (0.003–0.008) ist kein Zufall: reines Grau wirkt
 * neben dem Petrol-Akzent kalt und tot. Die Hue-Werte 60–85 sind ein warmer
 * Papierton, in beiden Modi.
 * ========================================================================== */

:root {
  /* light-dark() braucht das, sonst hat es nichts zu entscheiden. */
  color-scheme: light dark;

  /* -- Neutralrampe ------------------------------------------------------- */
  --neutral-99: oklch(0.99 0.003 85);
  --neutral-97: oklch(0.97 0.004 85);
  --neutral-93: oklch(0.93 0.004 80);
  --neutral-90: oklch(0.9 0.006 75);
  --neutral-66: oklch(0.66 0.008 70);
  --neutral-50: oklch(0.5 0.008 60);
  --neutral-32: oklch(0.32 0.008 70);
  --neutral-23: oklch(0.23 0.006 70);
  --neutral-22: oklch(0.22 0.006 60);
  --neutral-19: oklch(0.19 0.005 70);

  /* Bei L 0 entscheiden Chroma und Hue nichts mehr. Gebraucht wird der Wert nur
     vom Schatten im Dunkelmodus: dort muss etwas dunkler sein als die Seite,
     und --neutral-19 IST die Seite. */
  --neutral-0: oklch(0 0 0);

  /* -- Zustandsfarben ----------------------------------------------------- *
   * Je ein Hell- und ein Dunkelwert. Die Dunkelwerte sind heller UND flauer,
   * nicht bloß aufgehellt: gesättigtes Rot auf dunklem Grund flimmert.        */
  --red-52: oklch(0.52 0.17 27);
  --red-70: oklch(0.7 0.15 27);
  --amber-60: oklch(0.6 0.12 75);
  --amber-78: oklch(0.78 0.12 80);
  --green-58: oklch(0.58 0.1 150);
  --green-74: oklch(0.74 0.1 150);

  /* -- Radien -------------------------------------------------------------- *
   * Drei Werte, mehr gibt es nicht. Eine vierte Zwischenstufe ist die Stufe,
   * die niemand konsistent trifft.                                           */
  --radius-6: 6px;
  --radius-10: 10px;
  --radius-full: 999px;

  /* -- Abstände (Vielfache von 4) ------------------------------------------ */
  --space-4: 4px;
  --space-8: 8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-20: 20px;
  --space-24: 24px;
  --space-32: 32px;
  --space-40: 40px;
  --space-48: 48px;
  --space-64: 64px;

  /* -- Typoskala ----------------------------------------------------------- */
  --text-13: 13px;
  --text-15: 15px;
  --text-17: 17px;
  --text-21: 21px;
  --text-27: 27px;

  /* -- Schriftfamilien ----------------------------------------------------- *
   * Selbst gehostet (base.css, @font-face). Der Systemstack dahinter ist kein
   * Zierrat: font-display: swap zeigt ihn, solange Plex lädt.                */
  --font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:
    "IBM Plex Mono", ui-monospace, SFMono-Regular, "Cascadia Mono", monospace;
}

/* =============================================================================
 * TOKEN-LAYER: L1
 *
 * Semantik. Namen sagen wozu, nicht was. Werte verweisen auf L0.
 *
 * Hell und dunkel über light-dark(), einmal deklariert statt zweimal. Das ist
 * kein Trick, sondern das dokumentierte Verhalten: light-dark() wird am
 * GEBRAUCHSORT aufgelöst, nicht dort, wo die Property steht. Eine Zone mit
 * `color-scheme: dark` zieht deshalb die Dunkelwerte aus genau diesem Block,
 * ohne dass er ein zweites Mal auftaucht.
 *
 * Genau umgekehrt zu var(): das wird am DEKLARATIONSORT substituiert — siehe
 * die Warnung in L2. Beides in einer Wegwerfseite nachgemessen (M12.1), nicht
 * aus dem Kopf übernommen; die zwei Regeln sehen ähnlich aus und sind
 * gegenläufig.
 * ========================================================================== */

:root {
  /* -- Vordergrund --------------------------------------------------------- */
  --fg-default: light-dark(var(--neutral-22), var(--neutral-93));
  --fg-muted: light-dark(var(--neutral-50), var(--neutral-66));

  /* -- Flächen ------------------------------------------------------------- */
  --bg-page: light-dark(var(--neutral-99), var(--neutral-19));
  --bg-surface: light-dark(var(--neutral-97), var(--neutral-23));

  /* -- Kanten -------------------------------------------------------------- */
  --border-subtle: light-dark(var(--neutral-90), var(--neutral-32));

  /* -- Schatten ------------------------------------------------------------ *
   * Eine Stufe, nur für Schwebendes (ADR-0024, design/brain-shell-preview.html).
   * light-dark() steht in der Farbe statt um den ganzen Wert, weil es nur
   * Farben nimmt — und der Wert enthält Kommas, die es sonst als sein zweites
   * Argument läse. Die zweite, 1px hohe Ebene des Entwurfs fehlt absichtlich:
   * jede schwebende Fläche hat eine 1px-Kante, die dasselbe leistet.          */
  --shadow: 0 8px 28px -6px
    light-dark(
      color-mix(in oklch, var(--neutral-22) 18%, transparent),
      color-mix(in oklch, var(--neutral-0) 55%, transparent)
    );

  /* -- Zustände ------------------------------------------------------------ *
   * Der Farbkanal gehört dem Zustand. Achsen greifen hier nicht hinein.      */
  --state-overdue: light-dark(var(--red-52), var(--red-70));
  --state-attention: light-dark(var(--amber-60), var(--amber-78));

  /* Die schwache Fassung ist eine Fläche, keine zweite Farbe: dieselbe Stufe
     wie --brand-accent-weak (0.11 hell, 0.16 dunkel), damit eine getönte Spalte
     und eine getönte Zeile gleich viel wiegen. Im Dunkeln braucht es mehr
     Deckkraft für denselben Eindruck. */
  --state-attention-weak: light-dark(
    color-mix(in oklch, var(--amber-60) 11%, transparent),
    color-mix(in oklch, var(--amber-78) 16%, transparent)
  );

  /* --state-positive ist NICHT der Status "erledigt".
   *
   * Erledigtes in einer Arbeitsliste tritt zurück und ist grau — dort soll der
   * Blick an Offenem hängen bleiben. Dieser Token ist für den rückblickenden
   * Ergebnismarker im Tagesplan, nach dem man aktiv sucht: "was ist gestern
   * durchgegangen". Zwei verschiedene Fragen, zwei verschiedene Farben.
   *
   * Wer ihn an einem Task-Status verwendet, hat den falschen Token. */
  --state-positive: light-dark(var(--green-58), var(--green-74));

  --state-positive-weak: light-dark(
    color-mix(in oklch, var(--green-58) 11%, transparent),
    color-mix(in oklch, var(--green-74) 16%, transparent)
  );

  /* -- Achsen -------------------------------------------------------------- *
   * Achsen (archiviert, schlafend) sind Oberfläche, nicht Farbe: Deckkraft
   * und Kante, nie ein eigener Farbton. Sonst konkurrieren sie mit dem
   * Statuskanal und die Zeile sagt zwei Dinge gleichzeitig. Spiegelt ADR-0022
   * und ADR-0023, wo dieselbe Trennung im Datenmodell steht.               */
  --axis-snoozed-opacity: 0.62;

  /* -- Fokus --------------------------------------------------------------- *
   * Zeigt bewusst nach L2. Der Fokusring ist die eine Stelle, an der die
   * Identität in der Semantikebene sichtbar sein soll: er ist ständig im Blick
   * und färbt sich damit gratis mit der App um, die ihn zeigt.              */
  --focus-ring: var(--brand-accent);

  /* -- Schrift ------------------------------------------------------------- */
  --font-body: var(--font-sans);
  --font-code: var(--font-mono);
}

/* =============================================================================
 * TOKEN-LAYER: L2
 *
 * Identität. Ausschließlich --brand-*. Sobald Cockpit existiert, ist dieser
 * Abschnitt das Einzige, was sich zwischen den beiden Apps unterscheiden darf.
 * Wächst hier etwas anderes hinein, divergieren die Apps unbemerkt — deshalb
 * hält tests/design-tokens.test.ts (Guard B) den Abschnitt sauber.
 *
 * ACHTUNG, und das ist eine echte Falle:
 * var() innerhalb einer Custom Property wird DORT aufgelöst, wo die Property
 * deklariert ist. Ein Element, das nur --brand-hue überschreibt, ändert
 * --brand-accent NICHT mit — es erbt den bereits ausgerechneten Wert. Jede
 * Zone, die den Hue setzt, muss die abgeleiteten Werte mitdeklarieren.
 * Deshalb stehen hier Hue und Ableitungen zusammen.
 *
 * Nachgemessen, nicht angenommen (M12.1): eine Zone mit nur `--brand-hue: 285`
 * behielt Akzent-Hue 195; erst die Zone, die auch --brand-accent neu
 * deklarierte, wurde violett.
 *
 * Brain 195 (Petrol), Cockpit 285 (Blauviolett) — gleiche Helligkeit, gleiche
 * Chroma, damit beide Farben dasselbe optische Gewicht haben.
 * ========================================================================== */

:root {
  --brand-hue: 195;
  --brand-accent: light-dark(
    oklch(0.55 0.11 var(--brand-hue)),
    oklch(0.72 0.1 var(--brand-hue))
  );
  --brand-accent-weak: light-dark(
    oklch(0.55 0.11 var(--brand-hue) / 0.11),
    oklch(0.72 0.1 var(--brand-hue) / 0.16)
  );
}
