/* ============================================================
   Design-System - Neo-Brutalismus
   ------------------------------------------------------------
   Die Designsprache in vier Regeln. Wer eine neue Flaeche baut,
   haelt sich daran, sonst faellt sie aus dem Bild:

     1. HARTE KANTE. Jede Flaeche hat denselben Rahmen
        (var(--bw) solid var(--ink)) und Ecken ohne Radius.
     2. HARTER SCHATTEN. Versatz statt Weichzeichnung:
        box-shadow: 6px 6px 0 var(--ink) - nie ein Blur-Radius.
     3. FLAECHIGE FARBE. Volltoene aus der Palette unten, keine
        Verlaeufe, keine gestapelten Transparenzen.
     4. GEDRUECKT HEISST VERSCHOBEN. Beim Tippen faehrt das Element
        auf seinen Schatten (translate + Schatten weg). Das ist die
        einzige Rueckmeldung, die es braucht.

   Farben sind gesetzt, nicht gemischt: --c1..--c5 sind die fuenf
   Akzente, die reihum benutzt werden (Kacheln, Karten, Badges).
   Alles Lesbare ist --ink auf --paper oder --ink auf einem Akzent -
   deshalb ist kein Akzent dunkel.

   Hier lag frueher LiquidGlass (WebGL-Shader). Das ist raus, und mit
   ihm die Zwaenge, die es dem Aufbau auferlegt hat: Shader-Kosten je
   Flaeche, Neuaufbau bei jedem Screenwechsel, Rastern bei jeder
   Textaenderung. Geblieben ist nur das flache DOM - das schadet nicht.
   ============================================================ */

:root {
  color-scheme: light;

  /* --- Grundtoene --- */
  --ink: #16110d;              /* Rahmen, Schatten, Text - fast schwarz */
  --paper: #fffdf5;            /* Flaechen */
  --canvas: #ffd84d;           /* Seitenhintergrund */
  --grid: rgba(22, 17, 13, 0.10);
  --muted: #efe9da;            /* neutrale Flaeche in einer Flaeche */

  /* --- Akzente (reihum verwendet) --- */
  --c1: #22d3ee;               /* Cyan */
  --c2: #ff4fa3;               /* Pink */
  --c3: #b8f62b;               /* Limette */
  --c4: #8b5cf6;               /* Violett */
  --c5: #ff8a3d;               /* Orange */

  /* Aufgehellte Fassungen derselben Akzente - nur fuer die Formen im
     Hintergrund. Darueber steht Text (Ueberschriften, Hinweise), und der
     muss lesbar bleiben; die Volltoene sind dafuer zu dunkel. */
  --c1-soft: #a9eefb;
  --c2-soft: #ffc2de;
  --c4-soft: #d5c6ff;

  --danger: #ff2d2d;
  --success: #00b34a;

  --text: var(--ink);
  --text-dim: rgba(22, 17, 13, 0.68);
  --text-faint: rgba(22, 17, 13, 0.45);

  /* --- Kante & Schatten --- */
  --bw: 3px;                   /* Rahmenstaerke, ueberall dieselbe */
  --sh: 6px;                   /* Schattenversatz Flaechen */
  --sh-btn: 5px;               /* Schattenversatz Bedienelemente */
  --shadow: var(--sh) var(--sh) 0 var(--ink);
  --shadow-btn: var(--sh-btn) var(--sh-btn) 0 var(--ink);

  /* Ecken bleiben eckig. Die Variable existiert nur, damit ein
     Ausreisser als Ausreisser sichtbar wird. */
  --r: 0px;

  /* Zwei Schriftrollen, beide ohne externe Dateien: schwere Grotesk fuer
     Titel und Aktionen, Monospace fuer Eingaben und Lesetext. Der Display-
     Fallback bleibt eine Grotesk, auch wenn Arial Black nicht installiert ist. */
  --font-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, "Courier New", monospace;
  --font: var(--font-mono);
  --font-display: "Arial Black", "Arial Bold", Impact, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Kurz und hart - Brutalismus federt nicht nach. */
  --ease: cubic-bezier(0.2, 0.9, 0.3, 1);
  --dur: 0.09s;
  --flip-dur: 0.5s;

  /* Screenwechsel duerfen etwas laenger lesbar sein als ein Druck auf
     einen Knopf, bleiben auf einem Handy aber deutlich unter einer
     Drittelsekunde. Keine dieser Bewegungen laeuft dauerhaft. */
  --motion-fast: 0.16s;
  --motion-screen: 0.28s;
  --motion-distance: 18px;
  --motion-distance-back: -18px;
}

* { box-sizing: border-box; }

/* Muss VOR allen display-Regeln stehen und !important sein: das
   hidden-Attribut kommt nur aus dem UA-Stylesheet und wird sonst von
   jedem eigenen display:flex/grid ueberstimmt - versteckte Felder
   waeren dann sichtbar. */
[hidden] { display: none !important; }

/* Platz fuer die Scrollleiste immer freihalten. Am Rechner waechst die
   Seite ueber die Fensterhoehe, sobald ein Formular aufklappt - die
   Leiste erscheint, und alles darunter rutscht um ihre Breite zur
   Seite. Der Sprung faellt genau in die Aufklapp-Animation und macht
   sie kaputt. Am Handy kostet die Zeile nichts: dort liegt die Leiste
   ueber dem Inhalt und belegt keine Breite. */
html { scrollbar-gutter: stable; }

/* KEIN -webkit-font-smoothing hier, und das ist eine Entscheidung.
   Die Eigenschaft wirkt ausschliesslich in WebKit, also auf iOS und
   macOS - unter Android und Windows ist sie wirkungslos. Mit dem Wert
   "antialiased" zeichnet iOS Text ohne Subpixel und damit sichtbar
   duenner. Genau das war der Unterschied aus Issue #19: derselbe
   Schriftzug wirkte auf dem iPad schmaler als auf demselben Bild
   unter Android, ohne dass an der Schrift selbst etwas anders war.
   Wer die Zeile wieder einbaut, baut den Unterschied wieder ein. */
html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font);
  font-weight: 600;
  line-height: 1.45;
  -webkit-tap-highlight-color: transparent;
  /* iOS skaliert Text in manchen Layouts von sich aus hoch ("Text
     Size Adjust"), Chrome unter Android und Windows tut das nicht.
     Ohne diese Zeile ist auch das ein Unterschied, den nur iOS zeigt. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overscroll-behavior-y: contain;
}

/* Formulare erben die Schrift nicht automatisch. Ohne diesen Reset fallen
   etwa dynamisch erzeugte Auswahlzeilen auf die Browser-Schrift zurueck. */
button, input, select, textarea {
  font: inherit;
  color: inherit;
}
button {
  appearance: none;
  -webkit-appearance: none;
  border-radius: var(--r);
}

/* iOS blendet beim langen Tippen sein eigenes Menue ein (Vorschau,
   "Kopieren") und markiert dabei Text blau; Android kennt beides
   nicht. Auf einem Handy, das reihum gegeben wird, ist das nicht nur
   ein Unterschied, sondern im Weg - besonders auf der Klappkarte. */
button, label.btn {
  -webkit-touch-callout: none;
}

/* Tastaturbedienung sichtbar halten: der Fokusring gehoert zum System,
   er ist kein Ueberbleibsel des Browsers. */
:focus-visible {
  outline: var(--bw) solid var(--c4);
  outline-offset: 2px;
}

/* ------------------------------------------------------------
   Hintergrund
   Raster plus drei harte Formen. Bewusst ohne Weichzeichner und ohne
   Daueranimation: die Formen blenden beim Laden einmal ein und stehen
   danach ruhig, damit die Karten davor die Bewegung tragen.
   ------------------------------------------------------------ */
/* Ebenen bewusst explizit (siehe auch #app > * in app.css):
     z-index 0 = .bg,  z-index 1 = alle Inhalte
   .bg ist position:fixed und wuerde ohne z-index jeden statischen
   Inhalt uebermalen - genau so waren die Ueberschriften schon einmal weg. */
.bg {
  position: fixed;
  /* Feste Hoehe statt inset:0 - der Grund ist iOS (Issue #19).
     Ein fixiertes Element ist dort so hoch wie der SICHTBARE
     Viewport, und der waechst und schrumpft beim Scrollen mit der
     ein- und ausfahrenden Adressleiste. Die Formen darin haengen an
     vw/vh, also wandern sie bei jedem Scrollen mit und laufen der
     Seite sichtbar hinterher - das ist das "Nachruckeln" aus dem
     Issue. 100lvh ist die GROSSE Viewporthoehe und aendert sich
     dabei nicht; die 100vh davor sind der Rueckfall fuer Browser
     ohne lvh (dort ist 100vh ohnehin schon die grosse Hoehe).
     Unter Android und Windows aendert die Zeile nichts. */
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100lvh;
  z-index: 0;
  overflow: hidden;
  /* Eigene Compositor-Ebene. Damit schiebt iOS den Hintergrund beim
     Scrollen als fertiges Bild, statt Raster und Formen Bild fuer
     Bild neu zu zeichnen - der zweite Teil desselben Ruckelns. */
  transform: translateZ(0);
  background-color: var(--canvas);
  background-image:
    linear-gradient(var(--grid) 2px, transparent 2px),
    linear-gradient(90deg, var(--grid) 2px, transparent 2px);
  background-size: 44px 44px;
}
.bg i {
  position: absolute;
  display: block;
  border: var(--bw) solid var(--ink);
  animation: motion-shape-in 0.46s var(--ease) both;
}
.bg i:nth-child(1) {
  width: 52vw; height: 52vw; border-radius: 50%;
  top: -14vw; right: -18vw;
  background: var(--c1-soft);
}
.bg i:nth-child(2) {
  width: 40vw; height: 40vw;
  bottom: 24vh; left: -16vw;
  background: var(--c2-soft);
  transform: rotate(18deg);
  animation-delay: 0.05s;
}
.bg i:nth-child(3) {
  width: 34vw; height: 34vw;
  bottom: -10vw; right: -8vw;
  background: var(--c4-soft);
  border-radius: 50% 0 50% 50%;
  animation-delay: 0.1s;
}

/* ------------------------------------------------------------
   Buttons
   ------------------------------------------------------------ */
/* appearance:none steht an jedem Bedienelement dieser Datei, und zwar
   wegen iOS: Safari zeichnet Knoepfe und Felder sonst mit eigener
   Optik darueber - abgerundete Ecken, Innenschatten, eigener Verlauf.
   Chrome unter Android und Windows tut das nicht, die Zeile ist dort
   wirkungslos. Ohne sie bekommt ausgerechnet die Designsprache mit
   den harten Kanten auf einem Geraet weiche. */
.btn {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 15px 20px;
  border: var(--bw) solid var(--ink);
  border-radius: var(--r);
  background: var(--paper);
  box-shadow: var(--shadow-btn);
  font: inherit;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 900;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink);
  cursor: pointer;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* Gedrueckt heisst verschoben: das Element faehrt auf seinen Schatten. */
.btn:active {
  transform: translate(var(--sh-btn), var(--sh-btn));
  box-shadow: 0 0 0 var(--ink);
}
.btn:disabled {
  background: var(--muted);
  color: var(--text-faint);
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
}

/* Die wichtigste Aktion traegt Farbe, alle anderen bleiben Papier. */
.btn--primary { background: var(--c3); }
.btn--sm { --sh-btn: 4px; padding: 10px 12px; font-size: 0.8rem; }

.btn-row { display: flex; gap: 12px; }
.btn-row > * { flex: 1; }

.link {
  background: none; border: none;
  color: var(--ink);
  font: inherit; font-family: var(--font-display);
  font-size: 0.82rem; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.05em;
  text-decoration: underline; text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  cursor: pointer;
  padding: 6px; align-self: center;
}

/* ------------------------------------------------------------
   Eingabefelder
   ------------------------------------------------------------ */
.input {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  padding: 13px 14px;
  border: var(--bw) solid var(--ink);
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  font: inherit; font-family: var(--font-mono);
  font-size: 1rem; font-weight: 700;
  min-width: 0;
  box-shadow: 3px 3px 0 var(--ink);
  transition: box-shadow var(--dur) var(--ease);
}
.input::placeholder { color: var(--text-dim); font-weight: 600; opacity: 1; }
.input:focus {
  outline: none;
  box-shadow: 4px 4px 0 var(--c1);
}

.field { display: flex; flex-direction: column; gap: 8px; }
.label {
  font-family: var(--font-display);
  font-size: 0.76rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink);
}

/* ------------------------------------------------------------
   Chips / Badges
   ------------------------------------------------------------ */
.chip {
  appearance: none;
  -webkit-appearance: none;
  padding: 9px 14px;
  border: var(--bw) solid var(--ink);
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  font: inherit; font-family: var(--font-display);
  font-size: 0.8rem; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.05em;
  cursor: pointer; user-select: none;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}
.chip[aria-pressed="true"] {
  background: var(--c3);
  box-shadow: 3px 3px 0 var(--ink);
}
.chip:active { transform: translate(2px, 2px); box-shadow: none; }

.badge {
  font-family: var(--font-display);
  font-size: 0.66rem; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.07em;
  padding: 4px 9px;
  border: 2px solid var(--ink);
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  white-space: nowrap;
}
.badge--ok  { background: var(--c3); }
.badge--bad { background: var(--c2); }
.badge--muted { background: var(--muted); color: var(--text-dim); }

/* ------------------------------------------------------------
   Bewegung
   ------------------------------------------------------------
   Die Klassen setzt js/motion.js erst NACH der synchronen
   Zustandsaenderung. So bleibt hidden die Wahrheit und die Bewegung
   ist nur Rueckmeldung, nie Teil der Spiellogik.

   translate3d sorgt dafuer, dass iOS und Android die kurze Bewegung
   auf einer Compositor-Ebene abspielen. will-change gilt nur waehrend
   der Animation und belegt deshalb nicht dauerhaft Grafikspeicher.
   ------------------------------------------------------------ */
.motion-enter,
.motion-pulse {
  will-change: transform, opacity;
  animation-fill-mode: both;
  animation-timing-function: var(--ease);
}

.motion-enter { animation-duration: var(--motion-screen); }
.motion-enter--content,
.motion-enter--list { animation-duration: 0.22s; }
.motion-enter--forward { animation-name: motion-in-forward; }
.motion-enter--back { animation-name: motion-in-back; }
.motion-enter--list { animation-name: motion-list-in; }

.motion-delay-0 { animation-delay: 0s; }
.motion-delay-1 { animation-delay: 0.035s; }
.motion-delay-2 { animation-delay: 0.07s; }
.motion-delay-3 { animation-delay: 0.105s; }
.motion-delay-4 { animation-delay: 0.14s; }
.motion-delay-5 { animation-delay: 0.175s; }

.motion-pulse { animation-duration: var(--motion-fast); }
.motion-pulse--tick { animation-name: motion-tick; }
.motion-pulse--title { animation-name: motion-title; }
.motion-pulse--focus { animation-name: motion-focus; animation-duration: 0.24s; }

@keyframes motion-in-forward {
  from { opacity: 0; transform: translate3d(0, var(--motion-distance), 0) scale(0.985); }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

@keyframes motion-in-back {
  from { opacity: 0; transform: translate3d(var(--motion-distance-back), 0, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes motion-list-in {
  from { opacity: 0; transform: translate3d(10px, 0, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes motion-tick {
  0% { transform: scale(1); }
  45% { transform: scale(1.045); }
  100% { transform: scale(1); }
}

@keyframes motion-title {
  from { opacity: 0.35; transform: translate3d(0, -5px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes motion-focus {
  0% { transform: scale(1); }
  50% { transform: scale(0.99); }
  100% { transform: scale(1); }
}

@keyframes motion-shape-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
