/*
 * Photography Durant — public design system
 *
 * Thesis: the chrome carries no color. Every chromatic note on the page comes
 * from the photographs themselves. The one exception is --light, the amber of
 * late Oklahoma sun, which appears ONLY where the visitor can act — focus
 * rings, hover, and the booking call. Restraint is the whole idea; it only
 * reads as intentional if the type and spacing are exact.
 */

/* ---------------------------------------------------------------- reset */

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

html,
body { margin: 0; padding: 0; }

img,
svg { display: block; max-width: 100%; }

/* ---------------------------------------------------------------- tokens */

:root {
    /*
     * Sampled from the logo, not invented. The mark is a camera aperture in
     * forest green holding a magnolia in cream line work — so the "dark" here
     * is a green-black rather than a neutral one, and the accent is the
     * magnolia's own champagne rather than an arbitrary brand color.
     */
    --ink: #050b07;
    --forest: #084020;
    --forest-deep: #003818;
    --film: #0b1710;
    --ash: #1c2a20;
    --bone: #bfc4b8;
    --paper: #f8f8f0;
    --light: #dec0a2;
    --petal: #fcead8;

    --display: 'Fraunces', Georgia, 'Times New Roman', serif;
    --body: 'Karla', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

    /* Fluid type scale. Ratio tightens on small screens so the display face
       never bullies a phone. */
    --step-mono: 0.75rem;
    --step-body: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
    --step-lead: clamp(1.125rem, 1.02rem + 0.5vw, 1.375rem);
    --step-h2: clamp(1.75rem, 1.3rem + 2.2vw, 3rem);
    --step-h1: clamp(2.75rem, 1.5rem + 6vw, 7rem);

    --gutter: clamp(1.25rem, 0.9rem + 2vw, 3.5rem);
    --measure: 62ch;
    --rule: 1px solid var(--ash);
}

/* ---------------------------------------------------------------- base */

body {
    background: var(--ink);
    color: var(--bone);
    font-family: var(--body);
    font-size: var(--step-body);
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3 {
    font-family: var(--display);
    color: var(--paper);
    font-weight: 400;
    line-height: 1.02;
    letter-spacing: -0.02em;
    margin: 0;
    /* Fraunces variable axes: slightly soft, slightly wonky. This is what
       keeps it from reading as a generic high-contrast serif. */
    font-variation-settings: 'SOFT' 30, 'WONK' 1;
}

a { color: inherit; }

a:focus-visible,
button:focus-visible {
    outline: 2px solid var(--light);
    outline-offset: 3px;
}

/* Keyboard users get to skip the masthead; it stays out of the visual design
   until it is focused. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 10;
    padding: 0.75rem 1.25rem;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--mono);
    font-size: var(--step-mono);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    text-decoration: none;
}

.skip-link:focus {
    left: 0.5rem;
    top: 0.5rem;
}

/* ---------------------------------------------------------------- utility layer */

/* Real photographic data — session name, date, dimensions. This layer only
   ever holds information the ShootProof API actually returns. It is not
   decoration, so it never carries invented values. */
.meta {
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bone);
    opacity: 0.55;
}

.eyebrow {
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--bone);
    opacity: 0.7;
    margin: 0;
}

.shell {
    width: 100%;
    max-width: 84rem;
    margin-inline: auto;
    padding-inline: var(--gutter);
}

/* ---------------------------------------------------------------- signature: the develop-in */

/*
 * Images do not fade in — they develop. The ramp runs black -> blown
 * contrast -> true, on a nonlinear ease, the way paper comes up in a tray.
 * One idea, used consistently, instead of scattered scroll effects.
 */
/* No scale in the ramp — a transform leaves photographs looking soft while it
   runs. Brightness and contrast alone still read as paper coming up. */
.develop {
    opacity: 0;
    filter: brightness(0) contrast(3);
    transition:
        opacity 200ms linear,
        filter 1000ms cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: filter;
}

.develop.is-developed {
    opacity: 1;
    filter: brightness(1) contrast(1);
}

/* Stagger within a group so a grid comes up like a contact sheet, not a wall. */
.develop:nth-child(2) { transition-delay: 90ms; }
.develop:nth-child(3) { transition-delay: 180ms; }
.develop:nth-child(4) { transition-delay: 270ms; }

@media (prefers-reduced-motion: reduce) {
    .develop,
    .develop.is-developed {
        opacity: 1;
        filter: none;
        transform: none;
        transition: none;
    }
}

/* ---------------------------------------------------------------- frames */

/*
 * Placeholder frames stand in until the ShootProof galleries are wired.
 * They are deliberately honest — a graded field, not a fake photograph.
 */
.frame {
    position: relative;
    overflow: hidden;
    display: block;
}

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

/* The lightbox trigger wrapping a frame's img (or a plate's picture). A block
   so it is exactly the photograph's own box, nothing more. */
.frame-link {
    display: block;
    cursor: zoom-in;
}

.frame-link:focus-visible {
    outline: 1px solid var(--light);
    outline-offset: 2px;
}

/* Empty frames only. A real photograph gets no gradient and no grain laid
   over it — the placeholder treatment exists to look like a waiting frame,
   not to "improve" someone's work. */
/* Sitting next to a real photograph, an empty frame should read as a frame
   still waiting for one — not as a dark green picture. Nearly no colour, just
   enough edge to hold the grid. */
.frame-empty {
    background:
        radial-gradient(120% 90% at 30% 15%, #121a15 0%, #0c120e 55%, #080d0a 100%);
    border: 1px solid #1f2a23;
}

.frame-empty::after {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.1;
    pointer-events: none;
    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='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

.frame-3x2 { aspect-ratio: 3 / 2; }
.frame-2x3 { aspect-ratio: 2 / 3; }

/* ---------------------------------------------------------------- admin bar */

/*
 * Only rendered when signed in. Fixed above everything, including the masthead,
 * which is why the masthead gains an offset when it is present — the masthead
 * is absolutely positioned over the hero and would otherwise sit underneath.
 */
.adminbar {
    position: fixed;
    inset-inline: 0;
    top: 0;
    z-index: 20;
    background: var(--forest-deep);
    border-bottom: 1px solid var(--light);
}

.adminbar-inner {
    max-width: 84rem;
    margin-inline: auto;
    padding: 0.55rem var(--gutter);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1.25rem;
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--paper);
}

.adminbar-links {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.adminbar-links a {
    color: var(--light);
    text-decoration: none;
    transition: color 180ms ease;
}

.adminbar-links a:hover { color: var(--paper); }

@media (max-width: 40rem) {
    .adminbar-inner { justify-content: center; }
    .adminbar-who { width: 100%; text-align: center; }
    .adminbar-links { width: 100%; justify-content: center; }
}

/* ---------------------------------------------------------------- masthead */

.masthead {
    position: absolute;
    inset-inline: 0;
    top: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: clamp(1.25rem, 3vh, 2.5rem) var(--gutter);
    /* No scrim over the photograph — a gradient reads as an edit to the print,
       and the photographer picks banners with quiet sky for the chrome instead.
       The text-shadow on the links is the only concession. */
}

/* The mark is a stacked lockup (aperture over script over DURANT), so it is
   sized by height and left to find its own width. */
/* Clears the fixed admin bar when one is present. */
.masthead-offset { padding-top: calc(clamp(1.25rem, 3vh, 2.5rem) + 2.5rem); }

.masthead-mark {
    display: block;
    line-height: 0;
    flex: 0 0 auto;
}

.masthead-mark img {
    height: clamp(4.5rem, 7vw, 6rem);
    width: auto;
}

.masthead-nav {
    display: flex;
    gap: clamp(1rem, 2.5vw, 2.25rem);
    font-size: 0.875rem;
    letter-spacing: 0.04em;
}

/* The masthead floats over whatever photograph the page leads with, so its
   legibility cannot depend on the image being dark in the top corner. */
.masthead-nav a {
    color: var(--paper);
    text-decoration: none;
    transition: color 180ms ease;
    text-shadow: 0 1px 14px rgba(5, 11, 7, 0.9), 0 1px 3px rgba(5, 11, 7, 0.7);
}

.masthead-nav a:hover { color: var(--light); }

@media (max-width: 40rem) {
    .masthead-nav a.is-secondary { display: none; }
}

/* ---------------------------------------------------------------- hero */

.hero {
    position: relative;
    min-height: 88svh;
    display: grid;
    align-items: end;
    isolation: isolate;
    overflow: hidden;
}

/*
 * There is deliberately no watermark over the hero. The brand's printed pieces
 * ghost the magnolia behind the mark, and that worked while the frame was an
 * empty placeholder — but over an actual photograph the aperture edges read as
 * smudges on the image rather than as a brand mark. The photograph is the
 * hero; it does not need help.
 */

.hero-frame {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: block;
}

.hero-frame img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Each hero frame carries its own crop point via --hero-position, set on the
       element by the template. Every one of them holds the subject away from the
       lower-left, where the headline sits. */
    object-position: var(--hero-position, 60% 42%);
}

/*
 * Two overlays, not one. The vertical gradient keeps the headline legible over
 * a bright sunlit field; the horizontal one weights the left third down so the
 * type has a quiet ground without laying a scrim rectangle over the photograph.
 */
.hero::before,
.hero::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
}

/* Light vertical fade: enough to seat the masthead at the top and hand off to
   the next section at the bottom, without flattening the sky. */
.hero::before {
    background: linear-gradient(
        180deg,
        rgba(5, 11, 7, 0.42) 0%,
        rgba(5, 11, 7, 0.02) 30%,
        rgba(5, 11, 7, 0.45) 76%,
        rgba(5, 11, 7, 0.88) 100%
    );
}

/* Legibility is bought locally, not globally. An ellipse anchored at the
   bottom-left darkens only the ground under the type, so the sunset keeps its
   colour everywhere else. */
.hero::after {
    background: radial-gradient(
        120% 95% at 0% 100%,
        rgba(5, 11, 7, 0.9) 0%,
        rgba(5, 11, 7, 0.55) 38%,
        rgba(5, 11, 7, 0) 72%
    );
}

.hero-body {
    position: relative;
    z-index: 3;
    padding-block: 0 clamp(3rem, 10vh, 7rem);
}

.hero-body .eyebrow,
.hero-title,
.hero-lead {
    text-shadow: 0 2px 22px rgba(5, 11, 7, 0.75), 0 1px 4px rgba(5, 11, 7, 0.5);
}

.hero-body .eyebrow {
    color: var(--paper);
    opacity: 0.9;
}

.hero-lead { color: var(--paper); }

/* The hero deliberately carries no develop-in. Animating a filter and a scale
   over a photograph makes the browser rasterise it mid-transform, and the
   result reads as a soft image — unacceptable on a photographer's own site.
   The frames further down still develop; they are small enough that it costs
   nothing visible. */

.hero-title {
    font-size: var(--step-h1);
    max-width: 18ch;
    margin-block: 0.5rem 1.25rem;
}

.hero-lead {
    font-size: var(--step-lead);
    max-width: 46ch;
    margin: 0;
    color: var(--bone);
}

/* ---------------------------------------------------------------- two doors */

/*
 * The studio runs two practices for two audiences. Blending them into one
 * "Services" page would be a lie about how the business works, so the split
 * is the primary structural device rather than a decorative section.
 */
.doors {
    display: grid;
    grid-template-columns: 1fr;
    border-top: var(--rule);
}

/*
 * Four services in a 2x2 rather than a single row of four. Four columns at this
 * width squeezes the body copy into narrow ribbons; a square grid keeps every
 * card readable and reads as a considered set.
 *
 * Borders are drawn per-cell rather than with `* + *` — in a two-column grid
 * that selector puts a left border on the first item of the second row, which
 * lands against the page edge.
 */
@media (min-width: 46rem) {
    .doors { grid-template-columns: 1fr 1fr; }
    .door:nth-child(odd) { border-right: var(--rule); }

    /*
     * The count is hers, not ours — a hidden category takes its door with it, so
     * the grid can be three or one. An odd last tile takes the whole row rather
     * than leaving a dead half-cell, and drops the divider it would otherwise
     * draw down the middle of nothing.
     */
    .door:last-child:nth-child(odd) {
        grid-column: 1 / -1;
        border-right: 0;
    }
}

.door {
    position: relative;
    display: grid;
    gap: 1.25rem;
    padding: clamp(2rem, 6vw, 4.5rem) var(--gutter);
    text-decoration: none;
    color: inherit;
    border-bottom: var(--rule);
    transition: background-color 320ms ease;
}

.door:hover,
.door:focus-visible { background-color: var(--film); }

.door-title {
    font-size: var(--step-h2);
    max-width: 14ch;
}

.door-copy {
    margin: 0;
    max-width: 38ch;
}

.door-cue {
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bone);
    transition: color 200ms ease, transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.door:hover .door-cue,
.door:focus-visible .door-cue {
    color: var(--light);
    transform: translateX(0.4rem);
}

/* ---------------------------------------------------------------- sections */

.section {
    padding-block: clamp(4rem, 12vh, 9rem);
}

.section-head {
    display: grid;
    gap: 0.9rem;
    margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.section-title {
    font-size: var(--step-h2);
    max-width: 20ch;
}

.prose {
    max-width: var(--measure);
    display: grid;
    gap: 1.1rem;
}

.prose p { margin: 0; }

/* ---------------------------------------------------------------- contact sheet */

/*
 * A fixed 3x2. The controller draws six frames at random from the library, so
 * the grid never has to cope with an arbitrary count — which is the whole
 * reason the earlier flex-and-centre approach existed. Two up on phones.
 */
.sheet {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: clamp(0.75rem, 1.5vw, 1.25rem);
}

@media (min-width: 48rem) {
    .sheet { grid-template-columns: repeat(3, 1fr); }
}

.plate { display: grid; gap: 0.7rem; }

/* ---------------------------------------------------------------- about */

.about {
    display: grid;
    gap: clamp(1.75rem, 4vw, 3.5rem);
    align-items: center;
}

@media (min-width: 60rem) {
    .about {
        /* Photograph slightly narrower than the text: it is a supporting portrait,
           not another showcase frame. */
        grid-template-columns: 5fr 6fr;
    }
}

.about-frame {
    display: block;
    overflow: hidden;
}

.about-frame img {
    display: block;
    width: 100%;
    height: auto;
}

.about-body .section-head {
    margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

/* ---------------------------------------------------------------- call to action */

.call {
    border-top: var(--rule);
    border-bottom: var(--rule);
    padding-block: clamp(3.5rem, 10vh, 7rem);
}

.call-inner {
    display: grid;
    gap: 1.75rem;
    justify-items: start;
}

.button {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.95rem 1.6rem;
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--ink);
    background: var(--light);
    border: 1px solid var(--light);
    transition: background-color 220ms ease, color 220ms ease;
}

.button:hover,
.button:focus-visible {
    background: transparent;
    color: var(--light);
}

/* ---------------------------------------------------------------- inner pages */

/* Inner pages have no hero, so the first section clears the fixed masthead. */
.page-head { padding-top: clamp(7rem, 18vh, 11rem); }

.page-title {
    font-size: var(--step-h1);
    max-width: 16ch;
    margin-block: 0.5rem 1.5rem;
}

.page-actions { margin-top: 2.25rem; }

.section-top-rule { border-top: var(--rule); }

/* ---------------------------------------------------------------- pricing */

.rates {
    margin: 0;
    display: grid;
    gap: 0;
    border-top: var(--rule);
}

.rate {
    display: grid;
    gap: 0.35rem;
    padding-block: clamp(1.1rem, 2.5vw, 1.5rem);
    border-bottom: var(--rule);
}

/* Name and price on one line from tablet up, note beneath spanning both — a
   price list is scanned down the right-hand edge, so the figures stay aligned. */
@media (min-width: 44rem) {
    .rate {
        grid-template-columns: 1fr auto;
        column-gap: 2rem;
        align-items: baseline;
    }

    .rate-note { grid-column: 1 / -1; }
}

.rate-name {
    font-family: var(--display);
    font-variation-settings: 'SOFT' 30, 'WONK' 1;
    font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.6rem);
    color: var(--paper);
    line-height: 1.1;
}

.rate-price {
    margin: 0;
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--light);
    white-space: nowrap;
}

.rate-note {
    margin: 0;
    max-width: 56ch;
    color: var(--bone);
}

.rates-fine {
    margin-top: clamp(1.75rem, 4vw, 2.5rem);
    font-size: 0.9375rem;
}

/* ---------------------------------------------------------------- side quests */

/*
 * Masonry-ish columns rather than a grid. These frames keep their own
 * proportions — a rodeo frame and a square and a tall one all sit together —
 * and columns absorb mixed heights without forcing a common crop.
 */
.quests {
    columns: 1;
    column-gap: clamp(0.75rem, 1.5vw, 1.25rem);
}

@media (min-width: 40rem) {
    .quests { columns: 2; }
}

@media (min-width: 60rem) {
    .quests { columns: 3; }
}

.quest {
    margin: 0 0 clamp(0.75rem, 1.5vw, 1.25rem);
    /* Stops a frame being split across a column boundary. */
    break-inside: avoid;
    display: grid;
    gap: 0.7rem;
}

.quest-frame { display: block; }

.quest-frame img {
    display: block;
    width: 100%;
    height: auto;
}

.section-head .prose { margin-top: 1rem; }

/* The way from the random taste on the home page into the full category.
   Same voice as the door cues: mono, quiet, brightens on approach. */
.quests-more {
    display: inline-block;
    margin-top: clamp(1.5rem, 3vw, 2.5rem);
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bone);
    text-decoration: none;
    transition: color 200ms ease, transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.quests-more:hover,
.quests-more:focus-visible {
    color: var(--light);
    transform: translateX(0.4rem);
}

/* ---------------------------------------------------------------- site map */

.sitemap-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0;
}

.sitemap-item {
    padding-block: clamp(1.25rem, 3vw, 1.75rem);
    border-bottom: var(--rule);
}

.sitemap-link {
    font-family: var(--display);
    font-variation-settings: 'SOFT' 30, 'WONK' 1;
    font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
    color: var(--paper);
    text-decoration: none;
    line-height: 1.1;
    transition: color 180ms ease;
}

.sitemap-link:hover { color: var(--light); }

.sitemap-summary { margin: 0.5rem 0 0.35rem; max-width: 52ch; }

/* ---------------------------------------------------------------- forms */

/* Wider than the prose measure: the two-column fields need enough room that a
   session-type label never wraps and pushes the select taller than its
   neighbour. */
.form-shell { max-width: 58rem; }

.form-grid {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
    .form-grid { grid-template-columns: 1fr 1fr; }
    /* Fields whose answers run long get the full width. Direct children only —
       the class sits on a wrapper the template adds, not on the input. */
    .form-grid > .field-wide { grid-column: 1 / -1; }
}

.form-grid .input,
.form-grid .select,
.form-grid .textarea { display: grid; gap: 0.5rem; }

.form-grid label {
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--bone);
}

.form-grid input,
.form-grid select,
.form-grid textarea {
    width: 100%;
    padding: 0.85rem 1rem;
    font-family: var(--body);
    font-size: 1rem;
    color: var(--paper);
    background: var(--film);
    border: 1px solid var(--ash);
    border-radius: 0;
    transition: border-color 180ms ease;
    -webkit-appearance: none;
    appearance: none;
}

.form-grid textarea { resize: vertical; min-height: 9rem; }

.form-grid input::placeholder,
.form-grid textarea::placeholder { color: var(--bone); opacity: 0.45; }

.form-grid input:focus,
.form-grid select:focus,
.form-grid textarea:focus {
    outline: none;
    border-color: var(--light);
}

.form-grid input:focus-visible,
.form-grid select:focus-visible,
.form-grid textarea:focus-visible {
    outline: 2px solid var(--light);
    outline-offset: 2px;
}

.form-grid .error-message {
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.06em;
    color: var(--light);
}

.form-grid .error input,
.form-grid .error select,
.form-grid .error textarea { border-color: var(--light); }

/*
 * Choices.js theme. choices.css is loaded after site.css, so every rule here is
 * scoped under .form-grid to out-rank it rather than relying on source order.
 */
.form-grid .choices { margin-bottom: 0; }

.form-grid .choices__inner {
    min-height: 0;
    padding: 0.85rem 1rem;
    font-family: var(--body);
    font-size: 1rem;
    color: var(--paper);
    background: var(--film);
    border: 1px solid var(--ash);
    border-radius: 0;
}

.form-grid .choices.is-open .choices__inner,
.form-grid .choices.is-focused .choices__inner {
    border-color: var(--light);
    border-radius: 0;
}

.form-grid .choices__list--single { padding: 0; }

.form-grid .choices[data-type*='select-one']::after {
    border-color: var(--bone) transparent transparent;
}

.form-grid .choices[data-type*='select-one'].is-open::after {
    border-color: transparent transparent var(--light);
}

.form-grid .choices__list--dropdown,
.form-grid .choices__list[aria-expanded] {
    background: var(--film);
    border: 1px solid var(--ash);
    border-radius: 0;
    color: var(--bone);
}

.form-grid .choices__list--dropdown .choices__item { padding: 0.7rem 1rem; }

.form-grid .choices__list--dropdown .choices__item--selectable.is-highlighted,
.form-grid .choices__list[aria-expanded] .choices__item--selectable.is-highlighted {
    background: var(--ash);
    color: var(--paper);
}

.form-grid .choices__placeholder { opacity: 0.45; }

.form-actions { margin-top: 2.25rem; }

.form-actions .button {
    border: 1px solid var(--light);
    cursor: pointer;
    font-size: var(--step-mono);
}

/* Google asks for attribution when the badge is hidden; the line sits under
   the form rather than the badge floating over the page. */
.grecaptcha-badge { visibility: hidden !important; }

/* ---------------------------------------------------------------- flash */

.message {
    max-width: 46rem;
    margin: 0 auto clamp(1.5rem, 4vh, 2.5rem);
    padding: 0.95rem 1.25rem;
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.06em;
    border: 1px solid var(--ash);
    background: var(--film);
    color: var(--paper);
}

.message.success { border-color: var(--light); }
.message.error { border-color: #b4634f; }

/* ---------------------------------------------------------------- error pages */

/* Errors get the public layout so a bad URL still looks like the studio.
   Pushed down clear of the fixed masthead. */
.error-page { padding-top: clamp(7rem, 18vh, 11rem); }

.error-title {
    font-size: var(--step-h1);
    margin-block: 0.5rem 1.5rem;
}

.error-actions { margin-top: 2.25rem; }

/* ---------------------------------------------------------------- footer */

.site-footer {
    padding-block: clamp(3rem, 8vh, 5rem);
    font-size: 0.9375rem;
}

.footer-top {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    justify-content: space-between;
    align-items: flex-start;
}

.footer-address {
    font-style: normal;
    display: grid;
    gap: 0.35rem;
}

.footer-address a {
    color: var(--bone);
    text-decoration: none;
}

.footer-address a:hover { color: var(--light); }

.footer-mark {
    height: clamp(5rem, 9vw, 7rem);
    width: auto;
    opacity: 0.9;
}

.footer-bottom {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 1.5rem;
    justify-content: space-between;
    align-items: center;
    margin-top: clamp(2rem, 6vh, 3.5rem);
    padding-top: 1.5rem;
    border-top: var(--rule);
}

.footer-links {
    display: flex;
    align-items: center;
    gap: 1.25rem;
}

.footer-links a {
    color: var(--bone);
    text-decoration: none;
    transition: color 180ms ease;
}

.footer-links a:hover { color: var(--light); }

.footer-fb {
    width: 26px;
    height: 26px;
    color: var(--bone);
    transition: color 180ms ease;
}

.footer-links a:hover .footer-fb { color: var(--light); }

/* ------------------------------------------------------ category pages */

.cat-hero {
    position: relative;
    min-height: clamp(20rem, 55vh, 34rem);
    overflow: hidden;
    display: flex;
    align-items: flex-end;
}

.cat-hero-frame img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* Same treatment as the home hero: the photograph darkens toward the copy so
   the headline never depends on where the light fell. */
.cat-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(5, 11, 7, 0.1) 30%, rgba(5, 11, 7, 0.82) 100%);
}

.cat-hero-body {
    position: relative;
    z-index: 1;
    padding-top: clamp(4rem, 10vh, 7rem);
    padding-bottom: clamp(2rem, 6vh, 3.5rem);
}

/* The no-banner opening: a centred editorial masthead with room to breathe,
   not a paragraph hugging the left edge of a void. */
.cat-head {
    padding-top: clamp(4rem, 12vh, 8rem);
    padding-bottom: clamp(2.5rem, 7vh, 5rem);
    text-align: center;
    border-bottom: 1px solid var(--ash);
}

.cat-head .cat-lead { margin-inline: auto; }

.cat-head .eyebrow a { color: inherit; }

.cat-head .eyebrow a:hover { color: var(--light); }

.cat-title {
    font-family: var(--serif);
    font-weight: 500;
    font-size: clamp(2.4rem, 6vw, 4rem);
    line-height: 1.05;
    color: var(--paper);
}

.cat-head .cat-title { color: var(--paper); }

.cat-lead {
    max-width: 38rem;
    margin-top: 0.9rem;
    color: var(--bone);
    font-size: clamp(1rem, 1.6vw, 1.15rem);
    line-height: 1.6;
}

.cat-copy { padding-top: clamp(2rem, 5vh, 3rem); }

.cat-copy .prose {
    max-width: 46rem;
    margin-inline: auto;
    color: var(--bone);
    line-height: 1.7;
}

.cat-copy .prose a { color: var(--light); }

.cat-children {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1rem;
    padding-top: clamp(1.5rem, 4vh, 2.5rem);
}

.cat-child {
    flex: 1 1 20rem;
    max-width: 28rem;
    border: 1px solid var(--ash);
    background: var(--film);
    transition: border-color 0.2s ease;
    overflow: hidden;
}

.cat-child:hover,
.cat-child:focus-visible { border-color: var(--light); }

/* The child's own photograph fronts the card — a door you can see through,
   not a text link pretending to be one. */
.cat-child-frame {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
}

.cat-child-frame img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: saturate(0.96);
    transition: transform 0.6s ease;
}

.cat-child:hover .cat-child-frame img { transform: scale(1.03); }

.cat-child-words {
    display: block;
    padding: 1.1rem 1.3rem 1.25rem;
}

.cat-child-name {
    display: block;
    font-family: var(--serif);
    font-size: 1.3rem;
    color: var(--paper);
    text-decoration: none;
}

/* The card is one link; nothing inside it dresses like a second one. */
.cat-child { text-decoration: none; }

.cat-child-copy {
    display: block;
    margin-top: 0.35rem;
    font-size: 0.9rem;
    color: var(--bone);
    line-height: 1.5;
}


.cat-sheet {
    padding-top: clamp(2rem, 5vh, 3rem);
    padding-bottom: clamp(2rem, 5vh, 3rem);
    columns: 3 18rem;
    column-gap: 1.25rem;
}

.cat-sheet .frame {
    break-inside: avoid;
    margin: 0 0 1.25rem;
}

.cat-sheet img {
    display: block;
    width: 100%;
    height: auto;
    filter: saturate(0.96);
}

.cat-sheet figcaption {
    padding-top: 0.5rem;
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.08em;
    color: var(--bone);
}

.cat-cta {
    padding-top: 1rem;
    padding-bottom: clamp(3rem, 8vh, 5rem);
}

/* ---------------------------------------------------------------- lightbox */

/*
 * The viewing room. A native <dialog> the lightbox script builds and fills —
 * nothing here renders without JavaScript, which is exactly right because
 * without JavaScript the links open the full-size files directly.
 *
 * The backdrop is the site's own ink frosted over the page, not a neutral
 * black: the whole palette is a green-black, and a #000 sheet in front of it
 * reads as a foreign layer. Blur carries the "the page is still under there"
 * feeling while getting every distraction out of the photograph's way.
 */
.lb {
    width: 100vw;
    height: 100dvh;
    max-width: none;
    max-height: none;
    margin: 0;
    border: 0;
    padding: clamp(1rem, 4vw, 3rem);
    background: transparent;
    color: var(--bone);
}

.lb[open] {
    display: grid;
    place-items: center;
}

.lb::backdrop {
    /* --ink, written out: custom properties on ::backdrop are still patchy. */
    background: rgba(5, 11, 7, 0.88);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
}

/* No page scroll behind the frame. */
body:has(.lb[open]) {
    overflow: hidden;
}

.lb-stage {
    margin: 0;
    display: grid;
    justify-items: center;
    gap: 0.9rem;
}

.lb-img {
    max-width: min(100%, 92vw);
    max-height: 80dvh;
    width: auto;
    height: auto;
    cursor: default;
}

@media (prefers-reduced-motion: no-preference) {
    .lb-img { transition: opacity 240ms ease; }
}

.lb-stage.is-loading .lb-img {
    opacity: 0;
}

.lb-meta {
    display: flex;
    gap: 1.5rem;
    align-items: baseline;
    font-family: var(--mono);
    font-size: var(--step-mono);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bone);
}

.lb-count {
    color: var(--light);
}

.lb button {
    appearance: none;
    background: transparent;
    border: 0;
    padding: 0.75rem;
    color: var(--bone);
    cursor: pointer;
    line-height: 0;
}

.lb button:hover,
.lb button:focus-visible {
    color: var(--light);
}

.lb button:focus-visible {
    outline: 1px solid var(--light);
    outline-offset: 2px;
}

.lb button svg {
    width: 1.6rem;
    height: 1.6rem;
}

.lb-close {
    position: fixed;
    top: clamp(0.5rem, 2vw, 1.5rem);
    right: clamp(0.5rem, 2vw, 1.5rem);
}

.lb-prev,
.lb-next {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
}

.lb-prev { left: clamp(0.25rem, 2vw, 1.5rem); }
.lb-next { right: clamp(0.25rem, 2vw, 1.5rem); }

/* An album of one has nowhere to page to. */
.lb-single .lb-prev,
.lb-single .lb-next,
.lb-single .lb-count {
    display: none;
}
