/* ==========================================================================
   thejoom.css — styles for the home page (index.html) only.
   static/css/common.css is shared by portfolio/*.html and is NOT touched here.
   Comments are intentionally written in English (Windows mojibake history).
   ========================================================================== */

@font-face {
    font-family: "Pretendard";
    src: url("/static/fonts/PretendardVariable.woff2") format("woff2-variations");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */

:root {
    color-scheme: light;

    /* Brand — logo and the primary call to action only. Never a decorative fill. */
    --brand-from: #7c3aed;
    --brand-to: #db2777;
    --brand-gradient: linear-gradient(102deg, var(--brand-from) 0%, var(--brand-to) 100%);

    /* Ink */
    --ink: #333b4a; /* 11.3:1 on white */
    --ink-deep: #1e2631; /* hero / work / footer band */
    --ink-muted: #5c6779; /* 5.7:1 on white */
    --on-dark: #ffffff; /* 15.3:1 on --ink-deep */
    --on-dark-muted: #b9c2cf; /* 8.5:1 on --ink-deep */

    /* Surfaces */
    --surface: #ffffff;
    --surface-soft: #f7f8fa;
    --sand: #f1e4cd; /* ivy warmth, secondary surface */
    --sand-soft: #faf3e7;
    --mist: #c7d0dc; /* secondary surface + rules */
    --ink-on-sand: #4a4335; /* warm ink, 7.8:1 on --sand */
    --line: #e3e8ee;
    --line-dark: #38414e;
    --wash-on-dark: rgb(255 255 255 / 0.06);

    /* Accent — interaction only (links, CTA, active, focus ring) */
    --accent: #6d4dcd; /* 5.8:1 on white */
    --accent-press: #5a3cb5; /* 7.7:1 on white */
    --accent-on-dark: #c9bbf5; /* 8.7:1 on --ink-deep */

    /* Blush — the one narrow text emphasis, dark surfaces only (7.2:1 on --ink-deep).
       Fails contrast on white, so it must never appear on a light surface. */
    --blush: #e9a08c;

    /* Type scale, ratio 1.25 from a 1rem base.
       Ladder: 0.8 / 1 / 1.25 / 1.5625 / 1.953 / 2.441 / 3.052 / 3.815rem.
       The upper steps are consumed through the fluid values below. */
    --fs-xs: 0.8rem;
    --fs-base: 1rem;
    --fs-md: 1.25rem;

    /* Fluid steps keep a rem term so browser zoom still moves them (WCAG 1.4.4) */
    --fs-h1: clamp(1.953rem, 1.4rem + 2.8vw, 3.052rem);
    --fs-h2: clamp(1.5625rem, 1.2rem + 1.8vw, 2.441rem);
    --fs-h3: clamp(1.25rem, 1.15rem + 0.5vw, 1.5625rem);
    --fs-lead: clamp(var(--fs-base), 0.9375rem + 0.25vw, var(--fs-md));
    /* Step index label. Locked to --fs-h3 so the figure and the step title sit
       on the same size rank at every width; the label is set apart from the
       title by weight alone (500 against 700), never by a second size step. */
    --fs-numeral: var(--fs-h3);

    /* Spacing — 8px grid */
    --s-1: 0.5rem;
    --s-2: 1rem;
    --s-3: 1.5rem;
    --s-4: 2rem;
    --s-5: 3rem;
    --s-6: 4rem;
    --gutter: clamp(1rem, 0.5rem + 2vw, 2rem);
    --section-y: clamp(3rem, 2.5rem + 3vw, 5.5rem);

    /* Layout */
    --wrap: 72rem;
    --measure: 65ch;
    --header-h: 4rem;
    --radius: 0.75rem;
    --radius-lg: 1.5rem;

    /* Ivy sizing. All five source files draw the character at the same pixel
       scale (content box is ~0.89 of image width in every file), so matching
       inline-size — not block-size — is what makes the heads read the same.
       The fluid term carries a viewport-width component as well as a height
       one, so a wide desktop gets a bigger ivy than a phone of the same
       height instead of the same 145px everywhere. */
    --ivy-w: clamp(7rem, 4rem + 9svh + 4vw, 13rem);

    --ring: var(--accent);
    --shadow-lift: 0 1rem 2.5rem -1.5rem rgb(30 38 49 / 0.45);
    --shadow-brand: 0 1.25rem 2.5rem -1.25rem rgb(124 58 237 / 0.6);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

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

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

@media (prefers-reduced-motion: no-preference) {
    html {
        scroll-behavior: smooth;
    }
}

body {
    margin: 0;
    background: var(--surface);
    color: var(--ink);
    font-family: "Pretendard", -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕",
        system-ui, sans-serif;
    font-size: var(--fs-base);
    font-weight: 400;
    line-height: 1.6;
    word-break: keep-all;
    overflow-wrap: break-word;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
    margin: 0;
    font-weight: 700;
    line-height: 1.28;
    letter-spacing: -0.03em;
    text-wrap: balance;
}

h1 {
    font-size: var(--fs-h1);
}

h2 {
    font-size: var(--fs-h2);
    max-inline-size: 26ch;
}

h3 {
    font-size: var(--fs-h3);
    letter-spacing: -0.02em;
}

/* Service headings use the base rank on narrow screens; weight preserves hierarchy. */
h4 {
    font-size: var(--fs-base);
    letter-spacing: -0.02em;
}

@media (min-width: 48rem) {
    h4 {
        font-size: var(--fs-md);
    }
}

p {
    margin: 0;
    text-wrap: pretty;
}

ul,
ol {
    margin: 0;
    padding: 0;
    list-style: none;
}

img {
    display: block;
    max-inline-size: 100%;
}

a {
    color: inherit;
}

:where(a, button, summary):focus-visible {
    outline: 3px solid var(--ring);
    outline-offset: 3px;
    border-radius: var(--s-1);
}

[id] {
    scroll-margin-block-start: calc(var(--header-h) + var(--s-2));
}

main:focus {
    outline: none;
}

.skip-link {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.skip-link:focus-visible {
    inline-size: auto;
    block-size: auto;
    margin: var(--s-1);
    padding: var(--s-1) var(--s-2);
    overflow: visible;
    clip-path: none;
    z-index: 30;
    border-radius: var(--radius);
    background: var(--ink-deep);
    color: var(--on-dark);
    font-weight: 600;
    text-decoration: none;
}

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */

.wrap {
    inline-size: min(100% - (var(--gutter) * 2), var(--wrap));
    margin-inline: auto;
}

.band {
    padding-block: var(--section-y);
}

.band--ink {
    background: var(--ink-deep);
    color: var(--on-dark);
    --ring: var(--accent-on-dark);
}

.band--sand {
    background: var(--sand-soft);
}

.prose {
    max-inline-size: var(--measure);
    color: var(--ink-muted);
    font-size: var(--fs-lead);
    line-height: 1.7;
}

.band--ink .prose {
    color: var(--on-dark-muted);
}

.eyebrow {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    color: var(--ink-muted);
    font-size: var(--fs-base);
    font-weight: 600;
}

.eyebrow::after {
    content: "";
    flex: 0 0 var(--s-5);
    block-size: 1px;
    background: var(--mist);
}

.band--ink .eyebrow {
    color: var(--on-dark-muted);
}

.band--ink .eyebrow::after {
    background: var(--line-dark);
}

.section-head {
    display: grid;
    gap: var(--s-2);
    margin-block-end: var(--s-5);
}

.contact__grid > .section-head {
    margin-block-end: 0;
}

/* The single narrow text emphasis. Dark surfaces only — colour is the only
   emphasis carried by this span (no extra weight, no size change). */
.hl {
    color: var(--blush);
}

/* --------------------------------------------------------------------------
   4. Buttons and links
   -------------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-1);
    min-block-size: 2.75rem;
    padding: var(--s-1) var(--s-3);
    border: 1px solid transparent;
    border-radius: 999px;
    font: inherit;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition:
        transform 0.18s ease,
        box-shadow 0.18s ease,
        background-color 0.18s ease,
        border-color 0.18s ease,
        color 0.18s ease;
}

.btn--primary {
    background-image: var(--brand-gradient);
    color: var(--on-dark);
    box-shadow: var(--shadow-lift);
}

.btn--ghost {
    border-color: var(--mist);
    background: transparent;
    color: var(--ink);
}

.band--ink .btn--ghost {
    border-color: var(--line-dark);
    color: var(--on-dark);
}

.btn--sm {
    padding-inline: var(--s-2);
    font-size: var(--fs-xs);
}

@media (hover: hover) {
    .btn--primary:hover {
        box-shadow: var(--shadow-brand);
        transform: translateY(-1px);
    }

    .btn--ghost:hover {
        border-color: var(--accent);
        color: var(--accent);
    }

    .band--ink .btn--ghost:hover {
        border-color: var(--accent-on-dark);
        background: var(--wash-on-dark);
        color: var(--on-dark);
    }
}

.btn:active {
    transform: translateY(1px);
    box-shadow: none;
}

.btn[aria-disabled="true"],
.btn:disabled {
    box-shadow: none;
    background-image: none;
    background-color: var(--line);
    color: var(--ink-muted);
    pointer-events: none;
}

.link {
    color: var(--accent);
    font-weight: 600;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.25em;
    transition: color 0.18s ease;
}

.band--ink .link {
    color: var(--accent-on-dark);
}

@media (hover: hover) {
    .link:hover {
        color: var(--accent-press);
    }

    .band--ink .link:hover {
        color: var(--on-dark);
    }
}

.link:active {
    color: var(--accent-press);
}

.cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
}

/* --------------------------------------------------------------------------
   5. Site header
   -------------------------------------------------------------------------- */

.site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 20;
    background: var(--surface);
    border-block-end: 1px solid var(--line);
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2);
    min-block-size: var(--header-h);
}

.site-header__brand {
    display: inline-flex;
    align-items: center;
    padding-block: var(--s-1);
}

.site-header__brand img {
    block-size: 1.75rem;
    inline-size: auto;
}

.nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    min-block-size: 2.75rem;
    padding-inline: var(--s-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-size: var(--fs-xs);
    font-weight: 600;
    cursor: pointer;
}

.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
    display: block;
    inline-size: 1rem;
    block-size: 2px;
    background: currentColor;
    border-radius: 2px;
}

.nav-toggle__bars {
    position: relative;
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
    content: "";
    position: absolute;
    inset-inline-start: 0;
}

.nav-toggle__bars::before {
    inset-block-start: -5px;
}

.nav-toggle__bars::after {
    inset-block-start: 5px;
}

@media (hover: hover) {
    .nav-toggle:hover {
        border-color: var(--accent);
        color: var(--accent);
    }
}

.nav-toggle:active {
    background: var(--surface-soft);
}

.site-nav {
    display: none;
}

.site-nav[data-open="true"] {
    display: grid;
    position: absolute;
    inset-inline: 0;
    inset-block-start: 100%;
    gap: var(--s-1);
    padding: var(--s-2) var(--gutter) var(--s-3);
    background: var(--surface);
    border-block-end: 1px solid var(--line);
    box-shadow: var(--shadow-lift);
}

.site-nav__list {
    display: grid;
    gap: var(--s-1);
}

.site-nav__list a {
    display: flex;
    align-items: center;
    min-block-size: 2.75rem;
    padding-inline: var(--s-1);
    border-radius: var(--radius);
    font-weight: 600;
    text-decoration: none;
    transition: color 0.18s ease, background-color 0.18s ease;
}

@media (hover: hover) {
    .site-nav__list a:hover {
        color: var(--accent);
        background: var(--surface-soft);
    }
}

.site-nav__list a:active {
    color: var(--accent-press);
}

@media (min-width: 64rem) {
    .nav-toggle {
        display: none;
    }

    .site-nav,
    .site-nav[data-open="true"] {
        display: flex;
        position: static;
        align-items: center;
        gap: var(--s-3);
        padding: 0;
        border: 0;
        box-shadow: none;
        background: transparent;
    }

    .site-nav__list {
        grid-auto-flow: column;
        gap: var(--s-3);
    }

    .site-nav__list a {
        min-block-size: 2.5rem;
        padding-inline: 0;
        font-size: var(--fs-xs);
        font-weight: 600;
    }
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */

.hero {
    /* The trust row already closes the hero, so it does not need the full band
       rhythm underneath it as well. */
    padding-block-end: var(--s-6);
}

.hero__box {
    container-type: inline-size;
    container-name: hero;
}

.hero__grid {
    display: grid;
    gap: var(--s-5);
    align-items: center;
}

.hero__body {
    display: grid;
    gap: var(--s-3);
    justify-items: start;
    min-inline-size: 0;
}

.hero__logo {
    inline-size: clamp(11rem, 8rem + 12vw, 18rem);
    block-size: auto;
    aspect-ratio: 360 / 92;
}

.hero__body h1 {
    max-inline-size: 22ch;
}

.hero__figure {
    display: flex;
    justify-content: center;
    margin: 0;
    min-inline-size: 0;
}

.trust {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-3);
    margin-block-start: var(--s-5);
    padding-block-start: var(--s-4);
    border-block-start: 1px solid var(--line-dark);
}

/* Two tiers per claim: the short label carries it, the line under it explains.
   Both stay on ink and muted ink — no fill, no gradient. */
.trust li {
    display: grid;
    gap: var(--s-1);
    padding-inline-start: var(--s-2);
    border-inline-start: 2px solid var(--line-dark);
    min-inline-size: 0;
}

.trust__label {
    color: var(--on-dark);
    font-size: var(--fs-md);
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.02em;
}

.trust__desc {
    color: var(--on-dark-muted);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.6;
}

@container hero (min-width: 30rem) {
    .trust {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@container hero (min-width: 46rem) {
    .hero__grid {
        grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
        gap: var(--s-6);
    }
}

@container hero (min-width: 60rem) {
    .trust {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/* --------------------------------------------------------------------------
   7. What we build — two tracks, told apart by how they are billed
   -------------------------------------------------------------------------- */

.build__box {
    container-type: inline-size;
    container-name: build;
}

.tracks {
    display: grid;
    gap: var(--s-6);
}

.track {
    display: grid;
    gap: var(--s-4);
    min-inline-size: 0;
}

/* Badge, title, qualifier — the same three tiers in both heads, so the two
   billing labels land on the same reading line and can be compared. */
.track__head {
    display: grid;
    gap: var(--s-1);
    justify-items: start;
    min-inline-size: 0;
}

/* Deliberately not a pill: a pill this size reads as a button, and nothing in
   these two lists is clickable. One badge per track, never one per category. */
.track__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-1);
    min-block-size: 2.75rem;
    padding: var(--s-1) var(--s-2);
    border-radius: var(--s-1);
    background: var(--sand);
    color: var(--ink-on-sand); /* 7.8:1 on --sand */
    font-size: var(--fs-base);
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

.track__badge-icon {
    inline-size: var(--s-2);
    block-size: var(--s-2);
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    flex: 0 0 auto;
}

.track__note {
    color: var(--ink-muted);
}

/* One shared card surface keeps the subscription scope and both build tracks
   in the same visual language. */
.scope,
.offer,
.duty {
    padding: var(--s-3);
    border: 1px solid var(--mist);
    border-radius: var(--radius-lg);
    background: var(--surface);
}

.offer h4,
.duty h4,
.scope h3,
.role h4,
.step h3 {
    color: var(--ink-deep);
}

.offers,
.duties {
    display: grid;
    gap: var(--s-4);
    min-inline-size: 0;
}

.offer {
    display: grid;
    gap: var(--s-1);
    min-inline-size: 0;
}

.offer p {
    color: var(--ink-muted);
    max-inline-size: var(--measure);
}

/* The monthly badge, rather than a contrasting card style, distinguishes the
   ongoing track from the one-off work. */
.track--run .track__badge {
    background: var(--ink-deep);
    color: var(--on-dark);
}

.duty {
    display: grid;
    gap: var(--s-1);
    min-inline-size: 0;
}

.duty p {
    color: var(--ink-muted);
    max-inline-size: var(--measure);
}

/* Experience text conveys the meaning of the title colour. */
.duty--proven h4 {
    color: var(--ink);
}

.duty__experience {
    display: block;
    margin-block-start: var(--s-1);
    color: var(--ink-muted);
    font-size: var(--fs-xs);
}

/* Six items, so the column count divides them evenly at every step; an
   auto-fit track would leave a two-cell orphan row on a wide desktop. */
@container build (min-width: 34rem) {
    .offers,
    .duties {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@container build (min-width: 56rem) {
    .offers,
    .duties {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

}

/* --------------------------------------------------------------------------
   8. Process — five steps, each carrying its own ivy marker
   -------------------------------------------------------------------------- */

.process {
    padding-block: var(--section-y);
    /* The section reads as one chapter now that the steps are ordinary rows,
       so the warmth moves from alternating steps to the whole band. */
    background: var(--sand-soft);
    /* Warm ink for the whole band. The page-wide greys are blue-based, and over
       sand that mismatch is what read as "flat" — nothing here is desaturated,
       it is the wrong temperature. Rank inside the band is carried by size and
       weight, so one ink is enough. 8.9:1 on --sand-soft. */
    color: var(--ink-on-sand);
}

.process .eyebrow,
.process .prose {
    color: var(--ink-on-sand);
}

.process__head {
    margin-block-end: var(--s-5);
}

.process__box {
    container-type: inline-size;
    container-name: process;
}

.steps {
    /* Section-local ivy scale. Here the character is a list marker, not the
       in-flow figure the rest of the page uses, so this overrides --ivy-w
       rather than adding a second sizing rule to .ivy. Width is what unifies
       them: all five files draw the character at the same pixel scale, so one
       common inline-size makes the heads read the same even though the natural
       ratios run from 0.61 to 0.94. */
    --ivy-w: clamp(4rem, 3rem + 6cqi, 7rem);
    /* The marker plate, stated once here rather than left to each image. Width
       is a declared grid track, so the icon column cannot drift with whichever
       source file happens to be widest. The 1.65 block factor clears the
       tallest of the five ratios (443/725 = 0.611) and --s-2 is the 8px inset
       that surrounds it, which is what makes all five plates identical. */
    --mark-w: calc(var(--ivy-w) + var(--s-2));
    --mark-h: calc(var(--ivy-w) * 1.65 + var(--s-2));
    min-inline-size: 0;
}

.step {
    display: grid;
    grid-template-columns: var(--mark-w) minmax(0, 1fr);
    column-gap: var(--s-2);
    row-gap: var(--s-1);
    align-content: center;
    /* An even row rhythm for the list, without the viewport-sized steps this
       section used to carry. Floor, never a cap. Kept a little above the
       tallest step's own height, so four lines of text no longer sit in a box
       twice their size. */
    min-block-size: clamp(10rem, 8rem + 4vw, 12rem);
    /* The plate now carries the row's visual padding, so the row's own padding
       comes down a step. That keeps the row height where the previous pass put
       it while the marker inside it grows by two thirds. */
    padding-block: var(--s-2);
    border-block-end: 1px solid var(--mist);
}

.step:last-child {
    border-block-end: 0;
}

/* The label now matches the title's size and ink, so weight is the only thing
   separating them — 500 against the h3's 700. Same line-height and tracking as
   the title as well, which is what puts the two on one optical line rather than
   merely on one baseline. Tabular figures keep 01–05 the same width, so the
   title's left edge does not shift down the list. */
.step__num {
    font-size: var(--fs-numeral);
    font-weight: 500;
    line-height: 1.28;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.step__body {
    display: grid;
    gap: var(--s-2);
    min-inline-size: 0;
}

/* Colour is inherited from the band so the step copy keeps the section's warm
   ink; size and weight already separate it from the title. */
.step__body p {
    font-size: var(--fs-lead);
    line-height: 1.7;
    max-inline-size: var(--measure);
}

/* The marker plate. It is the section's colour as much as it is the icon's
   frame: one sand rectangle per step, identical in all five rows because its
   size comes from --mark-w/--mark-h and not from the character inside it. That
   is also what lets the character grow — the plate absorbs the ratio spread
   (1.07 to 1.64) that used to make the icon column wobble.
   Narrow: the plate holds its own column beside the whole step, centred against
   the label and the copy stacked to its right. */
.step__mark {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: center;
    display: grid;
    place-items: center;
    inline-size: var(--mark-w);
    block-size: var(--mark-h);
    padding: var(--s-1);
    border-radius: var(--radius-lg);
    background: var(--sand);
}

@container process (min-width: 52rem) {
    .step {
        /* Plate, then a track that holds the two-digit label at its raised
           --fs-numeral ceiling; min-content is the floor, so a fallback face
           widens the track instead of pushing into the title. */
        grid-template-columns: var(--mark-w) minmax(min-content, 3rem) minmax(0, 1fr);
        column-gap: var(--s-3);
        align-items: baseline;
    }

    /* One row now, and the plate is taller than the copy beside it, so it starts
       with the label and the title rather than centring against them: plate top,
       numeral and title all share one rail across the five steps. */
    .step__mark {
        grid-row: 1;
        align-self: start;
    }
}

.ivy {
    inline-size: var(--ivy-w);
    block-size: auto;
}

/* Natural ratios kept per file; matching inline-size keeps the character
   drawing scale identical across all five. */
.ivy--clipboard {
    aspect-ratio: 431 / 607;
}

.ivy--cursor {
    aspect-ratio: 408 / 569;
}

.ivy--checkbox {
    aspect-ratio: 443 / 725;
}

.ivy--deskbell {
    aspect-ratio: 442 / 472;
}

.ivy--folder {
    aspect-ratio: 437 / 548;
}

/* --------------------------------------------------------------------------
   9. Work
   -------------------------------------------------------------------------- */

.work {
    /* The process uses five inline characters. Preserve this band as
       separation before the next section, including when shots fail to load.
       Keep the existing minimum until viewport review. */
    display: grid;
    align-content: center;
    min-block-size: max(84vh, 40rem);
    min-block-size: max(84svh, 40rem);
}

.work__box {
    container-type: inline-size;
    container-name: work;
}

.work__grid {
    display: grid;
    gap: var(--s-4);
}

/* The section head already ends on the CTA, so its own trailing margin stacked
   on top of the grid gap and opened a hole above the list. */
.work__grid > .section-head {
    margin-block-end: 0;
}

/* Disclosure line. It has to be read before the shots are believed, so it keeps
   body size and is set apart by a rule rather than shrunk into fine print or
   boxed up — a box here would read as a fourth card group. */
.work__note {
    padding-inline-start: var(--s-2);
    border-inline-start: 2px solid var(--line-dark);
    max-inline-size: var(--measure);
    color: var(--on-dark-muted);
}

.work__sets {
    display: grid;
    gap: var(--s-5);
}

/* Each category is its own band: a full-bleed rule and a label above its shots.
   That divider is what carries the rhythm, so the cards themselves need no
   frame and the run of nine never reads as one undifferentiated grid. */
.work__set {
    display: grid;
    gap: var(--s-3);
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--line-dark);
}

/* Same label treatment the retired work tags used: the step down from --fs-h3
   is deliberate, since this names a group of shots rather than titling one. */
.work__set-title {
    color: var(--on-dark-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.08em;
}

.work__cards {
    display: grid;
    gap: var(--s-4);
}

.work-card {
    display: grid;
    gap: var(--s-2);
    min-inline-size: 0;
}

/* The screenshot is the card. Text sits straight on the band, so there is no
   box inside a box; the hairline is only there to hold the rounded corner and
   to keep the dark-hero shots from bleeding into the ink band.
   Cards are not links — no hover affordance, because nothing happens on click.
   The one way out of this section is the CTA at the bottom. */
.work-card__shot {
    inline-size: 100%;
    block-size: auto;
    aspect-ratio: 720 / 450;
    border: 1px solid var(--line-dark);
    border-radius: var(--radius);
    background: var(--wash-on-dark);
}

.work-card__body {
    display: grid;
    gap: var(--s-1);
    min-inline-size: 0;
}

/* Weight carries the label, colour carries the line: one emphasis each. */
.work-card__type {
    font-weight: 700;
}

.work-card__origin {
    color: var(--on-dark-muted);
    font-size: var(--fs-xs);
}

.work-card__line {
    color: var(--on-dark-muted);
}

@container work (min-width: 40rem) {
    .work__cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* A lone shot stretched across the full row would upscale a 720px source.
       Laid on its side it stays under its native width and gives the run of
       nine a break instead of a fifth identical pair. */
    .work__cards--single {
        grid-template-columns: minmax(0, 1fr);
    }

    .work-card--wide {
        grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
        column-gap: var(--s-4);
        align-items: center;
    }
}

/* --------------------------------------------------------------------------
   10. The subscription — one product, its price, and the two who do the work
   -------------------------------------------------------------------------- */

.plan__box {
    container-type: inline-size;
    container-name: plan;
}

/* The only priced block on the page, so it is given its own ground instead of
   another rule-topped list on the band. Sand, not ink: the work band directly
   above is already ink and a second dark field here would fuse the two. Sand
   is also the warmth the token set reserves for this character, and it hands
   the reader on to the sand contact band below. */
.plan {
    display: grid;
    gap: var(--s-4);
    padding: var(--s-3);
    border-radius: var(--radius-lg);
    background: var(--sand);
    color: var(--ink-on-sand); /* 7.8:1 on --sand */
    min-inline-size: 0;
}

.plan__figure {
    margin: 0;
    justify-self: center;
    min-inline-size: 0;
}

.plan__body {
    display: grid;
    gap: var(--s-4);
    min-inline-size: 0;
}

/* Badge, name, price — the same three tiers as the two track heads in the
   section above, so the price arrives on a rank the page has already set. */
.plan__head {
    display: grid;
    gap: var(--s-1);
    justify-items: start;
    min-inline-size: 0;
}

/* The subscription chip: ink on sand up here, ink on white down in the scopes.
   That is the pairing the two tracks above already use to tell a monthly fee
   from a one-off one, so the badge stays the page's billing signal and the
   boundary does not need a colour of its own. */
.track__badge--ink {
    background: var(--ink-deep);
    color: var(--on-dark); /* 15.3:1 on --ink-deep */
}

/* Size is the only thing lifting the price over the product name: both are 700
   and both are the slab's warm ink, so neither is emphasised twice. No fill and
   no gradient — the brand gradient stays on the logo and the call to action. */
.plan__price {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.28;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
}

/* Hairline rows, no second box. The slab is already a surface; a bordered card
   in here would be a card inside a card. */
.plan__roles {
    min-inline-size: 0;
}

.role {
    display: grid;
    gap: var(--s-1);
    padding-block: var(--s-3);
    border-block-start: 1px solid var(--mist);
    min-inline-size: 0;
}

.role:last-child {
    padding-block-end: 0;
}

/* Which of the two is the program and which is the person. Weight alone tells
   it from the name — 500 against the h4's 700, same size and same ink — which
   is the device the step labels already use in the process band. */
.role__kind {
    font-weight: 500;
}

.role p {
    max-inline-size: var(--measure);
}

/* Covered by the fee and quoted on its own, at one rank: same head, same row
   rhythm, same column width. The boundary is not small print under the price. */
.scopes {
    display: grid;
    gap: var(--s-3);
    margin-block-start: var(--s-5);
    min-inline-size: 0;
}

.scope {
    display: grid;
    gap: var(--s-3);
    align-content: start;
    min-inline-size: 0;
}

.plan__price-cta {
    margin-block-start: var(--s-2);
}

/* One switch for the whole section: the slab takes its figure column and the
   two scopes come alongside each other at the same width. */
@container plan (min-width: 44rem) {
    .plan {
        /* Track follows the --ivy-w ceiling so the largest desktop ivy fits. */
        grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
        gap: var(--s-5);
        align-items: center;
        padding: var(--s-5);
    }

    .scopes {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--s-4);
    }

    .scope {
        padding: var(--s-4);
    }
}

/* Wide enough for the two roles to be read as a comparison rather than as two
   stacked paragraphs: name on one rail, what they do on the next. */
@container plan (min-width: 64rem) {
    .role {
        grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
        column-gap: var(--s-4);
        align-items: baseline;
    }
}

/* --------------------------------------------------------------------------
   11. Contact
   -------------------------------------------------------------------------- */

.contact__grid {
    display: grid;
    gap: var(--s-3);
}

.contact__note {
    color: var(--ink-muted);
    font-size: var(--fs-xs);
}

/* --------------------------------------------------------------------------
   12. Footer
   -------------------------------------------------------------------------- */

.site-footer {
    background: var(--ink-deep);
    color: var(--on-dark-muted);
    padding-block: var(--s-6) var(--s-5);
    --ring: var(--accent-on-dark);
}

.site-footer__grid {
    display: grid;
    gap: var(--s-4);
}

.site-footer__brand img {
    block-size: 2rem;
    inline-size: auto;
    color: var(--on-dark);
    filter: brightness(0) invert(1);
}

.site-footer__note {
    max-inline-size: var(--measure);
    font-size: var(--fs-xs);
    line-height: 1.7;
}

.site-footer__links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-3);
}

.site-footer__links a {
    display: inline-flex;
    align-items: center;
    min-block-size: 2.5rem;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--on-dark);
    text-decoration: none;
}

@media (hover: hover) {
    .site-footer__links a:hover {
        color: var(--accent-on-dark);
        text-decoration: underline;
        text-underline-offset: 0.25em;
    }
}

.site-footer__links a:active {
    color: var(--accent-on-dark);
}

.site-footer__legal {
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--line-dark);
    font-size: var(--fs-xs);
    letter-spacing: 0.04em;
}

@media (min-width: 48rem) {
    .site-footer__grid {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: var(--s-5);
        align-items: start;
    }

    .site-footer__legal {
        grid-column: 1 / -1;
    }
}

/* --------------------------------------------------------------------------
   13. Motion preferences
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    .btn:hover,
    .btn:active {
        transform: none;
    }
}
