/* ── Lenis 1.3.23 base styles, inlined ──────────────────────────
   Previously a separate stylesheet from unpkg, which was a
   render-blocking request to a third-party host. It is 500 bytes;
   carrying it here removes a DNS + TLS round trip from the critical
   path. Note the `overflow: clip` rule below — that is the one the
   .wrapper override further down deliberately beats. */
html.lenis,
html.lenis body {
  height: auto;
}

.lenis:not(.lenis-autoToggle).lenis-stopped {
  overflow: clip;
}

.lenis [data-lenis-prevent],
.lenis [data-lenis-prevent-wheel],
.lenis [data-lenis-prevent-touch],
.lenis [data-lenis-prevent-vertical],
.lenis [data-lenis-prevent-horizontal] {
  overscroll-behavior: contain;
}

.lenis.lenis-smooth iframe {
  pointer-events: none;
}

.lenis.lenis-autoToggle {
  transition-property: overflow;
  transition-duration: 1ms;
  transition-behavior: allow-discrete;
}

/* ============================================================
   Esther Nadoff — editorial system
   Ported from the printed resume: warm cream stock, warm near-black
   ink, Archivo for everything structural, Monsieur La Doulaise for
   the script. No pure black, no pure white, no red.
   ============================================================ */

:root {
    /* The site prints in reverse: warm near-black ground, warm cream
       type. The loader keeps the cream sheet of the resume (--sheet
       below) and fades through the ground colour to hand off to it. */
    --ground: oklch(0.155 0.004 60);
    --ground-soft: oklch(0.205 0.004 60);
    --type: oklch(0.945 0.008 92);
    --type-body: oklch(0.855 0.006 92);
    --type-soft: oklch(0.655 0.005 92);
    --type-faint: oklch(0.495 0.004 92);
    --rule: oklch(0.945 0.008 92 / 0.22);
    --rule-soft: oklch(0.945 0.008 92 / 0.12);

    /* The opening sheet — the resume's own stock and ink */
    --sheet: oklch(0.949 0.012 92);
    --sheet-ink: oklch(0.19 0 0);

    /* Type */
    --sans: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    --script: 'Monsieur La Doulaise', 'Snell Roundhand', cursive;

    /* The resume's structural letterspacing, carried through */
    --track-head: 0.18em;
    --track-eyebrow: 0.22em;

    --bezzy: cubic-bezier(0.8, 0, 0, 1);
    --bezzy2: cubic-bezier(0.430, 0.195, 0.020, 1);
    --bezzy3: cubic-bezier(0.5, 0, 0, 1);

    /* Cotton: fractal-noise grain tile, multiplied over the sheet */
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
}

* {
    margin: 0;
    padding: 0;
    scrollbar-width: none;
    -ms-overflow-style: none;
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
*::-webkit-scrollbar { display: none; }

/* Present for search engines and screen readers; the visual opening is
   photographic and carries no headline of its own */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

html, body {
    /* Easy rems, 1rem = 10px */
    font-size: 62.5%;
    background: var(--ground);
    color: var(--type-body);
    font-family: var(--sans);
}

/* The stock, carried over from the resume but reading in reverse.
   Overlay rather than multiply, so the same grain sits correctly on the
   black of the site and the cream of the opening sheet. */
.paper-grain {
    position: fixed;
    inset: 0;
    z-index: 120;
    pointer-events: none;

    background-image: var(--grain);
    background-size: 300px 300px;
    mix-blend-mode: overlay;
    opacity: 0.3;
    transition: opacity 0.7s var(--bezzy2);
}

.paper-light {
    position: fixed;
    inset: 0;
    z-index: 119;
    pointer-events: none;

    background:
        radial-gradient(90rem 70rem at 8% 4%, oklch(1 0 0 / 0.055), transparent 62%),
        radial-gradient(80rem 80rem at 96% 98%, oklch(0 0 0 / 0.38), transparent 66%);
    transition: opacity 0.7s var(--bezzy2);
}

/* While the opening sheet is up, the paper is cream, so it takes the
   resume's own treatment: grain multiplied back, a white highlight off
   the top left, a faint pool bottom right. The rules above are the
   reverse of this, for the black the site runs on. */
body.is-opening .paper-grain {
    mix-blend-mode: multiply;
    opacity: 0.22;
}

body.is-opening .paper-light {
    background:
        radial-gradient(90rem 70rem at 8% 4%, oklch(1 0 0 / 0.5), transparent 62%),
        radial-gradient(80rem 80rem at 96% 98%, oklch(0.19 0 0 / 0.10), transparent 66%);
}

/* The highlight would read as a grey smear across the blackout, so the
   whole treatment lifts while the screen is dark */
body.is-blackout .paper-light,
body.is-blackout .paper-grain {
    opacity: 0;
}


/* ------------------------------------------------------------
   Opening loader — the flower inks in, sinks back into the sheet,
   and the name is written over it
   ------------------------------------------------------------ */
.loader {
    position: fixed;
    inset: 0;
    z-index: 100;

    display: grid;
    place-items: center;

    background: var(--sheet);
    transition: opacity 1.3s var(--bezzy2), visibility 1.3s var(--bezzy2),
                background-color 0.9s var(--bezzy2);
}

/* The sheet darkens to ink and the lockup goes with it, so the opening
   closes on itself rather than dissolving into the first hero */
/* The sheet darkens to the site's own ground, so the opening closes into
   the black the hero is already sitting on */
.loader.is-black {
    background-color: var(--ground);
}

.loader.is-black .loader-inner {
    opacity: 0;
    transition: opacity 0.7s var(--bezzy2);
}

.loader.is-done {
    opacity: 0;
    visibility: hidden;
}

/* The whole opening is one lockup, laid out exactly like the printed
   masthead: ESTHER, Nadoff swashing across and below it, and the
   drawing sitting behind them. Everything below is sized in ems of
   the block face, so the composition holds at any width. */
.loader-inner {
    position: relative;
    font-size: clamp(2.8rem, 5.6vw, 5.8rem);
    padding-bottom: 0.6em;

}

/* The drawing. It is painted in by the brush path inside the SVG mask,
   so the ink arrives stroke by stroke rather than fading up as a block. */
/* Centred behind the name. The lockup sits in the top of .loader-inner
   with 0.6em of padding below it, so the flower is offset up by half
   that padding to land on the name's centre rather than the box's. */
.loader-flower {
    position: absolute;
    left: 50%;
    top: calc(50% - 0.3em);
    transform: translate(-50%, -50%);
    z-index: 0;

    width: 5.2em;
    aspect-ratio: 1280 / 1600;

    transition: opacity 1.4s var(--bezzy2), filter 1.4s var(--bezzy2);
}

.loader-flower svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.loader-flower image {
    /* Match the ink the rest of the sheet is printed in */
    filter: grayscale(1) contrast(1.05);
}

/* Once it is drawn it stays exactly where and how big it was, and just
   settles back to a soft grey so the name can be written over it */
.loader.is-settled .loader-flower {
    opacity: 0.22;
    filter: grayscale(1);
}


/* The name doesn't type — the whole lockup resolves out of the paper
   at once, the way a name comes into focus. */
.loader-name {
    position: relative;
    z-index: 2;
    display: block;
    width: max-content;
    text-align: left;

    opacity: 0;
    filter: blur(18px);
    transition: opacity 1s var(--bezzy2), filter 1s var(--bezzy2);
}

.loader.is-settled .loader-name {
    opacity: 1;
    filter: blur(0);
}

.loader-name .block,
.loader-name .cursive {
    display: block;
    line-height: 1;
    color: var(--sheet-ink);
}

.loader-name .block {
    font-family: var(--sans);
    font-weight: 400;
    font-size: 1em;
    letter-spacing: var(--track-head);
    text-transform: uppercase;
}

/* The corner logo hangs the script at 0.9em in and 0.34em down from the
   top of the lockup. Reproduced here in normal flow — so the box still
   measures the full lockup and centres as one piece — by pulling the
   script up by the block's height less that offset. */
.loader-name .cursive {
    margin-top: -0.09em;
    margin-left: 0.9em;

    font-family: var(--script);
    font-weight: 400;
    font-size: 2.32em;
}

@media (prefers-reduced-motion: reduce) {
    .loader,
    .loader-flower,
    .loader-name { transition: none; }
}


/* Paint servers only — nothing to render */
.gradient-defs {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}


/* ------------------------------------------------------------
   Identity lockup, fixed top left — the resume masthead, shrunk
   ------------------------------------------------------------ */
.site-nav {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 50;

    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2.4rem;
    padding: 2.8rem 3.6rem;

    pointer-events: none;

    & a {
        pointer-events: auto;
        color: var(--type);
        text-decoration: none;
        transition: opacity 0.3s var(--bezzy2);

        &:hover { opacity: 0.55; }
    }
}

/* ESTHER set in Archivo with "Nadoff" swashing across and below it,
   the same overlap the printed masthead uses. */
.site-logo {
    position: relative;
    display: block;
    line-height: 1;
    padding-bottom: 1.2rem;

    & .block {
        display: block;
        font-family: var(--sans);
        font-weight: 400;
        font-size: 1.9rem;
        letter-spacing: var(--track-head);
        text-transform: uppercase;
        color: var(--type);
    }

    & .cursive {
        position: absolute;
        left: 0.9em;
        top: 0.34em;

        font-family: var(--script);
        font-weight: 400;
        font-size: 4.4rem;
        line-height: 1;
        color: var(--type);
        white-space: nowrap;
    }
}

.site-nav-links {
    display: flex;
    align-items: center;
    gap: 3.2rem;

    & a {
        font-family: var(--sans);
        font-weight: 700;
        font-size: 1.15rem;
        letter-spacing: var(--track-eyebrow);
        text-transform: uppercase;
        color: var(--type-soft);

        &:hover { color: var(--type); opacity: 1; }
    }
}

/* The type is cream on every section now, so the lockup only needs a
   little separation where it sits over a photograph */
body.on-photo .site-logo .block,
body.on-photo .site-logo .cursive,
body.on-photo .site-nav-links a {
    text-shadow: 0 0 2.4rem oklch(0 0 0 / 0.6);
}

.site-logo .block,
.site-logo .cursive,
.site-nav-links a {
    transition: color 0.6s var(--bezzy2), text-shadow 0.6s var(--bezzy2);
}


.wrapper {
    position: relative;
    height: 100svh;
    overflow: hidden;
}

.content { position: relative; }

/* Lenis locks scrolling by setting `overflow: clip` on the scroller. A
   clipped box cannot hold a scroll position, so the browser forces its
   scrollTop to 0 and the page snaps to the top behind an open dialog.
   `hidden` prevents scrolling just as well and keeps the position.
   Its own selector carries a :not() and so outranks a two-class rule —
   hence the extra weight and the !important on a vendor override. */
.wrapper.lenis.lenis-stopped {
    overflow: hidden !important;
}


/* ------------------------------------------------------------
   Photographic heroes — black and white, printed on the same stock
   ------------------------------------------------------------ */
.hero {
    position: relative;
    z-index: 1;

    display: grid;
    place-items: center;

    width: 100%;
    height: 100svh;
    overflow: clip;

    & picture, & img { display: block; }

    & picture {
        position: absolute;
        inset: 0;
        z-index: -1;
        background: var(--ground);

        & img {
            width: 100%;
            height: 100%;
            object-fit: cover;

            /* Everything is monochrome now, with the contrast lifted
               the same way the resume portrait is */
            filter: grayscale(1) contrast(1.08) brightness(0.92);

            &.crop-face { object-position: 50% 22%; }
        }
    }

    /* Vignette top and bottom so the marquee type holds against the
       photograph and the section beds into the black either side of it */
    &::after {
        content: '';
        position: absolute;
        inset: 0;
        z-index: 0;
        pointer-events: none;

        background:
            linear-gradient(180deg, oklch(0.155 0.004 60 / 0.55), transparent 30%, transparent 58%, oklch(0.155 0.004 60 / 0.72));
        mix-blend-mode: normal;
    }

    & .marquees { position: relative; z-index: 2; }
}


/* Curved marquee type */
.marquees {
    position: relative;
    width: 100%;
}

.radial-text-marquee {
    width: 100%;
    transform: translateY(-60%);

    /* The script shares the block word's box exactly, then gets lifted.
       The marquee centres each run by its bounding box, but the two faces
       sit very differently on the baseline: Archivo's caps are almost
       entirely above it (ink centre -0.35em) while the script straddles it
       with deep descenders (-0.10em). Box-centred therefore reads low, so
       the script is raised by the difference between the two ink centres.
       The font-size here is only so that em resolves against the script. */
    &.script {
        position: absolute;
        inset: 0;

        font-size: clamp(5rem, 18vw, 34rem);
        transform: translateY(-60%) translateY(-0.28em);
    }
}

.marquees h2,
.marquees h3 {
    text-align: center;
    white-space: nowrap;
    user-select: none;
    color: var(--type);
}

.marquees h2 {
    font-size: clamp(4.2rem, 15vw, 24rem);
    font-family: var(--sans);
    font-weight: 400;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.marquees h3 {
    font-size: clamp(5rem, 18vw, 34rem);
    font-family: var(--script);
    font-weight: 400;
    font-style: normal;
}


/* ------------------------------------------------------------
   Paper panels
   ------------------------------------------------------------ */
.panel {
    position: relative;
    z-index: 1;

    display: grid;
    align-items: center;

    width: 100%;
    min-height: 100svh;
    padding: 18rem 7vw;
    background: var(--ground);
}

.panel-inner {
    width: 100%;
    max-width: 108rem;
    margin: 0 auto;

    &.center { text-align: center; }
}

/* Section headings — the resume's 15px/700 rule, scaled up */
.eyebrow {
    margin-bottom: 4rem;

    font-family: var(--sans);
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type-soft);
}

.panel-title {
    font-family: var(--sans);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    font-size: clamp(4.4rem, 7.6vw, 10.5rem);
    line-height: 1.02;
    color: var(--type);

    & .script {
        font-family: var(--script);
        text-transform: none;
        font-size: 1.5em;
        line-height: 0.8;
        letter-spacing: 0;
        color: var(--type);
    }
}


/* Brands — its own band, running edge to edge. More room on top than
   below: it is the first thing after three full-bleed heroes and needs
   air to separate it from the photography. */
.brands-panel {
    min-height: auto;
    padding: 18rem 0 14rem;

    /* Cap the column at the panel width. The logo track is max-content,
       so without this the grid column inflates to the full length of the
       strip and shoves the centred heading off to the left. */
    grid-template-columns: minmax(0, 1fr);
}

.brands {
    width: 100%;

    & .eyebrow.center {
        text-align: center;
        margin-bottom: 4.4rem;
        font-size: 1.3rem;
    }
}

.logo-marquee {
    width: 100%;
    overflow: hidden;

    -webkit-mask-image: linear-gradient(to right, transparent, black 12%, black 88%, transparent);
    mask-image: linear-gradient(to right, transparent, black 12%, black 88%, transparent);
}

.logo-track {
    display: flex;
    width: max-content;
    will-change: transform;

    /* The CSS animation is the no-JS fallback. When scripting is on it is
       switched off and the strip is driven by GSAP instead, so it can be
       held at a chosen position until the section is reached. */
    animation: logo-scroll 32s linear infinite;
}

.js-marquee .logo-track {
    animation: none;
}

.logo-set {
    display: flex;
    align-items: center;
    gap: 5rem;
    padding-right: 5rem;

    & img {
        display: block;

        width: 20rem;
        height: 3.6rem;
        object-fit: contain;
        flex: none;

        /* Every mark flattened to the same cream */
        filter: brightness(0) invert(1);
        opacity: 0.5;
        transition: opacity 0.3s var(--bezzy2);

        &:hover { opacity: 0.8; }

        &.wide { height: 2.4rem; }
        &.tall { height: 5.6rem; }
    }
}

@keyframes logo-scroll {
    to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
    .logo-track {
        animation: none;
        flex-wrap: wrap;
        width: 100%;
        justify-content: center;
    }
}


/* ------------------------------------------------------------
   The work — an uneven tile grid
   ------------------------------------------------------------ */
.panel.work {
    padding-block: 14rem;
}

/* Two columns of tiles rather than a masonry row grid: each column packs
   its own tiles, so differing heights never leave holes, and the DOM
   order still reads left, right, left, right. */
.work-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 8rem;
}

.work-col {
    display: grid;
    gap: 8rem;
    align-content: start;
    list-style: none;
}

/* No artificial offset: the tiles are all different heights already, so
   the rows never line up on their own. An offset on top of that only
   guaranteed one column would dead-end before the other. */

.work-tile {
    display: block;
    width: 100%;
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    text-align: left;
    color: inherit;
    cursor: pointer;
}

/* Every tile takes its own media's true ratio, set per item, so the frame
   matches the thing inside it and nothing is ever cropped to fit */
.work-tile-media {
    display: block;
    position: relative;
    width: 100%;
    aspect-ratio: var(--ar);
    overflow: hidden;
    background: var(--ground-soft);

    & img, & video {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;

        transition: transform 0.7s var(--bezzy2);
    }
}

.work-tile:hover .work-tile-media img,
.work-tile:hover .work-tile-media video,
.work-tile:focus-visible .work-tile-media img,
.work-tile:focus-visible .work-tile-media video {
    transform: scale(1.03);
}

.work-name {
    display: block;
    margin-top: 1.8rem;

    font-family: var(--sans);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    font-size: clamp(1.8rem, 2vw, 2.6rem);
    line-height: 1.1;
    color: var(--type);
}

.work-meta {
    display: block;
    margin-top: 0.7rem;

    font-family: var(--sans);
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type-soft);
}

@media (max-width: 760px) {
    .gal-label { display: none; }
    .gal-status { justify-content: center; }
    .gal-btn { width: 4rem; height: 4rem; }
}

@media (max-width: 900px) {
    .work-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 6rem;
    }

    .work-col { gap: 6rem; }
}


/* ------------------------------------------------------------
   Project detail — one panel, filled from whichever row opened it
   ------------------------------------------------------------ */
.work-detail {
    position: fixed;
    inset: 0;
    z-index: 130;

    display: grid;
    place-items: center;
    padding: 4vh 4vw;
}

.work-detail[hidden] { display: none; }

.work-detail-scrim {
    position: absolute;
    inset: 0;
    background: oklch(0.09 0.003 60 / 0.9);

    opacity: 0;
    transition: opacity 0.5s var(--bezzy2);
}

.work-detail-sheet {
    position: relative;
    z-index: 1;

    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: start;
    gap: 4rem;

    width: min(112rem, 100%);
    max-height: 92vh;
    overflow-y: auto;
    padding: 4rem;

    background: var(--ground-soft);
    border: 1px solid var(--rule-soft);

    opacity: 0;
    transform: translateY(2.4rem);
    transition: opacity 0.55s var(--bezzy2), transform 0.55s var(--bezzy2);
}

.work-detail.is-open .work-detail-scrim { opacity: 1; }
.work-detail.is-open .work-detail-sheet { opacity: 1; transform: none; }

/* The frame takes the media's own ratio (set per project from the tile),
   so an opened case shows the whole image or video rather than a 16:10
   crop of it. --ar falls back only if a project is missing one. */
/* A campaign that ran as print, social, and film browses as a set. The
   frame takes each piece's own ratio and eases between them, so a
   full-page newspaper ad and a 4:5 social post are both shown whole
   rather than matted into one compromise shape. */
.work-detail-figure {
    position: relative;
    display: grid;
    gap: 1.6rem;
    align-content: start;
    min-width: 0;
}

/* Sits over the footage rather than under it, so the offer to turn the
   sound on is where the sound is. */
.gal-sound {
    position: absolute;
    top: 1.4rem;
    right: 1.4rem;
    z-index: 2;

    padding: 0.9rem 1.6rem;
    background: oklch(0.09 0.003 60 / 0.62);
    border: 1px solid oklch(0.945 0.008 92 / 0.22);
    cursor: pointer;
    backdrop-filter: blur(6px);

    font-family: var(--sans);
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type);
    transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.gal-sound[hidden] { display: none; }

.gal-sound:hover,
.gal-sound:focus-visible {
    background: var(--type);
    border-color: var(--type);
    color: var(--ground);
}

.gal-sound[aria-pressed="true"] {
    background: var(--type);
    border-color: var(--type);
    color: var(--ground);
}

.work-detail-gallery {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 1.6rem;
}

.work-detail-gallery[hidden] { display: none; }

.gal-btn {
    width: 4.4rem;
    height: 4.4rem;
    display: grid;
    place-items: center;

    background: none;
    border: 1px solid var(--rule-soft);
    border-radius: 50%;
    cursor: pointer;

    font-family: var(--sans);
    font-size: 1.6rem;
    color: var(--type-soft);
    transition: color 0.3s ease, border-color 0.3s ease, background 0.3s ease;
}

.gal-btn:hover,
.gal-btn:focus-visible {
    color: var(--ground);
    background: var(--type);
    border-color: var(--type);
}

.gal-status {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1.6rem;
    min-width: 0;

    font-family: var(--sans);
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
}

.gal-label {
    color: var(--type-body);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gal-count {
    color: var(--type-soft);
    flex: none;
    font-variant-numeric: tabular-nums;
}

.work-detail-media {
    aspect-ratio: var(--ar, 16 / 10);
    transition: aspect-ratio 0.45s var(--bezzy2);

    & img, & video {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: contain;
        background: var(--ground);
    }
}

.work-detail-text h3 {
    font-family: var(--sans);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    font-size: clamp(2.4rem, 3vw, 3.6rem);
    line-height: 1.05;
    color: var(--type);
}

.work-detail-meta {
    margin-top: 1.2rem;

    font-family: var(--sans);
    font-size: 1.2rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type-soft);
}

.work-detail-copy {
    margin-top: 2.4rem;

    font-family: var(--sans);
    font-size: 1.5rem;
    line-height: 1.75;
    color: var(--type-body);
}

.work-detail-link {
    display: inline-block;
    margin-top: 2.8rem;
    padding: 1.4rem 2.8rem;

    border: 1px solid var(--rule);
    font-family: var(--sans);
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type);
    text-decoration: none;

    transition: background 0.35s var(--bezzy2), color 0.35s var(--bezzy2),
                border-color 0.35s var(--bezzy2);

    &:hover { background: var(--type); border-color: var(--type); color: var(--ground); }
}

.work-detail-cta:empty { display: none; }

.work-detail-close {
    position: absolute;
    top: 1.6rem;
    right: 1.6rem;
    z-index: 2;

    appearance: none;
    background: none;
    border: 0;
    padding: 0.8rem;
    cursor: pointer;

    font-family: var(--sans);
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type-soft);

    &:hover { color: var(--type); }
}

@media (max-width: 860px) {
    .work-detail-sheet {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
        padding: 1.6rem 2rem 2.4rem;
    }

    /* On a narrow screen the sheet is a single column and the media fills
       it, so an overlaid close button sits on the picture and disappears
       into it. Put it back in the flow, above the media, on the sheet's
       own ground where it can be seen and hit. */
    .work-detail-close {
        position: static;
        justify-self: end;
        padding: 1rem 0.4rem;
        margin: 0;
        font-size: 1.2rem;
        color: var(--type);
    }
}


/* ------------------------------------------------------------
   The letter
   ------------------------------------------------------------ */
.panel.letter {
    padding-block: 14rem 12rem;
    text-align: center;
}

.panel.letter .panel-inner {
    display: grid;
    justify-items: center;
}

/* The drawing sketches itself in at the head of the letter */
.panel.letter .signature-flower {
    width: min(20vw, 12rem);
    margin: 0 0 2.4rem;
}

/* The opening line, set like the running head across the top of the
   resume: small, tracked, uppercase, in the soft grey */
.letterhead {
    margin-bottom: 4.4rem;

    font-family: var(--sans);
    font-size: 1.2rem;
    font-weight: 700;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type-soft);
}

.letter-body {
    max-width: 62rem;

    & p {
        font-family: var(--sans);
        font-size: clamp(1.7rem, 2vw, 2.2rem);
        font-weight: 400;
        line-height: 1.75;
        color: var(--type-body);
    }

    & p + p { margin-top: 2.4rem; }
}

/* Each line starts held back and is brought up as you read down it */
.letter-body p {
    opacity: 0.16;
    will-change: opacity, transform;
}

/* The letter is signed with the mark itself — the same lockup the corner
   logo and the opening use, at sign-off size. Everything is in ems of the
   block face so the overlap holds wherever it appears. */
.sign-lockup {
    position: relative;
    width: max-content;
    margin: 4.4rem auto 0;
    padding-bottom: 0.5em;

    font-size: clamp(1.8rem, 2.4vw, 2.8rem);
    text-align: left;

    opacity: 0;
    filter: blur(14px);
}

.sign-lockup .block {
    display: block;

    font-family: var(--sans);
    font-weight: 400;
    font-size: 1em;
    letter-spacing: var(--track-head);
    text-transform: uppercase;
    line-height: 1;
    color: var(--type);
}

.sign-lockup .cursive {
    display: block;
    margin-top: -0.09em;
    margin-left: 0.9em;

    font-family: var(--script);
    font-weight: 400;
    font-size: 2.32em;
    line-height: 1;
    color: var(--type);
}

.panel.letter .contact-links {
    justify-content: center;
    margin-top: 5.6rem;
}

.contact-detail { text-align: center; }


/* Contact — three ways in, given identical weight so none of them
   reads as the primary and the other two as filled-in fields */
.contact-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 1.2rem;

    & a {
        padding: 1.6rem 3.2rem;

        border: 1px solid var(--rule);
        font-family: var(--sans);
        font-size: 1.2rem;
        font-weight: 700;
        letter-spacing: var(--track-eyebrow);
        text-transform: uppercase;
        color: var(--type);
        text-decoration: none;

        transition: background 0.35s var(--bezzy2), color 0.35s var(--bezzy2),
                    border-color 0.35s var(--bezzy2);

        &:hover {
            background: var(--type);
            border-color: var(--type);
            color: var(--ground);
        }
    }
}

.contact-detail {
    margin-top: 2rem;

    font-family: var(--sans);
    font-size: 1.3rem;
    font-weight: 400;
    letter-spacing: 0.04em;
    color: var(--type-soft);
}

/* The sheet signs off in its corners: the line of record bottom left,
   the signature and its drawing bottom right */
/* The footer carries only the line of record now, so it centres under
   the letter rather than hanging in a corner on its own */
.panel-foot {
    position: absolute;
    left: 7vw;
    right: 7vw;
    bottom: 4rem;
    z-index: 1;

    display: flex;
    align-items: flex-end;
    justify-content: center;
}

.sign-off {
    display: grid;
    justify-items: center;
}

/* The sign-off drawing, under the signature. Inverted so the dark
   strokes of the original read as light on the black, and sketched in
   by the same stroke sequence the opening uses. */
.signature-flower {
    width: min(13vw, 8.5rem);
    aspect-ratio: 1280 / 1600;
    margin: 0.6rem auto 0;
    opacity: 0.5;
}

.signature-flower svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.signature-flower image {
    filter: invert(1) grayscale(1);
}

.copyright {
    margin: 0;

    font-family: var(--sans);
    font-size: 1.1rem;
    font-weight: 400;
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--type-faint);
}


@media screen and (max-width: 640px) {
    .site-nav { padding: 1.6rem 1.8rem; }
    .site-nav-links { gap: 1.6rem; }
    .panel { padding: 14rem 7vw; }

    /* The corner lockup is a mark at this size, not a headline */
    .site-logo { padding-bottom: 0.9rem; }
    .site-logo .block { font-size: 1.2rem; }
    .site-logo .cursive { font-size: 2.7rem; }
    .site-nav-links a { font-size: 1rem; }

    /* Give the letter and the CTAs room on a narrow screen */
    .panel.letter { padding-block: 11rem 10rem; }
    .contact-links { gap: 1rem; }
    .contact-links a { padding: 1.4rem 2.4rem; }
}
