/* ==========================================================================
   Matt Andrews – global styles
   Mobile first. Breakpoints: tablet ≥770px, desktop ≥1280px.
   ========================================================================== */

/* Fonts (self-hosted, variable)
   -------------------------------------------------------------------------- */
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url("../fonts/manrope-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url("../fonts/manrope-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Fraunces";
    font-style: italic;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/fraunces-italic-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Fraunces";
    font-style: italic;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/fraunces-italic-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/fraunces-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/fraunces-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Handwriting for sticky notes (only downloaded where a note appears) */
@font-face {
    font-family: "Caveat";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/caveat-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Design tokens
   -------------------------------------------------------------------------- */
:root {
    --cream: #faf4eb;
    --orange: #961313;
    --dark: #031f35;
    --yellow: #ffe96b;
    --white: #fff;
    --line: rgba(3, 31, 53, .55);

    --font-body: "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --font-display: "Fraunces", Georgia, "Times New Roman", serif;

    --ease: cubic-bezier(.45, 0, .55, 1);      /* ease-in-out */
    --ease-out: cubic-bezier(.22, 1, .36, 1);
    --hover: .2s var(--ease);

    --gutter: 20px;
    --max: 1500px;          /* home page content */
    --max-inner: 1280px;    /* inner pages content */
    --section-space: 80px;
}

@media (min-width: 770px) {
    :root {
        --gutter: 40px;
        --section-space: 110px;
    }
}

@media (min-width: 1280px) {
    :root {
        --gutter: 60px;
        --section-space: 140px;
    }
}

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

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    margin: 0;
    background: var(--cream);
    color: var(--dark);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: clip; /* scroll reveals start just off-screen */
}

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

img,
video {
    height: auto;
}

h1, h2, h3, p, ul, dl, dd, figure, blockquote {
    margin: 0;
}

ul {
    padding: 0;
    list-style: none;
}

a {
    color: inherit;
    transition: color var(--hover), background-color var(--hover), border-color var(--hover), opacity var(--hover);
}

button {
    font: inherit;
    color: inherit;
    cursor: pointer;
}

:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 100;
    padding: .6em 1.2em;
    border-radius: 999px;
    background: var(--dark);
    color: var(--cream);
    text-decoration: none;
    transform: translateY(-200%);
}

.skip-link:focus {
    transform: none;
}

/* Shared type */
.display-italic,
.page-title,
.intro__heading,
.logos__heading,
.contact__heading,
.project__title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 500;
    line-height: 1.15;
    color: var(--orange);
}

/* Buttons
   -------------------------------------------------------------------------- */
.button {
    display: inline-block;
    padding: .7em 2.2em;
    border: 1px solid var(--orange);
    border-radius: 999px;
    font-size: .9375rem;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    transition: color var(--hover), background-color var(--hover), border-color var(--hover);
}

.button--fill {
    background: var(--orange);
    color: var(--cream);
}

.button--fill:hover {
    background: var(--dark);
    border-color: var(--dark);
}

.button--outline {
    background: transparent;
    color: var(--orange);
}

.button--outline:hover {
    background: var(--orange);
    color: var(--cream);
}

/* Logo (inline SVG, takes the text colour) */
.logo {
    width: 100%;
    height: auto;
}

/* Header
   -------------------------------------------------------------------------- */
.site-header {
    position: relative;
    z-index: 10;
    color: var(--dark);
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    width: min(100% - 2 * var(--gutter), var(--max));
    margin-inline: auto;
    padding-block: 22px;
}

.site-header__logo {
    display: block;
    width: clamp(200px, 30vw, 265px);
    margin-left: auto;
    color: inherit;
}

.site-header__logo:hover {
    color: var(--orange);
}

.site-nav {
    display: none;
}

.site-nav__list {
    display: flex;
    gap: 2.2em;
}

.site-nav__link {
    color: var(--orange);
    text-decoration: none;
}

/* (the pale hover yellow only shows up on dark backgrounds) */
.site-nav__link:hover,
.site-nav__link[aria-current="page"] {
    color: var(--dark);
}

.menu-button {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin-left: -10px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--orange);
}

.menu-button svg,
.menu-tab svg,
.site-menu__close svg {
    width: 28px;
    height: 28px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
}

.menu-button:hover {
    color: var(--dark);
}

/* Light header: cream text over a coloured project header */
.site-header--light {
    color: var(--cream);
}

.site-header--light .site-nav__link,
.site-header--light .menu-button {
    color: var(--cream);
}

.site-header--light .site-nav__link:hover,
.site-header--light .site-nav__link[aria-current="page"],
.site-header--light .menu-button:hover,
.site-header--light .site-header__logo:hover {
    color: var(--yellow);
}

@media (min-width: 770px) {
    .site-header__inner {
        padding-block: 34px;
    }

    .site-nav {
        display: block;
        font-size: 1.1875rem;
    }

    .menu-button {
        display: none;
    }
}

@media (min-width: 1280px) {
    .site-header__inner {
        padding-inline: 40px;
    }

    .site-nav {
        font-size: 1.1875rem;
    }
}

/* Floating menu tab: top centre once the header has scrolled away
   -------------------------------------------------------------------------- */
/* A 68px circle with its top 26px above the screen edge; the top padding
   equals that hidden part, so the icon centres in the visible 42px */
.menu-tab {
    position: fixed;
    top: -26px;
    left: 50%;
    z-index: 30;
    display: grid;
    place-items: center;
    width: 68px;
    height: 68px;
    padding: 26px 0 0;
    border: 0;
    border-radius: 50%;
    background: var(--orange);
    color: var(--cream);
    box-shadow: 0 6px 10px rgba(3, 31, 53, .35);
    transform: translate(-50%, -110%);
    transition: transform .35s var(--ease), background-color var(--hover), color var(--hover);
}

.menu-tab.is-visible {
    transform: translate(-50%, 0);
}

.menu-tab:hover {
    color: var(--yellow);
}

.menu-is-open .menu-tab {
    transform: translate(-50%, -110%);
}

/* Slide-down menu: full screen on mobile; just the links, full width, above
   ------------------------------------------------------------------------ */
.site-menu {
    position: fixed;
    inset: 0 0 auto;
    z-index: 40;
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    background: var(--orange);
    color: var(--cream);
    visibility: hidden;
    transform: translateY(-100%);
    transition: transform .45s var(--ease), visibility 0s linear .45s;
}

.site-menu.is-open {
    visibility: visible;
    transform: none;
    transition: transform .45s var(--ease), visibility 0s;
}

.site-menu__inner {
    position: relative;
    width: min(100% - 2 * var(--gutter), var(--max));
    margin-inline: auto;
    padding-block: 22px 60px;
    text-align: center;
}

.site-menu__close {
    position: absolute;
    top: 22px;
    left: -10px;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--cream);
    transition: color var(--hover);
}

.site-menu__close:hover {
    color: var(--yellow);
}

.site-menu__logo {
    display: block;
    width: min(230px, 64vw);
    margin: 56px auto 70px;
    color: var(--cream);
}

.site-menu__logo:hover {
    color: var(--yellow);
}

.site-menu__list {
    display: grid;
    gap: 1.1em;
    font-size: 1.75rem;
    line-height: 1.2;
}

.site-menu__link {
    text-decoration: none;
}

.site-menu__link:hover,
.site-menu__link[aria-current="page"] {
    color: var(--yellow);
}

.site-menu :focus-visible {
    outline-color: var(--cream);
}

.menu-is-open body {
    overflow: hidden;
}

@media (min-width: 770px) {
    .site-menu {
        height: auto;
    }

    /* Just tall enough for one row: links on the left (lined up with the
       header nav), logo and close button on the right */
    .site-menu__inner {
        display: flex;
        align-items: center;
        gap: 24px;
        min-height: 96px;
        padding-block: 18px;
        text-align: left;
    }

    .site-menu nav {
        order: 1;
        flex: 1;
    }

    .site-menu__logo {
        order: 2;
        flex: 0 0 auto;
        width: clamp(170px, 18vw, 232px);
        margin: 0;
    }

    .site-menu__close {
        order: 3;
        position: static;
        flex: 0 0 auto;
        margin-right: -10px;
    }

    .site-menu__list {
        display: flex;
        gap: 2.2em;
        font-size: 1.1875rem;
    }

    .menu-is-open body {
        overflow: visible;
    }
}

@media (min-width: 1280px) {
    .site-menu__inner {
        padding-inline: 40px;
    }

    .site-menu__list {
        font-size: 1.1875rem;
    }
}

/* Invisible layer under the open menu: clicking outside the menu closes it */
.site-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 35;
    display: none;
    border: 0;
    background: transparent;
}

.menu-is-open .site-menu-backdrop {
    display: block;
}

/* Scroll reveals (see initReveal in scripts/main.js)
   Full-width elements fade in upwards; half-width ones from their side.
   -------------------------------------------------------------------------- */
.js [data-reveal] {
    opacity: 0;
    transform: translateY(48px);
    transition: opacity .9s var(--ease-out), transform .9s var(--ease-out);
}

.js [data-reveal-dir="left"] {
    transform: translateX(-64px);
}

.js [data-reveal-dir="right"] {
    transform: translateX(64px);
}

.js [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .js [data-reveal] {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* Home: hero animation + intro
   -------------------------------------------------------------------------- */

/* Full-width wrapper that trims the hero words at the screen edges as they
   spread apart on scroll, so they can't make the page wider on phones
   (hidden first for older Safari) */
.intro-wrap {
    overflow-x: hidden;
    overflow-x: clip;
}

.intro {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
        "hero"
        "text";
    width: min(100% - 2 * var(--gutter), var(--max));
    margin-inline: auto;
    padding-top: 28px;
}

.hero {
    grid-area: hero;
    --hero-size: min(16vw, 96px);
    --hero-line: .94em;
    font-size: var(--hero-size);
    font-weight: inherit;
    line-height: 1;
}

.hero__words {
    display: grid;
    grid-template-columns: auto auto;
    grid-template-rows: repeat(3, var(--hero-line));
    align-items: baseline;
    justify-content: start;
    column-gap: .14em;
}

.hero__word {
    grid-column: 1;
    justify-self: end;
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 560;
    font-optical-sizing: auto;
    letter-spacing: -.01em;
    line-height: var(--hero-line);
}

.hero__word--brand { grid-row: 1; }
.hero__word--web   { grid-row: 2; }
.hero__word--print { grid-row: 3; margin-right: .05em; }

.hero__design {
    grid-column: 2;
    grid-row: 2;
    font-size: .56em;
    font-weight: 500;
    letter-spacing: -.01em;
    line-height: 1;
}

/* Hero: "kinetic slot machine"
   Every row – brand, web, print and design – is a reel that rolls down
   through related words and lands on the final one, one after another, with
   a small bounce. Then it stays alive: the words drift with the mouse at
   different depths and spread apart as the page scrolls, over a slow
   outline marquee (scripts/main.js → initHeroKinetic).

   The finished words are the natural (un-animated) state, so reduced motion
   and any browser without animation support simply see the static hero.
   Timing: --hero-speed scales every duration (0.71 = 1.4× the lab's 1×).
   --w = start delay, --d = spin time per reel. */
.hero--kinetic {
    --hero-speed: .71;
    position: relative;
    isolation: isolate;
}

.hero--kinetic .hero__words {
    column-gap: .2em;
}

.hero--kinetic .hero__word--brand { --w: .1s; --d: 1.6s;  --depth: 24px;  --spread: -8vw; }
.hero--kinetic .hero__word--web   { --w: .1s; --d: 1.95s; --depth: -10px; --spread: 0vw; }
.hero--kinetic .hero__word--print { --w: .1s; --d: 2.3s;  --depth: 34px;  --spread: -4vw; }
.hero--kinetic .hero__design      { --w: .1s; --d: 2.8s;  --depth: -10px; --spread: 6vw; }

/* Kinetic layer: initHeroKinetic sets --mx / --my (mouse, -1…1) and --sp
   (scroll, 0…1). web and design share a depth so they never overlap. */
.hero--kinetic .hero__word,
.hero--kinetic .hero__design {
    transform:
        translate(calc(var(--mx, 0) * var(--depth)), calc(var(--my, 0) * var(--depth)))
        translateX(calc(var(--sp, 0) * var(--spread)));
}

/* Reels: a window one line tall. The strip lists the final word first, so
   at rest (transform: none) only the final word shows. Extra room on the
   side where longer words spill out during the roll. */
@property --hero-fade {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 0%;
}

.hero__reel {
    --step: calc(var(--hero-line) + .4em);
    display: block;
    height: calc(var(--hero-line) + .35em);
    margin: -.1em -.2em -.25em -4em;
    padding: 0 .2em 0 4em;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--hero-fade), #000 calc(100% - var(--hero-fade)), transparent);
    mask-image: linear-gradient(to bottom, transparent, #000 var(--hero-fade), #000 calc(100% - var(--hero-fade)), transparent);
}

.hero__design .hero__reel {
    margin: -.1em -6em -.25em -.2em;
    padding: 0 6em 0 .2em;
}

.hero__strip {
    display: block;
}

.hero__item {
    display: flex;
    justify-content: flex-end;
    height: var(--step);
    padding-top: .1em;
    line-height: var(--hero-line);
    white-space: nowrap;
}

/* Only the final word sets the width; the others spill out while rolling */
.hero__item:not(.is-final) {
    contain: inline-size;
}

.hero__design .hero__item {
    justify-content: flex-start;
}

/* Orange copy of the words, exactly over the dark ones. Hidden until the
   mouse is over the hero; initHoverBlobs then clips it to a constantly
   reshaping blob around the pointer. */
.hero__words--hover {
    position: absolute;
    inset: 0;
    color: var(--orange);
    pointer-events: none;
    clip-path: circle(0 at 0 0);
}

/* Page backdrop: the "independent · designer" outline marquee, fixed behind
   the whole home page. It starts behind the hero words; initHeroKinetic
   then lets it glide down to the middle of the screen as you scroll and
   settle there while the page scrolls over it. Without that script (or
   with reduced motion) it simply sits in the middle of the screen.
   Text size matches the hero (1.7 × the hero word size). */
.page-backdrop {
    position: fixed;
    inset: 0;
    z-index: -1;
    overflow: hidden;
    font-family: var(--font-display);
    font-size: calc(min(16vw, 96px) * 1.7);
    font-style: italic;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    pointer-events: none;
}

.page-backdrop__rows {
    position: absolute;
    top: 50%;
    left: 0;
    display: grid;
    gap: .05em;
    transform: translateY(-50%);
}

@media (min-width: 770px) {
    .page-backdrop {
        font-size: calc(min(9.75vw, 124px) * 1.7);
    }
}

@media (min-width: 1280px) {
    .page-backdrop {
        font-size: calc(min(7.6vw, 146px) * 1.7);
    }
}

.hero__marquee-track {
    width: max-content;
    color: transparent;
    -webkit-text-stroke: 1px rgba(150, 19, 19, .28);
}

/* Highlight sweep: every few seconds a wash of colour zooms across each
   row of outline lettering – a faint orange tail building to a peak, a
   sharp edge into a white glow that fades out (based on
   theme_assets/mask-text-highlight-gradient.webp). The gradient fills the
   letters only (background-clip: text); initHeroKinetic moves it across
   the screen by setting --sweep-x. Off-screen until then. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    .hero__marquee-track {
        background-image: linear-gradient(90deg,
            rgba(150, 19, 19, 0) 0%,
            rgba(150, 19, 19, .06) 15%,
            rgba(150, 19, 19, .18) 30%,
            rgba(150, 19, 19, .4) 45%,
            rgba(150, 19, 19, .62) 55%,
            rgba(255, 255, 255, .95) 58.5%,
            rgba(255, 255, 255, .7) 75%,
            rgba(255, 255, 255, 0) 100%);
        background-repeat: no-repeat;
        background-size: var(--sweep-width, 55vw) 100%;
        background-position: var(--sweep-x, -300vw) 0;
        -webkit-background-clip: text;
        background-clip: text;
    }

    /* Bottom row sweeps right to left, so its wash is mirrored */
    .hero__marquee-track--reverse {
        background-image: linear-gradient(270deg,
            rgba(150, 19, 19, 0) 0%,
            rgba(150, 19, 19, .06) 15%,
            rgba(150, 19, 19, .18) 30%,
            rgba(150, 19, 19, .4) 45%,
            rgba(150, 19, 19, .62) 55%,
            rgba(255, 255, 255, .95) 58.5%,
            rgba(255, 255, 255, .7) 75%,
            rgba(255, 255, 255, 0) 100%);
    }
}

@media (prefers-reduced-motion: no-preference) {
    .hero--play .hero__strip {
        animation: hero-slot calc(var(--d) * var(--hero-speed)) linear calc(var(--w) * var(--hero-speed)) both;
    }

    .hero--play .hero__reel {
        animation: hero-slot-blur calc(var(--d) * var(--hero-speed)) linear calc(var(--w) * var(--hero-speed)) both;
    }

    .page-backdrop {
        animation: hero-marquee-in 1s var(--ease-out) both;
    }

    .hero--kinetic .hero__word,
    .hero--kinetic .hero__design,
    .hero__marquee-track,
    .page-backdrop__rows {
        will-change: transform;
    }
}

/* Roll down from the first word to the final one, run a touch past, settle */
@keyframes hero-slot {
    0% {
        transform: translateY(calc((var(--n) - 1) * var(--step) * -1));
        animation-timing-function: cubic-bezier(.3, .15, .45, 1);
    }
    86% {
        transform: translateY(calc(var(--step) * .14));
        animation-timing-function: cubic-bezier(.4, 0, .4, 1);
    }
    100% {
        transform: none;
    }
}

/* Blur while fast, and fade the reel's top and bottom edges like a drum */
@keyframes hero-slot-blur {
    0%   { opacity: 0; filter: blur(0); --hero-fade: 30%; }
    6%   { opacity: 1; }
    15%  { filter: blur(3px); }
    60%  { filter: blur(1.5px); }
    75%  { --hero-fade: 30%; }
    84%  { filter: blur(0); }
    92%  { --hero-fade: 0%; }
    100% { opacity: 1; filter: blur(0); --hero-fade: 0%; }
}

@keyframes hero-marquee-in {
    from { opacity: 0; transform: scale(1.25); }
}

.intro__me {
    grid-area: hero;
    justify-self: end;
    align-self: end;
    width: 44%;
    max-width: 210px;
    margin-bottom: -14%;
}

/* Foot tap: the illustration is two copies of the same image.
   - The body has the front of the forward shoe notched out (from the left
     edge: x 0–68, y 345–394 of the 456 × 432 image).
   - The foot copy is clipped to the same area plus a few pixels (x 0–72),
     overlapping the body so there's no seam, stopping short of the
     trouser creases; it tilts up from the heel.
   Rhythm: a double tap, 5s, a single tap, 5s, repeat. The ground shadow
   stays on the body, so a sliver of light shows as the toe lifts.
   All percentages are of the image, so it scales with the illustration. */
.intro__me {
    position: relative;
}

.intro__me img {
    width: 100%;
}

.intro__me-body {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 0 91.2%, 15.35% 91.2%, 13.16% 79.86%, 0 79.86%);
}

.intro__me-foot {
    position: absolute;
    inset: 0;
    clip-path: polygon(0 79.86%, 14.04% 79.86%, 16.23% 91.2%, 0 91.2%);
    transform-origin: 18.86% 90.74%; /* the heel */
}

@media (prefers-reduced-motion: no-preference) {
    .intro__me-foot {
        animation: me-foot-tap 11.4s linear 3s infinite;
    }
}

/* 11.4s cycle: double tap at 0s, single tap at 5.6s */
@keyframes me-foot-tap {
    0%, 5.3%, 49.1%, 51.8%, 100% {
        transform: none;
    }
    0%, 2.6%, 49.1% {
        animation-timing-function: cubic-bezier(.3, 0, .3, 1); /* lift */
    }
    1.3%, 3.9%, 50.4% {
        transform: rotate(14deg);
        animation-timing-function: cubic-bezier(.6, 0, .9, .6); /* drop: quick landing */
    }
    2.6% {
        transform: none;
    }
}

.intro__text {
    grid-area: text;
    max-width: 640px;
    margin-top: 64px;
}

.intro__heading {
    margin-bottom: .45em;
    font-size: clamp(1.75rem, 1.2rem + 1.6vw, 2.25rem);
}

.intro__text p {
    font-size: 1.0625rem;
}

/* Small phones: the illustration gets its own row under the words instead
   of tucking in beside them, so the top doesn't feel cramped */
@media (max-width: 639px) {
    .intro {
        grid-template-areas:
            "hero"
            "me"
            "text";
        padding-top: 48px;
    }

    .intro__me {
        grid-area: me;
        width: 48%;
        max-width: 240px;
        margin: 28px 0 0;
    }

    .intro__text {
        margin-top: 44px;
    }
}

@media (min-width: 770px) {
    /* Outer 1fr columns keep the words + illustration centred as a group
       while the intro text below uses the full width */
    .intro {
        grid-template-columns: 1fr auto auto 1fr;
        grid-template-areas:
            ". hero me ."
            "text text text text";
        column-gap: 0;
        padding-top: 36px;
    }

    .hero {
        --hero-size: min(9.75vw, 124px);
    }

    .intro__me {
        grid-area: me;
        justify-self: start;
        width: clamp(150px, 20vw, 230px);
        max-width: none;
        margin: 0 0 -10px -2vw;
    }

    .intro__text {
        max-width: none;
        margin-top: 56px;
    }

    .intro__text p {
        font-size: 1.125rem;
    }
}

@media (min-width: 1280px) {
    .intro {
        /* the hero row spans the full width so the words centre on the page */
        grid-template-columns: minmax(0, 1040px) 210px minmax(0, 1fr);
        grid-template-areas:
            "hero hero hero"
            "text me .";
        column-gap: 40px;
        padding-top: 50px;
    }

    .hero {
        --hero-size: min(7.6vw, 146px);
        justify-self: center;
    }

    .intro__me {
        width: 210px;
        align-self: center;
        margin: 40px 0 0;
    }

    .intro__text {
        align-self: center;
        margin-top: 110px;
        padding-left: 60px;
    }

    .intro__text p {
        max-width: 54ch;
    }
}

/* Project tiles (home, work page, "more work")
   -------------------------------------------------------------------------- */
.work {
    width: min(100% - 2 * var(--gutter), var(--max));
    margin: var(--section-space) auto 0;
}

.tiles {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-auto-flow: row dense;
    gap: 56px 12%;
}

/* Tilt and sheen on hover (initTileTilt in main.js sets the angles and the
   light position from the mouse; mouse only, off with reduced motion) */
.tile__link {
    display: block;
    text-decoration: none;
    perspective: 900px;
}

.tile__media {
    position: relative;
    overflow: hidden;
    background: var(--white);
    transform: rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
    transition: transform .25s var(--ease-out), box-shadow .3s var(--ease);
}

/* Hovered: lifts towards the viewer, with a deeper two-layer shadow
   (a wide soft one for height, a tighter one close underneath) */
.tile.is-tilting .tile__media {
    transform: translateZ(28px) rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
    box-shadow:
        0 34px 50px -24px rgba(3, 31, 53, .6),
        0 12px 20px -12px rgba(3, 31, 53, .4);
}

.tile__sheen {
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at var(--sx, 50%) var(--sy, 50%), rgba(255, 255, 255, .35), transparent 45%);
    mix-blend-mode: soft-light;
    opacity: 0;
    transition: opacity .3s var(--ease);
    pointer-events: none;
}

.tile.is-tilting .tile__sheen {
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .tile__media {
        transform: none;
        transition: none;
    }
}

.tile__media img,
.tile__media video {
    width: 100%;
    transition: transform .6s var(--ease);
}

/* Home page: every tile shares the landscape proportion of the wide
   project images (1500 × 718); square images are cropped to fill it from
   the centre. For a sharp result, supply images at this shape. */
.work .tile__media {
    aspect-ratio: 1500 / 718;
}

.work .tile__media img,
.work .tile__media video {
    height: 100%;
    object-fit: cover;
}

.tile__link:hover .tile__media img,
.tile__link:hover .tile__media video {
    transform: scale(1.025);
}

/* Caption: counter, services, client. On desktop, wide tiles put the
   client on the right of the counter with the services underneath. */
.tile__caption {
    display: grid;
    grid-template-areas:
        "index"
        "services"
        "client";
    gap: .35em;
    margin-top: 16px;
}

.tile__index {
    grid-area: index;
    margin-bottom: .5em;
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(3, 31, 53, .55);
}

.tile__index-number {
    margin-inline: .25em;
    color: var(--orange);
}

.tile__services {
    grid-area: services;
    max-width: 44ch;
    font-family: var(--font-display);
    font-size: 1.125rem; /* phones; tablet and desktop set their own */
    font-style: italic;
    font-weight: 450;
    line-height: 1.3;
    color: var(--orange);
    transition: color var(--hover);
}

.tile__link:hover .tile__services {
    color: var(--dark);
}

.tile__client {
    grid-area: client;
    font-size: .9375rem; /* phones; tablet and desktop set their own */
}

/* "Client – Name": the name in the same type and colour as "Client" */
.tile__client-name::before {
    content: "– ";
}

@media (min-width: 770px) {
    .tiles {
        row-gap: 90px;
    }

    .tile__services {
        font-size: 1.1875rem;
    }

    .tile__client {
        font-size: .9375rem;
    }
}

/* Half-width tiles slide in from the side (scroll reveals); trim anything
   past the screen edge so the page never gets wider. Hidden first for
   older Safari. */
main {
    overflow-x: hidden;
    overflow-x: clip;
}

/* Square tiles sit two to a row from 851px up (one column at 850px and below) */
@media (min-width: 851px) {
    .tiles {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 8%;
    }

    .tile--wide {
        grid-column: 1 / -1;
    }
}

@media (min-width: 1280px) {
    .tiles {
        column-gap: 12%;
        row-gap: 110px;
    }

    .tile__services {
        font-size: 1.25rem;
    }

    .tile--wide .tile__caption {
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "index    client"
            "services services";
        column-gap: 40px;
    }

    .tile--wide .tile__client {
        align-self: end;
        margin-bottom: .35em;
    }
}

/* Section title bar ("Selected work."), shared eyebrow label and the
   intro buttons
   -------------------------------------------------------------------------- */
.eyebrow {
    margin-bottom: 10px;
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .11em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--orange);
}

.section-head {
    display: grid;
    gap: 16px;
    margin-bottom: 40px;
    padding-bottom: 22px;
    border-bottom: 1px solid rgba(3, 31, 53, .18);
}

.section-head__title {
    font-size: clamp(2.5rem, 1.7rem + 2.6vw, 4rem);
    font-weight: 550;
    letter-spacing: -.045em;
    line-height: 1;
}

.section-head__title span {
    color: var(--orange);
}

/* Same type as the intro paragraph ("I'm Matt, …") */
.section-head__summary {
    max-width: 38ch;
    font-size: 1.0625rem;
}

@media (min-width: 770px) {
    .section-head__summary {
        font-size: 1.125rem;
    }
}

#selected-work {
    scroll-margin-top: 40px;
}

.intro__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 28px;
    margin-top: 28px;
}

.button--arrow {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: .92em 1.4em;
    font-weight: 650;
}

.button--arrow span,
.intro__work-link span {
    display: inline-block;
    transition: transform .25s var(--ease-out);
}

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

.intro__work-link {
    font-size: .9375rem;
    font-weight: 650;
    text-decoration-color: rgba(3, 31, 53, .3);
    text-underline-offset: 5px;
}

.intro__work-link span {
    margin-left: 4px;
    color: var(--orange);
}

.intro__work-link:hover {
    color: var(--orange);
}

.intro__work-link:hover span {
    transform: translateY(3px);
}

@media (min-width: 770px) {
    .section-head {
        grid-template-columns: 1fr auto;
        align-items: end;
        column-gap: 32px;
    }

    .intro__actions {
        margin-top: 34px;
    }
}

@media (min-width: 1280px) {
    .section-head {
        margin-bottom: 54px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .button--arrow span,
    .intro__work-link span {
        transition: none;
    }
}


/* Contact ("Let's make it happen.")
   A solid panel the same width as the dark footer (see .site-footer).
   -------------------------------------------------------------------------- */
.contact {
    --panel: #f1e7db;
    width: min(100% - 24px, var(--max));
    margin: var(--section-space) auto 0;
    padding: 44px 20px 48px;
    border-radius: 32px;
    background: var(--panel);
    scroll-margin-top: 40px;
}

.contact__intro {
    max-width: 720px;
    margin: 0 auto 42px;
    text-align: center;
}

.contact__heading {
    margin-bottom: 14px;
    font-size: clamp(2.75rem, 1.7rem + 4vw, 4.75rem);
    letter-spacing: -.04em;
    line-height: 1;
}

/* Same size as the intro paragraph ("I'm Matt, …") */
.contact__lead {
    max-width: 54ch;
    margin-inline: auto;
    font-size: 1.0625rem;
}

@media (min-width: 770px) {
    .contact__lead {
        font-size: 1.125rem;
    }
}

@media (min-width: 770px) {
    .contact {
        width: min(100% - 2 * var(--gutter), var(--max));
        padding: clamp(56px, 6vw, 88px) clamp(40px, 7vw, 100px);
        border-radius: clamp(40px, 4vw, 56px);
    }
}

.contact-form__hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.contact-form {
    display: grid;
    gap: 34px;
}

.contact-form__fields {
    display: grid;
    gap: 34px;
}

.contact-form__field label {
    display: block;
    padding-left: 4px;
    font-size: 1.0625rem;
}

.contact-form input,
.contact-form textarea {
    display: block;
    width: 100%;
    padding: .55em 4px;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--dark);
    font: inherit;
    font-size: 1.0625rem;
}

.contact-form input {
    border-bottom: 1px solid var(--line);
    transition: border-color var(--hover), box-shadow var(--hover);
}

.contact-form input:focus {
    outline: none;
    border-color: var(--orange);
    box-shadow: 0 1px 0 var(--orange);
}

.contact-form__field--message {
    padding: 18px 18px 10px;
    border: 1px solid var(--line);
    border-radius: 20px;
    transition: border-color var(--hover), box-shadow var(--hover);
}

.contact-form__field--message label {
    padding-left: 0;
}

.contact-form textarea {
    min-height: 220px;
    padding-inline: 0;
    resize: vertical;
}

.contact-form textarea:focus {
    outline: none;
}

.contact-form__field--message:focus-within {
    border-color: var(--orange);
    box-shadow: 0 0 0 1px var(--orange);
}

.contact-form [aria-invalid="true"],
.contact-form__field--message:has([aria-invalid="true"]) {
    border-color: var(--orange);
}

/* Labels and typed text match the intro paragraph size */
@media (min-width: 770px) {
    .contact-form__field label,
    .contact-form input,
    .contact-form textarea {
        font-size: 1.125rem;
    }
}
.contact-form__error {
    margin-top: 6px;
    padding-left: 4px;
    font-size: .875rem;
    color: var(--orange);
}

.contact-form__footer {
    display: grid;
    justify-items: start;
    gap: 16px;
}

.contact-form__privacy {
    font-size: .8125rem;
    opacity: .8;
}

.contact__alert {
    margin: 0 auto 30px;
    padding: 14px 20px;
    border: 1px solid var(--orange);
    border-radius: 14px;
    color: var(--orange);
    text-align: center;
}

.contact__success {
    max-width: 640px;
    margin-inline: auto;
    padding: 36px 30px;
    border: 1px solid var(--line);
    border-radius: 20px;
    text-align: center;
}

.contact__success:focus {
    outline: none;
}

.contact__success-title {
    margin-bottom: .4em;
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-style: italic;
    color: var(--orange);
}

.contact__phone {
    margin-top: 44px;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-style: italic;
    line-height: 1.35;
    color: var(--orange);
    text-align: center;
}

.contact__phone a {
    display: block;
    margin-top: .2em;
    font-size: 1.6em;
    text-decoration: none;
}

.contact__phone a:hover {
    color: var(--dark);
}

/* phones: the number on its own line */
.contact__phone-call {
    display: block;
}

@media (min-width: 770px) {
    .contact__phone {
        font-size: 1.375rem;
    }

    .contact__phone-call {
        display: none;
    }

    .contact__phone a {
        display: inline;
        margin: 0 0 0 .25em;
        font-size: 1em;
    }
}

@media (min-width: 1280px) {
    .contact__intro {
        margin-bottom: 56px;
    }

    .contact-form {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
        column-gap: 48px;
        max-width: 1120px;
        margin-inline: auto;
    }

    .contact-form__fields {
        align-content: space-between;
        padding-top: 18px;
    }

    .contact-form__field--message {
        display: flex;
        flex-direction: column;
    }

    .contact-form textarea {
        flex: 1;
    }

    .contact-form__footer {
        grid-column: 1 / -1;
        justify-items: center;
        text-align: center;
    }
}

/* Footer
   -------------------------------------------------------------------------- */
.site-footer {
    width: min(100% - 24px, var(--max));
    margin: var(--section-space) auto 0;
    padding: 60px var(--gutter) 34px;
    border-radius: 60px 60px 0 0;
    background: var(--dark);
    color: var(--cream);
}

.site-footer__inner {
    display: grid;
    justify-items: center;
    text-align: center;
}

.site-footer__links {
    display: grid;
    gap: .35em;
    font-size: 1.25rem;
}

.site-footer__link {
    text-decoration: none;
}

.site-footer__link:hover {
    color: var(--yellow);
}

.site-footer__logo {
    position: relative;
    display: block;
    width: min(100%, 900px);
    margin: 56px 0 70px;
    color: var(--cream);
}

/* Orange copy of the logo shown through the mouse blob (initHoverBlobs).
   Where the blob effect isn't running (touch, reduced motion), hover turns
   the logo yellow instead. */
.site-footer__logo-blob {
    position: absolute;
    inset: 0;
    color: var(--orange);
    pointer-events: none;
    clip-path: circle(0 at 0 0);
}

.site-footer__logo:not(.has-blob):hover {
    color: var(--yellow);
}

.site-footer__small {
    font-size: .8125rem;
}

.site-footer__small a {
    text-decoration: none;
}

.site-footer__small a:hover {
    color: var(--yellow);
}

.site-footer :focus-visible {
    outline-color: var(--yellow);
}

@media (min-width: 770px) {
    .site-footer {
        width: min(100% - 2 * var(--gutter), var(--max));
        padding-top: 50px;
        border-radius: 80px 80px 0 0;
    }

    .site-footer__links {
        display: flex;
        gap: 0;
        font-size: 1rem;
    }

    .site-footer__links li + li::before {
        content: "/";
        padding-inline: .7em;
    }

    .site-footer__logo {
        width: min(80%, 900px);
        margin-block: 80px 90px;
    }
}

/* Project page
   -------------------------------------------------------------------------- */
.project-hero {
    background: var(--brand-bg, var(--dark));
    color: var(--cream);
    /* the facts slide in from the side: never let that widen the page */
    overflow-x: hidden;
    overflow-x: clip;
}

.project-hero__inner {
    display: grid;
    gap: 50px;
    width: min(100% - 2 * var(--gutter), var(--max-inner));
    margin-inline: auto;
    padding-block: 40px 60px;
}

.project-hero__logo {
    display: grid;
    place-items: center;
    color: var(--brand-fg, var(--cream));
}

.project-hero__logo img {
    width: min(74vw, 320px); /* as the original designs: ~320px, most of a phone screen */
    height: auto;
}

.project-hero__name {
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 1.6rem + 3.6vw, 4.5rem);
    font-style: italic;
    font-weight: 500;
    line-height: 1.05;
    text-align: center;
}

.project-hero__facts {
    display: grid;
    gap: 28px;
}

.project-hero__facts dt {
    font-family: var(--font-display);
    font-size: 1rem;
    font-style: italic;
    font-weight: 600;
}

.project-hero__facts dd {
    font-size: 1.0625rem;
    line-height: 1.5;
}

.project {
    width: min(100% - 2 * var(--gutter), var(--max-inner));
    margin-inline: auto;
}

.project__top {
    display: flex;
    justify-content: space-between;
    padding-top: 24px;
}

.project__more--top {
    display: none;
}

.back-arrow {
    display: block;
    width: 48px;
    color: var(--orange);
}

.back-arrow svg {
    width: 100%;
    height: auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.back-arrow circle {
    transition: fill var(--hover);
}

.back-arrow path {
    stroke-width: 2.5;
    transition: stroke var(--hover);
}

.back-arrow:hover circle {
    fill: var(--orange);
}

.back-arrow:hover path {
    stroke: var(--cream);
}

.project__intro {
    margin-top: 30px;
}

.project__intro-text {
    display: grid;
    gap: 1.2em;
    font-size: 1.0625rem;
}

.project__title {
    margin-bottom: .35em;
    font-size: clamp(2.25rem, 1.8rem + 1.6vw, 2.75rem);
}

/* More work: a rule separates it from the project, then the button and
   three small landscape cards (same shape as the home page) */
.project__others {
    margin-top: 80px;
    padding-top: 50px;
    border-top: 1px solid rgba(3, 31, 53, .18);
}

.project__others .tiles {
    margin-top: 40px;
    gap: 44px 4%;
}

.project__others .tile {
    grid-column: auto;
}

.project__others .tile__media {
    aspect-ratio: 1500 / 718;
}

.project__others .tile__media img,
.project__others .tile__media video {
    height: 100%;
    object-fit: cover;
}

.project__others .tile__index {
    display: none;
}

.project__others .tile .tile__caption { /* beats the wide-tile caption layout */
    grid-template-columns: 1fr;
    grid-template-areas:
        "services"
        "client";
}

.project__others .tile__services {
    font-size: 1.0625rem;
}

@media (min-width: 851px) {
    .project__others .tiles {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* Image blocks: wide = full width; square / tall / quote = half width on
   desktop. A tall block is two rows high, so it sits beside two half blocks. */
.blocks {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-auto-flow: row dense;
    gap: 50px 6.5%;
    margin-top: 50px;
}

.block {
    display: flex;
    flex-direction: column;
}

/* A subtle two-layer shadow lifts the images off the page */
.block__media {
    overflow: hidden;
    background: var(--white);
    box-shadow:
        0 2px 4px rgba(3, 31, 53, .06),
        0 18px 30px -18px rgba(3, 31, 53, .28);
}

.block--wide .block__media   { aspect-ratio: 16 / 9; }
.block--square .block__media { aspect-ratio: 1; }
.block--tall .block__media   { aspect-ratio: 1 / 2; } /* the whole picture, never cropped */

.block__media img,
.block__placeholder {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.block figcaption {
    margin-top: 12px;
    padding-left: 4px;
    font-family: var(--font-display);
    font-size: 1rem;
    font-style: italic;
    line-height: 1.35;
    color: var(--orange);
}

.block--quote {
    justify-content: center;
    padding: 10px 0;
}

.block--quote p {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 1.2rem + 1vw, 1.875rem);
    font-style: italic;
    font-weight: 450;
    line-height: 1.3;
    color: var(--orange);
}

.block--quote footer {
    margin-top: 1.2em;
    font-size: .9375rem;
}

@media (min-width: 770px) {
    .project-hero__inner {
        gap: 60px;
        padding-block: 60px 80px;
    }

    .project-hero__facts dd {
        font-size: 1.125rem;
    }

    .project__intro-text {
        font-size: 1.125rem;
    }

    .project__top {
        padding-top: 30px;
    }

    .block figcaption {
        font-size: 1.1875rem;
    }
}

@media (min-width: 1280px) {
    .project__top {
        justify-content: flex-end;
        padding-top: 56px; /* space below the header bar */
    }

    .project__more--top {
        display: inline-block;
    }

    .back-arrow {
        display: none;
    }

    .project__intro {
        margin-top: 34px;
    }
}

/* Two columns from 851px, as the home page tiles */
@media (min-width: 851px) {
    .project-hero__inner {
        grid-template-columns: 1fr 1fr;
        align-items: center;
        min-height: clamp(520px, 36vw, 700px);
        padding-block: 40px 90px;
    }

    .project-hero__facts {
        padding-left: 4%;
    }

    .project-hero__facts dd {
        max-width: 34ch;
    }

    .project__intro-text {
        grid-template-columns: 1fr 1fr;
        column-gap: 8%;
    }

    .blocks {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        row-gap: 60px;
        margin-top: 60px;
    }

    .block--wide {
        grid-column: 1 / -1;
    }

    /* Tall: two rows high; grows to line up with whatever sits beside it */
    .block--tall {
        grid-row: span 2;
    }

    .block--tall .block__media {
        flex: 1 0 auto;
        aspect-ratio: 1 / 2;
    }

    /* Centre the quote in the space you actually see: reach up into the
       row gap above, and stop where the images beside it end (above their
       captions) */
    .block--quote {
        margin-top: -60px; /* the row gap */
        margin-bottom: calc(12px + 1.1875rem * 1.35); /* a caption's height */
        padding: 20px 4% 20px 0;
    }

    /* Beside a tall image, make the quote's row exactly the height left
       beside it (a column width less a caption), so the tall image's extra
       height isn't shared out between both rows and the quote stays centred */
    .blocks {
        container-type: inline-size;
    }

    .block--tall + .block--quote {
        box-sizing: border-box;
        min-height: calc((100cqw - 6.5cqw) / 2 - (12px + 1.1875rem * 1.35));
    }
}

/* About page
   -------------------------------------------------------------------------- */
.about {
    width: min(100% - 2 * var(--gutter), var(--max-inner));
    margin: 40px auto 0;
}

/* Title and opening line, then the "chat" link: Matt's photo with a deep
   red "Chat with me about your project" label tucked behind it, the two
   together one link to the contact form. It follows the paragraphs below:
   in one column (up to 850px) it sits under the opening line, full width;
   from 851px, when they split into two columns, it moves beside the title
   and fills the second column. */
.about__chat {
    display: flex;
    align-items: center;
    width: 100%; /* full width under the text; its own size on desktop */
    margin-top: 32px;
    color: var(--cream);
    text-decoration: none;
}

.about__chat-label {
    display: flex;
    flex: 1 1 auto;
    justify-content: space-between; /* arrow by the photo */
    align-items: center;
    gap: 14px;
    min-width: 0;
    margin-right: -40px; /* runs in behind the photo */
    padding: 16px 52px 16px 20px;
    border-radius: 14px;
    background: var(--orange);
    box-shadow: 0 16px 30px -18px rgba(3, 31, 53, .55);
    transition: background-color var(--hover);
}

.about__chat-text {
    max-width: 11em;
    font-family: var(--font-display);
    font-size: 1.125rem;
    font-style: italic;
    font-weight: 500;
    line-height: 1.2;
}

.about__chat-arrow {
    flex: none;
    width: 32px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform .25s var(--ease-out);
}

.about__chat-arrow circle {
    stroke-opacity: .5;
    transition: fill var(--hover), stroke-opacity var(--hover);
}

.about__chat-arrow path {
    stroke-width: 2.5;
}

.about__chat:hover .about__chat-label {
    background: var(--dark);
}

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

.about__chat:hover .about__chat-arrow circle {
    fill: var(--cream);
    stroke-opacity: 1;
}

.about__chat:hover .about__chat-arrow path {
    stroke: var(--dark);
}

/* The photo: a round card that tilts towards the mouse in 3D (--rx, --ry),
   with the picture inside drifting the other way (--px, --py) so it seems
   to sit deeper, a soft light following the mouse (--lx, --ly) and the
   shadow moving away from it (--sx, --sy). initDepthPortrait sets the
   values; at rest it's flat. */
.about__portrait {
    position: relative;
    z-index: 1;
    flex: none;
    display: block;
    perspective: 650px;
}

.about__photo {
    position: relative;
    display: block;
    width: 112px;
    height: 112px;
    overflow: hidden;
    border-radius: 50%;
    box-shadow: var(--sx, 0px) calc(14px + var(--sy, 0px)) 30px -12px rgba(3, 31, 53, .5);
    transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
    isolation: isolate; /* keeps the round clip while it tilts */
}

.about__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1.16) translate(var(--px, 0px), var(--py, 0px));
}

.about__photo-light {
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at var(--lx, 50%) var(--ly, 30%), rgba(255, 255, 255, .32), transparent 60%);
    mix-blend-mode: soft-light;
    pointer-events: none;
}

/* the smallest phones: no room for the arrow, so the label keeps to two
   lines (the photo and label are still the link) */
@media (max-width: 399px) {
    .about__chat-arrow {
        display: none;
    }
}

@media (min-width: 770px) {
    .about__chat-label {
        gap: 18px;
        margin-right: -56px;
        padding: 22px 76px 22px 28px;
        border-radius: 16px;
    }

    .about__chat-text {
        font-size: 1.375rem;
    }

    .about__chat-arrow {
        width: 40px;
    }

    .about__photo {
        width: 150px;
        height: 150px;
    }
}

/* Two columns, like the paragraphs below */
@media (min-width: 851px) {
    .about__head {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: 8%;
        align-items: center;
    }

    .about__chat {
        margin-top: 0;
    }
}

/* …a narrower column until desktop: a smaller photo and label */
@media (min-width: 851px) and (max-width: 1279px) {
    .about__chat-label {
        gap: 12px;
        margin-right: -44px;
        padding: 18px 56px 18px 22px;
        border-radius: 14px;
    }

    .about__chat-text {
        font-size: 1.125rem;
    }

    .about__chat-arrow {
        width: 32px;
    }

    .about__photo {
        width: 120px;
        height: 120px;
    }
}

@media (min-width: 1280px) {
    .about__chat-label {
        gap: 22px;
        margin-right: -64px;
        padding: 26px 96px 26px 32px;
        border-radius: 18px;
    }

    .about__chat-text {
        font-size: 1.5rem;
    }

    .about__chat-arrow {
        width: 44px;
    }

    .about__photo {
        width: 188px;
        height: 188px;
    }
}

.about__lead {
    max-width: 34ch;
    text-wrap: balance; /* no single word left on the last line */
    font-size: clamp(1.375rem, 1.1rem + 1vw, 1.875rem);
    font-weight: 500;
    line-height: 1.35;
}

.about__text {
    display: grid;
    gap: 1.2em;
    margin-top: 32px;
    font-size: 1.0625rem;
}

.about__section {
    margin-top: var(--section-space);
}

/* A picture of real work above each service, linking to the project */
.about-pic {
    display: block;
    text-decoration: none;
}

.about-pic__media {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--white);
    box-shadow:
        0 2px 4px rgba(3, 31, 53, .06),
        0 18px 30px -18px rgba(3, 31, 53, .28);
    transition: transform .2s var(--ease), box-shadow .2s var(--ease);
}

.about-pic__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* artwork on white (e.g. a logo): show all of it, with breathing room */
.about-pic__media img.is-contain {
    padding: 6%;
    object-fit: contain;
}

.about-pic:hover .about-pic__media {
    transform: translateY(-4px);
    box-shadow:
        0 4px 8px rgba(3, 31, 53, .08),
        0 26px 36px -18px rgba(3, 31, 53, .34);
}

.service__pic {
    margin-bottom: 28px;
}

/* What I do: web, brand, print */
.services {
    display: grid;
    gap: 48px;
}

.service__title {
    margin-bottom: .4em;
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-style: italic;
    font-weight: 500;
    line-height: 1.1;
    color: var(--orange);
}

.service p {
    font-size: 1.0625rem;
}

.service__list {
    margin: 20px 0 0;
    padding: 0;
    list-style: none;
}

.service__list li {
    padding: .5em 0;
    border-top: 1px solid rgba(3, 31, 53, .14);
}

/* Why work with me */
.reasons {
    display: grid;
    gap: 32px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.reason__title {
    margin-bottom: .3em;
    font-size: 1.125rem;
    font-weight: 700;
}

.reason p {
    font-size: 1.0625rem;
}

/* Get in touch */
.about__cta {
    margin-block: var(--section-space);
    text-align: center;
}

.about__cta-text {
    font-family: var(--font-display);
    font-size: clamp(2rem, 1.5rem + 2vw, 3rem);
    font-style: italic;
    font-weight: 500;
    line-height: 1.1;
    color: var(--orange);
}

.about__cta-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 14px;
    margin-top: 28px;
}

@media (min-width: 770px) {
    .about__text,
    .service p,
    .reason p {
        font-size: 1.125rem;
    }

    .reasons {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 8%;
        row-gap: 40px;
    }
}

/* Columns from 851px, as the home and project pages */
@media (min-width: 851px) {
    .about__text {
        grid-template-columns: 1fr 1fr;
        column-gap: 8%;
    }

    .services {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        column-gap: 5%;
    }

    .reasons {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        column-gap: 5%;
    }
}

/* Cookie banner – a small card bottom-left (slim bar on phones). Accept and
   Reject look identical, so neither is nudged. Shown by initConsent.
   -------------------------------------------------------------------------- */
.cookie-banner {
    position: fixed;
    right: 12px;
    bottom: 12px;
    left: 12px;
    z-index: 80;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 16px;
    padding: 14px 16px;
    border-radius: 12px;
    background: var(--dark);
    color: var(--cream);
    box-shadow: 0 10px 30px rgba(3, 31, 53, .35);
    font-size: .875rem;
    line-height: 1.45;
    opacity: 0;
    translate: 0 16px;
    transition: opacity .4s var(--ease), translate .4s var(--ease);
}

.cookie-banner[hidden] {
    display: none;
}

.cookie-banner.is-visible {
    opacity: 1;
    translate: 0 0;
}

.cookie-banner__text {
    flex: 1 1 220px;
}

.cookie-banner__text a {
    color: var(--cream);
    text-decoration: underline;
    text-underline-offset: 2px;
    white-space: nowrap;
    transition: color var(--hover);
}

.cookie-banner__text a:hover {
    color: var(--yellow);
}

.cookie-banner__buttons {
    display: flex;
    gap: 10px;
}

.cookie-banner__btn {
    min-width: 84px;
    min-height: 38px;
    padding: 0 16px;
    border: 1px solid var(--cream);
    border-radius: 999px;
    background: none;
    color: var(--cream);
    font: inherit;
    cursor: pointer;
    transition: color var(--hover), background-color var(--hover), border-color var(--hover);
}

.cookie-banner__btn:hover {
    border-color: var(--yellow);
    background: var(--yellow);
    color: var(--dark);
}

.cookie-banner :focus-visible {
    outline: 2px solid var(--yellow);
    outline-offset: 3px;
}

@media (min-width: 770px) {
    .cookie-banner {
        right: auto;
        bottom: 20px;
        left: 20px;
        max-width: 440px;
        padding: 18px 20px;
    }
}

/* "Cookie settings" in the footer: a button that looks like the links */
.site-footer__cookies {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
    transition: color var(--hover);
}

.site-footer__cookies:hover {
    color: var(--yellow);
}

/* Coming soon (projects.php → coming_soon): blurred, labelled, not a link */
.tile--soon .tile__media img,
.tile--soon .tile__media video {
    filter: blur(18px) saturate(.85);
    transform: scale(1.12); /* hides the soft blurred edge */
}

.tile__soon {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 2;
    padding: .55em 1.3em;
    border-radius: 999px;
    background: var(--dark);
    color: var(--cream);
    font-family: var(--font-display);
    font-size: clamp(1.125rem, .9rem + 1vw, 1.75rem);
    font-style: italic;
    white-space: nowrap;
    transform: translate(-50%, -50%);
}

.tile--soon .tile__link {
    cursor: pointer;
}

/* …and on click, a little show (once, about 2.5 seconds – nothing loops, so
   it never looks like something loading):
   - the blurred picture sharpens for a teasing glimpse, then blurs again
   - a paper card pops in; a blue pencil draws a squiggle and a sparkle
   - "I'll show you soon!" springs in underneath */
.tile__soon,
.tile__sketch {
    transition: opacity .3s var(--ease), transform .3s var(--ease);
}

.tile__sketch {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 3;
    display: grid;
    justify-items: center;
    gap: 4px;
    width: min(88%, 360px);
    padding: 18px 22px 18px;
    border-radius: 14px;
    background: #fbf8f0;
    color: #2f63a8; /* the sticky notes' blue pencil */
    box-shadow: 0 18px 30px -16px rgba(3, 31, 53, .5);
    opacity: 0;
    transform: translate(-50%, -46%) rotate(-1.5deg);
    pointer-events: none;
}

.tile--soon.is-sketching .tile__soon {
    opacity: 0;
    transform: translate(-50%, -50%) scale(.9);
}

.tile--soon.is-sketching .tile__sketch {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(-1.5deg);
}

.tile__sketch-art {
    position: relative;
    width: 220px;
    height: 60px;
}

.tile__scribble {
    width: 100%;
    height: 100%;
    overflow: visible;
}

.tile__scribble path {
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
}

.tile__sparkle {
    transform-box: fill-box;
    transform-origin: 0 50%;
}

.tile__sparkle path {
    stroke: var(--orange);
}

/* the pencil's tip sits on the line as it draws */
.tile__pencil {
    position: absolute;
    top: 0;
    left: 0;
    width: 32px;
    height: 32px;
    offset-path: path("M8 42 C 26 6, 46 10, 54 34 S 82 56, 96 30 S 124 4, 138 28 S 166 54, 192 20");
    offset-anchor: 6% 94%;
    offset-rotate: 0deg;
    offset-distance: 100%;
}

.tile__pencil-body { fill: #e5b53a; }
.tile__pencil-band { fill: #c46a6a; }
.tile__pencil-tip  { fill: #f1d7b0; stroke: #2f63a8; stroke-width: 1; stroke-linejoin: round; }

.tile__sketch-text,
.tile__sketch-soon {
    font-family: "Caveat", "Comic Sans MS", cursive;
    line-height: 1.15;
    text-align: center;
}

.tile__sketch-text {
    font-size: 1.45rem;
    font-weight: 500;
    text-wrap: balance;
}

.tile__sketch-soon {
    font-size: 2rem;
    font-weight: 700;
    color: var(--orange);
}

@media (prefers-reduced-motion: no-preference) {
    .tile--soon.is-sketching .tile__media img,
    .tile--soon.is-sketching .tile__media video {
        animation: tile-peek 2.8s var(--ease) both;
    }

    .tile--soon.is-sketching .tile__sketch {
        animation: tile-pop .5s cubic-bezier(.2, 1.4, .4, 1) both;
    }

    .tile--soon.is-sketching .tile__scribble > path {
        animation: tile-draw 1.2s var(--ease) .3s both;
    }

    .tile--soon.is-sketching .tile__pencil {
        animation: tile-pencil 1.7s var(--ease) .3s both;
    }

    .tile--soon.is-sketching .tile__sparkle path {
        animation: tile-draw .3s var(--ease-out) 1.5s both;
    }

    .tile--soon.is-sketching .tile__sparkle path:nth-child(2) { animation-delay: 1.58s; }
    .tile--soon.is-sketching .tile__sparkle path:nth-child(3) { animation-delay: 1.66s; }

    .tile--soon.is-sketching .tile__sparkle {
        animation: tile-twinkle .5s var(--ease) 1.95s 2;
    }

    .tile--soon.is-sketching .tile__sketch-soon {
        animation: tile-spring .6s cubic-bezier(.2, 1.6, .4, 1) 1.7s both;
    }
}

/* a teasing glimpse: sharper for a moment, then blurred again */
@keyframes tile-peek {
    0%   { filter: blur(18px) saturate(.85); }
    40%  { filter: blur(5px) saturate(1); }
    55%  { filter: blur(5px) saturate(1); }
    100% { filter: blur(18px) saturate(.85); }
}

@keyframes tile-pop {
    from { opacity: 0; transform: translate(-50%, -40%) rotate(4deg) scale(.8); }
}

@keyframes tile-draw {
    from { stroke-dashoffset: 1; }
    to   { stroke-dashoffset: 0; }
}

@keyframes tile-pencil {
    0%   { offset-distance: 0%; transform: rotate(0deg); }
    70%  { offset-distance: 100%; transform: rotate(0deg); }
    80%  { offset-distance: 100%; transform: rotate(-14deg); } /* a flourish */
    90%  { offset-distance: 100%; transform: rotate(4deg); }
    100% { offset-distance: 100%; transform: rotate(0deg); }
}

@keyframes tile-twinkle {
    50% { transform: scale(1.35); }
}

@keyframes tile-spring {
    from { opacity: 0; transform: translateY(10px) scale(.6) rotate(-6deg); }
}

.tile--soon .tile__link:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 6px;
}


/* Archive project pages (archive/page.php): older Pixsion work, kept simple –
   a dark header with the name and what was done, then pictures and text in a
   narrower column (the old images are about 800px wide)
   -------------------------------------------------------------------------- */
.archive-hero__title {
    font-family: var(--font-display);
    font-size: clamp(2.25rem, 1.6rem + 2.4vw, 3.5rem);
    font-style: italic;
    font-weight: 500;
    line-height: 1.08;
    color: var(--brand-fg);
}

.archive-hero .project-hero__facts dd + dd {
    margin-top: .15em;
}

.archive {
    width: min(100% - 2 * var(--gutter), 860px);
}

.archive__image {
    margin: 40px 0;
}

.archive__image img {
    display: block;
    width: 100%;
    height: auto;
    box-shadow:
        0 2px 4px rgba(3, 31, 53, .06),
        0 18px 30px -18px rgba(3, 31, 53, .28);
}

.archive__image figcaption {
    margin-top: 12px;
    padding-left: 4px;
    font-family: var(--font-display);
    font-size: 1rem;
    font-style: italic;
    line-height: 1.35;
    color: var(--orange);
}

.archive__text {
    margin: 40px 0;
}

@media (min-width: 851px) {
    /* the same column as the page below: title over the first column of
       text, involvement over the second */
    .archive-hero .project-hero__inner {
        width: min(100% - 2 * var(--gutter), 860px);
        min-height: clamp(360px, 26vw, 460px);
        column-gap: 8%;
    }

    .archive-hero .project-hero__facts {
        padding-left: 0;
    }

    /* text flows down one column and into the next, as in the layout */
    .archive__text {
        display: block;
        columns: 2;
        column-gap: 8%;
    }

    .archive__text p {
        margin-bottom: 1.2em;
    }
}

/* Breadcrumb at the top of project and archive pages: above the back arrow on
   phones and tablets; on desktop, to the left of "Explore more work" */
.project__top--crumbs {
    flex-wrap: wrap;
    gap: 18px 24px;
}

.breadcrumb {
    flex-basis: 100%;
    font-size: .875rem;
}

.breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    margin: 0;
    padding: 0;
    list-style: none;
}

.breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-inline: .5em;
    opacity: .45;
}

.breadcrumb a {
    color: var(--orange);
    text-decoration: none;
    transition: color var(--hover);
}

.breadcrumb a:hover {
    color: var(--dark);
}

.breadcrumb [aria-current] {
    opacity: .75;
}

@media (min-width: 1280px) {
    .project__top--crumbs {
        flex-wrap: nowrap;
        justify-content: space-between;
        align-items: center;
    }

    .project__top--crumbs .breadcrumb {
        flex-basis: auto;
    }
}

/* Archive collection page (archive/index.php): the work tiles, smaller –
   one, two, then three across */
.page-archive-index .simple-page {
    width: min(100% - 2 * var(--gutter), var(--max));
}

/* A short line under a page title (work and archive pages) */
.page-title + .page-intro {
    margin: -24px 0 50px;
    font-size: 1.125rem;
}

.page-intro a {
    color: var(--orange);
    transition: color var(--hover);
}

.page-intro a:hover {
    color: var(--dark);
}

.archive-tiles {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 50px 5%;
}

.archive-tiles .tile__media {
    aspect-ratio: 795 / 374;
}

.archive-tiles .tile__media img {
    height: 100%;
    object-fit: cover;
}

.archive-tiles .tile__caption {
    gap: .2em;
}

@media (min-width: 600px) {
    .archive-tiles {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1100px) {
    .archive-tiles {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        row-gap: 60px;
    }
}

/* The link to the archive at the foot of the work page */
.archive-link {
    display: grid;
    justify-items: center;
    gap: 6px;
    margin: 110px auto 0;
    padding-top: 60px;
    border-top: 1px solid rgba(3, 31, 53, .14);
    text-align: center;
    text-decoration: none;
    color: var(--orange);
    transition: color var(--hover);
}

.archive-link__title {
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 1.6rem + 3.6vw, 4.5rem);
    font-style: italic;
    font-weight: 500;
    line-height: 1.05;
}

.archive-link__title span {
    display: inline-block;
    transition: transform .25s var(--ease-out);
}

.archive-link__when {
    font-size: .875rem;
    font-weight: 700;
    letter-spacing: .11em;
    text-transform: uppercase;
}

.archive-link:hover {
    color: var(--dark);
}

.archive-link:hover .archive-link__title span {
    transform: translateX(6px);
}

/* Simple pages (work, about, privacy, 404)
   -------------------------------------------------------------------------- */
.simple-page {
    width: min(100% - 2 * var(--gutter), var(--max-inner));
    margin: 40px auto 0;
}

.page-work .simple-page {
    width: min(100% - 2 * var(--gutter), var(--max));
}

.page-title {
    margin-bottom: 40px;
    font-size: clamp(2.5rem, 1.8rem + 2.6vw, 3.5rem);
}

.prose {
    max-width: 68ch;
    font-size: 1.0625rem;
}

.prose > * + * {
    margin-top: 1em;
}

.prose h2 {
    margin-top: 1.8em;
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-style: italic;
    font-weight: 500;
    color: var(--orange);
}

.prose a {
    color: var(--orange);
    text-underline-offset: .15em;
}

.prose a:hover {
    color: var(--dark);
}

.prose__small {
    font-size: .875rem;
    opacity: .75;
}

/* Sticky notes (includes/note.php, initStickyNotes in scripts/main.js)
   Design notes in blue pencil on slightly weathered, lined off-white paper,
   taped to the page. They always sit OVER the layout (never in the flow),
   and initStickyNotes hides any note that would cover text or run off the
   screen at the current size. When a note reaches the top of the screen it
   peels off and flutters down; it re-sticks 5s later.
   -------------------------------------------------------------------------- */
.note {
    --rot: -3deg;
    --pencil: #2f63a8;   /* designer's blue pencil */
    --rule: rgba(70, 125, 195, .2);
    position: absolute;
    z-index: 5;
    width: clamp(160px, 15vw, 210px);
    padding: 30px 20px 18px 22px;
    color: var(--pencil);
    font-family: "Caveat", "Comic Sans MS", cursive;
    /* paper: aged grain, gentle curl (darker edges, soft band across the
       middle), warm weathered rim, pale ruled lines, off-white base */
    background-color: #fbf8f0;
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .36 0 0 0 0 .25 0 0 0 .1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
        linear-gradient(90deg, rgba(3, 31, 53, .05), transparent 14%, transparent 86%, rgba(3, 31, 53, .06)),
        linear-gradient(transparent 38%, rgba(3, 31, 53, .035) 50%, transparent 62%),
        radial-gradient(ellipse at 50% 45%, transparent 62%, rgba(150, 120, 70, .09)),
        repeating-linear-gradient(transparent 0 27px, var(--rule) 27px 28px);
    background-position: 0 0, 0 0, 0 0, 0 0, 0 24px; /* rules sit just under each line of writing */
    background-size: 160px 160px, auto, auto, auto, auto;
    /* slightly curled bottom corners */
    border-radius: 2px 3px 14px 4px / 2px 3px 6px 3px;
    /* shadow only around the bottom third, as if the paper lifts */
    box-shadow:
        0 1px 1px rgba(3, 31, 53, .07),
        0 18px 16px -14px rgba(3, 31, 53, .32),
        8px 14px 14px -14px rgba(3, 31, 53, .22),
        -6px 14px 14px -14px rgba(3, 31, 53, .18);
    transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(var(--rot));
}

/* Matte sticky tape across the top, with torn ends */
.note::before {
    content: "";
    position: absolute;
    top: -13px;
    left: 50%;
    width: 92px;
    height: 28px;
    margin-left: -46px;
    background: linear-gradient(rgba(236, 229, 210, .78), rgba(214, 205, 182, .72));
    clip-path: polygon(0 8%, 6% 0, 12% 10%, 18% 2%, 82% 3%, 88% 10%, 94% 0, 100% 9%, 98% 30%, 100% 52%, 97% 74%, 100% 94%, 92% 100%, 86% 92%, 80% 100%, 18% 98%, 12% 90%, 6% 100%, 0 92%, 3% 70%, 0 48%, 3% 26%);
    transform: rotate(-3deg);
}

.note--yellow {
    background-color: #f8e58c;
}

.note__text {
    font-size: 1.5rem;
    font-weight: 500;
    line-height: 28px; /* sits on the ruled lines */
    text-shadow: 0 0 .6px rgba(47, 99, 168, .45); /* soft pencil edge */
}

.note__by {
    font-size: 1.35rem;
    line-height: 28px;
    text-align: right;
}

/* Mouse users can drag notes about */
@media (hover: hover) and (pointer: fine) {
    .note {
        cursor: grab;
        user-select: none;
    }

    .note.is-dragging {
        cursor: grabbing;
        box-shadow:
            0 1px 1px rgba(3, 31, 53, .07),
            0 28px 24px -16px rgba(3, 31, 53, .3),
            10px 20px 18px -16px rgba(3, 31, 53, .2),
            -8px 20px 18px -16px rgba(3, 31, 53, .16);
    }
}

/* Hidden where it would cover text (set by the script) */
.note.is-off {
    display: none;
}

/* Gone while its paper copy flutters down; back with a slap */
.note.is-gone {
    visibility: hidden;
}

.note.is-resticking {
    animation: note-restick .5s cubic-bezier(.2, 1.4, .4, 1);
}

@keyframes note-restick {
    from { opacity: 0; transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(calc(var(--rot) + 10deg)) scale(1.3); }
    60%  { opacity: 1; transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(calc(var(--rot) - 2deg)) scale(.96); }
}

/* The falling copy (positioned and moved by the script) */
.note--falling {
    z-index: 60;
    margin: 0;
    pointer-events: none;
    will-change: transform;
}

/* Where the home page notes sit – always over the layout --------------------
   Intro: lives inside the illustration's box (.intro__me) */
.note--intro {
    /* phones: in the empty space to the left of the illustration */
    /* (moves up and left as the screen widens, which frees more room) */
    right: calc(100% + clamp(12px, 46.5vw - 169px, 52px));
    bottom: calc(12% + clamp(-47px, 41.9vw - 210px, -11px));
}

/* Phones: the gap between the hero and the intro is tight, so the note
   (paper, writing, ruled lines and tape) is drawn about 15% smaller */
@media (max-width: 639px) {
    .note--intro {
        width: 136px;
        padding: 26px 17px 15px 19px;
        background-position: 0 0, 0 0, 0 0, 0 0, 0 20px;
        background-image:
            url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .36 0 0 0 0 .25 0 0 0 .1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
            linear-gradient(90deg, rgba(3, 31, 53, .05), transparent 14%, transparent 86%, rgba(3, 31, 53, .06)),
            linear-gradient(transparent 38%, rgba(3, 31, 53, .035) 50%, transparent 62%),
            radial-gradient(ellipse at 50% 45%, transparent 62%, rgba(150, 120, 70, .09)),
            repeating-linear-gradient(transparent 0 23px, var(--rule) 23px 24px);
    }

    .note--intro::before {
        top: -11px;
        width: 78px;
        height: 24px;
        margin-left: -39px;
    }

    .note--intro .note__text {
        font-size: 1.275rem;
        line-height: 24px;
    }

    .note--intro .note__by {
        font-size: 1.15rem;
        line-height: 24px;
    }
}

@media (min-width: 1280px) {
    /* desktop: in the gap between the intro text and the illustration */
    .note--intro {
        right: calc(100% + 40px);
        bottom: auto;
        top: 12%;
    }
}

/* Between those (640–1279px) the same note appears instead in the space
   to the right of "Selected work", just above the rule */
.section-head {
    position: relative;
}

.note--work {
    right: 3%;
    bottom: -26px; /* taped over the rule */
}

@media (min-width: 640px) and (max-width: 1279px) {
    .note--intro {
        display: none;
    }
}

@media (max-width: 639px), (min-width: 1280px) {
    .note--work {
        display: none;
    }
}

/* Project tile: stuck over the image's top-right corner */
.tile {
    position: relative;
}

.note--tile {
    top: -22px;
    right: 5%;
    width: clamp(150px, 13vw, 190px);
}

/* Client logos (includes/client-logos.php, initLogoMarquee in main.js)
   A full-width row of logos drifting across, fading out at the edges.
   -------------------------------------------------------------------------- */
.logos {
    margin-top: var(--section-space);
}

.logos__heading {
    font-size: clamp(1.75rem, 1.2rem + 1.6vw, 2.25rem); /* as "Looking for a designer?" */
    text-align: center;
}

.logos__window {
    margin-top: 18px;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

.logos__track {
    display: flex;
    width: max-content;
    margin: 0 auto;
    list-style: none;
}

.logos__item {
    flex: 0 0 auto;
    width: clamp(96px, 11vw, 150px);
    margin-right: clamp(36px, 6vw, 90px);
}

.logos__item img {
    width: 100%;
    opacity: .78;
    mix-blend-mode: multiply;
}

/* Moving (set by the script): starts from the left, no centring */
.logos__track.is-moving {
    margin: 0;
    will-change: transform;
}

/* "Let's make it happen." – depth zoom (as 05 in the lab): each word falls
   towards the screen in turn, starting huge and blurred and shrinking
   smoothly into sharp focus. Plays when the contact intro scrolls into view
   (its .is-revealed). */
.contact__heading--drop span {
    display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
    .js .contact__heading--drop span {
        opacity: 0;
    }

    .js .contact__intro.is-revealed .contact__heading--drop span {
        animation: heading-depth 1.1s cubic-bezier(.16, 1, .3, 1) calc(.1s + var(--i) * .16s) both;
    }
}

@keyframes heading-depth {
    from { opacity: 0; transform: scale(3.4); filter: blur(20px); }
    45%  { opacity: 1; }
    to   { opacity: 1; transform: none; filter: blur(0); }
}

/* "Visit the … website" on project pages: centred under the intro, in the
   client's brand colours, turning orange on hover */
.project__visit {
    margin: 40px 0;
    text-align: center;
}

.project__visit + .blocks {
    margin-top: 0;
}

.project__visit-button {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: .92em 1.6em;
    border-color: var(--brand-bg);
    background: var(--brand-bg);
    color: var(--brand-fg);
    font-weight: 600;
}

.project__visit-button:hover {
    border-color: var(--orange);
    background: var(--orange);
    color: var(--cream);
}

.project__visit-button span[aria-hidden] {
    transition: transform .25s var(--ease-out);
}

.project__visit-button:hover span[aria-hidden] {
    transform: translate(3px, -3px);
}

/* Pop-up gallery (project pages; initLightbox in main.js)
   -------------------------------------------------------------------------- */
.block__open {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
}

.block__open img {
    transition: transform .6s var(--ease-out);
}

.block__open:hover img {
    transform: scale(1.02);
}

/* The gallery: the client's brand colour wipes up the screen and the
   picture is unveiled from the bottom; changing slides wipes the next
   picture across in the direction of travel. Title top centre (level with
   the close button), counter bottom left, orange buttons bottom right.
   Three rows – top bar, picture, bottom bar – so nothing overlaps. */
.lightbox {
    --top: 88px;
    --bottom: 104px;
    --side: 40px;
    --d: 1;
    width: 100%; /* not 100vw: that runs under the page scrollbar */
    max-width: none;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;
    background: transparent;
    color: var(--brand-fg, var(--cream));
    isolation: isolate;
}

.lightbox::backdrop {
    background: transparent;
}

.lightbox[open] {
    display: grid;
    grid-template-rows: var(--top) minmax(0, 1fr) var(--bottom);
}

.lightbox__backdrop {
    position: fixed;
    inset: 0;
    z-index: -1;
    background: var(--brand-bg, var(--dark));
}

/* Top bar: title centred, kept clear of the close button */
.lightbox__top {
    display: grid;
    place-items: center;
    padding: 0 90px;
}

.lightbox__caption {
    font-family: var(--font-display);
    font-size: 1.125rem;
    font-style: italic;
    line-height: 1.3;
    text-align: center;
}

.lightbox__close {
    position: absolute;
    top: calc((var(--top) - 46px) / 2);
    right: var(--side);
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font-size: 2rem;
    line-height: 1;
    transition: color var(--hover);
}

.lightbox__close:hover {
    color: var(--orange);
}

/* The picture: two layers in one place, so one can wipe over the other */
.lightbox__stage {
    display: grid;
    place-items: center;
    min-height: 0;
    padding: 0 var(--side);
    overflow: hidden;
    /* sideways finger movements come to the gallery as swipes; up/down
       scrolling (tall images) and pinch-to-zoom still work as normal */
    touch-action: pan-y pinch-zoom;
}

.lightbox__img {
    grid-area: 1 / 1;
    max-width: 100%;
    max-height: calc(100dvh - var(--top) - var(--bottom));
    object-fit: contain;
    background: #fff; /* transparent artwork (e.g. logo animations) on white */
    box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
    /* a swipe shouldn't pick the picture up or select it */
    -webkit-user-drag: none;
    user-select: none;
    -webkit-touch-callout: none;
}

/* A layer that isn't showing takes no room (a tall one would otherwise
   stretch the picture area and push the next picture off-screen) */
.lightbox__img:not(.is-active):not(.is-leaving) {
    display: none;
}

.lightbox.is-back {
    --d: -1;
}

/* Let a flicked picture fly out over the bars (not clipped at the stage);
   tall pictures need the stage to scroll, so they stay clipped */
.lightbox:not(.is-tall) .lightbox__stage {
    overflow: visible;
}

/* Tall images: shown at a readable width and scrolled */
.lightbox.is-tall .lightbox__stage {
    place-items: start center;
    overflow: auto;
    overscroll-behavior: contain;
}

.lightbox__img.is-tall {
    width: min(100%, 820px);
    max-height: none;
}

/* Bottom bar: big counter left, buttons right */
.lightbox__bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 0 var(--side);
}

.lightbox__count {
    font-family: var(--font-display);
    font-size: 2.6rem;
    font-style: italic;
    line-height: 1;
    color: #fff;
}

.lightbox__nav {
    display: flex;
    gap: 10px;
}

.lightbox__btn {
    display: grid;
    place-items: center;
    width: 58px;
    height: 58px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #fff;
    color: var(--brand-bg, var(--dark));
    transition: transform .25s var(--ease-out), background-color var(--hover), color var(--hover);
}

.lightbox__btn:hover {
    transform: scale(1.1);
    background: var(--orange);
    color: #fff;
}

.lightbox__btn svg {
    width: 24px;
    height: 24px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.lightbox :focus-visible {
    outline: 2px solid var(--cream);
    outline-offset: 4px;
}

/* Opening: a spot of the brand colour grows from where you clicked to
   fill the screen, and the picture comes into focus. Changing pictures: the
   current one is flicked away with a spin and the next comes up from the
   pile (forwards flicks to the left, back to the right). */
@media (prefers-reduced-motion: no-preference) {
    .lightbox.is-revealing .lightbox__backdrop {
        animation: brand-spread .8s cubic-bezier(.65, 0, .35, 1) both;
    }

    .lightbox.is-revealing .lightbox__img.is-active {
        animation: brand-dissolve-in .7s var(--ease) .35s both;
    }

    .lightbox.is-revealing .lightbox__top,
    .lightbox.is-revealing .lightbox__bottom,
    .lightbox.is-revealing .lightbox__close {
        animation: lightbox-fade .4s var(--ease) .55s both;
    }

    .lightbox .is-leaving {
        z-index: 2;
        animation: flick-away .55s cubic-bezier(.5, 0, .75, 0) forwards;
    }

    .lightbox .is-entering {
        z-index: 0;
        animation: flick-up .5s var(--ease-out) .12s both;
    }

    .lightbox.is-closing {
        animation: lightbox-fade-out .25s var(--ease) forwards;
    }
}

@keyframes brand-spread {
    from { clip-path: circle(0 at var(--ox, 50%) var(--oy, 50%)); }
    to   { clip-path: circle(150% at var(--ox, 50%) var(--oy, 50%)); }
}

@keyframes brand-dissolve-in {
    from { opacity: 0; filter: blur(16px); }
}

@keyframes flick-away {
    to {
        opacity: 0;
        transform: translate(calc(var(--d) * -75vw), 10vh) rotate(calc(var(--d) * -20deg));
    }
}

@keyframes flick-up {
    from { opacity: 0; transform: translateY(24px) scale(.88) rotate(calc(var(--d) * 3deg)); }
}

@keyframes lightbox-fade {
    from { opacity: 0; }
}

@keyframes lightbox-fade-out {
    to { opacity: 0; }
}

/* Smaller screens: tighter bars and buttons */
@media (max-width: 769px) {
    .lightbox {
        --top: 72px;
        --bottom: 88px;
        --side: 16px;
    }

    .lightbox__top {
        padding: 0 64px;
    }

    .lightbox__caption {
        font-size: 1rem;
    }

    .lightbox__close {
        right: 10px;
    }

    .lightbox__count {
        font-size: 2rem;
    }

    .lightbox__btn {
        width: 50px;
        height: 50px;
    }
}

/* Short screens (e.g. a phone turned sideways): slimmer bars, so the
   picture keeps most of the height */
@media (max-height: 500px) {
    .lightbox {
        --top: 52px;
        --bottom: 60px;
    }

    .lightbox__close {
        top: 3px;
    }

    .lightbox__count {
        font-size: 1.6rem;
    }

    .lightbox__btn {
        width: 44px;
        height: 44px;
    }
}

/* Page behind the open gallery doesn't scroll (the class is on <html>,
   which holds the page scrollbar) */
.lightbox-is-open {
    overflow: hidden;
}

/* Previous / next project links (project pages) */
.project-nav {
    display: flex;
    justify-content: space-between;
    gap: 24px;
    margin-top: 70px;
}

.project-nav__link {
    display: grid;
    gap: 4px;
    text-decoration: none;
}

.project-nav__link--next {
    text-align: right;
}

.project-nav__label {
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: rgba(3, 31, 53, .6);
}

.project-nav__label span {
    display: inline-block;
    color: var(--orange);
    transition: transform .25s var(--ease-out);
}

.project-nav__client {
    font-family: var(--font-display);
    font-size: clamp(1.4rem, 1.1rem + 1vw, 2rem);
    font-style: italic;
    font-weight: 500;
    line-height: 1.15;
    color: var(--orange);
    transition: color var(--hover);
}

.project-nav__link:hover .project-nav__client {
    color: var(--dark);
}

.project-nav__link--prev:hover .project-nav__label span {
    transform: translateX(-4px);
}

.project-nav__link--next:hover .project-nav__label span {
    transform: translateX(4px);
}

/* The rule above "more work" now follows these links */
.project-nav + .lightbox + .project__others,
.project-nav + .project__others {
    margin-top: 50px;
}
