/* ===================================================================
   GALLERY STACK

   Nachbau der dropping-stack-Komponente von paulkalkbrenner.net. Das
   vordere Bild liegt ganz vorn, drei weitere warten darüber und dahinter
   (echte Tiefe über perspective und translateZ, gesetzt in
   gallery-stack.js). Ein Schritt lässt das vordere Bild nach unten
   wegfallen, der Rest rückt nach.

   Erreicht der Abschnitt beim Runterscrollen den oberen Rand, rastet er
   ein; dann lässt jede Scroll-Geste genau ein Bild fallen, sieben Mal,
   danach geht es weiter (siehe gallery-stack.js, 08.10.).

   White ground, black text.
   =================================================================== */

/* Keine Klebe-Strecke mehr (08.10.): Die Bilder fallen nicht über eine
   Scrollstrecke, sondern je Geste, während der Abschnitt eingerastet ist.
   --stack-lauf bleibt als Stellschraube stehen, auf 0. */
.stack-section {
  background: var(--white);
  color: var(--black);
  /* Die Polsterung wandert auf den klebenden Inhalt: min-height hier
     rechnet mit border-box, und Polsterung am Abschnitt läge außerhalb
     seiner Inhaltsbox — dorthin kann ein klebendes Kind nicht wandern. */
  padding-block: 0;
  --stack-lauf: 0px;
  /* Nichts verlässt den Abschnitt: kein seitlich gezogenes Bild als
     Querscroll, und kein fallendes Bild unten in den nächsten Abschnitt
     hinein. clip statt hidden: hidden machte den Abschnitt zum
     Scroll-Container, und daran scheitert das Kleben des Inhalts. */
  overflow: clip;
  min-height: calc(100svh + var(--stack-lauf));
}
/* Der Inhalt bleibt stehen, während die Strecke durchläuft. Volle
   Fensterhöhe plus Zentrierung, damit der Stapel dabei mittig im Bild
   steht statt am oberen Rand zu kleben. */
.stack-section > .wrap {
  position: sticky;
  top: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Höhenbezogen statt breitenbezogen, und das ist hier der Punkt: Der
     Abschnitt muss in EINE Fensterhöhe passen, sonst steht die Leiste
     mit Prev/Next über die ganze Klebe-Strecke unter der Falz. Mit den
     Breiten-Tokens (--space-xl/2xl) war der Inhalt 964px hoch bei 768px
     Fenster — 1.25 Bildschirmhöhen. Gemessen mit diesen Werten: 711px
     bei 768, 814px bei 900, 580px bei 600. */
  padding-block: clamp(2rem, 6svh, 5rem);
}
.stack-section .stack-head {
  margin-bottom: clamp(1.5rem, 4svh, 3.5rem);
}
/* Sobald der Stapel fast die ganze Breite einnimmt, steht die wartende
   Reihe genau unter der Überschrift statt neben ihr: das hinterste
   Bild ragt rund 36% der Stapelhöhe über dessen Oberkante hinaus. Auf
   dem Telefon sind das etwa 93px, die Überschrift braucht also
   mindestens so viel Luft nach unten. Auf breiten Fenstern ist der
   Stapel mittig und schmaler als die Zeile, dort entsteht das Problem
   nicht und der Abstand bleibt knapp. */
@media (max-width: 900px) {
  .stack-section .stack-head { margin-bottom: clamp(3.5rem, 11svh, 6rem); }
}

.stack-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-s) var(--space-2xl);
  margin-bottom: var(--space-xl);
}
/* --size-h2 was out of scale here — this is a section heading like any
   other on the site, not a page title, and it was eating the vertical
   room the images needed */
.stack-head h2 {
  font-size: var(--size-h3);
  text-transform: uppercase;
  line-height: 0.9;
}
/* Stack centred in the row, note beside it and vertically centred
   against the images. The empty first column is what keeps the stack
   itself centred on the page rather than pushed left by the note. */
.stack-body {
  display: grid;
  /* The middle track is sized explicitly rather than left to `auto`.
     .stack's own width is a min() containing 100%, and a percentage
     inside a content-sized track is circular — the track collapsed to
     zero and the images vanished. Here the percentage resolves against
     the grid container, which is definite. */
  grid-template-columns: minmax(0, 1fr) var(--stack-w) minmax(0, 1fr);
  align-items: center;
  gap: var(--space-l);
}
.stack-body > .stack { grid-column: 2; width: 100%; }
.stack-note {
  grid-column: 3;
  align-self: center;
  max-width: 24ch;
  color: var(--fg-muted);
  font-size: var(--size-small);
}

/* ---- the stack itself ---- */
/* 4:3 frame. The set is 9 photos at 1.5 and 5 near-square at 1.06, so
   4:3 sits between them: a light top/bottom crop on the 35mm frames, a
   modest side crop on the medium-format scans, nothing mangled. The
   earlier frame was 3.25 wide and cut both to ribbons.
   Width is capped so the height still fits a short viewport together
   with the heading and the bar — that overflow pushed the controls off
   screen before. */
/* One source for the stack's width, so the grid track and the stack
   itself cannot disagree. Height-bound, since a 4:3 frame on a short
   viewport runs out of vertical room long before horizontal. */
.stack-section { --stack-w: min(100%, calc(62svh * 4 / 3), calc(42rem * 4 / 3)); }
.stack {
  position: relative;
  width: var(--stack-w);
  aspect-ratio: 4 / 3;
  margin-inline: auto;
  /* room above for the peeking strips of the upcoming frames */
  margin-top: 2.2rem;
}

.stack__clip {
  position: absolute;
  inset: 0;
}

.stack__item {
  position: absolute;
  inset: 0;
  display: block;
  /* grab, nicht pointer: Das vordere Bild wird gezogen. Ein Klick ohne
     Zug öffnet weiterhin das Projekt. */
  cursor: grab;
  /* gegen den nativen Link-Drag der Maus, zusätzlich zum Skript */
  -webkit-user-drag: none;
  user-select: none;
  -webkit-touch-callout: none;
  transform-origin: 50% 50%;
  overflow: hidden;
  /* Keine transition: Dauer und Kurve jedes Schritts gehören dem Skript. */
}
.stack__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
}
/* ---- bar: counter left, Prev/Next right ---- */
.stack__bar {
  display: flex;
  align-items: baseline;
  margin-top: var(--space-s);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: var(--w-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--black);
}
/* Prev sits hard left, Next hard right, counter centred between them.
   The thumbnails that used to sit beside the words are gone. */
.stack__bar { justify-content: space-between; }
/* Über die Rahmen gelegt. Der abgehende Rahmen zieht auf seinen ersten
   Prozenten über die Leiste hinweg; ohne eigene Ebene läge der Zähler
   in diesem Moment unter dem Foto. Am Original liegt der abgehende
   Rahmen bei z-index 2000 über allem — die Leiste hier darüber zu
   lassen ist die eine bewusste Abweichung, damit die Bedienung lesbar
   bleibt. */
.stack__bar,
.stack-note { position: relative; z-index: 1100; }
.stack__count { font-variant-numeric: tabular-nums; }

.stack__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--black);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  position: relative;
}
/* Hover: keine Linie; die Farbe breitet sich vom Mauspunkt aus (F3,
   siehe "HOVER AUF TEXT" in components.css) */

/* Eingerastet (gallery-stack.js): Die Seite scrollt nicht, solange die
   Bilder je Geste fallen; das hält auch den Nachlauf eines Trackpad-
   Wischs an. scrollbar-gutter hält den Platz einer sichtbaren
   Bildlaufleiste frei, damit nichts seitlich springt. */
html.stapel-sperre { overflow: hidden; scrollbar-gutter: stable; }

/* Schon gesehen (05.10.: "nur beim ersten Aufruf"): Beim nächsten Besuch
   der Startseite im selben Tab läuft die Galerie nicht mehr über das
   Scrollen ab. Der Stapel steht dann wie ein gewöhnlicher Abschnitt im
   Fluss; Prev/Next, Ziehen und Wischen gehen weiter. */
html.stapel-frei .stack-section { min-height: 0; --stack-lauf: 0px; padding-block: var(--space-xl) var(--space-2xl); }
html.stapel-frei .stack-section > .wrap { position: static; min-height: 0; display: block; padding-block: 0; }

@media (prefers-reduced-motion: reduce) {
  .stack__item { transition: none; }
  /* Ohne Bewegung gibt es nichts zu scrollen: das Skript schaltet dann
     auf reines Prev/Next um. Eine Klebe-Strecke wäre hier nur eine
     Bildschirmhöhe Leerlauf, also fällt sie weg. */
  .stack-section { min-height: 0; --stack-lauf: 0px; padding-block: var(--space-xl) var(--space-2xl); }
  .stack-section > .wrap { position: static; min-height: 0; display: block; padding-block: 0; }
}
@media (max-width: 900px) {
  /* no room for a side column: the note goes back under the stack,
     still reading as one unit with it */
  .stack-body {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-s);
  }
  .stack-body > .stack { grid-column: 1; }
  .stack-note { grid-column: 1; max-width: none; }
}
@media (max-width: 640px) {
  .stack-section { --stack-w: min(100%, calc(46svh * 4 / 3)); }
  .stack { margin-top: 2rem; }
}
