/* =========================================================================
   Daniel Gold — Layout
   Braucht assets/shared/tokens.css (Block A) und assets/css/tokens.css (Block B).
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--step-0);
  line-height: var(--lh-body);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; height: auto; }
figure, blockquote, h1, h2, h3, p, ul, ol, dl, dd { margin: 0; padding: 0; }
ol, ul { list-style: none; }
a { color: inherit; text-decoration: none; }
p a, dd a { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 0.18em; text-decoration-thickness: 2px; }
p a:hover, dd a:hover { color: var(--accent); }
/* --- Feature: ::selection-Styling --- Akzentfarbe statt Browser-Blau, auf den
   inversen Sektionen (Schmuck, Kontakt) umgekehrt. Kontrast geprüft: Kobalt auf
   Papier und Papier auf Kobalt liegen beide bei ≈ 7,6:1 (AA verlangt 4,5:1). */
::selection { background: var(--kobalt); color: var(--paper); }
.s--kobalt ::selection, .s--ink ::selection { background: var(--paper); color: var(--kobalt); }
/* --- /Feature --- */
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* ---- Helfer ---- */
.shell { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.mono {
  font-family: var(--font-mono); font-size: var(--mono-size); font-weight: 400;
  letter-spacing: var(--mono-track); text-transform: uppercase; line-height: 1.6;
}
.display {
  font-family: var(--font-display); font-weight: 500;
  font-optical-sizing: auto; font-variation-settings: var(--display-axes);
  line-height: var(--lh-tight); letter-spacing: -0.01em; text-wrap: balance;
}
.display--hero { font-size: clamp(3rem, 1rem + 7.4vw, 7.5rem); }
.display--xl { font-size: clamp(2.6rem, 1.1rem + 6.6vw, 8rem); }
@media (max-width: 40rem) { .display--xl, .display--hero { hyphens: auto; overflow-wrap: anywhere; } }
.display--m { font-size: var(--step-2); }
.skip { position: absolute; left: var(--gutter); top: -4em; z-index: 100; background: var(--kobalt); color: var(--paper); padding: .6em 1em; }
.skip:focus { top: 1rem; }
/* Sentinel am Seitenanfang: main.js beobachtet es (IntersectionObserver), um die
   fixierte Nav einzufärben, sobald der Seitenanfang aus dem Bild scrollt. */
.scroll-top { position: absolute; top: 0; left: 0; width: 1px; height: 1px; pointer-events: none; }
/* Platzhalter: eine Mono-Zeile, sichtbar, nie Lorem Ipsum */
.note { margin-top: var(--sp-5); text-transform: none; letter-spacing: 0.04em; max-width: 70ch; overflow-wrap: anywhere; }
.note--center { text-align: center; margin-inline: auto; }
[data-para] { will-change: transform; }

/* ---- Sektions-Rahmen ---- */
.sect { padding-block: var(--sp-7); }
.sect--line { padding-top: 0; }
.sect--line > .shell:first-child { border-top: var(--hair) solid var(--line); padding-top: var(--sp-6); }
.head { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); margin-bottom: var(--sp-6); }
.head h2 { max-width: 16ch; }
.head__p { max-width: 52ch; font-size: var(--step-1); line-height: 1.4; }
@media (min-width: 62rem) {
  .head { grid-template-columns: minmax(0, 1fr) minmax(0, 10fr); align-items: start; }
  .head__n { padding-top: 0.6em; }
  .head__p { grid-column: 2; }
}

/* =========================================================== top ===== */
/* Fixiert (statt absolute): bleibt beim Scrollen sichtbar, damit Nav-Spy
   etwas zu zeigen hat — ohne eigene Flow-Höhe, die Hero-Abstände bleiben
   unverändert (kein CLS).
   Ohne JS immer deckend (lesbar über jeder Sektion, auch den dunklen
   s--ink/s--kobalt); mit JS startet sie transparent über dem Hero und wird
   deckend, sobald das Sentinel-Element am Seitenanfang aus dem Bild scrollt
   (IntersectionObserver, main.js) — zu dem Zeitpunkt ist man an jeder
   dunklen Sektion ohnehin schon vorbei. */
.top { position: fixed; inset-inline: 0; top: 0; z-index: 20; background: var(--paper); color: var(--ink); border-bottom: var(--hair) solid var(--line); }
html.js .top { background: transparent; border-bottom-color: transparent; transition: background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out); }
html.js .top.is-scrolled { background: var(--paper); border-bottom-color: var(--line); }
@media (prefers-reduced-motion: reduce) { html.js .top { transition: none; } }
.top__row { position: relative; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding-block: var(--sp-3); }
.top__mark { display: flex; align-items: center; gap: 0.6rem; font-family: var(--font-display); font-variation-settings: var(--display-axes); font-size: var(--step-1); }
.mark { width: 2rem; height: 2rem; }
/* --- Feature: Logo-Augen im Header --- klare, geometrische Pupillen (Vektor-
   Icon, kein Foto), sehr kleine Amplitude (main.js: MAX 22 viewBox-Einheiten
   von 1500 ≈ < 1px auf dem Bildschirm bei 2rem Logogröße — bewusst dezent,
   siehe Handover). Ruheposition ohne JS/Pointer/reduced-motion: zentriert.
   Wird seit dem Ticket "Kontaktseite — Logo statt Foto-Schale" auch von der
   großen Logo-Version im Kontakt-Hero mitbenutzt (ausdrücklich gewünschte
   Wiederverwendung, siehe dortiger Kommentar in index.html) — wer dieses
   Feature entfernt, nimmt der Kontaktseite die Pupillen-Farbe gleich mit. */
.mark__pupil { fill: var(--kobalt); transform: translate(var(--dx, 0px), var(--dy, 0px)); transition: transform 120ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .mark__pupil { transition: none; } }
/* --- /Feature --- */
.top__nav { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); }
.top__nav a:hover, .top__nav a.is-active { color: var(--accent); }
/* Mobil bleiben nur Kontakt (letztes Kind) und der Poster-Link sichtbar –
   Poster ist jetzt ein gleichberechtigter Nav-Punkt (kein Sektions-Anker,
   siehe navChrome() in main.js), soll aber auf schmalen Screens nicht die
   einzige verbliebene Kontakt-Kachel verdrängen. */
@media (max-width: 52rem) { .top__nav a:not(:last-child):not([href="poster.html"]) { display: none; } }

/* ========================================================== hero ===== */
.hero { position: relative; min-height: 100svh; display: grid; align-items: center; padding-block: var(--sp-7) var(--sp-6); }
.hero__grid { display: grid; gap: var(--sp-5); align-items: center; }
.hero__kicker { margin-bottom: var(--sp-4); }
.hero__lead { max-width: 40ch; font-size: var(--step-1); line-height: 1.4; margin-top: var(--sp-4); }
.hero__src { margin-top: var(--sp-3); }
.hero__art { position: relative; width: min(80vw, 30rem); margin-inline: auto; }
.hero__img { width: 100%; }
.hero__cap { margin-top: var(--sp-2); text-align: center; text-transform: none; letter-spacing: 0.04em; }
.hero__scroll { position: absolute; left: var(--gutter); bottom: var(--sp-3); }
@media (min-width: 62rem) {
  .hero__grid { grid-template-columns: 6fr 6fr; gap: var(--sp-4); }
  /* Breite aus der Höhe: Bühne ist 4:5, darf 74vh nicht übersteigen */
  .hero__art { width: min(40vw, 32rem, calc(74vh * 4 / 5)); margin-inline: 0 0; justify-self: end; }
}

/* Die große Idee: die Figur als 3D-Scan. Der Rahmen hat das Seitenverhältnis
   des Posters (4:5) — Poster und Canvas liegen deckungsgleich darin (CLS 0). */
.hero__art--3d { aspect-ratio: 4 / 5; }
.hero3d__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; user-select: none; pointer-events: none; transition: opacity .4s ease; }
.hero__art--3d canvas { cursor: grab; }
.hero__art--3d canvas:active { cursor: grabbing; }
.hero__art--3d .hero__cap { position: absolute; top: 100%; left: 0; right: 0; }

/* ======================================================= figuren ===== */
.head--figuren { position: relative; }
.head--figuren h2, .head--figuren .head__p { position: relative; z-index: 1; }
/* Eine Figur ragt in die Headline: liegt hinter dem Text, rechts, unten bündig */
.fig--head { position: absolute; right: calc(-1 * var(--gutter) / 2); bottom: -10%; width: clamp(9rem, 50vw, 15rem); z-index: 0; margin: 0; }
@media (min-width: 62rem) { .fig--head { right: -2vw; bottom: -18%; width: min(26vw, 22rem); } }
.fig img { width: 100%; }

/* Dichte Gruppe: 12 Spalten auf einem feinen Zeilenraster (grid-auto-rows in vw),
   jede Figur bekommt einen Bereich; Bereiche dürfen sich überlappen — das ist die Dichte. */
.group { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-rows: 7vw; column-gap: var(--sp-1); margin-top: var(--sp-6); }
.fig { align-self: end; }
.fig--g1  { grid-area: 1 / 1 / span 9 / span 6; }
.fig--g2  { grid-area: 3 / 7 / span 9 / span 6; }
.fig--g3  { grid-area: 10 / 2 / span 8 / span 5; }
.fig--g4  { grid-area: 11 / 7 / span 7 / span 6; }
.fig--g5  { grid-area: 17 / 1 / span 5 / span 4; }
.fig--g6  { grid-area: 16 / 5 / span 9 / span 5; }
.fig--g7  { grid-area: 18 / 9 / span 7 / span 4; }
.fig--g8  { grid-area: 22 / 1 / span 9 / span 5; }
.fig--g9  { grid-area: 24 / 6 / span 8 / span 7; }
.fig--g10 { grid-area: 31 / 2 / span 7 / span 5; }
.fig--g11 { grid-area: 30 / 7 / span 8 / span 5; }
@media (min-width: 62rem) {
  .group { grid-auto-rows: 4vw; column-gap: var(--sp-2); }
  .fig--g1  { grid-area: 1 / 1 / span 10 / span 4; }
  .fig--g2  { grid-area: 3 / 4 / span 9 / span 4; }
  .fig--g3  { grid-area: 1 / 7 / span 7 / span 3; }
  .fig--g4  { grid-area: 4 / 9 / span 8 / span 4; }
  .fig--g5  { grid-area: 10 / 2 / span 4 / span 2; }
  .fig--g6  { grid-area: 11 / 3 / span 9 / span 4; }
  .fig--g7  { grid-area: 9 / 6 / span 7 / span 3; }
  .fig--g8  { grid-area: 8 / 8 / span 7 / span 3; }
  .fig--g9  { grid-area: 12 / 10 / span 6 / span 3; }
  .fig--g10 { grid-area: 17 / 1 / span 6 / span 3; }
  .fig--g11 { grid-area: 18 / 5 / span 7 / span 3; }
}
@media (min-width: 62rem) and (min-width: 1200px) { .group { grid-auto-rows: 48px; } }

/* ======================================================= schalen ===== */
/* Das Feld: randlos, dicht, jede Schale ein Gesicht in der Menge */
.feld { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px; padding-inline: 2px; }
.schale { background: var(--paper); }
.schale img { width: 100%; }
@media (min-width: 40rem) { .feld { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .feld { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; padding-inline: 4px; } }
#schalen .note { margin-top: var(--sp-4); }

/* ------------------------------------------- Hover-Feinschliff (Figuren + Schalen) ---- */
/* Kein Eingriff am Foto selbst (Regel: Werkfotos nie verzerren/filtern) — die Figur
   kippt als Ganzes 2° und hebt sich minimal, als würden die Mundwinkel hochgehen.
   Nur mit Maus/Trackpad und wenn Bewegung erlaubt ist; das Bild trägt den Effekt
   (nicht die Figure), damit es die Parallax-Transform auf .fig (data-para) nicht überschreibt. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .fig img, .schale img { transition: transform var(--dur-1) var(--ease-out); transform-origin: 78% 100%; }
  .fig:hover img, .schale:hover img { transform: rotate(2deg) translateY(-3%); }
}

/* ===================================================== werkstatt ===== */
.werk { display: grid; gap: var(--sp-6); }
.steps { display: grid; gap: var(--sp-4); align-content: start; }
.steps__i { display: grid; gap: var(--sp-1); align-content: start; border-top: var(--hair) solid var(--line); padding-top: var(--sp-2); }
.steps__i p { max-width: 38ch; }
.steps__video { display: grid; gap: var(--sp-2); }
.loop { position: relative; aspect-ratio: 9 / 16; background: var(--ton); overflow: hidden; }
.loop__poster, .loop__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.loop__video { opacity: 0; transition: opacity .6s var(--ease-out); }
.loop.is-playing .loop__video { opacity: 1; }
.analoge { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
.analog img { width: 100%; }
.analog--w2 { grid-column: 1 / -1; }   /* Ofen volle Breite */
@media (min-width: 62rem) {
  .werk { grid-template-columns: 4fr 8fr; gap: var(--sp-5); }
  .analoge { gap: var(--sp-4); }
}

/* ======================================================= schmuck ===== */
/* Gold braucht dunkel: lockere Gruppe auf fast-schwarzem Grund */
.juwelen { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--sp-2); row-gap: var(--sp-5); align-items: center; }
.juwel img { width: 100%; }
.juwel--j1 { grid-column: 1 / span 7; }
.juwel--j2 { grid-column: 8 / span 5; margin-top: var(--sp-5); }
.juwel--j3 { grid-column: 2 / span 4; }
.juwel--j4 { grid-column: 7 / span 4; margin-top: calc(-1 * var(--sp-4)); }
.juwel--j5 { grid-column: 1 / span 5; }
.juwel--j6 { grid-column: 7 / span 2; }
.juwel--j7 { grid-column: 8 / span 5; margin-top: calc(-1 * var(--sp-5)); }
@media (min-width: 62rem) {
  .juwel--j1 { grid-column: 1 / span 4; }
  .juwel--j2 { grid-column: 6 / span 3; margin-top: var(--sp-7); }
  .juwel--j3 { grid-column: 10 / span 2; margin-top: calc(-1 * var(--sp-6)); }
  .juwel--j4 { grid-column: 2 / span 2; margin-top: calc(-1 * var(--sp-5)); }
  .juwel--j5 { grid-column: 5 / span 3; }
  .juwel--j6 { grid-column: 9 / span 1; margin-top: var(--sp-5); }
  .juwel--j7 { grid-column: 10 / span 3; margin-top: calc(-1 * var(--sp-7)); }
}

/* =================================================== zeichnungen ===== */
.sheets { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--sp-3); align-items: start; }
.sheet img, .sheet svg { width: 100%; height: auto; display: block; }
/* Zeichnen beim Reinscrollen: erst Linie (Umriss der Tuschefläche), dann Fläche */
.sheet svg path { fill-opacity: 0; stroke: currentColor; stroke-width: 2.5; stroke-linejoin: round; stroke-dasharray: var(--len, 0); stroke-dashoffset: var(--len, 0); }
.sheet.is-drawing svg path { stroke-dashoffset: 0; transition: stroke-dashoffset 1.6s var(--ease-in-out); }
.sheet.is-inked svg path { fill-opacity: 1; stroke-opacity: 0; transition: fill-opacity .5s var(--ease-out), stroke-opacity .6s var(--ease-out); }
.sheet--1 { grid-column: 1 / span 8; }
.sheet--2 { grid-column: 7 / span 6; margin-top: calc(-1 * var(--sp-6)); }
.sheet--3 { grid-column: 1 / span 7; margin-top: calc(-1 * var(--sp-4)); }
.sheet--4 { grid-column: 6 / span 7; margin-top: calc(-1 * var(--sp-5)); }
@media (min-width: 62rem) {
  .sheet--1 { grid-column: 1 / span 5; }
  .sheet--2 { grid-column: 6 / span 3; margin-top: var(--sp-7); }
  .sheet--3 { grid-column: 9 / span 4; margin-top: var(--sp-4); }
  .sheet--4 { grid-column: 3 / span 4; margin-top: calc(-1 * var(--sp-6)); }
}

/* ======================================================= objekte ===== */
/* Steck-Figuren stehen auf einer Linie wie auf einem Regal */
.objekte { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--sp-2); align-items: end; border-bottom: var(--hair) solid var(--line); padding-bottom: 2px; }
.obj img { width: 100%; }
.obj--o1 { grid-column: 1 / span 4; }
.obj--o2 { grid-column: 5 / span 4; }
.obj--o3 { grid-column: 9 / span 3; }
.obj--o4 { grid-column: 3 / span 4; margin-top: var(--sp-5); }
.obj--o5 { grid-column: 7 / span 3; margin-top: var(--sp-5); }
@media (min-width: 62rem) {
  .obj--o4, .obj--o5 { margin-top: 0; }
  .obj--o1 { grid-column: 1 / span 2; }
  .obj--o2 { grid-column: 4 / span 3; }
  .obj--o3 { grid-column: 7 / span 2; }
  .obj--o4 { grid-column: 9 / span 2; }
  .obj--o5 { grid-column: 11 / span 2; }
}

/* ========================================================= ueber ===== */
.about { display: grid; gap: var(--sp-5); }
.about .note { margin-top: 0; }
.facts { display: grid; gap: var(--sp-1); margin-top: var(--sp-4); }
.facts > div { display: grid; grid-template-columns: 7rem 1fr; gap: var(--sp-2); border-top: var(--hair) solid var(--line); padding-top: var(--sp-1); }
.facts a { text-decoration: none; }
.facts a:hover { color: var(--accent); }
.about__q { margin-top: var(--sp-5); max-width: 22ch; }
.about__portrait { max-width: 24rem; }
.about__portrait figcaption { margin-top: var(--sp-2); }
@media (min-width: 62rem) {
  .about { grid-template-columns: 7fr 4fr; column-gap: var(--sp-5); }
  .about__portrait { grid-column: 2; margin-top: var(--sp-6); justify-self: end; width: 100%; }
}

/* ======================================================= kontakt ===== */
.kontakt { padding-block: var(--sp-7); }
.kontakt__h { margin-bottom: var(--sp-5); }
/* Kontakt-Hero ist jetzt Danis Logo (SVG, viewBox 1500×1500 — quadratisch,
   die zwei konzentrischen Ringe sind rund) statt der fotografierten Schale;
   max. 60 vh, zentriert, gleiche Größenordnung wie vorher. */
.face { position: relative; width: min(100%, 60vh); margin-inline: auto; }
.face__logo { width: 100%; }
/* Pupillen: dieselbe Klasse/Logik wie beim Header-Logo (main.js → eyes(),
   --dx/--dy sitzen auf dem Eltern-<g>) — hier nur in der großen Version
   automatisch gut sichtbar, weil der Container viel größer ist als 2rem. */
/* Die Mail sitzt im Mund-Bereich des Logos (x 511–978, y 1117–1275 im
   1500er viewBox — am gerenderten Logo vermessen, siehe docs/handover.md).
   Deutlich kleinere Fläche als die alte Schalen-Mundöffnung → Schriftgröße
   entsprechend kleiner skaliert, damit der Platzhalter/die echte Adresse
   nicht über die Mundform hinausläuft. */
.face__mail {
  position: absolute; left: calc(511 / 1500 * 100%); top: calc(1117 / 1500 * 100%);
  width: calc(467 / 1500 * 100%); height: calc(158 / 1500 * 100%);
  display: grid; place-items: center; text-align: center; color: var(--paper);
}
.face__mail a, .face__ph { font-family: var(--font-display); font-variation-settings: var(--display-axes); font-size: clamp(0.5rem, 1.6vw, 1.1rem); line-height: 1.05; overflow-wrap: anywhere; text-transform: none; letter-spacing: 0; }
.face__mail a:hover { text-decoration: underline; text-underline-offset: 0.12em; }
/* Fallback, wenn die echte Adresse nicht in den (kleinen) Mund passt: .kontakt--below */
.kontakt--below .face__mail { position: static; width: auto; height: auto; margin-top: var(--sp-3); }
.kontakt--below .face__mail a, .kontakt--below .face__ph { font-size: clamp(0.85rem, 4vw, 2.2rem); }
.kontakt__ig { margin-top: var(--sp-5); text-align: center; font-family: var(--font-display); font-variation-settings: var(--display-axes); font-size: var(--step-2); line-height: 1.1; }
.kontakt__ig a:hover { text-decoration: underline; text-underline-offset: 0.12em; }
.kontakt .note { margin-top: var(--sp-4); }
/* Scroll-Ende: „nicer." erscheint unter dem Logo (main.js, IntersectionObserver
   auf den Footer, setzt .is-nicer). */
/* --- Feature: Sprechblasen-Fix --- dieselbe Blase wie bei den Schalen
   (.schale__blase). Seit Logo-statt-Foto (Ticket "Kontaktseite — Logo statt
   Foto-Schale") kein Mundwinkel-Pfad (.face__corner) mehr nötig: das Logo hat
   schon eine feste, gezeichnete Mundform, anders als das Foto brauchte es
   keinen Overlay-Trick für ein Lächeln. */
.face__nicer {
  position: absolute; left: 50%; bottom: -2.6em; transform: translate(-50%, -4px) scale(0.92);
  background: var(--paper); color: var(--ink); border: 2px solid var(--ink);
  border-radius: 14px 14px 14px 3px;
  padding: 0.3em 0.7em; white-space: nowrap;
  opacity: 0; transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out);
}
.face__nicer::before, .face__nicer::after {
  content: ""; position: absolute; left: 50%; bottom: 100%; width: 0; height: 0;
}
.face__nicer::before { translate: -50% 0; border: 7px solid transparent; border-bottom-color: var(--ink); }
.face__nicer::after { translate: -50% 2px; border: 5px solid transparent; border-bottom-color: var(--paper); }
.face.is-nicer .face__nicer { opacity: 1; transform: translate(-50%, 0) scale(1); }
@media (prefers-reduced-motion: reduce) { .face__nicer { transition: none; } }
/* --- /Feature --- */

/* ---- Kleinkram: Cursor wird über Werken zur kleinen Hand, die etwas hält ---- */
#figuren .fig img,
#schalen .schale img,
#objekte .obj img { cursor: url("../img/cursor-hand.svg") 16 6, default; }
#schmuck .juwel img { cursor: url("../img/cursor-hand-light.svg") 16 6, default; }

/* ======================================================== footer ===== */
.footer { border-top: var(--hair) solid var(--line); padding-block: var(--sp-6) var(--sp-4); }
.footer__top { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; margin-bottom: var(--sp-6); }
@media (min-width: 52rem) { .footer__top { grid-template-columns: minmax(0, 2fr) repeat(2, minmax(0, 1fr)); gap: var(--sp-4); } }
.footer__mark { width: clamp(4rem, 8vw, 6rem); height: auto; margin-bottom: var(--sp-3); }
.footer__name { font-size: var(--step-2); margin-bottom: var(--sp-2); }
.footer__col { display: grid; gap: 0.6rem; align-content: start; }
.footer__h { margin-bottom: var(--sp-1); }
.footer__col a:hover { color: var(--accent); }
.footer__legal { display: grid; gap: var(--sp-3); padding-top: var(--sp-3); border-top: var(--hair) solid var(--line); }
@media (min-width: 52rem) { .footer__legal { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; } }
.footer__imprint { max-width: 64ch; text-transform: none; letter-spacing: 0.04em; }
.footer__imprint summary { cursor: pointer; text-transform: uppercase; letter-spacing: var(--mono-track); }
.footer__imprint details + details { margin-top: var(--sp-2); }
.footer__imprint p { margin-top: var(--sp-2); }
.footer__imprint b { font-weight: 500; }
.footer__copy { text-transform: none; letter-spacing: 0.04em; }

/* Eigener Button statt gedämpftem Textlink: gut sichtbar, bleibt aber im
   Footer (Regel 8: keine Deckkraft auf Text — Hierarchie über Größe/Fläche,
   nicht über opacity). Hover/Focus kippt die Fläche in Akzentfarbe (dasselbe
   Inversions-Prinzip wie bei den s--*-Sektionen, nur im Kleinen). */
.footer__poster {
  margin-top: var(--sp-3);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: var(--hair) solid var(--line);
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.footer__poster:hover, .footer__poster:focus-visible {
  background: var(--accent); border-color: var(--accent); color: var(--paper);
}
.footer__poster__text { display: grid; gap: 0.3rem; }
.footer__poster__kicker { font-size: var(--mono-size); }
.footer__poster__label { font-family: var(--font-display); font-size: var(--step-0); font-variation-settings: var(--display-axes); }
.footer__poster__arrow { font-size: var(--step-1); transition: transform var(--dur-1) var(--ease-out); }
.footer__poster:hover .footer__poster__arrow, .footer__poster:focus-visible .footer__poster__arrow { transform: translateX(0.3em); }
@media (prefers-reduced-motion: reduce) {
  .footer__poster, .footer__poster__arrow { transition: none; }
}

/* =========================================================== 404 ===== */
.err { min-height: 80svh; display: grid; align-items: center; padding-block: var(--sp-7) var(--sp-6); }
.err__grid { display: grid; gap: var(--sp-5); align-items: center; justify-items: center; text-align: center; }
.err__art { width: min(60vw, 16rem); }
.err__n { margin-bottom: var(--sp-3); }
.err__p { max-width: 40ch; margin-top: var(--sp-3); font-size: var(--step-1); line-height: 1.4; margin-inline: auto; }
.err__back { margin-top: var(--sp-4); }
.err__back a:hover { color: var(--accent); }
@media (min-width: 52rem) {
  .err__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); text-align: left; justify-items: start; }
  .err__art { width: 100%; max-width: 22rem; justify-self: end; }
}

/* =================================================== Kleinkram 2 ===== */
/* Sieben kleine, unabhängige Spielereien. Jede für sich entfernbar. */

/* --- Feature: Krümel-Scrollbalken --- dünne Leiste über allem, kein Balken-
   Style: nur eine leise Spur in Akzentfarbe (18 % Deckkraft) plus ein kleiner,
   runder Krümel am aktuellen Fortschrittspunkt. Breite/Position kommen aus
   --progress (main.js, onScroll aus scroll.js, rAF-gebündelt). */
.kruemelbar { position: fixed; inset-inline: 0; top: 0; height: 3px; z-index: 30; pointer-events: none; }
.kruemelbar__kruemel {
  position: absolute; top: 50%; left: var(--progress, 0%);
  width: 7px; height: 7px; margin-left: -3.5px;
  border-radius: 50%; background: var(--kobalt);
  transform: translateY(-50%);
}
.kruemelbar__kruemel::before {
  content: ""; position: absolute; top: 50%; right: 100%; left: -100vw; height: 2px;
  background: var(--kobalt); opacity: 0.18; transform: translateY(-50%);
}

/* --- Feature: Fußspuren/Stempel-Trail --- Daniels Logo (dieselbe Marke wie in
   Kopf-/Fußzeile) taucht kurz als Abdruck auf, wenn eine neue Sektion ins Bild
   kommt, und verblasst wieder (main.js, ein IntersectionObserver für alle
   Sektionen). mix-blend-mode: difference macht das Motiv auf jedem Sektions-
   grund lesbar, ohne Farbe pro Sektion zu unterscheiden. */
.stempel {
  position: fixed; left: var(--gutter); bottom: var(--gutter); z-index: 15;
  width: clamp(2rem, 5vw, 3rem); color: #fff; mix-blend-mode: difference;
  opacity: 0; transform: scale(0.85) rotate(-8deg); pointer-events: none;
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.stempel.is-in { opacity: 0.9; transform: scale(1) rotate(-8deg); }
@media (prefers-reduced-motion: reduce) { .stempel { display: none; } }

/* --- Feature: Sprechblasen an weiteren Gesichts-Schalen --- nach Vorbild der
   Kontakt-Schale ("nicer."): Hover/Focus zeigt einen Ein-Wort-Kommentar. */
.schale--sprechend { position: relative; }
/* --- Feature: Sprechblasen-Fix --- war ein reines Text-Label (Rechteck, kein
   Zeiger). Jetzt: sichtbare 2px-Kontur statt Schatten-Deko, erhöhter und leicht
   asymmetrischer border-radius (eine scharfe Ecke = Blasenform statt Pille),
   deckender Papier-Grund, CSS-Dreieck als Zeiger Richtung Mund/Augen der
   Schale (Doppel-Dreieck-Technik: äußeres in der Kontur-Farbe, inneres 2px
   kleiner in Papier — dadurch hat auch der Zeiger eine Kontur). Gilt für alle
   Schalen inkl. der Kontakt-Schale ("nicer.", weiter unten in dieser Datei). */
.schale__blase {
  position: absolute; top: 8%; left: 50%; transform: translate(-50%, -6px) scale(0.92);
  background: var(--paper); color: var(--ink); border: 2px solid var(--ink);
  border-radius: 14px 14px 3px 14px;
  padding: 0.35em 0.7em; white-space: nowrap; z-index: 2;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.schale__blase::before, .schale__blase::after {
  content: ""; position: absolute; left: 50%; top: 100%; width: 0; height: 0;
}
.schale__blase::before { translate: -50% 0; border: 7px solid transparent; border-top-color: var(--ink); }
.schale__blase::after { translate: -50% -2px; border: 5px solid transparent; border-top-color: var(--paper); }
.schale--sprechend:hover .schale__blase,
.schale--sprechend:focus-visible .schale__blase { opacity: 1; transform: translate(-50%, 0) scale(1); }
@media (prefers-reduced-motion: reduce) { .schale__blase { transition: none; } }
/* --- /Feature --- */

/* --- Feature: Copy-Toast bei E-Mail-Klick --- Button statt Link (Klick kopiert,
   öffnet keinen Mail-Client), Sprechblase "kopiert." statt Browser-alert(). */
.face__mailbtn { background: none; border: 0; padding: 0; margin: 0; color: inherit; cursor: pointer; }
.face__toast {
  position: absolute; left: 50%; bottom: 100%; transform: translate(-50%, 4px);
  margin-bottom: 0.6em; background: var(--paper); color: var(--ink);
  border: var(--hair) solid var(--line); padding: 0.3em 0.7em;
  font-family: var(--font-mono); font-size: var(--mono-size); text-transform: uppercase;
  letter-spacing: var(--mono-track); white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.face__toast.is-visible { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) { .face__toast { transition: none; } }

/* --- Feature: Print-Stylesheet --- Nav, Buttons, Video/3D-Hero raus; die
   inversen Sektionen (Schmuck, Kontakt) bekommen dunkle Schrift, weil Browser
   Hintergrundfarben beim Drucken normalerweise weglassen — sonst würde der
   helle Text auf weißem Papier verschwinden. */
.print-only { display: none; }
@media print {
  .top, .footer__poster, .hero__art--3d, video,
  .kruemelbar, .stempel, .face__toast,
  .footer__timer, .fig::before, .fig::after,
  .schale::before, .schale::after { display: none !important; }
  .s--ink, .s--kobalt { background: none !important; color: var(--ink) !important; }
  body { background: #fff; }
  .hero__grid { display: block; }
  .print-only {
    display: block; max-width: 60ch; margin-top: var(--sp-4);
    border-top: var(--hair) solid var(--line); padding-top: var(--sp-2);
    font-family: var(--font-mono); font-size: var(--mono-size);
    text-transform: none; letter-spacing: 0.04em;
  }
}

/* ================================================ Artsy-Kleinkram ===== */
/* Acht kleine, unabhängige Spielereien (Sprechblasen-Fix + Pupillen-Fix +
   Logo-Augen stehen weiter oben, direkt bei den Regeln, die sie korrigieren/
   erweitern). Haltung: "ernst gebaut, unernst gemeint" (docs/spielzeug-konzept.md). */

/* --- Feature: Echtheits-Etikett (Hangtag) --- Hover/Focus auf eine Figur oder
   Schale zeigt ein gedrehtes Anhänger-Etikett, wie eine Sneaker-Authentifizierung.
   TEXT IST VORSCHLAG (zur Freigabe, siehe wunschliste-daniel.md). Reines CSS
   (::after + content), kein JS, kein Antasten der 27 Werk-Markups nötig.
   Nur Hover (Maus/Trackpad) — Figuren/Schalen sind normalerweise nicht
   fokussierbar; :focus-within greift zusätzlich dort, wo Kleinkram 2 schon
   tabindex gesetzt hat (die drei sprechenden Schalen), aber nicht flächendeckend
   nachgerüstet — hätte die Tab-Reihenfolge der ganzen Seite für ein rein
   dekoratives Detail spürbar verändert. */
.fig:not(.fig--head) { position: relative; }
.schale { position: relative; }
/* Die Gruppen sind bewusst dicht/überlappend (siehe .group/.feld) — beim
   Hover/Focus rückt die ganze Figur vor die Nachbarn, sonst würde das Etikett
   teils hinter der überlappenden Nachbarfigur verschwinden. */
.fig:hover, .fig:focus-within, .schale:hover, .schale:focus-within { z-index: 5; }
@media (hover: hover) and (pointer: fine) {
  .fig::after, .schale::after {
    content: "ORIGINAL · HANDGEFERTIGT · MÜNCHEN";
    position: absolute; bottom: 5%; left: 4%; z-index: 3;
    font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: var(--mono-track);
    background: var(--paper); color: var(--ink); border: 1px solid var(--ink);
    padding: 0.3em 0.5em; white-space: nowrap; pointer-events: none;
    opacity: 0; transform: rotate(-5deg) scale(0.85);
    transition: opacity var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
  }
  .fig:hover::after, .fig:focus-within::after,
  .schale:hover::after, .schale:focus-within::after { opacity: 1; transform: rotate(-5deg) scale(1); }
  @media (prefers-reduced-motion: reduce) { .fig::after, .schale::after { transition: none; } }
}

/* --- Feature: Seriennummer je Werk --- rein kosmetisch generiert (Farb-Kürzel
   aus data-col + fortlaufender CSS-Counter je Sektion) — keine echte Inventar-
   oder Verkaufslogik, kein Shop-Signal, sehr klein/low-key. data-col steht auf
   jeder .fig/.schale (Wert aus dem bereits vorhandenen alt-Text übernommen,
   nichts Neues erfunden). Format ist VORSCHLAG, siehe wunschliste-daniel.md. */
#figuren { counter-reset: werk; }
#schalen { counter-reset: werk; }
.fig, .schale { counter-increment: werk; }
/* position:relative redundant mit dem Hangtag-Feature weiter oben — hier
   trotzdem eigenständig gesetzt, damit diese Sektion für sich allein
   funktioniert (kein Feature darf ein anderes voraussetzen). */
.fig:not(.fig--head) { position: relative; }
.schale { position: relative; }
.fig::before, .schale::before {
  content: "DG-" attr(data-col) "-" counter(werk, decimal-leading-zero);
  position: absolute; bottom: 3%; right: 3%; z-index: 1;
  font-family: var(--font-mono); font-size: 0.55rem; letter-spacing: 0.06em;
  color: var(--ink); opacity: 0.4; pointer-events: none; white-space: nowrap;
}
.s--ink .schale::before, .s--ink .fig::before { color: var(--paper); }

/* --- Feature: Drop-Nummer im Footer --- Build-Nummer manuell im Code gepflegt
   (kein automatischer Zähler), Datum = Datum dieses Builds (nicht live "heute"
   bei jedem Aufruf — sonst würde die Seite bei jedem Besuch ein falsches "heute"
   zeigen). Startwert 001 und Format sind VORSCHLAG, siehe wunschliste-daniel.md. */
.footer__drop { margin-top: var(--sp-1); }

/* --- Feature: Live-Timer "Sekunden hier" --- zählt seit Seitenaufruf hoch,
   main.js aktualisiert höchstens 1×/Sekunde (setInterval, kein rAF-Loop nötig
   für eine Sekundenanzeige). IBM Plex Mono ist ohnehin eine Festbreiten-Schrift
   (jede Ziffer gleich breit) — tabular-nums zusätzlich gesetzt, schadet nicht
   und macht die Absicht explizit. */
.footer__timer { margin-top: var(--sp-1); font-variant-numeric: tabular-nums; }

/* --- Feature: Logo-Cursor sitewide --- war erst nur an zwei ausgewählten
   Stellen (Sektions-Überschriften, Leerraum zwischen Werken), jetzt
   Standard-Cursor für die ganze Seite (bruni-Entscheidung, Folge-Ticket zu
   "Logo-Cursor an ausgewählten Stellen") — dieselben Assets wie vorher,
   nichts Neues erstellt. `body` trägt den dunklen Cursor (Standard, passt zu
   Papier/Rohton), die zwei dunklen Sektionen kippen auf den hellen:
   `.s--ink`/`.s--kobalt` (Schmuck, Kontakt). Gilt automatisch auch für
   poster.html und 404.html, die dasselbe site.css laden — poster.html hat
   nur `.s--paper` auf dem `<body>`, keine dunkle Sektion, braucht also keine
   eigene Regel.
   Ausnahmen bleiben unverändert erhalten, weil eigene cursor-Deklarationen
   auf einem Element immer gegen einen nur ererbten Wert gewinnen (unabhängig
   von Spezifität) — kein struktureller Konflikt mit body/.s--ink/.s--kobalt:
   - Figuren/Schalen/Objekte: Hand-Cursor (weiter unten, `#figuren .fig img`
     etc., aus Kleinkram 2) bleibt aktiv.
   - Stempel-Moment auf der 404-Seite (`.err__art`) bleibt aktiv.
   - hero3d-Canvas (`grab`/`grabbing`) und die Poster-Baukasten-Regler
     (`.piece__resize`, `.piece__rotate`, …) bleiben aktiv.
   - Echte interaktive Standardelemente (Links, Buttons — inkl. dem Header-
     Logo-Link selbst) brauchen eine EIGENE Regel, sonst würden sie den
     ererbten Logo-Cursor übernehmen statt ihren Zeiger zu behalten (cursor
     ist eine vererbte Eigenschaft). Keine Formularfelder auf der Seite
     (geprüft) — deshalb keine Extra-Regel für input/select/textarea, die
     bräuchten ohnehin je nach Feldtyp einen anderen Cursor (z. B. `text`
     statt `pointer`) als pauschal zu raten. */
body { cursor: url("../img/cursor-logo.svg") 15 15, default; }
.s--ink, .s--kobalt { cursor: url("../img/cursor-logo-light.svg") 15 15, default; }
a, button { cursor: pointer; }

/* --- Feature: Stempel-Moment (404-Seite) --- Cursor wird zum Stempel-Icon
   (eigene, einfache Silhouette, kein Foto — gleiches Prinzip wie cursor-
   hand.svg) über der Scherben-Zeichnung; ein Klick legt Daniels Logo (aus
   logo.svg, keine neue Grafik) kurz als "gestempelte" Markierung an die
   Klickstelle, main.js entfernt sie nach ~600ms wieder. Bewusst nur hier —
   kein Dauerzustand, kein zweiter Ort. */
.err__art { position: relative; cursor: url("../img/cursor-stempel.svg") 16 28, default; }
.stempel-moment__mark {
  position: absolute; width: 4.5rem; height: 4.5rem; color: var(--ink);
  transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(0.4);
  opacity: 0; pointer-events: none;
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
}
.stempel-moment__mark.is-stamped {
  opacity: 0.85; transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(1);
  transition: opacity 90ms var(--ease-out), transform 90ms var(--ease-out);
}
@media (prefers-reduced-motion: reduce) { .stempel-moment__mark { display: none; } }
