/* d:picto — Grundoptik nach dem Entwurf d.picto.ai.
   Die Farben sind aus dem Layout abgenommen; sie stehen hier als Tokens,
   damit eine spaetere Korrektur an EINER Stelle passiert. */

/* Inter — dieselbe Schrift wie designstudios.ch (dort gemessen: Gewichte
   300 und 600). Selbst ausgeliefert statt von Google Fonts: der Shop soll
   bei jedem Seitenaufruf keinen Drittanbieter aufrufen, und Inter steht
   unter der SIL Open Font License. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/schriften/inter-v12-latin-300.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/schriften/inter-v12-latin-600.woff2') format('woff2');
}

:root {
  --blau-marke:  #105ba7;   /* aus dem Logo-SVG gemessen — das echte Markenblau */
  --blau-dunkel: #004a80;   /* Hero und Knopf (dunkler als das Markenblau) */
  --blau:        #1d6fa5;   /* Teasertext, Links */
  --grau:        #eef0f1;   /* Kacheln, Teaserflaechen */
  --grau-linie:  #c9ced1;
  --schwarz:     #1a1a1a;
  --grau-text:   #6b7276;
  --weiss:       #ffffff;

  /* Inter kennt nur diese zwei Gewichte — 400 oder 700 wuerde der Browser
     rechnerisch faelschen und die Schrift verzerren. */
  --schrift: 'Inter', system-ui, sans-serif;

  --gasse: 16px;            /* Seitenrand auf dem Telefon */
  --breite: 1120px;
  /* EIN Abstand fuer alles im Raster — Kacheln wie Teaser, auf jeder
     Schirmbreite derselbe Wert. Unterschiedliche Abstaende bei gleich
     aussehenden Flaechen lesen sich als Fehler. */
  --abstand: 12px;
  --logo-hoehe: 34px;
  --menue-unterlaenge: 3.02px;   /* »g« in Inter 600/14px, gemessen */
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--weiss);
  color: var(--schwarz);
  font-family: var(--schrift);
  font-weight: 300;
  -webkit-text-size-adjust: 100%;
}

b, strong { font-weight: 600; }

main, .kopf, .fuss {
  max-width: var(--breite);
  margin: 0 auto;
  padding-left: var(--gasse);
  padding-right: var(--gasse);
}

/* ---------- Kopf ---------- */

.kopf {
  display: flex;
  /* An der GRUNDLINIE, nicht mittig: Die Menüpunkte sollen auf derselben
     Fusslinie sitzen wie das Logo (Owner 29.09.2026). Mittig ausgerichtet
     sässen sie je nach Logohöhe mal höher, mal tiefer. */
  align-items: baseline;
  /* KEIN `space-between`: Das verteilt den Rest auch zwischen Menü und
     Korb, sobald die Kopfzeile breiter ist als ihr Inhalt — bei 820 px
     gemessene 154 px Abstand statt 24, das Menü hing in der Mitte. Der
     ganze Freiraum gehört links neben das Logo, dann steht alles Übrige
     als Block rechts. */
  justify-content: flex-start;
  padding-top: 28px;
  padding-bottom: 28px;
}

/* Das Logo ist eine SVG-Datei, kein Schriftnachbau: Helvetica Neue liegt
   auf Macs, aber nicht auf Windows und Android — dort waere die Marke auf
   Arial zurueckgefallen. Die Farbe steckt IM SVG (#105ba7) und wird hier
   bewusst nicht ueberschrieben. Das Verhaeltnis ist genau 3:1
   (viewBox 170.08 x 56.69), width und height im HTML halten den Platz frei,
   damit beim Laden nichts springt. */
/* Der ganze Freiraum landet hier — damit steht das Logo links und alles
   Übrige rechtsbündig beisammen, auf JEDER Breite. */
.marke {
  display: block;
  line-height: 0;
  margin-right: auto;
}

/* Die Menüpunkte sollen mit ihrer UNTERLÄNGE dort enden, wo das Logo
   endet — das »g« in »Piktogramme« auf derselben Linie wie das »p« in
   »d:picto« (Owner-Präzisierung 29.09.2026). Nicht Grundlinie auf
   Grundlinie: Das sass 2 px zu hoch, weil die Unterlänge des Logos tiefer
   reicht als seine Schriftlinie.

   Im SVG gemessen (viewBox 0 0 170.08 56.69): Grundlinie y = 42.43,
   Unterlänge des »p« y = 50.84. Die Unterlänge liegt also
   (56.69 − 50.84) / 56.69 = 10,31 % der Bildhöhe über der Bildunterkante.

   Die Baseline eines <img> ist seine Unterkante. Ein negativer unterer
   Aussenabstand hebt sie an, und `align-items: baseline` am Kopf richtet
   die Menüschrift daran aus. Nötig ist:

       10,31 % der Logohöhe   (Unterlänge des Logos über der Bildkante)
     + Unterlänge der Menüschrift

   Der zweite Summand hängt an der Schrift, nicht am Logo, und steht
   deshalb als eigene Variable: 3,02 px, am »g« in Inter 600/14 px im
   Browser gemessen. Wer die Menüschrift ändert, misst ihn neu —
   `scratchpad/fuss.mjs` tut genau das. */
.marke img {
  height: var(--logo-hoehe);
  width: auto;
  margin-bottom: calc(var(--logo-hoehe) * -0.1031 - var(--menue-unterlaenge));
}

/* Das Menü steht ab 1000 px in der Zeile; darunter übernimmt der
   Hamburger. Die Kopfzeile wird dafür zu vier Feldern: Marke, Menü,
   Warenkorb, Hamburger. */
/* Das Menü ist der NORMALFALL und steht sichtbar da. Bis 29.09.2026 war
   es umgekehrt (`display:none`, erst ab 1000 px sichtbar) — mit einem
   Hamburger, der keine Funktion hatte: Auf jedem Telefon waren die drei
   Punkte damit unerreichbar. Wann umgeschaltet wird, MISST jetzt
   `kopf.js`; ohne Skript bleibt das Menü sichtbar. */
.menue {
  display: flex;
  gap: 24px;
  font-size: 14px;
  font-weight: 600;
  margin-right: 24px;
  white-space: nowrap;
}
.menue a {
  color: var(--blau);
  text-decoration: none;
}
.menue a:hover { text-decoration: underline; }
.menue a[aria-current="page"] { color: var(--schwarz); }

/* Der Hamburger erscheint NUR, wenn gemessen zu wenig Platz ist. */
.burger { display: none; }
.kopf.eng .burger { display: block; }

/* Eng: Das Menü verlässt die Zeile und klappt unter der Kopfzeile auf.
   `position: absolute` statt eines Umbruchs, damit die Kopfhöhe gleich
   bleibt — eine Kopfzeile, die beim Öffnen wächst, schiebt die Seite. */
.kopf.eng .menue {
  display: none;
  position: absolute;
  top: 100%;
  /* Rechtsbündig unter dem Korb, nicht über die volle Breite: Das Menü
     gehört optisch zum Knopf, der es geöffnet hat. */
  right: var(--gasse);
  left: auto;
  min-width: 13em;
  z-index: 20;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: 4px 16px 12px;
  background: var(--weiss);
  border: 1px solid var(--grau-linie);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.10);
}
.kopf.eng.menue-offen .menue { display: flex; }
/* Grosse Trefferflächen: Auf dem Telefon wird mit dem Daumen gezielt. */
.kopf.eng .menue a {
  padding: 11px 0;
  border-top: 1px solid var(--grau-linie);
}
.kopf.eng .menue a:first-child { border-top: 0; }

/* Die Kopfzeile trägt das aufgeklappte Menü und muss es verankern. */
.kopf { position: relative; }

/* Im aufgeklappten Zustand werden aus den zwei Strichen ein Kreuz — der
   Knopf sagt damit, was der nächste Klick tut. */
.kopf.menue-offen .burger span:first-child {
  transform: translateY(3.5px) rotate(45deg);
}
.kopf.menue-offen .burger span:last-child {
  transform: translateY(-3.5px) rotate(-45deg);
}
.burger span { transition: transform 0.15s; }

.korb {
  /* Symbole haben keine Grundlinie: Der Korb richtet sich an der Mitte
     des Logos aus, nicht an der Schriftlinie der Menüpunkte. */
  align-self: center;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  text-decoration: none;
  color: var(--blau-dunkel);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
/* Das Symbol ist SS103 «Warenkorb» aus der eigenen Serie — kein
   Unicode-Emoji: das wird auf jeder Plattform anders gezeichnet und wäre
   in einem Piktogramm-Shop ein Fremdkörper. */
.korb-symbol { display: block; width: 22px; height: 22px; }
@media (max-width: 999px) {
  /* Auf dem Telefon steht der Korb links vom Hamburger.
     KEIN `margin-left: auto` mehr: Das war ein ZWEITER automatischer
     Aussenabstand neben dem am Logo, und zwei davon TEILEN SICH den
     Freiraum. Gemessen bei 960 px: 200 px links vom Menü, 224 px
     rechts davon — das Menü hing in der Mitte, obwohl sein Abstand zum
     Korb auf 24 px stand. Den ganzen Freiraum nimmt jetzt allein das
     Logo, und alles Übrige steht als Block rechts. */
  .korb { margin-right: 14px; }
}

.burger {
  align-self: center;
  background: none;
  border: 0;
  padding: 6px 0;
  cursor: pointer;
  width: 34px;
}
.burger span {
  display: block;
  height: 2px;
  background: var(--blau-dunkel);
  margin: 5px 0;
}

/* ---------- Hero ---------- */

/* EINE Höhe auf allen Seiten (Owner-Vorgabe 28.09.2026), abgeleitet von
   der Einstiegsseite: dort füllen sechs Textzeilen plus Innenabstand rund
   210 px. Auf Katalog- und Suchseiten ist der Block leer, die Mindesthöhe
   hält ihn trotzdem auf demselben Mass. `aria-hidden` bekommt er dort,
   weil er noch keinen Inhalt trägt — ein Screenreader soll keine leere
   Region ansagen. */
.hero {
  background: var(--blau-dunkel);
  color: var(--weiss);
  min-height: 210px;
  padding: 28px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  font-size: 17px;
  line-height: 1.5;
}
.hero p { margin: 0; }
.hero-zahl { font-weight: 600; margin-bottom: 2px !important; }


/* ---------- Suche ---------- */

.suche {
  display: flex;
  margin-top: 8px;
  max-width: 660px;
}
.suche input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-weight: 600;
  color: var(--blau-dunkel);
  background: var(--grau);
  border: 1px solid var(--grau-linie);
  border-right: 0;
  padding: 9px 12px;
}
.suche input::placeholder { color: var(--blau-dunkel); opacity: 1; }

/* Der hellblaue Ring des Browsers bringt hier nichts — das Feld ist als
   Eingabe erkennbar, und der Ring liegt als Fremdkörper über der eigenen
   Gestaltung.
   ABER: Er wird ERSETZT, nicht entfernt. Wer mit der Tastatur arbeitet,
   muss sehen, wo er steht; ein ersatzloses `outline: none` macht das Feld
   für Tastaturnutzer unsichtbar. Statt des Rings wird der Rahmen des
   Feldes dunkel — ruhiger, aber eindeutig. */
.suche input:focus,
.suche button:focus {
  outline: none;
}
.suche:focus-within input,
.suche:focus-within button {
  border-color: var(--blau-dunkel);
}
.suche:focus-within input {
  background: var(--weiss);
}
.suche button {
  flex: 0 0 auto;
  font-size: 17px;
  line-height: 1;
  color: var(--weiss);
  background: var(--blau-dunkel);
  border: 1px solid var(--blau-dunkel);
  padding: 9px 20px;
  cursor: pointer;
}

/* ---------- Familien ---------- */

.familien { margin-top: 34px; }
.familien h2 {
  font-size: 13px;
  font-weight: 600;
  margin: 0 0 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--grau-linie);
}

/* Auf breiten Schirmen alle neun Familien auf einmal — sie sind der
   Haupteinstieg in den Katalog, und was man wegblaettern muss, wird
   seltener gefunden. Platz ist dort genug. */
/* `minmax(0, 1fr)` statt `1fr`: Ein blosses `1fr` bedeutet
   `minmax(auto, 1fr)`, und `auto` als Minimum ist die min-content-Breite.
   Die längste Beschriftung ("Orientierung &") dehnt damit ihre Spalte, das
   Raster wird breiter als sein Container und läuft rechts aus dem Bild —
   was aussieht, als stimmte die Spaltenzahl nicht. Die 0 erlaubt das
   Schrumpfen. */
.kacheln {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--abstand);
}
@media (min-width: 1000px) { .kacheln { grid-template-columns: repeat(9, minmax(0, 1fr)); } }

/* Auf dem Telefon drei Spalten, vertikal gescrollt — das ist die
   Grundform, und sie gilt für die FAMILIENSEITEN mit ihren bis zu 47
   Motiven. Dort ist ein Streifen falsch: zu viele Elemente, und man
   vergleicht sie miteinander. */
@media (max-width: 699px) {
  .kacheln { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Die STARTSEITE wischt dagegen (Owner-Entscheid 28.09.2026, am Gerät
   erprobt — das Auswählen funktioniert). Sie hat genau neun Familien:
   überschaubar, einmal durchgewischt, und der Gewinn ist gross. Gerechnet
   für 390 px: eine Reihe statt drei spart über 300 px und holt die Teaser
   ("Vektor", "Pro") in den ersten Bildschirm, wo sie sonst bei 866 px
   liegen und nie gesehen werden.

   Der Anschnitt ist der tragende Teil: 2.2 Kacheln passen ins Bild, die
   dritte ragt herein. Ein Streifen, der glatt am Rand endet, sieht
   vollständig aus — dann sucht niemand weiter. */
@media (max-width: 699px) {
  .kacheln--streifen {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
  .kacheln--streifen::-webkit-scrollbar { display: none; }

  .kacheln--streifen .kachel {
    flex: 0 0 calc((100% - 2 * var(--abstand)) / 2.2);
    scroll-snap-align: start;
  }
}

/* `min-width: 0` durch die ganze Kette: Item -> Link -> Beschriftung
   -> Name. VORSORGE, kein behobener Fehler — gemessen passt das Raster
   (scrollWidth 468 = Containerbreite 468). Der Grund, es trotzdem zu
   setzen: `minmax(0, 1fr)` löst nur die SPALTE; Grid-Items und Flex-Kinder
   behalten `min-width: auto` (= min-content) und würden bei einem langen
   Motivnamen über ihre Spalte hinauslaufen. Der Katalog wächst noch, und
   dieser Fehler fällt erst beim längsten Namen auf. */
.kachel {
  min-width: 0;
}
.kachel a {
  display: block;
  min-width: 0;
  text-decoration: none;
  color: inherit;
}
.kachel .bild {
  background: var(--grau);
  /* IMMER quadratisch (Owner-Vorgabe 28.09.2026), auf jeder Schirmbreite.
     Das entspricht dem Gegenstand: Piktogramme sind auf einem Raster von
     72 x 72 konstruiert. Ein flacheres Feld auf dem Telefon hätte Höhe
     gespart, aber ein Piktogramm in einem liegenden Rahmen sieht aus wie
     ein Fehler im Beschnitt. */
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 300;
  color: var(--blau-dunkel);
}

/* Beschriftung: Name links (immer zweizeilig, umgebrochen nach dem &),
   Anzahl rechtsbuendig daneben, darunter eine 1px-Linie. Der Umbruch ist
   fest und nicht dem Zufall der Spaltenbreite ueberlassen — sonst stehen
   die Linien je Kachel auf anderer Hoehe und das Raster zerfaellt. */
/* Die Schriftgroesse steht HIER, nicht erst auf .name — sonst rechnen die
   em-Werte unten gegen die geerbten 16px des body statt gegen die 11px der
   Bezeichnung. Genau das war der Fehler: min-height ergab 45 px statt 30 px
   und liess die Linie 17.5 px zu tief stehen. */
.kachel .beschriftung {
  display: flex;
  min-width: 0;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  font-size: 11px;
  line-height: 1.25;
  margin-top: 5px;
  /* 0.25em = 2.75 px, genau der Durchschuss zwischen zwei Textzeilen
     (13.75 px Zeilenhoehe minus 11 px Schriftgroesse). Der Abstand bis zur
     Linie ist damit derselbe wie der Abstand der beiden Namenszeilen. */
  padding-bottom: 0.25em;
  border-bottom: 1px solid var(--grau-linie);
  /* Zwei Zeilen plus derselbe Abstand — damit alle Linien auf einer Hoehe
     liegen, auch wenn ein Name einmal nur eine Zeile braucht. */
  min-height: calc(2 * 1.25em + 0.25em);
}
.kachel .name {
  font-weight: 600;
  /* Bei schmalen Kacheln darf ein langes Wort umbrechen statt die Spalte
     zu sprengen. */
  overflow-wrap: break-word;
  min-width: 0;
}
.kachel .anzahl {
  font-weight: 300;
  color: var(--grau-text);
  text-align: right;
  flex: 0 0 auto;
  /* Ziffern gleicher Breite: sonst tanzen die Zahlen in der Spalte. */
  font-variant-numeric: tabular-nums;
}

.kachel--laedt { background: var(--grau); aspect-ratio: 1 / 1; }


/* ---------- Katalogseite ---------- */

/* Strukturwechsel bei 1000 px (Spec 25.09.2026): darüber Filterspalte
   links, darunter liegt die Familienliste über dem Raster. Der Wert liegt
   knapp unter dem iPad im Querformat (1024 px), damit ein Tablet noch das
   zweispaltige Layout bekommt. */
.katalog-raster {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  margin-top: 26px;
}
@media (min-width: 1000px) {
  .katalog-raster {
    grid-template-columns: 280px minmax(0, 1fr);
    gap: 32px;
  }
  /* Bleibt beim Scrollen stehen — sonst verliert man beim Auswählen den
     Überblick, welche Familien offen sind. `sticky` wirkt nur, wenn kein
     Vorfahr `overflow` beschneidet. */
  .filter {
    position: sticky;
    top: 20px;
    align-self: start;
  }
}

.familienliste {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
}
.familienliste li {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px solid var(--grau-linie);
}
.familienliste li.alle { margin-bottom: 10px; }
.familienliste a {
  color: var(--blau);
  text-decoration: none;
}
.familienliste a:hover { text-decoration: underline; }
/* Offene Familien stehen schwarz.
   Die Farbe MUSS auch auf dem `a` stehen, nicht nur auf dem `li`: Beim
   Aufklappen per Skript bleibt der Name ein Link, und `.familienliste a`
   überschreibt die Vererbung — der Eintrag blieb blau, obwohl die Familie
   offen war. Serverseitig fiel das nicht auf, weil die offene Familie dort
   überhaupt kein Link ist. */
.familienliste li.offen,
.familienliste li.offen a { color: var(--schwarz); }
/* Und die Unterstreichung weg: ein schwarzer Eintrag ist kein Ziel mehr,
   der Klick schliesst ihn nur. */
.familienliste li.offen a:hover { text-decoration: none; }
.familienliste .zahl {
  font-weight: 300;
  color: var(--grau-text);
  font-variant-numeric: tabular-nums;
}

.auswahlblock {
  font-size: 12px;
  border-top: 1px solid var(--grau-linie);
  padding-top: 10px;
}
.auswahl-kopf {
  display: flex;
  justify-content: space-between;
  font-weight: 600;
  margin: 0 0 6px;
}
.auswahl-hinweis {
  color: var(--grau-text);
  font-weight: 300;
  line-height: 1.35;
  margin: 0 0 10px;
}
.auswahlblock p { margin: 0 0 8px; }
.auswahlblock a { color: var(--blau); text-decoration: none; }

.btn {
  font: inherit;
  font-weight: 600;
  color: var(--weiss);
  background: var(--blau-dunkel);
  border: 0;
  padding: 9px 16px;
  cursor: pointer;
  width: 100%;
}
.btn:hover { background: var(--blau-marke); }

.familienblock { margin-bottom: 30px; }

/* Die Kachelgrösse ist FEST (120 px, schmal 104 px) und die Spaltenzahl
   ergibt sich daraus — nicht umgekehrt. Mit fester Spaltenstaffel
   schwankte die Kachel zwischen 46 und 214 px und sprang an den
   Umschaltpunkten; so bleibt sie bei 120–144 px (Spec 25.09.2026, dort
   durchgerechnet). Der Deckel verhindert, dass sie bei 1100 px
   Fensterbreite auf 153 px aufgeblasen wird. */
.kacheln-bereich .kacheln {
  grid-template-columns: repeat(auto-fill, minmax(104px, 144px));
}
@media (min-width: 700px) {
  .kacheln-bereich .kacheln {
    grid-template-columns: repeat(auto-fill, minmax(120px, 144px));
  }
}

.kachelknopf {
  display: block;
  width: 100%;
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  min-width: 0;
  cursor: pointer;
  color: inherit;
}
/* Der Auswahlzustand liegt auf dem Bildfeld, nicht auf der ganzen Kachel:
   der Rahmen soll das Piktogramm einfassen, nicht die Legende. */
.kachelknopf .bild {
  /* Eckig, überall (Owner-Vorgabe 28.09.2026) — der Layout-Entwurf zeigt
     abgerundete Kacheln, das ist verworfen. */
  border: 1px solid transparent;
  transition: border-color 0.12s;
}
.kachelknopf:hover .bild { border-color: var(--grau-linie); }
.kachelknopf.gewaehlt .bild { border-color: var(--blau-marke); }
.kachelknopf:focus-visible .bild { outline: 2px solid var(--blau-marke); outline-offset: 2px; }

/* Legende im Katalog: kleiner als auf der Startseite und OHNE Trennlinie —
   sie kostet dort nur Höhe und gewinnt nichts, weil die Kacheln in einem
   dichten Raster stehen und der Rahmen schon die Einheit markiert. */
.kacheln-bereich .beschriftung {
  border-bottom: 0;
  min-height: 0;
  font-size: 10px;
  padding-bottom: 0;
  margin-top: 4px;
}
.kacheln-bereich .name { font-weight: 600; }
.kacheln-bereich .anzahl { font-weight: 300; }

/* Auf dem Telefon liegt der Auswahlblock aus dem Bild — dort erscheint er
   als Leiste am unteren Rand, sobald etwas gewählt ist. */
.korbleiste {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  background: var(--weiss);
  border-top: 1px solid var(--grau-linie);
  box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
  font-size: 13px;
  z-index: 10;
}
.korbleiste .btn { width: auto; }
@media (min-width: 1000px) {
  /* Auf breiten Schirmen steht der Block in der Filterspalte. */
  .korbleiste { display: none; }
}

/* ---------- Familienseite, Suche, Fehlerseite ---------- */

.brotkrumen {
  margin: 4px 0 20px;
  font-size: 12px;
}
.brotkrumen a {
  color: var(--blau);
  text-decoration: none;
}
.brotkrumen a:hover { text-decoration: underline; }

/* Der Titel steht im selben Raster wie "Piktogrammfamilien" auf der
   Startseite — gleiche Linie, gleiche Höhe, damit die beiden Seiten als
   eine Familie lesbar sind. */
.familientitel {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: 13px;
  font-weight: 600;
  margin: 0 0 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--grau-linie);
}
/* Die Zahl ganz rechts, der Schalter direkt nach dem Namen — so steht er
   dort, wo der Blick nach dem Familiennamen ohnehin hinwandert, und nicht
   in der Ecke. */
.familienzahl { margin-left: auto; }

.alle-waehlen {
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--blau);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.alle-waehlen:hover { text-decoration: underline; }
.alle-waehlen.aktiv { color: var(--schwarz); }
.familienzahl {
  font-weight: 300;
  color: var(--grau-text);
  font-variant-numeric: tabular-nums;
}

.fehlerseite {
  padding: 40px 0 80px;
  max-width: 34em;
}
.fehlerseite h1 {
  font-size: 28px;
  font-weight: 600;
  color: var(--blau-dunkel);
  margin: 0 0 12px;
}
.fehlerseite p {
  font-size: 17px;
  line-height: 1.5;
  margin: 0 0 10px;
}
.fehlerseite a {
  color: var(--blau-dunkel);
  font-weight: 600;
}

/* ---------- Teaser ---------- */

.teaser {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--abstand);
  margin: 34px 0 60px;
}
@media (min-width: 700px) { .teaser { grid-template-columns: repeat(3, 1fr); } }

.teaser article {
  background: var(--grau);
  padding: 22px 24px 26px;
  font-size: 23px;
  line-height: 1.35;
  color: var(--blau);
  font-weight: 300;
}
.teaser p { margin: 0; }
.teaser a {
  color: var(--blau-dunkel);
  font-weight: 600;
  text-decoration: none;
}
.teaser a:hover { text-decoration: underline; }

/* ---------- Infoseiten ---------- */

.infoseite {
  padding-top: 30px;
  padding-bottom: 70px;
  max-width: 46em;
}
.infoseite h1 {
  font-size: 30px;
  font-weight: 600;
  color: var(--blau-dunkel);
  margin: 0 0 14px;
  line-height: 1.2;
}
.infoseite .lead {
  font-size: 20px;
  font-weight: 300;
  line-height: 1.45;
  color: var(--blau);
  margin: 0 0 32px;
}
.infoabschnitt {
  border-top: 1px solid var(--grau-linie);
  padding-top: 14px;
  margin-bottom: 22px;
}
.infoabschnitt h2 {
  font-size: 17px;
  font-weight: 600;
  margin: 0;
}
.offen-hinweis {
  background: var(--grau);
  padding: 14px 16px;
  font-size: 13px;
  color: var(--grau-text);
  line-height: 1.45;
}

/* ---------- Fuss ---------- */

.fuss {
  border-top: 1px solid var(--grau-linie);
  padding-top: 16px;
  padding-bottom: 40px;
  font-size: 12px;
  color: var(--grau-text);
}

/* Auf dem Telefon ist Höhe das knappe Gut, und die Kacheln sind
   unantastbar quadratisch. Der Platz kommt deshalb aus Kopf und Hero —
   dort kostet er nichts: 210 px für sechs Textzeilen waren grosszügig,
   und das Logo braucht keine 28 px Luft nach oben und unten.

   Was damit NICHT erreicht wird: die Teaser in den ersten Bildschirm zu
   holen. Mit drei quadratischen Spalten beginnen sie bei rund 800 px, ein
   iPhone zeigt 724 px. Das ist in Ordnung — auf einer Startseite scrollt
   man, und die Kacheln sind das Produkt. Wer sie kleiner macht, damit ein
   Teaser hineinpasst, tauscht das Wichtige gegen das Zweitwichtige. */
@media (max-width: 699px) {
  .kopf {
    padding-top: 20px;
    padding-bottom: 18px;
  }
  .marke img { height: 30px; }

  .hero {
    /* Auf der Startseite bestimmt der Text die Höhe (sechs Zeilen zu je
       22.4 px plus 40 px Innenabstand = 174 px). Genau dieser Wert gilt
       auch dort, wo der Block leer ist, damit er auf ALLEN Seiten gleich
       hoch steht (Owner-Vorgabe 28.09.2026). */
    min-height: 174px;
    padding: 20px;
    font-size: 16px;
    line-height: 1.4;
  }

  .familien { margin-top: 24px; }
  .teaser { margin-top: 24px; }
  .teaser article { font-size: 20px; padding: 18px 20px 22px; }
}

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

/* ---------- Warenkorb ---------- */

/* Dieselbe Breite wie die Piktogrammseite (--breite, über `main` geerbt) —
   Owner-Vorgabe 29.09.2026. Mein erster Entwurf war schmaler, mit dem
   Argument "hier wird geprüft, nicht gestöbert"; das zerschneidet aber den
   Weg: Der Kunde kommt aus dem Katalog, und ein springender Satzspiegel
   lässt den Korb wie eine fremde Seite wirken. Die Formulare weiter unten
   bleiben schmal — das ist Zeilenlänge im Eingabefeld, nicht Satzspiegel. */
.warenkorb {
  padding-top: 30px;
  padding-bottom: 70px;
}
.warenkorb h1 {
  font-size: 30px;
  font-weight: 600;
  color: var(--blau-dunkel);
  margin: 0 0 24px;
  line-height: 1.2;
}
.korb-laedt { color: var(--grau-text); font-weight: 300; }

.korb-leer { color: var(--grau-text); font-weight: 300; }
.korb-leer .btn {
  width: auto;
  display: inline-block;
  text-decoration: none;
  margin-top: 6px;
}

/* Die sechs Schritte tragen dieselbe Linie wie die Infoabschnitte — es ist
   dieselbe Gliederungsebene und darf nicht wie eine zweite Sprache wirken. */
.korb-schritt {
  border-top: 1px solid var(--grau-linie);
  padding-top: 14px;
  margin-bottom: 30px;
}
.korb-schritt h2 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 17px;
  font-weight: 600;
  color: var(--schwarz);
  margin: 0 0 10px;
}
/* Die Schrittzahl führt durch den Ablauf, ohne ihn zu dominieren: Sie ist
   Orientierung, nicht Inhalt. */
.schrittzahl {
  font-weight: 300;
  color: var(--grau-text);
  font-variant-numeric: tabular-nums;
}
.schrittzahl-rechts {
  margin-left: auto;
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  color: var(--grau-text);
}

.korb-hinweis {
  font-size: 12px;
  font-weight: 300;
  line-height: 1.4;
  color: var(--grau-text);
  margin: 0 0 12px;
}
.korb-hinweis a { color: var(--blau); text-decoration: none; }
.korb-hinweis a:hover { text-decoration: underline; }

/* Ein weggefallenes Piktogramm ist keine Randnotiz: Ohne sichtbare Warnung
   sucht der Kunde den Fehler bei sich. */
.korb-warnung {
  font-size: 12px;
  line-height: 1.4;
  color: var(--schwarz);
  background: var(--grau);
  border-left: 3px solid var(--blau-marke);
  padding: 8px 10px;
  margin: 0 0 12px;
}

/* ---------- Kacheln im Korb ---------- */

/* ≈72 px statt der 120 px des Katalogs: Im Korb wird geprüft, und 22 Stück
   sollen ohne Scrollen in zwei Reihen stehen. Der Deckel bei 88 px
   verhindert, dass wenige Positionen auf breitem Schirm aufgeblasen werden. */
.korbkacheln {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 88px));
  gap: var(--abstand);
}
.korbkachel {
  position: relative;
  min-width: 0;
}
.korbkachel .bild {
  background: var(--grau);
  aspect-ratio: 1 / 1;      /* quadratisch und eckig, wie überall */
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 300;
  color: var(--blau-dunkel);
}
/* 9 px, kleiner als im Katalog: Kontrolliert wird am BILD (Owner
   29.09.2026) — der Name ist die Stütze für den Zweifelsfall und den
   Screenreader, nicht das Führende. Er darf deshalb leiser sein als die
   Kachel selbst. */
.korbkachel .beschriftung {
  display: block;
  margin-top: 4px;
  font-size: 9px;
  line-height: 1.3;
}
/* Der Name MUSS hier stehen — im Korb kontrolliert man eine Liste, und
   dafür braucht es Wörter (Spec). Zwei Zeilen, dann abgeschnitten: Sonst
   stehen die Kacheln je nach Namenslänge auf verschiedener Höhe. */
.korbkachel .name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-weight: 600;
  /* Ohne das schneidet "Gepäckschliessfach" mitten im Wort ab: Ein langes
     Wort ohne Trennstelle passt in keine 72-px-Zeile, bricht nicht um und
     läuft in den overflow. So bricht es hart um und die zweite Zeile wird
     benutzt, für die der Platz ohnehin reserviert ist. */
  overflow-wrap: anywhere;
}
.korbkachel .code {
  display: block;
  font-weight: 300;
  color: var(--grau-text);
  font-variant-numeric: tabular-nums;
}

/* Entfernen sitzt AN der Kachel, nicht in einer Aktionsspalte: Die Spec
   verlangt es dort, und bei 72 px ist der Weg zur Zeile sonst weiter als
   zum Ziel. */
.entfernen {
  position: absolute;
  top: 0;
  right: 0;
  width: 20px;
  height: 20px;
  line-height: 18px;
  text-align: center;
  font-size: 15px;
  font-weight: 300;
  color: var(--weiss);
  background: var(--schwarz);
  border: 0;
  padding: 0;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s;
}
.korbkachel:hover .entfernen,
.entfernen:focus-visible { opacity: 1; }
/* Auf dem Telefon gibt es kein Hover — dort steht das Kreuz immer. */
@media (hover: none) {
  .entfernen { opacity: 1; }
}

/* Der Schalter, der die Einzelauswahl überhaupt erst einblendet. Als
   Textknopf, nicht als Kasten: Er ist eine Nebentür und soll die
   Kachelreihe nicht anführen. */
.einzelzeile { margin: 0 0 10px; }
.einzelschalter {
  font: inherit;
  font-size: 12px;
  font-weight: 300;
  color: var(--blau);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
}
.einzelschalter:hover { text-decoration: underline; }
.einzelschalter[aria-pressed="true"] { font-weight: 600; }

/* Abweichende Variante je Position: normalerweise GAR NICHT da. Sie
   erscheint, wenn der Schalter oben an ist — oder wenn diese eine Position
   abweicht, denn eine getroffene Entscheidung darf nie unsichtbar werden,
   auch nicht nach dem Ausschalten.

   Ein- und ausgeblendet wird über DIESELBE Struktur, nur die Klasse
   schaltet: Zwei verschiedene Markup-Formen für zwei Zustände haben hier
   schon zweimal Farbfehler erzeugt. */
.positionsvariante {
  display: block;
  width: 100%;
  margin-top: 3px;
  font: inherit;
  font-size: 9px;
  font-weight: 300;
  text-align: left;
  color: var(--grau-text);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  visibility: hidden;   /* nicht `display:none` — die Kachelhöhe bleibt gleich */
}
.korbkacheln.einzeln .positionsvariante,
.positionsvariante.abweichend { visibility: visible; }
.positionsvariante:hover { color: var(--blau); }
.positionsvariante.abweichend {
  font-weight: 600;
  color: var(--blau-marke);
}

/* ---------- Variante und Verwendung ---------- */

.wahl {
  display: grid;
  gap: var(--abstand);
  grid-template-columns: 1fr;
}
@media (min-width: 700px) {
  .wahl { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
}
.wahlfeld {
  display: block;
  position: relative;
  padding: 12px 14px;
  background: var(--grau);
  border: 1px solid transparent;   /* eckig, kein Radius */
  cursor: pointer;
}
.wahlfeld:hover { border-color: var(--grau-linie); }
/* :has trägt hier: Fällt es aus (alte Browser), bleibt das Feld nur ohne
   Rahmen — die Radiobutton selbst zeigt den Zustand weiterhin an. */
.wahlfeld:has(input:checked) {
  border-color: var(--blau-marke);
  background: var(--weiss);
}
.wahlfeld:has(input:focus-visible) {
  outline: 2px solid var(--blau-marke);
  outline-offset: 2px;
}
.wahlfeld input { margin-right: 6px; accent-color: var(--blau-marke); }
.wahltitel { font-weight: 600; font-size: 14px; }
.wahltext {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  font-weight: 300;
  line-height: 1.4;
  color: var(--grau-text);
}
.wahlpreis {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--blau-dunkel);
  font-variant-numeric: tabular-nums;
}

/* ---------- Preis ---------- */

.preistabelle {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.preistabelle th,
.preistabelle td {
  text-align: left;
  padding: 7px 0;
  font-weight: 300;
  border-bottom: 1px solid var(--grau-linie);
}
.preistabelle th { font-weight: 600; }
/* Zahlen rechtsbündig mit tabular-nums: untereinander stehende Beträge,
   die nicht fluchten, liest diese Zielgruppe als Schlamperei. */
.preistabelle .stueck,
.preistabelle .betrag {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.preistabelle .stueck { color: var(--grau-text); font-size: 12px; }
.preistabelle .summe th,
.preistabelle .summe td {
  font-weight: 600;
  border-bottom: 0;
  border-top: 1px solid var(--schwarz);
  padding-top: 9px;
}
.preis-fuss {
  font-size: 11px;
  font-weight: 300;
  color: var(--grau-text);
  margin: 8px 0 0;
}

/* ---------- Adresse und Anfrage ---------- */

.adressformular,
.anfrageformular {
  display: grid;
  gap: 10px var(--abstand);
  grid-template-columns: 1fr;
  max-width: 34em;
}
@media (min-width: 700px) {
  .adressformular { grid-template-columns: 1fr 1fr; }
  .feld-schmal { max-width: 8em; }
  .feld-breit { grid-column: 1 / -1; }
}
.feld { margin: 0; display: flex; flex-direction: column; }
.feld label {
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 3px;
}
/* Der Punkt markiert Pflichtfelder. Ein Sternchen liest sich als Fussnote
   und braucht eine Legende, die sonst nirgends steht. */
.pflicht { color: var(--blau-marke); }
/* type fehlt bei keinem Feld — ein <input> ohne type fällt durch diese
   Regel und steht dann in der Browsergrundoptik. */
.feld input,
.feld select,
.feld textarea {
  font: inherit;
  font-size: 14px;
  font-weight: 300;
  padding: 7px 9px;
  border: 1px solid var(--grau-linie);
  background: var(--weiss);
  color: var(--schwarz);
  min-width: 0;
}
.feld input:focus,
.feld select:focus,
.feld textarea:focus {
  outline: 2px solid var(--blau-marke);
  outline-offset: -1px;
  border-color: var(--blau-marke);
}
.feldhilfe {
  font-size: 11px;
  font-weight: 300;
  color: var(--grau-text);
  margin-top: 3px;
}
.anfrageformular { grid-template-columns: 1fr; }
.anfrageformular textarea { resize: vertical; }

/* Die Abzweigung für Weiterverkauf: deutlich abgesetzt, weil sie den
   Kaufweg ERSETZT und nicht ergänzt. */
.korb-anfrage {
  border-top: 1px solid var(--grau-linie);
  padding-top: 14px;
  margin-bottom: 30px;
}
.korb-anfrage h2 {
  font-size: 17px;
  font-weight: 600;
  margin: 0 0 8px;
  color: var(--blau-dunkel);
}
.korb-anfrage > p {
  font-size: 14px;
  font-weight: 300;
  line-height: 1.5;
  max-width: 40em;
  margin: 0 0 16px;
}
.korb-anfrage .btn { width: auto; }

.btn-gross { width: auto; padding: 12px 22px; font-size: 15px; }
.btn:disabled {
  background: var(--grau-linie);
  color: var(--weiss);
  cursor: not-allowed;
}
.btn:disabled:hover { background: var(--grau-linie); }

/* ---------- Abschlussseite ---------- */

.bestellseite h1 {
  font-size: 26px;
  margin-bottom: 8px;
}
.lead-bestellung {
  font-size: 16px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--blau);
  margin: 0 0 30px;
  max-width: 44em;
}

/* Der Beleg ist eine Liste von Angaben, keine Rechnung mit Beträgen —
   deshalb linksbündig und ohne die Zahlenausrichtung der Preistabelle. */
.belegtabelle {
  border-collapse: collapse;
  font-size: 14px;
  max-width: 44em;
}
.belegtabelle th,
.belegtabelle td {
  text-align: left;
  vertical-align: top;
  padding: 5px 0;
  font-weight: 300;
}
.belegtabelle th {
  font-weight: 600;
  width: 11em;
  padding-right: var(--abstand);
}

/* Die Kacheln der Abschlussseite sind nicht bedienbar: kein Entfernen,
   kein Umschalten. Was gekauft ist, ist gekauft. */
.bestellseite .korbkachel { cursor: default; }

.kassezeile { margin: 14px 0 8px; }

/* ---------- Umgebungs-Kennzeichnung ---------- */

/* Übernommen aus der Auftragsverwaltung (`--env-lokal-bg`,
   `--env-staging-bg`), Werte unverändert: Dieselbe Farbe muss in beiden
   Werkzeugen dasselbe heissen, sonst ist sie schlechter als keine.

     lokal (dieser Mac) → rot
     Staging            → gelb
     Produktion         → KEINE Hinterlegung — der Normalfall bleibt ruhig

   Kräftiger als eine übliche Warnfläche, weil eine ganze Leiste sonst wie
   ein Rendering-Fehler wirkt statt wie eine Warnung. */
:root {
  --env-lokal-bg: rgba(177, 40, 31, 0.16);
  --env-staging-bg: rgba(214, 158, 0, 0.24);
}

body[data-umgebung="lokal"] .kopf   { background: var(--env-lokal-bg); }
body[data-umgebung="staging"] .kopf { background: var(--env-staging-bg); }

/* Die Kopfzeile ist zentriert und schmaler als das Fenster — ohne das
   endet die Farbe mitten im Bild und sieht nach Fehler aus. Der Streifen
   läuft deshalb über die volle Breite. */
body[data-umgebung="lokal"] .kopf,
body[data-umgebung="staging"] .kopf {
  box-shadow: -50vw 0 0 var(--env-farbe), 50vw 0 0 var(--env-farbe);
}
body[data-umgebung="lokal"]   { --env-farbe: var(--env-lokal-bg); }
body[data-umgebung="staging"] { --env-farbe: var(--env-staging-bg); }

/* Das Wort stand hier bis 29.09.2026 neben dem Logo und ist auf
   Owner-Wunsch weg: Der Farbcode ist eingeführt und eindeutig, das Wort
   war Doppelung. Für Screenreader trägt `title` am <body> (kopf.js) — die
   Farbe allein wäre dort keine Aussage. */
