/* NORDIX — Projektgalerie („Elastic Gallery")
   Portierung der 21st.dev-Komponente nach Vanilla-CSS.

   VORLAGE vs. HIER — was anders ist und warum:
   · Die Vorlage ist React + Next/Image + Tailwind + lucide-react. Dieser
     Entwurf ist statisches HTML mit CSS. Der Mechanismus ist derselbe:
     flex-grow 4 für die aktive Karte, 1 für die übrigen, Übergang auf `flex`.
   · Vorlage: `rounded-2xl` (16px) und weiße Rahmen. Hier: 12px wie alle
     Flächen dieser Seite, Rahmen aus `--line`, aktiv aus `--orange`.
   · Vorlage: Kategorie-Pille weiß-transparent. Hier: Markenorange, weil die
     Seite genau eine Signalfarbe kennt.
   · Vorlage: `brightness-50` für inaktive Karten. Das frisst auf dunklem
     Grund das ganze Bild. Hier stattdessen ein Verlauf plus leichte
     Entsättigung — die Karte bleibt lesbar, tritt aber zurück.
   · Vorlage: Titel senkrecht in `font-black`. Hier Barlow Condensed 600,
     dieselbe Schrift wie Headline und Menü.
   · Ergänzt: Tastaturbedienung, `prefers-reduced-motion`, und ein
     Bildbetrachter, den die Vorlage nicht hat.

   Alle Werte hängen an Variablen, damit die Tweaks-Bar daran drehen kann. */

:root{
  --gal-h:clamp(380px,58vh,600px);
  --gal-gap:10px;
  --gal-r:12px;
  --gal-ease:cubic-bezier(.25,1,.5,1);
  --gal-dur:.7s;
}

.galerie{
  margin-top:34px;
  display:flex;
  gap:var(--gal-gap);
  height:var(--gal-h);
}

/* Überschrift der Galerie. Sie muss deutlich machen, dass es sich um eine
   Auswahl handelt — ohne sie liest sich die Zahl darunter wie eine Bilanz. */
.galtitel{margin-top:34px}
.galtitel + .galerie{margin-top:12px}

/* ---------- Karte ---------- */
.galerie .karte{
  position:relative;
  flex:1 1 0;
  min-width:0;
  overflow:hidden;
  border:1px solid var(--line);
  border-radius:var(--gal-r);
  background:var(--panel);
  cursor:pointer;
  padding:0;
  appearance:none;
  text-align:left;
  font:inherit;
  color:inherit;
  transition:flex var(--gal-dur) var(--gal-ease),
             border-color .4s ease;
}
.galerie .karte[aria-expanded="true"]{
  flex:4 1 0;
  border-color:var(--orange);
}
.galerie .karte:focus-visible{outline:2px solid var(--orange);outline-offset:3px}

/* ---------- Bild ---------- */
.galerie .karte img{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  transition:transform 1s var(--gal-ease),filter .6s ease;
  /* Ruhezustand: herangezoomt und zurückgenommen, damit die aktive Karte
     die Aufmerksamkeit bekommt. Nicht abgedunkelt — auf diesem Grund wäre
     das Bild sonst schlicht weg. */
  transform:scale(1.12);
  filter:saturate(.55) contrast(.95) brightness(.72);
}
.galerie .karte:hover img{filter:saturate(.8) contrast(1) brightness(.9)}
.galerie .karte[aria-expanded="true"] img{
  transform:scale(1);
  filter:none;
}

/* Verlauf, damit Schrift auf jedem Bild steht */
.galerie .karte::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,
    color-mix(in srgb,var(--bg) 92%,transparent) 0%,
    color-mix(in srgb,var(--bg) 55%,transparent) 38%,
    transparent 72%);
  opacity:0;transition:opacity .5s ease;
}
.galerie .karte[aria-expanded="true"]::after{opacity:1}

/* ---------- Inhalt der aufgeklappten Karte ---------- */
.galerie .inhalt{
  position:absolute;inset:auto 0 0 0;
  /* ::after wird als letztes Kind gezeichnet und läge damit ÜBER der Schrift —
     der Verlauf hätte genau das zugedeckt, was er lesbar machen soll. */
  z-index:2;
  display:flex;flex-direction:column;align-items:flex-start;gap:10px;
  padding:clamp(16px,2.2vw,28px);
  transition:opacity .5s ease,transform .5s var(--gal-ease);
  opacity:0;transform:translateY(38px);
  pointer-events:none;
}
.galerie .karte[aria-expanded="true"] .inhalt{
  opacity:1;transform:none;transition-delay:.2s;pointer-events:auto;
}

.galerie .kat{
  font-size:var(--fs-micro);
  letter-spacing:var(--tr-micro);
  text-transform:uppercase;
  color:var(--bg);
  background:var(--orange);
  padding:5px 11px;
  border-radius:999px;
  white-space:nowrap;
}

.galerie .titel{
  font-family:var(--font-display);
  font-weight:600;
  font-size:clamp(26px,3.4vw,48px);
  line-height:.94;
  letter-spacing:var(--tr-h1);
  text-transform:uppercase;
  color:var(--ink);
  max-width:12ch;
}

.galerie .mehr{
  margin-top:4px;
  display:inline-flex;align-items:center;gap:8px;
  font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-2);
  transition:color .25s ease;
}
.galerie .karte:hover .mehr,
.galerie .karte:focus-visible .mehr{color:var(--orange)}
.galerie .mehr svg{width:13px;height:13px;transition:transform .3s var(--gal-ease)}
.galerie .karte:hover .mehr svg{transform:translate(2px,-2px)}

/* ---------- Beschriftung der schmalen Karten ---------- */
.galerie .senkrecht{
  position:absolute;left:50%;bottom:22px;transform:translateX(-50%);
  z-index:2;
  text-shadow:0 2px 14px rgba(0,0,0,.8);
  writing-mode:vertical-rl;
  font-family:var(--font-display);
  font-weight:600;
  font-size:clamp(14px,1.25vw,19px);
  letter-spacing:.13em;
  text-transform:uppercase;
  color:var(--ink);
  white-space:nowrap;
  transition:opacity .4s ease,transform .4s ease;
  pointer-events:none;
}
.galerie .karte[aria-expanded="true"] .senkrecht{
  opacity:0;transform:translateX(-50%) scale(.6);
}
.galerie .karte:not([aria-expanded="true"]) .senkrecht{transition-delay:.4s}

/* Nummer oben — Anschluss an die Mikrotypo der übrigen Seite */
.galerie .nr{
  position:absolute;top:14px;left:0;right:0;text-align:center;z-index:2;
  font-size:var(--fs-micro);letter-spacing:var(--tr-micro);
  color:var(--orange);pointer-events:none;
  text-shadow:0 2px 10px rgba(0,0,0,.9);
}

/* ---------- Handy: gestapelt statt nebeneinander ---------- */
@media(max-width:700px){
  .galerie{
    flex-direction:column;
    height:auto;
    max-height:none;
  }
  .galerie .karte{
    flex:0 0 auto;
    height:74px;
    transition:height var(--gal-dur) var(--gal-ease),border-color .4s ease;
  }
  .galerie .karte[aria-expanded="true"]{flex:0 0 auto;height:340px}
  .galerie .senkrecht{
    writing-mode:horizontal-tb;
    left:18px;right:auto;bottom:auto;top:50%;
    transform:translateY(-50%);
    font-size:17px;
  }
  .galerie .karte[aria-expanded="true"] .senkrecht{transform:translateY(-50%) scale(.6)}
  .galerie .nr{top:50%;left:auto;right:16px;transform:translateY(-50%);text-align:right}
  .galerie .titel{font-size:28px}
}

@media(prefers-reduced-motion:reduce){
  .galerie .karte,.galerie .karte img,.galerie .inhalt,
  .galerie .senkrecht,.galerie .karte::after{transition:none}
}

/* ======================================================================
   BILDBETRACHTER — in der Vorlage nicht enthalten
   Björns Vorgabe: „View Project" öffnet die Beispielbilder mit einem
   kurzen Erklärtext, aber ausdrücklich KEINE eigene Unterseite. Also ein
   Overlay auf derselben Seite: schlank, ohne Router, ohne zweite URL.
   ====================================================================== */
.pv{
  position:fixed;inset:0;z-index:120;
  display:flex;align-items:center;justify-content:center;
  padding:clamp(12px,3vw,40px);
  background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:blur(14px);
  opacity:0;visibility:hidden;
  /* `pointer-events` ist hier kein Feinschliff, sondern die eigentliche
     Absicherung. Die Schicht liegt über der ganzen Seite (`inset:0`). Solange
     sie Klicks annimmt, fängt sie jeden davon ab — und zwar unsichtbar.

     Am 17.08.2026 nachgemessen: Nach einmal Öffnen und Schließen blieb
     `visibility` auf `visible` stehen, obwohl `opacity` schon 0 war. Die
     verzögerte Umschaltung (`visibility 0s .35s`) lief nicht zu Ende, weil
     sich beim Zustandswechsel die Übergangsangabe selbst mitändert. Ergebnis
     war eine unsichtbare Scheibe über der Seite, die jeden Klick schluckte.

     `pointer-events` kennt weder Verzögerung noch Übergang und gilt sofort.
     Für Tastatur und Sprachausgabe setzt galerie.js zusätzlich `inert`. Auf
     eine Zeitangabe verlässt sich an dieser Stelle nichts mehr. */
  pointer-events:none;
  transition:opacity .35s ease,visibility 0s .35s;
}
.pv[data-open="true"]{opacity:1;visibility:visible;pointer-events:auto;
  transition:opacity .35s ease,visibility 0s}

.pv .blatt{
  position:relative;
  width:min(1180px,100%);
  max-height:100%;
  overflow:auto;
  overscroll-behavior:contain;
  background:var(--bg-2);
  border:1px solid var(--line-2);
  border-radius:16px;
  padding:clamp(20px,3vw,40px);
  transform:translateY(18px) scale(.985);
  transition:transform .4s var(--gal-ease);
}
.pv[data-open="true"] .blatt{transform:none}

.pv .kopf{display:flex;align-items:flex-start;gap:20px;margin-bottom:6px}
.pv .kopf .idx{font-size:var(--fs-micro);letter-spacing:var(--tr-micro);color:var(--orange);
  padding-top:9px;flex:0 0 auto}
.pv h3{font-size:clamp(24px,3.2vw,42px);line-height:1;letter-spacing:var(--tr-h2)}
.pv .kat2{margin-top:9px;font-size:var(--fs-micro);letter-spacing:var(--tr-micro);
  text-transform:uppercase;color:var(--ink-3)}

.pv .zu{
  margin-left:auto;flex:0 0 auto;
  width:40px;height:40px;border-radius:999px;
  border:1px solid var(--line-2);background:transparent;color:var(--ink-2);
  cursor:pointer;font-size:19px;line-height:1;
  transition:color .22s ease,border-color .22s ease,background-color .22s ease;
}
.pv .zu:hover,.pv .zu:focus-visible{color:var(--orange);border-color:var(--orange);
  background:color-mix(in srgb,var(--orange) 12%,transparent)}

.pv .text{margin-top:18px;max-width:70ch;color:var(--ink-2)}
.pv .text p+p{margin-top:14px}

/* Platzhalter, solange Björns Beschreibungstexte fehlen */
.pv .text .offen{
  display:inline-block;margin-top:4px;
  font-size:var(--fs-micro);letter-spacing:var(--tr-micro);text-transform:uppercase;
  color:var(--ink-3);border:1px dashed var(--line-2);padding:7px 12px;border-radius:6px;
}

.pv .bilder{
  margin-top:26px;
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));
  gap:12px;
}
.pv .bilder img,
.pv .bilder video{
  width:100%;aspect-ratio:4/5;object-fit:cover;
  border:1px solid var(--line);border-radius:10px;
  background:var(--panel);
  display:block;
}
/* Die Videokachel bekommt den Markenrahmen — sonst merkt niemand, dass sich
   dort etwas bewegt, bevor es zu spät ist. */
.pv .bilder video{border-color:var(--orange)}
/* Das erste Bild bekommt mehr Gewicht — es trägt den Fall.
   Jedes Bild steckt in einer `picture`-Hülle, die dem Browser die Wahl
   zwischen WebP und JPEG lässt. Im Layout ist sie durchsichtig
   (`picture{display:contents}` in tokens.css), im DOM ist sie es nicht:
   `:first-child` gehört deshalb an die Hülle, die Rasterangabe an das Bild
   darin. Stünde sie weiter am `img`, wäre plötzlich JEDES Bild ein erstes
   Kind — nämlich das seiner eigenen Hülle. */
.pv .bilder > picture:first-child img{grid-column:span 2;aspect-ratio:16/11}
/* Sein Nachbar in derselben Zeile ist höher als 4/5 — ohne das bliebe unter
   ihm eine Lücke, weil die Zeile sich am breiten Bild ausrichtet. */
.pv .bilder > picture:not(:first-child) img,
.pv .bilder video:not(:first-child){height:100%}
@media(max-width:600px){
  .pv .bilder{grid-template-columns:1fr 1fr}
  .pv .bilder > picture:first-child img{grid-column:span 2}
}

html.pv-offen{overflow:hidden}

@media(prefers-reduced-motion:reduce){
  .pv,.pv .blatt{transition:none}
}
