/* dennismit2n.github.io — landing page styles */

/* ==================================================================
   Palette ggaallaaxxyy77 — die Markenebene
   Quelle: colors.css (eine Primärfarbe + sieben Akzentfarben, je elf
   Stufen 50–950). Hier stehen NUR die Stufen, die die Seite wirklich
   benutzt, und zwar EINMAL: ein Farbwert ist in beiden Darstellungen
   derselbe, nur seine Rolle wechselt. Die drei Themen-Blöcke weiter
   unten verweisen darauf, statt Hex-Werte zu wiederholen — genau dort
   sind schon zweimal Farben in einem Block vergessen worden
   (--zaehlwerk am 31.07.2026, --spectro am 13.09.2026).

   Warum ausgerechnet diese Stufen: gegen die echten Flächen dieser
   Seite gerechnet fallen die Stufen 600 und 700 in BEIDEN Darstellungen
   unter AA. Hell bleiben damit 800–950, dunkel 50–500. Die leuchtenden
   Mittelstufen kann nur tragen, was Dekoration ist — der Familienbalken.
   ================================================================== */
:root {
  --gx-primary-50:  #CDD0FF;  /* Pledge-Pille hell */
  --gx-primary-200: #B4B5FF;  /* Pledge-Text dunkel — 7,40 auf der Pille */
  --gx-primary-300: #A5A5FF;  /* Akzent dunkel — 7,78 Karte / 8,44 Grund */
  --gx-primary-700: #6D54FB;  /* Familienbalken dunkel, Deko */
  --gx-primary-800: #5F4FD4;  /* Familienbalken hell, Deko */
  --gx-primary-900: #524AAB;  /* Akzent hell — 7,18 Karte / 6,51 Grund */
  --gx-primary-950: #464480;  /* Pledge-Text hell — 5,86 auf der Pille */
  --gx-violet-300:  #AFA1FF;  /* accent-2: Lavendel-Segment dunkel */
  --gx-violet-500:  #967AFF;  /* accent-2: Lavendel-Segment hell */
  --gx-sky-200:     #75C7FF;  /* accent-4: Eis-Segment, beide Darstellungen */
}

:root {
  color-scheme: light;
  --accent: var(--gx-primary-900);
  --accent-strong: var(--gx-primary-950);
  --accent-fill: var(--gx-primary-800);
  --accent-soft: #CBCDF9;
  --ice: var(--gx-sky-200);
  --lavender: var(--gx-violet-500);
  /* Heller Modus „gedämpft“ (Dennis, 30.10.2026: „weiß zu hell, möchte das auch
     dunkler“). Grund, Kachel und Rahmen liegen weiter auf dem Farbton der Palette
     (283°), aber deutlich tiefer als vorher (#F2F3F8 / #FFFFFF): Grund OKLCH
     L 0,893, Kachel L 0,927. Möglich wurde das nur, weil alle Kachelfarben unten
     mitgewandert sind — die alten fielen gegen diesen Grund bis auf 2,36:1. */
  --bg: #DADBE6;
  --panel: #E5E6EF;
  /* Die Kacheln lassen 12 % der Aurora durch (vorher 6 %): auch ihr Grund soll
     leuchten. Alle Farben darauf sind gegen diesen Schleier über dem dunkelsten
     Aurora-Punkt gerechnet, nicht gegen die blanke Kachel. */
  --panel-veil: rgba(229, 230, 239, 0.88);
  /* Aurora hell: viel Farbe, kaum Helligkeitsverlust (L 0,845–0,87 auf einem Grund
     von 0,893). -a ist die Deckkraft. Prüfnachweis im Aurora-Block. */
  --au-1: #C4C6FF; --au-1-a: 0.55;
  --au-2: #DAC0FB; --au-2-a: 0.5;
  --au-3: #A8DCFC; --au-3-a: 0.5;
  --au-4: #EEC5E9; --au-4-a: 0.35;
  /* Konstruktionsraster wie im Bauplan der Profil-README (Linien in primary-900) */
  --raster-fein: rgba(82, 74, 171, 0.045);
  --raster-grob: rgba(82, 74, 171, 0.09);
  /* Verlauf des Claims wie im README-Banner (Lila → Eisblau → Violett). Hell jeder
     Stopp auf 4,6:1 gegen den dunkelsten Aurora-Punkt gerechnet. */
  --claim-1: #5249AA;
  --claim-2: #005C89;
  --claim-3: #6F34BC;
  /* Leuchtkraft: Anteil der Kachelfarbe im Schein um Symbol, Kappe und Rahmen */
  --glow: 38%;
  --glow-hover: 60%;
  --haze: 0.10;
  --name-glow: 0px;
  /* Datum auf den Mini-Kacheln: Mit 0,85 Deckkraft kam es im Hellen auf
     3,89:1, 0,93 hält 4,57 auf --bg. Im Dunkeln bleibt es bei 0,85. */
  --date-alpha: 0.93;
  --text: #1A1932;
  --text-soft: #535479;
  --border: #C3C4D8;
  /* Kachelfarben, Neufassung 30.10.2026 (Dennis: „die Farben allgemein mehr Glow,
     und die, die sich ähnlich sind, jeweils die Nuancen anpassen“). Die Farbtöne
     sind auseinandergezogen: RAM-cooler wandert von Eisblau zu Azur (passt jetzt
     zum Blau seines Symbols), Collective-Calc zu Smaragd, Zählwerk Richtung
     Gelbgrün, shrinkling zu Purpur, fontART zu Magenta, der Besucher-Ticker zu
     Elektro-Indigo. Kleinster Abstand zweier Kachelfarben im Dunkeln (OKLab):
     vorher 0,036 (RAM-cooler ~ Heizwarte), jetzt 0,071.
     Hell ist jede Farbe die hellste ihres Farbtons, die gegen --bg UND gegen den
     Kachelschleier über dem dunkelsten Aurora-Punkt (#E2E3F0) 4,6:1 hält; das gilt
     auch für jeden Verlaufsstopp (schlechtester Wert 4,57). Damit sind auch die
     alten Ausreißer erledigt (Prismaticals Regenbogen 3,1, bigday 2,9, Rad 4,3).
     Dunkel hält jede Farbe gegen --panel, --bg und den Schleier über dem hellsten
     Aurora-Punkt (#181F3F) mindestens 5,8:1, jeder Verlaufsstopp 4,6:1.
     Methode: OKLCH bei festem Farbton, Chroma per Bisektion in den Gamut geklemmt,
     Helligkeit per Bisektion auf das Kontrastziel. Wer den Grund oder die Aurora
     verschiebt, rechnet diese Werte neu — sie sind Prüfnachweis, keine Verzierung.
     Prismatical, Spectroton, Heizwarte und Pocketsum tragen dazu ihren Verlauf
     (Name und Kappe), der Vollton daneben ist nur Anker für Rahmen und Knopf.
     Fadenkreuz bleibt in beiden Darstellungen schwarz (siehe .tool-card.tool-fadenkreuz);
     --fadenkreuz gilt nur für seinen Abschnitt auf werkstatt.html. Die Kappe von
     Gaming ist Schmuck, keine Schrift, und folgt Dennis' Farben (--gm-1 bis 4). */
  --wifi: #006A79;
  --shrink: #8724DC;
  --bigday: #845600;
  --ram: #0061AF;
  --rad: #C10037;
  --collective: #006E43;
  --zaehlwerk: #4C6900;
  --fontart: #AA0DA5;
  --fontart-flow: linear-gradient(100deg, #8A6A00, #AA0DA5, #8A6A00, #AA0DA5, #8A6A00);
  --ticker: #4648E5;
  --masterprompt: #A73D00;
  --prisma: #6349C9;
  --prisma-flow: linear-gradient(100deg, #C2001F, #A14300, #656200, #006B67, #6145D5);
  --spectro: #006C64;
  --spectro-flow: linear-gradient(100deg, #006B67, #005D59, #004F4C, #00423F, #003533);
  --heizwarte: #03678E;
  --heizwarte-flow: linear-gradient(100deg, #00678E, #007015, #8F5000, #AE3600, #C30010);
  --fadenkreuz: #101512;
  --fadenkreuz-flow: linear-gradient(#33ff88, #33ff88);
  --pocketsum: #1A1932;
  --pocketsum-flow: linear-gradient(90deg, #5A4FC0 0 20%, #9D4600 20% 40%, #00659B 40% 60%, #006F31 60% 80%, #C1003A 80%);
  --gaming: #3f3f46;
  --gm-1: #d4148a;
  --gm-2: #c8102e;
  --gm-3: #1570ef;
  --gm-4: #00b35a;
  --gaming-flow: linear-gradient(90deg, var(--gm-1), var(--gm-2), var(--gm-3), var(--gm-4));
  --craftionary: #086D57;
  --vault: #765C00;
  --ruestkammer: #9A4900;

  --mods: #7A2E6D;
  --shadow: 0 10px 30px rgba(26, 25, 50, 0.14);
}

/* Dark theme comes in two doors with identical furniture:
   1) system preference (unless the user forced light),
   2) the theme dropdown forcing dark.
   Keep both blocks in sync! (Seit 30.10.2026 stehen sie Zeile für Zeile gleich,
   damit ein Vergleich per Auge reicht.)
   --bg #0F0F21, --panel #181831 und --border #2D2C4F liegen auf 282,8°: eine
   violette Nacht, die sich nicht vordrängt. --text #E2E2F6 ist ein Hauch
   Lila-Blassblau statt Papierweiß.
   Neu am 30.10.2026: Die Aurora leuchtet kräftiger, deshalb mussten die zwei
   Schriften heller werden, die frei auf ihr stehen: --text-soft #9C9ECD → #B7B9DC
   und --accent primary-300 → primary-200 (#B4B5FF). Beide halten 4,6:1 gegen den
   hellsten Punkt, den zwei übereinanderliegende Wolken erzeugen (#1A4796); die
   alten Werte kamen dort auf 3,44 und 3,96. Die Kacheln lassen 14 % Aurora durch
   (vorher 6 %). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --accent: var(--gx-primary-200);
    --accent-strong: var(--gx-primary-200);
    --accent-fill: var(--gx-primary-700);
    --accent-soft: #291F67;
    --lavender: var(--gx-violet-300);
    --bg: #0F0F21;
    --panel: #181831;
    --panel-veil: rgba(24, 24, 49, 0.86);
    --au-1: #4B3CAB; --au-1-a: 0.7;
    --au-2: #502684; --au-2-a: 0.75;
    --au-3: #015BA6; --au-3-a: 0.55;
    --au-4: #781B7E; --au-4-a: 0.4;
    --raster-fein: rgba(165, 165, 255, 0.05);
    --raster-grob: rgba(165, 165, 255, 0.1);
    --claim-1: #A5A5FF;
    --claim-2: #75C7FF;
    --claim-3: #AFA1FF;
    --glow: 62%;
    --glow-hover: 85%;
    --haze: 0.17;
    --name-glow: 16px;
    --date-alpha: 0.85;
    --text: #E2E2F6;
    --text-soft: #B7B9DC;
    --border: #2D2C4F;
    --wifi: #23E3FA;
    --shrink: #C28DFF;
    --bigday: #FFC334;
    --ram: #6CB2FF;
    --rad: #FF7886;
    --collective: #00E698;
    --zaehlwerk: #BEE800;
    --fontart: #F96EF0;
    --fontart-flow: linear-gradient(100deg, #EAC54F, #F96EF0, #EAC54F, #F96EF0, #EAC54F);
    --ticker: #7D95FF;
    --masterprompt: #FF8F4B;
    --prisma: #CCC6FF;
    --prisma-flow: linear-gradient(100deg, #ff9e95, #ffae55, #cfd149, #00e8df, #bfb9ff);
    --spectro: #01DFC8;
    --spectro-flow: linear-gradient(100deg, #8bfff8, #48e8e0, #13ccc5, #00b0a9, #129993);
    --heizwarte: #A7E3FF;
    --heizwarte-flow: linear-gradient(100deg, #7dd3fc, #86efac, #fde047, #fdba74, #f87171);
    --fadenkreuz: #33ff88;
    --fadenkreuz-flow: linear-gradient(#33ff88, #33ff88);
    --pocketsum: #E2E2F6;
    --pocketsum-flow: linear-gradient(90deg, #A5A5FF 0 20%, #FFC97A 20% 40%, #75C7FF 40% 60%, #7EE0A0 60% 80%, #FF9FB5 80%);
    --gaming: #a1a1aa;
    --gm-1: #ff2bd6;
    --gm-2: #ff3b5c;
    --gm-3: #2f8bff;
    --gm-4: #33ff88;
    --gaming-flow: linear-gradient(90deg, var(--gm-1), var(--gm-2), var(--gm-3), var(--gm-4));
    --craftionary: #63CEAF;
    --vault: #FDD711;
    --ruestkammer: #FF9948;

    --mods: #E08AD0;
    --shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --accent: var(--gx-primary-200);
  --accent-strong: var(--gx-primary-200);
  --accent-fill: var(--gx-primary-700);
  --accent-soft: #291F67;
  --lavender: var(--gx-violet-300);
  --bg: #0F0F21;
  --panel: #181831;
  --panel-veil: rgba(24, 24, 49, 0.86);
  --au-1: #4B3CAB; --au-1-a: 0.7;
  --au-2: #502684; --au-2-a: 0.75;
  --au-3: #015BA6; --au-3-a: 0.55;
  --au-4: #781B7E; --au-4-a: 0.4;
  --raster-fein: rgba(165, 165, 255, 0.05);
  --raster-grob: rgba(165, 165, 255, 0.1);
  --claim-1: #A5A5FF;
  --claim-2: #75C7FF;
  --claim-3: #AFA1FF;
  --glow: 62%;
  --glow-hover: 85%;
  --haze: 0.17;
  --name-glow: 16px;
  --date-alpha: 0.85;
  --text: #E2E2F6;
  --text-soft: #B7B9DC;
  --border: #2D2C4F;
  --wifi: #23E3FA;
  --shrink: #C28DFF;
  --bigday: #FFC334;
  --ram: #6CB2FF;
  --rad: #FF7886;
  --collective: #00E698;
  --zaehlwerk: #BEE800;
  --fontart: #F96EF0;
  --fontart-flow: linear-gradient(100deg, #EAC54F, #F96EF0, #EAC54F, #F96EF0, #EAC54F);
  --ticker: #7D95FF;
  --masterprompt: #FF8F4B;
  --prisma: #CCC6FF;
  --prisma-flow: linear-gradient(100deg, #ff9e95, #ffae55, #cfd149, #00e8df, #bfb9ff);
  --spectro: #01DFC8;
  --spectro-flow: linear-gradient(100deg, #8bfff8, #48e8e0, #13ccc5, #00b0a9, #129993);
  --heizwarte: #A7E3FF;
  --heizwarte-flow: linear-gradient(100deg, #7dd3fc, #86efac, #fde047, #fdba74, #f87171);
  --fadenkreuz: #33ff88;
  --fadenkreuz-flow: linear-gradient(#33ff88, #33ff88);
  --pocketsum: #E2E2F6;
  --pocketsum-flow: linear-gradient(90deg, #A5A5FF 0 20%, #FFC97A 20% 40%, #75C7FF 40% 60%, #7EE0A0 60% 80%, #FF9FB5 80%);
  --gaming: #a1a1aa;
  --gm-1: #ff2bd6;
  --gm-2: #ff3b5c;
  --gm-3: #2f8bff;
  --gm-4: #33ff88;
  --gaming-flow: linear-gradient(90deg, var(--gm-1), var(--gm-2), var(--gm-3), var(--gm-4));
  --craftionary: #63CEAF;
  --vault: #FDD711;
  --ruestkammer: #FF9948;

  --mods: #E08AD0;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}

[hidden] { display: none !important; }

* { box-sizing: border-box; }

/* Die Grundfarbe sitzt auf html, nicht auf body. Nötig ist das nicht: solange
   html gar keinen Hintergrund trägt, reicht der Browser den von body an die
   Leinwand weiter und malt die body-Box selbst nicht mehr — die Aurora wäre
   auch so zu sehen. Es steht hier, weil diese Fortpflanzung in dem Moment
   endet, in dem html irgendeinen Hintergrund bekommt, und dann verschwände
   die Ebene ohne erkennbaren Grund. Lieber ausdrücklich als raffiniert. */
html { background: var(--bg); }

/* Zwei Schriften, zwei Rollen: Lesen und Bedienen in der Systemschrift,
   Namen und Überschriften in Fraunces (Block „Überschriftenschrift“ am
   Ende dieser Datei). */
:root {
  --font-text: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-schild: "Fraunces Werkstatt", "Fraunces Ersatz", var(--font-text);
}

body {
  margin: 0;
  font-family: var(--font-text);
  background: transparent;
  color: var(--text);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* ==================================================================
   Aurora + Bauplan, Neufassung 30.10.2026 (Dennis: „noch mehr glowy, es soll
   irgendwie verstrahlt wirken, Bewegung wäre auch nice, so wie die Banner auf
   der Profil-README“). Vier weich gezeichnete Farbwolken wandern langsam über
   den Grund, darüber liegt still das Konstruktionsraster der Werkstattzeichnung
   aus der README.

   Leuchten ohne Lesbarkeitsverlust: Die Wolken tragen viel Farbe, aber wenig
   Helligkeit (dunkel OKLCH L 0,38–0,47 bei Chroma bis 0,17, hell L 0,845–0,87
   auf einem Grund von 0,893). Freistehende Schrift (Markenname,
   Hero-Unterzeile, Mehr-Zeile, Fußzeile, Platzhalter-Kacheln, Navigation auf
   werkstatt.html) ist gegen den UNGÜNSTIGSTEN Fall gerechnet: zwei beliebige
   Wolken voll deckend übereinander. Hell ist das der dunkelste Punkt #CEC9F8:
   --text-soft 4,59, --accent 4,57, --text 10,88. Dunkel ist es der hellste
   Punkt #1A4796: --text-soft 4,61, --accent 4,61, --text 6,90.
   Weil der Nachweis jede Überlagerung abdeckt, dürfen die Wolken frei wandern
   (die alte Ebene durfte das nicht, ihr Nachweis hing an der Lage). Wer Farbe
   oder Deckkraft ändert, rechnet beide Fälle neu: Einzelwolke UND Paar.

   Die vierte Wolke ist .aurora::before, das Raster .aurora::after — so
   brauchen die drei Seiten kein neues Markup.
   overflow: hidden ist kein Schmuck: die Wolken ragen absichtlich über den
   Rand, ohne die Klammer ließe sich die Seite seitlich wischen.
   ================================================================== */
.aurora {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.aurora span,
.aurora::before {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(70px);
}
.aurora::before { content: ''; }
.au-1 { width: 64vw; height: 62vh; top: -18vh; left: -16vw; background: var(--au-1); opacity: var(--au-1-a); }
.au-2 { width: 60vw; height: 62vh; bottom: -20vh; right: -14vw; background: var(--au-2); opacity: var(--au-2-a); }
.au-3 { width: 40vw; height: 44vh; top: 8vh; right: -8vw; background: var(--au-3); opacity: var(--au-3-a); }
.aurora::before { width: 38vw; height: 42vh; bottom: -4vh; left: -10vw; background: var(--au-4); opacity: var(--au-4-a); }
/* Konstruktionsraster: fein alle 24 px, grob alle 120 px, wie im Bauplan der
   Profil-README. Es steht still und läuft nach unten aus. */
.aurora::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--raster-grob) 1px, transparent 1px),
    linear-gradient(90deg, var(--raster-grob) 1px, transparent 1px),
    linear-gradient(var(--raster-fein) 1px, transparent 1px),
    linear-gradient(90deg, var(--raster-fein) 1px, transparent 1px);
  background-size: 120px 120px, 120px 120px, 24px 24px, 24px 24px;
  -webkit-mask-image: linear-gradient(#000 45%, transparent 100%);
  mask-image: linear-gradient(#000 45%, transparent 100%);
}

/* Positive Abfrage: Bewegung gibt es nur, wo niemand sie abbestellt hat. Die
   Wolken wandern auf eigenen Bahnen mit eigener Dauer, damit sich das Bild nie
   sichtbar wiederholt. Nur transform wird bewegt: das übernimmt die Grafikkarte,
   die Unschärfe wird dabei nicht neu gerechnet. */
@media (prefers-reduced-motion: no-preference) {
  .au-1 { animation: au-wandern-1 34s ease-in-out infinite alternate; }
  .au-2 { animation: au-wandern-2 41s ease-in-out infinite alternate; }
  .au-3 { animation: au-wandern-3 29s ease-in-out infinite alternate; }
  .aurora::before { animation: au-wandern-4 47s ease-in-out infinite alternate; }
  .aurora span,
  .aurora::before { will-change: transform; }
}
@keyframes au-wandern-1 { 0% { transform: translate(0, 0) scale(1); } 50% { transform: translate(16vw, 10vh) scale(1.12); } 100% { transform: translate(6vw, 24vh) scale(0.94); } }
@keyframes au-wandern-2 { 0% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-18vw, -12vh) scale(1.08); } 100% { transform: translate(-6vw, -26vh) scale(0.95); } }
@keyframes au-wandern-3 { 0% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-24vw, 20vh) scale(1.15); } 100% { transform: translate(-40vw, 6vh) scale(1); } }
@keyframes au-wandern-4 { 0% { transform: translate(0, 0) scale(1); } 50% { transform: translate(22vw, -20vh) scale(1.1); } 100% { transform: translate(38vw, -8vh) scale(0.92); } }

/* Keine Obergrenze (Dennis, 31.10.2026, vorher 1680 px): Wer mit Strg und
   Minus verkleinert, macht die Seite in CSS-Pixeln breiter, und dann sollen
   Kachelspalten dazukommen, statt dass vier Spalten in der Mitte schrumpfen.
   Kopf und Hero bleiben schmal (.hero), das Kachelraster nutzt die Breite,
   mit einem halben freien Kachelplatz links und rechts (siehe .tools).
   werkstatt.html deckelt weiter über .page-wide. */
.page {
  min-height: 100dvh;
  margin: 0 auto;
  padding: 20px 20px 36px;
  display: flex;
  flex-direction: column;
}

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Header */
/* Der Kopf darf umbrechen. Ein Auswahlfeld ist so breit wie sein längster
   Eintrag, und der wechselt mit der Sprache (Russisch „Системная“ macht das
   Feld 25 px breiter als im Deutschen) — eine Rechnung „passt schon“ hält
   keine neue Übersetzung aus. Reicht die Zeile nicht, rutschen die Felder
   in eine zweite Zeile statt über den Rand, rechtsbündig dank
   margin-left: auto. */
.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 10px 12px;
}

.brand { display: flex; align-items: center; gap: 10px; }
.brand-icon { width: 30px; height: 30px; display: block; }
.brand-name { font-weight: 600; font-size: 0.95rem; letter-spacing: 0.01em; color: var(--text-soft); }

.header-controls { display: flex; align-items: center; gap: 8px; margin-left: auto; }

#langSelect,
#themeSelect {
  font: inherit;
  font-size: 0.9rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 10px;
}

/* Hero */
.hero { max-width: 920px; margin: 0 auto; text-align: center; padding: 54px 8px 42px; }

/* min(…, 13vw): Bei großer Browserschrift (24 px) auf 320 px ragte das
   längste Wort sonst über den Rand — „herramientas“ in Fraunces, das
   russische „инструменты,“ schon immer. Bei normaler Schrift greift die
   Grenze nie (30 px Schriftgröße gegen 41 px Grenze). */
.hero h1 {
  font-size: min(clamp(1.9rem, 5vw, 2.7rem), 13vw);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 14px;
}
/* Der Claim im Verlauf des README-Banners (Lila → Eisblau → Violett). Positive
   Abfrage wie bei den Verlaufsnamen: ohne background-clip bleibt er einfarbig. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero h1,
  .wk-hero h1 {
    background-image: linear-gradient(100deg, var(--claim-1), var(--claim-2) 55%, var(--claim-3));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.hero-sub { margin: 0 0 20px; color: var(--text-soft); font-size: 1.08rem; }

/* Radius = halbe Höhe des zweizeiligen Schilds (zwei Zeilen à 1.55em plus
   2 × 10 px Innenabstand). Zweizeilig ist es am Desktop in jeder Sprache und
   sieht dort aus wie eine Pille. Vorher stand hier 999px: das kappt der
   Browser auf die halbe Höhe, am Telefon mit drei bis sieben Zeilen wurden
   die Enden so zu Halbkreisen über die ganze Höhe — ein Oval, aus dessen
   Rundung bei 320 px in fünf Sprachen Text herausragte. */
.pledge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--accent-soft);
  color: var(--accent-strong);
  border-radius: calc(1.55em + 10px);
  padding: 10px 18px;
  font-size: 0.95rem;
  font-weight: 500;
  text-align: left;
  max-width: 100%;
  margin: 0;
}
.pledge svg { flex: none; }

.family-bar {
  display: flex;
  width: 200px;
  height: 6px;
  margin: 30px auto 0;
  border-radius: 999px;
  overflow: hidden;
  box-shadow: 0 0 18px -3px var(--ice);
}
.family-bar span { display: block; height: 100%; }
.fb-royal { flex: 3; background: var(--accent-fill); }
.fb-ice { flex: 1.6; background: var(--ice); }
.fb-lav { flex: 1; background: var(--lavender); }
/* gaming.html: statt der drei Markenfarben der Verlauf der Gaming-Kachel */
.gaming-bar { background: var(--gaming-flow); }
a.brand { text-decoration: none; color: inherit; }
.hero-back { margin: 0; }
.hero-back a { color: var(--accent); font-weight: 500; text-decoration: none; }
.hero-back a:hover { text-decoration: underline; }

/* Toolbox */
.tools h2 {
  display: flex;
  align-items: center;
  gap: 10px;
  /* „De gereedschapskist“ und „Ящик с инструментами“ passen bei 24 px
     Browserschrift nicht in 320 px: erst die Grenze (bei normaler Schrift
     wirkungslos), anywhere nur noch als letzte Rettung gegen Überlauf. */
  font-size: min(1.35rem, 8.5vw);
  margin: 22px 0 18px;
  overflow-wrap: anywhere;
}
/* Gezeichnetes Symbol statt Emoji (Dennis, 30.10.2026): die flache Werkzeugkiste
   aus dem Titelbild der Profil-README, auf gaming.html ein Gamepad, beide im
   Verlauf ihrer Seite. Emoji in Überschriften lesen sich als KI-Muster. */
.tb-icon { width: 40px; height: 30px; flex: none; overflow: visible; }

/* Links und rechts bleibt ein halber Kachelplatz frei (Dennis, 31.10.2026:
   die Kacheln standen zu nah am Rand, ein ganzer Platz war zu viel). Bei n
   Kachelspalten rechnet das Raster mit n + 1 gleich breiten Plätzen und teilt
   einen davon auf beide Ränder auf. Ein Platz samt Lücke ist
   (Breite + Lücke) / (n + 1) breit, jeder Rand die Hälfte davon, und den
   bekommen Überschrift, Raster und Mehr-Zeile. Jeder Platz bleibt mindestens
   280 px breit, n richtet sich nach der Breite des Abschnitts:
     ab 1780 px   5 Kachelspalten, alle 300 px eine mehr, bis 12 Spalten
                  ab 3880 px (so breit wird es nur beim Verkleinern)
     ab 1480 px   4 Kachelspalten
     ab 1180 px   3 Kachelspalten
     ab  880 px   2 Kachelspalten
     ab  580 px   2 Kachelspalten zu 280 px in der Mitte, der Rand wächst mit
                  und trifft bei 880 px genau den halben Platz, ohne Sprung
     darunter     eine Spalte, Rand ist nur der Seitenabstand
   Gilt für die Startseite und gaming.html, beide bauen den Abschnitt .tools.
   min(100%, …) verhindert Überlauf unter 320 px. */
.tools { container-type: inline-size; }
.tools > * { padding-inline: var(--kachelrand, 0px); }

.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 20px;
}
@container (min-width: 580px) {
  .tools > * { --kachelrand: calc((100cqi - 580px) / 2); }
  .tool-grid { grid-template-columns: repeat(2, 1fr); }
}
@container (min-width: 880px) {
  .tools > * { --kachelrand: calc((100cqi + 20px) / 6); }
}
@container (min-width: 1180px) {
  .tools > * { --kachelrand: calc((100cqi + 20px) / 8); }
  .tool-grid { grid-template-columns: repeat(3, 1fr); }
}
@container (min-width: 1480px) {
  .tools > * { --kachelrand: calc((100cqi + 20px) / 10); }
  .tool-grid { grid-template-columns: repeat(4, 1fr); }
}
/* n Spalten ab 300 · (n + 1) − 20 px, Rand (Breite + Lücke) / (2 · (n + 1)) */
@container (min-width: 1780px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 12); } .tool-grid { grid-template-columns: repeat(5, 1fr); } }
@container (min-width: 2080px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 14); } .tool-grid { grid-template-columns: repeat(6, 1fr); } }
@container (min-width: 2380px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 16); } .tool-grid { grid-template-columns: repeat(7, 1fr); } }
@container (min-width: 2680px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 18); } .tool-grid { grid-template-columns: repeat(8, 1fr); } }
@container (min-width: 2980px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 20); } .tool-grid { grid-template-columns: repeat(9, 1fr); } }
@container (min-width: 3280px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 22); } .tool-grid { grid-template-columns: repeat(10, 1fr); } }
@container (min-width: 3580px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 24); } .tool-grid { grid-template-columns: repeat(11, 1fr); } }
@container (min-width: 3880px) { .tools > * { --kachelrand: calc((100cqi + 20px) / 26); } .tool-grid { grid-template-columns: repeat(12, 1fr); } }

/* Kachelform: EIN Radius für Kachel, Farbkappe, Fokusrahmen und Sternenfeld
   (vorher stand 16px an vier Stellen einzeln). Gilt auch für die Abschnitte
   auf werkstatt.html, damit beide Seiten dieselbe Kachel zeigen.
   8 px statt 16: straff wie gefräst statt bauchig. Knöpfe und Schilder sind
   eine Stufe weniger rund (Auswahlfelder 6, Knöpfe 5, Schilder 3) statt
   Pillen. Die Werkzeug-Symbole bringen ihre Rundung im SVG selbst mit
   (rx 11 von 48) und bleiben, was sie sind: die Icons der Werkzeuge.
   --tool-flow ist die Füllung der Kappe: ein Vollton aus --tool, nur die
   zwei Farbwerkzeuge setzen weiter unten ihren Verlauf ein.
   --cap: so weit läuft die Farbe an den Seiten herab, bevor sie ausklingt. */
.tool-card,
.wk-tool {
  --card-r: 8px;
  --bar-h: 4px;
  --cap: 40px;
  --tool-flow: linear-gradient(var(--tool, var(--accent)), var(--tool, var(--accent)));
}

.tool-card {
  --tool: var(--accent);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--panel-veil);
  border: 1px solid var(--border);
  border-radius: var(--card-r);
  padding: 22px;
  color: var(--text);
  text-decoration: none;
  box-shadow: var(--shadow);
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.2s ease;
  isolation: isolate;
  /* Bei großer Browserschrift (24 px) und 320 px Breite schoben
     „Real_RAM_cooler“ und das SKILL-Schild die Seite seitlich auf. Lieber
     mitten im Wort umbrechen als die ganze Seite wischbar machen. */
  overflow-wrap: anywhere;
}
.tool-wifi { --tool: var(--wifi); }
.tool-shrink { --tool: var(--shrink); }
.tool-bigday { --tool: var(--bigday); }
.tool-ram { --tool: var(--ram); }
.tool-rad { --tool: var(--rad); }
.tool-collective { --tool: var(--collective); }
.tool-zaehlwerk { --tool: var(--zaehlwerk); }
.tool-fontart { --tool: var(--fontart); --tool-flow: var(--fontart-flow); }
.tool-ticker { --tool: var(--ticker); }
.tool-masterprompt { --tool: var(--masterprompt); }
.tool-prismatical { --tool: var(--prisma); --tool-flow: var(--prisma-flow); }
.tool-spectroton { --tool: var(--spectro); --tool-flow: var(--spectro-flow); }
.tool-heizwarte { --tool: var(--heizwarte); --tool-flow: var(--heizwarte-flow); }
.tool-fadenkreuz { --tool: var(--fadenkreuz); --tool-flow: var(--fadenkreuz-flow); }
.tool-pocketsum { --tool: var(--pocketsum); --tool-flow: var(--pocketsum-flow); }
.tool-gaming { --tool: var(--gaming); --tool-flow: var(--gaming-flow); }
.tool-craftionary { --tool: var(--craftionary); }
.tool-vault { --tool: var(--vault); }
.tool-ruestkammer { --tool: var(--ruestkammer); }

/* Leuchten (30.10.2026, Dennis: „mehr Glow“). Drei Schichten, alle in der Farbe
   der Kachel: ein Schein von der Kappe in die Kachel hinein (::after, hinter dem
   Inhalt, isolation hält ihn in der Kachel), ein Schein um die Oberkante und die
   leuchtenden Symbole. Mit Verlauf (Prismatical, Spectroton, Heizwarte,
   Pocketsum, Gaming) scheint der Verlauf selbst. Die Platzhalter leuchten
   nicht: dort ist noch nichts, das leuchten könnte. --haze, --glow und
   --glow-hover stehen je Darstellung in den Farbblöcken (dunkel kräftiger). */
.tool-card:not(.tool-platzhalter)::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--tool-flow);
  opacity: var(--haze);
  -webkit-mask-image: radial-gradient(130% 80% at 50% 0%, #000, transparent 72%);
  mask-image: radial-gradient(130% 80% at 50% 0%, #000, transparent 72%);
  /* Weichzeichnen, bevor die Maske greift: sonst zeichnet Pocketsums Kappe
     mit ihren harten Stufen sichtbare Streifen in die Kachel. */
  filter: blur(12px);
  pointer-events: none;
}
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  .tool-card:not(.tool-platzhalter) {
    box-shadow: var(--shadow), 0 -10px 30px -16px color-mix(in srgb, var(--tool) var(--glow), transparent);
  }
  .tool-card:not(.tool-platzhalter):hover,
  .tool-card:not(.tool-platzhalter):focus-within {
    box-shadow: var(--shadow), 0 0 36px -10px color-mix(in srgb, var(--tool) var(--glow-hover), transparent);
  }
  .tool-head img {
    filter: drop-shadow(0 0 10px color-mix(in srgb, var(--tool) var(--glow), transparent));
  }
  /* Namen glühen nur im Dunkeln (--name-glow ist hell 0). Verlaufsnamen nicht:
     ihr Schatten läge über dem Verlauf und machte ihn trüb (siehe unten). */
  .tool-name {
    text-shadow: 0 0 var(--name-glow) color-mix(in srgb, var(--tool) 55%, transparent);
  }
  .tb-icon { filter: drop-shadow(0 0 8px color-mix(in srgb, var(--claim-2) var(--glow), transparent)); }
}

/* Die Farbkappe an der Oberkante, für jede Kachel in ihrer Farbe.
   Sie ist KEIN eigenes Kästchen mit eigener Rundung, sondern eine Ebene
   genau so groß wie die Kachel samt Rahmen (inset: -1px, weil absolute
   Kinder an der Innenkante des Rahmens ansetzen) und mit derselben Rundung.
   Vorher: ein 4 px hohes Kästchen mit 16 px Rundung — der Browser kappt
   Radien, die höher sind als das Kästchen, anteilig auf 4 px. Der Balken
   ragte dadurch über die gerundete Ecke hinaus wie ein Sims.
   Grundstufe (Browser ohne mask-composite): nur der oberste Streifen der
   Ebene wird gemalt, den Rest schneidet der Browser an derselben Kontur
   ab wie die Kachel — ein gerader Balken, der der Ecke aufs Pixel folgt. */
.tool-card::before,
.wk-tool::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background: var(--tool-flow) top / 100% var(--bar-h) no-repeat;
  pointer-events: none;
}
/* Kappe: Die Ebene bekommt einen eigenen Rahmen, oben --bar-h, seitlich
   1 px — genau über dem echten Kachelrahmen. Die Maske lässt nur diesen
   Ring stehen (Rand-Box minus Innen-Box) und blendet ihn nach unten aus.
   Der Browser rundet die Innen-Box mit Außenradius minus Randbreite je
   Achse (hier 7 × 4 px, elliptisch, gleicher Mittelpunkt wie die
   Außenkante). Die Kappe hat also keine eigene Ecke, sie IST die Ecke: Sie
   wird von --bar-h oben stetig zur 1-px-Haarlinie an der Seite dünner und
   klingt dort im Rahmen aus.
   Der Verlauf ist nur --cap hoch gemalt, nicht über die ganze Kachel: sonst
   endet Prismaticals Regenbogen oben rechts bei Blau statt bei Violett.
   Voll deckend bis unter die Ecke (--card-r + --bar-h), dann Ausklang. */
@supports (mask-composite: exclude) {
  .tool-card::before,
  .wk-tool::before {
    border: 1px solid transparent;
    border-top-width: var(--bar-h);
    background: var(--tool-flow) border-box top / 100% var(--cap) no-repeat;
    mask:
      linear-gradient(#000 calc(var(--card-r) + var(--bar-h)), transparent var(--cap)) border-box,
      linear-gradient(#000 0 0) padding-box,
      linear-gradient(#000 0 0) border-box;
    mask-composite: intersect, exclude;
  }
}

/* Platzhalter-Kacheln: angekuendigt, aber noch nichts dahinter. Gestrichelter
   Rahmen und gedaempfte Farbe, damit sie auf einen Blick als "noch nichts"
   lesbar sind, ohne wie ein Fehler auszusehen. Sie tragen bewusst KEIN
   .tool-open und keine Mini-Kacheln — ein Knopf ins Leere waere schlimmer als
   keiner — und deshalb auch keinen Hover-Effekt, der Klickbarkeit verspricht. */
.tool-platzhalter {
  --tool: var(--text-soft);
  background: transparent;
  border-style: dashed;
  box-shadow: none;
}
.tool-platzhalter:hover { border-color: var(--border); transform: none; }
/* Der leere Platzhalter hat keine eigene Farbe: Seine Kappe ist gestrichelt
   wie sein Rahmen und grau, als gerader Streifen ohne Ausklang (eine
   gestrichelte Haarlinie an den Seiten läge quer zu den Strichen des
   Rahmens). Grau aus --text-soft bei halber Deckkraft, nicht --border: in der
   Rahmenfarbe verschwand sie im Dunkeln fast ganz. Die dunkle Materie malt
   ihre Kappe im eigenen Rahmen (siehe unten) und braucht die Ebene nicht. */
.tool-platzhalter::before {
  border: 0;
  mask: none;
  background: repeating-linear-gradient(90deg, var(--text-soft) 0 12px, transparent 12px 20px) top / 100% var(--bar-h) no-repeat;
  opacity: 0.5;
}
.tool-dunkle-materie::before { content: none; }
.tool-platzhalter .tool-name { color: var(--text-soft); }
.tool-platzhalter .tool-desc { color: var(--text-soft); }
.platzhalter-icon {
  width: 44px;
  height: 44px;
  flex: none;
  border: 2px dashed var(--border);
  border-radius: 11px;
}

/* Die Platzhalter-Kachel fuer das ungenannte Werkzeug traegt keinen Codenamen,
   sondern ein Aussehen: dunkle Materie. Tiefer Raum mit ein paar Lichtpunkten
   und einem Ring, der aussieht, als kruemme etwas Unsichtbares das Licht
   dahinter. Sie bleibt in BEIDEN Darstellungen dunkel — das ist der Witz;
   deshalb stehen hier feste Farben statt der Themenvariablen, und deshalb
   traegt sie ihre eigene Textfarbe. */
/* Die Kappe steckt hier IM Rahmen statt als Ebene darüber: Rahmen
   durchsichtig und oben --bar-h stark, darunter ein Verlauf vom Lila in
   die alte Rahmenfarbe, die Innenfläche nur bis zur Rahmen-Innenkante.
   Grund: Kappe und Kachel sind sonst zwei getrennt geglättete Kanten.
   Bei Skalierung 125 %, 150 % oder am Telefon (2,75) treffen die sich nicht
   ganz, und die dunkle Kachel blitzte im hellen Thema als graue Haarlinie
   außen an der Kappe hervor. Bei den übrigen Kacheln passiert dasselbe,
   ist dort aber unsichtbar, weil Rahmen und Grund fast gleich hell sind. */
.tool-dunkle-materie,
.tool-dunkle-materie:hover {
  --tool: #b9a7ff;
  border: 1px solid transparent;
  border-top-width: var(--bar-h);
  /* 22 px Innenabstand wie jede Kachel, minus den dickeren Oberrand */
  padding-top: calc(22px + 1px - var(--bar-h));
  background:
    radial-gradient(58% 44% at 76% 24%, rgba(150,120,255,.20) 0%, transparent 62%) padding-box,
    radial-gradient(120% 96% at 26% 14%, #1a1440 0%, #0c0a22 52%, #050410 100%) padding-box,
    linear-gradient(var(--tool) calc(var(--card-r) + var(--bar-h)), #2a2150 var(--cap)) border-box;
  color: #d8d4f0;
}
.tool-dunkle-materie .tool-name { color: #b9a7ff; }
.tool-dunkle-materie .tool-desc { color: #b4aed4; }
.tool-dunkle-materie .tool-meta { color: #8079a8; }
/* Sternenfeld: einzelne Punkte als winzige Farbverlaeufe, kein Bild und kein
   Skript. Bewusst wenige und ungleich verteilt — ein regelmaessiges Raster
   saehe nach Tapete aus, nicht nach Himmel. */
.tool-dunkle-materie::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background-image:
    radial-gradient(1.6px 1.6px at 18% 26%, rgba(255,255,255,.75), transparent),
    radial-gradient(1.2px 1.2px at 64% 12%, rgba(255,255,255,.55), transparent),
    radial-gradient(1.8px 1.8px at 86% 62%, rgba(255,255,255,.65), transparent),
    radial-gradient(1.1px 1.1px at 32% 78%, rgba(255,255,255,.45), transparent),
    radial-gradient(1.4px 1.4px at 52% 48%, rgba(255,255,255,.35), transparent),
    radial-gradient(1px 1px at 8% 58%, rgba(255,255,255,.40), transparent),
    radial-gradient(1.3px 1.3px at 92% 30%, rgba(255,255,255,.50), transparent);
}
/* Das Icon ist der Linseneffekt: ein Ring um ein Nichts. Die Materie selbst
   ist nicht zu sehen, nur was sie mit dem Licht dahinter macht. */
.materie-icon {
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, #050410 0%, #050410 44%,
              rgba(185,167,255,.85) 50%, rgba(150,120,255,.28) 58%, transparent 72%);
  box-shadow: 0 0 14px rgba(150,120,255,.35);
}

/* Kleines Schild neben dem Werkzeugnamen fuer die Art des Eintrags. Bisher
   nur create-masterprompt: es ist als einziges weder Webseite noch Programm,
   und das soll man sehen, bevor man auf "Oeffnen" klickt. Abstand nur über
   den gap von .tool-head: ein eigener margin-left rückte das Schild ein,
   sobald es am Telefon in die nächste Zeile rutscht. */
.tool-art {
  align-self: center;
  padding: 2px 7px;
  border: 1px solid var(--tool);
  border-radius: 3px;
  color: var(--tool);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Die bunte Kachel: Regenbogen im Farbbalken (siehe --tool-flow oben) und der
   Werkzeugname im Farbverlauf. Der Verlauf ist reine Dekoration — Beschreibung,
   Meta-Zeile und Knopf bleiben in Volltönen, damit nichts nur über Farbe
   erzählt wird.
   Positive Abfrage, nicht negative: Wo background-clip fehlt, bleibt es beim
   Anker-Vollton — ein `color: transparent` ohne Verlauf wäre unsichtbarer Text. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .tool-prismatical .tool-name {
    text-shadow: none;
    background-image: var(--prisma-flow);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* Dieselbe Mechanik für Spectroton, nur mit der Stufen-Rampe. Bewusst zwei
   getrennte Regelsätze statt einer gemeinsamen Klasse: die beiden Kacheln
   teilen sich das Muster, nicht die Farbe. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .tool-spectroton .tool-name {
    text-shadow: none;
    background-image: var(--spectro-flow);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* Heizwarte: derselbe Verlauf-Name, kalt → warm. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .tool-heizwarte .tool-name {
    text-shadow: none;
    background-image: var(--heizwarte-flow);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* Pocketsum: der Name in den fünf Rechnerfarben, als harte Stufen. Jede Stufe hält
   gegen --panel AA (hell 5,02 bis 7,18:1, dunkel 7,77 bis 11,44:1). */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .tool-pocketsum .tool-name {
    text-shadow: none;
    background-image: var(--pocketsum-flow);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.tool-card:hover {
  border-color: var(--tool);
  transform: translateY(-2px);
}
/* The tile is no longer focusable itself — the border follows whatever inside
   has the focus, be it the stretched link or one of the mini tiles. */
.tool-card:focus-within { border-color: var(--tool); }

/* Fadenkreuz: Neongrün, Schwarz, Weiß. Wie die dunkle Materie bleibt die
   Kachel in BEIDEN Darstellungen schwarz – Neongrün auf hellem Grund läge
   bei 1,20:1. Deshalb feste Farben statt Themenvariablen und eigene
   Textfarben, gemessen gegen den Kachelgrund #0d100e: Name 14,40:1, Text
   17,58:1, Meta 8,28:1, Mini-Kacheln 11,03:1 (Überfahren 13,64:1).
   Die Kappe steckt wie bei der dunklen Materie IM Rahmen statt als Ebene
   darüber: eine schwarze Kachel ließe im hellen Thema bei 125/150 % sonst
   eine graue Haarlinie neben der Kappe blitzen. Beim Überfahren und mit
   Fokus wird der ganze Rahmen neongrün wie bei jeder Kachel. */
.tool-card.tool-fadenkreuz {
  --tool: #33ff88;
  border: 1px solid transparent;
  border-top-width: var(--bar-h);
  padding-top: calc(22px + 1px - var(--bar-h));
  background:
    radial-gradient(70% 55% at 88% 10%, rgba(51, 255, 136, .10) 0%, transparent 65%) padding-box,
    linear-gradient(#0d100e, #080a09) padding-box,
    linear-gradient(var(--tool) calc(var(--card-r) + var(--bar-h)), #1f2b24 var(--cap)) border-box;
  color: #f3f6f4;
}
.tool-card.tool-fadenkreuz::before { content: none; }
.tool-card.tool-fadenkreuz:hover,
.tool-card.tool-fadenkreuz:focus-within { border-color: var(--tool); }
.tool-fadenkreuz .tool-desc { color: #f3f6f4; }
.tool-fadenkreuz .tool-meta { color: #a3ada7; }
.tool-card.tool-fadenkreuz .tool-mini a { background: #121714; border-color: #26322b; color: #c3ccc6; }
.tool-card.tool-fadenkreuz .tool-mini a:hover,
.tool-card.tool-fadenkreuz .tool-mini a:focus-visible { border-color: var(--tool); color: var(--tool); }

/* Wird es eng, rutscht erst das SKILL-Schild in die nächste Zeile, dann
   der Name unter das Symbol — aber kein Name bricht mitten im Wort. Der
   Name misst sich beim Zeilenbau an seiner vollen Länge (max-content):
   Seit die Kacheln in fünf Spalten stehen (30.10.2026), maß er sich
   vorher am längsten Wort und brach „create-masterprompt“ am Bindestrich,
   obwohl das Schild in die nächste Zeile gepasst hätte. Findet der Name
   neben dem Symbol keinen Platz, steht er allein in seiner Zeile und darf
   dort schrumpfen und umbrechen.
   break-word statt des anywhere der Kachel: nur ein Wort, das allein
   keine Zeile findet, wird noch geteilt. Nötig seit Fraunces: sie läuft
   breiter als die Systemschrift, und bei 320 px stand sonst ein einzelnes
   „t“ von „create-masterprompt“ in einer dritten Zeile. */
.tool-head { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.tool-head img { width: 44px; height: 44px; border-radius: 10px; display: block; }
.tool-name {
  flex: 0 1 max-content;
  max-width: max-content;
  overflow-wrap: break-word;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--tool);
}
.tool-desc { font-size: 0.98rem; }
.tool-meta { font-size: 0.85rem; color: var(--text-soft); }

/* The stretched link: its ::after covers the whole tile, so a click anywhere
   opens the tool even though the tile itself is only a <div>. */
.tool-open {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--tool);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
}
/* Die Klickfläche sitzt 1 px innerhalb des Rahmens, also einen Pixel
   weniger rund — dann läuft der Fokusring (2 px Abstand) im selben Bogen
   um die Kachel wie ihre Außenkante. */
.tool-open::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: calc(var(--card-r) - 1px);
}
/* Without this the focus ring would hug the word "Open" only. Drawing it on
   the overlay instead puts it back around the whole tile, as before. */
.tool-open:focus-visible { outline: none; }
.tool-open:focus-visible::after { outline: 2px solid var(--accent); outline-offset: 2px; }
.tool-open .arrow { transition: transform 0.15s ease; }
.tool-card:hover .arrow { transform: translateX(3px); }

/* Two mini tiles inside the card. They have to sit ABOVE the stretched link,
   otherwise the overlay swallows their clicks — hence position + z-index. */
.tool-mini {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 2px;
}
.tool-mini a {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--bg);
  color: var(--text-soft);
  font-size: 0.82rem;
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.tool-mini a:hover,
.tool-mini a:focus-visible {
  border-color: var(--tool, var(--accent));
  color: var(--tool, var(--accent));
}
.tool-mini-date { font-variant-numeric: tabular-nums; opacity: var(--date-alpha); }

/* Fourteen links pointing at the same label but a different target — so far
   only create-masterprompt's overview image, which exists in every language
   this page speaks. Each link shows only under its own html[lang]; English is
   the fallback and hides only while one of the other thirteen is active. Pure
   CSS, no JS: document.documentElement.lang is set synchronously in i18n.js
   apply(), so this reacts on every language switch by itself. */
html:not([lang="de"]) [data-lang-only="de"] { display: none; }
html:not([lang="es"]) [data-lang-only="es"] { display: none; }
html:not([lang="fr"]) [data-lang-only="fr"] { display: none; }
html:not([lang="it"]) [data-lang-only="it"] { display: none; }
html:not([lang="nl"]) [data-lang-only="nl"] { display: none; }
html:not([lang="pl"]) [data-lang-only="pl"] { display: none; }
html:not([lang="pt"]) [data-lang-only="pt"] { display: none; }
html:not([lang="tr"]) [data-lang-only="tr"] { display: none; }
html:not([lang="ru"]) [data-lang-only="ru"] { display: none; }
html:not([lang="hi"]) [data-lang-only="hi"] { display: none; }
html:not([lang="zh"]) [data-lang-only="zh"] { display: none; }
html:not([lang="ja"]) [data-lang-only="ja"] { display: none; }
html:not([lang="ko"]) [data-lang-only="ko"] { display: none; }
html[lang="de"] [data-lang-only="en"],
html[lang="es"] [data-lang-only="en"],
html[lang="fr"] [data-lang-only="en"],
html[lang="it"] [data-lang-only="en"],
html[lang="nl"] [data-lang-only="en"],
html[lang="pl"] [data-lang-only="en"],
html[lang="pt"] [data-lang-only="en"],
html[lang="tr"] [data-lang-only="en"],
html[lang="ru"] [data-lang-only="en"],
html[lang="hi"] [data-lang-only="en"],
html[lang="zh"] [data-lang-only="en"],
html[lang="ja"] [data-lang-only="en"],
html[lang="ko"] [data-lang-only="en"] { display: none; }

.more-line {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  text-align: center;
  color: var(--text-soft);
  font-size: 0.92rem;
  margin: 28px 0 0;
}
.more-line a { color: var(--accent); font-weight: 500; text-decoration: none; }
.more-line a:hover { text-decoration: underline; }

/* Footer */
.site-footer {
  margin-top: auto;
  padding-top: 48px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 6px;
  text-align: center;
  font-size: 0.85rem;
  color: var(--text-soft);
}
.site-footer a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
}
.site-footer a:hover { text-decoration: underline; }
.sep { opacity: 0.6; }

/* Startseite, nur wer nicht Englisch bekommt: bis i18n.js zum ersten Mal
   übersetzt hat, bleiben Inhalt, Fußzeile und die noch leeren Auswahlfelder
   unsichtbar — visibility, nicht display: none, damit das Gerüst seinen
   Platz behält. Der Rohbau ist Englisch, die Übersetzungen sind länger: der
   Kopf wuchs, Schild und Kacheln rückten bis zu 59 px nach unten
   (Layout-Verschiebung bis 0,065 bei Fast 3G, gemessen 24.09.2026). Die
   Klasse setzt ein Skript im Kopf von index.html, ohne JavaScript bleibt
   also alles sichtbar; main.js nimmt sie ab, das load-Ereignis spätestens. */
.i18n-wartet main,
.i18n-wartet .site-footer,
.i18n-wartet .header-controls { visibility: hidden; }

@media (max-width: 480px) {
  .hero { padding: 40px 4px 34px; }
  /* Schmalerer Rand am Telefon, 14 statt 20 px. */
  .page { padding-left: 14px; padding-right: 14px; }
  /* Am Telefon stehen die beiden Auswahlfelder immer in einer eigenen Zeile
     unter der Marke und teilen sie sich hälftig. Vorher ragten sie bei 320 px
     in jeder Sprache bis zu 84 px über den Rand, bei 375 px in zwölf von
     vierzehn — die Seite liess sich seitlich wischen (WCAG 1.4.10 verlangt
     320 px ohne). Immer statt nur bei Bedarf, damit der Kopf nicht je nach
     Sprache mal ein-, mal zweizeilig ist. Die Felder werden dabei breiter,
     nie schmaler; min-width: 0 sorgt dafür, dass ein künftiges überlanges
     Wort im Feld gekappt wird statt die Seite zu verbreitern. */
  .header-controls { flex: 1 1 100%; }
  .header-controls .lang-wrap { flex: 1 1 0; min-width: 0; }
  #langSelect,
  #themeSelect { width: 100%; min-width: 0; }
  /* Hier hat das Versprechens-Schild in jeder Sprache drei bis sieben
     Zeilen; mittig daneben hinge das Schloss verloren am Rand. Es sitzt
     deshalb auf Höhe der ersten Zeile (Zeilenhöhe 1.55em, Icon 18 px). */
  .pledge { align-items: flex-start; }
  .pledge svg { margin-top: calc((1.55em - 18px) / 2); }
}

@media (prefers-reduced-motion: reduce) {
  .tool-card, .tool-open .arrow, .tool-mini a { transition: none; }
  .tool-card:hover { transform: none; }
}

/* ==================================================================
   werkstatt.html — news and guides
   Same brand as the start page, but the layout of the launch console:
   navigation on the left, content on the right. Everything sits in one
   document so anchors work without JavaScript.
   ================================================================== */

.page-wide { max-width: 1080px; }

a.brand { text-decoration: none; color: inherit; }

.wk-hero { text-align: center; padding: 44px 8px 26px; }
/* Grenze aus demselben Grund wie bei .hero h1: „handleidingen“ (nl). */
.wk-hero h1 {
  font-size: min(clamp(1.8rem, 4.6vw, 2.5rem), 12.5vw);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 12px;
}

.wk-frame {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 32px;
  align-items: start;
  margin-top: 8px;
}

/* Bis werkstatt.js den Rahmen zum ersten Mal gefüllt hat, bleiben er und die
   Fußzeile unsichtbar — visibility, nicht display: none, damit das Gerüst
   seinen Platz behält. Sonst steht die Fußzeile bei langsamer Verbindung
   Sekunden lang unter dem leeren Rahmen und springt dann aus dem Bild
   (Layout-Verschiebung 0,70 am Telefon bei Fast 3G, gemessen 24.09.2026).
   Die Klasse setzt ein Skript im Kopf von werkstatt.html, ohne JavaScript
   bleibt also alles sichtbar. */
.wk-im-bau .wk-frame,
.wk-im-bau .site-footer { visibility: hidden; }

/* Navigation */
.wk-nav { position: sticky; top: 18px; }
.wk-nav-title {
  margin: 0 0 8px;
  padding: 0 10px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.wk-nav-list { display: flex; flex-direction: column; gap: 2px; }
.wk-nav-button {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-left: 3px solid transparent;
  border-radius: 0 5px 5px 0;
  color: var(--text);
  text-decoration: none;
  font-size: 0.92rem;
}
.wk-nav-button:hover { background: var(--panel); }
.wk-nav-button[aria-current="true"] {
  background: var(--panel);
  border-left-color: var(--tool, var(--accent));
  font-weight: 600;
}
.wk-nav-dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--tool, var(--accent));
}
.wk-nav-back {
  display: inline-block;
  margin-top: 16px;
  padding: 0 10px;
  color: var(--accent);
  font-size: 0.88rem;
  text-decoration: none;
}
.wk-nav-back:hover { text-decoration: underline; }

/* Tool sections */
.wk-content { min-width: 0; }
/* Kein overflow: hidden mehr — es schnitt die Farbkappe an der Innenkante
   des Rahmens ab. Was vorher darunter verschwand, bricht jetzt um statt
   abgeschnitten zu werden (overflow-wrap in .wk-body): ein langer Pfad wie
   %USERPROFILE%\.claude\projects ragte bei großer Browserschrift über den
   Rahmen. Geprüft 320–1280 px, vierzehn Sprachen, Schrift 16 bis 24 px.
   position: relative hält die Kappe in ihrem Abschnitt; vorher fehlte es,
   und die Balken von Prismatical und Spectroton landeten über der
   Navigationsspalte. */
.wk-tool {
  position: relative;
  background: var(--panel-veil);
  border: 1px solid var(--border);
  border-radius: var(--card-r);
  margin-bottom: 18px;
  box-shadow: var(--shadow);
  /* The sticky header of a browser must not swallow the heading when an
     anchor is opened. */
  scroll-margin-top: 18px;
}
.wk-tool-head {
  display: flex;
  align-items: center;
  gap: 13px;
  flex-wrap: wrap;
  padding: 15px 20px;
  border-bottom: 1px solid var(--border);
}
.wk-tool-head img { width: 40px; height: 40px; border-radius: 9px; display: block; }
.wk-tool-name { margin: 0; font-size: 1.1rem; font-weight: 600; color: var(--tool, var(--accent)); }
.wk-tool-cta {
  margin-left: auto;
  color: var(--tool, var(--accent));
  font-weight: 600;
  font-size: 0.92rem;
  text-decoration: none;
}
.wk-tool-cta:hover { text-decoration: underline; }

.wk-body { padding: 6px 20px 20px; overflow-wrap: anywhere; }

.wk-section {
  margin: 20px 0 4px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  font-size: 1.05rem;
  font-weight: 700;
  scroll-margin-top: 18px;
}
.wk-body > .wk-section:first-child { border-top: 0; padding-top: 8px; margin-top: 8px; }

.wk-sub {
  margin: 16px 0 6px;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--tool, var(--accent));
}

.wk-text { margin: 0 0 10px; font-size: 0.95rem; }
.wk-steps, .wk-pitfalls { margin: 0 0 10px; padding-left: 22px; font-size: 0.95rem; }
.wk-steps li, .wk-pitfalls li { margin-bottom: 7px; }
.wk-pitfalls { color: var(--text-soft); }

/* Screenshots under "What it looks like". Width, height and row share come from
   werkstatt.js (flex and max-width per picture, from its aspect ratio). */
.wk-shots { display: flex; flex-wrap: wrap; gap: 12px; margin: 2px 0 14px; }
.wk-shot { margin: 0; min-width: 0; }
.wk-shot-frame {
  display: block;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--bg);
}
.wk-shot-frame img { display: block; width: 100%; height: auto; }
a.wk-shot-frame:hover { border-color: var(--tool, var(--accent)); }
a.wk-shot-frame:focus-visible { outline-color: var(--tool, var(--accent)); }

.wk-docs { margin: 12px 0 0; font-size: 0.88rem; }
.wk-external { color: var(--accent); text-decoration: none; }
.wk-external:hover { text-decoration: underline; }
.wk-arrow { display: inline-block; }

/* News entries */
.wk-news { list-style: none; margin: 12px 0 0; padding: 0; }
.wk-news > li {
  padding-left: 15px;
  border-left: 2px solid var(--border);
  margin-bottom: 16px;
}
.wk-news > li:last-child { margin-bottom: 0; }
.wk-news-meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 9px;
  margin: 0 0 4px;
}
.wk-news-date {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}
.wk-news-version {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--tool, var(--accent));
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 7px;
}

/* Narrow screens: the sidebar becomes a scrollable row of chips above the
   content. Sticky is dropped — a bar that follows you costs more room than
   it gives on a phone. */
@media (max-width: 720px) {
  .wk-frame { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .wk-nav { position: static; }
  /* Die Leiste scrollt und schneidet deshalb an ihrer Innenkante ab — auch
     den Fokusring (2 px Ring + 2 px Abstand), dem oben und am ersten Chip
     links die Kante fehlte. 4 px Polster rundum geben ihm Platz, der
     negative Rand hält die Chips an ihrer bisherigen Stelle. */
  .wk-nav-list {
    flex-direction: row;
    gap: 6px;
    overflow-x: auto;
    padding: 4px;
    margin: -4px -4px 0;
  }
  .wk-nav-button {
    flex: none;
    border-left: 0;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: var(--panel);
    white-space: nowrap;
  }
  .wk-nav-button[aria-current="true"] { border-color: var(--tool, var(--accent)); }
  .wk-nav-back { margin-top: 12px; padding: 0; }
  .wk-body { padding: 6px 15px 16px; }
  .wk-tool-head { padding: 13px 15px; }
}

/* ==================================================================
   Überschriftenschrift: Fraunces (SIL Open Font License 1.1, The
   Fraunces Project Authors; Lizenztext liegt neben den Dateien in
   assets/fonts/fraunces/OFL.txt). Von Dennis am 24.09.2026 aus sechs
   Entwürfen gewählt, weil sie als einzige der Seite eine eigene Stimme
   gibt: eine warme, leicht altmodische Antiqua — die Werkstatt als
   Hobelbank, nicht als Start-up.

   Regel: NAMEN UND ÜBERSCHRIFTEN in Fraunces, alles zum Lesen und
   Bedienen bleibt in der Systemschrift (--font-text).

   Selbst gehostet, kein Abruf bei fremden Diensten. Nur die Stärke-Achse
   (wght): latin 36 KB, latin-ext 33 KB (lädt nur, wo Polnisch, Türkisch
   o. Ä. es braucht). Die Fassung mit optischer Größe wog fast doppelt so
   viel und sah im Vergleich kaum anders aus. Fraunces hat kein
   Kyrillisch, kein Devanagari, keine CJK-Zeichen — siehe Sprachweiche unten.
   ================================================================== */
@font-face {
  font-family: "Fraunces Werkstatt";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("../assets/fonts/fraunces/fraunces-latin-ext-wght-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Fraunces Werkstatt";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("../assets/fonts/fraunces/fraunces-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Platzhalter, solange Fraunces lädt: Georgia, auf Fraunces getrimmt,
   damit beim Tausch möglichst keine Zeile umspringt. Zwei Stärken, weil
   die Werkzeugliste auf werkstatt.html normal (400) läuft und mit nur
   Georgia Bold beim Laden kurz fett dastand. Gemessen: Fraunces 560/600
   ist rund 0,93-mal so breit wie Georgia Bold, Fraunces 400 rund
   1,06-mal so breit wie Georgia. Die Höhen sind Fraunces' eigene (0,978
   über, 0,255 unter der Grundlinie), geteilt durch size-adjust. Nur
   Lateinschrift, damit Kyrillisch nie in Georgia landet. Wo Georgia
   fehlt (Android, Linux), greift direkt die Systemschrift. Kostet keinen
   Download. */
@font-face {
  font-family: "Fraunces Ersatz";
  font-style: normal;
  font-weight: 500 900;
  src: local("Georgia Bold"), local("Georgia-Bold");
  size-adjust: 93%;
  ascent-override: 105.2%;
  descent-override: 27.4%;
  line-gap-override: 0%;
  unicode-range: U+0000-02FF, U+1E00-1EFF, U+2000-206F, U+20AC, U+2122;
}
@font-face {
  font-family: "Fraunces Ersatz";
  font-style: normal;
  font-weight: 100 499;
  src: local("Georgia");
  size-adjust: 106.3%;
  ascent-override: 92%;
  descent-override: 24%;
  line-gap-override: 0%;
  unicode-range: U+0000-02FF, U+1E00-1EFF, U+2000-206F, U+20AC, U+2122;
}

/* Überschriften. 560 statt 700: helle Schrift strahlt auf dem dunklen
   Grund ohnehin breiter; 560 ist kräftig, aber ruhiger. Dünne Schnitte
   unter 400 würden auf Dunkel flirren — darum keine. */
.hero h1,
.wk-hero h1,
.tools h2,
.wk-section {
  font-family: var(--font-schild);
  font-weight: 560;
}
.hero h1,
.wk-hero h1 {
  letter-spacing: -0.01em;
  /* Zwei gleich lange Zeilen statt „… von dir / wollen“ */
  text-wrap: balance;
}
/* Fraunces hat kleinere Kleinbuchstaben als Segoe UI; 1.05 → 1.1rem
   gleicht das bei „Anleitung“/„Neuigkeiten“ aus. */
.wk-section { font-size: 1.1rem; }

/* Namen: Marke und Werkzeugnamen stehen in allen vierzehn Sprachen in
   Lateinschrift — so trägt die Schrift auch auf der russischen oder
   japanischen Seite etwas bei, wie ein Firmenschild in einer fremden
   Stadt. Auf werkstatt.html auch in der Navigationsleiste, damit jedes
   Werkzeug überall dieselbe Namensschrift trägt. */
.brand-name,
.tool-name,
.wk-tool-name,
.wk-nav-button {
  font-family: var(--font-schild);
  letter-spacing: 0;
}
.brand-name { font-size: 1.02rem; }

/* Sprachweiche: Russisch, Hindi, Chinesisch, Japanisch und Koreanisch
   haben in Fraunces keine Buchstaben. Ohne Weiche käme ein Flickenteppich
   heraus (Komma und Leerzeichen in Fraunces zwischen Systemschrift), also
   behalten die Überschriften dort Schrift, Stärke und Größe wie vor
   Fraunces. Nur text-wrap: balance gilt bewusst in allen Sprachen — es
   trennt auch ja/ko besser als vorher („ツ|ール“, „작|은“). Ebenso übersetzte
   Werkzeugnamen („QR-карточка для Wi-Fi“): auf der Startseite erkennbar an
   data-i18n, auf werkstatt.html setzt werkstatt.js data-name-uebersetzt. */
:is(.hero h1, .wk-hero h1, .tools h2, .wk-section):is(:lang(ru), :lang(hi), :lang(zh), :lang(ja), :lang(ko)) {
  font-family: var(--font-text);
  font-weight: 700;
}
:is(.hero, .wk-hero) h1:is(:lang(ru), :lang(hi), :lang(zh), :lang(ja), :lang(ko)) { letter-spacing: -0.015em; }
.wk-body .wk-section:is(:lang(ru), :lang(hi), :lang(zh), :lang(ja), :lang(ko)) { font-size: 1.05rem; }
:is(.tool-name[data-i18n], [data-name-uebersetzt]):is(:lang(ru), :lang(hi), :lang(zh), :lang(ja), :lang(ko)) {
  font-family: var(--font-text);
}

/* ==================================================================
   Sehhilfen (31.10.2026): Hoher Kontrast, Farbenblind, Umgekehrte Farben.
   Dennis' Entscheidungen, alle per Auswahl: EIN Feld mit acht Einträgen,
   und die Wahl gilt in allen Werkzeugen (localStorage
   „werkstatt.darstellung“, alle liegen auf einem Ursprung). Das Kopf-Skript
   jeder Seite übersetzt sie vor dem ersten Bild in zwei Attribute:
     data-theme   light | dark               wie bisher, die drei Blöcke oben
     data-vision  contrast | cvd | invert    neu, nur hier unten
   Hoher Kontrast und Farbenblind kommen immer mit festem data-theme, auch
   wenn „System“ dem Gerätewunsch „Kontrast erhöhen“ folgt (header.js). Die
   drei Farbblöcke oben bleiben dafür Zeile für Zeile, wie sie sind: die
   Profil-README liest den Dunkel-Block (readme-bauen.mjs, erster Treffer
   für :root[data-theme="dark"]).
   ================================================================== */

/* Hoher Kontrast, dunkel. Schwarz mit Schrift #E0E0E0, 15,91:1 (Dennis:
   „leicht gedämpft“ statt Reinweiß). Jede Schrift hält 7:1 gegen Schwarz.
   Die Kachelfarben des Dunkel-Blocks tun das schon alle (schlechtester Wert
   --ticker 7,61), deshalb erben sie und stehen hier nicht. Verläufe werden
   zu ihrem Anker-Vollton. Aurora, Schleier, Leuchten und Schatten fallen
   weg (Regeln weiter unten). */
:root[data-vision="contrast"][data-theme="dark"] {
  --bg: #000000;
  --panel: #000000;
  --panel-veil: #000000;
  --text: #E0E0E0;
  --text-soft: #C4C4C4;   /* 12,04 */
  --border: #A0A0A0;      /* 8,03, Rahmen im Hohen Kontrast 2 px */
  --accent-soft: #000000;
  --claim-1: var(--accent);
  --claim-2: var(--accent);
  --claim-3: var(--accent);
  --glow: 0%;
  --glow-hover: 0%;
  --haze: 0;
  --name-glow: 0px;
  --shadow: none;
  --fontart-flow: linear-gradient(var(--fontart), var(--fontart));
  --prisma-flow: linear-gradient(var(--prisma), var(--prisma));
  --spectro-flow: linear-gradient(var(--spectro), var(--spectro));
  --heizwarte-flow: linear-gradient(var(--heizwarte), var(--heizwarte));
  --pocketsum-flow: linear-gradient(var(--pocketsum), var(--pocketsum));
  --gaming-flow: linear-gradient(var(--gaming), var(--gaming));
}

/* Hoher Kontrast, hell. Weiß mit schwarzer Schrift. Jede Kachelfarbe behält
   ihren Farbton (OKLCH) und ist so weit nachgedunkelt, dass sie gegen Weiß
   7,2:1 hält; vorher lagen sie bei 6,3. Gerechnet mit farbe.mjs der
   Sehhilfen-Runde (Bisektion der Helligkeit, Chroma in den Gamut geklemmt). */
:root[data-vision="contrast"][data-theme="light"] {
  --accent: #5249AA;        /* 7,26 */
  --accent-strong: #464480; /* 8,75 */
  --accent-soft: #FFFFFF;
  --bg: #FFFFFF;
  --panel: #FFFFFF;
  --panel-veil: #FFFFFF;
  --text: #000000;
  --text-soft: #2B2B2B;     /* 14,16 */
  --border: #585757;        /* 7,20 */
  --claim-1: var(--accent);
  --claim-2: var(--accent);
  --claim-3: var(--accent);
  --glow: 0%;
  --glow-hover: 0%;
  --haze: 0;
  --name-glow: 0px;
  --shadow: none;
  --wifi: #00606E;          /* 7,25 */
  --shrink: #7E12D2;        /* 7,23 */
  --bigday: #794E00;        /* 7,23 */
  --ram: #0058A1;           /* 7,22 */
  --rad: #B10032;           /* 7,20 */
  --collective: #00643D;    /* 7,27 */
  --zaehlwerk: #455F00;     /* 7,27 */
  --fontart: #9E0099;       /* 7,21 */
  --ticker: #403DDB;        /* 7,22 */
  --masterprompt: #993700;  /* 7,24 */
  --prisma: #5B3FBF;        /* 7,22 */
  --spectro: #00625B;       /* 7,25 */
  --heizwarte: #005D82;     /* 7,27 */
  --craftionary: #00634F;   /* 7,25 */
  --vault: #6C5400;         /* 7,23 */
  --ruestkammer: #8D4200;   /* 7,21 */

  --mods: #7A2E6D;
  --fontart-flow: linear-gradient(var(--fontart), var(--fontart));
  --prisma-flow: linear-gradient(var(--prisma), var(--prisma));
  --spectro-flow: linear-gradient(var(--spectro), var(--spectro));
  --heizwarte-flow: linear-gradient(var(--heizwarte), var(--heizwarte));
  --pocketsum-flow: linear-gradient(var(--pocketsum), var(--pocketsum));
  --gaming-flow: linear-gradient(var(--gaming), var(--gaming));
}

/* Was im Hohen Kontrast wegfällt oder kräftiger wird, in beiden Grundtönen.
   Die Farbkappe wird zum festen oberen Rahmen in der Werkzeugfarbe: die
   Ebene mit Maske (.tool-card::before) rechnet mit 1 px Rahmen, hier sind es
   2 px. */
:root[data-vision="contrast"] .aurora { display: none; }
:root[data-vision="contrast"] .tool-card,
:root[data-vision="contrast"] .wk-tool {
  border-width: 2px;
  border-top: 5px solid var(--tool, var(--accent));
  box-shadow: none;
}
:root[data-vision="contrast"] .tool-card::before,
:root[data-vision="contrast"] .wk-tool::before,
:root[data-vision="contrast"] .tool-card::after { content: none; }
:root[data-vision="contrast"] .tool-card:hover,
:root[data-vision="contrast"] .tool-card:focus-within { box-shadow: none; }
:root[data-vision="contrast"] .tool-platzhalter { border-top: 2px dashed var(--border); }
:root[data-vision="contrast"] :is(.tool-head img, .tb-icon) { filter: none; }
:root[data-vision="contrast"] :is(.family-bar, .materie-icon) { box-shadow: none; }
:root[data-vision="contrast"] :is(.sep, .tool-mini-date) { opacity: 1; }
/* Verlaufsschrift wird einfarbig: Claim in Textfarbe, Namen in Werkzeugfarbe */
:root[data-vision="contrast"] :is(.hero h1, .wk-hero h1) { background: none; color: var(--text); }
:root[data-vision="contrast"] .tool-name { background: none; color: var(--tool); text-shadow: none; }
:root[data-vision="contrast"] .pledge { border: 2px solid var(--accent-strong); }
:root[data-vision="contrast"] :is(#langSelect, #themeSelect, .tool-mini a, .wk-shot-frame, .wk-news-version) { border-width: 2px; }
:root[data-vision="contrast"] :focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
:root[data-vision="contrast"] .tool-open:focus-visible { outline: none; }
:root[data-vision="contrast"] .tool-open:focus-visible::after { outline: 3px solid var(--accent); outline-offset: 2px; }
/* Textlinks unterstrichen, nicht erst beim Überfahren */
:root[data-vision="contrast"] :is(.more-line a, .site-footer a, .hero-back a, .wk-nav-back, .wk-external, .wk-tool-cta, .tool-open) { text-decoration: underline; }
@media (max-width: 720px) {
  :root[data-vision="contrast"] .wk-nav-button { border-width: 2px; }
}

/* Am Telefon teilen sich die zwei Auswahlfelder eine Zeile. Seit den acht
   Darstellungen ist deren längster Eintrag („Hoher Kontrast dunkel“, ru
   „Для дальтоников, светлая“) gut doppelt so lang wie der längste
   Sprachname, also bekommt die Darstellung den größeren Teil der Zeile. */
@media (max-width: 480px) {
  .header-controls .lang-wrap:has(#themeSelect) { flex-grow: 1.6; }
}
/* Die zwei schwarzen Kacheln (dunkle Materie, Fadenkreuz) bleiben schwarz,
   ihre Schrift ist fest hell. Statt Raumverlauf und Sternen: Schwarz, Rahmen
   wie jede Kachel, oben ihre Farbe. Die Meta-Zeile der dunklen Materie
   (#8079a8, 5,22) wird heller, damit sie 7:1 hält (#9892C2, 7,23). */
:root[data-vision="contrast"] .tool-dunkle-materie,
:root[data-vision="contrast"] .tool-dunkle-materie:hover {
  background: #000000;
  border: 2px dashed #A0A0A0;
  padding-top: 22px;
}
:root[data-vision="contrast"] .tool-dunkle-materie .tool-meta { color: #9892C2; }
:root[data-vision="contrast"] .tool-card.tool-fadenkreuz {
  background: #000000;
  border: 2px solid #A0A0A0;
  border-top: 5px solid var(--tool);
  padding-top: 22px;
}
:root[data-vision="contrast"] .tool-card.tool-fadenkreuz:hover,
:root[data-vision="contrast"] .tool-card.tool-fadenkreuz:focus-within { border-color: var(--tool); }

/* Farbenblind: Die Startseite trägt keine Bedeutungsfarben. Kachelfarben
   sind Erkennungszeichen, und jede Kachel trägt dazu Namen und Symbol. Hier
   gibt es deshalb nichts zu tauschen; Farbenblind dunkel und hell zeigen
   dieselben Farben wie Dunkel und Hell. Die Werkzeuge tauschen ihre
   Bedeutungsfarben selbst. */

/* Umgekehrte Farben, wie der Farbfilter von Windows: umgedreht wird, was
   gerade zu sehen ist (data-theme bleibt dafür leer, das System entscheidet
   den Grundton). Bildschirmfotos und andere Rasterbilder werden ein zweites
   Mal umgedreht und sind damit wieder echt: invert(1) ist seine eigene
   Umkehrung, im Browser pixelgenau nachgemessen. Mit hue-rotate wäre das
   nicht so, dort schneidet jeder Schritt Farben ab. Symbole (SVG) drehen mit
   wie unter Windows. data-echt markiert, was sonst noch echt bleiben muss. */
:root[data-vision="invert"] { filter: invert(1); }
:root[data-vision="invert"] :is(img:not([src*=".svg"]), video, [data-echt]):not([data-echt] *) { filter: invert(1); }
/* Gedruckt wird ungedreht: Papier bleibt weiß, die Tinte reicht nicht für eine dunkle Seite */
@media print {
  :root[data-vision="invert"],
  :root[data-vision="invert"] :is(img:not([src*=".svg"]), video, [data-echt]):not([data-echt] *) { filter: none; }
}

/* Umdrehen erhält den WCAG-Kontrast NICHT, weil Helligkeit nicht linear
   empfunden wird: Mitteltöne kippen. Die helle Fassung übersteht es (jede
   Farbe umgedreht mindestens 7,05:1). In der dunklen fielen zehn
   Kachelfarben und fünf Verlaufsstopps umgedreht unter 4,5:1, am
   schlechtesten Collective-Calc mit 2,83. Sie werden hier gerade so weit
   heller (gleicher Farbton), dass ihre UMKEHRUNG gegen den umgedrehten
   Kachelschleier über dem hellsten Aurora-Punkt (#181F3F, umgedreht
   #E7E0C0) 4,6:1 hält. Freie Schrift auf der Aurora hält umgedreht schon
   (schlechtester Wert --accent 5,00 gegen #1A4796). farbe.mjs zielUmkehr. */
@media (prefers-color-scheme: dark) {
  :root[data-vision="invert"] {
    --wifi: #3CE9FF;
    --shrink: #C491FF;
    --rad: #FF9199;
    --collective: #3DFBAC;
    --fontart: #FF8DF6;
    --ticker: #88A0FF;
    --masterprompt: #FF995D;
    --spectro: #3BF3DB;
    --fadenkreuz: #41FF8C;
    --ruestkammer: #FF9C4E;

    --mods: #E08AD0;
    --fontart-flow: linear-gradient(100deg, #F5D56A, #FF8DF6, #F5D56A, #FF8DF6, #F5D56A);
    --prisma-flow: linear-gradient(100deg, #ff9e95, #ffae55, #cfd149, #39faf1, #bfb9ff);
    --spectro-flow: linear-gradient(100deg, #8bfff8, #48e8e0, #40e2da, #48d3cb, #53c5bf);
    --heizwarte-flow: linear-gradient(100deg, #7dd3fc, #86efac, #fde047, #fdba74, #ff928f);
  }
}
/* Die Meta-Zeile der dunklen Materie (fest #8079a8) käme umgedreht auf 3,47,
   die Trennpunkte der Fußzeile (60 % Deckkraft) auf 3,06 */
:root[data-vision="invert"] .tool-dunkle-materie .tool-meta { color: #948DBD; }
:root[data-vision="invert"] .sep { opacity: 1; }

/* ── Werkstatt-Mods: Kachel (index.html) und Seite mods.html ─────────────────
   Pflaume als Kachelfarbe, hell gedaempft, dunkel aufgehellt (--mods oben je
   Themenblock). Die Seite zeigt fuenf aufklappbare <details>, je Mod ein Bild,
   die Installationszeile und ein Prompt mit Kopierknopf (js/mods.js). */
.tool-mods { --tool: var(--mods); }
.mods-bar { background: linear-gradient(90deg, var(--mods), var(--accent)); }
.mods { max-width: 920px; margin: 0 auto; padding: 0 8px 40px; }
.mods h2 { display: flex; align-items: center; gap: 12px; }
.mods-icon { width: 34px; height: 34px; border-radius: 8px; }
.mods-intro, .mods-how p, .mods-all p { color: var(--text-soft); line-height: 1.6; }
.mods-how, .mods-all { margin: 22px 0; }
.mods-how h3, .mods-all h3 { margin: 0 0 6px; color: var(--text); font-size: 1.05rem; }
.mods-hint { font-size: 0.92rem; }
.mods-list { display: grid; gap: 12px; margin: 22px 0; }
details.mod { background: var(--panel); border: 1px solid var(--border); border-top: 3px solid var(--mods); border-radius: 8px; }
details.mod summary { display: flex; align-items: center; gap: 12px; padding: 14px 18px; cursor: pointer; list-style: none; font-weight: 600; color: var(--text); }
details.mod summary::-webkit-details-marker { display: none; }
details.mod summary:hover { color: var(--mods); }
.mod-cmd { margin-left: auto; font-size: 0.85rem; font-weight: 400; color: var(--text-soft); }
.mod-chevron { color: var(--text-soft); transition: transform 0.2s; }
details.mod[open] .mod-chevron { transform: rotate(180deg); }
.mod-body { padding: 0 18px 18px; color: var(--text-soft); line-height: 1.6; }
.mod-body > p { margin: 0 0 12px; }
.mod-shot { margin: 0 0 14px; }
.mod-shot img { display: block; max-width: 100%; height: auto; border-radius: 6px; border: 1px solid var(--border); }
.mod-settings strong { color: var(--text); font-weight: 600; }
.mod-code { position: relative; margin: 14px 0; }
.mod-label { margin: 0 0 6px; font-size: 0.9rem; color: var(--text); }
.mod-line, .mod-prompt { margin: 0; padding: 12px 14px 44px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; font-size: 0.86rem; line-height: 1.55; white-space: pre-wrap; word-break: break-word; color: var(--text); }
.mod-line code, .mod-prompt code { font-family: ui-monospace, Consolas, "Cascadia Mono", monospace; }
.mod-prompt code { font-family: inherit; }
.copy-btn { position: absolute; right: 8px; bottom: 8px; padding: 6px 12px; border-radius: 6px; border: 1px solid var(--mods); background: transparent; color: var(--mods); font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer; }
.copy-btn:hover, .copy-btn:focus-visible, .copy-btn.is-copied { background: var(--mods); color: #fff; }
.mod-source { margin: 0; font-size: 0.92rem; }
.mod-source a { color: var(--accent); font-weight: 500; text-decoration: none; }
.mod-source a:hover { text-decoration: underline; }
@media (prefers-reduced-motion: reduce) { .mod-chevron { transition: none; } }
