@layer tokens, reset, base, prose, components, utilities;

/* Careers page (/careers). Page-specific rules only: layout, hero, rail,
   lists, the closing apply band, motion. Palette, type scale and spacing come
   from /tokens.css; reset, body, links, focus ring, header, footer and the
   shared .eyebrow / .nav-link idioms from /site.css. Kept external so the
   page ships a strict no-inline CSP.

   Breakpoints (custom properties cannot drive media queries, so the numbers
   live here once):
     900px  the rail becomes a sticky side column and the fixed bottom bar
            hands the CTA over to it
     600px  list gutters and the apply band tighten for narrow phones */

/* ======================================================================
   Prose: headings and paragraphs inside the job description
   ====================================================================== */

@layer prose {
    .job :is(h1, h2) {
        text-wrap: balance;
    }

    .job p {
        color: var(--text-secondary);
        text-wrap: pretty;
    }

    .job p + p {
        margin-block-start: var(--space-5);
    }

    .section__title {
        font-size: var(--step-2);
        font-weight: 600;
        line-height: var(--leading-tight);
        letter-spacing: var(--tracking-heading);
        margin-block-end: var(--space-6);
    }

    /* A lead sentence sits closer to the list it introduces than to prose. */
    .section__title + p + :is(.ladder, .offer) {
        margin-block-start: var(--space-5);
    }
}

/* ======================================================================
   Components
   ====================================================================== */

@layer components {

    /* ---------- Header badge: the above-the-fold CTA ---------- */

    .hiring-badge {
        display: inline-flex;
        align-items: center;
        gap: var(--space-2);
        padding: var(--space-3) var(--space-4); /* >= 44px tall with body leading */
        border: 1px solid var(--border-strong);
        border-radius: var(--radius-pill);
        background: var(--surface-glass-soft);
        color: var(--text-secondary);
        font-size: var(--step--1);
        font-weight: 500;
        letter-spacing: var(--tracking-snug);

        /* The sticky rail owns the CTA on desktop; two identical buttons
           above the fold would compete. */
        @media (width >= 900px) {
            display: none;
        }
        text-decoration: none;

        &:hover {
            color: var(--text-primary);
            border-color: var(--border-hover);
        }
    }

    /* ---------- Page: the two-column block, then the closing band ---------- */

    .job {
        display: grid;
        row-gap: var(--space-12);
        /* Content-box so the gutter sits outside the 1120px column, exactly
           as the header and footer inners do: wordmark and prose share an edge. */
        box-sizing: content-box;
        max-inline-size: var(--page-max);
        margin-inline: auto;
        padding-block: var(--space-16) var(--space-section);
        padding-inline: var(--gutter);

        @media (width >= 900px) {
            row-gap: var(--space-section);
        }
    }

    /* Hero, body and rail share their own grid, separate from the band, so
       the sticky rail's containing block ends where the body ends: Chrome
       constrains a sticky grid item by the grid container, not its grid
       area, and would otherwise let the rail slide over the band. */
    .job__columns {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        row-gap: var(--space-12);

        /* The rail hugs the page edge so the header badge and footer links
           line up with it; the gap absorbs whatever is left over. */
        @media (width >= 900px) {
            grid-template-columns: minmax(0, var(--measure)) 280px;
            grid-template-rows: auto 1fr;
            justify-content: space-between;
            column-gap: var(--space-16);
            row-gap: var(--space-section);
        }
    }

    .hero {
        @media (width >= 900px) {
            grid-area: 1 / 1 / 2 / 2;
        }
    }

    .job__body {
        @media (width >= 900px) {
            grid-area: 2 / 1 / 3 / 2;
            padding-block-start: var(--space-6); /* air under the hero; aligns the rail bottom with the first h2 */
        }
    }

    .job__body > section + section {
        margin-block-start: var(--space-section);
    }

    /* ---------- Hero ---------- */

    .hero__kicker {
        margin-block-end: var(--space-5);
    }

    .hero__title {
        font-size: var(--step-4);
        font-weight: 560;
        line-height: var(--leading-tight);
        letter-spacing: var(--tracking-tight);
    }

    .hero__lede {
        margin-block-start: var(--space-6);
        font-family: var(--font-display);
        font-style: italic;
        font-size: var(--step-3);
        line-height: var(--leading-snug);
        text-wrap: balance;
    }

    .hero__accent {
        color: var(--text-primary);
    }

    /* ---------- Rail: facts, compact CTA ---------- */

    .rail {
        display: grid;
        row-gap: var(--space-8);
        align-self: start;

        @media (width >= 900px) {
            grid-area: 1 / 2 / 3 / 3;
            position: sticky;
            inset-block-start: calc(var(--header-compact) + var(--space-6)); /* clears the sticky header */
        }
    }

    .facts__row {
        display: grid;
        grid-template-columns: 6rem minmax(0, 1fr);
        column-gap: var(--space-3);
        align-items: baseline;
        padding-block: var(--space-3);
        border-block-end: 1px solid var(--border);

        &:first-child {
            padding-block-start: 0;
        }
    }

    .facts__value {
        color: var(--text-primary);
        font-size: var(--step--1);
        font-weight: 500;
    }

    /* ---------- Stack: a labelled mono list inside "Who this is for" ---------- */

    .stack-block {
        margin-block: var(--space-6);
    }

    .stack-block__title {
        margin-block-end: var(--space-3);
    }

    /* Mono plus a gap is separator enough; nothing leaks into the
       accessible name and no line ever opens with a middot. */
    .stack {
        display: flex;
        flex-wrap: wrap;
        gap: var(--space-2) var(--space-4);
        padding: 0;
        list-style: none;
        color: var(--text-secondary);
        font-family: var(--font-mono);
        font-size: var(--step--1);
        line-height: var(--leading-body);
    }

    .stack__item {
        white-space: nowrap;
    }

    /* ---------- Numbered hairline ladder: the one list style ---------- */

    .ladder {
        padding: 0;
        list-style: none;
        counter-reset: ladder;
        border-block-start: 1px solid var(--border);
    }

    /* Each row is a two-cell grid: the ::before numeral and the .ladder__body
       wrapper. The wrapper is load-bearing: it turns the mixed inline copy
       into a real grid item with a first baseline for the numeral to align
       to (anonymous grid items align inconsistently across engines). */
    .ladder__item {
        counter-increment: ladder;
        display: grid;
        grid-template-columns: var(--space-10) minmax(0, 1fr);
        column-gap: var(--space-4);
        align-items: baseline;
        padding-block: var(--space-5);
        border-block-end: 1px solid var(--border);
        color: var(--text-secondary);
        text-wrap: pretty;

        &::before {
            content: counter(ladder, decimal-leading-zero);
            color: var(--primary-soft);
            font-family: var(--font-mono);
            font-size: var(--step--1);
            font-variant-numeric: tabular-nums;
        }

        @media (width < 600px) {
            grid-template-columns: var(--space-8) minmax(0, 1fr);
            column-gap: var(--space-3);
        }
    }

    .ladder__term {
        color: var(--text-primary);
        font-weight: 600;
    }

    /* ---------- Fit split: two rules, no boxes ---------- */

    .fit-split {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
        gap: var(--space-6);
        margin-block: var(--space-8);
    }

    .fit-split__panel {
        padding-inline-start: var(--space-5);
        border-inline-start: 2px solid var(--border-strong);
    }

    .fit-split__panel--yes {
        border-color: var(--primary-soft);
    }

    .fit-split__label {
        display: block;
        margin-block-end: var(--space-2);
    }

    .fit-split__label--yes {
        color: var(--primary-soft);
    }

    /* ---------- Offer: hairline rows with a quiet check ---------- */

    .offer {
        padding: 0;
        list-style: none;
        border-block-start: 1px solid var(--border);
    }

    .offer__item {
        display: grid;
        grid-template-columns: var(--space-10) minmax(0, 1fr);
        column-gap: var(--space-4);
        padding-block: var(--space-4);
        border-block-end: 1px solid var(--border);
        color: var(--text-secondary);
        text-wrap: pretty;

        /* A check drawn from two borders: survives forced colours and
           print, unlike a glyph that may be missing from the font. The
           0.45em top offset seats it on the x-height of the first line. */
        &::before {
            content: "";
            inline-size: var(--space-3);
            block-size: var(--space-2);
            margin-block-start: 0.45em;
            margin-inline-start: var(--space-1);
            border-inline-start: 2px solid var(--text-secondary);
            border-block-end: 2px solid var(--text-secondary);
            rotate: -45deg;
        }

        @media (width < 600px) {
            grid-template-columns: var(--space-8) minmax(0, 1fr);
            column-gap: var(--space-3);
        }
    }

    /* ---------- Primary button ---------- */

    .button {
        /* The gradient's light end is pulled toward --primary-deep so the
           off-white label stays above 4.5:1 on every pixel of the button. */
        --button-light: color-mix(in oklch, var(--primary) 30%, var(--primary-deep));
        --button-glow: var(--glow-primary);
        /* Contact shadow: a plain black alpha, no token exists for ink. */
        --button-ink: oklch(0% 0 0 / 0.4);

        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: var(--space-2);
        padding: var(--space-4) var(--space-8);
        border-radius: var(--radius-sm);
        background-image: linear-gradient(135deg, var(--button-light), var(--primary-deep));
        background-size: 200% 100%;
        background-position: 100% 0;
        box-shadow:
            0 6px 20px var(--button-glow),
            0 1px 2px var(--button-ink),
            inset 0 1px 0 var(--border-strong);
        color: var(--text-primary);
        font-size: var(--step-0);
        font-weight: 600;
        line-height: var(--leading-tight);
        letter-spacing: var(--tracking-snug);
        text-decoration: none;

        &:hover {
            --button-glow: var(--glow-primary-hover);

            background-position: 0 0;
            box-shadow:
                0 10px 28px var(--button-glow),
                0 1px 2px var(--button-ink),
                inset 0 1px 0 var(--border-strong);
        }

        &:active {
            scale: 0.97;
        }
    }

    .button__arrow {
        display: inline-block;
    }

    .button--compact {
        padding-block: var(--space-4); /* keeps the smaller type at >= 44px */
        font-size: var(--step--1);

        /* Under 900px the bottom bar carries the CTA; a second button a few
           lines above it would just be noise. */
        @media (width < 900px) {
            display: none;
        }
    }

    /* ---------- Apply: the closing band, the only card on the page ---------- */

    .apply {
        position: relative;
        isolation: isolate;
        display: grid;
        justify-items: center;
        row-gap: var(--space-3);
        padding: var(--space-12);
        border: 1px solid var(--border-strong);
        border-radius: var(--radius-lg);
        background:
            radial-gradient(ellipse 60% 80% at 50% 0%, var(--tint-primary) 0%, transparent 70%),
            var(--surface-glass);
        text-align: center;
        scroll-margin-block-start: var(--space-8);

        /* Top hairline highlight. */
        &::before {
            content: "";
            position: absolute;
            inset-block-start: 0;
            inset-inline-start: 50%;
            translate: -50% 0;
            inline-size: min(420px, 70%);
            block-size: 1px;
            background: linear-gradient(
                90deg,
                transparent,
                color-mix(in oklch, var(--primary-soft) 70%, transparent),
                transparent
            );
        }

        @media (width < 600px) {
            padding: var(--space-8);
        }

        /* Full width under both columns: title, text and fallback left, button right. */
        @media (width >= 900px) {
            grid-template-columns: minmax(0, 1fr) auto;
            column-gap: var(--space-16);
            align-items: center;
            justify-items: start;
            text-align: start;
        }
    }

    .apply__title {
        font-size: var(--step-2);
        font-weight: 600;
        line-height: var(--leading-tight);
        letter-spacing: var(--tracking-heading);
    }

    .apply__text {
        max-inline-size: 44ch;
    }

    .apply__button {
        margin-block-start: var(--space-4);

        /* Spans every row so it centres on the band, not on the title pair. */
        @media (width >= 900px) {
            grid-area: 1 / 2 / 4 / 3;
            justify-self: end;
            margin-block-start: 0;
        }
    }

    .apply__fallback {
        margin-block-start: var(--space-2);
        color: var(--text-tertiary);
        font-size: var(--step--1);

        @media (width >= 900px) {
            grid-area: 3 / 1 / 4 / 2;
        }
    }

    /* Vertical padding grows the tap target to >= 44px without moving the line. */
    .apply__email {
        display: inline-block;
        padding-block: var(--space-3);
        margin-block: calc(-1 * var(--space-3));
        font-family: var(--font-mono);
        -webkit-user-select: all;
        user-select: all;
    }

    /* ---------- Mobile bottom bar (< 900px) ---------- */

    .cta-bar {
        display: none;

        @media (width < 900px) {
            display: block;
            position: fixed;
            inset-inline: 0;
            inset-block-end: 0;
            z-index: 1;
            padding-block: var(--space-3) calc(var(--space-3) + env(safe-area-inset-bottom));
            padding-inline: var(--gutter);
            border-block-start: 1px solid var(--border);
            background: var(--surface-glass);
            -webkit-backdrop-filter: blur(12px);
            backdrop-filter: blur(12px);
        }
    }

    .cta-bar__button {
        inline-size: 100%;
    }

    /* The fixed bar floats over the flow, so the document reserves its
       height (2 x space-3 + the ~50px button + hairline) below the footer:
       the last footer link stays reachable at max scroll, including in
       engines without scroll timelines, where the bar never retires. */
    @media (width < 900px) {
        body {
            padding-block-end: calc(var(--space-16) + var(--space-3) + env(safe-area-inset-bottom));
        }
    }

    /* The bar and the rail's compact button retire as the apply band scrolls
       in, so two Apply buttons are never on screen together. Scroll-driven
       visibility, not decorative motion, so it is not gated on the
       reduced-motion preference. .job is the common ancestor of the band,
       the bar and the rail, which is what lets the named timeline reach them. */
    @supports (animation-timeline: view()) {
        .job {
            timeline-scope: --apply-card;
        }

        .apply {
            view-timeline-name: --apply-card;
        }

        .cta-bar,
        .button--compact {
            animation: retire linear both;
            animation-timeline: --apply-card;
            animation-range: entry 0% entry 50%;
        }

        /* Once the bar can retire, the footer no longer needs the reserve;
           its own safe-area padding is enough. */
        @media (width < 900px) {
            body {
                padding-block-end: 0;
            }
        }
    }

    @keyframes retire {
        to {
            opacity: 0;
            visibility: hidden;
        }
    }

    /* ---------- Grain: kills gradient banding in the background tints ---------- */

    body::after {
        content: "";
        position: fixed;
        inset: 0;
        z-index: -1;
        pointer-events: none;
        opacity: 0.035;
        mix-blend-mode: overlay;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
        background-size: 180px 180px;
    }

    /* ---------- Motion: opt-in only ---------- */

    @keyframes rise {
        from {
            opacity: 0;
            translate: 0 var(--space-3);
        }

        to {
            opacity: 1;
            translate: 0 0;
        }
    }

    @media (prefers-reduced-motion: no-preference) {
        .hiring-badge {
            transition:
                color var(--duration-fast) var(--ease),
                border-color var(--duration-fast) var(--ease);
        }

        /* Press is a plain ease-out; the spring plays only on release, where
           the overshoot reads as the button bouncing back. */
        .button {
            transition:
                background-position var(--duration-base) var(--ease),
                box-shadow var(--duration-base) var(--ease),
                scale var(--duration-fast) var(--ease-spring);

            &:active {
                transition: scale var(--duration-fast) var(--ease);
            }
        }

        .button__arrow {
            transition: translate var(--duration-base) var(--ease);
        }

        .button:hover .button__arrow {
            translate: var(--space-1) 0;
        }

        /* First paint: hero and rail fade in. Opacity only, so if the
           cross-document view transition also fades the page the two
           never visibly compound. */
        .hero,
        .rail {
            transition: opacity var(--duration-slow) var(--ease);

            @starting-style {
                opacity: 0;
            }
        }

        .rail {
            transition-delay: var(--duration-fast);
        }

        /* Scroll-driven reveals on leaf blocks only: a section never animates
           as a whole, so nothing compounds. Rows reveal in order simply
           because each enters the viewport after the one above it. */
        @supports (animation-timeline: view()) {
            .job__body :is(.section__title, .fit-split, .stack-block, .ladder__item, .offer__item),
            .job__body section > p,
            .apply__title,
            .apply__text,
            .apply__button {
                animation: rise var(--ease) both;
                animation-timeline: view();
                /* `cover` normalises on viewport + element height, so a short
                   row and a long paragraph rise over the same scroll distance. */
                animation-range: entry 0% cover 25%;
            }
        }
    }
}

/* ======================================================================
   Forced colours: keep shapes that are drawn with backgrounds
   ====================================================================== */

@media (forced-colors: active) {
    body::after,
    .apply::before {
        display: none;
    }

    .button {
        border: 1px solid currentColor;
    }
}

/* ======================================================================
   Print: colours come from the token remap in tokens.css
   ====================================================================== */

@media print {
    body::after,
    .apply::before,
    .cta-bar,
    .hiring-badge {
        display: none;
    }

    .job,
    .job__columns {
        display: block;
    }

    .rail {
        position: static;
        margin-block: var(--space-8);
    }

    .apply {
        margin-block-start: var(--space-12);
    }

    .hero,
    .rail,
    .button--compact,
    .job__body :is(.section__title, .fit-split, .stack-block, .ladder__item, .offer__item),
    .job__body section > p,
    .apply__title,
    .apply__text,
    .apply__button {
        animation: none;
        opacity: 1;
        translate: none;
    }

    .button {
        border: 1px solid currentColor;
        background: none;
        color: inherit;
        box-shadow: none;
    }
}
