/* Die eine Oberfläche, die gut aussehen muss. Ruhig, viel Weißraum, keine
   Spielereien — die Zielgruppe entscheidet über Seriosität. Alle Farben und
   Schriften kommen aus /theme.css.

   Statisch aus public/ ausgeliefert und nicht über den Vite-Bundle: per
   JavaScript nachgeladenes CSS erzeugt einen Blitz ungestylten Inhalts, und
   diese Seite ist das Produkt. */

*, *::before, *::after { box-sizing: border-box; }

/* Keine Bildlaufleiste. Nicht aus Ziererei: die Seite wird auf Telefonen
   benutzt, wo das System ohnehin keine anzeigt, und auf dem Onepager steckt sie
   in einem gezeichneten Gerät, in dem ein Betriebssystem-Balken den Eindruck
   sofort bricht. Gescrollt wird weiter, nur ohne Leiste.

   Auf `html`, nicht auf `body`: den Bildlauf des Dokuments führt in allen
   aktuellen Browsern das Wurzelelement. */
html {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html::-webkit-scrollbar { display: none; }

body {
  margin: 0;
  background: var(--bg, #0b0b0c);
  color: var(--text, #fff);
  font-family: var(--font-body, system-ui), sans-serif;
  font-weight: var(--font-body-weight, 400);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Kopf und Inhalt teilen sich dieselbe Spalte: gleiche Maximalbreite, gleiche
   Zentrierung, gleiches Innenmaß. Nur so steht die linke Logokante exakt über
   der linken Kante der Überschrift — an der Ansichtskante ausgerichtet stünde
   es auf einem breiten Bildschirm weit daneben. */
.head,
.wrap { max-width: 560px; margin: 0 auto; }

/* Logo links, Pille rechts. `wrap` mit `gap`, weil beide zusammen auf einem
   schmalen Telefon nicht nebeneinander passen — dann rutscht die Pille unter
   das Logo, statt eines von beiden zu quetschen. */
.head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  padding: 24px clamp(16px, 5vw, 48px);
}
.wrap { padding: 8px clamp(16px, 5vw, 48px) 64px; }

/* Höhe aus `--logo-height` (kommt aus theme.css), Breite aus dem
   Seitenverhältnis. **Nicht als style-Attribut am Bild**: in Produktion gilt
   `style-src 'self'`, und der Browser verwirft Inline-Styles dann kommentarlos.
   `min-width: 0` erlaubt dem Logo, in der Flex-Zeile zu schrumpfen, statt die
   Pille umzubrechen. */
.logo {
  display: block;
  height: var(--logo-height, 40px);
  width: auto;
  max-width: 100%;
  min-width: 0;
  object-fit: contain;
  object-position: left center;
}
.brand { display: flex; min-width: 0; }
.logo-text { font-size: 20px; font-weight: 600; }

.head-rechts { display: flex; align-items: center; }

.langs { display: flex; gap: 2px; justify-content: center; }

/* Kürzel statt Flaggen: eine Flagge steht für ein Land, nicht für eine Sprache,
   und „welche Flagge für Englisch" hat keine richtige Antwort. */
.lang {
  padding: 2px 6px;
  font: inherit;
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: 0.04em;
  color: var(--muted, #a1a1aa);
  background: none;
  border: 0;
  border-radius: 3px;
  cursor: pointer;
}
.lang:hover { color: var(--text, #111); }
.lang.is-active { color: var(--text, #111); font-weight: 600; }
.lang:focus-visible { outline: 2px solid var(--accent, #ed1c24); outline-offset: 1px; }

/* Termin und Ort. Farbe und Textfarbe kommen aus dem Theme, damit die Pille
   beim nächsten Kunden nicht rot ist, nur weil ICR es war. */
.badge {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  padding: 6px 18px;
  border-radius: 999px;
  background: var(--accent, #ed1c24);
  color: var(--cta-text, #fff);
  font-size: clamp(11px, 3vw, 13px);
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
}
.badge strong { font-weight: 700; }

/* Auf schmalen Telefonen fehlen dem Gespann sonst rund zwölf Pixel und die
   Pille bricht unter das Logo. `max-height` statt `height`, weil die Höhe als
   Inline-Stil aus theme.json kommt und eine CSS-`height` dagegen verlöre —
   eine Obergrenze greift trotzdem. */
@media (max-width: 430px) {
  .head { gap: 12px; padding-left: 16px; padding-right: 16px; }
  /* Die Deckelung gilt dem **kompakten** Kopf: dort teilen Marke und Pille eine
     enge Zeile, und ein 80er Logo drängte die Pille aus dem Bild. Im großen
     Layout bricht die Pille in eine eigene Kopfzeile um, die Marke hat ihre
     Zeile für sich, und 34px wären dort grundlos klein.

     Negativ formuliert, weil die Anmeldeseite gar kein `data-layout` trägt und
     die Deckelung dort weiter greifen muss.

     **`body:not(…)` und nicht `:not(…)`.** Ohne den Typ trifft die Regel jedes
     Logo: `<html>`, `<header>` und `<span class="brand">` sind allesamt
     Vorfahren, die das Attribut nicht tragen, und einer genügt. */
  body:not([data-layout="gross"]) .logo { max-height: 34px; }
  .badge { padding: 5px 13px; }
}

/* Klein genug, dass eine Überschrift von der Länge „Ihr Profilbild für den ICR
   2026" auf jeder realistischen Breite in eine Zeile passt — auf einem 375er
   Telefon wie auf dem Desktop.

   `text-wrap: balance` statt `white-space: nowrap`: die Copy kommt aus
   theme.json und ist pro Kunde anders. Ein erzwungenes nowrap schöbe eine
   längere Überschrift aus dem Bild; so bricht sie im Zweifel um, aber
   ausgewogen statt mit einem einzelnen Wort in der zweiten Zeile. */
h1 {
  font-family: var(--font-heading, var(--font-body, system-ui)), sans-serif;
  font-weight: var(--font-heading-weight, 600);
  font-size: clamp(18px, 5.2vw, 26px);
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 16px 0 8px;
}

.intro { color: var(--muted, #a1a1aa); margin: 0 0 28px; }

/* Die Leinwand erscheint erst, wenn ein Foto da ist. Vorher zeigte sie nur
   einen leeren Rahmen mit einem roten Balken — das sieht nach kaputt aus und
   nicht nach „hier kommt Ihr Bild hin". Die Klasse setzt main.js. */
/* Der Ring als `box-shadow` und nicht als `border`: die Höhe des Rahmens setzt
   main.js aus der Szenenhöhe, und bei `box-sizing: border-box` fräße ein echter
   Rand zwei Pixel davon ab — die Leinwand wäre unten beschnitten. Ein Schatten
   liegt außerhalb des Kastens und lässt die Rechnung in Ruhe.

   Nötig ist er, weil viele Vorlagen unten auf einer weißen Fläche enden. Ohne
   Ring liefe die Bildkante in den weißen Seitenhintergrund, und niemand sähe,
   wo das Bild aufhört. */
.stage-frame {
  display: none;
  overflow: hidden;
  width: 100%;
  border-radius: 4px;
  margin-bottom: 28px;
  background: var(--surface, rgba(127, 127, 127, 0.1));
  box-shadow: 0 0 0 1px var(--border, rgba(127, 127, 127, 0.35));
}
body.has-photo .stage-frame { display: block; }
#stage { transform-origin: top left; }

.controls { margin-top: 28px; }
.field { margin: 0 0 18px; }
.field label { display: block; margin-bottom: 6px; font-size: 14px; color: var(--muted, #a1a1aa); }

.field input[type="text"] {
  width: 100%;
  padding: 12px 14px;
  font: inherit;
  color: inherit;
  background: var(--surface, rgba(127, 127, 127, 0.1));
  border: 1px solid var(--border, rgba(127, 127, 127, 0.4));
  border-radius: 3px;
}
.field input[type="text"]:focus-visible,
.field select:focus-visible {
  outline: 2px solid var(--accent, #ed1c24);
  outline-offset: 2px;
}

/* Auswahlfeld wie die Textzeile, damit die Spalte eine Kante behält. Das
   native Aufklappmenü bleibt: es ist auf jedem System bedienbar, und ein
   nachgebautes wäre auf einem Telefon schlechter. */
.field select {
  width: 100%;
  padding: 12px 14px;
  font: inherit;
  color: inherit;
  background: var(--surface, rgba(127, 127, 127, 0.1));
  border: 1px solid var(--border, rgba(127, 127, 127, 0.4));
  border-radius: 3px;
}

/* Beim Umschalter steht die Beschriftung hinter dem Kasten: erst die Marke,
   dann wofür sie steht. */
.field-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
}
.field-toggle input { width: 18px; height: 18px; accent-color: var(--accent, #ed1c24); flex: none; }
.field-toggle label { margin-bottom: 0; cursor: pointer; }

/* Das native Dateifeld ist auf jedem System anders und nie schön. Das Label
   trägt die Gestaltung, das Feld selbst bleibt für Tastatur und Screenreader
   erreichbar statt display:none — und steht deshalb im Markup davor, damit
   der Fokusring über den Geschwisterselektor am Label sichtbar wird. */
#photo {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.upload {
  display: block;
  padding: 20px;
  margin-bottom: 0;
  text-align: center;
  font-size: 15px;
  color: var(--text, #fff);
  border: 1px dashed var(--border, rgba(127, 127, 127, 0.5));
  border-radius: 3px;
  cursor: pointer;
}
.upload:hover,
#photo:focus-visible + .upload { border-color: var(--accent, #ed1c24); }
#photo:focus-visible + .upload { outline: 2px solid var(--accent, #ed1c24); outline-offset: 2px; }

.formats { border: 0; padding: 0; margin: 0 0 20px; }
.formats legend { font-size: 14px; color: var(--muted, #a1a1aa); margin-bottom: 8px; padding: 0; }

/* Kacheln statt einer Zeile Radios. Der Grund ist das LinkedIn-Titelbild: aus
   „4:1" allein erschließt niemand, dass es ein schmaler Streifen ohne Platz
   für ein Gesicht ist, aus dem Rechteck daneben sofort.

   `auto-fit` statt einer festen Spaltenzahl: die Zahl der Formate steht im
   Template und ändert sich pro Kunde. */
/* Eine Zeile, keine Spalten.

   Ein Raster gibt jeder Kachel eine gleich breite Spalte und verteilt sie damit
   über die ganze Kolumne: bei zwei Formaten standen 250 px Luft dazwischen,
   obwohl die Kacheln gedeckelt sind. Die Kacheln gehören nebeneinander, und was
   rechts übrig bleibt, bleibt übrig. */
.format-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Selbst ein Raster, damit die Karte die volle Zeilenhöhe bekommt. Ohne das
   bleibt eine Karte mit einzeiliger Beschriftung kürzer als eine mit
   umbrechender, und die Reihe steht unten ausgefranst.

   `flex: 1 1 96px` mit Deckel: bei vier Formaten wachsen die Kacheln auf die
   verfügbare Breite und füllen die Zeile, bei einem oder zwei hören sie bei
   160 px auf, statt sich über die halbe Kolumne zu ziehen. */
.format { display: grid; flex: 1 1 96px; max-width: 160px; cursor: pointer; }

/* Auf dem Telefon zwei je Zeile. Vier Kacheln zu 96 px passen dort nicht in
   eine Reihe, und ohne diese Regel bräche die vierte allein um. */
@media (max-width: 28rem) {
  .format { flex-basis: calc(50% - 4px); max-width: none; }
}

/* Nicht `display: none`: ein ausgeblendetes Radio ist nicht mehr fokussierbar,
   und die Formatwahl wäre per Tastatur unerreichbar. */
.format input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.format-karte {
  display: grid;
  grid-template-rows: auto 1fr auto;
  justify-items: center;
  gap: 2px;
  padding: 10px 6px 8px;
  border: 1px solid var(--border, #27272a);
  border-radius: 3px;
  text-align: center;
  transition: border-color 120ms ease, background-color 120ms ease;
}

.format-skizze {
  inline-size: 34px;
  block-size: 34px;
  color: var(--muted, #a1a1aa);
}

/* Umriss statt Fläche: gefüllt sähen die Rechtecke aus wie Knöpfe, und die
   Aussage ist das Verhältnis, nicht das Gewicht. */
.format-skizze rect {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}

.format-titel { font-size: 14px; line-height: 1.3; }
.format-mass {
  font-size: 12px;
  line-height: 1.3;
  color: var(--muted, #a1a1aa);
  font-variant-numeric: tabular-nums;
}

.format:hover .format-karte { border-color: var(--accent, #ed1c24); }

/* Geschwisterselektor und **nicht** `:has(input:checked)`: `setFormat` in
   app/main.js hakt das Radio programmatisch an, und darauf rechnet `:has()`
   nicht zuverlässig neu. Siehe den Kommentar an formatChoicesHtml. */
.format input:checked ~ .format-karte {
  border-color: var(--accent, #ed1c24);
  background: color-mix(in srgb, var(--accent, #ed1c24) 10%, transparent);
}
.format input:checked ~ .format-karte .format-skizze { color: var(--accent, #ed1c24); }
.format input:checked ~ .format-karte .format-skizze rect {
  fill: color-mix(in srgb, var(--accent, #ed1c24) 22%, transparent);
}

.format input:focus-visible ~ .format-karte {
  outline: 2px solid var(--accent, #ed1c24);
  outline-offset: 2px;
}

/* `--cta` fällt auf den Akzent zurück. Zwei Tokens, weil beides
   auseinanderfallen kann: beim Büdchentag ist der Knopf blau und der Akzent in
   der Überschrift orange. Wo nur `--accent` gesetzt ist, ändert sich nichts. */
.cta {
  width: 100%;
  padding: 14px 20px;
  font: inherit;
  font-weight: 600;
  color: var(--cta-text, #fff);
  background: var(--cta, var(--accent, #ed1c24));
  border: 0;
  border-radius: 3px;
  cursor: pointer;
}
/* Ohne Foto gäbe es nur den Platzhalter zu exportieren. Der Knopf ist deshalb
   gesperrt, bis eines da ist — nicht versteckt, damit sichtbar bleibt, worauf
   die Seite hinausläuft. */
.cta:disabled { opacity: 0.45; cursor: not-allowed; }
.cta:disabled:active { pointer-events: none; }
.cta:focus-visible { outline: 2px solid var(--text, #fff); outline-offset: 2px; }

/* Unter dem Knopf zentriert. Der Knopf nimmt die volle Breite, und ein
   linksbündiges Icon darunter hinge an einer Kante, die es sonst nirgends gibt. */
.shares {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  margin-top: 20px;
}
.share { color: var(--muted, #a1a1aa); }

/* Ein Icon ohne Text braucht trotzdem eine Fläche, die sich mit dem Daumen
   treffen lässt: 24 px Grafik plus Innenabstand ergibt 44 px, das Mindestmaß
   für ein Tap-Target. */
.share-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 3px;
}
.share-icon:hover { color: var(--accent, #ed1c24); }
.share-icon:focus-visible { outline: 2px solid var(--accent, #ed1c24); outline-offset: 0; }

.legal { font-size: 13px; color: var(--muted, #a1a1aa); margin-top: 24px; }

/* Anmeldung und Ablaufhinweis teilen sich das Layout der Kundenseite, tragen
   aber kein Werkzeug. Der Inhalt sitzt weiter oben, weil unter ihm nichts
   folgt — sonst hinge ein Satz allein am oberen Rand einer leeren Seite. */
.ist-hinweis .wrap { padding-top: 48px; }
.ist-hinweis .controls { max-width: 320px; }

/* Der Fehlerhinweis am Anmeldeformular. Rot ist hier nicht die Akzentfarbe des
   Kunden: die kann selbst Rot sein, und dann wäre der Fehler nicht vom Rest zu
   unterscheiden. */
.fehler {
  margin: 0 0 20px;
  padding: 10px 14px;
  border-radius: 3px;
  background: rgba(200, 30, 30, 0.1);
  color: #b3261e;
  font-size: 14px;
}

/* Die Datenschutzzusage steht im Fuß und braucht dort keinen eigenen Abstand —
   den setzt der Fuß über `gap`. Schmaler als die Spalte, damit der Satz auf
   einem breiten Bildschirm nicht als eine sehr lange Zeile dasteht. */
.privacy {
  max-width: 42ch;
  margin: 0;
  font-size: 13px;
  color: var(--muted, #a1a1aa);
  text-wrap: balance;
}

/* Sprachwahl und Hinweis untereinander, beide zentriert. Der Umschalter steht
   oben: er ist eine Handlung, der Hinweis nur eine Angabe. */
.foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 32px clamp(16px, 5vw, 48px);
  text-align: center;
  font-size: 13px;
}
.foot a { color: var(--muted, #a1a1aa); }

/* ==========================================================================
   Layout „gross"

   Die zweite von zwei festen Anordnungen, gewählt über `theme.layout`. Alles
   hier ist unter `[data-layout="gross"]` gekapselt — das kompakte Layout darf
   sich nicht ändern, weil dieses dazukam.

   Der Unterschied ist nicht die Farbe, sondern die Gliederung: Termin und Ort
   stehen als Eyebrow über einer sehr großen Überschrift, das Upload-Feld ist
   der Blickfang statt einer Zeile, und alles Kleingedruckte läuft in einer
   zweiten Schriftrolle (`--font-mono`). Der Ton kommt trotzdem aus den Tokens:
   dieselbe Anordnung trägt einen Kongress genauso wie ein Stadtfest.
   ========================================================================== */

[data-layout="gross"] {
  /* Zurückhaltend gestapelt statt am oberen Rand klebend: die Seite besteht
     aus einem Gedanken und einem Feld, und beides darf mittig stehen. */
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* Marke links, Termin-Pille rechts. `flex-wrap`, weil beides zusammen auf einem
   Telefon nicht in eine Zeile passt: die Pille trägt Datum und Ort, und ein
   erzwungenes Nebeneinander presste entweder das Logo klein oder schöbe die
   Zeile seitlich aus dem Bild. Umgebrochen steht sie unter der Marke, also da,
   wo sie vorher stand. */
[data-layout="gross"] .head-gross {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  max-width: 640px;
  width: 100%;
  margin: 0 auto;
  padding: 24px clamp(20px, 5vw, 32px) 0;
}

[data-layout="gross"] .wrap-gross {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 24px;
  max-width: 640px;
  padding: 32px clamp(20px, 5vw, 32px) 48px;
}

/* Termin und Ort, im Kopf rechts neben der Marke. Sie beantwortet „wann und
   wo", bevor die Überschrift „was" sagt, und steht deshalb über allem anderen.

   **Kein `white-space: nowrap`.** Es wäre der Reflex, damit Datum und Ort in
   einer Zeile bleiben, und auf dem Desktop unnötig: dort ist ohnehin Platz.
   Eng wird es auf dem Telefon, und dort richtet es Schaden an. Gemessen sind
   es 319 px Pille gegen 335 px Spalte auf einem 375er Gerät, also 16 px Luft;
   ein längerer Ort schöbe die Seite seitlich aus dem Bild.

   Ohne die Sperre greift stattdessen `flex-wrap` oben: passt die Pille nicht
   mehr neben die Marke, rutscht sie ganz in die nächste Kopfzeile und hat dort
   die volle Breite. Erst wenn auch die nicht reicht, bricht ihr Text um. */
[data-layout="gross"] .eyebrow {
  margin: 0;
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--surface, #e4efce);
  font-family: var(--font-mono, var(--font-body, ui-monospace)), ui-monospace, monospace;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  line-height: 1.3;
}

[data-layout="gross"] h1 {
  margin: 0;
  font-family: var(--font-heading, var(--font-body, system-ui)), sans-serif;
  font-weight: var(--font-heading-weight, 900);
  font-size: clamp(2.5rem, 13vw, 4.5rem);
  line-height: 0.95;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  text-wrap: balance;
}

/* Das hervorgehobene Teilstück der Überschrift. Der Renderer setzt den Span
   um die Wörter aus `copy.titleAccent` — im Kundentext steht kein Markup. */
[data-layout="gross"] h1 .akzent { color: var(--accent, #d8672e); }

[data-layout="gross"] .intro {
  margin: 0;
  max-width: 34ch;
  font-family: var(--font-mono, var(--font-body, ui-monospace)), ui-monospace, monospace;
  font-weight: 500;
  font-size: 15px;
  line-height: 1.6;
  color: var(--text, #273078);
  opacity: 0.85;
}

[data-layout="gross"] .controls { width: 100%; margin-top: 0; }

/* Das Upload-Feld **wird** zur Vorschau: beide stehen an derselben Stelle, und
   sobald ein Foto da ist, tritt das eine an die Stelle des anderen. Untereinander
   waere die aufgeraeumte Seite ploetzlich zwei Kaesten hoch, und der obere haette
   seine Aufgabe erledigt.

   **Rahmen und Polsterung traegt ein eigener Kasten drumherum.** Am `.stage-frame`
   selbst duerfen sie nicht haengen: `main.js` rechnet den Massstab aus dessen
   `clientWidth` und setzt seine Hoehe aus der Szenenhoehe. Ein Padding zaehlt in
   `clientWidth` mit, ein Rand bei `box-sizing: border-box` gegen die Hoehe - die
   Buehne bekommt dadurch einen zu grossen Massstab und laeuft aus ihrem Kasten
   heraus. Genau derselbe Grund, aus dem der Ring im kompakten Layout ein
   `box-shadow` ist und kein `border`. */
/* Sobald ein Foto da ist, steht das Bild für sich. Polsterung, Rand und Fläche
   sind hier raus: der gerahmte Zustand konkurrierte mit dem Bild, das er
   zeigen soll, und das Bild ist das Ergebnis der Seite.

   Der Kasten bleibt trotzdem stehen. Er trägt den Abstand nach unten und
   `line-height: 0` gegen die Unterlänge unter der Leinwand — und vor allem
   darf beides **nicht** an `.stage-frame`: dort zählt Polsterung in
   `clientWidth` mit, aus dem main.js den Maßstab rechnet. Siehe CLAUDE.md. */
[data-layout="gross"] .stage-rahmen {
  display: none;
  margin: 0 0 20px;
  line-height: 0;
}
[data-layout="gross"].has-photo .stage-rahmen { display: block; }
[data-layout="gross"] .stage-frame {
  margin: 0;
  border-radius: 12px;
  box-shadow: none;
  background: none;
}
[data-layout="gross"].has-photo .upload-gross { display: none; }

/* Das Upload-Feld. Im kompakten Layout eine Zeile, hier das, worauf die Seite
   hinausläuft — und deshalb groß genug, dass man es auf einem Telefon mit dem
   Daumen trifft, ohne zu zielen. */
[data-layout="gross"] .upload-gross {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 48px 16px;
  background: var(--surface, #e4efce);
  border: 3px dashed var(--cta, var(--accent, #273078));
  border-radius: 20px;
  text-align: center;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
[data-layout="gross"] .upload-gross:hover { background: var(--accent-weich, var(--surface, #b4ff7a)); }
[data-layout="gross"] .upload-icon { display: block; line-height: 0; color: var(--cta, var(--accent, #273078)); }
[data-layout="gross"] .upload-titel {
  font-family: var(--font-heading, var(--font-body, system-ui)), sans-serif;
  font-weight: var(--font-heading-weight, 900);
  font-size: 22px;
  line-height: 1.1;
  text-transform: uppercase;
}
[data-layout="gross"] .upload-hinweis {
  font-family: var(--font-mono, var(--font-body, ui-monospace)), ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.7;
}

/* Knöpfe und Beschriftungen in der Mono-Rolle, versal und gesperrt — das ist
   der Ton, den die Anordnung trägt. */
[data-layout="gross"] .cta {
  min-height: 52px;
  border-radius: 999px;
  font-family: var(--font-mono, var(--font-body, ui-monospace)), ui-monospace, monospace;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
[data-layout="gross"] .field label,
[data-layout="gross"] .formats legend {
  font-family: var(--font-mono, var(--font-body, ui-monospace)), ui-monospace, monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
[data-layout="gross"] .field input[type="text"],
[data-layout="gross"] .field select { border-radius: 12px; border-width: 2px; }

/* Der Fuss bleibt schlicht und mittig - wie im kompakten Layout. Er traegt
   Angaben, keine Handlungen; ein versaler Link mit farbigem Unterstrich zoege
   Aufmerksamkeit auf die Stelle, an der die Seite zu Ende ist. */
[data-layout="gross"] .foot { max-width: 640px; margin: 0 auto; }

/* ==========================================================================
   Layout `callshop`

   Ein Redaktionswerkzeug, kein Teilnehmertool: dunkler Grund, eine helle
   Karte. Uebernommen aus dem abgeloesten Generator, damit niemand umlernen
   muss. Alles hier ist gekapselt; `kompakt` und `gross` duerfen davon nichts
   merken.
   ========================================================================== */

[data-layout="callshop"] {
  background: #000;
  color: #333;
  letter-spacing: 0.03em;
}

[data-layout="callshop"] .head-callshop {
  display: block;
  max-width: 400px;
  margin: 80px auto 20px;
  padding: 0;
}

[data-layout="callshop"] .brand img { width: 100%; height: auto !important; display: block; }

[data-layout="callshop"] h1 {
  font-size: 24px;
  font-weight: 400;
  line-height: 1.46;
  text-transform: uppercase;
  color: #fff;
  text-align: center;
  margin: 16px 0 20px;
}

[data-layout="callshop"] .wrap-callshop {
  max-width: none;
  margin: 0;
  padding: 0 0 40px;
}

/* Die Karte. `max-width` und `width` beide, wie im Original: auf schmalen
   Geraeten sollen links und rechts fuenf Prozent bleiben. */
[data-layout="callshop"] .karte {
  /* Das Original rechnet ohne box-sizing: max-width 350 px gilt dort für den
     Inhalt, außen sind es 412 px. Nur so bleiben alle Felder und Knöpfe so
     breit wie im Original. */
  box-sizing: content-box;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 12px;
  box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08);
  padding: 30px;
  max-width: 350px;
  width: 90%;
  margin: 0 auto 20px;
}

/* Das Upload-Feld: gestrichelter Rahmen, der auf Zeigen die Akzentfarbe
   annimmt. */
[data-layout="callshop"] .upload-callshop {
  display: block;
  border: 2px dashed #ccc;
  border-radius: 8px;
  padding: 40px;
  text-align: center;
  color: #888;
  cursor: pointer;
  transition: border-color 0.3s, color 0.3s;
}

[data-layout="callshop"] .upload-callshop:hover,
[data-layout="callshop"] .upload-callshop:focus-visible {
  border-color: var(--accent, #ffbcd9);
  color: var(--accent, #ffbcd9);
}

/* Die Vorschau ist die Leinwand selbst und von Anfang an sichtbar, auch ohne
   Foto: der Rahmen zeigt, wohin das Bild kommt. Weder Polsterung noch Rand,
   sonst liefe der Massstab aus main.js daneben. */
[data-layout="callshop"] .stage-frame {
  display: block;
  background: #222;
  margin: 20px 0;
  border-radius: 0;
  box-shadow: none;
}

[data-layout="callshop"] .field { margin: 0 0 10px; }

/* Beschriftungen sind unsichtbar, aber vorhanden.
   `display: none` waere das Naheliegende und falsch: es nimmt das Label aus
   dem Accessibility-Tree, und das Feld waere fuer einen Screenreader namenlos.
   Der Platzhalter ersetzt das nicht, er verschwindet beim Tippen. */
[data-layout="callshop"] .field > label:not(.upload-callshop),
[data-layout="callshop"] .field-segmente > legend,
[data-layout="callshop"] .sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

[data-layout="callshop"] input[type="text"],
[data-layout="callshop"] input[type="date"],
[data-layout="callshop"] input[type="time"],
[data-layout="callshop"] select {
  width: 100%;
  height: 44px;
  padding: 0 16px;
  margin-top: 8px;
  border: 2px solid #eee;
  border-radius: 8px;
  background: #f8f8f8;
  color: #333;
  font-size: 15px;
  font-family: inherit;
  font-weight: 400;
  box-sizing: border-box;
  transition: all 0.3s ease;
}

[data-layout="callshop"] input:focus,
[data-layout="callshop"] select:focus {
  border-color: var(--accent, #ffbcd9);
  background: #fff;
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 188, 217, 0.1);
}

/* Auswahl und Freitext nebeneinander. */
[data-layout="callshop"] .auswahl-zeile { display: flex; gap: 10px; }
[data-layout="callshop"] .auswahl-zeile select { flex: 1; }
[data-layout="callshop"] .auswahl-zeile .frei { flex: 1; }
[data-layout="callshop"] select:disabled { opacity: 0.5; }

/* Segmente: Pillen auf dunklem Grund. Das Radio selbst ist versteckt, sichtbar
   ist das Label. Wie im Original füllen die Overlay-Pillen die volle Breite
   (width 100%, flex 1) und liegen ohne Lücke aneinander. */
[data-layout="callshop"] .segmente {
  display: flex;
  width: 100%;
  background: #333;
  border-radius: 16px;
  padding: 3px;
  gap: 0;
}
[data-layout="callshop"] [data-inputs-oben] .segment { flex: 1; }
[data-layout="callshop"] .segment { display: block; margin: 0; }

/* Ein fieldset bringt Browser-Defaults mit (padding, margin, min-width), die
   die Segmente um 28 px schmaler machen als ihren Kasten. */
[data-layout="callshop"] .field-segmente {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}
[data-layout="callshop"] .segment input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

[data-layout="callshop"] .segment span {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 24px;
  padding: 5px 12px;
  border-radius: 14px;
  color: #666;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.3s ease;
  box-sizing: border-box;
}

/* Im Original faerbt der Hover die Schrift auf den eigenen Hintergrund und
   macht den Text unsichtbar. Das ist ein Defekt und kein Gestaltungsmittel;
   hier steht deshalb #333. */
[data-layout="callshop"] .segment input:not(:checked) + span:hover { color: var(--accent, #ffbcd9); }
[data-layout="callshop"] .segment input:checked + span {
  background: var(--accent, #ffbcd9);
  color: #fff;
}
[data-layout="callshop"] .segment input:focus-visible + span {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* Der Umschalter unter dem Export-Knopf traegt die zweite Akzentfarbe. Wie im
   Original nur so breit wie sein Inhalt und zentriert — gemessen: 131 px. */
[data-layout="callshop"] .segmente-blau {
  width: max-content;
  margin: 10px auto 0;
}
[data-layout="callshop"] .segmente-blau .segment input:checked + span {
  background: var(--cta, #557fb9);
}
[data-layout="callshop"] .segmente-blau .segment input:not(:checked) + span:hover {
  color: var(--cta, #557fb9);
}

/* Formatwahl links, Ausrichtung rechts. */
[data-layout="callshop"] .zeile-format {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 15px;
  margin: 20px 0;
}

[data-layout="callshop"] .formats { border: 0; padding: 0; margin: 0; min-width: 0; }
/* `flex-wrap: wrap` aus der Basis-Regel bricht die zweite Wahl in eine eigene
   Zeile: die Kacheln haben dort `flex: 1 1 96px`, und zwei davon passen nicht
   in eine 93 px breite Pille. Aus einem Umschalter wurden dadurch zwei
   uebereinanderliegende Zeilen. */
[data-layout="callshop"] .format-list { margin: 0; flex-wrap: nowrap; }
[data-layout="callshop"] .format input { position: absolute; opacity: 0; pointer-events: none; }
/* Die Basis-Regel `.format` bringt Abstände für das kompakte Layout mit
   (margin 0 16px 8px 0); in der Pille gibt es keine. Und keine Streckung: im
   Original ist die Formatpille so breit wie ihr Inhalt, anders als die
   Overlay-Segmente darueber, die die volle Breite fuellen. */
[data-layout="callshop"] .format-list .format {
  display: block;
  margin: 0;
  gap: 0;
  flex: 0 0 auto;
  max-width: none;
}

/* Die Format-Pillen tragen denselben Look wie die Overlay-Segmente: das
   Original stylt alle Umschalter gleich. Ohne diese Regeln lägen nackte
   Spans auf dem dunklen Grund. */
[data-layout="callshop"] .format-list .format span {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 24px;
  padding: 5px 12px;
  border-radius: 14px;
  color: #666;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.3s ease;
  box-sizing: border-box;
}
[data-layout="callshop"] .format-list .format input:checked + span {
  background: var(--accent, #ffbcd9);
  color: #fff;
}
[data-layout="callshop"] .format-list .format input:not(:checked) + span:hover {
  color: var(--accent, #ffbcd9);
}
[data-layout="callshop"] .format-list .format input:focus-visible + span {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

[data-layout="callshop"] .anker {
  display: flex;
  background: #333;
  border-radius: 16px;
  padding: 3px;
  gap: 2px;
}

[data-layout="callshop"] .anker-btn {
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  border-radius: 14px;
  background: none;
  color: #666;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

[data-layout="callshop"] .anker-btn:hover {
  background: rgba(255, 188, 217, 0.2);
  color: var(--accent, #ffbcd9);
}

[data-layout="callshop"] .anker-btn.is-active {
  background: var(--accent, #ffbcd9);
  color: #fff;
}

[data-layout="callshop"] .cta {
  width: 100%;
  margin-top: 20px;
  padding: 12px 20px;
  border: none;
  border-radius: 50px;
  background: var(--cta, #557fb9);
  color: var(--cta-text, #fff);
  font-size: 16px;
  font-weight: 700;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.3s ease;
}

[data-layout="callshop"] .cta:hover:not(:disabled) { background: #78ce82; }
[data-layout="callshop"] .cta.ist-fertig { background: #78ce82; }
[data-layout="callshop"] .cta.ist-fehler { background: #E24A4A; }
[data-layout="callshop"] .cta:disabled { opacity: 0.5; cursor: not-allowed; }

/* Die Bildmarke im Fuß: wie im Original 55 px, zentriert, 20 px Abstand. */
[data-layout="callshop"] .fussmarke {
  display: block;
  width: 55px;
  margin: 20px auto 0;
}
[data-layout="callshop"] .fussmarke img { width: 100%; height: auto; display: block; }

[data-layout="callshop"] .foot,
[data-layout="callshop"] .shares { text-align: center; padding: 20px 0; }
[data-layout="callshop"] .foot a,
[data-layout="callshop"] .shares a { color: var(--accent, #ffbcd9); }
[data-layout="callshop"] .foot a:hover,
[data-layout="callshop"] .shares a:hover { color: #fff; }
[data-layout="callshop"] .privacy { color: #666; }

/* Datum und Uhrzeit stehen nebeneinander, bis der Platz ausgeht. */
[data-layout="callshop"] .inputs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 20px;
}
[data-layout="callshop"] .inputs > .field { grid-column: span 2; }
[data-layout="callshop"] .inputs > .field:has(input[type="date"]),
[data-layout="callshop"] .inputs > .field:has(input[type="time"]) { grid-column: span 1; }

@media (max-width: 580px) {
  [data-layout="callshop"] .inputs { grid-template-columns: 1fr; }
  [data-layout="callshop"] .inputs > .field { grid-column: span 1; }
  [data-layout="callshop"] .upload-callshop { padding: 20px; }
  [data-layout="callshop"] input[type="text"],
  [data-layout="callshop"] input[type="date"],
  [data-layout="callshop"] input[type="time"],
  [data-layout="callshop"] select { font-size: 16px; }
}

@media (max-width: 480px) {
  [data-layout="callshop"] .head-callshop { margin: 20px auto; max-width: 300px; }
  /* Wie das Original bei 480 px: die Karte nimmt die volle Breite. */
  [data-layout="callshop"] .karte { width: 90%; max-width: none; margin: 0 auto 20px; padding: 15px; }
}
