/* Kestrel & Facet: a concept site by KTS Pro Solutions.
   Self-contained: this page loads no site stylesheet, and the site's Tailwind build does not scan
   this folder (src/assets/css/tailwind.css), so nothing here reaches any other page.

   Graphite and stone. The ring is made in a dark studio (warm graphite, a soft light behind the
   piece, champagne, the 3D), and the page then opens into daylight stone for the bespoke process
   and the collection, with the ring shown in a dark case on it. A contemporary display serif
   (Instrument Serif) against a modern grotesk (Geist). Soft corners, glass, pills.

   Contrast, measured (WCAG; QUALITY.md 3 holds every line of text to 4.5:1, headings included):
   - on graphite: text 14.5, body 9.5, muted 6.2, champagne 9.5; on the raised surface 13.0, 8.5,
     5.6, 8.5; on the studio glow 11.8, 7.7, 5.0, 7.7. Ink on a champagne pill 9.5.
   - on stone: ink 13.6, body 7.3, muted 6.0, bronze 5.5; on pearl 12.2, 6.6, 5.4, 5.0. Muted keeps 5.1
     at its worst, over the grain and the facet lines.
   - the foils are headings: the night foil's darkest stop is 6.1 on graphite; every stop of the
     day foil is at least 5.5 on stone and 5.0 on pearl. */

/* ---------------------------------------------------------------- fonts */

/* Self-hosted, open licence (fonts/OFL.txt), subset to this page's characters: 47 KB for all three */
@font-face {
    font-family: "KF Instrument";
    src: url("fonts/instrument-serif.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "KF Instrument";
    src: url("fonts/instrument-serif-italic.woff2") format("woff2");
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: "KF Geist";
    src: url("fonts/geist.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

/* ---------------------------------------------------------------- tokens */

:root {
    /* the studio */
    --kf-bg: #1C1A18;
    --kf-glow: #2E2B27;
    --kf-surface: #262320;
    --kf-text: #EEEAE3;
    --kf-text-soft: #C4BFB6;
    --kf-muted: #A09A90;
    --kf-accent: #D4BD8F;
    --kf-accent-hi: #ECDDBC;
    --kf-line: rgba(238, 234, 227, 0.1);
    --kf-line-strong: rgba(238, 234, 227, 0.18);

    /* daylight */
    --kf-ivory: #E7E3DB;
    --kf-pearl: #DDD8CF;
    --kf-ink: #1C1A18;
    --kf-ink-soft: #4A463F;
    --kf-ink-muted: #58534C;
    --kf-bronze: #6B5530;
    --kf-ink-line: rgba(28, 26, 24, 0.12);
    --kf-ink-line-strong: rgba(28, 26, 24, 0.24);

    /* foils: a metal's light across display type */
    --kf-foil: linear-gradient(100deg, #B0966A 0%, #ECDDBC 18%, #D4BD8F 36%, #B0966A 52%, #E3CFA6 70%, #ECDDBC 82%, #C4AA7B 100%);
    --kf-foil-day: linear-gradient(100deg, #5A4524 0%, #6B5530 22%, #463518 44%, #5A4524 64%, #6B5530 82%, #5A4524 100%);

    --kf-serif: "KF Instrument", "Instrument Serif", Georgia, "Times New Roman", serif;
    --kf-sans: "KF Geist", "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

    /* Geometry: a slim line of honesty at the top, a floating island of navigation under it */
    --kf-strip-h: 1.75rem;
    --kf-bar-h: 3.5rem;
    --kf-bar-gap: 0.75rem;
    --header-h: calc(var(--kf-strip-h) + var(--kf-bar-gap) * 2 + var(--kf-bar-h));
    --gutter: clamp(1rem, 4vw, 3.5rem);
    --kf-max: 90rem;
    --r-xl: 2rem;
    --r-lg: 1.375rem;
    --r-md: 1rem;
    --r-pill: 999px;

    /* Motion: long, soft landings */
    --kf-ease: cubic-bezier(0.2, 0.7, 0.1, 1);
    --kf-out: cubic-bezier(0.16, 1, 0.3, 1);
    --kf-in-out: cubic-bezier(0.65, 0, 0.35, 1);
}

@media (max-width: 59.99rem) {
    :root {
        --kf-bar-h: 3.25rem;
        --kf-bar-gap: 0.5rem;
        --r-xl: 1.5rem;
    }
}

/* ---------------------------------------------------------------- base */

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

html {
    background: var(--kf-bg);
    color: var(--kf-text);
    font-family: var(--kf-sans);
    font-weight: 400;
    -webkit-text-size-adjust: 100%;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

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

body {
    margin: 0;
    font-size: 1.0625rem;
    line-height: 1.65;
    letter-spacing: -0.005em;
}

::selection {
    background: var(--kf-accent);
    color: var(--kf-ink);
    -webkit-text-fill-color: var(--kf-ink);
}

img {
    display: block;
    max-width: 100%;
    height: auto;
}

a {
    color: inherit;
}

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

.kf-light :focus-visible {
    outline-color: var(--kf-bronze);
}

[id] {
    scroll-margin-top: var(--header-h);
}

.kf-skip {
    position: fixed;
    z-index: 50;
    left: 1rem;
    top: -5rem;
    padding: 0.75rem 1.25rem;
    border-radius: var(--r-pill);
    background: var(--kf-text);
    color: var(--kf-ink);
    font-weight: 500;
    text-decoration: none;
}

.kf-skip:focus {
    top: 1rem;
}

.kf-wrap {
    width: 100%;
    max-width: var(--kf-max);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

/* Foil: display type lit like metal. Still: a sweep of light across it would mean repainting the
   words on every frame of it. */
.kf-foil {
    background: var(--kf-foil);
    background-size: 250% 100%;
    background-position: 0 0;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* Small labels: the grotesk, set small, tracked and upper case */
.kf-eyebrow,
.kf-index,
.kf-step__num,
.kf-piece__num,
.kf-vitrine__no,
.kf-form__legend,
.kf-field__label,
.kf-counter__of {
    font-family: var(--kf-sans);
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.4;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- header */

.kf-header {
    position: fixed;
    z-index: 20;
    inset: 0 0 auto;
    pointer-events: none;
}

.kf-concept {
    pointer-events: auto;
    margin: 0;
    height: var(--kf-strip-h);
    display: flex;
    align-items: center;
    justify-content: center;
    padding-inline: 1rem;
    background: var(--kf-surface);
    border-bottom: 1px solid var(--kf-line);
    font-size: 0.75rem;
    font-weight: 400;
    line-height: 1;
    letter-spacing: 0.01em;
    color: var(--kf-text-soft);
    white-space: nowrap;
    transition: background-color 0.6s var(--kf-ease), color 0.6s var(--kf-ease), border-color 0.6s var(--kf-ease);
}

.kf-concept__short {
    display: none;
}

@media (max-width: 39.99rem) {
    .kf-concept__long {
        display: none;
    }

    .kf-concept__short {
        display: inline;
    }
}

/* The island: navigation floating over the page on frosted glass */
.kf-bar {
    pointer-events: auto;
    width: min(calc(100% - 2 * var(--gutter)), 78rem);
    height: var(--kf-bar-h);
    margin: var(--kf-bar-gap) auto 0;
    padding: 0 0.375rem 0 1.375rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    border: 1px solid var(--kf-line);
    border-radius: var(--r-pill);
    background: rgba(28, 26, 24, 0.82);
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
    backdrop-filter: blur(16px) saturate(1.3);
    box-shadow: 0 0.75rem 2.5rem -1.25rem rgba(0, 0, 0, 0.6);
    transition: background-color 0.6s var(--kf-ease), border-color 0.6s var(--kf-ease), box-shadow 0.6s var(--kf-ease);
}

.kf-mark {
    font-family: var(--kf-serif);
    font-size: 1.4375rem;
    font-weight: 400;
    line-height: 1;
    letter-spacing: -0.005em;
    text-decoration: none;
    white-space: nowrap;
    color: var(--kf-text);
    transition: color 0.6s var(--kf-ease);
}

.kf-amp {
    font-style: italic;
    color: var(--kf-accent);
    transition: color 0.6s var(--kf-ease);
}

.kf-nav {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.kf-nav__link {
    display: inline-flex;
    align-items: center;
    height: 2.75rem;
    padding-inline: 1rem;
    border-radius: var(--r-pill);
    font-size: 0.875rem;
    font-weight: 450;
    letter-spacing: 0;
    text-decoration: none;
    color: var(--kf-text-soft);
    transition: color 0.35s var(--kf-ease), background-color 0.35s var(--kf-ease);
}

.kf-nav__cta {
    display: inline-flex;
    align-items: center;
    height: 2.75rem;
    margin-left: 0.5rem;
    padding-inline: 1.25rem;
    border-radius: var(--r-pill);
    background: var(--kf-accent);
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0;
    text-decoration: none;
    color: var(--kf-ink);
    transition: background-color 0.35s var(--kf-ease), color 0.35s var(--kf-ease), transform 0.7s var(--kf-out);
}

@media (hover: hover) {
    .kf-nav__link:hover {
        color: var(--kf-text);
        background: rgba(238, 234, 227, 0.08);
    }

    .kf-nav__cta:hover {
        background: var(--kf-accent-hi);
    }
}

@media (max-width: 59.99rem) {
    .kf-nav__link {
        display: none;
    }

    .kf-bar {
        padding-left: 1.125rem;
    }

    .kf-mark {
        font-size: 1.25rem;
    }

    .kf-nav__cta {
        height: 2.375rem;
        padding-inline: 1rem;
        font-size: 0.8125rem;
    }
}

/* Over the light sections the header turns to day with them (kf.js sets is-light). */
.is-light .kf-concept {
    background: var(--kf-pearl);
    border-bottom-color: var(--kf-ink-line);
    color: var(--kf-ink-soft);
}

.is-light .kf-bar {
    background: rgba(231, 227, 219, 0.94);
    border-color: var(--kf-ink-line);
    box-shadow: 0 0.75rem 2.5rem -1.25rem rgba(28, 26, 24, 0.3);
}

.is-light .kf-mark {
    color: var(--kf-ink);
}

.is-light .kf-amp {
    color: var(--kf-bronze);
}

.is-light .kf-nav__link {
    color: var(--kf-ink-soft);
}

.is-light .kf-nav__cta {
    background: var(--kf-ink);
    color: var(--kf-ivory);
}

@media (hover: hover) {
    .is-light .kf-nav__link:hover {
        color: var(--kf-ink);
        background: rgba(28, 26, 24, 0.07);
    }

    .is-light .kf-nav__cta:hover {
        background: var(--kf-ink-soft);
    }
}

.is-light :focus-visible {
    outline-color: var(--kf-bronze);
}

/* How far down the page you are: a hairline of champagne under the strip. */
.kf-progress {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(var(--kf-strip-h) - 1px);
    height: 1px;
    background: var(--kf-accent);
    transform: scaleX(0);
    transform-origin: left;
    pointer-events: none;
    will-change: transform;
}

.is-light .kf-progress {
    background: var(--kf-bronze);
}

/* ---------------------------------------------------------------- buttons */

/* A pill of champagne, its arrow in a dark bead that slides on hover */
.kf-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.875rem;
    height: 3.5rem;
    padding: 0 0.4375rem 0 1.625rem;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--kf-accent);
    color: var(--kf-ink);
    font: inherit;
    font-size: 0.9375rem;
    font-weight: 500;
    letter-spacing: -0.005em;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.4s var(--kf-ease), transform 0.7s var(--kf-out);
}

.kf-btn__arrow {
    display: grid;
    place-items: center;
    width: 2.625rem;
    height: 2.625rem;
    border-radius: 50%;
    background: var(--kf-ink);
    color: var(--kf-accent);
    overflow: hidden;
}

.kf-btn__arrow svg {
    width: 0.9375rem;
    height: 0.9375rem;
    transition: transform 0.6s var(--kf-out);
}

@media (hover: hover) {
    .kf-btn:hover {
        background: var(--kf-accent-hi);
    }

    .kf-btn:hover .kf-btn__arrow svg {
        transform: translateX(0.2rem);
    }
}

.kf-btn > span:first-child {
    display: inline-block;
}

/* Buttons that lean a little toward a mouse pointer (kf.js moves them; it never does on touch or
   with reduced motion). The words inside lean a little further. */
.kf-magnetic > span {
    transition: transform 0.7s var(--kf-out);
}

/* ---------------------------------------------------------------- the theatre */

/* The stage is sticky for the whole of the hero and the four chapters, and the sections scroll
   over it. Its frame sits exactly where each section's own still sits, so the 3D and the stills
   share one rectangle and the page has the same layout with or without the 3D. */

.kf-theatre {
    position: relative;
}

.kf-stage {
    position: sticky;
    top: 0;
    z-index: 0;
    height: 100svh;
    margin-bottom: -100svh;
    pointer-events: none;
}

/* flow-root: on a phone the frame's top margin would otherwise collapse through the stage and
   move the whole theatre down by the header's height */
.kf-stage__grid {
    display: flow-root;
}

.kf-hero,
.kf-chapter {
    position: relative;
    z-index: 1;
}

.kf-visual {
    display: grid;
    place-items: center;
}

.kf-frame {
    margin: 0;
    aspect-ratio: 1;
}

/* Desktop: copy left, the ring right. */
@media (min-width: 60rem) {
    :root {
        --vis-h: calc(100svh - var(--header-h));
    }

    .kf-stage__grid,
    .kf-hero__grid,
    .kf-chapter__grid {
        display: grid;
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        column-gap: clamp(2rem, 5vw, 5rem);
    }

    .kf-visual {
        grid-column: 2;
        grid-row: 1;
        align-self: start;
        height: var(--vis-h);
    }

    .kf-frame {
        width: min(100%, calc(var(--vis-h) - 3rem));
    }

    .kf-stage__visual,
    .kf-hero__visual {
        margin-top: var(--header-h);
    }

    .kf-hero__grid {
        min-height: 100svh;
    }

    /* the copy is centred in the space under the header, never closer to it than a clear gap */
    .kf-hero__copy {
        grid-column: 1;
        grid-row: 1;
        align-self: center;
        padding-block: calc(var(--header-h) + clamp(1.5rem, 5vh, 4rem)) clamp(1.5rem, 5vh, 4rem);
    }

    .kf-chapter__grid {
        min-height: 170svh;
    }

    .kf-chapter__visual {
        position: sticky;
        top: var(--header-h);
    }

    .kf-card {
        grid-column: 1;
        grid-row: 1;
        align-self: center;
        max-width: 30rem;
    }
}

/* Phone and tablet: the ring sits at the top of the screen and the words rise over it. */
@media (max-width: 59.99rem) {
    :root {
        --vis-h: min(50svh, calc(100vw - 2 * var(--gutter) + 2rem));
        --kf-feather: calc(0.25 * var(--vis-h));
    }

    .kf-visual {
        height: var(--vis-h);
    }

    .kf-frame {
        width: min(100%, calc(var(--vis-h) - 1rem));
    }

    .kf-stage__visual,
    .kf-hero__visual {
        margin-top: var(--header-h);
    }

    /* The ring first, where the stage draws it; the words under it */
    .kf-hero__grid {
        display: flex;
        flex-direction: column;
    }

    .kf-hero__visual {
        order: -1;
    }

    .kf-hero__copy {
        position: relative;
        isolation: isolate;
        padding-block: 1.25rem 4.5rem;
    }

    /* With the 3D on, the stage stays pinned at the top of the screen and the hero's words rise
       straight through it, so they carry a surface of their own, as the chapter cards do. It is
       the page's own graphite, solid behind the words and feathered above and below them: at rest
       it cannot be seen, and as the words rise the stone sinks behind them into the dark.
       - The feather is a quarter of the frame's height, which keeps it inside the empty dark below
         the stone at rest on any phone.
       - Its ramp is smootherstep in six steps: a bright facet shows any corner in a straight ramp
         as a line across the stone.
       - One gradient, not two layers, so no seam can open between them.
       Without the 3D the hero's still scrolls away with the words, and this is off. */
    .kf-3d-ready .kf-hero__copy::before {
        --f: var(--kf-feather);
        content: "";
        position: absolute;
        z-index: -1;
        inset: calc(-1 * var(--f)) calc(-1 * var(--gutter)) calc(4.5rem - var(--f));
        background: linear-gradient(
            rgba(28, 26, 24, 0),
            rgba(28, 26, 24, 0.035) calc(var(--f) / 6),
            rgba(28, 26, 24, 0.21) calc(var(--f) * 2 / 6),
            rgba(28, 26, 24, 0.5) calc(var(--f) * 3 / 6),
            rgba(28, 26, 24, 0.79) calc(var(--f) * 4 / 6),
            rgba(28, 26, 24, 0.965) calc(var(--f) * 5 / 6),
            var(--kf-bg) var(--f),
            var(--kf-bg) calc(100% - var(--f)),
            rgba(28, 26, 24, 0.965) calc(100% - var(--f) * 5 / 6),
            rgba(28, 26, 24, 0.79) calc(100% - var(--f) * 4 / 6),
            rgba(28, 26, 24, 0.5) calc(100% - var(--f) * 3 / 6),
            rgba(28, 26, 24, 0.21) calc(100% - var(--f) * 2 / 6),
            rgba(28, 26, 24, 0.035) calc(100% - var(--f) / 6),
            rgba(28, 26, 24, 0)
        );
        pointer-events: none;
    }

    .kf-chapter__grid {
        min-height: 175svh;
        padding-bottom: 25svh;
    }

    .kf-chapter__visual {
        position: sticky;
        top: var(--header-h);
    }

    .kf-card {
        position: relative;
        z-index: 2;
        margin-top: 38svh;
        padding: 1.75rem 1.5rem 1.625rem;
        border: 1px solid var(--kf-line);
        border-radius: var(--r-lg);
        background: var(--kf-surface);
        box-shadow: 0 1.5rem 3rem -1.5rem rgba(0, 0, 0, 0.6);
    }
}

/* ---------------------------------------------------------------- hero and chapters */

.kf-eyebrow,
.kf-index {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    margin: 0 0 1.5rem;
    color: var(--kf-accent);
}

.kf-index span {
    font-family: var(--kf-serif);
    font-style: italic;
    font-size: 1.375rem;
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1;
    text-transform: none;
}

.kf-index::before,
.kf-eyebrow::before {
    content: "";
    width: 1.75rem;
    height: 1px;
    background: currentColor;
    transform-origin: left;
}

/* The headline is sized by the window's height as well as its width, so it always fits under the
   header with room to breathe, whatever the screen. */
.kf-display {
    margin: 0;
    font-family: var(--kf-serif);
    font-weight: 400;
    font-size: clamp(3.25rem, min(8.2vw, 13vh), 9rem);
    line-height: 0.94;
    letter-spacing: -0.02em;
    text-wrap: balance;
}

/* Each line of the headline rises into place through a mask. The mask clips only the edge the
   line rises from: the tails of an f, a comma or a descender are never cut, above, below or at
   the sides. */
.kf-line {
    display: inline-block;
    vertical-align: top;
    clip-path: inset(-0.6em -0.6em -0.3em -0.6em);
}

.kf-line__in {
    display: inline-block;
}

.kf-display em,
.kf-title em {
    font-style: italic;
    color: var(--kf-accent);
}

.kf-display em.kf-foil {
    color: transparent;
    padding-right: 0.04em;
}

/* On a desktop the headline is set as three deliberate lines; a phone wraps it on its own */
@media (min-width: 60rem) {
    .kf-display .kf-line {
        display: block;
    }
}

.kf-lede {
    max-width: 29rem;
    margin: 1.75rem 0 0;
    font-size: 1.1875rem;
    font-weight: 400;
    line-height: 1.6;
    color: var(--kf-text-soft);
}

.kf-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 2rem;
    margin: 2.5rem 0 0;
}

/* The scroll cue: a small capsule with a bead that falls through it */
.kf-scrollcue {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.875rem;
    min-height: 2.75rem;
    font-size: 0.875rem;
    font-weight: 450;
    text-decoration: none;
    color: var(--kf-muted);
}

.kf-scrollcue::before {
    content: "";
    width: 1.375rem;
    height: 2.125rem;
    border: 1px solid var(--kf-line-strong);
    border-radius: var(--r-pill);
}

.kf-scrollcue::after {
    content: "";
    position: absolute;
    left: calc(0.6875rem - 2px);
    top: calc(50% - 0.6rem);
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--kf-accent);
}

/* The bead's slow fall. Transform and opacity only, and not at all for anyone who has asked for
   less motion. */
@media (prefers-reduced-motion: no-preference) {
    .kf-scrollcue::after {
        animation: kf-cue 2.4s var(--kf-ease) infinite;
    }

    @keyframes kf-cue {
        0% { transform: translateY(0); opacity: 0; }
        20% { opacity: 1; }
        70% { transform: translateY(0.85rem); opacity: 1; }
        100% { transform: translateY(0.85rem); opacity: 0; }
    }
}

.kf-title {
    margin: 0 0 1.5rem;
    font-family: var(--kf-serif);
    font-weight: 400;
    font-size: clamp(2.5rem, min(4.8vw, 8.5vh), 4.75rem);
    line-height: 0.98;
    letter-spacing: -0.015em;
    text-wrap: balance;
}

.kf-card p:not(.kf-index) {
    margin: 0 0 1rem;
    color: var(--kf-text-soft);
}

.kf-card p:last-child {
    margin-bottom: 0;
}

/* The hero arrives: the eyebrow's line draws, the headline rises line by line, then the words and
   the button follow, all within a second and a half. CSS only, so it needs no script and starts
   with the first paint; transforms and opacity only, so nothing repaints; the hero's still, the
   page's largest paint, never moves. */
@media (prefers-reduced-motion: no-preference) {
    .kf-hero .kf-eyebrow {
        animation: kf-rise 1s var(--kf-out) 0.05s both;
    }

    .kf-hero .kf-eyebrow::before {
        animation: kf-draw 1.1s var(--kf-out) 0.05s both;
    }

    .kf-hero .kf-line__in {
        animation: kf-line-in 1.15s var(--kf-out) both;
    }

    .kf-hero .kf-line:nth-child(1) .kf-line__in { animation-delay: 0.1s; }
    .kf-hero .kf-line:nth-child(2) .kf-line__in { animation-delay: 0.18s; }
    .kf-hero .kf-line:nth-child(3) .kf-line__in { animation-delay: 0.26s; }

    .kf-hero .kf-lede {
        animation: kf-rise 1.1s var(--kf-out) 0.38s both;
    }

    .kf-hero .kf-actions {
        animation: kf-rise 1.1s var(--kf-out) 0.48s both;
    }
}

@keyframes kf-line-in {
    from { transform: translate3d(0, 140%, 0); }
    to { transform: none; }
}

@keyframes kf-rise {
    from { opacity: 0; transform: translate3d(0, 1.25rem, 0); }
    to { opacity: 1; transform: none; }
}

@keyframes kf-draw {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
}

/* Scroll-driven, where the browser has scroll timelines: these move with the scroll on the
   compositor, with no script at all (motion.js leaves them alone when it sees support). The
   ranges and easings are the ones the script uses without it. */
@supports (animation-timeline: scroll()) {
    @media (prefers-reduced-motion: no-preference) {
        .kf-progress {
            animation: kf-grow-x linear both;
            animation-timeline: scroll(root block);
        }

        .kf-js .kf-dawn {
            view-timeline: --kf-dawn block;
        }

        /* the champagne line draws across as the dawn rises into the screen, and fades as the
           light opens */
        .kf-js .kf-dawn__line {
            animation: kf-draw-x cubic-bezier(0.33, 1, 0.68, 1) both, kf-fade-out linear both;
            animation-timeline: --kf-dawn, --kf-dawn;
            animation-range: entry 20% entry 90%, contain 30% contain 55%;
        }

        /* the light opens out of the line while the dawn is held on the screen */
        .kf-js .kf-dawn__light {
            animation: kf-open-y cubic-bezier(0.65, 0, 0.35, 1) both;
            animation-timeline: --kf-dawn;
            animation-range: contain 2% contain 64%;
        }

        /* then its words arrive */
        .kf-js .kf-dawn__a,
        .kf-js .kf-dawn__b {
            transition: none;
            animation: kf-rise cubic-bezier(0.16, 1, 0.3, 1) both;
            animation-timeline: --kf-dawn;
            animation-range: contain 42% contain 62%;
        }

        .kf-js .kf-dawn__b {
            animation-range: contain 48% contain 68%;
        }
    }
}

@keyframes kf-grow-x {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
}

@keyframes kf-draw-x {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
}

@keyframes kf-fade-out {
    from { opacity: 1; }
    to { opacity: 0; }
}

@keyframes kf-open-y {
    from { transform: scaleY(0.0001); }
    to { transform: scaleY(1); }
}

/* Endless motion rests while it is off the screen (kf.js marks it is-off) */
.is-off,
.is-off *,
.is-off::before,
.is-off::after {
    animation-play-state: paused !important;
}

/* ---------------------------------------------------------------- the loupe */

/* Round the stone at rest: a bezel of ticks, turning slowly, and on a wide screen its anatomy,
   drawn to the 3D's own camera. It arrives after the headline and leaves as soon as the page moves
   (motion.js sets is-away), so it never drifts from the stone the stage holds in place. */
.kf-hero__visual .kf-frame {
    position: relative;
}

/* The bezel turns as a whole square, and a turning square's corners reach past its frame: the
   hero clips its sides (clip, not hidden, so nothing becomes a scroller), which cuts nothing that
   shows, since the ring and every call-out sit inside the window. */
.kf-hero {
    overflow-x: clip;
}

.kf-loupe {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    transition: opacity 0.5s var(--kf-ease);
}

.kf-loupe.is-away {
    opacity: 0;
}

.kf-loupe svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    fill: none;
}

.kf-loupe__ring {
    stroke: var(--kf-accent);
    transform-origin: 50% 48%;
}

.kf-loupe__ring circle,
.kf-loupe__ring path {
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

.kf-loupe__ring circle {
    stroke-opacity: 0.3;
}

.kf-loupe__ring path {
    stroke-opacity: 0.55;
}

.kf-loupe__lines line {
    stroke: var(--kf-accent);
    stroke-opacity: 0.6;
    stroke-width: 0.14;
}

.kf-loupe__lines circle {
    fill: var(--kf-accent);
}

.kf-anno {
    position: absolute;
    font-size: 0.6875rem;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--kf-text-soft);
}

.kf-anno--top { transform: translate(-50%, -100%); }
.kf-anno--bottom { transform: translate(-50%, 0); }
.kf-anno--left { transform: translate(-100%, -50%); }
.kf-anno--right { transform: translate(0, -50%); }

/* the anatomy is for a wide screen; a phone keeps the bezel */
.kf-loupe__lines,
.kf-anno {
    display: none;
}

@media (min-width: 60rem) {
    .kf-loupe__lines,
    .kf-anno {
        display: block;
    }
}

@media (prefers-reduced-motion: no-preference) {
    .kf-loupe__ring {
        animation: kf-fade 1.4s var(--kf-ease) 0.45s both, kf-spin 160s linear 0.45s infinite;
    }

    .kf-loupe__lines line {
        stroke-dasharray: 1;
        stroke-dashoffset: 1;
        animation: kf-stroke 1.1s var(--kf-out) calc(0.95s + var(--n) * 0.12s) forwards;
    }

    .kf-loupe__lines circle {
        animation: kf-fade 0.9s var(--kf-ease) calc(0.85s + var(--n) * 0.12s) both;
    }

    .kf-anno {
        animation: kf-fade 0.9s var(--kf-ease) calc(1.35s + var(--n) * 0.12s) both;
    }
}

@keyframes kf-stroke {
    to { stroke-dashoffset: 0; }
}

@keyframes kf-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* The hero's foot: a ruled line under the words, with the scroll cue and the four stages of the
   making, each a way in. On a phone, the cue alone. */
.kf-hero__foot {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    margin-top: 2rem;
}

.kf-hero__index {
    display: none;
}

@media (min-width: 60rem) {
    .kf-hero__foot {
        max-width: 38rem;
        margin-top: clamp(2rem, 5vh, 3.25rem);
        padding-top: 1rem;
        border-top: 1px solid var(--kf-line);
    }

    /* the capsule speaks for itself here; its words stay for a screen reader */
    .kf-hero__foot .kf-scrollcue__text {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .kf-hero__index {
        display: flex;
        flex-wrap: wrap;
        gap: 0 clamp(1rem, 2.2vw, 2rem);
        list-style: none;
        margin: 0;
        padding: 0;
    }

    .kf-hero__index a {
        display: inline-flex;
        align-items: center;
        gap: 0.45rem;
        min-height: 2.75rem;
        font-size: 0.875rem;
        font-weight: 450;
        text-decoration: none;
        color: var(--kf-text-soft);
        transition: color 0.3s var(--kf-ease);
    }

    .kf-hero__index span {
        font-family: var(--kf-serif);
        font-style: italic;
        font-size: 1.125rem;
        line-height: 1;
        color: var(--kf-accent);
    }

    @media (hover: hover) {
        .kf-hero__index a:hover {
            color: var(--kf-text);
        }
    }
}

@media (prefers-reduced-motion: no-preference) {
    .kf-hero .kf-hero__foot {
        animation: kf-rise 1.1s var(--kf-out) 0.6s both;
    }
}

/* On a short wide window the foot would push the button off the first screen: it goes (the rail
   beside the chapters offers the same four ways in). */
@media (min-width: 60rem) and (max-height: 47.5rem) {
    .kf-hero__foot {
        display: none;
    }
}

/* ---------------------------------------------------------------- the making rail */

/* Beside the chapters on a wide screen: where the making is up to, following the 3D, and a way to
   jump to any stage. Off the page elsewhere. */
.kf-rail {
    display: none;
}

@media (min-width: 60rem) and (min-height: 34rem) {
    .kf-rail {
        display: block;
        position: fixed;
        z-index: 15;
        left: calc(var(--gutter) / 2);
        top: 50%;
        transform: translate(-50%, -50%);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.6s var(--kf-ease), visibility 0s linear 0.6s;
    }

    .kf-rail.is-on {
        opacity: 1;
        visibility: visible;
        transition: opacity 0.6s var(--kf-ease);
    }
}

.kf-rail__list {
    position: relative;
    z-index: 1;
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 1rem;
}

.kf-rail__link {
    position: relative;
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    text-decoration: none;
    color: var(--kf-muted);
    transition: color 0.4s var(--kf-ease);
}

.kf-rail__num {
    display: grid;
    place-items: center;
    min-width: 1.9rem;
    height: 1.9rem;
    padding-inline: 0.2rem;
    border-radius: var(--r-pill);
    background: var(--kf-bg);
    font-family: var(--kf-serif);
    font-style: italic;
    font-size: 1.125rem;
    line-height: 1;
}

.kf-rail__name {
    position: absolute;
    left: 100%;
    top: 50%;
    padding: 0.4rem 0.75rem;
    border-radius: var(--r-pill);
    background: var(--kf-surface);
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    white-space: nowrap;
    color: var(--kf-text-soft);
    opacity: 0;
    transform: translate(-0.5rem, -50%);
    transition: opacity 0.35s var(--kf-ease), transform 0.5s var(--kf-out);
    pointer-events: none;
}

.kf-rail__link[aria-current="step"] {
    color: var(--kf-accent);
}

.kf-rail__link:hover,
.kf-rail__link:focus-visible {
    color: var(--kf-text);
}

.kf-rail__link:hover .kf-rail__name,
.kf-rail__link:focus-visible .kf-rail__name {
    opacity: 1;
    transform: translate(0, -50%);
}

.kf-rail__track {
    position: absolute;
    left: 50%;
    top: 1.375rem;
    bottom: 1.375rem;
    width: 1px;
    background: var(--kf-line-strong);
}

.kf-rail__fill {
    position: absolute;
    inset: 0;
    background: var(--kf-accent);
    transform: scaleY(0);
    transform-origin: top;
    will-change: transform;
}

/* ---------------------------------------------------------------- arriving words */

/* Words and lines arrive as they come into view (kf.js marks them is-in). The hidden states apply
   only while kf.js is running (kf-js, set before the first paint and dropped if the script never
   arrives) and never with reduced motion, so the words are always there without either. */
@media (prefers-reduced-motion: no-preference) {
    .kf-js [data-reveal] {
        opacity: 0;
        transform: translate3d(0, 1.4rem, 0);
        transition: opacity 1.2s var(--kf-out) var(--d, 0s), transform 1.4s var(--kf-out) var(--d, 0s);
    }

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

    .kf-js .kf-index[data-reveal]::before {
        transform: scaleX(0);
        transition: transform 1.4s var(--kf-out) calc(var(--d, 0s) + 0.1s);
    }

    .kf-js .kf-index[data-reveal].is-in::before {
        transform: none;
    }

    .kf-js [data-split] .kf-w > span {
        transform: translate3d(0, 140%, 0);
        transition: transform 1.3s var(--kf-out) calc(var(--d, 0s) + var(--i, 0) * 55ms);
    }

    .kf-js [data-split].is-in .kf-w > span {
        transform: none;
    }

    /* The case rises into the display light, and its controls follow it in (transform and
       opacity, so the compositor moves it and nothing repaints) */
    .kf-js [data-reveal-clip] {
        opacity: 0;
        transform: translate3d(0, 2.5rem, 0) scale(0.97);
        transition: opacity 1.2s var(--kf-out), transform 1.6s var(--kf-out);
    }

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

    .kf-js [data-reveal-clip] .kf-vitrine__ui {
        opacity: 0;
        transition: opacity 0.9s var(--kf-out) 0.9s;
    }

    .kf-js [data-reveal-clip].is-in .kf-vitrine__ui {
        opacity: 1;
    }
}

/* A word in its mask (kf.js wraps each word of a [data-split] title). As with the headline, the
   mask clips only the edge the word rises from, so no tail is ever cut. */
.kf-w {
    display: inline-block;
    vertical-align: top;
    clip-path: inset(-0.6em -0.5em -0.3em -0.5em);
}

.kf-w > span {
    display: inline-block;
}

/* The stills and the 3D. Each still is the frame the 3D shows at that point, drawn by the same
   code, and the canvas sits in the stage's frame, the same rectangle, under them. The canvas is
   not shown until a frame of the 3D has been drawn on it (kf-3d-ready): until then the stills
   are the page. Then the stills dissolve into the 3D, and once they have (kf-3d-settled) the
   chapter stills are taken out of the page, so the ones not yet loaded never are. */
.kf-still img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 0.9s var(--kf-ease);
}

.kf-stage .kf-frame {
    position: relative;
}

.kf-canvas {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    opacity: 0;
}

.kf-3d-ready .kf-canvas {
    opacity: 1;
}

.kf-3d-ready .kf-still img {
    opacity: 0;
}

.kf-3d-settled .kf-chapter .kf-still img {
    display: none;
}

/* ---------------------------------------------------------------- the dawn */

/* From the studio into daylight. As it is scrolled through, a champagne line crosses the graphite
   and the stone opens out of it to fill the screen; then the words arrive. Without kf.js, or with
   reduced motion, it is simply the opening of the light: the stone band and its words, still. */
.kf-dawn {
    position: relative;
    z-index: 1;
    background: var(--kf-ivory);
    color: var(--kf-ink);
}

.kf-dawn__pin {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 62svh;
    padding: clamp(6rem, 12vw, 10rem) var(--gutter) clamp(2rem, 5vw, 4rem);
    overflow: hidden;
}

.kf-dawn__light,
.kf-dawn__line {
    display: none;
}

.kf-dawn__text {
    position: relative;
    z-index: 1;
    margin: 0;
    max-width: 16ch;
    font-family: var(--kf-serif);
    font-weight: 400;
    font-size: clamp(2.75rem, min(6.4vw, 11vh), 6.5rem);
    line-height: 0.98;
    letter-spacing: -0.02em;
    text-align: center;
    text-wrap: balance;
    color: var(--kf-ink);
}

.kf-dawn__a,
.kf-dawn__b {
    display: block;
}

.kf-dawn__b {
    margin-top: 0.08em;
    padding-inline: 0.05em;
    font-style: italic;
    background: var(--kf-foil-day);
    background-size: 250% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

@media (prefers-reduced-motion: no-preference) {
    .kf-js .kf-dawn {
        height: 190svh;
        background: var(--kf-bg);
    }

    /* The theatre's last frame sinks into the dark as the dawn rises over it, rather than being
       cut by its edge (the same eased feather as the hero's words on a phone) */
    .kf-js .kf-dawn::before {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        bottom: 100%;
        height: 45svh;
        background: linear-gradient(
            rgba(28, 26, 24, 0),
            rgba(28, 26, 24, 0.035) 16.7%,
            rgba(28, 26, 24, 0.21) 33.3%,
            rgba(28, 26, 24, 0.5) 50%,
            rgba(28, 26, 24, 0.79) 66.7%,
            rgba(28, 26, 24, 0.965) 83.3%,
            var(--kf-bg)
        );
        pointer-events: none;
    }

    .kf-js .kf-dawn__pin {
        position: sticky;
        top: 0;
        height: 100svh;
        min-height: 0;
        padding: var(--header-h) var(--gutter) 0;
    }

    .kf-js .kf-dawn__light {
        display: block;
        position: absolute;
        inset: 0;
        background: var(--kf-ivory);
        transform: scaleY(0);
        transform-origin: 50% calc(50% + var(--header-h) / 2);
        will-change: transform;
    }

    .kf-js .kf-dawn__line {
        display: block;
        position: absolute;
        left: 0;
        right: 0;
        top: calc(50% + var(--header-h) / 2);
        height: 1px;
        background: linear-gradient(90deg, rgba(212, 189, 143, 0), var(--kf-accent) 22%, var(--kf-accent-hi) 50%, var(--kf-accent) 78%, rgba(212, 189, 143, 0));
        transform: scaleX(0);
        will-change: transform, opacity;
    }

    .kf-js .kf-dawn__a,
    .kf-js .kf-dawn__b {
        opacity: 0;
        transform: translate3d(0, 1.5rem, 0);
        transition: opacity 1s var(--kf-out), transform 1.3s var(--kf-out);
    }

    .kf-js .kf-dawn__b {
        transition-delay: 0.14s;
    }

    .kf-js .kf-dawn.is-day .kf-dawn__a,
    .kf-js .kf-dawn.is-day .kf-dawn__b {
        opacity: 1;
        transform: none;
    }
}

/* ---------------------------------------------------------------- the light sections */

.kf-light {
    position: relative;
    z-index: 1;
    background: var(--kf-ivory);
    color: var(--kf-ink);
}

.kf-light .kf-index {
    color: var(--kf-bronze);
}

.kf-light .kf-title {
    color: var(--kf-ink);
}

.kf-section__head {
    max-width: 46rem;
    margin-bottom: clamp(3rem, 7vw, 5.5rem);
}

.kf-section__intro {
    max-width: 34rem;
    margin: 0;
    font-size: 1.1875rem;
    font-weight: 400;
    color: var(--kf-text-soft);
}

.kf-light .kf-section__intro {
    color: var(--kf-ink-soft);
}

/* ---------------------------------------------------------------- the bespoke process */

.kf-bespoke {
    padding-block: clamp(3rem, 7vw, 6rem) clamp(5rem, 10vw, 9rem);
}

.kf-counter {
    display: none;
}

.kf-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}

/* The line the steps hang from, and its fill as you move down them (kf.js sets --fill) */
.kf-steps::before,
.kf-steps::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 1px;
}

.kf-steps::before {
    background: var(--kf-ink-line-strong);
}

.kf-steps::after {
    background: var(--kf-bronze);
    transform: scaleY(var(--fill, 0));
    transform-origin: top;
    transition: transform 1.1s var(--kf-out);
}

.kf-step {
    position: relative;
    padding: clamp(2.25rem, 5vw, 4rem) 0 clamp(2.25rem, 5vw, 4rem) clamp(1.75rem, 4vw, 3.5rem);
}

.kf-step + .kf-step {
    border-top: 1px solid var(--kf-ink-line);
}

/* The bead on the line, cut like a facet: lit when the step is reached */
.kf-step::before {
    content: "";
    position: absolute;
    left: -0.3125rem;
    top: calc(clamp(2.25rem, 5vw, 4rem) + 0.95rem);
    width: 0.625rem;
    height: 0.625rem;
    border: 1px solid var(--kf-ink-line-strong);
    background: var(--kf-ivory);
    transform: rotate(45deg);
    transition: background-color 0.6s var(--kf-ease), border-color 0.6s var(--kf-ease);
}

.kf-step.is-active::before,
.kf-step.is-past::before {
    background: var(--kf-bronze);
    border-color: var(--kf-bronze);
}

.kf-step__num {
    display: block;
    margin-bottom: 0.875rem;
    color: var(--kf-ink-muted);
    transition: color 0.6s var(--kf-ease);
}

.kf-step.is-active .kf-step__num {
    color: var(--kf-bronze);
}

.kf-step__title {
    margin: 0 0 0.875rem;
    font-family: var(--kf-serif);
    font-weight: 400;
    font-size: clamp(2.125rem, 3.8vw, 3.5rem);
    line-height: 1;
    letter-spacing: -0.015em;
}

.kf-step p {
    max-width: 31rem;
    margin: 0;
    color: var(--kf-ink-soft);
}

@media (min-width: 60rem) {
    .kf-bespoke__grid {
        display: grid;
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        column-gap: clamp(2rem, 6vw, 7rem);
        align-items: start;
    }

    .kf-bespoke__aside {
        position: sticky;
        top: calc(var(--header-h) + clamp(2rem, 5vw, 4rem));
    }

    .kf-step {
        min-height: 42svh;
        display: flex;
        flex-direction: column;
        justify-content: center;
    }

    /* The big numeral that turns over as the steps go by */
    .kf-counter {
        display: flex;
        align-items: flex-end;
        gap: 1rem;
        margin-top: clamp(2rem, 5vw, 4rem);
    }

    .kf-counter__mask {
        display: block;
        height: 1em;
        overflow: hidden;
        font-family: var(--kf-serif);
        font-style: italic;
        font-size: clamp(6.5rem, 12vw, 11.5rem);
        line-height: 1;
    }

    .kf-counter__reel {
        display: block;
        transition: transform 1.1s var(--kf-out);
    }

    .kf-counter__reel span {
        display: block;
        height: 1em;
        padding-right: 0.08em;
        background: var(--kf-foil-day);
        background-size: 250% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
    }

    .kf-counter__of {
        padding-bottom: 1.4rem;
        color: var(--kf-ink-muted);
    }
}

/* ---------------------------------------------------------------- the collection */

.kf-collection {
    padding-block: clamp(2rem, 5vw, 4rem) clamp(6rem, 12vw, 10rem);
}

.kf-showcase {
    display: grid;
    gap: 2.5rem;
}

@media (min-width: 60rem) {
    .kf-showcase {
        grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
        column-gap: clamp(2.5rem, 6vw, 7rem);
        align-items: center;
    }
}

/* The vitrine: a dark studio case set into the light page, soft-cornered, a champagne hairline
   inside its edge. */
.kf-vitrine {
    position: relative;
    justify-self: center;
    width: min(100%, calc((100svh - var(--header-h) - 5rem) * 0.8));
    aspect-ratio: 4 / 5;
    border-radius: var(--r-xl);
    background: var(--kf-bg);
    box-shadow: 0 2.5rem 5rem -2.5rem rgba(28, 26, 24, 0.5);
    color: var(--kf-text);
}

@media (max-width: 59.99rem) {
    .kf-vitrine {
        width: min(100%, calc(56svh * 0.8));
    }
}

.kf-vitrine::after {
    content: "";
    position: absolute;
    inset: 0.75rem;
    border: 1px solid rgba(212, 189, 143, 0.28);
    border-radius: calc(var(--r-xl) - 0.75rem);
    pointer-events: none;
    z-index: 2;
}

.kf-vitrine__frame {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: inherit;
    touch-action: pan-y;
}

/* A breath of shadow at the top and the foot of the case, so its words never sit on the metal */
.kf-vitrine__frame::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background:
        linear-gradient(rgba(28, 26, 24, 0.82), rgba(28, 26, 24, 0) 18%),
        linear-gradient(0deg, rgba(28, 26, 24, 0.86), rgba(28, 26, 24, 0) 20%);
    pointer-events: none;
}

.kf-vitrine__frame:focus-visible {
    outline: 2px solid var(--kf-accent);
    outline-offset: -0.75rem;
}

.kf-vitrine__still {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 0.5s var(--kf-ease);
}

.kf-vitrine.has-3d .kf-vitrine__frame {
    cursor: grab;
}

.kf-vitrine.has-3d .kf-vitrine__frame:active {
    cursor: grabbing;
}

.kf-vitrine.has-3d .kf-vitrine__still {
    opacity: 0;
}

.kf-vitrine .kf-canvas {
    transition: opacity 0.35s var(--kf-ease);
}

.kf-vitrine.is-swapping .kf-canvas,
.kf-vitrine.is-swapping .kf-vitrine__still {
    opacity: 0;
}

.kf-vitrine__caption {
    position: absolute;
    z-index: 3;
    left: 1.75rem;
    top: 1.625rem;
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    pointer-events: none;
}

.kf-vitrine__no {
    color: var(--kf-accent);
}

.kf-vitrine__name {
    font-family: var(--kf-serif);
    font-size: 1.375rem;
    line-height: 1;
    color: var(--kf-text);
}

.kf-vitrine__ui {
    position: absolute;
    z-index: 3;
    left: 1.125rem;
    right: 1.75rem;
    bottom: 1.125rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    pointer-events: none;
}

/* The metals and the hint come with the live ring (kf.js sets is-live): the stills show each ring
   in one metal only. */
.kf-swatches,
.kf-vitrine__hint {
    display: none;
}

.kf-vitrine.is-live .kf-swatches {
    display: flex;
    gap: 0.25rem;
    pointer-events: auto;
}

.kf-vitrine.is-live .kf-vitrine__hint {
    display: flex;
}

/* the metals, as pills. In the case each sits on its own dark glass, so the turning metal behind
   can never wash a label out (6.0:1 at worst, over pure white metal). */
.kf-swatch {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 2.75rem;
    padding: 0 0.875rem 0 0.625rem;
    border: 0;
    border-radius: var(--r-pill);
    background: rgba(28, 26, 24, 0.85);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--kf-text-soft);
    cursor: pointer;
    transition: color 0.4s var(--kf-ease), background-color 0.4s var(--kf-ease);
}

.kf-swatch__dot {
    width: 1rem;
    height: 1rem;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(238, 234, 227, 0.22);
    transition: box-shadow 0.4s var(--kf-ease);
}

.kf-swatch[data-metal="yellow"] .kf-swatch__dot { background: linear-gradient(135deg, #F6DFA4, #C99A45 55%, #8E6A2C); }
.kf-swatch[data-metal="white"] .kf-swatch__dot { background: linear-gradient(135deg, #FBFBF8, #C9C8C3 55%, #8D8C88); }
.kf-swatch[data-metal="rose"] .kf-swatch__dot { background: linear-gradient(135deg, #F9D3C1, #D49577 55%, #9A6049); }

.kf-swatch[aria-pressed="true"] {
    color: var(--kf-text);
    background: linear-gradient(rgba(238, 234, 227, 0.14), rgba(238, 234, 227, 0.14)), rgba(28, 26, 24, 0.85);
}

.kf-swatch[aria-pressed="true"] .kf-swatch__dot {
    box-shadow: 0 0 0 1px var(--kf-bg), 0 0 0 2px var(--kf-accent);
}

@media (hover: hover) {
    .kf-swatch:hover {
        color: var(--kf-text);
        background: linear-gradient(rgba(238, 234, 227, 0.08), rgba(238, 234, 227, 0.08)), rgba(28, 26, 24, 0.85);
    }
}

.kf-vitrine__hint {
    align-items: center;
    gap: 0.625rem;
    min-height: 2.25rem;
    margin: 0;
    padding: 0 0.875rem;
    border-radius: var(--r-pill);
    background: rgba(28, 26, 24, 0.85);
    font-size: 0.8125rem;
    font-weight: 450;
    color: var(--kf-text-soft);
    transition: opacity 0.6s var(--kf-ease);
}

.kf-vitrine__hint::before {
    content: "";
    width: 1.75rem;
    height: 1px;
    background: linear-gradient(90deg, rgba(212, 189, 143, 0), var(--kf-accent), rgba(212, 189, 143, 0));
}

.kf-vitrine.was-turned .kf-vitrine__hint {
    opacity: 0;
}

/* On a phone or tablet the case is small and the ring fills it, so the metals sit just below the
   case, on the stone, and the ring is never covered. The case's shadow falls across this row, so
   the labels are in the body ink (not muted), and hover goes to the full ink: the case's own night
   colours would vanish on the stone. */
@media (max-width: 59.99rem) {
    .kf-vitrine.is-live {
        margin-bottom: 4rem;
    }

    .kf-vitrine__ui {
        top: 100%;
        bottom: auto;
        left: -0.25rem;
        right: 0;
        padding-top: 0.75rem;
    }

    .kf-swatch {
        color: var(--kf-ink-soft);
        background: transparent;
    }

    .kf-swatch[aria-pressed="true"] {
        color: var(--kf-ink);
        background: rgba(28, 26, 24, 0.08);
    }

    @media (hover: hover) {
        .kf-swatch:hover {
            color: var(--kf-ink);
            background: rgba(28, 26, 24, 0.06);
        }
    }

    .kf-swatch__dot {
        box-shadow: 0 0 0 1px var(--kf-ink-line-strong);
    }

    .kf-swatch[aria-pressed="true"] .kf-swatch__dot {
        box-shadow: 0 0 0 1px var(--kf-ivory), 0 0 0 2px var(--kf-bronze);
    }

    .kf-swatch:focus-visible {
        outline-color: var(--kf-bronze);
    }

    .kf-vitrine__hint {
        color: var(--kf-ink-soft);
        background: transparent;
        padding: 0;
    }
}

@media (max-width: 29.99rem) {
    .kf-vitrine__hint {
        display: none !important;
    }
}

/* The pieces: choose one and the case shows it; its words open beneath its name. */
.kf-pieces {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--kf-ink-line-strong);
}

.kf-pieces li {
    border-bottom: 1px solid var(--kf-ink-line-strong);
}

.kf-piece {
    position: relative;
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr);
    align-items: baseline;
    width: 100%;
    padding: 1.625rem 0;
    border: 0;
    background: none;
    font: inherit;
    text-align: left;
    color: var(--kf-ink);
    cursor: pointer;
}

.kf-piece::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    background: var(--kf-bronze);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.9s var(--kf-out);
}

.kf-piece[aria-pressed="true"]::after {
    transform: scaleX(1);
    transform-origin: left;
}

.kf-piece:focus-visible {
    outline-offset: 0.25rem;
    border-radius: var(--r-md);
}

.kf-piece__num {
    color: var(--kf-ink-muted);
    transition: color 0.5s var(--kf-ease);
}

.kf-piece[aria-pressed="true"] .kf-piece__num {
    color: var(--kf-bronze);
}

.kf-piece__title {
    font-family: var(--kf-serif);
    font-size: clamp(2rem, 3.4vw, 3rem);
    line-height: 1;
    letter-spacing: -0.01em;
    transition: transform 0.7s var(--kf-out);
}

.kf-piece[aria-pressed="true"] .kf-piece__title {
    font-style: italic;
}

@media (hover: hover) {
    .kf-piece:hover .kf-piece__title {
        transform: translateX(0.5rem);
    }
}

.kf-piece__more {
    grid-column: 2;
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.8s var(--kf-out);
}

.kf-piece__text {
    min-height: 0;
    overflow: hidden;
    color: var(--kf-ink-soft);
}

.kf-piece[aria-pressed="true"] .kf-piece__more {
    grid-template-rows: 1fr;
}

.kf-piece[aria-pressed="true"] .kf-piece__text {
    padding-top: 0.75rem;
}

/* ---------------------------------------------------------------- the ribbon */

.kf-marquee {
    position: relative;
    z-index: 1;
    overflow: hidden;
    padding-block: clamp(3rem, 7vw, 6rem);
    background: var(--kf-bg);
}

.kf-marquee__track {
    display: flex;
    width: max-content;
}

.kf-marquee__set {
    display: flex;
    align-items: center;
    gap: 0.4em;
    padding-right: 0.4em;
    font-family: var(--kf-serif);
    font-size: clamp(3.75rem, 11vw, 10.5rem);
    line-height: 1.1;
    letter-spacing: -0.02em;
    white-space: nowrap;
    color: var(--kf-text);
}

.kf-marquee__set em {
    padding-right: 0.06em;
    font-style: italic;
    background: var(--kf-foil);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.kf-marquee__set i {
    font-style: normal;
    font-size: 0.4em;
    color: var(--kf-accent);
}

@media (prefers-reduced-motion: no-preference) {
    .kf-marquee__track {
        animation: kf-marquee 70s linear infinite;
    }

    @keyframes kf-marquee {
        to { transform: translate3d(-50%, 0, 0); }
    }
}

/* ---------------------------------------------------------------- appointment */

.kf-section {
    position: relative;
    z-index: 1;
    padding-block: clamp(5rem, 11vw, 10rem);
    background: var(--kf-bg);
}

.kf-appointment .kf-section__head {
    position: relative;
}

@media (min-width: 60rem) {
    .kf-appointment__grid {
        display: grid;
        grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
        column-gap: clamp(2rem, 7vw, 8rem);
        align-items: start;
    }
}

/* The maker's seal: the page's line round a monogram, turning slowly. Two layers, so the ring of
   words turns as a whole element, on the compositor, and the monogram stays upright. */
.kf-seal {
    position: relative;
    display: block;
    width: clamp(7.5rem, 10vw, 9.5rem);
    aspect-ratio: 1;
    margin-bottom: 2.5rem;
}

.kf-seal svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.kf-seal__ring text {
    font-family: var(--kf-sans);
    font-size: 13px;
    font-weight: 500;
    text-transform: uppercase;
    fill: var(--kf-text-soft);
}

.kf-seal__mark text {
    font-family: var(--kf-serif);
    font-size: 46px;
    fill: var(--kf-text);
}

.kf-seal__mark tspan {
    font-style: italic;
    fill: var(--kf-accent);
}

@media (prefers-reduced-motion: no-preference) {
    .kf-seal__ring {
        animation: kf-spin 48s linear infinite;
    }

    @keyframes kf-spin {
        to { transform: rotate(1turn); }
    }
}

.kf-notice {
    margin: 0;
    padding: 1.5rem 1.75rem;
    border: 1px solid rgba(212, 189, 143, 0.45);
    border-radius: var(--r-lg);
    background: rgba(238, 234, 227, 0.03);
    font-size: 1rem;
    color: var(--kf-text-soft);
}

.kf-notice strong {
    display: block;
    margin-bottom: 0.375rem;
    font-family: var(--kf-serif);
    font-size: 1.75rem;
    font-weight: 400;
    line-height: 1.1;
    color: var(--kf-text);
}

.kf-form__fields {
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

.kf-form__legend {
    margin-bottom: 2.25rem;
    padding: 0;
    color: var(--kf-muted);
}

.kf-field {
    margin: 0 0 2rem;
}

.kf-field__label {
    display: block;
    margin-bottom: 0.5rem;
    color: var(--kf-text-soft);
}

.kf-field__input {
    display: block;
    width: 100%;
    padding: 0.75rem 0;
    border: 0;
    border-bottom: 1px solid var(--kf-line-strong);
    border-radius: 0;
    background: transparent;
    color: var(--kf-text);
    font: inherit;
    font-size: 1rem;
    resize: none;
}

.kf-form__fields:disabled .kf-field__input {
    border-bottom-style: dashed;
    cursor: not-allowed;
}

/* The switched-off form's button: a ghost of the pill */
.kf-form__fields:disabled .kf-btn {
    background: transparent;
    box-shadow: inset 0 0 0 1px var(--kf-line-strong);
    color: var(--kf-muted);
    cursor: not-allowed;
}

.kf-form__fields:disabled .kf-btn__arrow {
    background: rgba(238, 234, 227, 0.06);
    color: var(--kf-muted);
}

@media (hover: hover) {
    .kf-form__fields:disabled .kf-btn:hover {
        background: transparent;
    }

    .kf-form__fields:disabled .kf-btn:hover .kf-btn__arrow svg {
        transform: none;
    }
}

/* ---------------------------------------------------------------- footer */

.kf-footer {
    position: relative;
    z-index: 1;
    padding-block: clamp(3rem, 7vw, 6rem) 3rem;
    border-top: 1px solid var(--kf-line);
    background: var(--kf-bg);
    font-size: 0.9375rem;
    color: var(--kf-text-soft);
}

/* The name, set across the whole width as a signature to end on; its letters rise in turn. */
.kf-signature {
    margin: 0 0 clamp(3rem, 6vw, 5rem);
    overflow: hidden;
    padding-block: 0.06em 0.14em;
    font-family: var(--kf-serif);
    font-size: min(16.5vw, 15.5rem);
    line-height: 0.9;
    letter-spacing: -0.035em;
    white-space: nowrap;
    text-align: center;
    color: var(--kf-text);
}

.kf-signature .kf-amp {
    padding-inline: 0.03em;
}

.kf-ch {
    display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
    .kf-js .kf-signature .kf-ch {
        transform: translate3d(0, 110%, 0);
        transition: transform 1.4s var(--kf-out) calc(var(--i, 0) * 45ms);
    }

    .kf-js .kf-signature.is-in .kf-ch {
        transform: none;
    }
}

.kf-footer__grid {
    display: grid;
    gap: 2rem;
    padding-top: 2.5rem;
    border-top: 1px solid var(--kf-line);
}

@media (min-width: 60rem) {
    .kf-footer__grid {
        grid-template-columns: minmax(0, 8fr) minmax(0, 3fr);
        align-items: start;
    }

    .kf-footer__small {
        justify-self: end;
    }
}

.kf-footer__about {
    max-width: 44rem;
}

.kf-footer p {
    margin: 0 0 1rem;
}

.kf-link {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    color: var(--kf-accent);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.35em;
}

.kf-footer__small {
    font-size: 0.8125rem;
    color: var(--kf-muted);
}

.kf-footer__small a {
    color: var(--kf-text-soft);
}

/* ---------------------------------------------------------------- atmosphere */

/* Light, the stone's own geometry, and a grain like paper: what keeps the graphite and the stone
   from being flat colour. Every light pool is a static gradient inside its own section, fading out
   before the section's edges (no seam where sections meet) and, in the theatre, before the 3D's
   frame (whose edges fade to the flat graphite). Text sits on them at its measured contrast or
   better: the pools on stone only lighten it, and the shade on stone is 5% bronze (muted text
   4.8:1 at its darkest). */

.kf-defs {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.kf-defs circle,
.kf-defs path {
    vector-effect: non-scaling-stroke;
}

/* The facet map: hairlines at any size */
.kf-motif {
    position: absolute;
    z-index: -1;
    aspect-ratio: 1;
    fill: none;
    stroke: currentColor;
    stroke-width: 1;
    stroke-linejoin: round;
    pointer-events: none;
}

/* The theatre: light from the upper left, like a window, held clear of the 3D's frame */
@media (min-width: 60rem) {
    .kf-stage {
        background: radial-gradient(30vw circle at 14% 30%, rgba(212, 189, 143, 0.075), rgba(212, 189, 143, 0) 100%);
    }
}

/* Daylight: a soft bright patch, and a breath of warm shade low on the other side */
.kf-light {
    background:
        radial-gradient(55% 35% at 80% 40%, rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0) 100%),
        radial-gradient(35% 25% at 12% 70%, rgba(107, 85, 48, 0.05), rgba(107, 85, 48, 0) 100%),
        var(--kf-ivory);
}

/* the motifs and the display light reach past their sections' sides: clipped there (clip, not
   hidden, so the process's sticky aside still sticks) */
.kf-light,
.kf-section {
    overflow-x: clip;
}

/* The process: the facet map, large and cropped, turning very slowly behind the steps */
.kf-motif--bespoke {
    right: -16vw;
    top: clamp(4rem, 12vh, 9rem);
    width: min(72vw, 62rem);
    color: var(--kf-bronze);
    opacity: 0.12;
}

/* The collection: display light behind the case */
.kf-showcase {
    position: relative;
    isolation: isolate;
}

.kf-showcase::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: -12% 0 -12% -6%;
    background: radial-gradient(42% 48% at 30% 50%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 100%);
    pointer-events: none;
}

@media (max-width: 59.99rem) {
    .kf-showcase::before {
        inset: -4% -6% auto;
        height: 70%;
        background: radial-gradient(60% 50% at 50% 50%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 100%);
    }
}

/* The night sections: a warm pool behind the words, inside the section */
.kf-marquee {
    background:
        radial-gradient(45% 42% at 50% 50%, rgba(212, 189, 143, 0.06), rgba(212, 189, 143, 0) 100%),
        var(--kf-bg);
}

.kf-section {
    background:
        radial-gradient(45% 40% at 80% 50%, rgba(212, 189, 143, 0.075), rgba(212, 189, 143, 0) 100%),
        radial-gradient(35% 30% at 10% 30%, rgba(238, 234, 227, 0.03), rgba(238, 234, 227, 0) 100%),
        var(--kf-bg);
}

.kf-footer {
    background:
        radial-gradient(55% 45% at 50% 50%, rgba(212, 189, 143, 0.06), rgba(212, 189, 143, 0) 100%),
        var(--kf-bg);
}

/* The appointment: the facet map in champagne, turning slowly beside the form */
.kf-motif--appointment {
    right: -20vw;
    top: 50%;
    width: min(64vw, 50rem);
    margin-top: calc(min(64vw, 50rem) / -2);
    color: var(--kf-accent);
    opacity: 0.06;
}

@media (prefers-reduced-motion: no-preference) {
    .kf-motif--bespoke,
    .kf-motif--appointment {
        animation: kf-spin 240s linear infinite;
    }

    .kf-motif--appointment {
        animation-direction: reverse;
    }
}

/* The dawn: the facet map opens behind its words with the light, turning into place */
.kf-motif--dawn {
    z-index: 0;
    left: 50%;
    top: 50%;
    width: min(76vw, 74vh);
    transform: translate(-50%, -50%);
    color: var(--kf-bronze);
    opacity: 0.13;
}

@media (prefers-reduced-motion: no-preference) {
    .kf-js .kf-motif--dawn {
        top: calc(50% + var(--header-h) / 2);
        opacity: 0;
        transform: translate(-50%, -50%) rotate(-20deg) scale(0.9);
        transition: opacity 1.2s var(--kf-out), transform 1.6s var(--kf-out);
    }

    .kf-js .kf-dawn.is-day .kf-motif--dawn {
        opacity: 0.13;
        transform: translate(-50%, -50%);
    }
}

@supports (animation-timeline: scroll()) {
    @media (prefers-reduced-motion: no-preference) {
        .kf-js .kf-motif--dawn {
            transition: none;
            animation: kf-facets-in cubic-bezier(0.16, 1, 0.3, 1) both;
            animation-timeline: --kf-dawn;
            animation-range: contain 26% contain 70%;
        }
    }
}

@keyframes kf-facets-in {
    from { opacity: 0; transform: translate(-50%, -50%) rotate(-20deg) scale(0.9); }
    to { opacity: 0.13; transform: translate(-50%, -50%); }
}

/* A fine grain over the page, like paper or film: a few hundred bytes of SVG noise, drawn once
   into its own layer. Under the header (z-index 19 against its 20), so the glass of the navigation
   stays clear, as glass would. Hidden where colours are forced. */
body::after {
    content: "";
    position: fixed;
    z-index: 19;
    inset: 0;
    background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 1.6 -0.55'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size: 180px 180px;
    opacity: 0.22;
    pointer-events: none;
    will-change: transform;
}

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

/* ---------------------------------------------------------------- the cursor */

/* Over the ring viewer, with a mouse: a ring of champagne that says what the pointer will do. */
.kf-cursor {
    display: none;
}

@media (hover: hover) and (pointer: fine) {
    .kf-cursor {
        position: fixed;
        z-index: 30;
        left: 0;
        top: 0;
        display: grid;
        place-items: center;
        width: 5.5rem;
        height: 5.5rem;
        margin: -2.75rem 0 0 -2.75rem;
        border: 1px solid var(--kf-accent);
        border-radius: 50%;
        background: rgba(28, 26, 24, 0.4);
        -webkit-backdrop-filter: blur(6px);
        backdrop-filter: blur(6px);
        font-size: 0.75rem;
        font-weight: 500;
        letter-spacing: 0.04em;
        color: var(--kf-text);
        pointer-events: none;
        opacity: 0;
        transition: opacity 0.3s var(--kf-ease);
        will-change: transform;
    }

    .kf-cursor.is-on {
        opacity: 1;
    }

    .kf-cursor span {
        transition: transform 0.4s var(--kf-out);
    }

    .kf-cursor.is-down span {
        transform: scale(0.85);
    }

    .kf-vitrine.has-cursor .kf-vitrine__frame {
        cursor: none;
    }
}
