/*
 * Sammlungs-Browser: Tab-Leiste, Karussell und Sprung-Raster
 * Markup dazu: site/snippets/collection-browser.php
 * Verhalten dazu: assets/js/collection-browser.js
 *
 * Grundzustand ist eine wischbare Spur — genau das, was ohne JavaScript
 * bedienbar bleibt. Erst mit html.js (Inline-Script im Header) wird daraus die
 * 3-up-Anordnung: Mitte gross, Nachbarn klein und gedimmt.
 *
 * Alle Folien sind gleich breit, gross wird die aktive allein über transform.
 * Das ist keine Kosmetik: würde die Breite mitwandern, müsste das JS die
 * Verschiebung mitten in einer laufenden Übergangsanimation messen und läge
 * dabei zwangsläufig daneben. So bleibt das Layout unverändert, die Bewegung
 * läuft auf dem Compositor, und die Verschiebung ist einmal gemessen richtig.
 *
 * Kein .reveal auf den Einträgen: bei hundert Zellen wäre das gestaffelte
 * Erscheinen (media-reveal.js) eine minutenlange Warteschlange statt einer
 * Welle. Der Blur-up der einzelnen Bildfläche greift unverändert.
 */

.browser {
  /* Höhe der Bühne. Auf ihr liegen nur noch die Bilder — die Zeile mit Titel,
     Status und «Details» steht darunter still (.browser__caption). Damit ist
     eine Folie schlicht das Quadrat, und Höhe und Breite sind dieselbe Zahl. */
  --browser-stage: 400px;
  /* Breite einer Folie im Layout. Alle gleich — siehe Kopfkommentar. */
  --browser-slide: min(86%, var(--browser-stage));
  --browser-gutter: 1rem;
  /* Verkleinerung der Nachbarn. Der Ursprung liegt an der dem Zentrum
     zugewandten Kante, damit sie sich an die aktive Folie schmiegen, statt
     eine Lücke zu hinterlassen. */
  --browser-side-scale: 0.55;
  --browser-thumb: 75px;
  --browser-accent: var(--color-hover);
  /* Stärke der Hervorhebung im Raster */
  --browser-mark: 0.25rem;

  margin-top: 3rem;
  /* Luft, wenn der Rückweg von einer Detailseite hierher springt
     (siehe snippets/collection-back.php) */
  scroll-margin-top: 2rem;
  padding: 2rem;
  background-color: rgb(250, 250, 250);
  border-radius: 1em;
  box-shadow: inset 0 0 .5em hsla(0, 0%, 0%, 0.1);
}

.browser__title {
  margin-top: 0;
  margin-bottom: 1.5rem;
  width: 100%;
  text-align: center;
  font-size: large;
  font-weight: 500;
  margin-bottom: 2em;
  padding-bottom: 1em;
  border-bottom: 1px solid var(--color-text-grey);
}

/* Alle Bildflächen im Browser sind quadratisch. Die Presets (square, thumb)
   schneiden zwar schon zu, aber media.php fällt bei animierten GIFs auf das
   Seitenverhältnis der Datei zurück — hier gilt das Quadrat trotzdem. */
.browser .media {
  aspect-ratio: 1 / 1;
}

/* ====================================== */
/* TAB-LEISTE                              */
/* ====================================== */

/* .filter und .filter-label kommen aus index.css — die Leiste sieht aus wie
   die übrigen Filter der Seite. */
.browser__tabs {
  margin-bottom: 1.5rem;
}

.browser__count {
  margin-left: 0.4em;
  font-variant-numeric: tabular-nums;
  opacity: 0.6;
}

/* ====================================== */
/* BÜHNE                                   */
/* ====================================== */

.browser__stage {
  position: relative;
  /* Die Höhe kommt aus den Folien und ist damit --browser-stage. Waagrecht
     wird abgeschnitten: die Spur ist breiter als die Bühne, alles ausserhalb
     bleibt ungeladen (loading="lazy"). clip statt hidden — hidden macht die
     Bühne zum Rollbereich, und ein Rollbereich lässt sich verschieben. */
  overflow: hidden;
  overflow: clip;
}

.browser__track {
  display: flex;
  gap: var(--browser-gutter);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  /* Wischen in der Spur soll nicht die ganze Seite mitziehen */
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Die Rollbalken-Leiste sässe quer unter den Bildern */
  scrollbar-width: none;
}

.browser__track::-webkit-scrollbar {
  display: none;
}

.browser__slide {
  flex: 0 0 var(--browser-slide);
  min-width: 0;
  margin: 0;
  scroll-snap-align: center;
}

.browser__slide[hidden],
.browser__cell[hidden] {
  display: none;
}

/* Mit JavaScript blättert nicht der Scroll-Container, sondern das JS
   verschiebt die Spur auf die gemessene Position (--browser-shift). */
.js .browser__track {
  /* visible statt hidden/clip: eine Fläche schneidet ihren Inhalt am eigenen,
     unverschobenen Rahmen zu — noch bevor das transform darunter greift. Bei
     mehr als zwei, drei Folien liegt jede weitere aber schon ausserhalb
     dieses Rahmens (offsetLeft wächst mit jeder Folie), und würde dort
     abgeschnitten, lange bevor sie ins Bild rückt. Sichtbar wird sie erst
     durchs Verschieben — genau das braucht also visible statt clip. Zugleich
     macht visible die Spur zu keinem Rollbereich, ganz ohne dass hidden das
     erst über den scrollLeft-Umweg verhindern müsste. Den waagrechten
     Zuschnitt übernimmt weiterhin .browser__stage: die ist nicht selbst
     verschoben, ihr Rahmen bleibt also die ganze Zeit an derselben Stelle. */
  overflow-x: visible;
  scroll-snap-type: none;
  /* Waagrecht wird geblättert, senkrecht scrollt weiterhin die Seite */
  touch-action: pan-y;
  transform: translate3d(var(--browser-shift, 0px), 0, 0);
  transition: transform 550ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Der erste Aufbau setzt die Spur an ihre Position, statt sichtbar
   dorthin zu fahren. collection-browser.js setzt .is-ready danach. */
.js .browser:not(.is-ready) .browser__track,
.js .browser:not(.is-ready) .browser__slide {
  transition: none;
}

.js .browser__slide {
  transform: scale(var(--browser-side-scale));
  opacity: 0;
  transition: transform 550ms cubic-bezier(0.16, 1, 0.3, 1),
              opacity 400ms ease;
}

.js .browser__slide.is-prev,
.js .browser__slide.is-next {
  opacity: 0.45;
}

.js .browser__slide.is-prev {
  transform-origin: right center;
}

.js .browser__slide.is-next {
  transform-origin: left center;
}

.js .browser__slide.is-current {
  transform: scale(1);
  opacity: 1;
}

.browser__slide .media {
  --media-bg: #f5f5f5;
}

/* Das Bild führt nirgendwohin (siehe collection-browser-slide.php), ein Klick
   auf eine Nachbarfolie holt sie trotzdem in die Mitte — der Zeiger soll das
   ankündigen. Auf der aktiven Folie passiert das nicht, dort bleibt er neutral. */
.js .browser__slide:not(.is-current) {
  cursor: pointer;
}

/* ====================================== */
/* ZEILE ZUM AKTIVEN EXPONAT               */
/* ====================================== */

/*
 * Ohne JavaScript steht sie in jeder Folie und zieht mit ihr vorbei — anders
 * geht es dort nicht. Mit JavaScript wandert ihr Inhalt in eine einzige Zeile
 * unter der Bühne, die stehen bleibt und nur ihren Inhalt wechselt.
 */
.browser__slide-body,
.browser__caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5em 0.75em;
  width: min(100%, var(--browser-slide));
  margin: 0.75em auto 0;
  color: inherit;
  text-decoration: none;
}

.browser__caption {
  display: none;
}

.js .browser__slide-body {
  display: none;
}

.js .browser__caption {
  display: flex;
  transition: opacity 180ms ease;
}

/* Kurz weg, während collection-browser.js den Inhalt tauscht */
.js .browser__caption.is-fading {
  opacity: 0;
}

.browser__slide-title {
  font-weight: 500;
}

.browser__details {
  margin-left: auto;
  padding: 0.35em 1em;
  border: 1px solid currentColor;
  border-radius: 2em;
  font-size: small;
  white-space: nowrap;
  color: inherit;
  text-decoration: none;
  transition: color 0.3s ease, background 0.3s ease, border-color 0.3s ease;
}

/* .browser__caption selbst ist kein Link (siehe collection-browser.php) —
   ein Hover irgendwo in der Zeile darf die Pille trotzdem ankündigen. */
.browser__details:hover,
.browser__details:focus-visible,
.browser__caption:hover .browser__details {
  color: var(--color-white);
  background: var(--browser-accent);
  border-color: var(--browser-accent);
}

/* ====================================== */
/* PFEILE                                  */
/* ====================================== */

/* Ohne JavaScript tun sie nichts, deshalb erscheinen sie erst mit html.js.
   Gewischt werden kann auch ohne sie. */
.browser__nav {
  display: none;
  position: absolute;
  top: 50%;
  z-index: 4;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: #fff;
  background: hsla(0, 0%, 0%, 0.45);
  backdrop-filter: blur(3px);
  cursor: pointer;
  transform: translateY(-50%);
  transition: opacity 0.3s ease, background 0.3s ease;
}

.js .browser__nav {
  display: flex;
}

.browser__nav:hover,
.browser__nav:focus-visible {
  background: hsla(0, 0%, 0%, 0.7);
}

.browser__nav--prev {
  left: 0.75rem;
}

.browser__nav--next {
  right: 0.75rem;
}

.browser__nav svg {
  width: 1.25rem;
  height: 1.25rem;
}

.browser__nav--prev svg {
  transform: scaleX(-1);
}

/* Am Anfang bzw. Ende der Auswahl: sichtbar aus dem Weg, statt zu springen */
.browser__nav[disabled] {
  opacity: 0;
  pointer-events: none;
}

/* ====================================== */
/* SPRUNG-RASTER                           */
/* ====================================== */

.browser__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, var(--browser-thumb));
  /* Zentriert: die letzte Zeile ist selten voll, linksbündig hinge sie
     schief unter dem mittigen Karussell. */
  justify-content: center;
  gap: 0.5rem;
  margin: 2rem 0 0;
  padding: 2rem 0 0;
  list-style: none;
  border-top: 1px solid #ddd;
}

.browser__cell {
  margin: 0;
}

/* Zurückgenommen, damit die aktive Zelle und die, auf der die Maus liegt,
   ohne Umrandung erkennbar sind. */
.browser__thumb {
  position: relative;
  display: block;
  width: var(--browser-thumb);
  opacity: 0.5;
  transition: opacity 0.3s ease;
}

.browser__thumb .media {
  --media-bg: #f0f0f0;
}

.browser__thumb:hover,
.browser__thumb:focus-visible,
.browser__thumb[aria-current="true"] {
  opacity: 1;
}

/* Die Markierung der aktiven Zelle liegt als Pseudoelement über dem Bild,
   nicht als outline oder border: border würde die Kachel kleiner machen als
   alle anderen, und eine outline zeichnet je nach Engine unter die
   Bildfläche — die trägt wegen media.css ein transform und damit einen
   eigenen Stacking-Kontext. Ein positioniertes Geschwister danach liegt
   verlässlich darüber. Nach innen gesetzt, damit der Rasterabstand
   gleichmässig bleibt. */
.browser__thumb[aria-current="true"]::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  border: var(--browser-mark) solid var(--browser-accent);
  pointer-events: none;
}

/* ====================================== */
/* RÜCKWEG AUF DER DETAILSEITE             */
/* ====================================== */

/* Markup dazu: site/snippets/collection-back.php */
.browser-back {
  margin: 1.5rem 0 0;
  text-align: center;
}

.browser-back__link {
  font-size: small;
  display: inline-block;
  padding: 0.25em 1em;
  border: 1px solid currentColor;
  border-radius: 2em;
  color: inherit;
  text-decoration: none;
  transition: color 0.3s ease, background 0.3s ease, border-color 0.3s ease;
}

.browser-back__link:hover,
.browser-back__link:focus-visible {
  color: var(--color-white);
  background: var(--color-hover);
  border-color: var(--color-hover);
}

/* ====================================== */
/* BEWEGUNG SPARSAM                        */
/* ====================================== */

@media (prefers-reduced-motion: reduce) {
  .js .browser__track,
  .js .browser__slide,
  .browser__thumb,
  .browser__details {
    transition-duration: 0s;
  }
}
