/* ===================================
   INSTALLATION PAGES
   Shared by work.html, the individual case-study pages,
   and the "On View Now" section on index.html.
   =================================== */

:root {
    /* page-local accents - the forest palette, kept in the site family */
    --wow-emerald: #00FFC8;
    --wow-gold: #FFB627;
    --wow-line: rgba(255, 255, 255, 0.08);
}

/* ===================================
   TOP BAR
   =================================== */

.inst-topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    padding: var(--space-sm) var(--container-padding);
    background: rgba(0, 0, 0, 0.72);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--wow-line);
}

.inst-topbar-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
}

.inst-topbar .back-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--color-text-secondary);
    text-decoration: none;
    font-family: var(--font-mono);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    transition: color 0.3s ease;
}

.inst-topbar .back-link:hover {
    color: var(--wow-emerald);
}

.inst-topbar .back-link svg {
    transition: transform 0.3s ease;
}

.inst-topbar .back-link:hover svg {
    transform: translateX(-4px);
}

.inst-topbar-label {
    font-family: var(--font-mono);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--color-text-secondary);
}

/* ===================================
   HERO
   =================================== */

.inst-hero {
    position: relative;
    min-height: 78vh;
    display: flex;
    align-items: flex-end;
    overflow: hidden;
    border-bottom: 1px solid var(--wow-line);
}

.inst-hero-media {
    position: absolute;
    inset: 0;
}

.inst-hero-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 60%;
}

/* a slow drift so the hero breathes rather than sitting dead;
   turned off further down for anyone who asked for less motion */
.inst-hero-media img {
    animation: heroDrift 28s ease-in-out infinite alternate;
    transform-origin: 55% 60%;
}

@keyframes heroDrift {
    from { transform: scale(1); }
    to   { transform: scale(1.07); }
}

/* darken the lower half so the title always has contrast */
.inst-hero-media::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        180deg,
        rgba(0, 0, 0, 0.55) 0%,
        rgba(0, 0, 0, 0.15) 35%,
        rgba(0, 0, 0, 0.85) 100%
    );
}

.inst-hero-content {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: var(--container-max);
    margin: 0 auto;
    /* Deeper bottom padding than top. The hero is bottom-aligned, so this is
       what lifts the title clear of the fold rather than leaving it sitting on
       the bottom edge of the photograph. */
    padding: var(--space-lg) var(--container-padding) var(--space-xl);
    /* Centred. One line to undo - delete this and the eyebrow and title both
       return to the left. */
    text-align: center;
}

/* ===================================
   STATEMENT - between the hero and the credits
   Set larger than body prose and given room to breathe. It is the first thing
   read after the title, so it carries the piece on its own rather than
   sitting under a heading.
   =================================== */

.inst-lead {
    border-bottom: 1px solid var(--wow-line);
}

.inst-lead-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: var(--space-xl) var(--container-padding);
}

/* The measure is centred under the centred hero title, but the text inside it
   stays left-aligned. Centring the block fixes the axis; centring the words
   themselves would leave both edges ragged and make four lines harder to read. */
.inst-lead p {
    max-width: 62ch;               /* long lines are the main thing that makes prose tiring */
    margin-left: auto;
    margin-right: auto;
    font-size: clamp(17px, 2.1vw, 21px);
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.86);
}

.inst-lead p + p {
    margin-top: var(--space-md);
}

@media (max-width: 768px) {
    .inst-lead-inner {
        padding: var(--space-lg) var(--container-padding);
    }
}

.inst-eyebrow {
    font-family: var(--font-mono);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.24em;
    color: var(--wow-gold);
    margin-bottom: var(--space-sm);
}

.inst-hero h1 {
    font-family: var(--font-display);
    font-size: clamp(52px, 11vw, 140px);
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.02em;
    margin-bottom: var(--space-sm);
}

.inst-hero-line {
    font-size: clamp(17px, 2.4vw, 22px);
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.85);
    max-width: 640px;
}

/* ===================================
   CREDIT STRIP
   =================================== */

.inst-credits {
    border-bottom: 1px solid var(--wow-line);
    background: var(--color-surface);
}

.inst-credits-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: var(--space-md) var(--container-padding);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--space-md);
}

.inst-credit dt {
    font-family: var(--font-mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--color-text-secondary);
    margin-bottom: 6px;
}

.inst-credit dd {
    font-size: 15px;
    line-height: 1.5;
    color: var(--color-text-primary);
}

/* ===================================
   TEAM STRIP - the four people, inside the credits band
   Moved up from its own section at the foot of the page so the reader learns
   who made this without scrolling past the whole piece first.
   =================================== */

.inst-team-strip {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 var(--container-padding) var(--space-md);
}

.inst-team-label {
    /* The rule above it is the divider between the facts and the faces. */
    padding-top: var(--space-md);
    border-top: 1px solid var(--wow-line);
    margin: 0 0 var(--space-sm);
    font-family: var(--font-mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--color-text-secondary);
}

.inst-team-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--space-sm);
}

/* Face beside name, rather than the stacked card used at the foot of the
   page. A credits band has to stay short, and four portraits stacked over
   four names would be taller than the facts they sit under. */
.inst-face {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 8px;
    background: rgba(10, 10, 10, 0.6);
    backdrop-filter: blur(10px);
    text-decoration: none;
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.inst-face:hover,
.inst-face:focus-visible {
    border-color: rgba(0, 255, 200, 0.4);
    transform: translateY(-2px);
    outline: none;
}

.inst-face img {
    width: 52px;
    height: 52px;
    flex-shrink: 0;
    border-radius: 50%;
    object-fit: cover;
    filter: grayscale(1);
    transition: filter 0.35s ease;
}

.inst-face:hover img,
.inst-face:focus-visible img {
    filter: grayscale(0);
}

.inst-face-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;          /* lets the link line below actually truncate */
}

.inst-face-name {
    font-size: 15px;
    font-weight: 700;
    line-height: 1.25;
}

/* Same accent cycle the Previous Work names use, so each team member's
   name takes the next colour in the site palette. */
/* Muted companions to the site accents. Four names in full-strength blue,
   orange, cyan and magenta read as a colour swatch; pulled back toward white
   they still tell the four people apart without competing with the work. */
.inst-team-row .inst-face:nth-child(5n + 1) .inst-face-name { color: #86B8DA; }
.inst-team-row .inst-face:nth-child(5n + 2) .inst-face-name { color: #DFA184; }
.inst-team-row .inst-face:nth-child(5n + 3) .inst-face-name { color: #8AD5C3; }
.inst-team-row .inst-face:nth-child(5n + 4) .inst-face-name { color: #D394B5; }
.inst-team-row .inst-face:nth-child(5n + 5) .inst-face-name { color: #DCC38A; }

.inst-face-link {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.06em;
    color: var(--color-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color 0.3s ease;
}

.inst-face:hover .inst-face-link,
.inst-face:focus-visible .inst-face-link {
    color: var(--wow-emerald);
}

@media (prefers-reduced-motion: reduce) {
    .inst-face { transition: none; }
    .inst-face:hover,
    .inst-face:focus-visible { transform: none; }
}

/* unfilled facts - deliberately loud so they can't ship by accident */
.needs-fill {
    display: inline-block;
    padding: 2px 8px;
    border: 1px dashed var(--wow-gold);
    border-radius: 4px;
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    color: var(--wow-gold);
    background: rgba(255, 182, 39, 0.08);
}

/* ===================================
   BODY SECTIONS
   =================================== */

.inst-body {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: var(--space-xl) var(--container-padding);
}

.inst-section {
    margin-bottom: var(--space-xl);
}

.inst-section:last-child {
    margin-bottom: 0;
}

.inst-section-title {
    font-family: var(--font-mono);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.24em;
    color: var(--wow-emerald);
    padding-bottom: var(--space-xs);
    border-bottom: 1px solid var(--wow-line);
    margin-bottom: var(--space-md);
}

.inst-prose {
    max-width: 720px;
}

.inst-prose p {
    font-size: clamp(16px, 1.9vw, 19px);
    line-height: 1.75;
    color: rgba(255, 255, 255, 0.82);
    margin-bottom: var(--space-md);
}

.inst-prose p:last-child {
    margin-bottom: 0;
}

.inst-prose em {
    color: var(--wow-gold);
    font-style: italic;
}

.inst-pullquote {
    max-width: 820px;
    margin: var(--space-lg) 0;
    padding-left: var(--space-md);
    border-left: 2px solid var(--wow-gold);
}

/* beats .inst-prose p, which would otherwise set the body size */
.inst-prose p.inst-pullquote,
.inst-prose .inst-pullquote p {
    font-size: clamp(20px, 3vw, 28px);
    line-height: 1.4;
    font-weight: 500;
    color: var(--color-text-primary);
}

/* a standalone quote paragraph keeps the block's own breathing room */
.inst-prose p.inst-pullquote {
    margin: var(--space-lg) 0;
}

/* a paragraph inside blockquote.inst-pullquote sits tight to its cite */
.inst-prose .inst-pullquote p {
    margin-bottom: 0;
}

/* for a future attributed quote: blockquote.inst-pullquote > cite */
.inst-attribution {
    display: block;
    margin-top: var(--space-sm);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-style: normal;
    color: var(--color-text-secondary);
}

/* ===================================
   THE VISIT - numbered beats
   =================================== */

.inst-beats {
    max-width: 760px;
    position: relative;
    padding-left: var(--space-md);
    border-left: 1px solid var(--wow-line);
}

.inst-beat {
    position: relative;
    padding-bottom: var(--space-lg);
}

.inst-beat:last-child {
    padding-bottom: 0;
}

/* the dot on the spine */
.inst-beat::before {
    content: '';
    position: absolute;
    left: calc(var(--space-md) * -1 - 4px);
    top: 9px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--wow-emerald);
    box-shadow: 0 0 12px rgba(0, 255, 200, 0.6);
}

.inst-beat h3 {
    font-size: 19px;
    font-weight: 700;
    margin-bottom: 6px;
}

.inst-beat p {
    font-size: 16px;
    line-height: 1.7;
    color: var(--color-text-secondary);
}

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

.inst-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
    gap: var(--space-md);
}

.inst-figure {
    margin: 0;
    border: 1px solid var(--wow-line);
    border-radius: 8px;
    overflow: hidden;
    background: var(--color-surface);
}

.inst-figure.is-wide {
    grid-column: 1 / -1;
}

.inst-figure img {
    display: block;
    width: 100%;
    height: auto;
}

.inst-figure figcaption {
    padding: var(--space-sm) var(--space-md);
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 1.6;
    letter-spacing: 0.04em;
    color: var(--color-text-secondary);
    border-top: 1px solid var(--wow-line);
}

/* ===================================
   STILLS GRID
   Thumbnails that open full size in the lightbox. Its own class rather than
   .room-shot, which is sized for the projector rail and would force these
   into a 66px strip.
   =================================== */

.stills-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--space-sm);
}

.still-shot {
    display: block;
    padding: 0;
    /* A fixed ratio with object-fit below, so frames captured at slightly
       different window heights still line up as a grid. */
    aspect-ratio: 16 / 9;
    border: 1px solid var(--wow-line);
    border-radius: 8px;
    overflow: hidden;
    background: var(--color-surface);
    cursor: pointer;
    line-height: 0;
    transition: border-color 0.3s ease;
}

.still-shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s ease;
}

.still-shot:hover,
.still-shot:focus-visible {
    border-color: rgba(0, 255, 200, 0.45);
    outline: none;
}

.still-shot:hover img,
.still-shot:focus-visible img {
    transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
    .still-shot img { transition: none; }
    .still-shot:hover img,
    .still-shot:focus-visible img { transform: none; }
}

@media (max-width: 600px) {
    .stills-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

/* ===================================
   IN THE ROOM - exhibition photographs
   Shown as a projection: one large stage, and a rail of every shot below it.
   Nine photographs in the height of one, rather than a grid two screens tall.
   =================================== */

.room-note {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    color: var(--color-text-secondary);
    margin: calc(var(--space-md) * -1 + 4px) 0 var(--space-md);
}

/* Where it goes next, under where it is now. A sentence rather than a label,
   so it gets normal line spacing and a readable measure instead of the tight
   mono run-on the line above uses. */
.room-note-touring {
    max-width: 62ch;
    line-height: 1.7;
    letter-spacing: 0.04em;
    margin-top: calc(var(--space-md) * -1 + 2px);
}

/* Özge took the exhibition photographs, so her name sits with them rather
   than only in the team strip. Brighter than the venue line beside it. */
.room-credit {
    color: rgba(255, 255, 255, 0.78);
}

.room-projector {
    max-width: 1000px;
}

.room-stage {
    position: relative;
    display: block;
    width: 100%;
    height: clamp(300px, 52vh, 520px);
    padding: 0;
    border: 1px solid var(--wow-line);
    border-radius: 10px;
    overflow: hidden;
    background: #000;
    cursor: zoom-in;
    transition: border-color 0.3s ease;
}

.room-stage:hover,
.room-stage:focus-visible {
    border-color: var(--sec-accent, var(--wow-emerald));
    outline: none;
}

.room-stage-inner {
    position: absolute;
    inset: 0;
    display: block;
}

/* Two layers cross-fading, each holding one photo. */
.room-stage-layer {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 0.55s ease;
}

.room-stage-layer.is-front {
    opacity: 1;
}

/* A blurred copy of the same photo, filling the frame behind it. The set mixes
   portrait and landscape, so a contained image always leaves bars somewhere;
   this puts the photo's own light in them instead of black.
   Overscanned past the edges so the blur has no soft border of its own. */
.room-stage-blur {
    position: absolute;
    inset: -8%;
    background-size: cover;
    background-position: center;
    filter: blur(34px) saturate(1.35) brightness(0.5);
}

/* contain, not cover: cropping a portrait to a wide frame loses the room. */
.room-stage-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* The piece is a projection, so the stage keeps a permanent scanline. */
.room-stage-inner::after {
    content: '';
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        transparent,
        transparent 2px,
        rgba(0, 255, 200, 0.04) 2px,
        rgba(0, 255, 200, 0.04) 4px
    );
    pointer-events: none;
}

.room-stage-count {
    position: absolute;
    right: var(--space-sm);
    bottom: var(--space-sm);
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.14em;
    color: var(--sec-accent, var(--wow-emerald));
    background: rgba(0, 0, 0, 0.6);
    padding: 4px 10px;
    border-radius: 4px;
}

.room-rail {
    display: flex;
    gap: var(--space-xs);
    margin-top: var(--space-sm);
    overflow-x: auto;
    padding-bottom: var(--space-xs);
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
}

.room-rail::-webkit-scrollbar {
    height: 6px;
}

.room-rail::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
}

/* every photo is a button so it is keyboard reachable without extra work.
   They share the rail width evenly so the whole set fits with no scrollbar,
   and only start scrolling once min-width bites on a narrow screen. */
.room-shot {
    display: block;
    flex: 1 1 0;
    min-width: 84px;
    height: 66px;
    padding: 0;
    border: 1px solid var(--wow-line);
    border-radius: 6px;
    overflow: hidden;
    background: var(--color-surface);
    cursor: pointer;
    line-height: 0;
    scroll-snap-align: start;
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.room-shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* dimmed so the one on the stage is obvious at a glance */
    filter: brightness(0.5) saturate(0.65);
    transition: filter 0.35s ease;
}

.room-shot:hover,
.room-shot:focus-visible {
    border-color: rgba(0, 255, 200, 0.45);
    outline: none;
}

.room-shot:hover img,
.room-shot:focus-visible img {
    filter: brightness(0.9) saturate(1);
}

.room-shot[aria-current="true"] {
    border-color: var(--sec-accent, var(--wow-emerald));
    box-shadow: 0 0 14px -2px var(--sec-accent, var(--wow-emerald));
}

.room-shot[aria-current="true"] img {
    filter: none;
}

/* ===================================
   LIGHTBOX
   =================================== */

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* the author display:flex above beats the UA stylesheet's [hidden] rule,
   so the closed state has to be stated explicitly */
.lightbox[hidden] {
    display: none;
}

.lightbox-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.97);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: zoom-out;
}

.lightbox-stage {
    position: relative;
    margin: 0;
    max-width: min(1500px, 94vw);
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
}

.lightbox-stage img {
    max-width: 100%;
    max-height: 82vh;
    width: auto;
    height: auto;
    border-radius: 6px;
    box-shadow: 0 30px 90px rgba(0, 0, 0, 0.8);
}

.lightbox-counter {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.14em;
    color: var(--color-text-secondary);
}

.lightbox button {
    position: absolute;
    z-index: 1;
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid rgba(255, 255, 255, 0.16);
    color: var(--color-text-primary);
    border-radius: 50%;
    cursor: pointer;
    line-height: 1;
    transition: background 0.25s ease, border-color 0.25s ease;
}

.lightbox button:hover,
.lightbox button:focus-visible {
    background: rgba(0, 255, 200, 0.16);
    border-color: var(--wow-emerald);
    outline: none;
}

.lightbox-close {
    top: var(--space-md);
    right: var(--space-md);
    width: 44px;
    height: 44px;
    font-size: 26px;
}

.lightbox-prev,
.lightbox-next {
    top: 50%;
    transform: translateY(-50%);
    width: 52px;
    height: 52px;
    font-size: 30px;
}

.lightbox-prev { left: var(--space-md); }
.lightbox-next { right: var(--space-md); }

/* ===================================
   SCROLL REVEAL
   Applied by js/lightbox.js, and only when motion is welcome.
   =================================== */

.will-reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity 0.7s ease, transform 0.7s ease;
}

.will-reveal.is-revealed {
    opacity: 1;
    transform: none;
}

/* ===================================
   TEAM
   Cards work with or without a headshot - the img is optional.
   =================================== */

.inst-artists {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-md);
    max-width: 980px;
}

.inst-artist {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding: var(--space-md);
    border: 1px solid var(--wow-line);
    border-radius: 8px;
    background: var(--color-surface);
    text-decoration: none;
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.inst-artist:hover {
    border-color: rgba(0, 255, 200, 0.4);
    transform: translateY(-3px);
}

.inst-artist img {
    width: 84px;
    height: 84px;
    border-radius: 50%;
    object-fit: cover;
    margin-bottom: var(--space-sm);
    filter: grayscale(1);
    transition: filter 0.35s ease;
}

.inst-artist:hover img {
    filter: grayscale(0);
}

.inst-artist-name {
    font-size: 17px;
    font-weight: 700;
    line-height: 1.3;
}

/* Same accent cycle the Previous Work names use, so each team member's
   name takes the next colour in the site palette. */
.inst-artists .inst-artist:nth-child(5n + 1) .inst-artist-name { color: var(--color-accent-structure); }
.inst-artists .inst-artist:nth-child(5n + 2) .inst-artist-name { color: var(--color-accent-friction); }
.inst-artists .inst-artist:nth-child(5n + 3) .inst-artist-name { color: var(--color-accent-flow-cyan); }
.inst-artists .inst-artist:nth-child(5n + 4) .inst-artist-name { color: var(--color-accent-flow-magenta); }
.inst-artists .inst-artist:nth-child(5n + 5) .inst-artist-name { color: var(--wow-gold); }

.inst-artist-link {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.06em;
    color: var(--color-text-secondary);
    transition: color 0.3s ease;
}

.inst-artist:hover .inst-artist-link {
    color: var(--wow-emerald);
}

/* ===================================
   BUILD / SPEC LIST
   =================================== */

.inst-spec {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--space-md);
    max-width: 980px;
}

.inst-spec-item {
    padding: var(--space-md);
    border: 1px solid var(--wow-line);
    border-radius: 8px;
    background: var(--color-surface);
}

.inst-spec-item h3 {
    font-size: 16px;
    font-weight: 700;
    margin-bottom: 8px;
    color: var(--wow-emerald);
}

.inst-spec-item p {
    font-size: 15px;
    line-height: 1.65;
    color: var(--color-text-secondary);
}

.inst-stack {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-top: var(--space-md);
}

.inst-stack .tag {
    display: inline-block;
    padding: 5px 12px;
    border: 1px solid rgba(0, 255, 200, 0.25);
    border-radius: 4px;
    background: rgba(0, 255, 200, 0.06);
    color: var(--wow-emerald);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.06em;
}

/* ===================================
   INDEX GRID (installations.html)
   =================================== */

.inst-intro {
    max-width: 720px;
    margin-bottom: var(--space-xl);
}

.inst-intro p {
    font-size: clamp(16px, 2vw, 19px);
    line-height: 1.75;
    color: var(--color-text-secondary);
}

.inst-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: var(--space-md);
}

.inst-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--wow-line);
    border-radius: 10px;
    overflow: hidden;
    background: var(--color-surface);
    text-decoration: none;
    color: inherit;
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

a.inst-card:hover {
    transform: translateY(-6px);
    border-color: rgba(0, 255, 200, 0.45);
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
}

/* the featured piece spans the row */
.inst-card.is-featured {
    grid-column: 1 / -1;
    flex-direction: row;
}

.inst-card-media {
    position: relative;
    overflow: hidden;
    background: #000;
    aspect-ratio: 16 / 9;
}

.inst-card.is-featured .inst-card-media {
    flex: 1 1 58%;
    aspect-ratio: auto;
    min-height: 340px;
}

.inst-card-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s ease;
}

a.inst-card:hover .inst-card-media img {
    transform: scale(1.05);
}

.inst-card-info {
    padding: var(--space-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.inst-card.is-featured .inst-card-info {
    flex: 1 1 42%;
    justify-content: center;
    padding: var(--space-lg);
}

.inst-card-status {
    font-family: var(--font-mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--wow-gold);
}

.inst-card-status.is-progress {
    color: var(--color-text-secondary);
}

.inst-card h2 {
    font-size: clamp(22px, 3vw, 34px);
    font-weight: 700;
    line-height: 1.15;
}

.inst-card p {
    font-size: 15px;
    line-height: 1.7;
    color: var(--color-text-secondary);
}

.inst-card-cta {
    margin-top: var(--space-xs);
    font-family: var(--font-mono);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--wow-emerald);
}

/* cards with nothing to link to yet */
.inst-card.is-placeholder {
    border-style: dashed;
    opacity: 0.72;
}

.inst-card.is-placeholder .inst-card-media {
    display: flex;
    align-items: center;
    justify-content: center;
    background: radial-gradient(ellipse at center, rgba(0, 255, 200, 0.08) 0%, rgba(0, 0, 0, 0.95) 70%);
}

.inst-card.is-placeholder .inst-card-media span {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--color-text-secondary);
}

/* ===================================
   CONTACT FORM STATUS
   The line under the send button that tells the visitor
   whether the message actually went through.
   =================================== */

.form-status {
    margin-top: var(--space-sm);
    font-size: 15px;
    line-height: 1.6;
    min-height: 1.6em;
}

.form-status[data-state="success"] {
    color: var(--wow-emerald);
}

.form-status[data-state="error"] {
    color: var(--wow-gold);
}

.contact-submit:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* ===================================
   COMING SOON BLOCK (work.html)
   =================================== */

.inst-soon {
    margin-top: var(--space-xl);
    padding-top: var(--space-lg);
    border-top: 1px solid var(--wow-line);
}

.inst-soon-label {
    font-family: var(--font-mono);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.24em;
    color: var(--wow-gold);
    margin-bottom: var(--space-sm);
}

.inst-soon-list {
    font-size: clamp(17px, 2.4vw, 22px);
    line-height: 1.7;
    color: var(--color-text-secondary);
    max-width: 820px;
    margin-bottom: var(--space-lg);
}

.inst-soon-links {
    font-family: var(--font-mono);
    font-size: 13px;
    letter-spacing: 0.06em;
    color: var(--color-text-secondary);
}

.inst-soon-links a {
    color: var(--wow-emerald);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color 0.3s ease;
}

.inst-soon-links a:hover {
    border-bottom-color: var(--wow-emerald);
}

/* ===================================
   HOMEPAGE SECTION
   The featured card reused inside index.html. The shared
   .section-title / .section-subtitle pair is centred and widely
   spaced by default, which reads as a mismatch here.
   =================================== */

.installations-section .section-title,
.previous-section .section-title {
    margin-bottom: var(--space-xs);
}

.installations-section .section-subtitle,
.previous-section .section-subtitle {
    text-align: left;
    margin-top: 0;
    margin-bottom: var(--space-lg);
}

/* names only, no cards - the list carries the section on its own */
.previous-section .inst-soon-list {
    margin-bottom: var(--space-lg);
}

/* Each name takes the next accent in the site palette, cycling every five.
   The dot separator is generated, so names can be reordered or added
   without touching the punctuation. */
.name-list span {
    white-space: nowrap;
}

.name-list span:not(:last-child)::after {
    content: " \00B7 ";
    color: var(--color-text-secondary);
    opacity: 0.5;
    padding: 0 6px;
}

.name-list span:nth-child(5n + 1) { color: var(--color-accent-structure); }
.name-list span:nth-child(5n + 2) { color: var(--color-accent-friction); }
.name-list span:nth-child(5n + 3) { color: var(--color-accent-flow-cyan); }
.name-list span:nth-child(5n + 4) { color: var(--color-accent-flow-magenta); }
.name-list span:nth-child(5n + 5) { color: var(--wow-gold); }

/* ===================================
   FOOTER
   =================================== */

.inst-footer {
    border-top: 1px solid var(--wow-line);
    padding: var(--space-lg) var(--container-padding);
    text-align: center;
}

.inst-footer p {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--color-text-secondary);
    letter-spacing: 0.05em;
}

.inst-footer a {
    color: var(--color-text-secondary);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color 0.3s ease, border-color 0.3s ease;
}

.inst-footer a:hover {
    color: var(--wow-emerald);
    border-bottom-color: var(--wow-emerald);
}

/* ===================================
   RESPONSIVE
   =================================== */

@media (max-width: 900px) {
    .inst-card.is-featured {
        flex-direction: column;
    }

    .inst-card.is-featured .inst-card-media {
        min-height: 0;
        aspect-ratio: 16 / 9;
    }

    .inst-card.is-featured .inst-card-info {
        padding: var(--space-md);
    }
}

@media (max-width: 768px) {
    .inst-hero {
        /* Taller than it was, because the statement now lives in here too and
           62vh left it crushed against the bottom edge on a phone. */
        min-height: 76vh;
    }

    .inst-hero-content {
        padding: var(--space-md) var(--container-padding) var(--space-lg);
    }

    .inst-body {
        padding: var(--space-lg) var(--container-padding);
    }

    .inst-section {
        margin-bottom: var(--space-lg);
    }

    .inst-gallery,
    .inst-grid,
    .inst-spec {
        grid-template-columns: 1fr;
    }

    .room-stage {
        height: clamp(220px, 42vh, 340px);
    }

    .lightbox-prev,
    .lightbox-next {
        width: 42px;
        height: 42px;
        font-size: 24px;
    }

    .lightbox-prev { left: var(--space-xs); }
    .lightbox-next { right: var(--space-xs); }

    .lightbox-close {
        top: var(--space-sm);
        right: var(--space-sm);
    }
}


@media (max-width: 480px) {
    .inst-body,
    .inst-credits-inner {
        padding-left: var(--space-sm);
        padding-right: var(--space-sm);
    }

    .inst-beats {
        padding-left: var(--space-sm);
    }

    .inst-beat::before {
        left: calc(var(--space-sm) * -1 - 4px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .inst-card,
    .inst-card-media img,
    .room-shot,
    .room-shot img,
    .back-link svg {
        transition: none;
    }

    a.inst-card:hover {
        transform: none;
    }

    a.inst-card:hover .inst-card-media img,
    .room-shot:hover img,
    .room-shot:focus-visible img {
        transform: none;
    }

    /* hold the hero still */
    .inst-hero-media img {
        animation: none;
        transform: none;
    }

    /* the reveal is added by JS only when motion is welcome, but if the
       preference changes mid-session make sure nothing stays invisible */
    .will-reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ===================================
   HOMEPAGE THEME
   Puts the index.html visual language on the case-study pages: gradient
   headlines that shift colour section by section, glass cards with an
   animated border, scanlines over the photographs, and the nav dots.
   Comes last in the file so it wins over the plainer styling above.
   =================================== */

/* One accent per section, in the order the homepage journey uses them.
   Everything else in the section reads its colour from here, so changing
   this cycle recolours the title, the hover states and the nav dot together. */
/* Two strengths per section. --sec-accent is the full-saturation colour, which
   is right for a 7px dot or a 1px border. --sec-soft is the same hue pulled
   back toward white, for anything set at headline size: the saturated versions
   are overwhelming when they fill 48px letters. */
.inst-body .inst-section:nth-of-type(4n + 1) { --sec-accent: var(--color-accent-structure);    --sec-soft: #86B8DA; }
.inst-body .inst-section:nth-of-type(4n + 2) { --sec-accent: var(--color-accent-friction);     --sec-soft: #DFA184; }
.inst-body .inst-section:nth-of-type(4n + 3) { --sec-accent: var(--color-accent-flow-cyan);    --sec-soft: #8AD5C3; }
.inst-body .inst-section:nth-of-type(4n + 4) { --sec-accent: var(--color-accent-flow-magenta); --sec-soft: #D394B5; }

/* --- Hero title: gradient fill plus the stacked 3D shadow --- */

.inst-hero h1 {
    position: relative;
    display: inline-block;
    background: linear-gradient(135deg, var(--color-text-primary) 0%, var(--color-accent-structure) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* The shadow has to live on a copy of the text, because the real h1 is
   painted as a clipped gradient and cannot carry a text-shadow. */
.inst-hero h1::before {
    content: attr(data-text);
    position: absolute;
    top: 0;
    left: 0;
    color: transparent;
    -webkit-text-fill-color: transparent;
    text-shadow:
        1px 1px 0 rgba(0, 168, 255, 0.4),
        2px 2px 0 rgba(0, 168, 255, 0.35),
        3px 3px 0 rgba(0, 168, 255, 0.3),
        4px 4px 0 rgba(0, 168, 255, 0.25),
        5px 5px 0 rgba(0, 168, 255, 0.2),
        6px 6px 0 rgba(0, 168, 255, 0.15),
        8px 8px 15px rgba(0, 0, 0, 0.5);
    z-index: -1;
    pointer-events: none;
}

/* ===================================
   TITLE AS FALLEN WORD BLOCKS
   The letters in the piece are extruded pixel-type: a flat coloured face
   covered in square cells, a darker extruded side, and each block settled at
   its own slight angle. This rebuilds that in CSS, one span per letter.
   Overrides the single gradient headline above.
   =================================== */

.inst-hero h1.blocks {
    position: relative;             /* the pixel layer is measured against this */
    display: block;
    background: none;
    -webkit-text-fill-color: currentColor;
    letter-spacing: 0.02em;         /* blocks need air; -0.02em jams them together */
}

/* The old single extrusion is drawn per letter now. */
.inst-hero h1.blocks::before { content: none; }

/* Words stay whole when the line wraps. */
.blk-word { display: inline-block; white-space: nowrap; }

/* The letter itself only holds the space. Both the extruded side and the
   coloured face are drawn as copies on the two pseudo-elements, stacked with
   positive z-index. A negative z-index would be simpler, but the rotation
   below makes each letter its own stacking context, and inside one of those a
   negative child paints ON TOP of the element's background rather than behind
   it - the extrusion would cover the face it is meant to sit under. */
.blk {
    position: relative;
    display: inline-block;
    color: transparent;
    -webkit-text-fill-color: transparent;
    /* Cell size scales with the type, so the grid stays proportional from
       phone to desktop instead of turning into noise at 88px. */
    --cell: 0.14em;
}

.blk::before,
.blk::after {
    content: attr(data-l);
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    color: transparent;
    -webkit-text-fill-color: transparent;
}

/* The extruded side, and the halo. Both live here rather than on the face,
   which is a clipped background and cannot carry a shadow of its own. The two
   blurred shadows are the glow: a tight one hugging the letter, a wide soft
   one for the bloom it throws onto the photograph behind it. */
.blk::before {
    z-index: 0;
    /* Every offset is in em so the depth and the halo scale with the type.
       In px the extrusion looked right at 88px and turned into a thin edge
       once the title grew to 140. Ten steps rather than seven, because at the
       larger size fewer layers leave visible bands down the side. */
    text-shadow:
        0.008em 0.008em 0 var(--side),
        0.016em 0.016em 0 var(--side),
        0.024em 0.024em 0 var(--side),
        0.032em 0.032em 0 var(--side),
        0.040em 0.040em 0 var(--side),
        0.048em 0.048em 0 var(--side),
        0.056em 0.056em 0 var(--side),
        0.064em 0.064em 0 var(--side),
        0.072em 0.072em 0 var(--side),
        0.080em 0.080em 0 var(--side),
        0.09em 0.11em 0.18em rgba(0, 0, 0, 0.55),
        0 0 0.16em var(--glow),
        0 0 0.39em var(--glow);
}

/* the coloured face, with the pixel grid over it */
.blk::after {
    z-index: 1;
    background-color: var(--face);
    background-image:
        repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.30) 0 1px, transparent 1px var(--cell)),
        repeating-linear-gradient(180deg, rgba(0, 0, 0, 0.30) 0 1px, transparent 1px var(--cell)),
        linear-gradient(180deg, rgba(255, 255, 255, 0.32) 0%, rgba(0, 0, 0, 0.22) 100%);
    -webkit-background-clip: text;
    background-clip: text;
}

/* The five colours the words cycle through in the piece, the angle each one
   settles at, and the halo it throws. --glow is a softened copy of --face:
   the face colour at full strength across a 34px blur reads as a smear, not
   a glow. */
.blk.c1 { --face: #FF2E9A; --side: #7A0E48; --glow: rgba(255,  46, 154, 0.55); --tilt: -2.5deg; --ty:  0.012em; }
.blk.c2 { --face: #7BE04A; --side: #2F6A19; --glow: rgba(123, 224,  74, 0.50); --tilt:  1.5deg; --ty: -0.018em; }
.blk.c3 { --face: #00E0D0; --side: #036460; --glow: rgba(  0, 224, 208, 0.55); --tilt: -1deg;   --ty:  0.022em; }
.blk.c4 { --face: #FFB627; --side: #7C520A; --glow: rgba(255, 182,  39, 0.50); --tilt:  2.5deg; --ty: -0.01em;  }
.blk.c5 { --face: #A970FF; --side: #43257F; --glow: rgba(169, 112, 255, 0.55); --tilt: -1.8deg; --ty:  0.016em; }

.blk { transform: rotate(var(--tilt, 0deg)) translateY(var(--ty, 0)); }

@media (max-width: 600px) {
    /* Straighten up when the title wraps - tilted letters on two short lines
       read as a mistake rather than a style. */
    .blk { --tilt: 0deg; --ty: 0; }
}

/* ---- shed bits ----
   Glowing ones and zeros breaking off the letters and falling away. The words
   in the piece are the AI's answer made physical, so what crumbles off them
   is the data they were made of.

   Drawn on one canvas rather than as elements. The DOM version created and
   destroyed a node per bit and measured the letters on every spawn, and those
   forced layouts were the other half of the choppiness. */

.blk-canvas {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
}

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

/* --- Section titles: small mono label becomes a full gradient headline --- */

.inst-section-title {
    font-family: var(--font-display);
    font-size: clamp(30px, 4.4vw, 48px);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    text-transform: none;
    padding-bottom: 0;
    border-bottom: none;
    margin-bottom: var(--space-md);
    /* inline-block so the gradient box is the width of the words. Left as a
       block it stretches across the whole column and the accent end never
       reaches the text. */
    display: inline-block;
    /* White holds most of the word and the colour only arrives in the tail,
       so the headline reads as text with a tint rather than as a coloured object. */
    background: linear-gradient(135deg, var(--color-text-primary) 38%, var(--sec-soft, #8AD5C3) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* The venue line was tucked under a small mono label; the headline that
   replaced it is far taller, so ease off the negative pull. */
.room-note {
    margin-top: calc(var(--space-md) * -1 + 16px);
}

/* --- Credit strip: six glass cards instead of a flat row --- */

.inst-credits {
    background: linear-gradient(180deg, var(--color-surface) 0%, rgba(0, 168, 255, 0.05) 100%);
}

/* Five credits now that Touring has joined them: Team became the row of faces
   below, and My role came out. Fixed counts rather than auto-fit, which lands
   on four and strands the fifth alone on its own row. All five across once
   there is room, three up at tablet width. */
@media (min-width: 760px) and (max-width: 1139px) {
    .inst-credits-inner {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 1140px) {
    .inst-credits-inner {
        grid-template-columns: repeat(5, 1fr);
        gap: var(--space-sm);
    }
}

.inst-credit {
    padding: var(--space-sm);
    background: rgba(10, 10, 10, 0.6);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 8px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.inst-credit:hover {
    border-color: rgba(0, 255, 200, 0.35);
    transform: translateY(-2px);
}

/* --- Team cards get the project-card treatment from the homepage --- */

.inst-artist {
    position: relative;
    padding: var(--space-md);
    border: none;
    border-radius: 12px;
    overflow: visible;
    background: linear-gradient(135deg, rgba(10, 10, 10, 0.95) 0%, rgba(0, 168, 255, 0.05) 100%);
    transition: transform 0.3s ease;
}

.inst-artist::before {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: 14px;
    padding: 2px;
    background: linear-gradient(
        90deg,
        var(--color-accent-flow-cyan),
        var(--color-accent-structure),
        var(--color-accent-flow-magenta),
        var(--color-accent-friction),
        var(--color-accent-flow-cyan)
    );
    background-size: 300% 100%;
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    animation: borderGradient 4s linear infinite paused;
    opacity: 0.3;
    transition: opacity 0.4s ease;
    z-index: -1;
}

.inst-artist:hover {
    transform: translateY(-8px);
    animation: glowPulse 2s ease-in-out infinite;
}

.inst-artist:hover::before {
    animation-play-state: running;
    opacity: 1;
}

/* --- Scanlines over the stills on hover.
       Not on the rail thumbs: at 108px the lines are noise, and the stage
       carries a permanent scanline of its own. --- */

.inst-figure {
    position: relative;
}

.inst-figure::after {
    content: '';
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        transparent,
        transparent 2px,
        rgba(0, 255, 200, 0.05) 2px,
        rgba(0, 255, 200, 0.05) 4px
    );
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.inst-figure:hover::after {
    opacity: 1;
    animation: instScan 0.6s linear infinite;
}

/* --- The three deaths, cut out of one render --- */

.death-triptych {
    grid-column: 1 / -1;
}

.death-panels {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-sm);
    max-width: 620px;
}

.death-panel {
    position: relative;
    margin: 0;
    border: 1px solid var(--wow-line);
    border-radius: 8px;
    overflow: hidden;
    background: #000;
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.death-panel img {
    display: block;
    width: 100%;
    height: auto;
    transition: transform 0.6s ease;
}

.death-panel figcaption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: var(--space-xs) var(--space-sm);
    font-family: var(--font-mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.85) 60%);
}

/* each caption in the colour of the death it names */
.death-panel.is-dissolve figcaption { color: #A8CFE4; }
.death-panel.is-corrupt  figcaption { color: #96CFA2; }
.death-panel.is-burn     figcaption { color: #DFA681; }

.death-panel:hover {
    transform: translateY(-4px);
}

.death-panel.is-dissolve:hover { border-color: rgba(159, 216, 255, 0.5); }
.death-panel.is-corrupt:hover  { border-color: rgba(91, 255, 122, 0.5); }
.death-panel.is-burn:hover     { border-color: rgba(255, 155, 61, 0.5); }

.death-panel:hover img {
    transform: scale(1.05);
}

@media (max-width: 560px) {
    .death-panels {
        gap: var(--space-xs);
    }

    .death-panel figcaption {
        font-size: 9px;
        letter-spacing: 0.1em;
        padding: 6px 8px;
    }
}

/* The pattern repeats every 4px, so shifting the background by exactly one
   period loops with no visible jump. Moving it by transform would pop. */
@keyframes instScan {
    from { background-position-y: 0; }
    to   { background-position-y: 4px; }
}

.inst-figure {
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.inst-figure:hover {
    border-color: rgba(0, 255, 200, 0.4);
}

/* --- Nav dots sit inboard of the sticky topbar --- */

.inst-page .nav-dots {
    right: var(--space-sm);
}

@media (max-width: 900px) {
    .inst-page .nav-dots {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .inst-artist,
    .inst-credit,
    .inst-figure,
    .death-panel,
    .death-panel img,
    .room-stage-img {
        transition: none;
    }

    .inst-artist:hover,
    .inst-credit:hover,
    .inst-figure:hover,
    .death-panel:hover,
    .death-panel:hover img {
        transform: none;
        animation: none;
    }

    .inst-artist:hover::before,
    .inst-figure:hover::after {
        animation: none;
    }
}
