/* Shared styles for the projects index and the project detail pages. */

/* ---- LAYOUT ---- */
.band {
    padding: 0 var(--side);
    border-bottom: 1px solid var(--fg);
}

.band--dark {
    background: var(--fg);
    color: var(--bg);
    border-bottom-color: var(--fg);
}

.band--plain {
    border-bottom: none;
}

.wrap {
    max-width: var(--maxw);
    margin: 0 auto;
    width: 100%;
}

/* ---- SHARED TYPE ---- */
.eyebrow {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    font-family: var(--mono);
    font-size: 0.65rem;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--muted);
}

.eyebrow span.dash {
    width: 36px;
    height: 1px;
    background: var(--hairline);
}

.display {
    font-family: var(--mono);
    font-weight: 700;
    font-size: clamp(1.7rem, 4.2vw, 2.9rem);
    line-height: 1.1;
    letter-spacing: -0.02em;
    text-wrap: balance;
}

.display .second {
    color: var(--muted);
}

.section-title {
    font-family: var(--mono);
    font-weight: 700;
    font-size: clamp(1.1rem, 2.4vw, 1.6rem);
    letter-spacing: 0.05em;
    line-height: 1.2;
}

.lede {
    font-size: clamp(0.95rem, 1.6vw, 1.05rem);
    line-height: 1.75;
    color: var(--dim);
    max-width: 46ch;
    text-wrap: pretty;
}

.note {
    font-family: var(--mono);
    font-size: 0.65rem;
    line-height: 1.9;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    max-width: 42ch;
}

.section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
}

/* ---- ENQUIRE BUTTON ---- */
.enquire {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.25rem;
    background: var(--fg);
    color: var(--bg);
    padding: 1.25rem 1.5rem;
    border: none;
    font-family: var(--mono);
    font-size: 0.7rem;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.3s var(--ease);
}

.enquire:not(:disabled):hover {
    background: var(--dim);
}

.enquire:disabled {
    background: var(--hairline);
    color: var(--muted);
    cursor: not-allowed;
}

.enquire .arrow {
    transition: transform 0.4s var(--ease);
}

.enquire:not(:disabled):hover .arrow {
    transform: translate(3px, -3px);
}

.terms {
    font-family: var(--mono);
    font-size: 0.65rem;
    line-height: 1.8;
    letter-spacing: 0.08em;
    color: var(--muted);
}

/* ---- PAGE INTRO ---- */
.page-intro {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.75rem;
    padding: 4rem 0 3.5rem;
}

/* ---- FILMSTRIP ----
   A horizontally scrolling strip of frames, bleeding past the right gutter so
   the cut card is its own scroll affordance. Same component on desktop and
   phone, different card size. Progress and range are read off the live scroll
   position, so they cannot claim a position the strip cannot reach. */
.strip-band {
    padding: 0;
    border-bottom: 1px solid var(--fg);
}

.strip-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1.25rem;
    padding: 2.5rem var(--gutter-x) 1.25rem;
}

.strip-nav {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.ghost-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    border: 1px solid var(--fg);
    padding: 0.8rem 1.125rem;
    font-family: var(--mono);
    font-size: 0.65rem;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--fg);
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.3s var(--ease), color 0.3s var(--ease);
}

.ghost-btn:hover {
    background: var(--fg);
    color: var(--bg);
}

.ghost-btn .arrow {
    transition: transform 0.4s var(--ease);
}

.ghost-btn:hover .arrow {
    transform: translateY(3px);
}

.strip-nav button {
    width: 40px;
    height: 40px;
    display: grid;
    place-items: center;
    background: none;
    border: 1px solid var(--fg);
    color: var(--fg);
    font-family: var(--mono);
    font-size: 0.8rem;
    cursor: pointer;
    transition: background 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s;
}

.strip-nav button:hover:not(:disabled) {
    background: var(--fg);
    color: var(--bg);
}

.strip-nav button:disabled {
    border-color: var(--hairline);
    color: var(--muted);
    cursor: default;
}

/* Only the count in the head on a phone; only the range under the bar on
   desktop. Both are written by the same code. */
.strip-count {
    display: none;
}

/* Left edge lines up with the page content; the right edge overhangs it by one
   gutter and no more. Running to the window edge instead would mean the overhang
   grows with the centering margin, so on a wide screen the strip escaped the
   content column by 300px or more. */
.strip-viewport {
    margin-left: var(--gutter-x);
    max-width: calc(var(--maxw) + var(--side));
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}

.strip-viewport::-webkit-scrollbar {
    display: none;
}

.strip {
    display: flex;
    gap: 1px;
    width: max-content;
    background: var(--fg);
    border: 1px solid var(--fg);
    border-right: 0;
    list-style: none;
}

.film {
    flex: none;
    width: 288px;
    scroll-snap-align: start;
    background: var(--bg);
    display: flex;
}

.film > * {
    display: flex;
    flex-direction: column;
    width: 100%;
    text-decoration: none;
    color: var(--fg);
}

.film-shot {
    aspect-ratio: 1 / 1;
    background: #E4E4E4;
    overflow: hidden;
}

.film-shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 1s var(--ease);
}

a.film-link:hover .film-shot img {
    transform: scale(1.03);
}

.film-label {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    padding: 1rem 1.125rem 1.25rem;
    border-top: 1px solid var(--fg);
}

.film-name {
    font-size: 1rem;
    line-height: 1.3;
}

/* Pinned to the bottom of the label, so a name that wraps to two lines does not
   push its own meta line out of step with the cards either side of it. */
.film-meta {
    margin-top: auto;
    font-family: var(--mono);
    font-size: 0.65rem;
    letter-spacing: 0.08em;
    color: var(--muted);
}

.strip-progress {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem var(--gutter-x) 2.75rem;
}

.strip-track {
    flex: none;
    width: 280px;
    height: 2px;
    background: var(--hairline);
}

.strip-fill {
    display: block;
    height: 100%;
    width: 100%;
    background: var(--fg);
}

.strip-range {
    font-family: var(--mono);
    font-size: 0.65rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* Snapping must not animate for anyone who asked for less motion. */
@media (prefers-reduced-motion: reduce) {
    .strip-viewport {
        scroll-behavior: auto;
    }
}

/* ---- HERO ---- */
.hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: 3.5rem;
    padding: 4rem 0 0;
}

.hero-copy {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 3rem;
    padding-bottom: 4rem;
}

.hero-copy .stack {
    display: flex;
    flex-direction: column;
    gap: 1.75rem;
}

.hero-cta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
}

.hero-figure {
    position: relative;
    background: #E4E4E4;
    border-left: 1px solid var(--fg);
    border-right: 1px solid var(--fg);
    margin-right: -1px;
    /* Fixed frame ratio, so the crop stays consistent whatever the source
       photo happens to be. Do not add max-height here: with aspect-ratio it
       caps the width too and the figure stops reaching the grid edge. */
    aspect-ratio: 3 / 4;
    overflow: hidden;
}

.hero-figure img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* ---- SPEC STRIP ---- */
.specs {
    display: grid;
    /* Explicit four, not auto-fit, which dropped a column on a tablet and left
       a dead orphan cell showing the grid colour. */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    background: var(--hairline);
    border-top: 1px solid var(--hairline);
    border-left: 1px solid var(--hairline);
    border-right: 1px solid var(--hairline);
}

.spec {
    background: var(--bg);
    padding: 1.6rem 1.5rem 1.9rem;
}

.spec dt {
    font-family: var(--mono);
    font-size: 0.6rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 0.625rem;
}

.spec dd {
    font-size: 0.95rem;
    line-height: 1.45;
}

/* Each value is two facts. Stacked here, run inline on a phone. */
.spec dd span {
    display: block;
}

/* Below this the four across strip has too little width per cell, so the same
   content becomes hairline label/value rows: a third of the height on a phone,
   and no orphan cell at any width in between. */
@media (max-width: 1100px) {
    .specs {
        display: block;
        background: none;
        border-top: none;
        border-left: none;
        border-right: none;
    }

    .spec {
        display: grid;
        grid-template-columns: 6rem minmax(0, 1fr);
        gap: 0 1.25rem;
        align-items: baseline;
        padding: 0.85rem 0;
        border-top: 1px solid var(--hairline);
    }

    .spec:last-child {
        border-bottom: 1px solid var(--hairline);
    }

    .spec dt {
        margin-bottom: 0;
        line-height: 1.6;
    }

    /* The two facts run on one line, wrapping only when they have to. */
    .spec dd {
        display: flex;
        flex-wrap: wrap;
        font-size: 0.9rem;
    }

    .spec dd span {
        display: inline;
    }

    /* Trailing rather than leading, so a value that wraps reads as continuing
       instead of turning the second line into a bullet point. */
    .spec dd span:not(:last-child)::after {
        content: '\00B7';
        margin: 0 0.4rem;
        color: var(--muted);
    }
}

/* ---- PROCESS GALLERY ---- */
.process {
    padding: 5rem 0 5.5rem;
    display: flex;
    flex-direction: column;
    gap: 2.75rem;
}

.process-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1px;
    background: var(--fg);
    border: 1px solid var(--fg);
}

.process-grid figure {
    background: #E4E4E4;
    display: flex;
    flex-direction: column;
}

/* The cell itself always stays opaque, only the photo fades in. Fading the
   whole figure would expose the black grid behind it as a void. The guard
   class is added by scripts/project.js, so with no JS everything is visible. */
.process-grid.reveal-ready .shot > * {
    opacity: 0;
    transform: scale(1.02);
    transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
}

.process-grid.reveal-ready figure.visible .shot > * {
    opacity: 1;
    transform: none;
}

.process-grid .shot {
    position: relative;
    aspect-ratio: 3 / 4;
    overflow: hidden;
}

.process-grid figure.full {
    grid-column: 1 / -1;
}

/* A row of regular figures that does not divide evenly into three leaves an
   unoccupied grid cell, which shows the grid's own black background as a
   dead box. Add one .filler per empty slot instead, same hatch used for an
   unphotographed piece elsewhere on the site. */
.process-grid .filler {
    background-color: var(--bg);
    background-image:
        repeating-linear-gradient(45deg,
            transparent 0 6px,
            var(--hairline) 6px 7px);
}

.process-grid figure.full .shot {
    aspect-ratio: 16 / 9;
}

.process-grid img,
.process-grid video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* flex: 1 so a caption that wraps to two lines grows the whole row, and every
   shorter caption beside it fills down in its own background rather than
   showing the figure's grey through the leftover space. */
.process-grid figcaption {
    flex: 1;
    padding: 0.875rem 1rem;
    background: var(--bg);
    font-family: var(--mono);
    font-size: 0.65rem;
    line-height: 1.6;
    letter-spacing: 0.05em;
    color: var(--dim);
}

/* ---- TIPS ---- */
.tips {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.6fr);
    gap: 3.5rem;
    padding: 5.5rem 0 6rem;
}

.tips-intro {
    display: flex;
    flex-direction: column;
    gap: 1.125rem;
    position: sticky;
    top: 3rem;
    align-self: start;
}

.tips-intro p {
    font-size: 0.95rem;
    line-height: 1.7;
    color: #9C9C9C;
    max-width: 32ch;
    text-wrap: pretty;
}

.tips-list {
    list-style: none;
    display: flex;
    flex-direction: column;
}

.tips-list li {
    display: grid;
    grid-template-columns: 52px minmax(0, 1fr);
    gap: 1.5rem;
    padding: 1.6rem 0;
    border-top: 1px solid var(--dim);
}

.tips-list li:last-child {
    border-bottom: 1px solid var(--dim);
}

.tips-list .num {
    font-family: var(--mono);
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    color: var(--muted);
    padding-top: 0.4rem;
}

.tips-list h3 {
    font-family: var(--mono);
    font-weight: 700;
    font-size: 0.95rem;
    line-height: 1.45;
    letter-spacing: 0.02em;
    margin-bottom: 0.6rem;
}

.tips-list p {
    font-size: 0.95rem;
    line-height: 1.7;
    color: #C4C4C4;
    max-width: 62ch;
    text-wrap: pretty;
}

.tips-list p a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
    transition: color 0.3s;
}

.tips-list p a:hover {
    color: var(--bg);
}

/* ---- PROJECT ROWS ---- */
.rows-section {
    padding: 4.5rem 0 5rem;
    display: flex;
    flex-direction: column;
    gap: 2rem;
}

.rows {
    list-style: none;
}

/* The list is the main way into the work, and the only way in on a phone, so
   every row carries a thumbnail to scan by. */
.row {
    display: grid;
    grid-template-columns: 72px 48px minmax(0, 1.1fr) minmax(0, 1fr) 120px 40px;
    gap: 1.25rem;
    align-items: center;
    padding: 1.125rem 0.75rem;
    border-top: 1px solid var(--fg);
    font-size: 1rem;
    color: var(--fg);
    text-decoration: none;
    transition: background 0.3s var(--ease);
}

.rows li:last-child .row {
    border-bottom: 1px solid var(--fg);
}

.row:hover {
    background: #E4E4E4;
}

.row .name {
    font-size: clamp(1.15rem, 2vw, 1.5rem);
    letter-spacing: -0.01em;
}

.row .idx,
.row .when {
    font-family: var(--mono);
    font-size: 0.65rem;
    letter-spacing: 0.1em;
    color: var(--muted);
}

.row .idx {
    font-size: 0.7rem;
}

.row .material {
    color: var(--muted);
}

.row .arrow {
    text-align: right;
    font-size: 1.1rem;
    transition: transform 0.4s var(--ease);
}

.row:hover .arrow {
    transform: translate(3px, -3px);
}

/* A shrunk-down hero shot. Its own 300px file, not the full size photo scaled
   in the browser, which would be half a megabyte for a 72px square. */
.row-thumb {
    grid-row: 1 / -1;
    width: 100%;
    aspect-ratio: 1 / 1;
    border: 1px solid var(--fg);
    background: #E4E4E4;
    overflow: hidden;
}

.row-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.8s var(--ease);
}

a.row:hover .row-thumb img {
    transform: scale(1.06);
}

/* ---- BACK LINK ---- */
.back {
    display: inline-block;
    font-family: var(--mono);
    font-size: 0.65rem;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--muted);
    text-decoration: none;
    transition: color 0.3s;
}

.back:hover {
    color: var(--fg);
}

/* ---- INTRO ANIMATION ---- */
.rise {
    animation: fadeUp 0.9s var(--ease) both;
}

/* ---- RESPONSIVE ---- */
@media (max-width: 900px) {
    .hero,
    .tips {
        grid-template-columns: 1fr;
        gap: 2.5rem;
    }

    .hero-copy {
        padding-bottom: 0;
    }

    .hero-figure {
        border-left: none;
        border-right: none;
        margin-right: 0;
        margin-bottom: 3rem;
        aspect-ratio: 1 / 1;
    }

    .tips-intro {
        position: static;
    }

    .process-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    /* Compact ledger: small thumb, name and material beside it, date dropped
       since the material line already carries the status. */
    .row {
        grid-template-columns: 44px minmax(0, 1fr) 18px;
        gap: 0.15rem 0.75rem;
        padding: 0.6rem 0;
        border-top-color: var(--hairline);
    }

    .rows li:last-child .row {
        border-bottom-color: var(--hairline);
    }

    .row .idx,
    .row .when {
        display: none;
    }

    .row .name {
        grid-column: 2;
        font-size: 0.97rem;
    }

    .row .material {
        grid-column: 2;
        font-family: var(--mono);
        font-size: 0.6rem;
        letter-spacing: 0.08em;
    }

    /* Two implicit rows now (name, material), and "-1" only reaches the end of
       the explicit grid, so the span is stated. */
    .row-thumb {
        grid-row: 1 / span 2;
    }

    .row .arrow {
        grid-row: 1 / span 2;
        grid-column: 3;
        font-size: 0.9rem;
    }
}

@media (max-width: 600px) {
    .hero {
        padding-top: 2.5rem;
    }

    .process {
        padding: 3rem 0 3.5rem;
    }

    .process-grid {
        grid-template-columns: 1fr;
    }

    .tips {
        padding: 3.5rem 0 4rem;
    }

    .tips-list li {
        grid-template-columns: 36px minmax(0, 1fr);
        gap: 1rem;
    }

    .rows-section {
        padding: 3rem 0 3.5rem;
    }

    .enquire {
        width: 100%;
    }

    /* The intro compresses to eyebrow and title so the strip lands near the
       fold. The lede is the one thing that goes: the manifesto carries the
       philosophy, this page has to show the work. Compressed, not crushed:
       the strip still clears the fold with this much room around the title. */
    .page-intro {
        gap: 0.875rem;
        padding: 1.75rem 0 2rem;
    }

    .page-intro .lede {
        display: none;
    }

    .page-intro .display {
        font-size: 1.5rem;
    }

    .page-intro .terms {
        margin-top: 0.25rem;
    }

    /* ---- FILMSTRIP ON A PHONE ----
       Edge to edge, no gutter, two cards in view, and the arrows give way to
       the count plus "View all" because a thumb can just swipe.

       The progress bar rides above the strip with the count it belongs to,
       rather than below it, where it sat alone in a band of its own between
       the strip's bottom rule and the section's and read as an orphan. Moving
       it leaves those two rules adjacent, so the strip's own border is left to
       divide the section and the band drops its rule. */
    .strip-band {
        display: flex;
        flex-direction: column;
        border-bottom: none;
    }

    .strip-head {
        order: 0;
        padding: 1.125rem var(--side) 0.375rem;
        gap: 0.75rem;
    }

    .strip-progress {
        order: 1;
        padding: 0 var(--side) 0.875rem;
        /* The count's own metrics, so the track below can be measured in ch of
           the very same font and land on exactly its width. */
        font-family: var(--mono);
        font-size: 0.65rem;
        letter-spacing: 0.14em;
    }

    .strip-viewport {
        order: 2;
    }

    .strip-eyebrow,
    .strip-range {
        display: none;
    }

    .strip-count {
        display: block;
        font-family: var(--mono);
        font-size: 0.65rem;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--muted);
        font-variant-numeric: tabular-nums;
    }

    .strip-nav button {
        display: none;
    }

    .strip-viewport {
        margin-left: 0;
        max-width: none;
    }

    .strip {
        border-left: 0;
    }

    .film {
        width: 236px;
    }

    .film-shot {
        aspect-ratio: 6 / 5;
    }

    .film-label {
        gap: 0.25rem;
        padding: 0.7rem 0.875rem 0.875rem;
    }

    .film-name {
        font-size: 0.97rem;
    }

    /* No wider than the count it underlines. "Selected · 01 / 07" is 18
       monospace characters, each followed by its 0.14em of letter spacing, and
       the count keeps that length until the ledger passes 99 pieces. */
    .strip-track {
        flex: none;
        width: calc(18ch + 2.52em);
    }
}
