/* ---------------------------------------------------------------
   Die Traumwandler — Frontend
   Alles Variable steckt in :root (siehe src/theme-css.php)
   --------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    font-family: var(--font);
    color: var(--text);
    background: var(--bg-1);
    overflow-x: hidden;
}

/* Wandernder Verlauf, rein per CSS animiert */
body::before {
    content: "";
    position: fixed;
    inset: -20vmax;
    z-index: -2;
    background:
        radial-gradient(45vmax 45vmax at 15% 20%, var(--bg-2), transparent 60%),
        radial-gradient(50vmax 50vmax at 85% 15%, var(--bg-3), transparent 60%),
        radial-gradient(55vmax 55vmax at 70% 85%, var(--bg-4), transparent 62%),
        radial-gradient(40vmax 40vmax at 25% 90%, var(--bg-2), transparent 60%),
        var(--bg-1);
    animation: drift var(--bg-speed) ease-in-out infinite alternate;
    will-change: transform;
}

/* Feines Korn: nimmt dem Verlauf das Digitale */
body::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: .035;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

@keyframes drift {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    50%  { transform: translate3d(2%, -3%, 0) scale(1.08); }
    100% { transform: translate3d(-3%, 2%, 0) scale(1.04); }
}

@media (prefers-reduced-motion: reduce) {
    body::before { animation: none; }
}

/* ---------- Header ---------- */

.site-header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: clamp(.9rem, 2.2vw, 1.6rem) clamp(1rem, 3vw, 2.4rem);
    padding-top: max(clamp(.9rem, 2.2vw, 1.6rem), env(safe-area-inset-top));
    background: linear-gradient(to bottom, rgba(0,0,0,.42), transparent);
    pointer-events: none;
}

.site-header > * { pointer-events: auto; }

.logo {
    font-size: clamp(.82rem, 1.25vw, 1rem);
    font-weight: 500;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    text-decoration: none;
    color: var(--text);
    mix-blend-mode: difference;
}

.logo img { display: block; height: clamp(22px, 3.4vw, 40px); width: auto; }

.contact {
    font-size: clamp(.72rem, 1vw, .82rem);
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    text-decoration: none;
    color: var(--text);
    padding: .55em 1.2em;
    border: 1px solid currentColor;
    border-radius: 999px;
    transition: background-color .35s ease, color .35s ease;
    backdrop-filter: blur(6px);
}

.contact:hover,
.contact:focus-visible {
    background: var(--accent);
    color: #111;
    border-color: var(--accent);
}

/* ---------- Grid ---------- */

.grid {
    position: relative;
    max-width: var(--max-width);
    margin: 0 auto;
    padding: calc(clamp(3.5rem, 9vw, 6.5rem)) clamp(.6rem, 2.2vw, 2.4rem) clamp(3rem, 8vw, 6rem);
}

/* Die Kachel ist die aeussere Flaeche. Im Passepartout-Modus ist sie sichtbar
   und traegt den Rand; im transparenten Modus ist sie schlicht nicht da. */
.tile {
    position: absolute;
    margin: 0;
    padding: var(--tile-pad, 0px);
    background: var(--tile-bg, transparent);
    border-radius: calc(var(--radius) + var(--tile-pad, 0px) * .6);
    cursor: zoom-in;
    opacity: 0;
    /* Position und Einblend-Versatz setzt das JS per inline transform. */
    transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.3,1);
}

.tile.is-in { opacity: 1; }

/* Der Rahmen beschneidet den Hover-Zoom, damit er im Passepartout-Modus nicht
   in den Rand hineinlaeuft. Er traegt auch die Platzhalterfarbe, die
   verschwindet, sobald das Bild da ist - freigestellte Bilder bekommen erst
   gar keine (siehe gallery.js). */
.tile-frame {
    display: block;
    width: 100%;
    height: 100%;
    overflow: hidden;
    border-radius: var(--radius);
    background-color: var(--tile-color, transparent);
    transition: background-color .5s ease .15s;
}

.tile.is-loaded .tile-frame { background-color: transparent; }

.tile img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .8s cubic-bezier(.2,.7,.3,1), filter .5s ease;
}

@media (hover: hover) {
    .tile:hover img { transform: scale(1.035); }
    .grid:hover .tile:not(:hover) img { filter: brightness(.72) saturate(.85); }
}

/* ---------- Projekt als Cover-Gruppe ---------- */

/* Die ersten Arbeiten eines Projekts als Mosaik in einer Kachel.
   Bei zwei Arbeiten zwei gleiche Spalten, ab drei eine große links und
   zwei kleine rechts. Der Fugenabstand leitet sich vom Rasterabstand ab,
   bleibt aber deutlich enger - innerhalb einer Kachel gehört zusammen,
   was zwischen den Kacheln getrennt wäre. */
.tile-mosaic {
    display: grid;
    gap: max(2px, calc(var(--gutter) * .28));
    background: none;
}

.tile-mosaic.m-2 {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr;
}

.tile-mosaic.m-3 {
    grid-template-columns: 1.85fr 1fr;
    grid-template-rows: 1fr 1fr;
}

.tile-mosaic.m-3 img:first-child { grid-row: 1 / 3; }

.tile-mosaic img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: calc(var(--radius) * .8);
    background-color: var(--tile-color, transparent);
    transition: transform .8s cubic-bezier(.2,.7,.3,1),
                filter .5s ease,
                background-color .5s ease .15s;
}

.tile.is-loaded .tile-mosaic img { background-color: transparent; }

/* Im Mosaik wirkt der Zoom auf jeder Zelle unruhig - hier reicht ein
   sanftes Aufhellen der ganzen Gruppe. */
@media (hover: hover) {
    .tile.is-project:hover .tile-mosaic img { transform: none; filter: brightness(1.06); }
}

/* Die Zahl sitzt bewusst als volle Fläche auf der Kachel, nicht als
   Milchglas: Über hellen wie dunklen Bildern soll sie gleich gut lesbar
   sein. Farbe und Größe kommen aus den Einstellungen. */
.stack-count {
    position: absolute;
    right: calc(var(--tile-pad, 0px) + .7rem);
    bottom: calc(var(--tile-pad, 0px) + .7rem);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--badge-size, 34px);
    height: var(--badge-size, 34px);
    border-radius: 50%;
    background: var(--badge-bg, #e8dcc8);
    color: var(--badge-fg, #14141a);
    font-size: calc(var(--badge-size, 34px) * .42);
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 3px 14px rgba(0,0,0,.35);
    pointer-events: none;
    transition: transform .35s cubic-bezier(.2,.7,.3,1);
}

/* Zweistellig darf der Kreis zur Pille werden. */
.stack-count { min-width: var(--badge-size, 34px); width: auto; padding: 0 .34em; border-radius: 999px; }

@media (hover: hover) {
    .tile.is-project:hover .stack-count { transform: scale(1.1); }
}

/* ---------- Video im Raster ---------- */

.tile-preview {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity .45s ease;
    pointer-events: none;
}

.tile.is-previewing .tile-preview { opacity: 1; }

.tile-frame { position: relative; }

.play-mark {
    position: absolute;
    left: 50%;
    top: 50%;
    width: clamp(44px, 16%, 78px);
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    pointer-events: none;
    opacity: .92;
    transition: opacity .35s ease, transform .35s cubic-bezier(.2,.7,.3,1);
    filter: drop-shadow(0 2px 14px rgba(0,0,0,.45));
}

.play-mark svg { width: 100%; height: 100%; display: block; }
.play-mark circle { fill: rgba(12,12,16,.34); stroke: rgba(255,255,255,.92); stroke-width: 1.6; }
.play-mark path { fill: rgba(255,255,255,.95); }

/* Während der Vorschau tritt das Zeichen zurück, verschwindet aber nicht -
   sonst wäre nicht mehr erkennbar, dass hier ein Video liegt. */
.tile.is-previewing .play-mark { opacity: .4; transform: translate(-50%, -50%) scale(.86); }

@media (hover: hover) {
    .tile.is-video:hover .play-mark { transform: translate(-50%, -50%) scale(1.06); opacity: 1; }
    .tile.is-video.is-previewing:hover .play-mark { transform: translate(-50%, -50%) scale(.9); opacity: .55; }
}

@media (prefers-reduced-motion: reduce) {
    .tile-preview { display: none; }
}

.empty {
    text-align: center;
    opacity: .55;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    font-size: .78rem;
    padding: 25vh 0;
}

/* ---------- Fuß ---------- */

/* Zwei Pflichtlinks, sonst nichts. Erscheint erst, wenn man am Ende der
   Arbeiten angekommen ist - im Kopf hätte er nur Platz weggenommen. */
.site-footer {
    padding: 0 clamp(1rem, 3vw, 2.4rem) clamp(2rem, 5vw, 3.5rem);
    padding-bottom: max(clamp(2rem, 5vw, 3.5rem), env(safe-area-inset-bottom));
    text-align: center;
}

.site-footer nav {
    display: inline-flex;
    align-items: center;
    gap: .8em;
    font-size: .7rem;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    opacity: .5;
    transition: opacity .3s ease;
}

.site-footer:hover nav { opacity: .8; }

.site-footer a {
    color: var(--text);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: .15em;
    transition: border-color .3s ease;
}

.site-footer a:hover,
.site-footer a:focus-visible { border-bottom-color: currentColor; }

/* ---------- Impressum und Datenschutz ---------- */

.legal {
    max-width: 68ch;
    margin: 0 auto;
    padding: clamp(5rem, 12vw, 8rem) clamp(1.2rem, 4vw, 2.4rem) clamp(2rem, 5vw, 3rem);
    color: var(--text);
    font-size: clamp(.92rem, 1.05vw, 1rem);
    line-height: 1.75;
}

.legal h1 {
    font-size: clamp(1.1rem, 2vw, 1.5rem);
    font-weight: 500;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    margin: 0 0 2.5rem;
}

.legal h2 {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    margin: 2.6rem 0 .8rem;
    opacity: .7;
}

.legal h2:first-of-type { margin-top: 0; }

.legal p { margin: 0 0 1.1rem; }

.legal a { color: var(--accent); text-decoration: underline; text-underline-offset: .2em; }
.legal a:hover { text-decoration-thickness: 2px; }

.legal-empty { opacity: .6; font-style: italic; }

.legal-page .site-header { position: absolute; background: none; }

/* ---------- Lightbox ---------- */

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(6, 6, 9, .88);
    backdrop-filter: blur(22px) saturate(120%);
    opacity: 0;
    transition: opacity .3s ease;
}

.lightbox[hidden] { display: none; }
.lightbox.is-open { opacity: 1; }

/* Bühne: Bildfläche oben, Beschreibung darunter. Ohne Beschreibung ist die
   zweite Zeile nicht da und alles sitzt wie vorher genau in der Mitte. */
.lb-stage {
    margin: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(.8rem, 2vw, 1.4rem);
    padding: clamp(1.2rem, 5vw, 4rem);
}

/* min-height: 0 ist hier das Entscheidende - ohne diese Zeile weigert sich der
   Flex-Kasten zu schrumpfen und die Beschreibung schiebt das Bild unten hinaus. */
.lb-media {
    position: relative;   /* Traeger fuer die Einwilligung darueber */
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    will-change: transform;
}

/* ---------- Ziehen und Übergang ----------

   Beim Ziehen laeuft das Bild mit - ohne diese Rueckmeldung fuehlt sich das
   am Schreibtisch nach Fehlgriff an statt nach Blaettern. Losgelassen federt
   es zurueck oder der naechste Inhalt uebernimmt. */
/* Nur greifbar, wo es auch etwas zu holen gibt - bei einem einzelnen Bild
   ohne Serie waere die Hand ein leeres Versprechen. */
.lightbox:not(.is-single) .lb-media,
.lightbox.is-series .lb-media { cursor: grab; }
.lightbox.is-dragging .lb-media { cursor: grabbing; }

/* Waehrend gezogen wird, soll der Browser nicht selbst scrollen oder
   zurueckblaettern wollen. */
.lb-media { touch-action: none; }
.lightbox { overscroll-behavior: contain; }

/* Ohne das hier greift beim Ziehen die eingebaute Bild-Verschiebung des
   Browsers: Auf dem Mac haengt dann das Bild als Datei am Zeiger und vom
   Blaettern bleibt nichts uebrig. Dasselbe gilt fuer das Markieren - ein
   Zug ueber das Bild soll keinen blauen Auswahlrahmen hinterlassen. */
.lightbox img,
.lightbox video {
    -webkit-user-drag: none;
    user-select: none;
    -webkit-user-select: none;
}

.lightbox { user-select: none; -webkit-user-select: none; }

/* Die Beschreibung bleibt Text und muss sich kopieren lassen. */
.lb-caption, .lb-consent { user-select: text; -webkit-user-select: text; }

/* Was mitlaufen soll, laeuft mit; was bedient wird, bleibt anfassbar. */
.lightbox.is-dragging .lb-media { transition: none; }
.lightbox.is-dragging img,
.lightbox.is-dragging video { pointer-events: none; }

.lb-caption, .lb-consent, .lightbox video, .lightbox iframe { cursor: auto; }

/* Zurueckfedern nach einem Zug, der nicht gereicht hat. */
.lightbox:not(.is-dragging) .lb-media {
    transition: transform .3s cubic-bezier(.2,.8,.3,1);
}

/* Der neue Inhalt kommt aus der Richtung herein, in die man gegangen ist.
   Nur die Bewegung liegt hier - das Ein- und Ausblenden macht weiterhin das
   Medium selbst ueber .is-ready, sonst blendet es doppelt. */
.lb-media.enter-l { animation: lb-from-l .34s cubic-bezier(.2,.8,.3,1); }
.lb-media.enter-r { animation: lb-from-r .34s cubic-bezier(.2,.8,.3,1); }
.lb-media.enter-t { animation: lb-from-t .32s cubic-bezier(.2,.8,.3,1); }
.lb-media.enter-b { animation: lb-from-b .32s cubic-bezier(.2,.8,.3,1); }

@keyframes lb-from-l { from { transform: translate3d(-7%, 0, 0); } }
@keyframes lb-from-r { from { transform: translate3d(7%, 0, 0); } }
@keyframes lb-from-t { from { transform: translate3d(0, -5%, 0); } }
@keyframes lb-from-b { from { transform: translate3d(0, 5%, 0); } }

@media (prefers-reduced-motion: reduce) {
    .lb-media { animation: none !important; transition: none; }
}

/* ---------------------------------------------------------------------------
   Einwilligung vor dem Player
   ---------------------------------------------------------------------------
   Liegt ueber dem lokalen Vorschaubild, nicht davor: Man sieht, um welches
   Video es geht, und entscheidet mit dem Bild vor Augen. Das Vorschaubild wird
   dafuer abgedunkelt - nicht verdeckt.
   --------------------------------------------------------------------------- */

.lb-consent {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(1rem, 4vw, 2rem);
    background: rgba(8, 8, 12, .62);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    border-radius: var(--radius);

    /* Nur die Karte faengt Klicks. Die Blaetter-Pfeile und das Kreuz liegen
       teils unter dieser Flaeche - sie muessen erreichbar bleiben, sonst sitzt
       man vor einem Video fest, das man gar nicht sehen wollte. */
    pointer-events: none;
}

.lb-consent[hidden] { display: none; }

.lb-consent-card {
    pointer-events: auto;
    width: min(100%, 42ch);
    text-align: center;
    color: var(--text);
    font-size: clamp(.78rem, .42rem + .5vw, .92rem);
    line-height: 1.6;
}

.lb-consent-head {
    margin: 0 0 .6em;
    font-size: 1.05em;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
}

.lb-consent-text {
    margin: 0 0 1.4em;
    opacity: .78;
    text-align: left;
}

/* Die Lightbox setzt ihre Knoepfe absolut an die Raender - dieser hier gehoert
   mitten in die Karte und muss sich das zurueckholen. */
.lb-consent button.lb-consent-go {
    position: static;
    display: inline-block;
    padding: .8em 1.8em;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    background: var(--accent);
    color: #14141a;
    font: inherit;
    font-size: .95em;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    cursor: pointer;
    transition: opacity .2s ease, transform .2s ease;
}

.lb-consent button.lb-consent-go:hover { opacity: .88; }
.lb-consent button.lb-consent-go:active { transform: translateY(1px); }

.lb-consent-keep {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .55em;
    margin-top: 1.1em;
    opacity: .74;
    font-size: .9em;
    cursor: pointer;
}

.lb-consent-keep input {
    width: 1em;
    height: 1em;
    accent-color: var(--accent);
    cursor: pointer;
}

.lb-consent-more {
    margin: 1.1em 0 0;
    opacity: .6;
    font-size: .86em;
}

.lb-consent-more a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-underline-offset: .18em;
    text-decoration-thickness: 1px;
}

/* Auf dem Handy ist die Hoehe knapp - dort darf der Text mitscrollen, statt
   den Knopf aus dem Bild zu schieben. */
@media (max-height: 560px) {
    .lb-consent { align-items: flex-start; overflow-y: auto; }
    .lb-consent-text { margin-bottom: 1em; }
}

.lb-stage img,
.lb-stage video,
.lb-stage iframe {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--radius);
    box-shadow: 0 30px 90px rgba(0,0,0,.55);
    opacity: 0;
    transform: scale(.985);
    transition: opacity .35s ease, transform .35s ease;
}

.lb-stage img.is-ready,
.lb-stage video.is-ready,
.lb-stage iframe.is-ready { opacity: 1; transform: none; }

.lb-stage video[hidden],
.lb-stage iframe[hidden],
.lb-stage img[hidden] { display: none; }

/* Der eingebettete Player bekommt feste 16:9 und füllt die Bühne so weit
   wie möglich - anders als ein Bild bringt er kein eigenes Seitenverhältnis mit. */
.lb-stage iframe {
    width: 100%;
    max-width: min(100%, calc((100vh - 8rem) * 16 / 9));
    aspect-ratio: 16 / 9;
    height: auto;
    border: 0;
    background: #000;
}

/* Steht eine Beschreibung darunter, bleibt weniger Höhe übrig - der Deckel für
   die Breite muss mitgehen, sonst legt der Player schwarze Balken an die Seiten. */
.lightbox.has-caption .lb-stage iframe {
    max-width: min(100%, calc((100vh - 16rem) * 16 / 9));
}

/* Der Player bekommt Luft, damit die Steuerleiste nicht unter den
   Blätter-Pfeilen klebt. */
.lb-stage video { background: #000; }

/* Gemeinsame Grundlage der Bedienelemente im Lightbox-Rahmen. Bewusst nur
   das, was wirklich für alle gilt - Aussehen und Deckkraft regeln die
   einzelnen Gruppen weiter unten, sonst gewinnt hier die Spezifität gegen
   jeden späteren Zustand (z. B. abgeblendete Pfeile am Serienende). */
.lightbox > button {
    position: absolute;
    z-index: 2;
    color: var(--text);
    font-family: var(--font);
    cursor: pointer;
    line-height: 1;
}

.lb-close {
    top: clamp(.6rem, 2vw, 1.4rem);
    right: clamp(.6rem, 2vw, 1.6rem);
    font-size: 2.4rem;
    background: none;
    border: 0;
    padding: .4em .6em;
    opacity: .55;
    transition: opacity .25s ease, transform .25s ease;
}

.lb-close:hover,
.lb-close:focus-visible { opacity: 1; }

/* ---------- Navigation: zwei Achsen, zwei Formensprachen ----------

   Ein nackter Pfeil auf dem Bild sieht aus wie Dekoration. Damit klar ist,
   dass hier etwas zu drücken ist, bekommen die Pfeile eine eigene Fläche:
   gleiche Machart wie das Zähler-Pill (Blur, feiner Rand), dauerhaft sichtbar,
   aber gedämpft - das Bild bleibt die Hauptsache.

   Die beiden Achsen sehen bewusst verschieden aus:
     waagerecht → Kreis,  einfacher Chevron  ("ein Schritt zur Seite")
     senkrecht  → Pille,  Doppel-Chevron     ("hier liegt ein Stapel")
   Dazu kommt senkrecht die Punkt-Leiter am rechten Rand, die Tiefe und
   Position der Serie zeigt. Erst damit sieht man, dass es dort mehr gibt. */

.lb-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    opacity: 1;
    color: var(--text);
    background: rgba(12,12,16,.42);
    border: 1px solid rgba(255,255,255,.16);
    backdrop-filter: blur(10px) saturate(120%);
    -webkit-backdrop-filter: blur(10px) saturate(120%);
    box-shadow: 0 6px 22px rgba(0,0,0,.32);
    transition:
        background .22s ease,
        border-color .22s ease,
        box-shadow .22s ease,
        opacity .22s ease,
        transform .22s cubic-bezier(.2,.8,.3,1);
}

/* Der Chevron selbst. Als Strich gezeichnet, damit er bei jeder Größe
   gleich sauber sitzt - anders als die Textglyphe vorher. */
.lb-ico {
    width: 100%;
    height: 100%;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .82;
    transition: opacity .22s ease, transform .22s cubic-bezier(.2,.8,.3,1);
}

.lb-nav:hover .lb-ico,
.lb-nav:focus-visible .lb-ico { opacity: 1; }

/* Die unsichtbare Klickfläche ist immer mindestens fingergroß, auch wenn die
   sichtbare Fläche kleiner ist. */
.lb-nav::after {
    content: "";
    position: absolute;
    inset: -8px;
}

.lb-nav:hover,
.lb-nav:focus-visible {
    background: rgba(20,20,26,.72);
    border-color: rgba(255,255,255,.42);
    box-shadow: 0 10px 30px rgba(0,0,0,.45);
}

.lb-nav:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

/* ---------- Erste Achse: waagerecht durch die Arbeiten ---------- */

.lb-nav-x {
    top: 50%;
    width:  clamp(2.75rem, 4.4vw, 3.5rem);
    height: clamp(2.75rem, 4.4vw, 3.5rem);
    border-radius: 50%;
    transform: translateY(-50%);
}

.lb-nav-x .lb-ico { width: 46%; height: 46%; }

.lb-prev { left:  clamp(.4rem, 1.8vw, 1.4rem); }
.lb-next { right: clamp(.4rem, 1.8vw, 1.4rem); }

/* Beim Zeigen wächst die Fläche leicht und der Chevron läuft in seine
   Richtung voraus - die Fläche wird gedrückt, der Pfeil zeigt wohin. */
.lb-nav-x:hover, .lb-nav-x:focus-visible { transform: translateY(-50%) scale(1.08); }
.lb-nav-x:active { transform: translateY(-50%) scale(.96); }

.lb-prev:hover .lb-ico, .lb-prev:focus-visible .lb-ico { transform: translateX(-2px); }
.lb-next:hover .lb-ico, .lb-next:focus-visible .lb-ico { transform: translateX(2px); }

.lightbox.is-single .lb-prev,
.lightbox.is-single .lb-next { display: none; }

/* ---------- Zweite Achse: in die Tiefe eines Projekts ---------- */

/* Hochkant-Pille statt Kreis: schon aus dem Augenwinkel eine andere Gattung.
   Etwas kräftiger als die waagerechten, weil hier bisher am ehesten etwas
   übersehen wurde. */
.lb-nav-y {
    left: 50%;
    display: none;
    width:  clamp(2.5rem, 3.8vw, 3.1rem);
    height: clamp(3.4rem, 5.4vw, 4.4rem);
    border-radius: 999px;
    background: rgba(12,12,16,.5);
    border-color: rgba(255,255,255,.22);
    transform: translateX(-50%);
}

.lb-nav-y .lb-ico { width: 58%; height: 58%; }

/* Der zweite Chevron ist der leisere - zusammen lesen sie sich als Stapel,
   nicht als doppelter Pfeil. */
.lb-ico-trail { opacity: .42; transition: opacity .22s ease, transform .22s ease; }

.lightbox.is-series .lb-nav-y { display: flex; }

.lb-up   { top:    clamp(.4rem, 1.8vw, 1.2rem); }
.lb-down { bottom: clamp(.4rem, 1.8vw, 1.2rem); }

.lb-nav-y:hover, .lb-nav-y:focus-visible { transform: translateX(-50%) scale(1.06); }
.lb-nav-y:active { transform: translateX(-50%) scale(.96); }

.lb-up:hover   .lb-ico, .lb-up:focus-visible   .lb-ico { transform: translateY(-2px); }
.lb-down:hover .lb-ico, .lb-down:focus-visible .lb-ico { transform: translateY(2px); }

/* Beim Zeigen holt der leise Chevron auf - der Stapel "atmet" kurz. */
.lb-nav-y:hover .lb-ico-trail,
.lb-nav-y:focus-visible .lb-ico-trail { opacity: .78; }

/* Am Anfang bzw. Ende der Serie gibt es dort nichts mehr - die Fläche bleibt
   stehen, damit die Achse nicht verschwindet, tritt aber deutlich zurück. */
.lb-nav:disabled {
    opacity: .22;
    cursor: default;
    box-shadow: none;
}

.lb-nav:disabled:hover {
    background: rgba(12,12,16,.5);
    border-color: rgba(255,255,255,.22);
    box-shadow: none;
}

.lb-nav-y:disabled:hover { transform: translateX(-50%); }
.lb-nav-y:disabled:hover .lb-ico { transform: none; }

/* ---------- Punkt-Leiter: wie tief geht die Serie, wo stehe ich ----------

   Am rechten Rand, außerhalb des Blätter-Kreises. Senkrecht angeordnet, damit
   sie ohne Erklärung zur senkrechten Achse gehört. Jedes Segment ist zugleich
   eine Sprungmarke. */
.lb-rail {
    position: absolute;
    z-index: 3;
    right: clamp(.35rem, 1.1vw, .8rem);
    top: 50%;
    transform: translateY(-50%);
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 8px 5px;
    border-radius: 999px;
    background: rgba(12,12,16,.34);
    border: 1px solid rgba(255,255,255,.1);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transition: background .22s ease, border-color .22s ease;
}

.lb-rail[hidden] { display: none; }
.lightbox.is-series .lb-rail:not([hidden]) { display: flex; }

/* Damit sich Leiter und Blätter-Kreis nicht ins Gehege kommen, rückt der
   rechte Pfeil in dem Fall ein Stück nach innen. */
.lightbox.is-series .lb-next { right: clamp(1.5rem, 3.4vw, 2.6rem); }

.lb-rail-dot {
    position: relative;
    width: 4px;
    height: 12px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(255,255,255,.3);
    cursor: pointer;
    transition: background .22s ease, height .22s ease, width .22s ease;
}

/* Auch hier: die Fläche zum Treffen ist größer als das, was man sieht. */
.lb-rail-dot::after {
    content: "";
    position: absolute;
    inset: -5px -9px;
}

.lb-rail-dot:hover { background: rgba(255,255,255,.65); width: 6px; }

.lb-rail-dot:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

.lb-rail-dot.is-active {
    background: var(--text);
    height: 24px;
    width: 5px;
}

/* Zeigt man auf einen der senkrechten Pfeile, hebt sich die Leiter mit an -
   so wird sichtbar, dass Pfeile und Leiter eine Gruppe sind. */
.lightbox:has(.lb-nav-y:hover) .lb-rail,
.lightbox:has(.lb-nav-y:focus-visible) .lb-rail {
    background: rgba(20,20,26,.6);
    border-color: rgba(255,255,255,.3);
}

/* Einmaliger Hinweis beim Öffnen eines Projekts. */
.lightbox.hint-depth .lb-down:not(:disabled) {
    animation: nudge 1.6s ease-in-out 2;
}

@keyframes nudge {
    0%, 100% { transform: translateX(-50%) scale(1); }
    45%      { transform: translateX(-50%) scale(1.06) translateY(6px); }
}

@media (prefers-reduced-motion: reduce) {
    .lightbox.hint-depth .lb-down { animation: none; }
    .lb-nav, .lb-ico, .lb-rail-dot { transition: none; }
}

/* Auf schmalen Schirmen wird es eng - dort rücken die Flächen näher an den
   Rand und die Leiter wird schlanker. */
@media (max-width: 560px) {
    .lb-nav-x { width: 2.6rem; height: 2.6rem; }
    .lb-nav-y { width: 2.4rem; height: 3.2rem; }
    .lb-rail  { gap: 5px; padding: 6px 4px; }
    .lb-rail-dot { height: 9px; }
    .lb-rail-dot.is-active { height: 18px; }
}

/* Zähler - erscheint nur bei einem Projekt. Sitzt links unten, damit er dem
   Abwärtspfeil in der Mitte nicht in die Quere kommt. */
.lb-count {
    position: absolute;
    left: clamp(.8rem, 3vw, 2rem);
    bottom: clamp(.8rem, 2.5vw, 1.8rem);
    z-index: 3;
    margin: 0;
    padding: .4em 1em;
    border-radius: 999px;
    background: rgba(12,12,16,.5);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,.18);
    color: var(--text);
    font-size: .74rem;
    letter-spacing: .12em;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

.lb-count[hidden] { display: none; }

/* ---------- Beschreibung unter dem Bild ---------- */

/* Zurückhaltend: kleiner als der Rest, gedämpft, in Lesebreite mittig unter
   dem Bild. Sie soll etwas hinzufügen, nicht mit dem Bild um Aufmerksamkeit
   ringen - deshalb weder Fläche noch Rahmen. */
.lb-caption {
    flex: 0 0 auto;
    width: 100%;
    max-width: 58ch;
    max-height: 28%;
    overflow-y: auto;
    overscroll-behavior: contain;
    text-align: center;
    color: var(--text);
    opacity: .72;
    font-size: clamp(.78rem, .42rem + .5vw, .92rem);
    line-height: 1.6;
    letter-spacing: .01em;
    -webkit-overflow-scrolling: touch;
}

.lb-caption[hidden] { display: none; }

.lb-caption p { margin: 0; }
.lb-caption p + p { margin-top: .7em; }

.lb-caption a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-underline-offset: .18em;
    text-decoration-thickness: 1px;
}

.lb-caption a:hover { text-decoration-thickness: 2px; }

/* Auf dem Handy ist der Platz knapp - dort darf sie weniger Höhe nehmen und
   liegt dichter am Bild. */
@media (max-width: 560px) {
    .lb-caption { max-height: 24%; text-align: left; }
}

/* Bei einem Projekt sitzt unten der Abwärtspfeil und links der Zähler. Die
   Beschreibung braucht dort etwas Abstand, damit sie nicht darunter gerät. */
.lightbox.is-series.has-caption .lb-caption { padding: 0 clamp(2.4rem, 8vw, 5rem); }

/* Bei einem Projekt sitzen oben und unten Pfeile - die Bühne rückt zusammen,
   damit sie nicht über dem Bild liegen. */
.lightbox.is-series .lb-stage {
    padding-top: clamp(3.2rem, 7vw, 4.6rem);
    padding-bottom: clamp(3.2rem, 7vw, 4.6rem);
}

/* Steht eine Beschreibung darunter, rückt der Fuß der Bühne noch ein Stück
   höher - sonst käme der Text dem Abwärtspfeil bzw. dem Zähler zu nah. */
.lightbox.has-caption .lb-stage { padding-bottom: clamp(2.4rem, 6vw, 3.6rem); }

.lightbox.is-series.has-caption .lb-stage { padding-bottom: clamp(4.6rem, 9vw, 6rem); }

body.lb-open { overflow: hidden; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
