/* ==========================================================================
   We Do Development — warm organic system

   Colour carries the page instead of decorating it: baked clay, ochre and
   sage on a cream base, with whole sections filled edge to edge. Shapes are
   soft and slightly irregular. Sections sit close together so the page feels
   generous rather than empty.
   ========================================================================== */

@import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400..800&family=Instrument+Sans:ital,wght@0,400..700;1,400..600&family=JetBrains+Mono:wght@400;500&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500&family=Marcellus&display=swap");

:root {
    /* ── warm ground ──────────────────────────────────────────────────── */
    --cream: #fdf6ec;
    --cream-deep: #f7e8d5;
    --sand: #f0d9bd;

    /* ── clay (primary) ───────────────────────────────────────────────── */
    --clay-100: #fde8dc;
    --clay-200: #f9cbb0;
    --clay-300: #f2a97f;
    --clay-400: #e8834f;
    --clay-500: #b4491d; /* the workhorse — dark enough for cream text (4.9:1) */
    --clay-600: #9a3c17;
    --clay-700: #8d3715;
    --clay-800: #632711;
    --clay-bright: #d4622e; /* decorative only: shapes, dots, never text bg */

    /* ── ochre (secondary warm) ───────────────────────────────────────── */
    --ochre-200: #fbe3ab;
    --ochre-400: #f0b73f;
    --ochre-500: #dd9c1c;
    --ochre-700: #9c6a0e;

    /* ── sage (cool counterweight) ────────────────────────────────────── */
    --sage-100: #eef2e4;
    --sage-200: #dbe4c8;
    --sage-400: #a8bd85;
    --sage-500: #86a05f;
    --sage-600: #4d5f33; /* darkened so cream text clears 4.5:1 */
    --sage-700: #3d4c28;

    /* ── warm neutrals ────────────────────────────────────────────────── */
    --bark-900: #2a1f18; /* deep warm brown, near-black */
    --bark-800: #3d2e23;
    --bark-700: #574438;
    --bark-500: #6f5c4d; /* meets 4.5:1 on cream and on sand */
    --bark-300: #bfae9e;

    --text: var(--bark-900);
    --text-soft: var(--bark-700);
    --text-faint: var(--bark-500);
    --rule: color-mix(in srgb, var(--bark-900) 14%, transparent);

    /* ── type ─────────────────────────────────────────────────────────── */
    --display: "Bricolage Grotesque", system-ui, sans-serif;
    --body: "Instrument Sans", system-ui, sans-serif;
    --mono: "JetBrains Mono", ui-monospace, monospace;

    /* ── scale & rhythm ───────────────────────────────────────────────── */
    --gutter: clamp(1.25rem, 4vw, 3.5rem);
    --rhythm: clamp(
        3rem,
        5.5vw,
        5.25rem
    ); /* deliberately tighter than before */

    --step--1: clamp(0.8rem, 0.77rem + 0.14vw, 0.88rem);
    --step-0: clamp(1rem, 0.96rem + 0.2vw, 1.12rem);
    --step-1: clamp(1.18rem, 1.1rem + 0.4vw, 1.45rem);
    --step-2: clamp(1.5rem, 1.28rem + 1.1vw, 2.25rem);
    --step-3: clamp(1.95rem, 1.5rem + 2.2vw, 3.2rem);
    --step-4: clamp(2.5rem, 1.6rem + 4.4vw, 5.2rem);

    --r-sm: 10px;
    --r-md: 18px;
    --r-lg: 30px;
    --r-xl: 44px;
    --r-pill: 999px;
    /* irregular radii — the organic tell */
    --r-blob: 62% 38% 46% 54% / 54% 48% 52% 46%;

    --shadow-sm: 0 2px 8px color-mix(in srgb, var(--bark-900) 8%, transparent);
    --shadow-md: 0 8px 24px color-mix(in srgb, var(--bark-900) 12%, transparent);
    --shadow-lg: 0 20px 50px
        color-mix(in srgb, var(--bark-900) 16%, transparent);
}

/* ── base ───────────────────────────────────────────────────────────── */
*,
*::before,
*::after {
    box-sizing: border-box;
}
html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--cream);
    color: var(--text);
    font-family: var(--body);
    font-size: var(--step-0);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
    font-family: var(--display);
    font-weight: 600;
    line-height: 1.02;
    letter-spacing: -0.03em;
    margin: 0;
    text-wrap: balance;
}
h1 {
    font-size: var(--step-4);
    font-weight: 700;
    letter-spacing: -0.042em;
}
h2 {
    font-size: var(--step-3);
    font-weight: 650;
    letter-spacing: -0.035em;
}
h3 {
    font-size: var(--step-1);
    font-weight: 600;
}

p {
    margin: 0 0 1em;
}
p:last-child {
    margin-bottom: 0;
}

a {
    color: var(--clay-700);
    text-underline-offset: 0.2em;
}
a:hover {
    color: var(--clay-800);
}
img {
    display: block;
    max-width: 100%;
}
:focus {
    outline: none;
}
:focus-visible {
    outline: 3px solid var(--clay-500);
    outline-offset: 3px;
    border-radius: 4px;
}
::selection {
    background: var(--clay-200);
    color: var(--bark-900);
}

/* ── layout ─────────────────────────────────────────────────────────── */
.container {
    width: min(75rem, 100% - 2 * var(--gutter));
    margin-inline: auto;
}
.section {
    padding-block: var(--rhythm);
}
.section--tight {
    padding-block: calc(var(--rhythm) * 0.6);
}
.lead {
    font-size: var(--step-1);
    line-height: 1.5;
    color: var(--text-soft);
    max-width: 40ch;
}
.muted {
    color: var(--text-faint);
}

/* ── coloured bands ─────────────────────────────────────────────────── */
/* Full-bleed fills — the main device for keeping the page warm and full. */
.band {
    position: relative;
}
.band--cream {
    background: var(--cream-deep);
}
.band--sand {
    background: var(--sand);
}
.band--clay {
    background: var(--clay-500);
    color: var(--cream);
}
.band--sage {
    background: var(--sage-600);
    color: var(--cream);
}
.band--bark {
    background: var(--bark-900);
    color: var(--cream);
}

.band--clay h2,
.band--sage h2,
.band--bark h2,
.band--clay h3,
.band--sage h3,
.band--bark h3 {
    color: var(--cream);
}
.band--clay .lead,
.band--sage .lead {
    color: color-mix(in srgb, var(--cream) 88%, transparent);
}
.band--bark .lead {
    color: var(--bark-300);
}

/* soft curved transitions between bands */
.band--curved {
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    margin-top: calc(-1 * var(--r-sm));
}
/* Where the block before has its own fill (the services band, the project
   stage), overlap by the full radius so the corners show that fill and not
   the page behind it. The block before grows by the same amount, so the
   space you see stays the same. */
.band:has(+ .projects) {
    padding-bottom: calc(var(--r-xl) - var(--r-sm));
}
.projects + .band--curved {
    margin-top: calc(-1 * var(--r-xl));
}
.band--curved-both {
    border-radius: var(--r-xl);
}

/* organic blobs floating behind content */
.band__blob {
    position: absolute;
    border-radius: var(--r-blob);
    pointer-events: none;
    opacity: 0.5;
    animation: drift 18s ease-in-out infinite alternate;
}
@keyframes drift {
    to {
        transform: translate(14px, -18px) rotate(8deg) scale(1.06);
    }
}

/* ── eyebrow ────────────────────────────────────────────────────────── */
.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    font-family: var(--mono);
    font-size: var(--step--1);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--clay-700);
    background: var(--clay-100);
    padding: 0.45em 1em;
    border-radius: var(--r-pill);
    margin-bottom: 1.25rem;
}
.eyebrow--sage {
    color: var(--sage-700);
    background: var(--sage-200);
}
.band--clay .eyebrow,
.band--sage .eyebrow,
.band--bark .eyebrow {
    color: var(--cream);
    background: color-mix(in srgb, #ffffff 18%, transparent);
}

/* ── buttons ────────────────────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.6em;
    font-family: var(--body);
    font-weight: 600;
    font-size: var(--step-0);
    padding: 0.95em 1.9em;
    border: 2px solid transparent;
    border-radius: var(--r-pill);
    cursor: pointer;
    text-decoration: none;
    line-height: 1.2;
    transition:
        transform 0.2s cubic-bezier(0.34, 1.4, 0.64, 1),
        background-color 0.2s ease,
        box-shadow 0.2s ease;
}
.btn:hover {
    transform: translateY(-2px);
}
.btn:active {
    transform: translateY(0);
}

.btn--primary {
    background: var(--clay-500);
    color: var(--cream);
    box-shadow: var(--shadow-sm);
}
.btn--primary:hover {
    background: var(--clay-600);
    color: var(--cream);
    box-shadow: var(--shadow-md);
}

.btn--ghost {
    border-color: color-mix(in srgb, var(--bark-900) 22%, transparent);
    color: var(--text);
}
.btn--ghost:hover {
    border-color: var(--clay-500);
    color: var(--clay-700);
    background: var(--clay-100);
}

.btn--oncolor {
    background: var(--cream);
    color: var(--clay-700);
}
.btn--oncolor:hover {
    background: #fff;
    color: var(--clay-800);
}

/* WhatsApp green — kept at brand hue but dark enough for cream text */
.btn--whatsapp {
    background: #1d7a4c;
    color: var(--cream);
    justify-self: start;
    margin-top: 0.35rem;
}
.btn--whatsapp:hover {
    background: #15613b;
    color: var(--cream);
}

.btn__arrow {
    transition: transform 0.2s ease;
}
.btn:hover .btn__arrow {
    transform: translateX(3px);
}

/* ── header ─────────────────────────────────────────────────────────── */
.nav {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2.5vw, 2.25rem);
    padding-block: 1.35rem;
}
.nav-brand {
    margin-right: auto;
    display: inline-flex;
    align-items: center;
}
.nav-brand__logo {
    display: block;
    height: 32px;
    width: auto;
}
.nav-links {
    display: flex;
    gap: clamp(1rem, 2.2vw, 1.9rem);
    list-style: none;
    margin: 0;
    padding: 0;
}
.nav-links a {
    font-weight: 600;
    font-size: var(--step-0);
    text-decoration: none;
    color: var(--text-soft);
    padding: 0.4em 0.1em;
    position: relative;
}
.nav-links a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0.1em;
    height: 3px;
    border-radius: var(--r-pill);
    background: var(--clay-400);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.25s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.nav-links a:hover {
    color: var(--text);
}
.nav-links a:hover::after,
.nav-links a[aria-current="page"]::after {
    transform: scaleX(1);
    transform-origin: left;
}
.nav-links a[aria-current="page"] {
    color: var(--clay-700);
}

/* slightly smaller than a body button so it sits inside the nav bar */
.nav-cta {
    padding: 0.6em 1.35em;
    font-size: var(--step--1);
}

.lang {
    display: flex;
    gap: 2px;
    padding: 3px;
    background: var(--cream-deep);
    border-radius: var(--r-pill);
}
.lang a {
    font-size: var(--step--1);
    font-weight: 700;
    text-decoration: none;
    padding: 0.35em 0.85em;
    border-radius: var(--r-pill);
    color: var(--text-faint);
}
.lang a:hover {
    background: var(--clay-100);
    color: var(--clay-700);
}
.lang a.is-active {
    background: var(--clay-500);
    color: var(--cream);
}

/* ── mobile menu ────────────────────────────────────────────────────── */
/* On wide screens the menu wrapper drops out of the layout and the nav
   reads as one row. Below 52rem (and only when menu.js runs) it becomes a
   full-screen bark overlay: it opens as a circle out of the toggle, the
   labels decode from code glyphs and the current page sits in a clay block. */
.nav-menu {
    display: contents;
}
.nav-toggle,
.nav-links__num {
    display: none;
}

@media (max-width: 52rem) {
    .nav--js .nav-toggle {
        position: relative;
        z-index: 101;
        display: grid;
        place-content: center;
        gap: 5px;
        width: 48px;
        height: 48px;
        padding: 0;
        border: 0;
        border-radius: var(--r-pill);
        background: var(--bark-900);
        color: var(--cream);
        cursor: pointer;
        transition: background-color 0.3s ease, transform 0.2s ease;
    }
    .nav--js .nav-toggle:active {
        transform: scale(0.94);
    }
    .nav-toggle__bar {
        display: block;
        width: 20px;
        height: 2px;
        border-radius: 2px;
        background: currentColor;
        transition:
            transform 0.45s cubic-bezier(0.77, 0, 0.18, 1),
            opacity 0.2s ease,
            width 0.3s ease;
    }
    /* uneven bars at rest, so it reads as typed lines rather than a stock icon */
    .nav-toggle__bar:nth-child(2) {
        width: 14px;
        justify-self: end;
    }
    .nav--open .nav-toggle {
        background: var(--cream);
        color: var(--bark-900);
    }
    .nav--open .nav-toggle__bar:nth-child(1) {
        transform: translateY(7px) rotate(45deg);
    }
    .nav--open .nav-toggle__bar:nth-child(2) {
        width: 0;
        opacity: 0;
    }
    .nav--open .nav-toggle__bar:nth-child(3) {
        transform: translateY(-7px) rotate(-45deg);
    }

    .nav--js .nav-brand {
        position: relative;
        z-index: 101;
    }
    /* light logo on the dark overlay */
    .nav--js .nav-brand__logo {
        transition: filter 0.3s ease 0.15s;
    }
    .nav--open .nav-brand__logo {
        filter: invert(1);
    }

    .nav--js .nav-menu {
        position: fixed;
        inset: 0;
        z-index: 100; /* above the bands, which stack at 1 */
        display: flex;
        flex-direction: column;
        gap: 2rem;
        padding: 7rem var(--gutter) max(2rem, env(safe-area-inset-bottom));
        overflow-y: auto;
        background-color: var(--bark-900);
        background-image: radial-gradient(color-mix(in srgb, var(--cream) 9%, transparent) 1px, transparent 1.5px);
        background-size: 32px 32px;
        color: var(--cream);
        clip-path: circle(0 at var(--menu-x, 100%) var(--menu-y, 0));
        visibility: hidden;
        transition:
            clip-path 0.55s cubic-bezier(0.77, 0, 0.18, 1),
            visibility 0s linear 0.55s;
    }
    .nav--open .nav-menu {
        clip-path: circle(150% at var(--menu-x, 100%) var(--menu-y, 0));
        visibility: visible;
        transition:
            clip-path 0.7s cubic-bezier(0.77, 0, 0.18, 1),
            visibility 0s;
    }

    .nav--js .nav-links {
        flex-direction: column;
        gap: 0.25rem;
        margin-block: auto;
    }
    .nav--js .nav-links li {
        opacity: 0;
        transform: translateY(1.5rem);
        transition: opacity 0.2s ease, transform 0.2s ease;
    }
    .nav--open .nav-links li {
        opacity: 1;
        transform: none;
        transition:
            opacity 0.5s ease calc(0.25s + var(--i) * 70ms),
            transform 0.6s cubic-bezier(0.16, 1, 0.3, 1) calc(0.25s + var(--i) * 70ms);
    }
    .nav--js .nav-links a {
        display: flex;
        align-items: baseline;
        gap: 0.9rem;
        padding: 0.15em 0;
        color: var(--cream);
    }
    .nav--js .nav-links a::after {
        display: none;
    }
    .nav--js .nav-links__num {
        display: inline;
        font-family: var(--mono);
        font-size: var(--step--1);
        letter-spacing: 0.12em;
        color: color-mix(in srgb, var(--cream) 55%, transparent);
        min-width: 2.2ch;
    }
    .nav--js .nav-links__label {
        position: relative;
        padding: 0 0.15em;
        border-radius: var(--r-sm);
        font-family: var(--display);
        font-weight: 800;
        font-size: clamp(2.1rem, 10.5vw, 4.5rem);
        line-height: 1.05;
        text-transform: uppercase;
        letter-spacing: -0.01em;
        white-space: nowrap;
        /* a clay block wipes in from the left */
        background: linear-gradient(var(--clay-500), var(--clay-500)) no-repeat left / 0 100%;
        transition: background-size 0.35s cubic-bezier(0.77, 0, 0.18, 1);
    }
    .nav--js .nav-links a:hover .nav-links__label,
    .nav--js .nav-links a[aria-current="page"] .nav-links__label {
        background-size: 100% 100%;
    }
    /* keyboard focus gets its own ring, so it never reads as the current page */
    .nav--js .nav-links a:focus-visible {
        outline: none;
    }
    .nav--js .nav-links a:focus-visible .nav-links__label {
        outline: 3px solid var(--cream);
        outline-offset: 3px;
    }

    .nav--js .lang,
    .nav--js .nav-cta {
        opacity: 0;
        transition: opacity 0.2s ease;
    }
    .nav--open .lang,
    .nav--open .nav-cta {
        opacity: 1;
        transition: opacity 0.5s ease 0.6s;
    }
    .nav--js .lang {
        align-self: flex-start;
        background: color-mix(in srgb, var(--cream) 10%, transparent);
    }
    .nav--js .lang a {
        color: color-mix(in srgb, var(--cream) 75%, transparent);
    }
    .nav--js .lang a:hover {
        background: color-mix(in srgb, var(--cream) 16%, transparent);
        color: var(--cream);
    }
    .nav--js .nav-cta {
        padding: 0.95em 1.9em;
        font-size: var(--step-0);
    }
}

/* ── hero ───────────────────────────────────────────────────────────── */
.hero {
    position: relative;
    padding-block: clamp(2.5rem, 5vw, 4.5rem) clamp(2.5rem, 5vw, 4rem);
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
}
.hero__title {
    max-width: 14ch;
    margin-bottom: 1.35rem;
    container-type: inline-size;
}

/* Rotating words — warm clay. They share one grid cell, so the box is as
   tall as the longest phrase needs and nothing gets cut off; the overflow
   only clips the slide in and out. */
.rotator {
    display: grid;
    overflow: hidden;
    color: var(--clay-500);
    /* shrinks only as far as the longest phrase needs to stay on one line;
       a letter in the display face averages about 0.44em */
    font-size: min(1em, calc(100cqi / (var(--longest, 14) * 0.44)));
}
.rotator__word {
    grid-area: 1 / 1;
    opacity: 0;
    transform: translateY(105%);
}
.rotator__word.is-active {
    opacity: 1;
    transform: translateY(0);
}
.rotator--ready .rotator__word {
    transition:
        transform 0.58s cubic-bezier(0.34, 1.42, 0.64, 1),
        opacity 0.3s ease;
}
.rotator--ready .rotator__word.is-leaving {
    opacity: 0;
    transform: translateY(-105%);
    transition:
        transform 0.4s cubic-bezier(0.5, 0, 0.75, 0),
        opacity 0.24s ease;
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    margin-top: 1.9rem;
}

/* hero art — stacked organic shapes with a browser window on top */
.hero__art {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 22rem;
}
.hero__shape {
    position: absolute;
    border-radius: var(--r-blob);
    animation: drift 16s ease-in-out infinite alternate;
}
/* decorative only — no text sits on these, so the brighter tints are fine */
.hero__shape--1 {
    width: 68%;
    aspect-ratio: 1;
    background: var(--ochre-200);
    top: 2%;
    right: 6%;
}
.hero__shape--2 {
    width: 52%;
    aspect-ratio: 1;
    background: var(--sage-200);
    bottom: 4%;
    left: 2%;
    animation-delay: -6s;
}
.hero__shape--3 {
    width: 34%;
    aspect-ratio: 1;
    background: var(--clay-200);
    top: 38%;
    right: 44%;
    animation-delay: -11s;
}

/* The browser window on top of the shapes. Its screen holds one scene per
   rotating phrase (assets/js/hero-art.js shows the matching one). A scene's
   parts all animate in with `both` fill, so they replay every time it is
   shown and, with reduced motion, simply appear in their end state. */
.window {
    position: relative;
    z-index: 1;
    width: min(100%, 26rem);
    overflow: hidden;
    border-radius: var(--r-md);
    background: var(--cream);
    box-shadow: var(--shadow-lg);
    transform: rotate(-1.5deg);
}
.window__bar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0.7rem 1rem;
    background: var(--bark-900);
}
.window__dot {
    width: 9px;
    height: 9px;
    border-radius: var(--r-pill);
}
.window__dot:nth-child(1) {
    background: var(--clay-bright);
}
.window__dot:nth-child(2) {
    background: var(--ochre-400);
}
.window__dot:nth-child(3) {
    background: var(--sage-400);
}
.window__url {
    margin-left: 0.75rem;
    padding: 0.2em 0.9em;
    border-radius: var(--r-pill);
    background: color-mix(in srgb, #ffffff 8%, var(--bark-900));
    color: var(--bark-300);
    font-family: var(--mono);
    font-size: 0.68rem;
}
.window__screen {
    position: relative;
    aspect-ratio: 4 / 3;
    padding: 1.1rem 1.2rem;
    font-size: 0.8rem;
}
.scene {
    position: absolute;
    inset: 1.1rem 1.2rem;
    display: none;
}
.scene.is-active {
    display: block;
    animation: scene-in 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes scene-in {
    from {
        opacity: 0;
        transform: translateY(10px) scale(0.98);
    }
}
@keyframes pop {
    from {
        opacity: 0;
        transform: scale(0.6);
    }
}
@keyframes grow {
    from {
        transform: scaleX(0);
    }
}
@keyframes slide-in {
    from {
        opacity: 0;
        transform: translateX(40%);
    }
}

/* 1 · a site builds itself, then the cursor clicks its button */
.scene--build > * {
    position: absolute;
}
.sb-nav {
    inset: 0 0 auto;
    height: 10%;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6%;
    animation: scene-in 0.4s ease both;
}
.sb-nav::before {
    content: "";
    position: absolute;
    left: 0;
    width: 9%;
    height: 70%;
    border-radius: 4px;
    background: var(--clay-500);
}
.sb-nav i {
    width: 9%;
    height: 22%;
    border-radius: 3px;
    background: var(--bark-300);
}
.sb-line {
    left: 0;
    border-radius: 4px;
    transform-origin: left;
    animation: grow 0.55s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.sb-line--1 {
    top: 21%;
    width: 56%;
    height: 9%;
    background: var(--bark-900);
    animation-delay: 0.15s;
}
.sb-line--2 {
    top: 34%;
    width: 40%;
    height: 5%;
    background: var(--bark-300);
    animation-delay: 0.3s;
}
.sb-btn {
    top: 45%;
    left: 0;
    width: 24%;
    height: 9%;
    border-radius: var(--r-pill);
    background: var(--clay-500);
    animation: pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) 0.5s both;
}
.sb-btn::after {
    /* the click lands here */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--clay-500) 60%, transparent);
    animation: click-ring 0.6s ease-out 1.75s both;
}
@keyframes click-ring {
    to {
        box-shadow: 0 0 0 14px transparent;
    }
}
.sb-img {
    top: 16%;
    right: 0;
    width: 36%;
    height: 40%;
    border-radius: var(--r-sm);
    background:
        radial-gradient(circle at 70% 30%, var(--ochre-400) 0 14%, transparent 15%),
        linear-gradient(160deg, var(--sage-200), var(--sage-400));
    animation: reveal 0.6s cubic-bezier(0.77, 0, 0.18, 1) 0.4s both;
}
@keyframes reveal {
    from {
        clip-path: inset(0 0 100% 0 round var(--r-sm));
    }
    to {
        clip-path: inset(0 round var(--r-sm));
    }
}
.sb-cards {
    inset: auto 0 0;
    height: 32%;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6%;
}
.sb-cards i {
    border-radius: var(--r-sm);
    background: var(--cream-deep);
    border-top: 4px solid var(--clay-300);
    animation: pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.sb-cards i:nth-child(1) { animation-delay: 0.75s; }
.sb-cards i:nth-child(2) { animation-delay: 0.85s; border-top-color: var(--sage-400); }
.sb-cards i:nth-child(3) { animation-delay: 0.95s; border-top-color: var(--ochre-400); }
.sb-cursor {
    top: 50%;
    left: 15%;
    width: 9%;
    color: var(--bark-900);
    filter: drop-shadow(0 2px 3px rgb(0 0 0 / 0.25));
    animation: cursor 1.9s cubic-bezier(0.65, 0, 0.35, 1) 0.2s both;
}
@keyframes cursor {
    0% {
        opacity: 0;
        transform: translate(560%, 420%);
    }
    20% {
        opacity: 1;
    }
    80% {
        transform: translate(0, 0) scale(1);
    }
    86% {
        transform: translate(0, 0) scale(0.82);
    }
    94%,
    100% {
        transform: translate(0, 0) scale(1);
    }
}

/* 2 · a performance score running up to 100 */
@property --score {
    syntax: "<integer>";
    inherits: true;
    initial-value: 100;
}
.scene--speed.is-active {
    display: grid;
    justify-items: center;
    align-content: center;
    gap: 0.45rem;
}
.gauge {
    position: relative;
    display: grid;
    place-items: center;
    width: 44%;
    aspect-ratio: 1;
    animation: score 1.3s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
}
.gauge::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(var(--sage-500) calc(var(--score) * 1%), var(--cream-deep) 0);
    -webkit-mask: radial-gradient(farthest-side, transparent 78%, #000 80%);
    mask: radial-gradient(farthest-side, transparent 78%, #000 80%);
}
.gauge__num::after {
    counter-reset: score var(--score);
    content: counter(score);
    font-family: var(--display);
    font-size: 2.4rem;
    font-weight: 800;
    color: var(--sage-600);
}
@keyframes score {
    from {
        --score: 0;
    }
}
.speed__label {
    font-family: var(--display);
    font-weight: 700;
    font-size: 0.95rem;
}
.speed__load {
    font-family: var(--mono);
    font-size: 0.7rem;
    color: var(--text-faint);
}
.speed__load b {
    color: var(--text);
}
.speed__bar {
    width: 70%;
    height: 6px;
    overflow: hidden;
    border-radius: var(--r-pill);
    background: var(--cream-deep);
}
.speed__bar i {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--sage-500);
    transform-origin: left;
    animation: grow 0.5s cubic-bezier(0.5, 0, 0.2, 1) 0.1s both;
}

/* 3 · enquiries landing one after another, the count ticking up */
@property --leads {
    syntax: "<integer>";
    inherits: true;
    initial-value: 3;
}
.scene--leads.is-active {
    display: grid;
    align-content: center;
    gap: 0.55rem;
}
.leads__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.2rem;
    font-family: var(--display);
    font-weight: 700;
    font-size: 0.95rem;
}
.leads__count {
    display: grid;
    place-items: center;
    min-width: 1.6rem;
    height: 1.6rem;
    border-radius: var(--r-pill);
    background: var(--clay-500);
    color: var(--cream);
    font-family: var(--mono);
    font-size: 0.75rem;
    animation: leads 1.3s steps(3, end) 0.3s both;
}
.leads__count::after {
    counter-reset: leads var(--leads);
    content: "+" counter(leads);
}
@keyframes leads {
    from {
        --leads: 0;
    }
}
.inbox__item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--r-sm);
    background: var(--cream-deep);
    animation: slide-in 0.5s cubic-bezier(0.34, 1.4, 0.64, 1) calc(0.3s + var(--i) * 0.4s) both;
}
.inbox__icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: var(--r-pill);
    background: var(--clay-500);
    color: var(--cream);
}
.inbox__icon svg {
    width: 55%;
    height: 55%;
}
.inbox__text {
    display: grid;
    line-height: 1.25;
}
.inbox__text small {
    color: var(--text-faint);
    font-size: 0.7rem;
}

/* 4 · an uptime grid filling day by day, with one short blip */
.scene--uptime.is-active {
    display: grid;
    align-content: center;
    gap: 0.6rem;
}
.uptime__grid {
    display: grid;
    grid-template-columns: repeat(16, 1fr);
    gap: 4px;
}
.uptime__grid i {
    aspect-ratio: 1;
    border-radius: 3px;
    background: var(--sage-400);
    animation: pop 0.35s ease calc(var(--d) * 45ms) both;
}
.uptime__grid i:nth-child(43) {
    background: var(--ochre-400);
}
.uptime__score {
    font-family: var(--mono);
    font-size: 0.75rem;
    color: var(--text-faint);
}
.uptime__score b {
    margin-right: 0.25rem;
    font-family: var(--display);
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--sage-600);
}
.uptime__note {
    font-size: 0.75rem;
    color: var(--text-soft);
}

/* 5 · a key turns, then everything gets ticked off as yours */
.scene--own.is-active {
    display: grid;
    align-content: center;
    gap: 0.5rem;
}
.own__key {
    width: 13%;
    margin-bottom: 0.2rem;
    color: var(--ochre-500);
    animation: key 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes key {
    from {
        opacity: 0;
        transform: rotate(-120deg) scale(0.5);
    }
}
.own__row {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px dashed var(--rule);
    font-weight: 600;
    font-size: 0.9rem;
    animation: scene-in 0.35s ease calc(0.35s + var(--i) * 0.3s) both;
}
.own__tick {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--r-pill);
    background: var(--sage-500);
    color: var(--cream);
    font-size: 0.75rem;
    animation: pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) calc(0.45s + var(--i) * 0.3s) both;
}
.own__tag {
    margin-left: auto;
    padding: 0.1em 0.65em;
    border-radius: var(--r-pill);
    background: var(--clay-100);
    color: var(--clay-700);
    font-family: var(--mono);
    font-size: 0.68rem;
    animation: slide-in 0.4s ease calc(0.55s + var(--i) * 0.3s) both;
}

/* ── projects ───────────────────────────────────────────────────────── */
/* A contact sheet of client identities. Each plate is filled with the
   client's own colour so their logo reads the way it was designed; the
   caption underneath stays in our palette, so the page stays ours. */
.projects__intro {
    display: grid;
    grid-template-columns: 1.1fr 0.9fr;
    align-items: end;
    gap: 1.5rem 3rem;
    margin-bottom: clamp(2rem, 4vw, 3rem);
}
.projects__intro h2 {
    max-width: 19ch;
}
.projects__intro p {
    margin: 0;
    max-width: 42ch;
    color: var(--text-soft);
    font-size: var(--step-0);
}
.projects-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(1.75rem, 3vw, 2.5rem) clamp(0.85rem, 1.6vw, 1.25rem);
    margin: 0;
    padding: 0;
    list-style: none;
}
/* Homepage project ring (assets/js/ring.js). Without JS it is a row of
   cards that scrolls sideways; .ring--live turns it into the 3D ring on a
   stage that takes the colour of the client in front. The section intro
   sits on the stage too, so it takes on that colour along with it. */
/* The stage is a band like the others: rounded top tucked over the band
   before it, content lined up with the page container. */
.ring__stage {
    --ring-w: clamp(190px, 26vw, 330px);
    --ring-inset: max(var(--gutter), (100% - 75rem) / 2);
    position: relative;
    overflow: hidden;
    margin-top: calc(-1 * var(--r-xl));
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    background: var(--stage-bg, var(--cream-deep));
    color: var(--stage-ink, var(--text));
    transition:
        background-color 0.7s cubic-bezier(0.16, 1, 0.3, 1),
        color 0.4s ease;
}
.ring__track {
    display: flex;
    gap: clamp(0.85rem, 1.6vw, 1.25rem);
    margin: 0;
    padding: clamp(1.5rem, 3vw, 2.5rem) var(--ring-inset) var(--rhythm);
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
}
.ring__track .project {
    flex: 0 0 var(--ring-w);
    scroll-snap-align: center;
}
.ring__ghost,
.ring__bar[hidden] {
    display: none;
}

.ring__intro {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    align-items: end;
    gap: 1rem 3rem;
    padding: var(--rhythm) var(--ring-inset) 0;
}
.ring__title {
    max-width: 16ch;
    color: inherit;
}
.ring__lede p {
    margin: 0 0 1rem;
    max-width: 42ch;
    opacity: 0.85;
}
.ring__more {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.55em 1.15em;
    border: 2px solid color-mix(in srgb, currentColor 45%, transparent);
    border-radius: var(--r-pill);
    color: inherit;
    font-size: var(--step--1);
    font-weight: 600;
    text-decoration: none;
    transition:
        background-color 0.2s ease,
        color 0.2s ease,
        border-color 0.2s ease;
}
.ring__more:hover,
.ring__more:focus-visible {
    border-color: currentColor;
    background: var(--stage-ink, var(--text));
    color: var(--stage-bg, var(--cream));
}
.ring__more span {
    transition: transform 0.2s ease;
}
.ring__more:hover span {
    transform: translateX(3px);
}

/* Live: intro on top, the ring in the middle, the bar at the foot. The
   ring's band is sized off the plate (4:3, so 0.75 × its width) with the
   section rhythm above and below it, so the gaps match the rest of the
   page at every screen size instead of following the viewport height. */
.ring--live .ring__stage {
    display: grid;
}
.ring--live .ring__ghost {
    display: block;
    position: absolute;
    inset: 50% 0 auto;
    translate: 0 -50%;
    margin: 0;
    font-family: var(--display);
    font-weight: 800;
    line-height: 0.9;
    text-align: center;
    text-transform: uppercase;
    white-space: nowrap;
    letter-spacing: -0.02em;
    opacity: 0.13;
    pointer-events: none;
    user-select: none;
}
.ring--live .ring__viewport {
    position: relative;
    height: calc(var(--ring-w) * 0.75 + 2 * var(--rhythm));
    display: grid;
    place-items: center;
    perspective: 1500px;
    touch-action: pan-y;
    cursor: grab;
    user-select: none;
}
.ring--live.is-dragging .ring__viewport {
    cursor: grabbing;
}
.ring--live .ring__track {
    position: relative;
    display: block;
    width: var(--ring-w);
    aspect-ratio: 4 / 3;
    padding: 0;
    overflow: visible;
    transform-style: preserve-3d;
}
.ring--live .ring__track .project {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
}
.ring--live .project__link {
    -webkit-user-drag: none;
}
.ring--live .project__logo {
    pointer-events: none;
}
.ring--live .project__caption {
    /* the bar below says it for the front card */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
}
.ring--live .project__plate {
    box-shadow:
        0 30px 60px -24px rgb(0 0 0 / 0.45),
        inset 0 0 0 1px rgb(0 0 0 / 0.08);
}
/* the front card floats a little proud of the stage, which shares its colour */
.ring--live .project.is-front .project__plate {
    box-shadow:
        0 40px 80px -24px rgb(0 0 0 / 0.55),
        0 0 0 1px color-mix(in srgb, var(--stage-ink, var(--bark-900)) 18%, transparent);
}

.ring__bar {
    /* plus room for the curved band below, which tucks up over the stage */
    padding: 0 var(--ring-inset) calc(var(--rhythm) + var(--r-xl));
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: end;
    gap: 1rem clamp(1rem, 3vw, 2.5rem);
}
.ring__count,
.ring__hint {
    font-family: var(--mono);
    font-size: var(--step--1);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    opacity: 0.7;
}
.ring__count {
    padding-bottom: 0.35rem;
}
.ring__info {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}
/* Long names wrap to a second line rather than being cut off; the bar is
   anchored at the bottom, so an extra line grows upwards. */
.ring__name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
    font-family: var(--display);
    font-weight: 800;
    font-size: var(--step-2);
    line-height: 1.05;
    text-transform: uppercase;
}
.ring__meta {
    font-size: var(--step--1);
    line-height: 1.45;
    opacity: 0.8;
    max-width: 52ch;
}
.ring__nav {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
.ring__hint {
    margin-right: 0.6rem;
}
.ring__btn {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    padding: 0;
    border: 2px solid color-mix(in srgb, currentColor 45%, transparent);
    border-radius: var(--r-pill);
    background: transparent;
    color: inherit;
    font-size: 1.1rem;
    cursor: pointer;
    transition:
        background-color 0.2s ease,
        color 0.2s ease,
        border-color 0.2s ease,
        transform 0.2s ease;
}
.ring__btn:hover,
.ring__btn:focus-visible {
    border-color: currentColor;
    background: var(--stage-ink, var(--text));
    color: var(--stage-bg, var(--cream));
}
.ring__btn:active {
    transform: scale(0.94);
}
@media (max-width: 40rem) {
    .ring__stage {
        --ring-w: min(64vw, 260px);
    }
    .ring__intro {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.75rem;
    }
    .ring__bar {
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 0.75rem;
    }
    .ring__count,
    .ring__hint,
    .ring__meta {
        display: none;
    }
    .ring__name {
        font-size: clamp(1.2rem, 5.6vw, 1.5rem);
    }
}
.project,
.case,
.next-case {
    --plate: var(--cream-deep);
    --plate-ink: var(--bark-900);
    --logo-w: 62%;
    --logo-h: 52%;
    min-width: 0;
}
.project__link {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    color: var(--text);
    text-decoration: none;
}
.project__plate {
    display: grid;
    place-items: center;
    aspect-ratio: 4 / 3;
    padding: 1rem;
    border-radius: var(--r-lg);
    background: var(--plate);
    color: var(--plate-ink);
    transition: border-radius 0.45s ease;
}
.project__logo {
    width: var(--logo-w);
    height: var(--logo-h);
    object-fit: contain;
}
.project__wordmark {
    font-family: "Cormorant Garamond", Georgia, serif;
    font-size: clamp(1.5rem, 1rem + 1.6vw, 2.2rem);
    font-weight: 500;
    line-height: 1;
    text-align: center;
}
.project__caption {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding-inline: 0.25rem;
}
.project__title {
    margin: 0;
    font-family: var(--display);
    font-size: var(--step-1);
    font-weight: 650;
    line-height: 1.15;
    letter-spacing: -0.02em;
    text-decoration: underline transparent 0.08em;
    text-underline-offset: 0.18em;
    transition: text-decoration-color 0.2s ease;
}
.project__meta {
    font-size: var(--step--1);
    line-height: 1.45;
    color: var(--text-soft);
}
.project__status {
    font-size: var(--step--1);
    color: var(--clay-700);
}

/* Plates answer the pointer with the same blob morph as the service
   cards; the name underlines so it reads as the link it is. */
a.project__link:hover .project__plate,
a.project__link:focus-visible .project__plate,
a.next-case:hover .project__plate,
a.next-case:focus-visible .project__plate {
    border-radius: 44px 22px 40px 26px / 36px 26px 44px 22px;
}
a.project__link:hover .project__title,
a.project__link:focus-visible .project__title {
    text-decoration-color: var(--clay-500);
}
a.project__link:focus-visible,
a.next-case:focus-visible {
    outline: none;
}
a.project__link:focus-visible .project__plate,
a.next-case:focus-visible .project__plate {
    outline: 3px solid var(--clay-500);
    outline-offset: 4px;
}

/* Still being built: the plate is drawn as a draft rather than filled. */
.project--draft .project__plate {
    background: color-mix(in srgb, var(--plate) 55%, var(--cream));
    outline: 2px dashed color-mix(in srgb, var(--plate-ink) 35%, transparent);
    outline-offset: -10px;
}

/* ── per-client plates: colour taken from each client's own site ── */
.project--ak-projects {
    --plate: #303036;
    --logo-w: 34%;
    --logo-h: 46%;
}
.project--fza {
    --plate: #ffffff;
    --logo-w: 84%;
}
.project--fza .project__plate {
    box-shadow: inset 0 0 0 1px var(--rule);
}
.project--eeland-wm {
    --plate: #1a1b1e;
    --logo-w: 64%;
    --logo-h: 66%;
}
.project--pizza-punt-uit {
    --plate: #d2c2b0;
    --logo-w: 76%;
}
.project--tifareep {
    /* the logo file ships on solid black */
    --plate: #000000;
    --logo-w: 40%;
    --logo-h: 56%;
}
.project--by-genevieve {
    --plate: #f1d8d6;
    --plate-ink: #7d4c39;
}
.project--by-genevieve .project__wordmark {
    font-family: "Marcellus", Georgia, serif;
    font-weight: 400;
    letter-spacing: 0.04em;
}
.project--reuzelekker {
    --plate: #ffffff;
    --logo-w: 74%;
}
.project--reuzelekker .project__plate {
    box-shadow: inset 0 0 0 1px var(--rule);
}
.project--reuzelekker.project--draft .project__plate {
    /* keep the site's own white rather than the draft's cream wash */
    background: var(--plate);
    outline-color: color-mix(in srgb, #ff847c 60%, transparent);
}
.project--bla-marine {
    --plate: #3c6b78;
    --plate-ink: #faf8f4;
}

@media (max-width: 60rem) {
    .projects__intro {
        grid-template-columns: 1fr;
        gap: 0.75rem;
    }
}
@media (max-width: 44rem) {
    .projects-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (max-width: 30rem) {
    .project__plate {
        border-radius: var(--r-md);
    }
    .project__title {
        font-size: var(--step-0);
    }
}

/* ── case pages ─────────────────────────────────────────────────────── */
/* The client's plate, blown up, is the one loud thing on the page. The
   rest is a quiet reading column in our own palette. */
.case__hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: clamp(2rem, 5vw, 4.5rem);
    padding-block: calc(var(--rhythm) * 0.6) clamp(2rem, 4vw, 3rem);
}
.case__title {
    max-width: 14ch;
    margin: 1.25rem 0 1rem;
    font-size: var(--step-4);
    overflow-wrap: break-word;
    hyphens: auto;
}
.case__subtitle {
    display: block;
    max-width: 30ch;
    margin-top: 0.75rem;
    font-family: var(--body);
    font-size: var(--step-1);
    font-weight: 500;
    line-height: 1.35;
    letter-spacing: 0;
    color: var(--text-soft);
}
.case__heading .lead {
    margin-bottom: 1.75rem;
}
.case__soon {
    margin: 0;
    font-weight: 600;
    color: var(--clay-700);
}
.case__hero .project__plate {
    border-radius: var(--r-xl);
    padding: 2rem;
}
.case__hero .project__wordmark {
    font-size: clamp(2.2rem, 1.4rem + 3vw, 4rem);
}

.crumbs ol {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--step--1);
    color: var(--text-faint);
}
.crumbs li + li::before {
    content: "/";
    margin-right: 0.4rem;
    color: var(--bark-300);
}
.crumbs a {
    color: var(--text-soft);
    text-decoration: none;
}
.crumbs a:hover {
    color: var(--clay-700);
    text-decoration: underline;
}

.facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    gap: 1.25rem 2rem;
    margin: 0;
    padding-block: 1.5rem;
    border-block: 1px solid var(--rule);
}
.facts dt {
    font-size: var(--step--1);
    color: var(--text-faint);
}
.facts dd {
    margin: 0.25rem 0 0;
    font-weight: 550;
    line-height: 1.4;
}
.facts__link {
    display: block;
    width: fit-content;
    margin-top: 0.3rem;
    font-size: var(--step--1);
    font-weight: 600;
}

/* Hero devices: the client's site on a MacBook and an iPhone (one composed
   image per project, transparent around the devices), on a cream field. */
.devices {
    position: relative;
    margin: 0;
    padding: 9% 7% 7%;
}
.devices__backdrop {
    /* frames the devices with an even margin all round, in our own colour
       so the client's site is the only colour in the picture */
    position: absolute;
    inset: 0;
    border-radius: var(--r-xl);
    background: var(--cream-deep);
}
.project--draft .devices__backdrop {
    outline: 2px dashed color-mix(in srgb, var(--bark-900) 25%, transparent);
    outline-offset: -10px;
}
.devices__image {
    position: relative;
    display: block;
    width: 100%;
    height: auto;
    filter: drop-shadow(0 22px 36px color-mix(in srgb, #000 22%, transparent));
}

.case__body {
    display: grid;
    grid-template-columns: minmax(0, 40rem) minmax(0, 21rem);
    justify-content: space-between;
    align-items: start;
    gap: clamp(2.5rem, 6vw, 5rem);
}
.case__part + .case__part {
    margin-top: clamp(2.25rem, 4vw, 3rem);
}
.case__part h2 {
    margin-bottom: 0.9rem;
    font-size: var(--step-2);
}
.case__part p {
    max-width: 62ch;
    font-size: var(--step-0);
    line-height: 1.7;
}
.case__part p:last-child {
    margin-bottom: 0;
}
.case__features {
    position: sticky;
    top: 2rem;
    padding: clamp(1.5rem, 3vw, 2rem);
    border-radius: var(--r-lg);
    background: var(--cream-deep);
}
.case__features h2 {
    font-size: var(--step-1);
}
.case__features .ticks {
    margin-top: 1.1rem;
}

/* Next case: one more plate, so the page never ends in a dead end. */
.next-case {
    display: grid;
    grid-template-columns: minmax(8rem, 15rem) minmax(0, 1fr);
    align-items: center;
    gap: clamp(1.25rem, 3vw, 2.5rem);
    padding-block: 0 var(--rhythm);
    color: var(--text);
    text-decoration: none;
}
.next-case:hover {
    color: var(--text);
}
.next-case__text {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.next-case__label {
    font-size: var(--step--1);
    color: var(--text-faint);
}
.next-case__name {
    font-family: var(--display);
    font-size: var(--step-3);
    font-weight: 650;
    line-height: 1.05;
    letter-spacing: -0.03em;
    text-decoration: underline transparent 0.06em;
    text-underline-offset: 0.15em;
    transition: text-decoration-color 0.2s ease;
}
a.next-case:hover .next-case__name,
a.next-case:focus-visible .next-case__name {
    text-decoration-color: var(--clay-500);
}
.next-case__summary {
    max-width: 48ch;
    color: var(--text-soft);
}

@media (max-width: 60rem) {
    .case__hero,
    .case__body {
        grid-template-columns: minmax(0, 1fr);
    }
    .case__features {
        position: static;
    }
}
@media (max-width: 40rem) {
    .next-case {
        grid-template-columns: 7rem minmax(0, 1fr);
    }
    .next-case__name {
        font-size: var(--step-2);
    }
    .case__hero .project__plate {
        border-radius: var(--r-lg);
    }
}

/* ── stats ──────────────────────────────────────────────────────────── */
.stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1rem, 2.5vw, 2rem);
}
.stat {
    background: var(--cream);
    border-radius: var(--r-lg);
    padding: clamp(1.35rem, 2.5vw, 1.9rem);
    border: 2px solid transparent;
    transition:
        transform 0.25s cubic-bezier(0.34, 1.35, 0.64, 1),
        border-color 0.25s ease;
}
.stat:hover {
    transform: translateY(-3px);
    border-color: var(--clay-200);
}
.stat__value {
    font-family: var(--display);
    font-size: var(--step-3);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.04em;
    color: var(--clay-600);
}
.stat:nth-child(2) .stat__value {
    color: var(--sage-600);
}
.stat:nth-child(3) .stat__value {
    color: #8a5c0c;
} /* ochre deep enough on cream */
.stat__label {
    margin-top: 0.4rem;
    font-size: var(--step--1);
    color: var(--text-faint);
    font-weight: 500;
}

/* ── cards ──────────────────────────────────────────────────────────── */
.grid-3 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1rem, 2.2vw, 1.6rem);
}
.card {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    background: var(--cream);
    border-radius: var(--r-lg);
    padding: clamp(1.5rem, 2.8vw, 2.1rem);
    transition:
        transform 0.28s cubic-bezier(0.34, 1.35, 0.64, 1),
        box-shadow 0.28s ease;
}
.card:hover {
    transform: translateY(-5px);
    box-shadow: var(--shadow-md);
}
.card__mark {
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--r-blob);
    background: var(--clay-500);
    color: var(--cream);
    margin-bottom: 0.35rem;
    transition: border-radius 0.4s ease;
}
.card:hover .card__mark {
    border-radius: 46% 54% 58% 42% / 42% 56% 44% 58%;
}
.card:nth-child(2) .card__mark {
    background: var(--sage-600);
}
.card:nth-child(3) .card__mark {
    background: #8a5c0c;
}
.card__mark svg {
    width: 1.45rem;
    height: 1.45rem;
}
.card__title {
    font-family: var(--display);
    font-size: var(--step-1);
    font-weight: 650;
}
.card__body {
    margin: 0;
    font-size: var(--step-0);
    color: var(--text-soft);
}

/* ── steps ──────────────────────────────────────────────────────────── */
.steps {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: clamp(1rem, 2.2vw, 1.75rem);
}
.step {
    position: relative;
}
.step__num {
    display: grid;
    place-items: center;
    width: 2.4rem;
    height: 2.4rem;
    margin-bottom: 0.8rem;
    border-radius: var(--r-blob);
    background: color-mix(in srgb, #ffffff 22%, transparent);
    font-family: var(--mono);
    font-size: var(--step--1);
    font-weight: 500;
}
.step__title {
    font-family: var(--display);
    font-size: var(--step-1);
    font-weight: 650;
    margin-bottom: 0.35rem;
}
.step__body {
    margin: 0;
    font-size: var(--step-0);
    opacity: 0.88;
}

/* ── split ──────────────────────────────────────────────────────────── */
.split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1.75rem, 4vw, 3.5rem);
    align-items: center;
}
.ticks {
    list-style: none;
    margin: 1.5rem 0 0;
    padding: 0;
    display: grid;
    gap: 0.7rem;
}
.ticks li {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    font-size: var(--step-0);
}
.ticks li::before {
    content: "";
    flex: none;
    width: 1.4rem;
    height: 1.4rem;
    margin-top: 0.1rem;
    border-radius: var(--r-blob);
    background: var(--clay-300);
}
.ticks li:nth-child(2)::before {
    background: var(--sage-400);
}
.ticks li:nth-child(3)::before {
    background: var(--ochre-400);
}

/* ── deploy panel ───────────────────────────────────────────────────── */
.deploy {
    background: var(--bark-900);
    color: var(--bark-300);
    border-radius: var(--r-lg);
    padding: clamp(1.25rem, 2.5vw, 1.75rem);
    font-family: var(--mono);
    font-size: var(--step--1);
    box-shadow: var(--shadow-lg);
    display: grid;
    gap: 0.9rem;
}
.deploy__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid color-mix(in srgb, #ffffff 12%, transparent);
}
.deploy__pulse {
    width: 8px;
    height: 8px;
    border-radius: var(--r-pill);
    flex: none;
    background: var(--sage-400);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--sage-400) 70%, transparent);
    animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
    70% {
        box-shadow: 0 0 0 7px transparent;
    }
    100% {
        box-shadow: 0 0 0 0 transparent;
    }
}
.deploy__branch {
    color: var(--clay-300);
}
.deploy__status {
    margin-left: auto;
    color: var(--bark-500);
}
.deploy__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.6rem;
}
.deploy__list li {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}
.deploy__list b {
    color: var(--cream);
    font-weight: 500;
}
.deploy__ok {
    color: var(--sage-400);
}
.deploy__meta {
    margin-left: auto;
    color: var(--bark-500);
    white-space: nowrap;
    font-size: 0.72rem;
}
.deploy__foot {
    display: flex;
    gap: 1.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid color-mix(in srgb, #ffffff 12%, transparent);
    font-size: 0.72rem;
    color: var(--bark-500);
}
.deploy__foot b {
    color: var(--sage-400);
    font-weight: 500;
}

/* ── chips ──────────────────────────────────────────────────────────── */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    list-style: none;
    margin: 0;
    padding: 0;
}
.chips li {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    font-weight: 600;
    font-size: var(--step--1);
    padding: 0.55em 1.15em;
    border-radius: var(--r-pill);
    background: var(--cream);
    color: var(--text-soft);
    transition:
        transform 0.2s cubic-bezier(0.34, 1.4, 0.64, 1),
        color 0.2s ease,
        background-color 0.2s ease;
}
/* On hover the chip picks up its tool's brand colour. --brand falls back to
   clay so an unmapped tool still behaves like the rest of the site. */
.chips li:hover {
    transform: translateY(-2px);
    background: color-mix(in srgb, var(--brand, var(--clay-500)) 12%, var(--cream));
    color: var(--brand, var(--clay-700));
}
.chips__icon {
    width: 1.15em;
    height: 1.15em;
    flex: none;
    /* icon carries the brand colour at rest; the label stays neutral */
    color: var(--brand, var(--text-faint));
    transition: color 0.2s ease;
}
/* an unmatched tool name renders an empty <svg>; collapse it so the gap doesn't show */
.chips__icon:empty {
    display: none;
}

/* Brand hues, darkened where needed so they clear 4.5:1 on cream. */
.chip--symfony    { --brand: #1a1a1a; }
.chip--react      { --brand: #0b7c8c; }  /* React cyan is too light at brand value */
.chip--shopify    { --brand: #4a7c22; }
.chip--typescript { --brand: #2563b0; }
.chip--vue        { --brand: #35735a; }
.chip--nuxt       { --brand: #00654a; }
.chip--laravel    { --brand: #c0341d; }
.chip--wordpress  { --brand: #1c6a91; }

/* ── faq ────────────────────────────────────────────────────────────── */
/* Opens like the mobile menu: a bark panel grows as a circle out of the
   plus and the answer slides open beneath it, where the browser can
   animate to auto height. Closed rows are cream cards that cast a shadow
   on hover. */
.faq {
    display: grid;
    gap: 0.7rem;
}
.faq details {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    background: var(--cream);
    border-radius: var(--r-md);
}
.faq details::before {
    /* the panel; its circle starts where the plus sits */
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: var(--bark-900);
    background-image: radial-gradient(color-mix(in srgb, var(--cream) 9%, transparent) 1px, transparent 1.5px);
    background-size: 28px 28px;
    clip-path: circle(0 at calc(100% - 2.6rem) 2.1rem);
    transition: clip-path 0.55s cubic-bezier(0.77, 0, 0.18, 1);
}
.faq details[open]::before {
    clip-path: circle(150% at calc(100% - 2.6rem) 2.1rem);
    transition-duration: 0.7s;
}
/* (the rows also carry data-reveal, which owns their transform) */
.faq details:not([open]):hover {
    box-shadow: var(--shadow-md);
}
.faq summary {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.1rem clamp(1.15rem, 2.2vw, 1.7rem);
    cursor: pointer;
    list-style: none;
    font-family: var(--display);
    font-weight: 600;
    font-size: var(--step-1);
    transition: color 0.3s ease 0.1s;
}
.faq summary::-webkit-details-marker {
    display: none;
}
.faq__num {
    flex: none;
    font-family: var(--mono);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.12em;
    color: var(--clay-500);
    transition: color 0.3s ease 0.1s;
}
.faq summary::after {
    content: "+";
    display: grid;
    place-items: center;
    flex: none;
    width: 2.4rem;
    height: 2.4rem;
    margin-left: auto;
    border-radius: var(--r-pill);
    background: var(--clay-100);
    color: var(--clay-700);
    font-family: var(--mono);
    font-size: 1.25rem;
    transition:
        transform 0.45s cubic-bezier(0.34, 1.4, 0.64, 1),
        background-color 0.3s ease,
        color 0.3s ease;
}
.faq details[open] summary {
    color: var(--cream);
}
.faq details[open] .faq__num {
    color: var(--clay-300);
}
.faq details[open] summary::after {
    transform: rotate(135deg);
    background: var(--clay-500);
    color: var(--cream);
}
.faq details p {
    margin: 0;
    padding: 0 clamp(1.15rem, 2.2vw, 1.7rem) 1.4rem calc(clamp(1.15rem, 2.2vw, 1.7rem) + 2.2ch + 1rem);
    color: color-mix(in srgb, var(--cream) 85%, transparent);
    /* the panel spans the full grid, but the answer keeps a readable measure */
    max-width: calc(62ch + 5rem);
}
.faq details[open] p {
    animation: faq-answer 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.2s backwards;
}
@keyframes faq-answer {
    from {
        opacity: 0;
        transform: translateY(0.75rem);
    }
}
@supports (interpolate-size: allow-keywords) {
    .faq {
        interpolate-size: allow-keywords;
    }
    .faq details::details-content {
        block-size: 0;
        overflow: hidden;
        transition:
            block-size 0.5s cubic-bezier(0.77, 0, 0.18, 1),
            content-visibility 0.5s allow-discrete;
    }
    .faq details[open]::details-content {
        block-size: auto;
    }
}

/* ── banner ─────────────────────────────────────────────────────────── */
.banner {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(1.5rem, 3vw, 2.5rem);
    border-radius: var(--r-xl);
    padding: clamp(2rem, 4vw, 3.25rem);
    background: var(--clay-500);
    color: var(--cream);
}
.banner--sage {
    background: var(--sage-600);
}
.banner h2 {
    max-width: 18ch;
}
.banner p {
    margin: 0.5rem 0 0;
    max-width: 42ch;
    color: color-mix(in srgb, var(--cream) 88%, transparent);
}
.banner .btn {
    margin-left: auto;
}
.banner__blob {
    position: absolute;
    width: 22rem;
    aspect-ratio: 1;
    right: -6rem;
    top: -8rem;
    border-radius: var(--r-blob);
    background: color-mix(in srgb, #ffffff 12%, transparent);
    pointer-events: none;
    animation: drift 20s ease-in-out infinite alternate;
}
.banner > *:not(.banner__blob) {
    position: relative;
    z-index: 1;
}

/* ── plans ──────────────────────────────────────────────────────────── */
.plans {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1rem, 2.2vw, 1.6rem);
    align-items: start;
}
.plan {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
    background: var(--cream);
    border-radius: var(--r-lg);
    padding: clamp(1.5rem, 2.8vw, 2.1rem);
    border: 2px solid transparent;
    transition:
        transform 0.25s cubic-bezier(0.34, 1.35, 0.64, 1),
        box-shadow 0.25s ease;
}
.plan:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
}
.plan--featured {
    background: var(--clay-500);
    color: var(--cream);
    box-shadow: var(--shadow-md);
}
.plan__head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}
.plan__name {
    font-family: var(--display);
    font-size: var(--step-1);
    font-weight: 650;
}
.plan__badge {
    font-family: var(--mono);
    font-size: 0.68rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    background: var(--cream);
    color: var(--clay-700);
    padding: 0.3em 0.8em;
    border-radius: var(--r-pill);
}
.plan__price {
    font-family: var(--display);
    font-size: var(--step-3);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.04em;
}
.plan__note {
    margin: 0;
    font-size: var(--step--1);
    color: var(--text-faint);
}
.plan--featured .plan__note {
    color: var(--clay-100);
}
.plan__features {
    list-style: none;
    margin: 0.5rem 0 auto;
    padding: 0;
    display: grid;
    gap: 0.5rem;
    font-size: var(--step-0);
}
.plan__features li {
    display: flex;
    gap: 0.6rem;
    align-items: flex-start;
}
.plan__features li::before {
    content: "✓";
    color: var(--sage-600);
    flex: none;
    font-weight: 700;
}
/* sage on clay fails contrast — use the cream the rest of the card already uses */
.plan--featured .plan__features li::before {
    color: var(--cream);
    opacity: 0.9;
}
.plan .btn {
    margin-top: 1.25rem;
    width: 100%;
}

/* ── table ──────────────────────────────────────────────────────────── */
.table-wrap {
    background: var(--cream);
    border-radius: var(--r-lg);
    overflow: hidden;
    overflow-x: auto;
}
.table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--step-0);
}
.table th {
    text-align: left;
    font-family: var(--mono);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-faint);
    padding: 1rem clamp(1rem, 2vw, 1.6rem);
    border-bottom: 2px solid var(--rule);
    white-space: nowrap;
}
.table td {
    padding: 0.95rem clamp(1rem, 2vw, 1.6rem);
    border-bottom: 1px solid var(--rule);
    color: var(--text-soft);
}
.table td:first-child {
    color: var(--text);
    font-weight: 500;
}
.table tbody tr:last-child td {
    border-bottom: 0;
}

/* ── forms ──────────────────────────────────────────────────────────── */
.form {
    display: grid;
    gap: 1.1rem;
    max-width: 40rem;
}
.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.1rem;
}
.field {
    display: grid;
    gap: 0.35rem;
}
.field label {
    font-size: var(--step--1);
    font-weight: 600;
    color: var(--text-soft);
}
.input {
    width: 100%;
    font: inherit;
    font-size: var(--step-0);
    padding: 0.8em 1.1em;
    color: var(--text);
    caret-color: var(--clay-500);
    background: var(--cream);
    border: 2px solid transparent;
    border-radius: var(--r-md);
    transition:
        border-color 0.2s ease,
        background-color 0.2s ease;
}
.input::placeholder {
    color: var(--bark-300);
}
.input:hover {
    border-color: var(--clay-200);
}
.input:focus-visible {
    outline: none;
    border-color: var(--clay-500);
}
textarea.input {
    min-height: 8rem;
    resize: vertical;
}
/* Honeypot wrapper. Unlike .visually-hidden this hides the field from screen
   readers too — it is bait for bots, so nobody should ever reach it. Kept out
   of the layout entirely rather than with display:none, because some bots skip
   fields that are literally undisplayed. */
.hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
.form-error {
    font-size: var(--step--1);
    color: var(--clay-700);
    font-weight: 500;
}
.form-error ul {
    margin: 0;
    padding-left: 1.1rem;
}
.flash {
    padding: 1rem 1.4rem;
    margin-bottom: 1.75rem;
    border-radius: var(--r-md);
    background: var(--sage-200);
    color: var(--sage-700);
    font-weight: 500;
}

/* ── contact aside ──────────────────────────────────────────────────── */
.contact {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: clamp(1.75rem, 4vw, 3.5rem);
    align-items: start;
}
.info {
    background: var(--cream);
    border-radius: var(--r-lg);
    padding: clamp(1.5rem, 2.8vw, 2rem);
    display: grid;
    gap: 0.9rem;
}
.info--sage {
    background: var(--sage-200);
}
.info__title {
    font-family: var(--display);
    font-size: var(--step-1);
    font-weight: 650;
}
.info__lines {
    line-height: 1.9;
}
.info__big {
    font-size: var(--step-1);
    font-weight: 600;
}
/* ── socials ────────────────────────────────────────────────────────── */
.socials {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    margin: 0.35rem 0 0;
    padding: 0;
}
.socials a {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    font-size: var(--step--1);
    font-weight: 600;
    text-decoration: none;
    padding: 0.5em 1em;
    border-radius: var(--r-pill);
    background: var(--clay-100);
    color: var(--clay-700);
    transition:
        background-color 0.2s ease,
        transform 0.2s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.socials a:hover {
    background: var(--clay-200);
    color: var(--clay-800);
    transform: translateY(-2px);
}
.socials__icon {
    width: 1em;
    height: 1em;
    flex: none;
}
/* Icon-only pills (X) need even padding on all sides, not the narrower inline
   padding a labelled pill uses — otherwise the mark sits in a cramped oval. */
.socials a:has(.visually-hidden) {
    padding: 0.6em;
    width: 2.4em;
    height: 2.4em;
    justify-content: center;
    gap: 0;
}
.socials a:has(.visually-hidden) .socials__icon {
    width: 0.95em;
    height: 0.95em;
}

/* keeps the label for screen readers while hiding it visually */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* icon-only variant for the footer */
.socials--plain a {
    background: none;
    padding: 0.45em;
    color: var(--text-faint);
}
.socials--plain a:hover {
    background: var(--clay-100);
    color: var(--clay-700);
}
.socials--plain .socials__icon {
    width: 1.15rem;
    height: 1.15rem;
}

/* ── footer ─────────────────────────────────────────────────────────── */
.site-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 2rem;
    padding-block: 1.75rem 2.5rem;
    font-size: var(--step--1);
    color: var(--text-faint);
}
.site-footer__brand {
    display: inline-flex;
}
.site-footer__logo {
    height: 24px;
    width: auto;
}
/* socials and the copyright line share the right-hand end */
.site-footer__right {
    margin-left: auto;
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.25rem;
}
.site-footer__right .socials {
    margin: 0;
}

/* ── scroll reveal ──────────────────────────────────────────────────── */
.reveal-armed [data-reveal] {
    opacity: 0;
    transform: translateY(1rem);
    transition:
        opacity 0.6s ease,
        transform 0.6s cubic-bezier(0.34, 1.3, 0.64, 1);
}
.reveal-armed [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
}
.reveal-armed [data-reveal][style*="--i"] {
    transition-delay: calc(var(--i) * 70ms);
}

/* ── responsive ─────────────────────────────────────────────────────── */
@media (max-width: 60rem) {
    .hero,
    .split,
    .contact {
        grid-template-columns: 1fr;
    }
    .grid-3,
    .plans {
        grid-template-columns: 1fr;
    }
    .steps {
        grid-template-columns: repeat(2, 1fr);
    }
    .window {
        transform: none;
    }
    .hero__art {
        min-height: 18rem;
    }
    .banner .btn {
        margin-left: 0;
    }
}
@media (max-width: 40rem) {
    .stats,
    .steps {
        grid-template-columns: 1fr;
    }
    .form-row {
        grid-template-columns: 1fr;
    }
    /* no-JS fallback; with JS the menu folds into the overlay instead */
    .nav:not(.nav--js) {
        flex-wrap: wrap;
        gap: 0.75rem 1.25rem;
    }
    .nav:not(.nav--js) .nav-brand {
        margin-right: 0;
        width: 100%;
    }
    .hero__title {
        max-width: none;
    }
    .hero__art {
        display: none;
    }
    .hero__actions .btn {
        width: 100%;
    }
    /* the deploy log is decoration for the claim beside it; skip it on phones */
    .deploy {
        display: none;
    }
}

/* ── reduced motion ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .rotator__word:not(.is-active) {
        display: none;
    }
}
