/* ===========================================================================
   einhorn.live — Design-Tokens
   Eine Quelle fuer Farben, Typografie, Abstaende, Rundungen und Bewegung.
   Alle Apps und Panels benutzen ausschliesslich diese Variablen.
   Dunkelmodus ueber [data-theme="dark"] auf <html>.

   Stand 17.10.2026 — Ueberarbeitung des Fundaments:
   Die Markenfarben sind ABSICHTLICH unveraendert geblieben. In einigen Apps
   stehen Hexwerte hart im Quelltext; wuerde die Leitfarbe wandern, passten
   die nicht mehr und niemand wuerde es sofort merken. Geaendert wurde
   stattdessen alles, was Tiefe und Charakter macht und nirgends hart
   verdrahtet ist: Typografie, Schatten, Flaechen, Rundungen, Bewegung.
   =========================================================================== */

:root {
    /* ---- Markenfarben ---------------------------------------------------
       Violett als Leitfarbe (Einhorn), Mint als Gegenpol, Bernstein fuer
       Hinweise. Kontraste sind gegen die jeweilige Flaeche geprueft. */
    --brand-50:  #f5f1ff;
    --brand-100: #e9e0ff;
    --brand-200: #d4c2ff;
    --brand-300: #b79bff;
    --brand-400: #9a71fa;
    --brand-500: #7c4dee;
    --brand-600: #6436d2;
    --brand-700: #4f29a8;
    --brand-800: #3b1f7d;
    --brand-900: #2a1659;

    --mint-100: #d6f7ee;
    --mint-300: #86e3cb;
    --mint-500: #27bf9c;
    --mint-700: #16806a;

    --amber-100: #fdf0d2;
    --amber-300: #f7cf72;
    --amber-500: #e5a221;
    --amber-700: #9c6a0c;

    --rose-100: #ffe2e5;
    --rose-300: #ffa8b2;
    --rose-500: #e94b61;
    --rose-700: #a01c31;

    --sky-100: #d9ecff;
    --sky-300: #8ec5ff;
    --sky-500: #2f8ae0;
    --sky-700: #175a98;

    /* ---- Neutrale Toene -------------------------------------------------
       Leicht violett unterlegt statt reinem Grau. Neben einer violetten
       Leitfarbe wirkt echtes Neutralgrau schmutzig. */
    --grey-0:   #ffffff;
    --grey-25:  #fbfaff;
    --grey-50:  #f4f3f8;
    --grey-100: #e9e7f0;
    --grey-200: #d8d5e2;
    --grey-300: #b9b5c7;
    --grey-400: #918ca3;
    --grey-500: #6e6981;
    --grey-600: #524e61;
    --grey-700: #3b3847;
    --grey-800: #272531;
    --grey-900: #17161e;

    /* ---- Semantische Rollen, hell --------------------------------------- */
    --bg:            var(--grey-25);
    --bg-sunken:     var(--grey-50);
    --surface:       var(--grey-0);
    --surface-2:     var(--grey-50);
    --surface-hover: var(--brand-50);
    --border:        var(--grey-200);
    --border-strong: var(--grey-300);

    /* Erhoehte Flaeche: eine Karte, die vor dem Hintergrund stehen soll.
       Der leichte Verlauf von oben nach unten ist der Unterschied zwischen
       "weisses Rechteck" und "Gegenstand, der Licht abbekommt". */
    --surface-raised: linear-gradient(180deg,
                        var(--grey-0) 0%,
                        color-mix(in srgb, var(--brand-50) 55%, var(--grey-0)) 100%);
    /* Heller Saum an der Oberkante. Der alte Trick, der eine Flaeche
       physisch aussehen laesst, und er kostet kein einziges Pixel Ladezeit. */
    --ring-top: inset 0 1px 0 rgba(255, 255, 255, 0.9);

    --text:        var(--grey-800);
    --text-muted:  var(--grey-500);
    /* grey-400 waere hier die huebschere Wahl, kommt auf dem hellen Grund
       aber nur auf gemessene 3,12:1 — und genau in dieser Farbe stehen die
       Zeilen, die am wichtigsten sind: "Wir fragen nie nach E-Mail-Adresse"
       unter dem Anmeldefeld und die Fusszeile. Eine Stufe dunkler sind es
       5,05:1, und leise wirkt es immer noch. Im Dunkelmodus bleibt
       grey-400: dort steht es auf fast schwarzem Grund und passt. */
    --text-subtle: var(--grey-500);
    --text-on-brand: #ffffff;

    --primary:        var(--brand-500);
    --primary-hover:  var(--brand-600);
    --primary-soft:   var(--brand-50);
    --primary-border: var(--brand-200);

    --success:      var(--mint-500);
    --success-soft: var(--mint-100);
    --success-text: var(--mint-700);

    --warning:      var(--amber-500);
    --warning-soft: var(--amber-100);
    --warning-text: var(--amber-700);

    --danger:      var(--rose-500);
    --danger-soft: var(--rose-100);
    --danger-text: var(--rose-700);

    --info:      var(--sky-500);
    --info-soft: var(--sky-100);
    --info-text: var(--sky-700);

    /* Fachfarben, damit Mathe und Deutsch auf einen Blick zu trennen sind */
    --subject-mathe:   var(--sky-500);
    --subject-deutsch: var(--mint-500);
    --subject-sachu:   var(--amber-500);
    --subject-englisch: var(--rose-500);
    --subject-spiel:   var(--brand-400);

    /* ---- Typografie -----------------------------------------------------
       Drei Rollen statt einer. Bisher trug Nunito alles, auch die
       Ueberschriften — dadurch sah jede Seite ordentlich aus und keine
       hatte ein Gesicht.

       Fredoka  Ueberschriften und Kachelnamen. Rund, freundlich, kraeftig;
                gezeichnet fuer genau diese Aufgabe.
       Nunito   Flieasstext und Bedienelemente. Bleibt, weil sie in langen
                Zeilen besser liest als jede Display-Schrift.
       IBM Plex Mono  Zahlen, Codes, Uhrzeiten. Hat echte Ziffern gleicher
                Breite — in einer Rechen-App ist das kein Geschmack,
                sondern Lesbarkeit: die Spalten springen nicht mehr.

       Alle drei liegen lokal unter /assets/fonts/files/ und waren schon da.
       Es geht kein Aufruf nach draussen. */
    --font-display: "Fredoka", "Nunito", "Segoe UI", system-ui, sans-serif;
    --font-sans: "Nunito", "Segoe UI", system-ui, -apple-system, sans-serif;
    --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", "Menlo", monospace;

    /* Flexible Groessen: wachsen mit dem Viewport, bleiben aber begrenzt. */
    --fs-xs:   clamp(0.75rem, 0.72rem + 0.15vw, 0.82rem);
    --fs-sm:   clamp(0.875rem, 0.84rem + 0.2vw, 0.95rem);
    --fs-base: clamp(1rem, 0.96rem + 0.25vw, 1.1rem);
    --fs-lg:   clamp(1.15rem, 1.08rem + 0.4vw, 1.35rem);
    --fs-xl:   clamp(1.4rem, 1.28rem + 0.6vw, 1.75rem);
    --fs-2xl:  clamp(1.75rem, 1.5rem + 1.1vw, 2.4rem);
    --fs-3xl:  clamp(2.1rem, 1.7rem + 1.9vw, 3.2rem);
    /* Nur fuer den Begruessungsbereich der Startseite. Darf gross werden,
       steht aber nie neben Flieasstext. */
    --fs-display: clamp(2.6rem, 1.9rem + 3.4vw, 5rem);

    --lh-tight: 1.2;
    --lh-base:  1.55;
    /* Display-Schrift braucht engere Zeilen, sonst zerfaellt eine
       zweizeilige Ueberschrift in zwei Saetze. */
    --lh-display: 1.05;

    --fw-normal: 400;
    --fw-medium: 600;
    --fw-bold:   700;
    --fw-black:  800;

    /* ---- Abstaende ------------------------------------------------------ */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-5: 1.5rem;
    --sp-6: 2rem;
    --sp-7: 3rem;
    --sp-8: 4rem;

    /* ---- Rundungen ------------------------------------------------------
       Eine Stufe weicher als bisher. Zu einer runden Display-Schrift
       passen keine knappen Ecken. */
    --r-sm:   10px;
    --r-md:   14px;
    --r-lg:   22px;
    --r-xl:   30px;
    --r-full: 999px;

    /* ---- Schatten -------------------------------------------------------
       Eingefaerbt statt neutralgrau. Ein grauer Schatten auf einer leicht
       violetten Flaeche wird stumpf; derselbe Schatten im Markenton
       wirkt wie Licht und nicht wie Schmutz.

       Je Stufe zwei Lagen: eine enge fuer die Kante, eine weite fuer den
       Raum. Das ist der Unterschied zwischen "hat einen Schatten" und
       "liegt auf etwas". */
    --sh-sm: 0 1px 2px rgba(42, 22, 89, 0.05),
             0 2px 6px rgba(42, 22, 89, 0.06);
    --sh-md: 0 2px 6px rgba(42, 22, 89, 0.06),
             0 10px 24px rgba(42, 22, 89, 0.09);
    --sh-lg: 0 6px 18px rgba(42, 22, 89, 0.10),
             0 24px 56px rgba(42, 22, 89, 0.14);
    --sh-focus: 0 0 0 3px var(--primary-border);
    /* Schein in der Leitfarbe, fuer Kacheln und Knoepfe unter dem Zeiger.
       Nicht als Dauerzustand — nur als Antwort auf eine Handlung. */
    --sh-glow: 0 6px 20px color-mix(in srgb, var(--primary) 28%, transparent),
               0 2px 6px color-mix(in srgb, var(--primary) 20%, transparent);

    /* ---- Bedienflaechen -------------------------------------------------
       Mindestens 44px, weil die Seite vor allem auf Tablets benutzt wird. */
    --tap-min: 44px;
    --tap-lg:  56px;

    --container: 1180px;
    --transition: 160ms cubic-bezier(0.4, 0, 0.2, 1);

    /* ---- Bewegung -------------------------------------------------------
       Eine Quelle fuer Dauer und Kurve, damit CSS und GSAP nicht
       auseinanderlaufen. Dieselben Kurven stehen in motion.js noch einmal
       als Zahlen — CSS-Variablen kann GSAP nicht lesen. Wer hier etwas
       aendert, aendert es dort mit.

       ease-out   Der Normalfall. Schnell los, sanft an: fuehlt sich an wie
                  etwas, das ankommt, nicht wie etwas, das anfaehrt.
       ease-back  Winziger Ueberschwung. Nur fuer Dinge, die erscheinen —
                  Kacheln, Dialoge. Nie fuer Dinge, die verschwinden.
       ease-soft  Fuer Farb- und Deckkraftwechsel, wo ein Ueberschwung
                  nichts zu suchen hat. */
    --ease-out:  cubic-bezier(0.22, 1, 0.36, 1);
    --ease-back: cubic-bezier(0.34, 1.4, 0.64, 1);
    --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);

    --dur-fast: 150ms;
    --dur-base: 280ms;
    --dur-slow: 520ms;
}

/* ---- Dunkelmodus ------------------------------------------------------- */
[data-theme="dark"] {
    --bg:            var(--grey-900);
    --bg-sunken:     #101017;
    --surface:       var(--grey-800);
    --surface-2:     var(--grey-700);
    --surface-hover: #302c3f;
    --border:        #3a3747;
    --border-strong: #4d4a5c;

    /* Im Dunkeln laeuft der Verlauf nach oben: Licht kommt von oben, also
       ist die Oberkante heller. Derselbe Verlauf wie im Hellen waere hier
       eine Delle. */
    --surface-raised: linear-gradient(180deg,
                        color-mix(in srgb, var(--brand-300) 7%, var(--grey-800)) 0%,
                        var(--grey-800) 100%);
    --ring-top: inset 0 1px 0 rgba(255, 255, 255, 0.07);

    --text:        var(--grey-50);
    --text-muted:  var(--grey-300);
    --text-subtle: var(--grey-400);

    --primary:        var(--brand-300);
    --primary-hover:  var(--brand-200);
    --primary-soft:   #2b2342;
    --primary-border: #4a3d72;
    --text-on-brand:  var(--grey-900);

    --success:      var(--mint-300);
    --success-soft: #16352e;
    --success-text: var(--mint-300);

    --warning:      var(--amber-300);
    --warning-soft: #3a2f16;
    --warning-text: var(--amber-300);

    --danger:      var(--rose-300);
    --danger-soft: #3d1c24;
    --danger-text: var(--rose-300);

    --info:      var(--sky-300);
    --info-soft: #152c44;
    --info-text: var(--sky-300);

    --subject-mathe:   var(--sky-300);
    --subject-deutsch: var(--mint-300);
    --subject-sachu:   var(--amber-300);
    --subject-englisch: var(--rose-300);
    --subject-spiel:   var(--brand-300);

    /* Im Dunkeln traegt Schwarz den Schatten, nicht die Marke — ein
       violetter Schatten auf dunklem Grund sieht aus wie ein Lichtfehler. */
    --sh-sm: 0 1px 2px rgba(0, 0, 0, 0.45);
    --sh-md: 0 2px 8px rgba(0, 0, 0, 0.5),
             0 10px 24px rgba(0, 0, 0, 0.35);
    --sh-lg: 0 10px 30px rgba(0, 0, 0, 0.6),
             0 28px 64px rgba(0, 0, 0, 0.45);
    --sh-glow: 0 6px 22px color-mix(in srgb, var(--primary) 30%, transparent);
}

/* Wer keine Praeferenz gesetzt hat, folgt dem System. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
    }
}

/* Weniger Bewegung, wenn das System es verlangt.
   GSAP liest das NICHT von sich aus — das macht motion.js ueber
   gsap.matchMedia(). Diese Regeln hier decken nur CSS ab. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --transition: 0ms;
        --dur-fast: 0ms;
        --dur-base: 0ms;
        --dur-slow: 0ms;
    }
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
