/* ════════════════════════════════════════════════════════════════════════
   TEMPERATURE ZERO — Image Archive (/gallery/)            v1.0 · 2026-08-04

   A plate wall: every image the publication has run, cataloged against the
   piece it ran with. Built on the tz-system tokens — no new palette, no new
   type. Three ideas carry the page:

     1. The hero borrows the carousel's own hook-slide grammar (drifting art
        under a bottom-weighted scrim, title anchored in the solid zone), so
        the archive announces itself in the publication's visual voice.
     2. Structure encodes fact: lead art runs double-wide, body art runs
        single. The wall's rhythm IS the shape of each piece's art budget.
     3. Metadata stays out of the way until asked for — bare art on the wall,
        a full wall label in the viewer.

   Loaded only on the gallery page (see inc/tz-gallery.php).
   Versioned filename: Cloudflare strips ?ver=.
   ════════════════════════════════════════════════════════════════════════ */

.tz-gal {
    --gal-gap: 10px;
    --gal-cols: 6;
    --gal-max: 1560px;
    --gal-ink: rgba(226, 226, 232, 0.92);
}

/* The archive is the one page that wants the full width. */
.tz-gal-wrap {
    max-width: var(--gal-max);
    margin: 0 auto;
    padding: 0 24px;
    width: 100%;
}

/* The interior scaffold's top padding would push the hero off the header. */
.tz-interior .site-main .tz-gal { padding-top: 0; }


/* ════════════════════════════════════════════════════════════
   1. HERO — drifting plate strip under a bottom-weighted scrim
   ════════════════════════════════════════════════════════════ */
.tz-gal-hero {
    position: relative;
    min-height: clamp(360px, 52vh, 560px);
    display: flex;
    align-items: flex-end;
    overflow: hidden;
    margin-bottom: 0;
    background: var(--tz-bg);
}

.tz-gal-strip {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--gal-gap);
    z-index: 0;
}

.tz-gal-strip__row {
    display: flex;
    flex: 1 1 0;
    min-height: 0;
    gap: var(--gal-gap);
    width: max-content;
    will-change: transform;
}
.tz-gal-strip__row--a { animation: tz-gal-drift-a 150s linear infinite; }
.tz-gal-strip__row--b { animation: tz-gal-drift-b 190s linear infinite; }

.tz-gal-strip img {
    display: block;
    height: 100%;
    width: auto;
    object-fit: cover;
    border-radius: 2px;
    /* The art is the backdrop here, not the subject — it sits behind type. */
    filter: saturate(0.8) brightness(0.72);
}

/* The track holds the same run of plates twice; -50% lands on the seam. */
@keyframes tz-gal-drift-a {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-50%, 0, 0); }
}
@keyframes tz-gal-drift-b {
    from { transform: translate3d(-50%, 0, 0); }
    to   { transform: translate3d(0, 0, 0); }
}

/* Same ramp as the carousel hook slide: art untouched at the top, solid
   under the title so the type never fights the picture behind it. */
.tz-gal-hero::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(
        180deg,
        rgba(10, 10, 15, 0.22) 0%,
        rgba(10, 10, 15, 0.34) 24%,
        rgba(10, 10, 15, 0.78) 46%,
        rgba(10, 10, 15, 0.94) 62%,
        var(--tz-bg) 78%
    );
}

.tz-gal-hero__inner {
    position: relative;
    z-index: 2;
    /* Vertical only — this element also carries .tz-gal-wrap, whose 24px
       side padding is the thing keeping the title off the viewport edge. */
    padding-top: 3rem;
    padding-bottom: 2.2rem;
}

.tz-gal-hero .tz-page-title {
    font-family: var(--tz-sans);
    font-size: clamp(2.2rem, 5.2vw, 3.4rem);
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.04;
    color: var(--tz-heading);
    margin: 0;
}

.tz-gal-hero .tz-page-lede {
    max-width: 62ch;
    color: var(--gal-ink);
    margin-top: 1rem;
}

/* Readout: the archive's own numbers, in the instrument voice. */
.tz-gal-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0 2.4rem;
    margin: 1.6rem 0 0;
    padding: 0;
    list-style: none;
}
.tz-gal-stats div {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.6rem 0 0;
}
.tz-gal-stats dt {
    font-family: var(--tz-mono);
    font-size: 10px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--tz-muted);
}
.tz-gal-stats dd {
    font-family: var(--tz-sans);
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--tz-heading);
    margin: 0;
}
.tz-gal-stats dd .tz-gal-unit {
    font-family: var(--tz-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.1em;
    color: var(--tz-c-cyan);
    margin-left: 0.35rem;
}


/* ════════════════════════════════════════════════════════════
   2. SHELF BAR — sticky filter row
   ════════════════════════════════════════════════════════════ */
.tz-gal-bar {
    position: sticky;
    top: 0;
    z-index: 30;
    background: rgba(10, 10, 15, 0.82);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--tz-border);
    border-bottom: 1px solid var(--tz-border);
}

.tz-gal-bar__inner {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-top: 0.75rem;
    padding-bottom: 0.75rem;
}

/* Only the chips scroll — the progress readout stays pinned and visible. */
.tz-gal-shelves {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
}
.tz-gal-shelves::-webkit-scrollbar { display: none; }

.tz-gal-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.45rem;
    padding: 0.42rem 0.85rem;
    border: 1px solid var(--tz-border);
    border-radius: 100px;
    font-family: var(--tz-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--tz-muted);
    text-decoration: none;
    white-space: nowrap;
    background: transparent;
    cursor: pointer;
    transition: color var(--tz-duration-md) var(--tz-ease),
                border-color var(--tz-duration-md) var(--tz-ease),
                background var(--tz-duration-md) var(--tz-ease);
}
.tz-gal-chip:hover {
    color: var(--tz-text);
    border-color: rgba(74, 240, 200, 0.35);
    background: rgba(74, 240, 200, 0.04);
}
.tz-gal-chip__n {
    font-size: 10px;
    color: rgba(122, 122, 150, 0.75);
}
.tz-gal-chip[aria-current="true"],
.tz-gal-chip.is-on {
    color: var(--tz-bg);
    background: var(--tz-c-cyan);
    border-color: var(--tz-c-cyan);
    font-weight: 700;
}
.tz-gal-chip[aria-current="true"] .tz-gal-chip__n,
.tz-gal-chip.is-on .tz-gal-chip__n { color: rgba(10, 10, 15, 0.6); }

.tz-gal-count {
    font-family: var(--tz-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    color: var(--tz-muted);
    white-space: nowrap;
    flex: 0 0 auto;
}
.tz-gal-count b { color: var(--tz-text); font-weight: 400; }


/* ════════════════════════════════════════════════════════════
   3. THE WALL
   ════════════════════════════════════════════════════════════ */
.tz-gal-wall {
    display: grid;
    grid-template-columns: repeat(var(--gal-cols), minmax(0, 1fr));
    grid-auto-rows: auto;
    gap: var(--gal-gap);
    padding: var(--gal-gap) 0 0;
}

.tz-plate {
    position: relative;
    display: block;
    overflow: hidden;
    border-radius: var(--tz-radius-sm);
    background: var(--tzr-card-2);
    text-decoration: none;
    aspect-ratio: 16 / 9;
    outline: 1px solid rgba(30, 30, 46, 0.9);
    outline-offset: -1px;
    /* Fade in as the wall scrolls past; JS adds .is-in. */
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 500ms var(--tz-ease), transform 500ms var(--tz-ease),
                outline-color var(--tz-duration-md) var(--tz-ease);
}
.tz-plate.is-in { opacity: 1; transform: none; }
.no-js .tz-plate { opacity: 1; transform: none; }

/* Lead art runs double. That is the one structural claim the wall makes. */
.tz-plate--hero {
    grid-column: span 2;
    grid-row: span 2;
    aspect-ratio: auto;
}

.tz-plate img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: brightness(0.9) saturate(0.95);
    transform: scale(1.001); /* kill the sub-pixel seam on scale-back */
    transition: filter var(--tz-duration-lg) var(--tz-ease),
                transform 700ms var(--tz-ease);
}

.tz-plate:hover img,
.tz-plate:focus-visible img {
    filter: brightness(1.02) saturate(1.02);
    transform: scale(1.035);
}
.tz-plate:hover,
.tz-plate:focus-visible {
    outline-color: rgba(74, 240, 200, 0.55);
}
.tz-plate:focus-visible {
    outline: 2px solid var(--tz-c-cyan);
    outline-offset: 2px;
}

/* Accession number, top-left — a contact-sheet frame mark. */
.tz-plate__no {
    position: absolute;
    top: 8px;
    left: 9px;
    z-index: 2;
    font-family: var(--tz-mono);
    font-size: 9px;
    letter-spacing: 0.14em;
    color: var(--tz-c-cyan);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
    opacity: 0;
    transform: translateY(-3px);
    transition: opacity var(--tz-duration-md) var(--tz-ease),
                transform var(--tz-duration-md) var(--tz-ease);
}

.tz-plate__meta {
    position: absolute;
    inset: auto 0 0 0;
    z-index: 2;
    display: block;
    padding: 2.6rem 0.75rem 0.7rem;
    background: linear-gradient(180deg, rgba(10, 10, 15, 0) 0%, rgba(10, 10, 15, 0.88) 62%, rgba(10, 10, 15, 0.97) 100%);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity var(--tz-duration-md) var(--tz-ease),
                transform var(--tz-duration-md) var(--tz-ease);
}

.tz-plate:hover .tz-plate__no,
.tz-plate:focus-visible .tz-plate__no,
.tz-plate:hover .tz-plate__meta,
.tz-plate:focus-visible .tz-plate__meta {
    opacity: 1;
    transform: none;
}

.tz-plate__kind {
    display: block;
    font-family: var(--tz-mono);
    font-size: 9px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--tz-c-cyan);
    margin-bottom: 0.28rem;
}
.tz-plate__title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-family: var(--tz-sans);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: -0.01em;
    color: var(--tz-heading);
}
.tz-plate--hero .tz-plate__title { font-size: 0.92rem; -webkit-line-clamp: 3; }


/* ════════════════════════════════════════════════════════════
   4. LOAD MORE + ARCHIVE FOOTER
   ════════════════════════════════════════════════════════════ */
.tz-gal-more {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;
    padding: 2.6rem 0 1rem;
}

.tz-gal-more__btn {
    font-family: var(--tz-mono);
    font-size: 11px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--tz-c-cyan);
    background: transparent;
    border: 1px solid rgba(74, 240, 200, 0.35);
    border-radius: 100px;
    padding: 0.75rem 1.7rem;
    cursor: pointer;
    transition: background var(--tz-duration-md) var(--tz-ease),
                border-color var(--tz-duration-md) var(--tz-ease),
                color var(--tz-duration-md) var(--tz-ease);
}
.tz-gal-more__btn:hover {
    background: rgba(74, 240, 200, 0.08);
    border-color: var(--tz-c-cyan);
}
.tz-gal-more__btn:disabled { opacity: 0.45; cursor: default; }
.tz-gal-more__btn:focus-visible { outline: 2px solid var(--tz-c-cyan); outline-offset: 3px; }

.tz-gal-more__status {
    font-family: var(--tz-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    color: var(--tz-muted);
}

.tz-gal-colophon {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.6rem;
    padding: 2rem 0 4rem;
    margin-top: 1.5rem;
    border-top: 1px solid var(--tz-border);
    font-family: var(--tz-mono);
    font-size: 10px;
    letter-spacing: 0.13em;
    color: var(--tz-muted);
}
.tz-gal-colophon a { color: var(--tz-muted); text-decoration: none; border-bottom: 1px solid rgba(74, 240, 200, 0.25); }
.tz-gal-colophon a:hover { color: var(--tz-c-cyan); }

.tz-gal-empty {
    padding: 4rem 0;
    text-align: center;
    color: var(--tz-muted);
    font-family: var(--tz-sans);
}


/* ════════════════════════════════════════════════════════════
   5. THE VIEWER — plate + wall label
   ════════════════════════════════════════════════════════════ */
.tz-viewer[hidden] { display: none; }

.tz-viewer {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(12px, 3vw, 40px);
    background: rgba(6, 6, 10, 0.97);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    animation: tz-viewer-in 220ms var(--tz-ease);
}
@keyframes tz-viewer-in { from { opacity: 0; } to { opacity: 1; } }

.tz-viewer__stage {
    display: flex;
    align-items: stretch;
    gap: clamp(16px, 2.4vw, 34px);
    margin: 0;
    max-width: 1500px;
    width: 100%;
    max-height: 100%;
}

.tz-viewer__frame {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.tz-viewer__img {
    max-width: 100%;
    max-height: min(84vh, 900px);
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--tz-radius-sm);
    box-shadow: 0 30px 90px rgba(0, 0, 0, 0.75);
    background: var(--tzr-card-2);
}
.tz-viewer__img.is-loading { opacity: 0.55; filter: blur(6px); }
.tz-viewer__img { transition: opacity 260ms var(--tz-ease), filter 260ms var(--tz-ease); }

/* The wall label. */
.tz-viewer__label {
    flex: 0 0 clamp(250px, 24vw, 330px);
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 0.2rem 0 0;
    overflow-y: auto;
}

.tz-viewer__no {
    font-family: var(--tz-mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    color: var(--tz-c-cyan);
    padding-bottom: 0.75rem;
    border-bottom: 1px solid rgba(74, 240, 200, 0.3);
}

.tz-viewer__caption {
    font-family: var(--tz-sans);
    font-size: 1.02rem;
    line-height: 1.5;
    color: var(--tz-heading);
    margin: 0;
    letter-spacing: -0.01em;
}
.tz-viewer__caption:empty { display: none; }

.tz-viewer__spec {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.4rem 1rem;
    font-family: var(--tz-mono);
    font-size: 10px;
    letter-spacing: 0.1em;
    color: var(--tz-muted);
    margin: 0;
}
.tz-viewer__spec dt { text-transform: uppercase; color: rgba(122, 122, 150, 0.7); }
.tz-viewer__spec dd { margin: 0; color: var(--tz-text); }

.tz-viewer__ran {
    font-family: var(--tz-mono);
    font-size: 9px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--tz-muted);
    margin: 0.4rem 0 0.2rem;
}

.tz-viewer__link {
    font-family: var(--tz-sans);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--tz-heading);
    text-decoration: none;
    border-bottom: 1px solid rgba(74, 240, 200, 0.35);
    padding-bottom: 0.35rem;
    transition: color var(--tz-duration-md) var(--tz-ease);
    align-self: flex-start;
}
.tz-viewer__link:hover { color: var(--tz-c-cyan); }
.tz-viewer__link::after { content: ' →'; color: var(--tz-c-cyan); }

/* Controls */
.tz-viewer__close,
.tz-viewer__nav {
    position: absolute;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(16, 16, 26, 0.7);
    border: 1px solid var(--tz-border);
    color: var(--tz-text);
    cursor: pointer;
    border-radius: 50%;
    transition: background var(--tz-duration-md) var(--tz-ease),
                border-color var(--tz-duration-md) var(--tz-ease),
                color var(--tz-duration-md) var(--tz-ease);
}
.tz-viewer__close:hover,
.tz-viewer__nav:hover {
    background: rgba(74, 240, 200, 0.12);
    border-color: var(--tz-c-cyan);
    color: var(--tz-c-cyan);
}
.tz-viewer__close:focus-visible,
.tz-viewer__nav:focus-visible { outline: 2px solid var(--tz-c-cyan); outline-offset: 3px; }

.tz-viewer__close {
    top: clamp(10px, 2vw, 22px);
    right: clamp(10px, 2vw, 22px);
    width: 40px; height: 40px;
    font-size: 20px;
    line-height: 1;
}

.tz-viewer__nav {
    top: 50%;
    transform: translateY(-50%);
    width: 46px; height: 46px;
    font-size: 17px;
}
.tz-viewer__nav--prev { left: clamp(8px, 1.6vw, 20px); }
.tz-viewer__nav--next { right: clamp(8px, 1.6vw, 20px); }
.tz-viewer__nav[disabled] { opacity: 0.25; pointer-events: none; }


/* ════════════════════════════════════════════════════════════
   6. RESPONSIVE
   ════════════════════════════════════════════════════════════ */
@media (max-width: 1400px) { .tz-gal { --gal-cols: 5; } }
@media (max-width: 1100px) { .tz-gal { --gal-cols: 4; } }

/* Below this the hero stops being a picture-with-type-on-it: the strip
   becomes a band across the top and the words get their own solid ground.
   Overlaying a six-line lede on drifting art is unreadable on a phone. */
@media (max-width: 860px) {
    .tz-gal { --gal-cols: 3; }
    .tz-gal-hero { display: block; min-height: 0; }
    .tz-gal-strip {
        position: relative;
        inset: auto;
        height: clamp(130px, 22vh, 180px);
        overflow: hidden;
    }
    .tz-gal-strip__row--b { display: none; }
    .tz-gal-hero::after {
        inset: 0 0 auto 0;
        height: clamp(130px, 22vh, 180px);
        background: linear-gradient(
            180deg,
            rgba(10, 10, 15, 0.15) 0%,
            rgba(10, 10, 15, 0.45) 55%,
            rgba(10, 10, 15, 0.9) 85%,
            var(--tz-bg) 100%
        );
    }
    .tz-gal-hero__inner { padding-top: 1.6rem; padding-bottom: 1.8rem; }
}

@media (max-width: 620px) {
    .tz-gal { --gal-cols: 2; --gal-gap: 6px; }
    .tz-gal-wrap { padding: 0 14px; }
    .tz-gal-stats {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.2rem 1.5rem;
    }
    .tz-gal-stats dd { font-size: 1.1rem; }
    .tz-plate__meta { padding: 2rem 0.55rem 0.5rem; }
    .tz-plate__title { font-size: 0.7rem; -webkit-line-clamp: 2; }
}

/* Below the two-column breakpoint the label reads better under the plate. */
@media (max-width: 900px), (max-height: 620px) {
    .tz-viewer__stage { flex-direction: column; align-items: center; overflow-y: auto; }
    .tz-viewer__label { flex: 0 0 auto; width: 100%; max-width: 640px; }
    .tz-viewer__img { max-height: 58vh; }
    .tz-viewer__nav { top: auto; bottom: 14px; transform: none; width: 40px; height: 40px; }
}


/* ════════════════════════════════════════════════════════════
   7. REDUCED MOTION — the strip stops, everything still reads
   ════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
    .tz-gal-strip__row--a,
    .tz-gal-strip__row--b { animation: none; }
    .tz-plate,
    .tz-plate img,
    .tz-plate__no,
    .tz-plate__meta { transition: none; }
    .tz-plate { opacity: 1; transform: none; }
    .tz-plate:hover img,
    .tz-plate:focus-visible img { transform: none; }
    .tz-viewer { animation: none; }
}
