/* ============================================================
   polyDesign — Design System Tokens
   Quelle: Figma "polyPage Design V2" (FK3KQlmTD8R8fdzwzC6lwD)
   Aus Figma-Variablen + /designsystem/typo ausgelesen.
   Breakpoints: Tablet <= 960px, Mobile <= 480px
   Schriften nach Style-Namen gemappt (Figma weight-Zahlen sind
   unzuverlässig -> echte Schnitte verwendet).
   ============================================================ */

/* ---------- Schriften ---------- */
@font-face{
  font-family:"HGS3"; font-style:normal; font-weight:400; font-display:swap;
  src:url("assets/font/WOFF/5701GeoSans_Reg.woff2") format("woff2"),
      url("assets/font/WOFF/5701GeoSans_Reg.woff") format("woff");
}
@font-face{
  font-family:"HGS3"; font-style:normal; font-weight:600; font-display:swap;
  src:url("assets/font/WOFF/6746GeoSans_Semi.woff2") format("woff2"),
      url("assets/font/WOFF/6746GeoSans_Semi.woff") format("woff");
}
@font-face{
  font-family:"HGS3"; font-style:normal; font-weight:700; font-display:swap;
  src:url("assets/font/WOFF/5218GeoSans3_Bold.woff2") format("woff2"),
      url("assets/font/WOFF/5218GeoSans3_Bold.woff") format("woff");
}
@font-face{
  font-family:"HFM"; font-style:normal; font-weight:500; font-display:swap;
  src:url("assets/font/WOFF/HurmeFINMono1b-Medium.woff") format("woff");
}

:root{
  /* ---------- Farben ---------- */
  --poly-dark:#041226;    /* polyDarkBlue */
  --poly-beige:#EBE9E6;   /* polyBeige */
  --poly-green:#99E600;   /* polyGreen */
  --poly-magenta:#CC1461; /* polyMagenta */
  --poly-proxy:#7B7B7B;   /* proxy — Platzhalter/Neutralgrau */

  /* ---------- Rollen-Farben (Theming) ----------
     Module referenzieren NICHT mehr die Marken-Tokens direkt für Fläche
     und Vordergrund, sondern diese zwei Rollen. Ein Theme (unten) legt
     sie um → alle Module im Section-Wrapper erben automatisch.
     --poly-line ist KEIN fester Wert mehr, sondern wird aus ink+surface
     gemischt (siehe „Linienfarbe" unten) und folgt damit dem Theme.
     Akzente (green/magenta) bleiben Marken-Tokens (Hover/aktiv). */
  --surface: var(--poly-beige);   /* Modul-Hintergrund */
  --ink:     var(--poly-dark);    /* Text, Icons, Element-Vordergrund */
  /* Akzent = Hover/aktiv-Paar. Früher standen polyGreen/polyDarkBlue hart in
     jeder Hover-Regel; jetzt legt jedes Theme sein eigenes Paar fest. */
  --accent:     var(--poly-green);
  --accent-ink: var(--poly-dark);

  /* ---------- Font-Familien ---------- */
  --font-sans:"HGS3", system-ui, sans-serif;   /* Hurme Geometric Sans 3 */
  --font-mono:"HFM", ui-monospace, monospace;  /* Hurme FIN Mono 1b */
}

/* ---------- Abstände · Raster · Typo-Skala (Desktop/Tablet/Mobile) ----------
   EINE Quelle: build/tokens.json → build.py schreibt diese Region. Der
   Tokens-Reiter im Werkbank editiert die Werte (live). NICHT von Hand ändern. */
/* @tokens:start (generiert aus build/tokens.json — nicht von Hand editieren) */
:root{--poly-dark:#000F1E;--poly-beige:#EBE9E6;--poly-green:#99E600;--poly-magenta:#CC1461;--pad-min:5px;--pad-small:10px;--pad-medium:15px;--pad-medium-mobile:10px;--pad-big:30px;--pad-big-mobile:20px;--pad-ultra:90px;--pad-ultra-mobile:60px;--linewidth:1px;--grid-side:240px;--nav-h:120px;--nav-h-mobile:60px;--line-mix:50%;--line-mix-strong:50%;--h0-size:75px;--h0-lh:80px;--h0-ls:-0.02em;--h1-size:50px;--h1-lh:53px;--h1-ls:-0.02em;--h2-size:40px;--h2-lh:44px;--h2-ls:-0.02em;--h3-size:27px;--h3-lh:29px;--h3-ls:-0.02em;--body-size:19px;--body-lh:24px;--body-ls:-0.01em;--body-bold-size:19px;--body-bold-lh:24px;--body-bold-ls:-0.01em;--button-big-size:18px;--button-big-lh:22px;--button-big-ls:0em;--button-size:15px;--button-lh:20px;--button-ls:0em;--tag-size:13px;--tag-lh:20px;--tag-ls:0em;}@media (max-width:960px){:root{--h0-size:60px;--h0-lh:65px;--h0-ls:-0.02em;--h1-size:44px;--h1-lh:47px;--h1-ls:-0.02em;--h2-size:36px;--h2-lh:39px;--h2-ls:-0.02em;--h3-size:24px;--h3-lh:26px;--h3-ls:-0.02em;--body-size:19px;--body-lh:24px;--body-ls:-0.01em;--body-bold-size:19px;--body-bold-lh:24px;--body-bold-ls:-0.01em;--button-big-size:18px;--button-big-lh:22px;--button-big-ls:0em;--button-size:15px;--button-lh:20px;--button-ls:0em;--tag-size:13px;--tag-lh:20px;--tag-ls:0em;}}@media (max-width:480px){:root{--h0-size:48px;--h0-lh:52px;--h0-ls:-0.02em;--h1-size:30px;--h1-lh:33px;--h1-ls:-0.02em;--h2-size:26px;--h2-lh:29px;--h2-ls:-0.02em;--h3-size:23px;--h3-lh:26px;--h3-ls:-0.02em;--body-size:17px;--body-lh:22px;--body-ls:-0.01em;--body-bold-size:17px;--body-bold-lh:22px;--body-bold-ls:-0.01em;--button-big-size:16px;--button-big-lh:20px;--button-big-ls:0em;--button-size:14px;--button-lh:18px;--button-ls:0em;--tag-size:12px;--tag-lh:18px;--tag-ls:0em;}}@media (max-width:480px){:root{--pad-medium:var(--pad-medium-mobile);--pad-big:var(--pad-big-mobile);--pad-ultra:var(--pad-ultra-mobile)}}
/* @tokens:end */

/* Hinweis zur Mobile-Abstandsskala: der Block am Ende der generierten
   Region schaltet ab ≤480 --pad-medium/--pad-big/--pad-ultra auf ihre
   -mobile-Variante. Er wird von build.py.gen_token_css UND von
   werkbank.genTokenCss erzeugt (zeichengleich) — sonst überschreibt die
   Werkbank-Vorschau, die ihre Token-Region nach tokens.css injiziert,
   die Umschaltung wieder. Nicht von Hand hier ergänzen. */

/* Lange, unteilbare Wörter im Notfall brechen, statt aus dem
   Container zu laufen (entspricht word-break:break-word in Figma).
   „anywhere" (statt „break-word") reduziert auch die intrinsische
   Mindestbreite, damit Flex-/Grid-Elemente wirklich schrumpfen.
   overflow-wrap wird vererbt → gilt für allen Text. */
html{ overflow-wrap:anywhere; }

/* ---------- Text-Rasterung (Kantenglättung) ------------------
   Ohne diese Angabe glättet macOS Text gamma-korrigiert; die Stämme
   bekommen dadurch optisch Fleisch und die Schrift wirkt fetter als
   in Figma, das Text selbst in eine GPU-Textur zeichnet. Gemessen an
   der H1 (Hurme Geometric Sans 3 Bold, echter 700er-Schnitt, kein
   Faux-Bold): identische Geometrie, nur die Rasterung unterscheidet
   sich. „antialiased" schaltet auf die magerere Graustufen-Glättung
   und trifft die Figma-Anmutung.
   Beide Eigenschaften werden vererbt → html genügt für allen Text,
   inklusive der Vorschau-iframes der Werkbank (die laden tokens.css).
   Nicht auf Einzelmodule setzen: gemischte Glättung im selben Layout
   ist sichtbar.
------------------------------------------------------------- */
html{
  -webkit-font-smoothing:antialiased;   /* Safari/Chrome (macOS) */
  -moz-osx-font-smoothing:grayscale;    /* Firefox (macOS) */
}

/* ---------- Overlay-Bewegung ---------------------------------
   Dauer und Kurve des Overlay-Wipes (siehe module/col/col.css, module/col/overlay.js).
   Die Kurve startet flach (zweiter Kontrollwert 0.02) — die Bewegung setzt
   also weich ein und läuft weich aus, statt hart anzuspringen. Gemessener
   Fortschritt der Wipe-Kante bei 10/20/30/50/75 % der Dauer:
     cubic-bezier(.5,.02,.25,1)   2 ·  9 · 24 · 71 · 95 %   ← eingestellt
     cubic-bezier(.32,.08,.24,1)  6 · 22 · 45 · 79 · 96 %   (knackiger)
     cubic-bezier(.62,0,.3,1)     1 ·  5 · 13 · 59 · 94 %   (sehr weich)
     linear                      10 · 20 · 30 · 50 · 75 %
   Zu ist etwas schneller als auf: Schließen soll sich nicht nach Warten
   anfühlen.
   Von Hand einstellbar; sag Bescheid, wenn die Werte in den Tokens-Reiter
   der Werkbank sollen (dann müssen sie in build/tokens.json und beide
   Generatoren).
------------------------------------------------------------- */
:root{
  --ov-dur:.28s;                            /* Aufbau  (links → rechts) */
  --ov-dur-out:.22s;                        /* Abbau   (rechts → links) */
  --ov-ease:cubic-bezier(.5,.02,.25,1);
}

/* Seitengrund („Leinwand") — die Farbe, über der ein Overlay aufbaut.
   Nicht dasselbe wie --surface: eine Overlay-Seite kann ein eigenes Theme
   tragen (z.B. theme-dark). Läge dessen Fläche wie sonst auf <html>, wäre sie
   sofort da und der Wipe liefe unsichtbar dunkel auf dunkel — die Overlay-
   Fläche gehört deshalb auf <body> (das wird maskiert), und <html> trägt
   während der Bewegung diese neutrale Leinwand. Sie folgt dem Light/Dark-
   Modus, aber KEINEM Section-Theme: sie soll aussehen wie die Seite, von der
   man kommt. */
:root{ --canvas:var(--poly-beige); }
:root.poly-mode-dark{ --canvas:var(--poly-dark); }

/* ---------- Schraffur (Standard-Muster) ----------------------
   Leere Zellen, Video-/Bild-Platzhalter und col/pattern nutzen dasselbe
   45°-Linienmuster. Wichtig ist die KACHELUNG: ein reiner
   repeating-linear-gradient wird über die ganze Fläche gerastert, und weil
   der 135°-Verlauf mit Periode 16px in x/y auf 16·√2 = 22,63px fällt, landet
   jede Linie auf einer anderen Subpixel-Phase — sichtbar als unterschiedlich
   dicke, unruhige Linien (gemessen: Tinte pro Linie 80…160 statt konstant).
   Deshalb wird das Muster als Bild EINER Kachel definiert und über
   background-size auf ein ganzzahliges Raster gekachelt: die Kachel wird
   einmal gerastert und dann wiederholt → jede Linie identisch (gemessen
   ±0 bei DPR 1/1,5/2/3). Kachel 23px = 16·√2 gerundet, die Verlaufsperiode
   folgt daraus als 23px/√2 — per calc(), damit keine gerundete Kommazahl
   in zwei Renderern gespiegelt werden muss.
------------------------------------------------------------- */
:root{
  --hatch-pitch:23px;                 /* x/y-Raster der Kachel (ganzzahlig!) */
  --hatch-angle:135deg;
  --hatch-line:1px;
}
/* WICHTIG: die Fläche zwischen den Linien kommt NICHT aus dem Verlauf, sondern
   als background-color. Stand die Flächenfarbe als Verlaufsstopp drin, wurde
   sie mitinterpoliert und gerastert — gemessen: innerhalb des Musters lagen
   neben #EBE9E6 auch #EAE8E5-Pixel, also ein Wert daneben. In Safari fällt die
   Abweichung größer aus (anderer Interpolationsraum), sichtbar als „das Blau
   im Muster hat einen anderen Ton als die Fläche daneben". Mit
   background-color wird die Fläche exakt wie jede andere Modulfläche gemalt,
   und nur die 1px-Linien kommen aus dem Verlauf — der Lückenstopp ist deshalb
   `transparent`. Der harte Stopp am Kachelrand bleibt hart, es gibt keine
   Interpolation und damit auch keinen Farbsaum. */
.poly-hatch, .col-grid-cards__filler, .col-grid__filler{
  background-color:var(--surface);
  background-image:repeating-linear-gradient(var(--hatch-angle),
    var(--poly-line) 0 var(--hatch-line),
    transparent var(--hatch-line) calc(var(--hatch-pitch) / 1.41421356));
  background-size:var(--hatch-pitch) var(--hatch-pitch);
}

/* ============================================================
   Themes — feste Farbpaare (surface/ink)
   Auf einen Section-Wrapper gesetzt: legt --surface/--ink um UND
   malt die Fläche. Alle Module darin erben; die Linienfarbe wird daraus
   gemischt (siehe Block darunter) und folgt dem Theme mit.
   Default (ohne Klasse) = hell: surface polyBeige / ink polyDarkBlue.
   ============================================================ */
.theme-dark{        --surface:var(--poly-dark);    --ink:var(--poly-beige);
                    --accent:var(--poly-green);    --accent-ink:var(--poly-dark); }
/* green kehrt den Akzent um — auf grüner Fläche wäre grüner Hover unsichtbar. */
.theme-green{       --surface:var(--poly-green);   --ink:var(--poly-dark);
                    --accent:var(--poly-dark);     --accent-ink:var(--poly-green); }
.theme-magenta{     --surface:var(--poly-magenta); --ink:var(--poly-beige);
                    --accent:var(--poly-green);    --accent-ink:var(--poly-dark); }
.theme-dark-green{  --surface:var(--poly-dark);    --ink:var(--poly-green);      /* Highlight-Alternative */
                    --accent:var(--poly-green);    --accent-ink:var(--poly-dark); }
.theme-dark, .theme-green, .theme-magenta, .theme-dark-green{
  background:var(--surface); color:var(--ink);
}

/* ---------- Light/Dark-Modus --------------------------------
   Der Umschalter im Menü (module/col/mode.js) setzt `poly-mode-dark` auf <html> und
   dreht damit NUR das Default-Paar um. Sections mit eigenem Theme
   (`theme-magenta`, `theme-dark-green`, …) bleiben unberührt — deshalb die
   :not()-Kette: eine Seite, die selbst schon ein Theme trägt, wird vom Modus
   nicht überstimmt.
   Der Startwert kommt aus prefers-color-scheme, danach gilt die eigene Wahl
   (localStorage). Gesetzt wird die Klasse per Inline-Skript im <head>, damit
   die Seite nicht erst hell aufblitzt.
------------------------------------------------------------- */
:root.poly-mode-dark:not(.theme-dark):not(.theme-green):not(.theme-magenta):not(.theme-dark-green){
  --surface:var(--poly-dark);  --ink:var(--poly-beige);
  --accent:var(--poly-green);  --accent-ink:var(--poly-dark);
  --logo-ink:var(--poly-green);
}
/* Das Logo ist das einzige Element, das die Marke trägt — im Dark-Modus steht
   es grün statt beige. Über eine eigene Variable, damit die Ausnahme an EINER
   Stelle liegt statt in jeder Logo-Regel. Hell folgt es der Textfarbe, und
   Sections mit eigenem Theme setzen sie zurück — nach derselben Regel wie
   oben (der Modus überstimmt kein gesetztes Theme). Wichtig ist die
   Rücksetzung vor allem auf theme-green: grünes Logo auf grüner Fläche wäre
   unsichtbar. */
:root{ --logo-ink:var(--ink); }
.theme-dark, .theme-green, .theme-magenta, .theme-dark-green{ --logo-ink:var(--ink); }

/* ---------- Linienfarbe (theme-abhängig) --------------------
   Die Linien sollen zum Theme passen: statt einem festen Grau ist die
   Linienfarbe eine MISCHUNG aus ink und surface — `--line-mix` = Anteil ink
   (Token, im Werkbank editierbar). `--poly-line-strong` ist dieselbe Mischung
   mit höherem Anteil, für Elemente, die sich abheben müssen (elem/tag,
   mod/form-text, mod/form-select).

   Warum MISCHUNG und nicht Transparenz: das ganze Linienmodell lebt von
   −1px-Nähten, benachbarte Rahmen liegen also exakt übereinander. Zwei
   halbtransparente Linien im selben Pixel addieren sich zu einer dunkleren —
   jede Naht sähe kräftiger aus als eine einzelne Linie. Eine deckende
   Mischung sieht auf der Fläche identisch aus, ist beim Überlappen aber
   idempotent.

   Warum die Deklaration NEBEN den Theme-Klassen steht: `var()` in einem
   Custom Property wird auf dem Element aufgelöst, das die Eigenschaft
   DEKLARIERT. Stünde sie nur in :root, käme immer das Root-ink heraus und
   das Theme hätte keine Wirkung. Deshalb deklariert jede Theme-Klasse ihre
   eigene Linienfarbe mit — der Rest der Seite erbt sie.

   Der @supports-Block ist die Rückfallebene: Browser ohne color-mix
   (vor Safari 16.2 / Chrome 111) behalten die festen Hex-Werte. Der
   Fallback muss so herum stehen — bei Custom Properties greift der übliche
   „ungültige Deklaration wird verworfen"-Trick nicht, weil sie fast jeden
   Wert schlucken.
------------------------------------------------------------- */
:root, .theme-dark, .theme-green, .theme-magenta, .theme-dark-green{
  --poly-line:#999999;
  --poly-line-strong:#6B6B6B;
}
@supports (color: color-mix(in srgb, red 50%, blue)){
  :root, .theme-dark, .theme-green, .theme-magenta, .theme-dark-green{
    --poly-line:        color-mix(in srgb, var(--ink) var(--line-mix, 40%),        var(--surface));
    --poly-line-strong: color-mix(in srgb, var(--ink) var(--line-mix-strong, 65%), var(--surface));
  }
}

/* ============================================================
   Typo-Utility-Klassen
   Verwendung: <h1 class="t-h1">…</h1>, <p class="t-body">…</p>
   ============================================================ */
.t-h0{font-family:var(--font-sans);font-weight:700;font-size:var(--h0-size);line-height:var(--h0-lh);letter-spacing:var(--h0-ls);margin:0;color:var(--ink);}
.t-h1{font-family:var(--font-sans);font-weight:700;font-size:var(--h1-size);line-height:var(--h1-lh);letter-spacing:var(--h1-ls);margin:0;color:var(--ink);}
.t-h2{font-family:var(--font-sans);font-weight:700;font-size:var(--h2-size);line-height:var(--h2-lh);letter-spacing:var(--h2-ls);margin:0;color:var(--ink);}
.t-h3{font-family:var(--font-sans);font-weight:700;font-size:var(--h3-size);line-height:var(--h3-lh);letter-spacing:var(--h3-ls);margin:0;color:var(--ink);}
.t-body{font-family:var(--font-sans);font-weight:400;font-size:var(--body-size);line-height:var(--body-lh);letter-spacing:var(--body-ls);margin:0;color:var(--ink);}
.t-body-bold{font-family:var(--font-sans);font-weight:600;font-size:var(--body-bold-size);line-height:var(--body-bold-lh);letter-spacing:var(--body-bold-ls);margin:0;color:var(--ink);}
.t-button-big{font-family:var(--font-mono);font-weight:500;font-size:var(--button-big-size);line-height:var(--button-big-lh);letter-spacing:var(--button-big-ls);margin:0;color:var(--ink);}
.t-button{font-family:var(--font-mono);font-weight:500;font-size:var(--button-size);line-height:var(--button-lh);letter-spacing:var(--button-ls);margin:0;color:var(--ink);}
.t-tag{font-family:var(--font-mono);font-weight:500;font-size:var(--tag-size);line-height:var(--tag-lh);letter-spacing:var(--tag-ls);margin:0;color:var(--ink);}

/* ============================================================
   Linien-Layout (Überlappung)
   Kachelnder Container: Bausteine behalten ihren Rahmen, benachbarte
   Zellen überlappen sich um 1px → aus zwei Linien wird eine. Der
   Container zeichnet keinen eigenen Rahmen (die Zell-Rahmen bilden
   ihn). Standard für 1D-Kachelung; echtes 2D-Raster/Umbruch weiter
   via gap+Hintergrund (siehe comp/bento). Details: linien-register.md.
   ============================================================ */
.lines-v{ display:flex; flex-direction:column; align-items:stretch; }
.lines-v > * + *{ margin-top:calc(-1 * var(--linewidth)); }
.lines-h{ display:flex; flex-direction:row; align-items:stretch; }
.lines-h > * + *{ margin-left:calc(-1 * var(--linewidth)); }
