/* ==========================================================================
   THIRD. — Modern Bakery & Coffee
   Design system + homepage sections.
   Palette sampled from the brand wordmark (#532100) and the house photography.
   ========================================================================== */

:root {
    /* Surface */
    --th-cream: #F3EFE9;
    --th-bone: #E9E2D7;
    --th-stone: #D5CCBE;
    --th-paper: #FBF9F6;

    /* Ink */
    --th-ink: #17100A;
    --th-roast: #24170E;
    --th-espresso: #532100;
    --th-bean: #331C0C;

    /* Accent */
    --th-crema: #C1793C;
    --th-caramel: #A8642C;
    --th-oak: #8E6A4A;

    /* Derived */
    --th-ink-soft: rgba(23, 16, 10, .68);
    --th-ink-faint: rgba(23, 16, 10, .12);
    --th-cream-soft: rgba(243, 239, 233, .78);
    --th-cream-faint: rgba(243, 239, 233, .17);

    /* Type */
    --th-display: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --th-editorial: "Instrument Serif", "Times New Roman", Georgia, serif;
    --th-body: "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    --th-t-mega: clamp(3.75rem, 15.5vw, 15rem);
    --th-t-hero: clamp(2.75rem, 9vw, 8.5rem);
    --th-t-xl: clamp(2.25rem, 6.2vw, 5.75rem);
    --th-t-lg: clamp(1.75rem, 4.1vw, 3.5rem);
    --th-t-md: clamp(1.375rem, 2.4vw, 2.125rem);
    --th-t-sm: clamp(1.0625rem, 1.35vw, 1.3125rem);
    --th-t-body: clamp(1rem, 1.02vw, 1.0625rem);
    --th-t-label: clamp(.625rem, .72vw, .75rem);

    /* Rhythm */
    --th-gutter: clamp(1.25rem, 5vw, 5.5rem);
    --th-block: clamp(5rem, 11vw, 10.5rem);
    --th-rule: rgba(23, 16, 10, .14);
    --th-rule-light: rgba(243, 239, 233, .2);

    /* Motion */
    --th-ease: cubic-bezier(.16, .84, .28, 1);
    --th-ease-soft: cubic-bezier(.4, .0, .18, 1);

    --th-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   Section shell — every widget is edge to edge and owns its own spacing.
   -------------------------------------------------------------------------- */

.th-section {
    position: relative;
    width: 100%;
    max-width: 100%;
    margin: 0;
    /* Every surface declares its own muted-text and hairline colour, so shared
       primitives (.th-lede, .th-rule) read correctly on light and dark alike. */
    --th-muted: var(--th-ink-soft);
    font-family: var(--th-body);
    font-size: var(--th-t-body);
    line-height: 1.62;
    color: var(--th-ink);
    background: var(--th-cream);
    overflow: clip;
    isolation: isolate;
}

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

.th-section p {
    font-family: var(--th-body);
    font-size: inherit;
    line-height: inherit;
    margin: 0;
}

.th-section h1,
.th-section h2,
.th-section h3,
.th-section h4 {
    font-family: var(--th-display);
    font-weight: 800;
    line-height: .92;
    letter-spacing: -.035em;
    color: inherit;
    margin: 0;
    text-wrap: balance;
}

.th-section a {
    color: inherit;
    text-decoration: none;
}

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

.th-shell {
    width: 100%;
    max-width: var(--th-shell-max, 1680px);
    margin-inline: auto;
    padding-inline: var(--th-shell-gutter, var(--th-gutter));
}

/* Anchored sections clear the fixed header when linked from the megamenu. */
.th-section[id] {
    scroll-margin-top: calc(var(--th-header-h, 6rem) + 1rem);
}

.th-shell--narrow {
    max-width: 1240px;
}

/* Dark surfaces */
.th-hero,
.th-coffee,
.th-bakery,
.th-craft,
.th-amsterdam,
.th-social,
.th-cta-section,
.th--dark,
.th--espresso {
    --th-muted: var(--th-cream-soft);
    --th-rule: var(--th-rule-light);
}

.th--dark {
    background: var(--th-ink);
    color: var(--th-cream);
}

.th--espresso {
    background: var(--th-espresso);
    color: var(--th-cream);
}

/* Grain — a single pseudo element, no extra requests, no extra DOM.
   Size, strength and blend are vars so a widget can tune its own film. */
.th-grain::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: var(--th-grain-image, var(--th-grain));
    background-size: var(--th-grain-size, 160px);
    opacity: var(--th-grain-opacity, .16);
    mix-blend-mode: var(--th-grain-blend, overlay);
    pointer-events: none;
    z-index: 6;
}

/* --------------------------------------------------------------------------
   Typographic primitives
   -------------------------------------------------------------------------- */

.th-label {
    display: inline-flex;
    align-items: center;
    gap: .7em;
    font-family: var(--th-body);
    font-size: var(--th-t-label);
    font-weight: 500;
    letter-spacing: .22em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--th-crema);
}

.th-label::before {
    content: "";
    width: clamp(20px, 3vw, 46px);
    height: 1px;
    background: currentColor;
    opacity: .55;
}

.th-label--bare::before {
    display: none;
}

.th-index {
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .2em;
    font-variant-numeric: tabular-nums;
    opacity: .5;
}

.th-serif {
    font-family: var(--th-editorial);
    font-weight: 400;
    font-style: italic;
    letter-spacing: -.01em;
    line-height: 1.14;
}

.th-lede {
    font-size: var(--th-t-sm);
    line-height: 1.55;
    color: var(--th-muted);
    max-width: 44ch;
}

.th-rule {
    height: 1px;
    width: 100%;
    background: var(--th-rule);
    border: 0;
}

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

/* Link / button */
.th-cta {
    display: inline-flex;
    align-items: center;
    gap: .85em;
    font-family: var(--th-body);
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    line-height: 1;
    padding: 1.15em 1.9em;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: inherit;
    background: transparent;
    cursor: pointer;
    transition: color .5s var(--th-ease), border-color .5s var(--th-ease), background-color .5s var(--th-ease);
    position: relative;
    overflow: hidden;
}

.th-cta > span {
    position: relative;
    z-index: 2;
}

.th-cta::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--th-espresso);
    transform: scaleY(0);
    transform-origin: bottom;
    transition: transform .55s var(--th-ease);
    z-index: 1;
}

.th-cta:hover::before,
.th-cta:focus-visible::before {
    transform: scaleY(1);
}

.th-cta:hover,
.th-cta:focus-visible {
    color: var(--th-cream);
    border-color: var(--th-espresso);
}

.th--dark .th-cta::before,
.th--espresso .th-cta::before {
    background: var(--th-cream);
}

.th--dark .th-cta:hover,
.th--dark .th-cta:focus-visible,
.th--espresso .th-cta:hover,
.th--espresso .th-cta:focus-visible {
    color: var(--th-ink);
    border-color: var(--th-cream);
}

.th-cta__arrow {
    width: 1.1em;
    height: 1.1em;
    flex: none;
    position: relative;
    z-index: 2;
    transition: transform .5s var(--th-ease);
}

.th-cta:hover .th-cta__arrow,
.th-cta:focus-visible .th-cta__arrow {
    transform: translateX(.28em);
}

/* Action row — the shared home for a section's closing button. Sections that
   already carried a hand-placed CTA keep their own wrapper; this is what every
   other section hangs its button on. */
.th-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(.75rem, 1.6vw, 1.25rem);
    margin-top: clamp(1.75rem, 3.5vw, 3rem);
    max-width: none;
}

/* Placement per section: the row has to answer to the grid it lands in. */
.th-craft__actions {
    grid-column: 2;
    color: var(--th-cream);
}

.th-discover__actions {
    margin-top: clamp(2rem, 4vw, 3.25rem);
}

/* The panel frame already carries the gap above the row, unless it bleeds. The
   row itself has to carry the section's closing block: .th-section declares no
   bottom padding, so without this the button lands flush on the bottom edge and
   gets shaved by the section's `overflow: clip`. */
.th-duality__actions {
    margin-top: 0;
    padding-bottom: var(--thd-actions-bottom, var(--th-block));
}

.th-duality--bleed .th-duality__actions {
    margin-top: clamp(2rem, 4.5vw, 3.5rem);
}

.th-place__close .th-actions {
    grid-column: 1 / -1;
    margin-top: clamp(1rem, 2.2vw, 1.75rem);
}

/* The closing line hands its bottom block over to the button below it. */
.th-space__close:has(+ .th-actions) {
    padding-bottom: clamp(1.25rem, 2.5vw, 2rem);
}

.th-space__actions {
    margin-top: clamp(1.25rem, 2.5vw, 2rem);
    padding-bottom: var(--th-block);
}

/* Text link with a wiping underline */
.th-link {
    position: relative;
    display: inline-block;
    font-weight: 500;
    padding-bottom: .18em;
}

.th-link::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1px;
    background: currentColor;
    transform-origin: right;
    transform: scaleX(1);
    transition: transform .5s var(--th-ease);
}

.th-link:hover::after,
.th-link:focus-visible::after {
    transform-origin: left;
    animation: th-wipe .6s var(--th-ease);
}

@keyframes th-wipe {
    0% { transform: scaleX(1); transform-origin: right; }
    49% { transform: scaleX(0); transform-origin: right; }
    50% { transform: scaleX(0); transform-origin: left; }
    100% { transform: scaleX(1); transform-origin: left; }
}

/* Focus */
.th-section :focus-visible,
.th-shell :focus-visible {
    outline: 2px solid var(--th-crema);
    outline-offset: 4px;
    border-radius: 2px;
}

/* --------------------------------------------------------------------------
   Motion primitives
   -------------------------------------------------------------------------- */

.th-js .th-section [data-th-reveal] {
    opacity: 0;
    transform: translateY(2rem);
    transition:
        opacity 1s var(--th-ease),
        transform 1.05s var(--th-ease);
    transition-delay: calc(var(--d, 0) * 90ms);
}

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

.th-js .th-section [data-th-reveal="fade"] {
    transform: none;
}

/* Image reveal — the photo scales down behind a rising mask.
   The clip lives on the <img>, never on the observed element: a fully clipped
   element reports an empty intersection rect and the observer would never fire. */
.th-figure {
    position: relative;
    overflow: hidden;
    background: var(--th-bone);
}

/* Every image that has to fill a framed box is positioned rather than sized.
   The `.th-section` prefix is load-bearing: without it these tie with Elementor's
   `.elementor img {height:auto}`, which loads later and would win — leaving the
   photo short of its frame. All of these sit in a positioned parent of known height. */
.th-section .th-figure img,
.th-section .th-hero__media img,
.th-section .th-hero__media video,
.th-section .th-panel__media img,
.th-section .th-bakery__media img,
.th-section .th-space__reveal img,
.th-section .th-craft__frame img,
.th-section .th-coffee__disc img,
.th-section .th-social__tile img,
.th-section .th-social__tile video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: cover;
}

.th-js .th-figure[data-th-reveal="image"] {
    opacity: 1;
    transform: none;
    background: transparent;
}

.th-js .th-figure[data-th-reveal="image"] img {
    clip-path: inset(100% 0 0 0);
    transform: scale(1.2);
    transition:
        clip-path 1.35s var(--th-ease),
        transform 1.9s var(--th-ease);
    transition-delay: calc(var(--d, 0) * 90ms);
}

.th-js .th-figure[data-th-reveal="image"].is-in img {
    clip-path: inset(0 0 0 0);
    transform: scale(1);
}

/* Word-by-word typographic reveal */
.th-split {
    display: inline;
}

.th-word {
    display: inline-block;
    overflow: hidden;
    padding-bottom: .14em;
    margin-bottom: -.14em;
    vertical-align: bottom;
}

.th-word > span {
    display: inline-block;
    transform: translateY(110%);
    transition: transform 1.05s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 55ms + var(--d, 0) * 90ms);
}

.th-js [data-th-reveal].is-in .th-word > span,
.th-js [data-th-reveal].is-in.th-word > span {
    transform: none;
}

html:not(.th-js) .th-word > span {
    transform: none;
}

/* Letter-by-letter variant — same masked-rise mechanic at a tighter stagger,
   for the two places where a single word carries a whole section. */
.th-letter {
    display: inline-block;
    overflow: hidden;
    padding-bottom: .14em;
    margin-bottom: -.14em;
    vertical-align: bottom;
}

.th-letter > span {
    display: inline-block;
    transform: translateY(110%);
    transition: transform .95s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 34ms + var(--d, 0) * 90ms);
}

.th-js [data-th-reveal].is-in .th-letter > span {
    transform: none;
}

html:not(.th-js) .th-letter > span,
.th-is-editor .th-letter > span {
    transform: none;
}

.th-is-editor [data-th-reveal] {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
}

.th-is-editor .th-word > span {
    transform: none !important;
}

/* ==========================================================================
   01 — HERO
   ========================================================================== */

.th-hero {
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    background: var(--th-ink);
    color: var(--th-cream);
    /* The top rule carries the crest above it, so the reserved headroom is deeper
       than the rule alone would need. --th-header-h is published by the shell
       script and shrinks once the utility bar folds away on scroll. */
    padding-block: calc(var(--th-header-h, 6rem) + 5rem) clamp(1.5rem, 3.5vw, 3rem);
}

.th-hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
}

.th-hero__media img,
.th-hero__media video {
    object-position: 50% 58%;
    transform: scale(1.14) translate3d(0, calc(var(--th-p, 0) * -4%), 0);
    animation: th-hero-settle 2.6s var(--th-ease) forwards;
    will-change: transform;
}

/* The loop lies over the still and only fades in once it actually has frames,
   so a slow or refused video never shows as a black plate. */
.th-hero__bg-video {
    opacity: 0;
    transition: opacity 1.2s var(--th-ease);
    pointer-events: none;
}

.th-hero__bg-video.is-playing {
    opacity: 1;
}

@keyframes th-hero-settle {
    from { transform: scale(1.22) translate3d(0, 0, 0); }
    to { transform: scale(1.14) translate3d(0, 0, 0); }
}

.th-hero__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
        linear-gradient(to top, rgba(23, 16, 10, .92) 0%, rgba(23, 16, 10, .34) 42%, rgba(23, 16, 10, .58) 100%),
        radial-gradient(120% 90% at 22% 78%, rgba(83, 33, 0, .34) 0%, transparent 62%);
}

.th-hero__top {
    position: absolute;
    top: calc(var(--th-header-h, 6rem) + clamp(.75rem, 2vh, 1.75rem));
    left: 0;
    right: 0;
    z-index: 3;
}

/* House crest — a cup that draws itself in under drifting steam.
   Pure SVG + CSS: no library, no extra request. */
/* Crest and meta share one row: the emblem sits left of the hairline, which
   then runs on across the rest of the shell. */
.th-hero__top-shell {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2vw, 1.75rem);
}

.th-hero__crest {
    display: block;
    flex: none;
    width: clamp(38px, 4.2vw, 52px);
    height: auto;
    color: var(--th-cream-soft);
    overflow: visible;
}

/* pathLength="1" on every stroke lets one draw-in keyframe serve all of them. */
.th-hero__crest-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: th-draw-in 1.3s var(--th-ease) forwards;
    animation-delay: calc(.5s + var(--i) * .18s);
}

@keyframes th-draw-in {
    to { stroke-dashoffset: 0; }
}

.th-hero__crest-steam path {
    opacity: 0;
    animation: th-crest-steam 3.8s var(--th-ease-soft) infinite;
    animation-delay: calc(1.4s + var(--i) * .42s);
}

@keyframes th-crest-steam {
    0%   { opacity: 0; transform: translateY(3px) scaleY(.9); }
    28%  { opacity: .9; }
    68%  { opacity: .45; }
    100% { opacity: 0; transform: translateY(-4px) scaleY(1.1); }
}

.th-hero__top-inner {
    flex: 1;
    min-width: 0;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 2rem;
    padding-top: 1rem;
}

.th-hero__meta {
    font-size: var(--th-t-label);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--th-cream-soft);
}

.th-hero__body {
    position: relative;
    z-index: 3;
    width: 100%;
}

/* With a video the hero splits: wordmark, copy and actions on the left, the reel
   on the right. Without one the section keeps its original single-column form. */
.th-hero__body--split {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr);
    align-items: end;
    gap: clamp(2rem, 4vw, 4.5rem);
}

.th-hero__body--split .th-hero__foot {
    grid-column: 1 / -1;
    /* Two columns already carry the eye down; the foot needs less air above it. */
    margin-top: clamp(1.5rem, 3vw, 2.75rem);
}

.th-hero__lead {
    min-width: 0;
}

.th-hero__title {
    display: block;
    margin: 0;
}

.th-hero__mark {
    display: block;
    font-family: var(--th-display);
    font-size: var(--th-t-mega);
    font-weight: 900;
    letter-spacing: -.05em;
    line-height: .82;
    text-transform: uppercase;
}

.th-hero__mark span {
    display: inline-block;
    transform: translateY(115%);
    animation: th-rise 1.35s var(--th-ease) forwards;
    animation-delay: calc(.32s + var(--i) * .08s);
}

/* The wordmark's period is drawn as a round accent, echoing the bean in the logo. */
.th-accent-dot,
.th-hero__mark i {
    display: inline-block;
    width: .19em;
    height: .19em;
    margin-left: .05em;
    border-radius: 50%;
    background: var(--th-crema);
    font-style: normal;
    text-indent: -100vw;
    overflow: hidden;
    vertical-align: baseline;
}

@keyframes th-rise {
    to { transform: translateY(0); }
}

.th-hero__sub {
    display: block;
    font-family: var(--th-body);
    font-size: clamp(.75rem, 1.5vw, 1.0625rem);
    font-weight: 500;
    letter-spacing: .42em;
    text-transform: uppercase;
    line-height: 1;
    margin-top: clamp(.75rem, 1.6vw, 1.4rem);
    padding-left: .3em;
    color: var(--th-cream);
    opacity: 0;
    animation: th-fade-up 1.2s var(--th-ease) .95s forwards;
}

@keyframes th-fade-up {
    from { opacity: 0; transform: translateY(1.2rem); }
    to { opacity: 1; transform: none; }
}

/* The mega wordmark only fits full-bleed; inside the split column it steps down. */
.th-hero__body--split .th-hero__mark {
    font-size: clamp(3rem, 8vw, 8rem);
}

/* `.th-section p` zeroes every paragraph margin and outranks a bare class, so the
   intro has to match that specificity to keep its own spacing. */
.th-section .th-hero__intro {
    max-width: 46ch;
    margin-top: clamp(1.25rem, 2.4vw, 2rem);
    color: var(--th-cream-soft);
    opacity: 0;
    animation: th-fade-up 1.2s var(--th-ease) 1.1s forwards;
}

.th-hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(1rem, 2vw, 2rem);
    margin-top: clamp(1.5rem, 2.6vw, 2.25rem);
    opacity: 0;
    animation: th-fade-up 1.2s var(--th-ease) 1.28s forwards;
}

/* On the hero's dark ground the primary action inverts to cream and warms to
   crema on hover, so it reads before the outline link beside it. */
.th-hero .th-cta--filled {
    background: var(--th-cream);
    border-color: var(--th-cream);
    color: var(--th-ink);
}

.th-hero .th-cta--filled::before {
    background: var(--th-crema);
}

.th-hero .th-cta--filled:hover,
.th-hero .th-cta--filled:focus-visible {
    color: var(--th-ink);
    border-color: var(--th-crema);
}

.th-hero__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .7em;
    padding-bottom: .5em;
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--th-cream);
}

.th-hero__link::before,
.th-hero__link::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
}

.th-hero__link::before {
    background: var(--th-cream-faint);
}

.th-hero__link::after {
    background: var(--th-crema);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .55s var(--th-ease);
}

.th-hero__link:hover::after,
.th-hero__link:focus-visible::after {
    transform: scaleX(1);
}

.th-hero__link:hover .th-cta__arrow,
.th-hero__link:focus-visible .th-cta__arrow {
    transform: translateX(.28em);
}

/* --- Reel ---------------------------------------------------------------- */

.th-hero__reel {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: .85rem;
    opacity: 0;
    animation: th-fade-up 1.3s var(--th-ease) 1.05s forwards;
}

.th-hero__reel-frame {
    position: relative;
    aspect-ratio: 4 / 5;
    max-height: min(42vh, 400px);
    overflow: hidden;
    background: rgba(23, 16, 10, .55);
    border: 1px solid var(--th-cream-faint);
}

/* Same reasoning as the framed images above: positioned, not sized, so Elementor's
   later `height:auto` cannot leave the video short of its frame. */
.th-section .th-hero__reel-frame video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.th-hero__sound {
    position: absolute;
    right: .75rem;
    bottom: .75rem;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 2.6rem;
    height: 2.6rem;
    padding: 0;
    border: 1px solid var(--th-cream-faint);
    border-radius: 50%;
    background: rgba(23, 16, 10, .45);
    backdrop-filter: blur(6px);
    color: var(--th-cream);
    cursor: pointer;
    transition: background-color .4s var(--th-ease), border-color .4s var(--th-ease);
}

.th-hero__sound:hover,
.th-hero__sound:focus-visible {
    background: rgba(23, 16, 10, .75);
    border-color: var(--th-cream-soft);
}

.th-hero__sound svg {
    width: 1.15rem;
    height: 1.15rem;
}

.th-hero__sound-on {
    opacity: 0;
}

.th-hero__sound[aria-pressed="true"] .th-hero__sound-off {
    opacity: 0;
}

.th-hero__sound[aria-pressed="true"] .th-hero__sound-on {
    opacity: 1;
}

.th-hero__reel-label {
    display: flex;
    align-items: center;
    gap: .7em;
    font-size: var(--th-t-label);
    letter-spacing: .18em;
    text-transform: uppercase;
    line-height: 1.4;
    color: var(--th-cream-soft);
}

.th-hero__reel-label i {
    flex: none;
    width: .45em;
    height: .45em;
    border-radius: 50%;
    background: var(--th-crema);
    animation: th-pulse 2.6s var(--th-ease-soft) infinite;
}

@keyframes th-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: .35; transform: scale(.7); }
}

.th-hero__foot {
    position: relative;
    z-index: 3;
    display: grid;
    justify-items: center;
    text-align: center;
    gap: clamp(1.25rem, 2.5vw, 2rem);
    margin-top: clamp(2.5rem, 6vw, 4.5rem);
    padding-top: 1.15rem;
    opacity: 0;
    animation: th-fade-up 1.2s var(--th-ease) 1.25s forwards;
}

.th-hero__statement {
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: clamp(1.125rem, 2.2vw, 1.9rem);
    line-height: 1.2;
    max-width: 30ch;
    margin-inline: auto;
    color: var(--th-cream);
}

.th-hero__scroll {
    display: inline-flex;
    align-items: center;
    gap: .85em;
    font-size: var(--th-t-label);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--th-cream-soft);
    white-space: nowrap;
}

/* Scroll cue — a pour-over dripping into a cup. The falling drops carry the
   downward read that a mouse icon usually has to do, and stay on brand. */
.th-hero__pour {
    display: block;
    flex: none;
    width: 24px;
    height: 58px;
    overflow: visible;
}

.th-hero__pour-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: th-draw-in 1.1s var(--th-ease) forwards;
    animation-delay: calc(1.45s + var(--i) * .16s);
}

.th-hero__pour-drops circle {
    opacity: 0;
    animation: th-drip 2.9s var(--th-ease-soft) infinite;
    animation-delay: calc(2.4s + var(--i) * 1.45s);
}

@keyframes th-drip {
    0%        { transform: translateY(16px); opacity: 0; }
    14%       { opacity: 1; }
    68%       { transform: translateY(39px); opacity: 1; }
    80%, 100% { transform: translateY(41px); opacity: 0; }
}

/* The cup fills as the drops land, then resets with the loop. */
.th-hero__pour-fill {
    stroke-dasharray: 8.8;
    stroke-dashoffset: 8.8;
    animation: th-pour-fill 5.8s var(--th-ease-soft) infinite;
    animation-delay: 2.6s;
}

@keyframes th-pour-fill {
    0%        { stroke-dashoffset: 8.8; }
    45%, 82%  { stroke-dashoffset: 0; }
    100%      { stroke-dashoffset: 8.8; }
}

@media (max-width: 1024px) {
    .th-hero__body--split {
        grid-template-columns: 1fr;
        align-items: start;
        gap: clamp(1.75rem, 4vw, 2.5rem);
    }
    .th-hero__reel-frame {
        aspect-ratio: 16 / 10;
        max-height: 38vh;
    }
    /* Stacked, the body grows tall enough to run under the absolutely placed top
       rule. Dropping the rule back into the flow — pushed up by the auto margin
       against the section's flex-end — keeps the two from ever meeting. */
    .th-hero--reel .th-hero__top {
        position: static;
        margin-bottom: auto;
        /* On a short screen the auto margin collapses to nothing, so the gap has
           to be real padding. */
        padding-bottom: clamp(1.75rem, 6vw, 3rem);
    }
}

@media (max-width: 767px) {
    /* Crest + meta row is pure ornament — on a phone it only eats the hero's
       vertical room, so it drops out entirely. */
    .th-hero__top {
        display: none;
    }
    .th-hero__foot {
        gap: 1.5rem;
    }
    .th-hero__pour {
        width: 18px;
        height: 44px;
    }
}

/* ==========================================================================
   02 — MANIFESTO
   ========================================================================== */

/* An editorial spread: index rail · statement · collage. The section is scroll
   linked (`data-th-scroll="through"`), so --th-p drives the rail fill, the column
   hairlines and the venn. Every consumer falls back to `1` — the resting, fully
   drawn state — which is what no-JS, reduced motion and the editor all get. */

.th-manifesto {
    position: relative;
    padding-block: calc(var(--th-block) + clamp(0rem, 2vw, 2rem)) var(--th-block);
    background:
        radial-gradient(115% 80% at 8% -10%, var(--th-paper) 0%, rgba(251, 249, 246, 0) 62%),
        var(--th-cream);
}

/* The layout grid, made visible. Four hairlines that draw themselves downward
   as the section passes — the page's structure as ornament. */
.th-manifesto__field {
    position: absolute;
    inset-block: 0;
    inset-inline: 0;
    z-index: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    width: 100%;
    max-width: 1680px;
    margin-inline: auto;
    padding-inline: var(--th-gutter);
    pointer-events: none;
}

.th-manifesto__field i {
    justify-self: end;
    width: 1px;
    background: linear-gradient(to bottom, transparent, var(--th-rule) 14%, var(--th-rule) 74%, transparent);
    transform: scaleY(var(--th-p, 1));
    transform-origin: top;
}

.th-manifesto__inner {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: clamp(54px, 6vw, 96px) minmax(0, 1.08fr) minmax(0, .84fr);
    gap: clamp(1.75rem, 4vw, 4.5rem);
    align-items: start;
}

/* Rail ------------------------------------------------------------------- */

.th-manifesto__rail {
    position: sticky;
    top: clamp(6rem, 20vh, 13rem);
    display: grid;
    justify-items: center;
    gap: clamp(.9rem, 1.6vw, 1.35rem);
}

/* Outlined numeral — the section index as a piece of print furniture. */
.th-manifesto__num {
    font-family: var(--th-display);
    font-size: clamp(1.5rem, 2.6vw, 2.5rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-espresso);
    opacity: .5;
}

.th-manifesto__track {
    position: relative;
    width: 1px;
    height: clamp(88px, 15vh, 180px);
    background: var(--th-rule);
    overflow: hidden;
}

.th-manifesto__track i {
    position: absolute;
    inset: 0;
    background: var(--th-crema);
    transform: scaleY(var(--th-p, 1));
    transform-origin: top;
}

.th-manifesto__vertical {
    writing-mode: vertical-rl;
    font-size: var(--th-t-label);
    font-weight: 500;
    letter-spacing: .32em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--th-muted);
}

/* Statement -------------------------------------------------------------- */

.th-manifesto__statement {
    font-size: clamp(2.25rem, 4.35vw, 4.125rem);
    font-weight: 800;
    line-height: .97;
    letter-spacing: -.042em;
    max-width: 15ch;
    text-wrap: pretty;
}

.th-manifesto__statement em,
.th-manifesto__statement .th-word--accent em {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    letter-spacing: -.015em;
    color: var(--th-espresso);
}

/* Hand-drawn rule under the serif words. Lives on the inner span so it rides up
   with the word mask, then wipes in once the word has landed. */
.th-manifesto__statement .th-word--accent > span {
    position: relative;
}

.th-manifesto__statement .th-word--accent > span::after {
    content: "";
    position: absolute;
    left: -.02em;
    right: -.02em;
    bottom: .01em;
    height: .17em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12' preserveAspectRatio='none'%3E%3Cpath d='M2 8.4C38 3.2 66 10.6 104 5.6c30-4 62-2.2 94 2.2' fill='none' stroke='%23C1793C' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .8s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 55ms + 520ms);
}

.th-js [data-th-reveal].is-in .th-word--accent > span::after,
html:not(.th-js) .th-manifesto__statement .th-word--accent > span::after,
.th-is-editor .th-manifesto__statement .th-word--accent > span::after {
    transform: scaleX(1);
}

/* Copy ------------------------------------------------------------------- */

.th-manifesto__cols {
    display: grid;
    gap: clamp(1.25rem, 2.4vw, 1.9rem);
    max-width: 54ch;
    margin-top: clamp(2rem, 4.5vw, 3.5rem);
    /* Indented off the statement so the two blocks read as separate voices. */
    padding-left: clamp(0rem, 7vw, 6.5rem);
}

/* The `.th-section p` reset wins on specificity, so the copy sizes are set from
   the column down. */
.th-manifesto__cols .th-manifesto__lede {
    font-size: var(--th-t-md);
    line-height: 1.3;
    letter-spacing: -.018em;
    color: var(--th-ink);
    max-width: 26ch;
}

.th-manifesto__cols .th-manifesto__lede::first-letter {
    float: left;
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    font-size: 2.35em;
    line-height: .8;
    padding-right: .08em;
    margin-top: .02em;
    color: var(--th-espresso);
}

.th-manifesto__cols .th-manifesto__body {
    font-size: var(--th-t-sm);
    line-height: 1.58;
    color: var(--th-ink-soft);
    max-width: 46ch;
}

.th-manifesto__cols .th-manifesto__note {
    display: flex;
    align-items: center;
    gap: .95rem;
    font-size: var(--th-t-label);
    font-weight: 500;
    letter-spacing: .2em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--th-muted);
}

.th-manifesto__note-rule {
    flex: none;
    width: clamp(28px, 4vw, 64px);
    height: 1px;
    background: var(--th-crema);
}

/* Aside ------------------------------------------------------------------ */

.th-manifesto__aside {
    display: grid;
    gap: clamp(1.35rem, 2.6vw, 2.25rem);
    justify-items: end;
}

.th-manifesto__stack {
    position: relative;
    width: min(100%, 420px);
}

.th-manifesto__figure {
    width: 100%;
    aspect-ratio: 4 / 5;
}

/* `scale` and `rotate` are separate properties from `transform`, which the reveal
   system animates — the hover rides along without fighting it. The image reveal
   declares its own `transition`, so its list is restated here with `scale` added;
   the selector matches its weight and wins on order. */
.th-manifesto__figure--small {
    transition: scale 1.1s var(--th-ease), rotate 1.1s var(--th-ease);
}

.th-js .th-figure.th-manifesto__figure[data-th-reveal="image"] img {
    transition:
        clip-path 1.35s var(--th-ease),
        transform 1.9s var(--th-ease),
        scale 1.1s var(--th-ease);
}

html:not(.th-js) .th-manifesto__figure img {
    transition: scale 1.1s var(--th-ease);
}

.th-manifesto__stack:hover .th-manifesto__figure img {
    scale: 1.035;
}

.th-manifesto__stack:hover .th-manifesto__figure--small {
    rotate: -1.2deg;
    scale: 1.02;
}

/* Offset register frame — the print mark the photo is trimmed against. It hangs
   off the stack, not the figure, which clips its own overflow for the reveal. */
.th-manifesto__stack::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    translate: clamp(10px, 1.1vw, 18px) clamp(10px, 1.1vw, 18px);
    border: 1px solid var(--th-espresso);
    opacity: .34;
    pointer-events: none;
}

/* Parallax on `translate` rather than `transform`, which the image-reveal owns.
   The photo is oversized so the drift never uncovers the frame. */
.th-section .th-manifesto__figure img {
    top: -7%;
    height: 114%;
    translate: 0 calc((var(--th-p, .5) - .5) * -3.2rem);
}

.th-manifesto__figure--small {
    position: absolute;
    left: clamp(-2.75rem, -3.5vw, -1.25rem);
    bottom: clamp(-2.25rem, -3vw, -1.25rem);
    z-index: 4;
    width: clamp(112px, 36%, 186px);
    aspect-ratio: 3 / 4;
    /* `rotate` rather than `transform`, which the reveal system owns. */
    rotate: -3.6deg;
    border: 6px solid var(--th-paper);
    box-shadow: 0 34px 60px -32px rgba(23, 16, 10, .55);
}

/* The aside closes on a call to action rather than a caption. With a collage the
   small frame hangs past the stack's bottom edge, so the button steps clear of
   that overhang; without it the grid gap already reads right. */
.th-manifesto__stack.has-second + .th-manifesto__cta {
    margin-top: clamp(.75rem, 2vw, 1.5rem);
}

/* Venn — Third Wave × Third Place. Two lobes that close on each other as the
   section scrolls; multiply blending paints the intersection for free. */
.th-manifesto__venn {
    --th-conv: calc(1 - var(--th-p, 1));
    --th-shift: calc(32% + var(--th-conv) * 46%);
    position: relative;
    display: grid;
    place-items: center;
    width: min(100%, 340px);
    aspect-ratio: 2 / 1.06;
    margin-top: clamp(2rem, 4vw, 3.25rem);
    margin-left: clamp(0rem, 7vw, 6.5rem);
}

.th-manifesto__lobe {
    position: absolute;
    top: 50%;
    left: 50%;
    display: grid;
    place-items: center;
    width: 62%;
    aspect-ratio: 1;
    border: 1px solid var(--th-espresso);
    border-radius: 50%;
    background: rgba(193, 121, 60, .1);
    mix-blend-mode: multiply;
    opacity: .82;
}

.th-manifesto__lobe--a {
    translate: calc(-50% - var(--th-shift)) -50%;
}

.th-manifesto__lobe--b {
    translate: calc(-50% + var(--th-shift)) -50%;
}

.th-manifesto__lobe span {
    max-width: 7ch;
    font-size: calc(var(--th-t-label) * .95);
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    line-height: 1.35;
    text-align: center;
    color: var(--th-espresso);
}

.th-manifesto__lobe--a span {
    margin-right: 26%;
}

.th-manifesto__lobe--b span {
    margin-left: 26%;
}

.th-manifesto__core {
    position: relative;
    z-index: 2;
    font-family: var(--th-display);
    font-size: var(--th-t-sm);
    font-weight: 800;
    letter-spacing: -.03em;
    color: var(--th-espresso);
    opacity: clamp(0, calc((var(--th-p, 1) - .5) * 3), 1);
    transition: opacity .3s linear;
}

@media (min-width: 1101px) {
    /* The rail carries the label on wide screens, but the rail is aria-hidden —
       so the real one is only hidden visually, never from assistive tech. */
    .th-manifesto__label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }
}

@media (max-width: 1100px) {
    .th-manifesto__inner {
        grid-template-columns: minmax(0, 1.05fr) minmax(0, .85fr);
    }
    .th-manifesto__rail,
    .th-manifesto__field {
        display: none;
    }
    .th-manifesto__statement {
        margin-top: clamp(1.5rem, 4vw, 2.75rem);
    }
}

@media (max-width: 900px) {
    .th-manifesto__inner {
        grid-template-columns: minmax(0, 1fr);
        gap: clamp(2.5rem, 6vw, 4rem);
    }
    .th-manifesto__statement {
        max-width: 15ch;
    }
    .th-manifesto__cols {
        padding-left: 0;
    }
    .th-manifesto__aside {
        justify-items: start;
    }
    .th-manifesto__stack {
        width: min(100%, 340px);
        margin-left: clamp(1.5rem, 6vw, 3rem);
    }
    .th-manifesto__venn {
        width: min(100%, 300px);
        margin-left: 0;
    }
}

@media (max-width: 520px) {
    .th-manifesto__figure--small {
        left: -1rem;
        bottom: -1.25rem;
        border-width: 4px;
    }
}

/* ==========================================================================
   03 — DUALITY (Third Wave × Third Place)
   ========================================================================== */

/* Every structural value below is a var with the house default as its fallback,
   so the widget's style tabs can re-skin the section without touching CSS.
   Typography and colours are left as plain declarations: Elementor's group
   controls win on specificity when the editor sets them. */

/* The section reads light: a white sheet with the panel block set on it like a
   plate on paper. Intro furniture follows --thd-rule-soft, which the dark house
   presets flip in one place, so a re-skin never has to chase individual rules. */
.th-duality {
    background: var(--thd-bg, var(--th-paper));
    color: var(--thd-ink, var(--th-ink));
    --thd-rule-soft: var(--th-ink-faint);
    --th-muted: var(--th-ink-soft);
    --th-rule: var(--th-ink-faint);
}

/* padding-block, not the shorthand: the shorthand reset .th-shell's gutter and
   ran the intro out to the viewport edge while the rest of the page stayed
   inside the shell. */
.th-duality__intro {
    padding-block: var(--thd-intro-top, clamp(3.5rem, 8vw, 7rem)) var(--thd-intro-bottom, clamp(2.5rem, 5vw, 4rem));
    display: grid;
    grid-template-columns: var(--thd-intro-cols, minmax(0, 1fr) minmax(0, 1fr));
    gap: var(--thd-intro-gap, clamp(1.5rem, 4vw, 4rem));
    align-items: var(--thd-intro-align, end);
}

.th-duality__lead {
    display: grid;
    justify-items: start;
    gap: clamp(.9rem, 1.8vw, 1.35rem);
    min-width: 0;
}

/* Stamp — the drawn house mark, the cut-out numeral and a hairline that runs
   out across the column as the section is read. Print furniture, not a badge. */
.th-duality__stamp {
    display: flex;
    align-items: center;
    gap: clamp(.75rem, 1.6vw, 1.25rem);
    width: 100%;
    margin-bottom: clamp(.25rem, 1vw, .75rem);
}

.th-duality__crest {
    display: block;
    flex: none;
    width: clamp(52px, 5.4vw, 76px);
    height: auto;
    color: inherit;
    opacity: .82;
    overflow: visible;
}

/* pathLength="1" on every stroke lets one keyframe draw all six moves. */
.th-duality__crest-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

/* Six strokes now (loaf, scoring, counter, cup, handle+saucer, steam), so the
   stagger is tighter than the old three-move mark — the hand keeps moving
   instead of pausing between pieces, and the whole mark still lands under 2s. */
.th-js .th-duality__crest.is-in .th-duality__crest-draw {
    animation: th-draw-in 1.05s var(--th-ease) forwards;
    animation-delay: calc(var(--i, 0) * .14s);
}

html:not(.th-js) .th-duality__crest-draw,
.th-is-editor .th-duality__crest-draw {
    stroke-dashoffset: 0;
}

/* Crema — the dot sits inside the cup, so its origin has to move with it. */
.th-duality__crest-bead {
    transform-origin: 55px 25.5px;
    animation: th-pulse 3.4s var(--th-ease-soft) infinite;
}

/* Outlined numeral — the section index as a piece of type, not a label. */
.th-duality__num {
    flex: none;
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    /* `-webkit-text-fill-color` rather than `color: transparent`: it clears only
       the fill, so `currentColor` still resolves to the section's inherited ink.
       That matters here because the surface is re-skinnable from the Style tab —
       a hard-coded stroke colour would go invisible on half the presets. Engines
       without text-stroke fall back to a solid numeral, which still reads. */
    color: inherit;
    -webkit-text-fill-color: transparent;
    -webkit-text-stroke: 1px currentColor;
    opacity: .5;
}

.th-duality__stamp-rule {
    flex: 1;
    min-width: 0;
    height: 1px;
    background: var(--thd-rule-color, var(--thd-rule-soft));
    overflow: hidden;
}

.th-duality__stamp-rule i {
    display: block;
    height: 100%;
    background: var(--thd-accent, var(--th-crema));
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .06) * 2.4), 1));
    transform-origin: left;
}

.th-duality__title {
    font-size: var(--th-t-lg);
    line-height: .96;
    max-width: var(--thd-title-measure, 14ch);
}

.th-duality__note {
    color: var(--th-muted);
    max-width: var(--thd-note-measure, 40ch);
    justify-self: var(--thd-note-justify, end);
}

/* The panel block sits in the same .th-shell as the intro, so it lines up with
   every other widget instead of bleeding to the viewport edge. --bleed puts the
   old edge-to-edge behaviour back for sections that want it. */
.th-duality__frame {
    padding-bottom: var(--thd-panels-bottom, clamp(3.5rem, 8vw, 7rem));
}

.th-duality__frame--bleed {
    padding-bottom: var(--thd-panels-bottom, 0px);
}

.th-duality__panels {
    position: relative;
    display: flex;
    flex-direction: var(--thd-panels-dir, row);
    gap: var(--thd-panels-gap, 0px);
    min-height: var(--thd-panels-min, clamp(560px, 82svh, 900px));
    /* The plate carries its own ground so a panel without a photo still reads
       as part of the block, and so the light sheet stops at its edge. */
    background: var(--thd-panel-bg, var(--th-ink));
    color: var(--thd-panel-ink, var(--th-cream));
    --th-muted: var(--thd-panel-muted, var(--th-cream-soft));
    --th-rule: var(--th-rule-light);
    /* Reads as nothing where the plate already contrasts with the sheet, and as
       a hairline on the dark presets where the two grounds are the same value. */
    border-top: var(--thd-rule-width, 1px) solid var(--thd-rule-color, var(--thd-rule-soft));
    /* Rounding and clipping the plate rather than each panel keeps the seam
       square in every direction, reversed and stacked included. */
    border-radius: var(--thd-panel-radius, 0);
    overflow: clip;
}

/* An accent hairline that draws across the top of the plate while the block
   passes, so the join between intro and panels is an event, not a border. */
.th-duality__panels::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: var(--thd-rule-width, 1px);
    z-index: 6;
    background: var(--thd-accent, var(--th-crema));
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .12) * 2.2), 1));
    transform-origin: left;
    pointer-events: none;
}

.th-panel {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: var(--thd-panel-align, flex-end);
    padding: var(--thd-panel-pad, clamp(1.75rem, 3.5vw, 3.5rem) clamp(1.5rem, 3vw, 3rem));
    overflow: hidden;
    border-left: var(--thd-rule-width, 1px) solid var(--thd-rule-color, var(--th-rule-light));
    transition: flex-grow 1.1s var(--th-ease);
    cursor: default;
}

.th-panel:first-child {
    border-left: 0;
}

.th-panel__media {
    position: absolute;
    inset: 0;
    z-index: 0;
}

/* `transform` is owned by the hover scale, so the scroll drift rides on the
   separate `translate` property and the two never overwrite each other. The
   photo is oversized by the scale above, so the drift never uncovers an edge. */
.th-panel__media img {
    transform: scale(var(--thd-media-scale, 1.06));
    translate: 0 calc((var(--th-p, .5) - .5) * -3.4%);
    transition: transform 1.6s var(--th-ease), filter 1.1s var(--th-ease);
    filter: saturate(var(--thd-media-saturate, .72)) brightness(var(--thd-media-brightness, .5));
    object-position: var(--thd-media-pos, 50% 50%);
    will-change: transform;
}

/* Register ticks — four drawn corners that scribe the panel out of its ground.
   They grow with the section's progress and snap open on hover or focus, which
   gives the keyboard the same feedback the pointer gets. */
.th-panel__ticks {
    position: absolute;
    inset: clamp(.9rem, 1.8vw, 1.6rem);
    z-index: 3;
    pointer-events: none;
}

.th-panel__ticks i {
    position: absolute;
    width: clamp(14px, 2vw, 26px);
    height: clamp(14px, 2vw, 26px);
    border: 0 solid var(--thd-accent, var(--th-crema));
    opacity: calc(.18 + var(--th-p, 1) * .5);
    transition: opacity .7s var(--th-ease), scale .7s var(--th-ease);
    scale: calc(.6 + var(--th-p, 1) * .4);
}

.th-panel__ticks i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; transform-origin: top left; }
.th-panel__ticks i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; transform-origin: top right; }
.th-panel__ticks i:nth-child(3) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; transform-origin: bottom right; }
.th-panel__ticks i:nth-child(4) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; transform-origin: bottom left; }

.th-panel:hover .th-panel__ticks i,
.th-panel:focus-within .th-panel__ticks i {
    opacity: 1;
    scale: 1;
}

.th-panel__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
        var(--thd-overlay-from, rgba(23, 16, 10, .93)) 6%,
        var(--thd-overlay-mid, rgba(23, 16, 10, .3)) 60%,
        var(--thd-overlay-to, rgba(23, 16, 10, .55)) 100%);
}

.th-panel__body {
    position: relative;
    z-index: 2;
    display: grid;
    gap: var(--thd-body-gap, clamp(.75rem, 1.4vw, 1.15rem));
    /* start / center / end reads the same to both properties, so one control
       can drive the box alignment and the text alignment together. */
    justify-items: var(--thd-body-justify, stretch);
    text-align: var(--thd-body-text-align, start);
}

/* The index no longer sits alone: a meter runs out beside it, filling while the
   panel is read and completing on hover — the panel's own little progress rule. */
.th-panel__index {
    display: flex;
    align-items: center;
    gap: .9em;
    font-family: var(--th-display);
    font-size: calc(var(--th-t-label) * 1.15);
    font-weight: 700;
    letter-spacing: .28em;
    color: var(--thd-accent, var(--th-crema));
}

.th-panel__meter {
    display: block;
    flex: none;
    width: clamp(28px, 5vw, 74px);
    height: 1px;
    background: currentColor;
    opacity: .45;
    transform: scaleX(clamp(.12, calc((var(--th-p, 1) - .1) * 1.9), 1));
    transform-origin: left;
    transition: transform .8s var(--th-ease), opacity .6s var(--th-ease);
}

.th-panel:hover .th-panel__meter,
.th-panel:focus-within .th-panel__meter {
    transform: scaleX(1);
    opacity: 1;
}

.th-panel__title {
    font-size: clamp(1.75rem, 3.6vw, 3.25rem);
    line-height: .94;
    text-transform: uppercase;
    letter-spacing: -.03em;
}

.th-panel__keyword {
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: clamp(1.5rem, 2.6vw, 2.25rem);
    line-height: 1;
    color: var(--thd-accent, var(--th-crema));
}

/* The keyword is the panel's one serif note, so it gets the drawn rule. Plain
   currentColor rather than the manifesto's fixed crema squiggle, so a per-panel
   accent picked in the Style tab carries through to the underline as well. */
.th-panel__keyword span {
    position: relative;
    display: inline-block;
    padding-bottom: .12em;
}

.th-panel__keyword span::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: currentColor;
    opacity: .6;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .85s var(--th-ease);
    transition-delay: .45s;
}

.th-js [data-th-reveal].is-in .th-panel__keyword span::after,
html:not(.th-js) .th-panel__keyword span::after,
.th-is-editor .th-panel__keyword span::after {
    transform: scaleX(1);
}

.th-panel__text {
    color: var(--th-muted);
    max-width: var(--thd-text-measure, 42ch);
    font-size: var(--th-t-body);
}

.th-panel__seam {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 5;
    font-family: var(--th-display);
    font-size: clamp(2.5rem, 6vw, 5.5rem);
    font-weight: 400;
    color: var(--thd-panel-ink, var(--th-cream));
    pointer-events: none;
    mix-blend-mode: var(--thd-seam-blend, difference);
    opacity: var(--thd-seam-opacity, .9);
    transition: transform 1.1s var(--th-ease);
}

/* A dashed ring turns slowly behind the seam glyph — the same grain ring the
   hero crest uses, so the two marks read as one family. */
.th-panel__seam::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 2.15em;
    height: 2.15em;
    margin: -1.075em 0 0 -1.075em;
    border: 1px dashed currentColor;
    border-radius: 50%;
    opacity: .34;
    animation: th-spin 64s linear infinite;
}

.th-duality__panels:hover .th-panel__seam {
    transform: translate(-50%, -50%) rotate(var(--thd-seam-rotate, 90deg));
}

@media (hover: hover) and (min-width: 901px) {
    .th-duality__panels:hover .th-panel {
        flex-grow: var(--thd-grow-rest, .82);
    }
    .th-duality__panels .th-panel:hover,
    .th-duality__panels .th-panel:focus-within {
        flex-grow: var(--thd-grow-active, 1.4);
    }
    .th-panel:hover .th-panel__media img,
    .th-panel:focus-within .th-panel__media img {
        transform: scale(var(--thd-media-scale-hover, 1));
        filter: saturate(var(--thd-media-saturate-hover, .95)) brightness(var(--thd-media-brightness-hover, .68));
    }
}

@media (max-width: 900px) {
    .th-duality__intro {
        grid-template-columns: 1fr;
        align-items: start;
    }
    .th-duality__note {
        justify-self: start;
    }
    .th-panel__ticks {
        inset: .75rem;
    }
    .th-duality__panels {
        flex-direction: column;
        min-height: 0;
    }
    .th-panel {
        min-height: var(--thd-panel-min-mobile, 64svh);
        border-left: 0;
        border-top: var(--thd-rule-width, 1px) solid var(--thd-rule-color, var(--th-rule-light));
    }
    .th-panel:first-child {
        border-top: 0;
    }
    .th-panel__seam {
        display: none;
    }
}

/* Surface presets — pick a house surface without opening the colour pickers.
   The section is light by default, so the dark presets are the ones that have
   to flip the shared muted/rule tokens for the primitives to follow. */

.th-duality--ink,
.th-duality--espresso,
.th-duality--roast,
.th-duality--bean {
    --thd-ink: var(--th-cream);
    --thd-rule-soft: var(--th-cream-faint);
    --th-muted: var(--th-cream-soft);
    --th-rule: var(--th-rule-light);
}

.th-duality--ink {
    --thd-bg: var(--th-ink);
}

.th-duality--espresso {
    --thd-bg: var(--th-espresso);
}

.th-duality--roast {
    --thd-bg: var(--th-roast);
}

.th-duality--bean {
    --thd-bg: var(--th-bean);
}

.th-duality--cream {
    --thd-bg: var(--th-cream);
}

/* Kept for sections saved before white became the house default; it now simply
   states the default out loud. */
.th-duality--paper {
    --thd-bg: var(--th-paper);
}

/* Reversed order flips which panel sits against the outer edge, so the rule
   that has to disappear is the last one, not the first. */
.th-duality--reverse .th-panel:first-child {
    border-left: var(--thd-rule-width, 1px) solid var(--thd-rule-color, var(--th-rule-light));
}

.th-duality--reverse .th-panel:last-child {
    border-left: 0;
}

/* Stacked panels keep their vertical rule on the block edge, not the side. */
.th-duality--stacked .th-panel {
    border-left: 0;
    border-top: var(--thd-rule-width, 1px) solid var(--thd-rule-color, var(--th-rule-light));
}

.th-duality--stacked .th-panel:first-child {
    border-top: 0;
}

.th-duality--stacked .th-panel__seam {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .th-panel__media img {
        translate: none !important;
    }
    .th-duality__stamp-rule i,
    .th-duality__panels::before,
    .th-panel__meter,
    .th-panel__keyword span::after {
        transform: scaleX(1) !important;
    }
    .th-panel__ticks i {
        opacity: 1 !important;
        scale: 1 !important;
    }
    .th-duality__crest-draw {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }
    .th-duality__crest-bead,
    .th-panel__seam::before {
        animation: none !important;
    }
}

/* ==========================================================================
   04 — OUR COFFEE
   ========================================================================== */

.th-coffee {
    background: var(--th-roast);
    color: var(--th-cream);
    padding-block: var(--th-block);
}

.th-coffee__inner {
    display: grid;
    grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
    gap: clamp(2.5rem, 6vw, 6rem);
    align-items: center;
}

.th-coffee__copy {
    display: grid;
    gap: clamp(1.25rem, 2.4vw, 2rem);
    align-content: start;
}

.th-coffee__title {
    font-size: var(--th-t-lg);
    line-height: .95;
    max-width: 13ch;
}

.th-coffee__title em {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    color: var(--th-crema);
    letter-spacing: -.01em;
}

.th-coffee__note {
    font-size: var(--th-t-label);
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--th-cream-soft);
    line-height: 1.9;
    border-top: 1px solid var(--th-rule-light);
    padding-top: 1.1rem;
    max-width: 34ch;
}

.th-coffee__stage {
    position: relative;
    display: grid;
    place-items: center;
    aspect-ratio: 1 / 1;
    width: 100%;
    max-width: 600px;
    justify-self: center;
}

.th-coffee__disc {
    position: relative;
    width: min(76%, 450px);
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    overflow: hidden;
    box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .8);
}

.th-coffee__disc img {
    transform: scale(1.05) rotate(calc(var(--th-p, 0) * 22deg));
    transition: transform .9s var(--th-ease);
    will-change: transform;
}

.th-coffee__disc::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: radial-gradient(circle at 50% 42%, transparent 40%, rgba(23, 16, 10, .68) 100%);
}

.th-coffee__ring {
    position: absolute;
    inset: 4%;
    border: 1px solid var(--th-rule-light);
    border-radius: 50%;
    pointer-events: none;
}

.th-coffee__ring--outer {
    inset: -2%;
    border-style: dashed;
    opacity: .45;
    animation: th-spin 90s linear infinite;
}

@keyframes th-spin {
    to { transform: rotate(360deg); }
}

.th-coffee__nodes {
    position: absolute;
    inset: 0;
    list-style: none;
    margin: 0;
    padding: 0;
}

.th-coffee__node {
    position: absolute;
    margin: 0;
}

.th-coffee__node:nth-child(1) { top: 2%; left: 50%; transform: translateX(-50%); }
.th-coffee__node:nth-child(2) { top: 50%; right: 0; transform: translateY(-50%); }
.th-coffee__node:nth-child(3) { bottom: 2%; left: 50%; transform: translateX(-50%); }
.th-coffee__node:nth-child(4) { top: 50%; left: 0; transform: translateY(-50%); }

.th-coffee__btn {
    appearance: none;
    background: rgba(23, 16, 10, .6);
    backdrop-filter: blur(6px);
    border: 1px solid var(--th-rule-light);
    color: var(--th-cream-soft);
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .24em;
    text-transform: uppercase;
    padding: .95em 1.5em;
    border-radius: 999px;
    cursor: pointer;
    transition: color .5s var(--th-ease), border-color .5s var(--th-ease), background-color .5s var(--th-ease), transform .5s var(--th-ease);
    white-space: nowrap;
}

.th-coffee__btn:hover {
    color: var(--th-cream);
    border-color: var(--th-crema);
}

.th-coffee__btn[aria-selected="true"] {
    background: var(--th-crema);
    border-color: var(--th-crema);
    color: var(--th-ink);
    transform: scale(1.04);
}

.th-coffee__readout {
    min-height: 5.5em;
    display: grid;
    align-content: start;
    gap: .6rem;
    border-left: 1px solid var(--th-crema);
    padding-left: clamp(1rem, 1.6vw, 1.5rem);
}

.th-coffee__readout dt {
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 700;
    letter-spacing: .26em;
    text-transform: uppercase;
    color: var(--th-crema);
}

.th-coffee__readout dd {
    margin: 0;
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: var(--th-t-md);
    line-height: 1.2;
    color: var(--th-cream);
    max-width: 32ch;
}

.th-coffee__readout > * {
    animation: th-swap .7s var(--th-ease);
}

@keyframes th-swap {
    from { opacity: 0; transform: translateY(.5rem); }
    to { opacity: 1; transform: none; }
}

@media (max-width: 1024px) {
    .th-coffee__inner {
        grid-template-columns: 1fr;
    }
    .th-coffee__stage {
        aspect-ratio: auto;
        gap: 2rem;
    }
    .th-coffee__nodes {
        position: static;
        display: flex;
        flex-wrap: wrap;
        gap: .6rem;
        justify-content: center;
        margin-top: 1.75rem;
    }
    .th-coffee__node {
        position: static !important;
        transform: none !important;
    }
    .th-coffee__disc {
        width: min(86%, 440px);
    }
    .th-coffee__ring,
    .th-coffee__ring--outer {
        display: none;
    }
}

/* ==========================================================================
   05 — THE BAKERY
   Three movements: two dark spreads with one paper-white band between them.
   Everything that moves is driven by the shared --th-p scroll progress
   (third.js, data-th-scroll), so the section needs no JavaScript of its own
   beyond the hour counter.
   ========================================================================== */

.th-bakery {
    background: var(--th-ink);
    color: var(--th-cream);
}

/* --- 1 — Stage ----------------------------------------------------------- */

.th-bakery__stage {
    position: relative;
    overflow: hidden;
}

.th-bakery__media {
    position: absolute;
    inset: 0;
    z-index: 0;
}

.th-bakery__media img {
    object-position: 50% 46%;
    /* Slow counter-scroll: the oven shot drifts up as the block passes. */
    transform: scale(1.16) translate3d(0, calc(var(--th-p, .5) * -7% + 3.5%), 0);
    filter: saturate(.86);
    will-change: transform;
}

.th-bakery__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
        linear-gradient(to right, rgba(23, 16, 10, .93) 0%, rgba(23, 16, 10, .5) 52%, rgba(23, 16, 10, .82) 100%),
        linear-gradient(to top, rgba(23, 16, 10, .88) 0%, transparent 48%);
}

/* Oven warmth rising from the floor of the frame as the section is read. */
.th-bakery__glow {
    position: absolute;
    left: -10%;
    right: -10%;
    bottom: -22%;
    height: 78%;
    z-index: 1;
    pointer-events: none;
    background: radial-gradient(58% 100% at 46% 100%,
        rgba(193, 121, 60, .5) 0%,
        rgba(168, 100, 44, .22) 38%,
        transparent 72%);
    opacity: calc(.22 + var(--th-p, .5) * .78);
    mix-blend-mode: screen;
}

.th-bakery__stage-inner {
    position: relative;
    z-index: 2;
    min-height: clamp(640px, 100svh, 1040px);
    display: grid;
    grid-template-rows: auto 1fr auto;
    gap: clamp(2rem, 5vw, 4rem);
    padding-block: clamp(4.5rem, 9vw, 7rem) clamp(2rem, 4vw, 3.25rem);
}

.th-bakery__top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 2rem;
    border-top: 1px solid var(--th-cream-faint);
    padding-top: 1rem;
}

.th-bakery__meta {
    font-size: var(--th-t-label);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--th-cream-soft);
    text-align: right;
}

.th-bakery__hero {
    align-self: center;
    display: grid;
    justify-items: start;
    gap: clamp(1.15rem, 2.4vw, 1.9rem);
}

.th-bakery__big {
    font-size: var(--th-t-hero);
    line-height: .84;
    text-transform: uppercase;
    letter-spacing: -.045em;
    margin: 0;
}

.th-bakery__count,
.th-bakery__line {
    display: block;
}

/* The counted hours carry the accent; the unit answers in editorial italic,
   the same display/serif pairing the hero uses for its wordmark and subtitle. */
.th-bakery__count em {
    font-style: normal;
    color: var(--th-crema);
    font-variant-numeric: tabular-nums;
}

.th-bakery__count i {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    letter-spacing: -.01em;
    text-transform: none;
    margin-left: .1em;
}

.th-bakery__kicker {
    max-width: 42ch;
    color: var(--th-cream-soft);
    font-size: var(--th-t-sm);
    line-height: 1.55;
}

.th-bakery__cue {
    justify-self: start;
    display: inline-flex;
    align-items: center;
    gap: .9em;
    font-size: var(--th-t-label);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--th-cream-soft);
}

.th-bakery__cue i {
    display: block;
    position: relative;
    width: 1px;
    height: 54px;
    background: var(--th-cream-faint);
    overflow: hidden;
}

.th-bakery__cue i::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--th-crema);
    animation: th-bakery-drip 2.6s var(--th-ease-soft) infinite;
}

@keyframes th-bakery-drip {
    0% { transform: translateY(-100%); }
    55%, 100% { transform: translateY(100%); }
}

/* --- 2 — The rhythm of the night ----------------------------------------
   The one light movement in the section: a paper-white band between the two
   dark spreads, so the timeline reads like a schedule pinned to the wall.
   Re-declaring --th-muted and --th-rule flips the shared primitives back to
   their light-surface values for everything inside the block. */

.th-bakery__night {
    position: relative;
    /* Above the section's grain film (z-index 6) — the white surface stays
       clean instead of picking up the dark spread's noise. */
    z-index: 7;
    background: var(--th-paper);
    color: var(--th-ink);
    --th-muted: var(--th-ink-soft);
    --th-rule: var(--th-ink-faint);
    /* On a light surface the crema accent loses its footing, so the accents
       inside this block step down to the deeper caramel. */
    --thb-accent: var(--th-caramel);
}

/* Lifting the block above the film also lifts it out of it, so the band
   carries its own — lighter, multiplied — and the paper keeps its tooth. */
.th-bakery__night::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background-image: var(--th-grain);
    background-size: 160px;
    opacity: .06;
    mix-blend-mode: multiply;
    pointer-events: none;
}

/* The label and the ear both key off the crema by default. */
.th-bakery__night .th-label {
    color: var(--thb-accent);
}

.th-bakery__night-inner {
    display: grid;
    grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
    gap: clamp(2.5rem, 6vw, 6rem);
    align-items: start;
    padding-block: clamp(4.5rem, 10vw, 9rem);
}

.th-bakery__night-head {
    position: sticky;
    top: clamp(4rem, 14vh, 9rem);
    display: grid;
    justify-items: start;
    gap: clamp(1rem, 2vw, 1.6rem);
}

.th-bakery__ear {
    width: clamp(20px, 2.2vw, 26px);
    height: auto;
    color: var(--thb-accent, var(--th-crema));
}

.th-bakery__ear-stem,
.th-bakery__ear-grains path {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

.th-js .th-bakery__ear.is-in .th-bakery__ear-stem {
    animation: th-bakery-draw 1s var(--th-ease) forwards;
}

.th-js .th-bakery__ear.is-in .th-bakery__ear-grains path {
    animation: th-bakery-draw .75s var(--th-ease) forwards;
    animation-delay: calc(.4s + var(--i, 0) * .15s);
}

html:not(.th-js) .th-bakery__ear-stem,
html:not(.th-js) .th-bakery__ear-grains path,
.th-is-editor .th-bakery__ear-stem,
.th-is-editor .th-bakery__ear-grains path {
    stroke-dashoffset: 0;
}

@keyframes th-bakery-draw {
    to { stroke-dashoffset: 0; }
}

.th-bakery__night-title {
    font-size: var(--th-t-lg);
    line-height: .98;
    max-width: 14ch;
}

.th-bakery__rhythm {
    --thb-rail: clamp(2rem, 4vw, 3.25rem);

    position: relative;
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--thb-rail);
    display: grid;
    gap: clamp(2.25rem, 4.5vw, 3.75rem);
}

/* Absolute offsets resolve against the padding box, so left:0 lands on the
   outer edge of the list and the steps sit one --thb-rail to its right. */
.th-bakery__rail {
    position: absolute;
    left: 0;
    top: .6rem;
    bottom: .6rem;
    width: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-bakery__rail i {
    position: absolute;
    inset: 0;
    transform-origin: top;
    /* Fills from a fifth of the way in, full before the block leaves. */
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .2) * 2.1), 1));
    background: linear-gradient(to bottom, var(--th-caramel), var(--th-espresso));
}

.th-bakery__step {
    /* Each step carries its own threshold (--t, written by the widget) and
       lights when the block's progress passes it. */
    --lit: clamp(0, calc((var(--th-p, 1) - var(--t, 0)) * 11), 1);

    position: relative;
    display: grid;
    gap: .5rem;
    transform: translate3d(0, calc((1 - var(--lit)) * 1.25rem), 0);
}

.th-bakery__step-dot {
    position: absolute;
    left: calc(var(--thb-rail) * -1);
    top: .55rem;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    background: var(--thb-accent, var(--th-crema));
    /* The halo has to match the surface it sits on so the rail reads as if it
       runs behind the dot. */
    box-shadow: 0 0 0 4px var(--th-paper);
    transform: translateX(-50%) scale(calc(.4 + .6 * var(--lit)));
    opacity: calc(.28 + .72 * var(--lit));
}

.th-bakery__step-time {
    font-family: var(--th-display);
    font-size: clamp(.95rem, 1.35vw, 1.15rem);
    font-weight: 700;
    letter-spacing: .16em;
    font-variant-numeric: tabular-nums;
    color: var(--thb-accent, var(--th-crema));
    opacity: calc(.4 + .6 * var(--lit));
}

.th-bakery__step-title {
    font-size: clamp(1.25rem, 2.1vw, 1.75rem);
    line-height: 1.05;
    opacity: calc(.32 + .68 * var(--lit));
}

.th-bakery__step-text {
    max-width: 46ch;
    color: var(--th-muted);
    opacity: calc(.28 + .72 * var(--lit));
}

/* --- 3 — Outro ----------------------------------------------------------- */

.th-bakery__outro {
    display: grid;
    grid-template-columns: minmax(0, .88fr) minmax(0, 1.12fr);
    gap: clamp(2rem, 5vw, 5.5rem);
    align-items: center;
    padding-block: clamp(4rem, 9vw, 8rem);
}

/* Without a closing image the copy takes the full measure instead of leaving
   an empty column behind. */
.th-bakery__outro--solo {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
}

.th-bakery__outro--solo .th-bakery__copy {
    justify-items: center;
    max-width: 56ch;
}

.th-bakery__outro--solo .th-bakery__quote {
    padding-left: 0;
    padding-top: clamp(1rem, 2vw, 1.5rem);
}

.th-bakery__outro--solo .th-bakery__quote::before {
    top: 0;
    bottom: auto;
    left: 50%;
    width: clamp(48px, 8vw, 96px);
    height: 2px;
    transform: translateX(-50%) scaleX(clamp(0, calc((var(--th-p, 1) - .18) * 2.4), 1));
    transform-origin: center;
}

.th-bakery__figure {
    margin: 0;
    display: grid;
    gap: clamp(.85rem, 1.6vw, 1.15rem);
    width: 100%;
    max-width: 520px;
    justify-self: end;
    /* Light parallax on the frame itself — the mask reveal owns the image. */
    transform: translate3d(0, calc((.5 - var(--th-p, .5)) * 3rem), 0);
    will-change: transform;
}

.th-bakery__figure-frame {
    display: block;
    aspect-ratio: 4 / 5;
}

.th-bakery__figure figcaption {
    display: flex;
    align-items: center;
    gap: .75em;
    font-size: var(--th-t-label);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--th-cream-soft);
}

.th-bakery__figure figcaption i {
    width: clamp(18px, 2.4vw, 32px);
    height: 1px;
    flex: none;
    background: var(--th-crema);
}

.th-bakery__copy {
    display: grid;
    gap: clamp(1.25rem, 2.2vw, 1.9rem);
    align-content: start;
    justify-items: start;
    max-width: 48ch;
}

.th-bakery__quote {
    position: relative;
    margin: 0;
    padding-left: clamp(1.25rem, 2.4vw, 2rem);
}

/* The rule beside the quote draws itself while the block scrolls past. */
.th-bakery__quote::before {
    content: "";
    position: absolute;
    left: 0;
    top: .18em;
    bottom: .18em;
    width: 2px;
    background: var(--th-crema);
    transform-origin: top;
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .18) * 2.4), 1));
}

.th-bakery__quote p {
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: clamp(1.5rem, 3vw, 2.6rem);
    line-height: 1.12;
    letter-spacing: -.01em;
    color: var(--th-cream);
    max-width: 20ch;
}

.th-bakery__outro-title {
    font-size: var(--th-t-md);
    line-height: 1.08;
    max-width: 20ch;
}

.th-bakery__actions {
    margin-top: clamp(.25rem, 1vw, .75rem);
}

.th-bakery__signature {
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: var(--th-t-sm);
    color: var(--th-cream-soft);
}

.th-bakery__signature::before {
    content: "— ";
    color: var(--th-crema);
}

/* --- Responsive ---------------------------------------------------------- */

@media (max-width: 900px) {
    .th-bakery__night-inner,
    .th-bakery__outro {
        grid-template-columns: 1fr;
    }
    .th-bakery__night-head {
        position: static;
    }
    .th-bakery__figure {
        justify-self: start;
        max-width: 360px;
    }
}

@media (max-width: 600px) {
    .th-bakery__top {
        flex-direction: column;
        align-items: flex-start;
        gap: .5rem;
    }
    .th-bakery__meta {
        text-align: left;
    }
    .th-bakery__cue i {
        height: 34px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-bakery__figure,
    .th-bakery__step {
        transform: none !important;
    }
    /* Keep the centring translate — only the scroll-driven scale is dropped. */
    .th-bakery__step-dot {
        transform: translateX(-50%) !important;
    }
    .th-bakery__step,
    .th-bakery__step-time,
    .th-bakery__step-title,
    .th-bakery__step-text,
    .th-bakery__step-dot {
        opacity: 1 !important;
    }
    .th-bakery__rail i,
    .th-bakery__quote::before {
        transform: scaleY(1) !important;
    }
    .th-bakery__outro--solo .th-bakery__quote::before {
        transform: translateX(-50%) !important;
    }
    .th-bakery__cue i::after {
        animation: none !important;
    }
    .th-bakery__ear-stem,
    .th-bakery__ear-grains path {
        stroke-dashoffset: 0 !important;
    }
}

/* ==========================================================================
   06 — THE SPACE
   Head · full-bleed reveal · sticky detail. The section is scroll linked
   (data-th-scroll="through"), so --th-p drives the stamp rule, the light shaft
   and the materials list. Every consumer falls back to 1 — the resting state.
   ========================================================================== */

.th-space {
    background:
        radial-gradient(120% 70% at 88% -6%, var(--th-paper) 0%, rgba(251, 249, 246, 0) 58%),
        var(--th-cream);
    padding-block: var(--th-block) 0;
}

.th-space__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 4rem);
    align-items: end;
    margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.th-space__lead {
    display: grid;
    justify-items: start;
    gap: clamp(.9rem, 1.8vw, 1.35rem);
    min-width: 0;
}

/* Stamp — drawn window, cut-out numeral, and a hairline that runs out across
   the column as the section is read. */
.th-space__stamp {
    display: flex;
    align-items: center;
    gap: clamp(.85rem, 1.8vw, 1.4rem);
    width: 100%;
    margin-bottom: clamp(.5rem, 1.4vw, 1rem);
}

.th-space__window {
    display: block;
    flex: none;
    width: clamp(28px, 3.2vw, 40px);
    height: auto;
    color: var(--th-espresso);
    opacity: .75;
    overflow: visible;
}

.th-space__window-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

.th-js .th-space__window.is-in .th-space__window-draw {
    animation: th-draw-in 1.15s var(--th-ease) forwards;
    animation-delay: calc(var(--i, 0) * .2s);
}

html:not(.th-js) .th-space__window-draw,
.th-is-editor .th-space__window-draw {
    stroke-dashoffset: 0;
}

/* The lit pane brightens with the section's own progress — the room filling. */
.th-space__window-lit {
    opacity: calc(.12 + var(--th-p, 1) * .68);
}

.th-space__num {
    flex: none;
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-espresso);
    opacity: .5;
}

.th-space__stamp-rule {
    flex: 1;
    min-width: 0;
    height: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-space__stamp-rule i {
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .06) * 2.4), 1));
    transform-origin: left;
}

.th-space__title {
    font-size: var(--th-t-xl);
    line-height: .94;
    max-width: 11ch;
}

.th-space__title em,
.th-space__title .th-word--accent em {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    color: var(--th-espresso);
}

/* The serif run gets the house underline — the same drawn stroke the manifesto
   statement carries, so the two editorial voices match across sections. */
.th-space__title .th-word--accent > span {
    position: relative;
}

.th-space__title .th-word--accent > span::after {
    content: "";
    position: absolute;
    left: -.02em;
    right: -.02em;
    bottom: .02em;
    height: .16em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12' preserveAspectRatio='none'%3E%3Cpath d='M2 8.4C38 3.2 66 10.6 104 5.6c30-4 62-2.2 94 2.2' fill='none' stroke='%23C1793C' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .8s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 55ms + 520ms);
}

.th-js [data-th-reveal].is-in.th-space__title .th-word--accent > span::after,
html:not(.th-js) .th-space__title .th-word--accent > span::after,
.th-is-editor .th-space__title .th-word--accent > span::after {
    transform: scaleX(1);
}

.th-space__sticky h3 em {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    color: var(--th-espresso);
}

/* The photograph opens from an inset frame to full bleed as it scrolls in. */
.th-space__reveal {
    position: relative;
    width: calc(100% - (1 - var(--th-p, 1)) * var(--th-gutter) * 2);
    margin-inline: auto;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--th-bone);
}

.th-space__reveal img {
    object-position: 50% 42%;
    transform: scale(calc(1.14 - var(--th-p, 1) * .1));
    will-change: transform;
}

/* Morning light across the old loading floor: one wide sheared highlight that
   crosses the frame as the block passes, screened so it only ever adds light. */
.th-space__light {
    position: absolute;
    top: -30%;
    bottom: -30%;
    left: calc(var(--th-p, 1) * 128% - 34%);
    width: 26%;
    z-index: 1;
    pointer-events: none;
    transform: rotate(9deg);
    background: linear-gradient(to right,
        rgba(255, 246, 232, 0) 0%,
        rgba(255, 240, 219, .3) 44%,
        rgba(255, 246, 232, 0) 100%);
    mix-blend-mode: screen;
    opacity: calc(.35 + var(--th-p, 1) * .5);
}

/* Register ticks in the corners of the frame — the print mark the photo is
   trimmed against, drawn in as the frame opens out to the bleed. */
.th-space__ticks {
    position: absolute;
    inset: clamp(.85rem, 1.8vw, 1.75rem);
    z-index: 3;
    pointer-events: none;
}

.th-space__ticks i {
    position: absolute;
    width: clamp(14px, 2vw, 24px);
    height: clamp(14px, 2vw, 24px);
    border: 0 solid var(--th-cream);
    opacity: calc(var(--th-p, 1) * .7);
}

.th-space__ticks i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.th-space__ticks i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.th-space__ticks i:nth-child(3) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }
.th-space__ticks i:nth-child(4) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }

/* The caption sits straight on the photograph, so it carries its own shadow
   rather than a plate — a bright frame would otherwise swallow it. */
.th-space__meta {
    position: absolute;
    top: clamp(1.5rem, 3vw, 2.75rem);
    right: clamp(1.5rem, 3vw, 2.75rem);
    z-index: 4;
    font-size: var(--th-t-label);
    letter-spacing: .22em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--th-cream);
    text-shadow: 0 1px 14px rgba(23, 16, 10, .95), 0 1px 3px rgba(23, 16, 10, .8);
    opacity: var(--th-p, 1);
}

.th-space__quote {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 4;
    padding: clamp(1.5rem, 4vw, 3.5rem);
    background: linear-gradient(to top, rgba(23, 16, 10, .85), transparent);
    color: var(--th-cream);
}

.th-space__quote p {
    position: relative;
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: clamp(1.125rem, 2.4vw, 2.125rem);
    line-height: 1.16;
    max-width: 22ch;
    padding-left: clamp(1rem, 2vw, 1.75rem);
}

/* The rule beside the quote draws itself while the frame opens. */
.th-space__quote p::before {
    content: "";
    position: absolute;
    left: 0;
    top: .16em;
    bottom: .16em;
    width: 2px;
    background: var(--th-crema);
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .25) * 2.6), 1));
    transform-origin: top;
}

.th-space__detail {
    display: grid;
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    gap: clamp(2rem, 6vw, 6rem);
    padding-block: clamp(3.5rem, 9vw, 8rem);
    align-items: start;
}

.th-space__sticky {
    position: sticky;
    top: clamp(6rem, 14vh, 9rem);
    display: grid;
    gap: clamp(1.25rem, 2.4vw, 1.9rem);
    align-content: start;
}

.th-space__sticky h3 {
    font-size: var(--th-t-lg);
    line-height: .98;
    max-width: 12ch;
}

/* The materials read as a spec sheet that lights row by row, each against its
   own threshold — the same mechanic the bakery's night timeline uses, so the
   two lists behave alike even though they look nothing like each other. */
.th-space__materials {
    --ths-rail: clamp(2.25rem, 4.5vw, 4rem);

    position: relative;
    display: grid;
    gap: 0;
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--ths-rail);
    border-top: 1px solid var(--th-rule);
}

.th-space__rail {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-space__rail i {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, var(--th-crema), var(--th-caramel));
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .26) * 2.3), 1));
    transform-origin: top;
}

.th-space__material {
    /* Written by the widget; the row lights once the block's progress passes it. */
    --lit: clamp(0, calc((var(--th-p, 1) - var(--t, 0)) * 11), 1);

    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: baseline;
    gap: clamp(1rem, 3vw, 2.5rem);
    padding-block: clamp(1.1rem, 2.2vw, 1.8rem);
    border-bottom: 1px solid var(--th-rule);
    translate: calc((1 - var(--lit)) * .9rem) 0;
    transition: translate .5s var(--th-ease);
}

/* A crema hairline that writes itself along the row as it lights, then completes
   on hover — the row's own progress bar, doubling as the hover state. */
.th-space__material::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    background: var(--th-crema);
    transform: scaleX(var(--lit));
    transform-origin: left;
    transition: transform .7s var(--th-ease);
}

.th-space__material:hover::after {
    transform: scaleX(1);
}

/* The dot on the rail, pinned to the row's own baseline. */
.th-space__material::before {
    content: "";
    position: absolute;
    left: calc(var(--ths-rail) * -1);
    top: calc(clamp(1.1rem, 2.2vw, 1.8rem) + .45em);
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--th-crema);
    box-shadow: 0 0 0 4px var(--th-cream);
    transform: translateX(-50%) scale(calc(.35 + .65 * var(--lit)));
    opacity: calc(.24 + .76 * var(--lit));
}

.th-space__material-index {
    position: absolute;
    right: 0;
    top: clamp(1.1rem, 2.2vw, 1.8rem);
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .18em;
    font-variant-numeric: tabular-nums;
    color: var(--th-espresso);
    opacity: calc(.18 + .42 * var(--lit));
}

.th-space__material dt {
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.5vw, 2.125rem);
    font-weight: 700;
    letter-spacing: -.03em;
    text-transform: uppercase;
    line-height: 1;
    opacity: calc(.32 + .68 * var(--lit));
}

.th-space__material dd {
    margin: 0;
    padding-right: clamp(2rem, 4vw, 3.5rem);
    color: var(--th-ink-soft);
    font-size: var(--th-t-body);
    opacity: calc(.24 + .76 * var(--lit));
}

.th-space__pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(1rem, 2vw, 1.75rem);
    margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

.th-space__pair .th-figure:first-child {
    aspect-ratio: 4 / 5;
}

.th-space__pair .th-figure:last-child {
    aspect-ratio: 4 / 5;
    margin-top: clamp(2rem, 6vw, 5rem);
}

/* The two detail frames drift against each other as the column passes, which
   keeps a static pair from reading as a stock grid. `translate` again, because
   the image reveal owns `transform`. */
.th-section .th-space__pair .th-figure:first-child img {
    translate: 0 calc((var(--th-p, .5) - .5) * -1.6rem);
}

.th-section .th-space__pair .th-figure:last-child img {
    translate: 0 calc((var(--th-p, .5) - .5) * 1.6rem);
}

.th-space__close {
    position: relative;
    padding-block: clamp(1.25rem, 2.5vw, 2rem) var(--th-block);
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: clamp(1.25rem, 2.8vw, 2.5rem);
    line-height: 1.14;
    max-width: 26ch;
    color: var(--th-espresso);
}

/* A short rule above the closing line, drawn as the block finishes. */
.th-space__close-rule {
    position: absolute;
    left: 0;
    top: 0;
    width: clamp(56px, 9vw, 132px);
    height: 2px;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .48) * 3), 1));
    transform-origin: left;
}

@media (max-width: 900px) {
    .th-space__head,
    .th-space__detail {
        grid-template-columns: 1fr;
        align-items: start;
    }
    .th-space__sticky {
        position: static;
    }
    .th-space__reveal {
        aspect-ratio: 4 / 3;
        width: 100%;
    }
    .th-space__materials {
        --ths-rail: 1.5rem;
    }
    .th-space__material {
        grid-template-columns: minmax(0, 1fr);
        gap: .4rem;
    }
    .th-space__material dd {
        padding-right: 0;
    }
    .th-space__material-index {
        display: none;
    }
    .th-space__ticks {
        inset: .75rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-space__material {
        translate: none !important;
    }
    .th-space__material::after,
    .th-space__close-rule,
    .th-space__stamp-rule i {
        transform: scaleX(1) !important;
    }
    .th-space__rail i,
    .th-space__quote p::before {
        transform: scaleY(1) !important;
    }
    .th-space__material::before {
        transform: translateX(-50%) !important;
    }
    .th-space__material,
    .th-space__material dt,
    .th-space__material dd,
    .th-space__material::before,
    .th-space__ticks i,
    .th-space__meta {
        opacity: 1 !important;
    }
    .th-space__light {
        display: none;
    }
    .th-section .th-space__pair .th-figure img {
        translate: none !important;
    }
    .th-space__window-draw {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }
}

/* ==========================================================================
   07 — THIRD PLACE (the ladder)
   An ascent: a rail that fills with --th-p, rungs that light one by one against
   their own thresholds, and a dominant rung that sets letter by letter.
   ========================================================================== */

.th-place {
    background:
        radial-gradient(100% 60% at 50% 108%, rgba(193, 121, 60, .1) 0%, rgba(193, 121, 60, 0) 60%),
        var(--th-cream);
    padding-block: var(--th-block);
}

.th-place__head {
    position: relative;
    display: grid;
    gap: clamp(1rem, 2vw, 1.5rem);
    max-width: 46ch;
    margin-bottom: clamp(2.5rem, 6vw, 4.5rem);
}

/* Cut-out numeral, set as print furniture above the intro. */
.th-place__num {
    font-family: var(--th-display);
    font-size: clamp(1.5rem, 2.8vw, 2.5rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-espresso);
    opacity: .45;
}

.th-place__ladder {
    --thp-rail: clamp(1.75rem, 4vw, 3.5rem);

    position: relative;
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--thp-rail);
    border-top: 1px solid var(--th-rule);
}

/* The rail is the climb made visible: a hairline that fills top to bottom with
   the section's own progress, warming from crema into caramel as it rises. */
.th-place__rail {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-place__rail i {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, var(--th-crema), var(--th-caramel));
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .2) * 2.1), 1));
    transform-origin: top;
}

.th-rung {
    /* Written by the widget; the rung lights when the progress passes it. */
    --lit: clamp(0, calc((var(--th-p, 1) - var(--t, 0)) * 11), 1);

    position: relative;
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    align-items: center;
    gap: clamp(.85rem, 2.4vw, 2.5rem);
    padding-block: clamp(1.1rem, 2.4vw, 2rem);
    border-bottom: 1px solid var(--th-rule);
    color: var(--th-ink-soft);
    opacity: calc(.3 + .7 * var(--lit));
    translate: calc((1 - var(--lit)) * .75rem) 0;
    transition: color .7s var(--th-ease), translate .6s var(--th-ease);
}

/* A crema hairline that writes along the rung as it lights, and completes on
   hover — one mark doing both the scroll state and the pointer state. */
.th-rung::after {
    content: "";
    position: absolute;
    left: calc(var(--thp-rail) * -1);
    right: 0;
    bottom: -1px;
    height: 1px;
    background: var(--th-crema);
    transform: scaleX(var(--lit));
    transform-origin: left;
    transition: transform .8s var(--th-ease);
}

/* The dot where the rung meets the rail. */
.th-rung::before {
    content: "";
    position: absolute;
    left: calc(var(--thp-rail) * -1);
    top: 50%;
    width: 9px;
    height: 9px;
    margin-top: -4.5px;
    border-radius: 50%;
    background: var(--th-crema);
    box-shadow: 0 0 0 4px var(--th-cream);
    transform: translateX(-50%) scale(calc(.34 + .66 * var(--lit)));
}

.th-rung__index {
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .2em;
    font-variant-numeric: tabular-nums;
    opacity: .5;
}

/* The threshold glyph — house, desk, cup — inking itself as the rung lights.
   `stroke-dashoffset` is driven straight off --lit rather than a keyframe, so it
   scrubs with the scroll instead of firing once. */
.th-rung__glyph {
    display: block;
    width: clamp(22px, 2.6vw, 34px);
    color: var(--th-espresso);
}

.th-rung__glyph svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}

.th-rung__glyph path {
    stroke-dasharray: 1;
    stroke-dashoffset: clamp(0, calc(1 - (var(--lit) * 1.6 - var(--i, 0) * .3)), 1);
}

.th-rung__word {
    font-family: var(--th-display);
    font-size: clamp(2rem, 7vw, 6rem);
    font-weight: 700;
    line-height: .9;
    letter-spacing: -.04em;
    text-transform: uppercase;
}

.th-rung__meta {
    font-size: var(--th-t-label);
    letter-spacing: .2em;
    text-transform: uppercase;
    text-align: right;
    line-height: 1.7;
}

.th-rung--third {
    color: var(--th-espresso);
    padding-block: clamp(1.75rem, 4vw, 3.25rem);
}

.th-rung--third .th-rung__word {
    font-size: clamp(3rem, 15vw, 12rem);
    font-weight: 900;
    letter-spacing: -.055em;
}

/* The dominant rung's letters ride the scroll rather than an observer, so the
   word assembles exactly as the rail reaches it. */
.th-rung--third .th-letter > span {
    transform: translateY(calc((1 - clamp(0, calc(var(--lit) * 1.5 - var(--i, 0) * .18), 1)) * 110%));
    transition: transform .7s var(--th-ease);
}

/* The accent bead is a sibling of the masked letters, not one of them, so it
   would otherwise sit alone on an empty row while the word is still rising. */
.th-rung--third .th-rung__word i {
    opacity: clamp(0, calc(var(--lit) * 2 - 1.1), 1);
    scale: calc(.4 + .6 * var(--lit));
    transition: opacity .5s var(--th-ease), scale .5s var(--th-ease);
}

/* A soft crema warmth behind the dominant rung — the room's light, not a glow
   effect: it only ever appears once the rung is fully lit. */
.th-rung__halo {
    position: absolute;
    left: -6%;
    right: -6%;
    top: -10%;
    bottom: -10%;
    z-index: -1;
    pointer-events: none;
    border-radius: 50%;
    background: radial-gradient(58% 72% at 34% 50%, rgba(193, 121, 60, .3) 0%, rgba(193, 121, 60, 0) 70%);
    opacity: var(--lit);
}

.th-rung--third .th-rung__word i {
    display: inline-block;
    width: .17em;
    height: .17em;
    margin-left: .05em;
    border-radius: 50%;
    background: var(--th-crema);
    font-style: normal;
    text-indent: -100vw;
    overflow: hidden;
    vertical-align: baseline;
}

.th-rung--third .th-rung__index,
.th-rung--third .th-rung__meta {
    color: var(--th-espresso);
    opacity: .8;
}

/* Hover reveals a photograph — desktop pointer only. It arrives with a slight
   counter-rotation and a register frame, so it reads as a print left on the
   page rather than a tooltip. */
.th-rung__peek {
    position: absolute;
    right: clamp(6rem, 18vw, 20rem);
    top: 50%;
    width: clamp(140px, 14vw, 210px);
    aspect-ratio: 4 / 5;
    transform: translateY(-50%) scale(.86) rotate(-4deg);
    opacity: 0;
    pointer-events: none;
    z-index: 3;
    transition: opacity .6s var(--th-ease), transform .8s var(--th-ease);
    box-shadow: 0 30px 60px -25px rgba(23, 16, 10, .55);
    outline: 6px solid var(--th-paper);
    outline-offset: 0;
}

@media (hover: hover) and (min-width: 901px) {
    .th-rung:hover .th-rung__peek {
        opacity: 1;
        transform: translateY(-50%) scale(1) rotate(-2deg);
    }
    .th-rung:hover {
        color: var(--th-ink);
        opacity: 1;
    }
    .th-rung:hover::after {
        transform: scaleX(1);
    }
    /* Hovering a rung inks its glyph the rest of the way, whatever the scroll
       has already drawn. */
    .th-rung:hover .th-rung__glyph path {
        stroke-dashoffset: 0;
        transition: stroke-dashoffset .5s var(--th-ease);
        transition-delay: calc(var(--i, 0) * .08s);
    }
}

.th-place__close {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
    align-items: end;
    margin-top: clamp(3rem, 6vw, 5rem);
}

.th-place__close p:first-child {
    position: relative;
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: clamp(1.375rem, 3vw, 2.5rem);
    line-height: 1.14;
    color: var(--th-espresso);
    max-width: 20ch;
    padding-top: clamp(1.15rem, 2.2vw, 1.75rem);
}

.th-place__close-rule {
    position: absolute;
    left: 0;
    top: 0;
    width: clamp(56px, 9vw, 132px);
    height: 2px;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .5) * 3), 1));
    transform-origin: left;
}

@media (max-width: 900px) {
    .th-place__ladder {
        --thp-rail: 1.35rem;
    }
    .th-rung {
        grid-template-columns: auto auto minmax(0, 1fr);
        column-gap: .85rem;
    }
    .th-rung__meta {
        grid-column: 1 / -1;
        text-align: left;
        margin-top: .35rem;
    }
    .th-rung__peek {
        display: none;
    }
    .th-place__close {
        grid-template-columns: 1fr;
        align-items: start;
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-rung {
        translate: none !important;
        opacity: 1 !important;
    }
    .th-rung::after,
    .th-place__close-rule {
        transform: scaleX(1) !important;
    }
    .th-place__rail i {
        transform: scaleY(1) !important;
    }
    .th-rung::before {
        transform: translateX(-50%) !important;
    }
    .th-rung__glyph path {
        stroke-dashoffset: 0 !important;
    }
    .th-rung--third .th-letter > span {
        transform: none !important;
    }
    .th-rung--third .th-rung__word i {
        opacity: 1 !important;
        scale: 1 !important;
    }
    .th-rung__halo {
        opacity: 1 !important;
    }
}

/* The editor preview has no meaningful scroll of its own, so the dominant word
   is shown assembled rather than mid-rise. */
.th-is-editor .th-rung--third .th-letter > span {
    transform: none;
}

/* ==========================================================================
   08 — CRAFTSMANSHIP
   ========================================================================== */

.th-craft {
    background: var(--th-ink);
    color: var(--th-cream);
    padding-block: var(--th-block) 0;
}

.th-craft__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 4rem);
    align-items: end;
    margin-bottom: clamp(2.5rem, 6vw, 5rem);
}

.th-craft__lead {
    display: grid;
    justify-items: start;
    gap: clamp(.9rem, 1.8vw, 1.35rem);
    min-width: 0;
}

/* Stamp — the dial, the cut-out numeral, and a hairline that runs out as the
   section is read. Same furniture as the other sections, different mark. */
.th-craft__stamp {
    display: flex;
    align-items: center;
    gap: clamp(.85rem, 1.8vw, 1.4rem);
    width: 100%;
    margin-bottom: clamp(.5rem, 1.4vw, 1rem);
}

.th-craft__dial {
    display: block;
    flex: none;
    width: clamp(34px, 3.8vw, 48px);
    height: auto;
    color: var(--th-cream-soft);
    overflow: visible;
}

.th-craft__dial-ring,
.th-craft__dial-ticks path {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

.th-js .th-craft__dial.is-in .th-craft__dial-ring {
    animation: th-draw-in 1.4s var(--th-ease) forwards;
}

.th-js .th-craft__dial.is-in .th-craft__dial-ticks path {
    animation: th-draw-in .5s var(--th-ease) forwards;
    animation-delay: calc(.35s + var(--i, 0) * .05s);
}

html:not(.th-js) .th-craft__dial-ring,
html:not(.th-js) .th-craft__dial-ticks path,
.th-is-editor .th-craft__dial-ring,
.th-is-editor .th-craft__dial-ticks path {
    stroke-dashoffset: 0;
}

/* The hand is the only thing on the page that reports the scroll literally:
   one full turn across the section's passage. */
.th-craft__dial-hand {
    transform: rotate(calc(var(--th-p, 0) * 360deg));
    transform-origin: 24px 24px;
}

.th-craft__num {
    flex: none;
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-cream);
    opacity: .45;
}

.th-craft__stamp-rule {
    flex: 1;
    min-width: 0;
    height: 1px;
    background: var(--th-rule-light);
    overflow: hidden;
}

.th-craft__stamp-rule i {
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .04) * 2.6), 1));
    transform-origin: left;
}

.th-craft__title {
    font-size: var(--th-t-xl);
    line-height: .94;
    max-width: 12ch;
}

.th-craft__title em,
.th-craft__title .th-word--accent em {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    color: var(--th-crema);
}

/* The serif run carries the drawn rule, matching the manifesto statement. */
.th-craft__title .th-word--accent > span {
    position: relative;
}

.th-craft__title .th-word--accent > span::after {
    content: "";
    position: absolute;
    left: -.02em;
    right: -.02em;
    bottom: .02em;
    height: .16em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12' preserveAspectRatio='none'%3E%3Cpath d='M2 8.4C38 3.2 66 10.6 104 5.6c30-4 62-2.2 94 2.2' fill='none' stroke='%23C1793C' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .8s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 55ms + 520ms);
}

.th-js [data-th-reveal].is-in.th-craft__title .th-word--accent > span::after,
html:not(.th-js) .th-craft__title .th-word--accent > span::after,
.th-is-editor .th-craft__title .th-word--accent > span::after {
    transform: scaleX(1);
}

.th-craft__inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(2rem, 6vw, 6rem);
    align-items: start;
}

.th-craft__visual {
    position: sticky;
    top: 0;
    height: 100svh;
    display: grid;
    align-content: center;
}

.th-craft__frames {
    position: relative;
    width: 100%;
    aspect-ratio: 4 / 5;
    max-height: 74svh;
    overflow: hidden;
    background: var(--th-roast);
}

/* Frames cross-dissolve while the outgoing plate keeps drifting, so the swap
   reads as one continuous move rather than two separate fades. */
.th-craft__frame {
    position: absolute;
    inset: 0;
    opacity: 0;
    transform: scale(1.08);
    filter: saturate(.7);
    transition: opacity 1s var(--th-ease), transform 1.6s var(--th-ease), filter 1.2s var(--th-ease);
}

.th-craft__frame.is-active {
    opacity: 1;
    transform: scale(1);
    filter: saturate(.95);
}

/* A slow counter-scroll on top of the swap: the whole stack drifts against the
   sticky column, which stops the pinned frame from reading as a static block. */
.th-section .th-craft__frame img {
    translate: 0 calc((var(--th-p, .5) - .5) * -2.5%);
}

.th-craft__ticks {
    position: absolute;
    inset: clamp(.75rem, 1.6vw, 1.35rem);
    z-index: 3;
    pointer-events: none;
}

.th-craft__ticks i {
    position: absolute;
    width: clamp(12px, 1.8vw, 20px);
    height: clamp(12px, 1.8vw, 20px);
    border: 0 solid var(--th-cream);
    opacity: .48;
}

.th-craft__ticks i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.th-craft__ticks i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.th-craft__ticks i:nth-child(3) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }
.th-craft__ticks i:nth-child(4) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }

/* Meter — the running counter and the segmented progress, together under the
   frame, so the sequence always says where it is. */
.th-craft__meter {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2.2vw, 1.75rem);
    margin-top: 1.25rem;
}

.th-craft__counter {
    display: inline-flex;
    align-items: baseline;
    gap: .4em;
    flex: none;
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 700;
    letter-spacing: .18em;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    color: var(--th-crema);
}

/* The digits are stacked in one masked slot; the active one rides up into it,
   so the count rolls rather than blinks. */
.th-craft__counter-reel {
    position: relative;
    display: block;
    width: 2.1ch;
    height: 1em;
    overflow: hidden;
}

.th-craft__counter-reel i {
    position: absolute;
    inset: 0;
    font-style: normal;
    opacity: 0;
    transform: translateY(-70%);
    transition: transform .6s var(--th-ease), opacity .4s var(--th-ease);
}

.th-craft__counter-reel i.is-active {
    opacity: 1;
    transform: none;
}

.th-craft__counter b {
    font-weight: 600;
    color: var(--th-cream-soft);
    opacity: .7;
}

.th-craft__progress {
    display: flex;
    flex: 1;
    gap: .5rem;
    min-width: 0;
}

.th-craft__progress span {
    flex: 1;
    height: 2px;
    background: var(--th-cream-faint);
    overflow: hidden;
}

.th-craft__progress span::after {
    content: "";
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .8s var(--th-ease);
}

.th-craft__progress span.is-active::after {
    transform: scaleX(1);
}

.th-craft__steps {
    display: grid;
}

.th-step {
    position: relative;
    min-height: 68svh;
    display: grid;
    align-content: center;
    gap: clamp(.75rem, 1.6vw, 1.25rem);
    padding-block: clamp(2rem, 5vw, 4rem);
    padding-left: clamp(1.15rem, 2.4vw, 2.25rem);
    border-bottom: 1px solid var(--th-rule-light);
    opacity: .32;
    transition: opacity .9s var(--th-ease);
}

.th-step:last-child {
    border-bottom: 0;
}

.th-step.is-active {
    opacity: 1;
}

/* A rule beside the active step that draws top to bottom as it takes over —
   the sequence's read-head. */
.th-step__rule {
    position: absolute;
    left: 0;
    top: clamp(2rem, 5vw, 4rem);
    bottom: clamp(2rem, 5vw, 4rem);
    width: 2px;
    background: var(--th-crema);
    transform: scaleY(0);
    transform-origin: top;
    transition: transform 1s var(--th-ease);
}

.th-step.is-active .th-step__rule {
    transform: scaleY(1);
}

.th-step__index {
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 700;
    letter-spacing: .3em;
    color: var(--th-crema);
    font-variant-numeric: tabular-nums;
}

.th-step__word {
    font-size: clamp(2rem, 5.2vw, 4.25rem);
    line-height: .92;
    text-transform: uppercase;
    letter-spacing: -.04em;
}

/* The word sets letter by letter the moment the sequence reaches the step, and
   drops back when it leaves — so scrolling up replays it. */
.th-step .th-letter > span {
    transform: translateY(110%);
    transition: transform .85s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 32ms);
}

.th-step.is-active .th-letter > span {
    transform: none;
}

.th-step__text {
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: var(--th-t-md);
    line-height: 1.22;
    color: var(--th-cream-soft);
    max-width: 30ch;
}

.th-craft__foot {
    position: relative;
    padding-block: clamp(3rem, 7vw, 6rem);
    border-top: 1px solid var(--th-rule-light);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 4rem);
    align-items: start;
}

.th-craft__foot p {
    color: var(--th-cream-soft);
    max-width: 44ch;
}

.th-craft__foot .th-craft__foot-title {
    font-size: var(--th-t-md);
    color: var(--th-cream);
}

/* An accent hairline drawn over the foot's border as the section closes. */
.th-section .th-craft__foot-rule {
    grid-column: 1 / -1;
    position: absolute;
    left: 0;
    right: 0;
    top: -1px;
    height: 1px;
    max-width: none;
    overflow: hidden;
}

.th-craft__foot-rule i {
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .68) * 3.4), 1));
    transform-origin: left;
}

@media (max-width: 900px) {
    .th-craft__head,
    .th-craft__inner,
    .th-craft__foot {
        grid-template-columns: 1fr;
        align-items: start;
    }
    .th-craft__actions {
        grid-column: 1;
    }
    .th-craft__visual {
        position: static;
        height: auto;
    }
    .th-craft__frames {
        aspect-ratio: 3 / 4;
        max-height: none;
    }
    .th-step {
        min-height: 0;
        opacity: 1;
    }
    /* Without the pinned sequence there is no active step to wait for, so the
       words are simply set. */
    .th-step .th-letter > span {
        transform: none;
    }
    .th-step__rule {
        transform: scaleY(1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-step .th-letter > span {
        transform: none !important;
    }
    .th-step__rule,
    .th-craft__progress span::after {
        transform: scaleY(1) scaleX(1) !important;
    }
    .th-craft__stamp-rule i,
    .th-craft__foot-rule i {
        transform: scaleX(1) !important;
    }
    .th-craft__dial-hand {
        transform: none !important;
    }
    .th-craft__dial-ring,
    .th-craft__dial-ticks path {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }
    .th-section .th-craft__frame img {
        translate: none !important;
    }
    .th-craft__counter-reel i {
        transform: none !important;
    }
}

/* ==========================================================================
   09 — PEOPLE
   ========================================================================== */

.th-people {
    background:
        radial-gradient(110% 65% at 10% -8%, var(--th-paper) 0%, rgba(251, 249, 246, 0) 55%),
        var(--th-bone);
    padding-block: var(--th-block);
}

.th-people__inner {
    display: grid;
    grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
    gap: clamp(2rem, 6vw, 6rem);
    align-items: stretch;
}

/* The wrapper stretches to the row height so the portrait can stay pinned
   alongside the full founder list. */
.th-people__sticky {
    position: sticky;
    top: clamp(6rem, 14vh, 9rem);
}

/* Offset register frame — the print mark the portrait is trimmed against. It
   hangs off the plate, not the figure, which clips its own overflow. */
.th-people__plate {
    position: relative;
}

.th-people__plate::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    translate: clamp(-18px, -1.2vw, -10px) clamp(10px, 1.2vw, 18px);
    border: 1px solid var(--th-espresso);
    opacity: .3;
    pointer-events: none;
}

.th-people__figure {
    position: relative;
    z-index: 1;
    aspect-ratio: 4 / 5;
    background: var(--th-roast);
}

/* Parallax on `translate`, which the image reveal leaves alone. The photo is
   oversized so the drift never uncovers the frame. */
.th-section .th-people__figure img {
    object-position: 50% 28%;
    top: -6%;
    height: 112%;
    translate: 0 calc((var(--th-p, .5) - .5) * -2.6rem);
}

.th-people__figcaption {
    display: flex;
    align-items: center;
    gap: .8em;
    margin-top: .9rem;
    font-size: var(--th-t-label);
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--th-ink-soft);
    line-height: 1.7;
}

.th-people__figcaption i {
    flex: none;
    width: clamp(18px, 2.4vw, 34px);
    height: 1px;
    background: var(--th-crema);
}

.th-people__copy {
    display: grid;
    gap: clamp(1.5rem, 3vw, 2.5rem);
    align-content: start;
    justify-items: start;
}

/* Stamp — the two drawn cups, the cut-out numeral, and a hairline that runs out
   as the section is read. */
.th-people__stamp {
    display: flex;
    align-items: center;
    gap: clamp(.85rem, 1.8vw, 1.4rem);
    width: 100%;
}

.th-people__pairmark {
    display: block;
    flex: none;
    width: clamp(46px, 5vw, 66px);
    height: auto;
    color: var(--th-espresso);
    opacity: .8;
    overflow: visible;
}

.th-people__pairmark-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

.th-js .th-people__pairmark.is-in .th-people__pairmark-draw {
    animation: th-draw-in .95s var(--th-ease) forwards;
    animation-delay: calc(var(--i, 0) * .14s);
}

html:not(.th-js) .th-people__pairmark-draw,
.th-is-editor .th-people__pairmark-draw {
    stroke-dashoffset: 0;
}

.th-people__pairmark-bead {
    transform-origin: 44.5px 30px;
    animation: th-pulse 3.2s var(--th-ease-soft) infinite;
}

.th-people__num {
    flex: none;
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-espresso);
    opacity: .5;
}

.th-people__stamp-rule {
    flex: 1;
    min-width: 0;
    height: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-people__stamp-rule i {
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .06) * 2.4), 1));
    transform-origin: left;
}

.th-people__title {
    font-size: var(--th-t-lg);
    line-height: .96;
    max-width: 15ch;
}

.th-people__title em,
.th-people__title .th-word--accent em {
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    color: var(--th-espresso);
}

.th-people__title .th-word--accent > span {
    position: relative;
}

.th-people__title .th-word--accent > span::after {
    content: "";
    position: absolute;
    left: -.02em;
    right: -.02em;
    bottom: .02em;
    height: .16em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12' preserveAspectRatio='none'%3E%3Cpath d='M2 8.4C38 3.2 66 10.6 104 5.6c30-4 62-2.2 94 2.2' fill='none' stroke='%23C1793C' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .8s var(--th-ease);
    transition-delay: calc(var(--i, 0) * 55ms + 520ms);
}

.th-js [data-th-reveal].is-in.th-people__title .th-word--accent > span::after,
html:not(.th-js) .th-people__title .th-word--accent > span::after,
.th-is-editor .th-people__title .th-word--accent > span::after {
    transform: scaleX(1);
}

.th-people__list {
    display: grid;
    width: 100%;
    border-top: 1px solid var(--th-rule);
}

.th-founder {
    position: relative;
    display: grid;
    gap: clamp(.6rem, 1.2vw, 1rem);
    padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
    padding-left: clamp(2.5rem, 5vw, 4.5rem);
    border-bottom: 1px solid var(--th-rule);
}

/* The entry's own rule: it writes itself down the left as the block is read,
   and completes on hover or focus — so pointer and scroll drive one mark. */
.th-founder__rule {
    position: absolute;
    left: 0;
    top: clamp(1.75rem, 3.5vw, 2.75rem);
    bottom: clamp(1.75rem, 3.5vw, 2.75rem);
    width: 2px;
    background: var(--th-espresso);
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .22) * 2.2), 1));
    transform-origin: top;
    transition: transform .8s var(--th-ease);
}

.th-founder__index {
    position: absolute;
    left: 0;
    top: calc(clamp(1.75rem, 3.5vw, 2.75rem) - 1.5em);
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 700;
    letter-spacing: .22em;
    font-variant-numeric: tabular-nums;
    color: var(--th-crema);
}

@media (hover: hover) and (min-width: 901px) {
    .th-founder:hover .th-founder__rule,
    .th-founder:focus-within .th-founder__rule {
        transform: scaleY(1);
        background: var(--th-crema);
    }
}

.th-founder__name {
    font-family: var(--th-display);
    font-size: clamp(1.375rem, 2.8vw, 2.25rem);
    font-weight: 700;
    letter-spacing: -.03em;
    line-height: 1;
    text-transform: uppercase;
}

.th-founder__bio {
    color: var(--th-ink-soft);
    max-width: 48ch;
}

.th-founder__ritual {
    display: flex;
    align-items: flex-start;
    gap: .7em;
    font-family: var(--th-editorial);
    font-style: italic;
    font-size: var(--th-t-md);
    line-height: 1.2;
    color: var(--th-espresso);
    max-width: 32ch;
}

/* Three wisps rather than a bullet — the ritual is a cup, so it gets steam. */
.th-founder__steam {
    flex: none;
    width: 1.1em;
    height: auto;
    margin-top: .1em;
    color: var(--th-crema);
    overflow: visible;
}

.th-founder__steam path {
    opacity: 0;
    animation: th-crest-steam 4.2s var(--th-ease-soft) infinite;
    animation-delay: calc(var(--i, 0) * .5s);
}

.th-people__close {
    position: relative;
    padding-top: clamp(1.15rem, 2.2vw, 1.75rem);
    font-size: var(--th-t-md);
    line-height: 1.28;
    letter-spacing: -.015em;
    max-width: 40ch;
}

.th-people__close-rule {
    position: absolute;
    left: 0;
    top: 0;
    width: clamp(56px, 9vw, 132px);
    height: 2px;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .5) * 3), 1));
    transform-origin: left;
}

@media (max-width: 900px) {
    .th-people__inner {
        grid-template-columns: 1fr;
    }
    .th-people__sticky {
        position: static;
    }
    .th-people__plate {
        max-width: 420px;
    }
    .th-founder {
        padding-left: 1.5rem;
    }
    .th-founder__index {
        top: calc(clamp(1.75rem, 3.5vw, 2.75rem) - 1.35em);
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-section .th-people__figure img {
        translate: none !important;
    }
    .th-founder__rule {
        transform: scaleY(1) !important;
    }
    .th-people__stamp-rule i,
    .th-people__close-rule {
        transform: scaleX(1) !important;
    }
    .th-people__pairmark-draw {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }
    .th-people__pairmark-bead {
        animation: none !important;
    }
    .th-founder__steam path {
        animation: none !important;
        opacity: .7 !important;
    }
}

/* ==========================================================================
   10 — AMSTERDAM
   ========================================================================== */

.th-amsterdam {
    background: var(--th-espresso);
    color: var(--th-cream);
    padding-block: var(--th-block) 0;
    --th-rule: var(--th-rule-light);
}

.th-amsterdam__inner {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    gap: clamp(2rem, 6vw, 6rem);
    align-items: center;
}

.th-amsterdam__copy {
    display: grid;
    gap: clamp(1.25rem, 2.6vw, 2.25rem);
    align-content: start;
    justify-items: start;
}

/* Stamp — the location mark, the cut-out numeral, and a hairline that runs out
   as the section is read. */
.th-amsterdam__stamp {
    display: flex;
    align-items: center;
    gap: clamp(.85rem, 1.8vw, 1.4rem);
    width: 100%;
}

.th-amsterdam__pin {
    display: block;
    flex: none;
    width: clamp(38px, 4.2vw, 54px);
    height: auto;
    color: var(--th-cream-soft);
    overflow: visible;
}

.th-amsterdam__pin-ring {
    transform-origin: 24px 24px;
    animation: th-spin 60s linear infinite;
}

.th-amsterdam__pin-draw > * {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

.th-js .th-amsterdam__pin.is-in .th-amsterdam__pin-draw > * {
    animation: th-draw-in 1s var(--th-ease) forwards;
    animation-delay: calc(var(--i, 0) * .18s);
}

html:not(.th-js) .th-amsterdam__pin-draw > *,
.th-is-editor .th-amsterdam__pin-draw > * {
    stroke-dashoffset: 0;
}

.th-amsterdam__pin-bead {
    transform-origin: 24px 24px;
    animation: th-pulse 2.8s var(--th-ease-soft) infinite;
}

.th-amsterdam__num {
    flex: none;
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-cream);
    opacity: .45;
}

.th-amsterdam__stamp-rule {
    flex: 1;
    min-width: 0;
    height: 1px;
    background: var(--th-rule-light);
    overflow: hidden;
}

.th-amsterdam__stamp-rule i {
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .06) * 2.4), 1));
    transform-origin: left;
}

.th-amsterdam__title {
    font-size: clamp(2.25rem, 6vw, 5.5rem);
    line-height: .86;
    text-transform: uppercase;
    letter-spacing: -.045em;
}

/* Direct children only: the letter split nests spans of its own inside these,
   and a descendant selector would turn every letter into a block. */
.th-amsterdam__title > span {
    display: block;
}

.th-amsterdam__title > span:last-child {
    color: var(--th-crema);
    padding-left: .06em;
}

/* The address sits on a plate with drawn corner ticks rather than under a rule —
   an inscription, the way a house number is set into a façade. */
.th-amsterdam__address {
    position: relative;
    font-style: normal;
    display: grid;
    gap: .35rem;
    font-size: var(--th-t-md);
    line-height: 1.3;
    letter-spacing: -.01em;
    padding: clamp(1.15rem, 2.2vw, 1.75rem) clamp(1.5rem, 3vw, 2.5rem);
    background: rgba(23, 16, 10, .22);
}

.th-amsterdam__plate-ticks i {
    position: absolute;
    width: clamp(12px, 1.6vw, 18px);
    height: clamp(12px, 1.6vw, 18px);
    border: 0 solid var(--th-crema);
    opacity: .8;
}

.th-amsterdam__plate-ticks i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.th-amsterdam__plate-ticks i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.th-amsterdam__plate-ticks i:nth-child(3) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }
.th-amsterdam__plate-ticks i:nth-child(4) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }

.th-amsterdam__address strong {
    font-family: var(--th-display);
    font-weight: 700;
}

.th-amsterdam__city {
    color: var(--th-cream-soft);
    font-size: var(--th-t-body);
}

/* Offset register frame on the photograph, matching the manifesto and people
   plates — the print mark the image is trimmed against. */
.th-amsterdam__plate {
    position: relative;
    max-width: 560px;
    width: 100%;
    justify-self: end;
}

.th-amsterdam__plate::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    translate: clamp(10px, 1.1vw, 18px) clamp(10px, 1.1vw, 18px);
    border: 1px solid var(--th-crema);
    opacity: .4;
    pointer-events: none;
}

.th-amsterdam__figure {
    position: relative;
    z-index: 1;
    aspect-ratio: 4 / 5;
    width: 100%;
}

/* Parallax on `translate`, which the image reveal leaves alone. */
.th-section .th-amsterdam__figure img {
    top: -6%;
    height: 112%;
    translate: 0 calc((var(--th-p, .5) - .5) * -2.4rem);
}

.th-marquee__track {
    display: flex;
    width: max-content;
    animation: th-marquee var(--th-speed, 46s) linear infinite;
}

.th-marquee__group {
    display: flex;
    align-items: center;
    gap: clamp(1.5rem, 3vw, 3rem);
    padding-right: clamp(1.5rem, 3vw, 3rem);
    white-space: nowrap;
}

.th-marquee__group span {
    font-family: var(--th-display);
    font-size: clamp(.875rem, 1.6vw, 1.375rem);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
}

.th-marquee__group i {
    font-style: normal;
    color: var(--th-crema);
    font-size: .8em;
}

@keyframes th-marquee {
    to { transform: translateX(-50%); }
}

.th-marquee:hover .th-marquee__track {
    animation-play-state: paused;
}

@media (max-width: 900px) {
    .th-amsterdam__inner {
        grid-template-columns: 1fr;
    }
    .th-amsterdam__plate {
        justify-self: start;
        max-width: 100%;
    }
    .th-amsterdam__address {
        width: 100%;
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-amsterdam__stamp-rule i {
        transform: scaleX(1) !important;
    }
    .th-section .th-amsterdam__figure img {
        translate: none !important;
    }
    .th-amsterdam__pin-draw > * {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }
    .th-amsterdam__pin-ring,
    .th-amsterdam__pin-bead {
        animation: none !important;
    }
}

/* ==========================================================================
   11 — DISCOVER
   ========================================================================== */

.th-discover {
    background:
        radial-gradient(110% 60% at 90% -6%, var(--th-paper) 0%, rgba(251, 249, 246, 0) 55%),
        var(--th-cream);
    padding-block: var(--th-block);
}

.th-discover__head {
    display: grid;
    justify-items: start;
    gap: 1rem;
    margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

/* Stamp — the house bean, the cut-out numeral, and a hairline that runs out as
   the section is read. */
.th-discover__stamp {
    display: flex;
    align-items: center;
    gap: clamp(.85rem, 1.8vw, 1.4rem);
    width: 100%;
    margin-bottom: clamp(.25rem, 1vw, .75rem);
}

.th-discover__bean {
    display: block;
    flex: none;
    width: clamp(30px, 3.4vw, 42px);
    height: auto;
    color: var(--th-espresso);
    opacity: .8;
    overflow: visible;
}

.th-discover__bean-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

.th-js .th-discover__bean.is-in .th-discover__bean-draw {
    animation: th-draw-in 1.25s var(--th-ease) forwards;
    animation-delay: calc(var(--i, 0) * .3s);
}

html:not(.th-js) .th-discover__bean-draw,
.th-is-editor .th-discover__bean-draw {
    stroke-dashoffset: 0;
}

.th-discover__bean-bead {
    transform-origin: 20px 20px;
    animation: th-pulse 3.6s var(--th-ease-soft) infinite;
}

.th-discover__num {
    flex: none;
    font-family: var(--th-display);
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    font-variant-numeric: tabular-nums;
    color: transparent;
    -webkit-text-stroke: 1px var(--th-espresso);
    opacity: .5;
}

.th-discover__stamp-rule {
    flex: 1;
    min-width: 0;
    height: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-discover__stamp-rule i {
    display: block;
    height: 100%;
    background: var(--th-crema);
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .06) * 2.4), 1));
    transform-origin: left;
}

.th-discover__title {
    font-size: var(--th-t-lg);
    line-height: .96;
    max-width: 14ch;
}

.th-discover__list {
    --thd-rail: clamp(1.5rem, 3.5vw, 3rem);

    position: relative;
    padding-left: var(--thd-rail);
    border-top: 1px solid var(--th-rule);
}

/* The rail measures the list rather than the reader's attention: nothing on a
   navigation list dims, so this is the only thing the scroll drives here. */
.th-discover__rail {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--th-rule);
    overflow: hidden;
}

.th-discover__rail i {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, var(--th-crema), var(--th-caramel));
    transform: scaleY(clamp(0, calc((var(--th-p, 1) - .16) * 2.2), 1));
    transform-origin: top;
}

.th-discover__item {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: clamp(1rem, 3vw, 2.5rem);
    padding-block: clamp(1.5rem, 3.2vw, 2.75rem);
    border-bottom: 1px solid var(--th-rule);
    color: var(--th-ink);
    transition: padding-left .8s var(--th-ease), color .6s var(--th-ease);
}

/* A warm ground that wipes in from the rail on hover, so the row lifts off the
   page instead of only shifting sideways. */
.th-discover__wipe {
    position: absolute;
    left: calc(var(--thd-rail) * -1);
    right: 0;
    top: 0;
    bottom: -1px;
    z-index: 0;
    background: linear-gradient(to right, rgba(193, 121, 60, .13), rgba(193, 121, 60, 0) 72%);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .7s var(--th-ease);
    pointer-events: none;
}

.th-discover__item > *:not(.th-discover__wipe) {
    position: relative;
    z-index: 1;
}

.th-discover__index {
    font-family: var(--th-display);
    font-size: var(--th-t-label);
    font-weight: 600;
    letter-spacing: .2em;
    opacity: .45;
    font-variant-numeric: tabular-nums;
    transition: opacity .6s var(--th-ease);
}

/* The mask is exactly one slot tall and each copy is exactly one slot, so the
   roll is a clean translateY(-50%) whatever the clamped font size resolves to.
   The slot is a touch taller than the cap height to leave room for descenders. */
.th-discover__name {
    display: block;
    overflow: hidden;
    height: 1.1em;
    font-family: var(--th-display);
    font-size: clamp(1.75rem, 5.4vw, 4.5rem);
    font-weight: 700;
    letter-spacing: -.04em;
    text-transform: uppercase;
}

.th-discover__name-reel {
    display: block;
    transition: transform .75s var(--th-ease);
}

.th-discover__name-reel i {
    display: block;
    height: 1.1em;
    line-height: 1.1;
    font-style: normal;
}

.th-discover__name-reel i:last-child {
    color: var(--th-espresso);
}

.th-discover__kind {
    font-size: var(--th-t-label);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--th-ink-soft);
    text-align: right;
}

.th-discover__go {
    width: clamp(2.25rem, 3vw, 3rem);
    height: clamp(2.25rem, 3vw, 3rem);
    border: 1px solid var(--th-rule);
    border-radius: 50%;
    display: grid;
    place-items: center;
    flex: none;
    transition: background-color .6s var(--th-ease), color .6s var(--th-ease), border-color .6s var(--th-ease), transform .6s var(--th-ease);
}

.th-discover__go svg {
    width: 40%;
    height: 40%;
}

.th-discover__thumb {
    display: none;
}

/* The cursor-trailing preview only exists for fine pointers; keep it out of the
   document entirely everywhere else. */
.th-discover__cursor {
    display: none;
}

@media (hover: hover) and (min-width: 901px) {
    .th-discover__item:hover,
    .th-discover__item:focus-visible {
        padding-left: clamp(1rem, 2.5vw, 2.5rem);
        color: var(--th-espresso);
    }
    .th-discover__item:hover .th-discover__wipe,
    .th-discover__item:focus-visible .th-discover__wipe {
        transform: scaleX(1);
    }
    .th-discover__item:hover .th-discover__name-reel,
    .th-discover__item:focus-visible .th-discover__name-reel {
        transform: translateY(-50%);
    }
    .th-discover__item:hover .th-discover__index,
    .th-discover__item:focus-visible .th-discover__index {
        opacity: 1;
    }
    .th-discover__item:hover .th-discover__go,
    .th-discover__item:focus-visible .th-discover__go {
        background: var(--th-espresso);
        border-color: var(--th-espresso);
        color: var(--th-cream);
        transform: rotate(45deg);
    }
    .th-discover__cursor {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: clamp(200px, 18vw, 300px);
        aspect-ratio: 4 / 5;
        pointer-events: none;
        z-index: 4;
        opacity: 0;
        transform: translate3d(var(--x, 0), var(--y, 0), 0) translate(-50%, -50%) scale(.82);
        transition: opacity .5s var(--th-ease), transform .55s var(--th-ease);
        overflow: hidden;
        box-shadow: 0 40px 80px -30px rgba(23, 16, 10, .6);
        will-change: transform;
    }
    .th-discover__cursor.is-on {
        opacity: 1;
        transform: translate3d(var(--x, 0), var(--y, 0), 0) translate(-50%, -50%) scale(1);
    }
    .th-discover__slot {
        position: absolute;
        inset: 0;
        opacity: 0;
        transition: opacity .45s var(--th-ease);
    }
    .th-discover__slot.is-shown {
        opacity: 1;
    }
    .th-discover__slot img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
}

@media (max-width: 900px) {
    .th-discover__list {
        --thd-rail: 1.25rem;
    }
    .th-discover__item {
        grid-template-columns: auto minmax(0, 1fr);
        grid-template-areas:
            "wipe  wipe"
            "index name"
            "kind  kind"
            "thumb thumb";
        column-gap: 1rem;
        row-gap: .35rem;
        align-items: baseline;
    }
    .th-discover__wipe {
        grid-area: wipe;
    }
    .th-discover__index {
        grid-area: index;
    }
    .th-discover__name {
        grid-area: name;
    }
    .th-discover__kind {
        grid-area: kind;
        text-align: left;
    }
    .th-discover__thumb {
        display: block;
        grid-area: thumb;
        margin-top: .9rem;
        aspect-ratio: 16 / 9;
    }
    .th-discover__go {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .th-discover__stamp-rule i,
    .th-discover__wipe {
        transform: scaleX(1) !important;
    }
    .th-discover__wipe {
        opacity: 0;
    }
    .th-discover__rail i {
        transform: scaleY(1) !important;
    }
    .th-discover__name-reel {
        transform: none !important;
    }
    .th-discover__bean-draw {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }
    .th-discover__bean-bead {
        animation: none !important;
    }
}

/* ==========================================================================
   12 — SOCIAL
   ========================================================================== */

.th-social {
    background: var(--th-ink);
    color: var(--th-cream);
    padding-block: var(--th-block);
    --th-rule: var(--th-rule-light);
}

.th-social__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 1.5rem;
    margin-bottom: clamp(2rem, 4vw, 3rem);
    padding-bottom: clamp(1.25rem, 2.5vw, 2rem);
    border-bottom: 1px solid var(--th-rule-light);
}

.th-social__handle {
    font-size: clamp(2rem, 7vw, 6rem);
    line-height: .9;
    letter-spacing: -.05em;
}

.th-social__handle i {
    font-style: normal;
    color: var(--th-crema);
}

/* A staggered strip rather than a bento: every tile keeps the same 4:5 crop, and
   alternate tiles drop to give the row an editorial rhythm. */
.th-social__grid {
    --th-stagger: clamp(1rem, 4vw, 3.5rem);
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: start;
    gap: clamp(.5rem, 1.2vw, 1.25rem);
    padding-bottom: var(--th-stagger);
}

.th-social__tile {
    position: relative;
    overflow: hidden;
    background: var(--th-roast);
    aspect-ratio: 4 / 5;
}

/* Offset with `translate` rather than a margin: Elementor's widget reset
   (`.elementor .elementor-widget … figure {margin:0}`) outranks class selectors. */
.th-social__tile:nth-child(even) {
    translate: 0 var(--th-stagger);
}

.th-social__tile img,
.th-social__tile video {
    transition: transform 1.4s var(--th-ease), filter 1s var(--th-ease);
    filter: saturate(.9);
}

.th-social__tile:hover img,
.th-social__tile:hover video {
    transform: scale(1.05);
    filter: saturate(1.05);
}


.th-social__badge {
    position: absolute;
    left: .75rem;
    bottom: .75rem;
    z-index: 2;
    font-size: 10px;
    letter-spacing: .2em;
    text-transform: uppercase;
    padding: .5em .85em;
    border-radius: 999px;
    background: rgba(23, 16, 10, .6);
    backdrop-filter: blur(6px);
    color: var(--th-cream);
}

.th-social__foot {
    margin-top: clamp(1.5rem, 3vw, 2.5rem);
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    align-items: center;
    justify-content: space-between;
}

@media (max-width: 900px) {
    .th-social__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        --th-stagger: 0px;
        padding-bottom: 0;
    }
    .th-social__head {
        grid-template-columns: 1fr;
        align-items: start;
    }
}

/* ==========================================================================
   13 — FINAL CTA
   ========================================================================== */

.th-cta-section {
    position: relative;
    background:
        radial-gradient(70% 55% at 50% 42%, rgba(83, 33, 0, .5) 0%, rgba(83, 33, 0, 0) 68%),
        var(--th-ink);
    color: var(--th-cream);
    padding-block: clamp(6rem, 15vw, 13rem);
    text-align: center;
    overflow: hidden;
}

/* The watermark turns a few degrees and settles as the block passes, so the
   closing frame breathes without anything visibly animating. */
.th-cta-section__mark {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) rotate(calc((var(--th-p, .5) - .5) * 7deg)) scale(calc(1 + var(--th-p, .5) * .05));
    width: min(140%, 1500px);
    opacity: .05;
    pointer-events: none;
    z-index: 0;
    filter: grayscale(1);
    will-change: transform;
}

/* Crown — the ring on its horizon. A flex row rather than an absolutely pinned
   rule, so the hairline always meets the ring and never crosses the title. */
.th-cta-section__crown {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2.5vw, 2.25rem);
    margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}

/* Each half opens outward from the ring as the section is read. */
.th-cta-section__horizon {
    flex: 1;
    min-width: 0;
    height: 1px;
    opacity: .5;
    transform: scaleX(clamp(0, calc((var(--th-p, 1) - .08) * 2), 1));
}

.th-cta-section__horizon:first-child {
    background: linear-gradient(to right, transparent, var(--th-rule-light) 55%, var(--th-crema));
    transform-origin: right;
}

.th-cta-section__horizon:last-child {
    background: linear-gradient(to left, transparent, var(--th-rule-light) 55%, var(--th-crema));
    transform-origin: left;
}

.th-cta-section__inner {
    position: relative;
    z-index: 2;
    display: grid;
    justify-items: center;
    gap: clamp(1.5rem, 3vw, 2.5rem);
}

/* The ring's stroke is the scroll: it closes exactly as the reader lands on the
   end of the page. `stroke-dashoffset` is read straight off --th-p, not a
   keyframe, so it scrubs both ways. */
.th-cta-section__ring {
    display: block;
    flex: none;
    width: clamp(46px, 5.5vw, 72px);
    height: auto;
    color: var(--th-cream);
    overflow: visible;
}

.th-cta-section__ring-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: clamp(0, calc(1 - (var(--th-p, 1) - .12) * 1.9), 1);
}

/* The bean at the centre of the ring. It settles in off the same --th-p the
   stroke is drawn by, a beat behind it, so the mark reads as one gesture:
   the ring closes around the bean rather than next to it. */
.th-cta-section__bean {
    transform-origin: 36px 36px;
    opacity: clamp(0, calc((var(--th-p, 1) - .2) * 3.4), 1);
    transform: scale(clamp(.72, calc(.72 + (var(--th-p, 1) - .2) * .95), 1));
}

.th-cta-section__bean-crease {
    opacity: .85;
}

.th-cta-section__ring-bead {
    transform-origin: 36px 70px;
    animation: th-pulse 3s var(--th-ease-soft) infinite;
}

.th-cta-section__title {
    font-size: var(--th-t-xl);
    line-height: .94;
    letter-spacing: -.045em;
    text-transform: uppercase;
    max-width: 16ch;
}

.th-cta-section__title em {
    display: block;
    font-family: var(--th-editorial);
    font-style: italic;
    font-weight: 400;
    text-transform: none;
    letter-spacing: -.02em;
    color: var(--th-crema);
}

/* The subtitle rises out of a mask a beat after the title has finished setting,
   which gives the closing line its own moment instead of arriving with the rest. */
.th-cta-section__title em > span {
    display: inline-block;
    transform: translateY(105%);
    transition: transform 1.05s var(--th-ease);
    transition-delay: .5s;
}

/* The title is itself the revealed element, so the reset needs the compound
   `.is-in.th-cta-section__title` form — a descendant selector would never match. */
.th-js [data-th-reveal].is-in.th-cta-section__title em > span,
html:not(.th-js) .th-cta-section__title em > span,
.th-is-editor .th-cta-section__title em > span {
    transform: none;
}

/* The closing action is the page's last one, so it is filled rather than
   outlined — scoped here, the hero keeps its own treatment untouched. */
.th-cta-section .th-cta--filled {
    background: var(--th-cream);
    border-color: var(--th-cream);
    color: var(--th-ink);
}

.th-cta-section .th-cta--filled::before {
    background: var(--th-crema);
}

.th-cta-section .th-cta--filled:hover,
.th-cta-section .th-cta--filled:focus-visible {
    color: var(--th-ink);
    border-color: var(--th-crema);
}

/* Address lines are set individually, each with a leading hairline that draws
   in on a stagger — a colophon rather than a block of small caps. */
.th-cta-section__address {
    display: grid;
    justify-items: center;
    gap: .25rem;
    font-style: normal;
    font-size: var(--th-t-label);
    letter-spacing: .22em;
    text-transform: uppercase;
    line-height: 2;
    color: var(--th-cream-soft);
}

.th-cta-section__address span {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .85em;
}

.th-cta-section__address span::before {
    content: "";
    width: clamp(12px, 2vw, 26px);
    height: 1px;
    background: var(--th-crema);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform .7s var(--th-ease);
    transition-delay: calc(.4s + var(--i, 0) * .12s);
}

.th-js [data-th-reveal].is-in.th-cta-section__address span::before,
html:not(.th-js) .th-cta-section__address span::before,
.th-is-editor .th-cta-section__address span::before {
    transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
    .th-cta-section__mark {
        transform: translate(-50%, -50%) !important;
    }
    .th-cta-section__horizon,
    .th-cta-section__address span::before {
        transform: scaleX(1) !important;
    }
    .th-cta-section__ring-draw {
        stroke-dashoffset: 0 !important;
    }
    .th-cta-section__bean {
        opacity: 1 !important;
        transform: none !important;
    }
    .th-cta-section__ring-bead {
        animation: none !important;
    }
    .th-cta-section__title em > span {
        transform: none !important;
    }
}

/* ==========================================================================
   14 — REVIEWS
   The page's one white surface. After a run of dark and cream sections the
   proof arrives on paper: hairline cards, a Google score card that carries the
   rating, and the channel row that closes the block. Card colour, radius, star
   colour and column count all read a var first, so the Elementor controls can
   overwrite them from the widget wrapper.
   ========================================================================== */

.th-reviews-section {
    background: #FFF;
    color: var(--th-ink);
    padding-block: var(--th-block);
    --th-rule: rgba(23, 16, 10, .1);
    --th-reviews-line: rgba(23, 16, 10, .1);
    --th-reviews-shadow: 0 1px 2px rgba(23, 16, 10, .04), 0 20px 44px -30px rgba(23, 16, 10, .4);
    --th-star-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.6l2.6 5.3 5.8.8-4.2 4.1 1 5.8-5.2-2.7-5.2 2.7 1-5.8L1.6 7.7l5.8-.8z' fill='%23000'/%3E%3C/svg%3E");
}

/* Grain over white is a no-op in overlay, so this surface keeps the film soft
   and multiplied — just enough tooth to stop the paper reading as a flat plate. */
.th-reviews-section.th-grain::after {
    mix-blend-mode: var(--th-grain-blend, multiply);
    opacity: calc(var(--th-grain-opacity, .16) * .45);
}

/* Head — copy on the left, the Google score card on the right --------------- */

.th-reviews-section__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(15rem, 21rem);
    gap: clamp(2rem, 5vw, 5rem);
    align-items: end;
    padding-bottom: clamp(2rem, 4vw, 3.5rem);
    margin-bottom: clamp(2.25rem, 4.5vw, 3.75rem);
    border-bottom: 1px solid var(--th-reviews-line);
}

.th-reviews-section__eyebrow {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-bottom: clamp(1.1rem, 2.2vw, 1.75rem);
}

.th-reviews-section__title {
    font-size: var(--th-t-xl);
    max-width: 15ch;
}

.th-reviews-section__title em {
    font-family: var(--th-editorial);
    font-weight: 400;
    font-style: italic;
    letter-spacing: -.015em;
    color: var(--th-espresso);
}

.th-reviews-section__intro .th-lede {
    margin-top: clamp(1rem, 2vw, 1.5rem);
}

/* Score card ---------------------------------------------------------------- */

.th-reviews-section__score {
    display: grid;
    justify-items: start;
    gap: .8rem;
    padding: clamp(1.4rem, 2.2vw, 2rem);
    background: var(--th-reviews-card, #FFF);
    border: 1px solid var(--th-reviews-line);
    border-radius: var(--th-reviews-radius, 26px);
    box-shadow: var(--th-reviews-shadow);
}

.th-score__top {
    display: flex;
    align-items: center;
    gap: .7rem;
}

.th-score__g {
    width: 1.4rem;
    height: 1.4rem;
    flex: none;
}

.th-score__source {
    font-size: var(--th-t-label);
    font-weight: 500;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--th-ink-soft);
}

.th-score__value {
    display: flex;
    align-items: baseline;
    gap: .45rem;
    font-family: var(--th-display);
}

.th-score__number {
    font-size: clamp(2.5rem, 4.2vw, 3.5rem);
    font-weight: 800;
    line-height: .88;
    letter-spacing: -.045em;
}

.th-score__max {
    font-size: var(--th-t-sm);
    font-weight: 500;
    color: var(--th-ink-soft);
}

.th-score__count {
    font-size: .875rem;
    color: var(--th-ink-soft);
}

.th-reviews-section .th-cta--sm {
    margin-top: .4rem;
    padding: .95em 1.5em;
}

/* Stars — one masked box per star, part-filled to the decimal so a 4,7 reads
   as a 4,7. Scoped under .th-section so the section owns them even where the
   theme shell has already styled a star row for the utility bar. */

.th-section .th-stars {
    display: inline-flex;
    gap: .14em;
    font-size: 1rem;
    color: var(--th-star, #F5B400);
}

.th-section .th-stars--lg {
    font-size: 1.2rem;
}

.th-section .th-star {
    position: relative;
    display: block;
    width: 1em;
    height: 1em;
    background: var(--th-ink-faint);
    opacity: 1;
    -webkit-mask: var(--th-star-mask) center / contain no-repeat;
    mask: var(--th-star-mask) center / contain no-repeat;
}

.th-section .th-star i {
    position: absolute;
    inset: 0;
    display: block;
    background: currentColor;
    -webkit-mask: var(--th-star-mask) left center / auto 100% no-repeat;
    mask: var(--th-star-mask) left center / auto 100% no-repeat;
}

/* The cards ----------------------------------------------------------------- */

.th-reviews-section__grid {
    display: grid;
    grid-template-columns: repeat(var(--th-reviews-cols, 3), minmax(0, 1fr));
    gap: clamp(1rem, 1.8vw, 1.75rem);
    align-items: start;
}

/* Same editorial drop as the social strip. Margin rather than translate: the
   hover lift owns `translate`, and the two must not fight over one property. */
.th-reviews-section__grid--stagger {
    --th-review-drop: clamp(1rem, 2.4vw, 2.5rem);
    padding-bottom: var(--th-review-drop);
}

.th-reviews-section__grid--stagger .th-review:nth-child(even) {
    margin-top: var(--th-review-drop);
}

.th-review {
    position: relative;
    display: grid;
    justify-items: start;
    gap: .85rem;
    padding: clamp(1.4rem, 2.2vw, 2rem);
    background: var(--th-reviews-card, #FFF);
    border: 1px solid var(--th-reviews-line);
    border-radius: var(--th-reviews-radius, 26px);
    box-shadow: var(--th-reviews-shadow);
    transition:
        translate .6s var(--th-ease),
        box-shadow .6s var(--th-ease),
        border-color .6s var(--th-ease);
}

.th-review:hover,
.th-review:focus-within {
    translate: 0 -5px;
    border-color: rgba(23, 16, 10, .16);
    box-shadow: 0 1px 2px rgba(23, 16, 10, .05), 0 32px 60px -32px rgba(23, 16, 10, .45);
}

.th-review__mark {
    position: absolute;
    top: clamp(1.1rem, 1.8vw, 1.6rem);
    right: clamp(1.1rem, 1.8vw, 1.6rem);
    display: block;
}

.th-review__g {
    width: 1.15rem;
    height: 1.15rem;
}

.th-review__quote-mark {
    width: clamp(22px, 2vw, 28px);
    height: auto;
    color: var(--th-ink-faint);
}

.th-review__quote {
    margin: 0;
    padding: 0;
    border: 0;
    max-width: 40ch;
    font-family: var(--th-body);
    font-size: var(--th-t-body);
    font-style: normal;
    line-height: 1.6;
    color: var(--th-ink);
}

.th-review__author {
    display: flex;
    align-items: center;
    gap: .8rem;
    width: 100%;
    margin-top: .3rem;
    padding-top: 1rem;
    border-top: 1px solid var(--th-reviews-line);
}

.th-review__avatar {
    position: relative;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: none;
    overflow: hidden;
    border-radius: 999px;
    background: var(--th-bone);
    font-family: var(--th-display);
    font-size: .95rem;
    font-weight: 700;
    color: var(--th-espresso);
}

.th-section .th-review__avatar img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: cover;
}

.th-review__who {
    display: grid;
    gap: .12rem;
    min-width: 0;
}

.th-review__name {
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: -.01em;
}

.th-review__meta {
    font-size: .8rem;
    color: var(--th-ink-soft);
}

/* One link, whole card: the anchor keeps the accessible name, the pseudo
   element carries the hit area. */
.th-review--link .th-review__hit::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

.th-review--link:hover .th-review__hit,
.th-review--link .th-review__hit:focus-visible {
    text-decoration: underline;
    text-underline-offset: .22em;
}

/* Editor-only skeletons, so an empty grid still shows its rhythm. */
.th-review--empty {
    gap: .55rem;
}

.th-review__bone {
    display: block;
    width: var(--w, 100%);
    height: .7rem;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--th-bone), var(--th-cream));
}

.th-review__hint {
    margin-top: .45rem;
    font-size: var(--th-t-label);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--th-ink-soft);
}

/* Foot — the channel row ---------------------------------------------------- */

.th-reviews-section__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    margin-top: clamp(2.25rem, 4.5vw, 3.75rem);
    padding-top: clamp(1.5rem, 3vw, 2.25rem);
    border-top: 1px solid var(--th-reviews-line);
}

.th-reviews-section__foot-copy {
    display: grid;
    gap: .55rem;
}

.th-reviews-section__note {
    max-width: 44ch;
    color: var(--th-ink-soft);
}

.th-socials {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.th-socials li {
    list-style: none;
}

.th-social-btn {
    display: grid;
    place-items: center;
    width: clamp(2.75rem, 4vw, 3.25rem);
    aspect-ratio: 1;
    border: 1px solid var(--th-reviews-line);
    border-radius: 999px;
    background: var(--th-reviews-card, #FFF);
    color: var(--th-ink);
    transition:
        translate .5s var(--th-ease),
        background-color .5s var(--th-ease),
        border-color .5s var(--th-ease),
        color .5s var(--th-ease);
}

.th-social-btn:hover,
.th-social-btn:focus-visible {
    translate: 0 -3px;
    background: var(--th-espresso);
    border-color: var(--th-espresso);
    color: var(--th-cream);
}

/* The four-colour G stays itself, so its button lifts on cream instead. */
.th-social-btn--google:hover,
.th-social-btn--google:focus-visible {
    background: var(--th-cream);
    border-color: var(--th-stone);
    color: var(--th-ink);
}

.th-social-btn__icon {
    width: 1.3rem;
    height: 1.3rem;
}

.th-social-btn__g {
    width: 1.15rem;
    height: 1.15rem;
}

@media (max-width: 1100px) {
    .th-reviews-section__head {
        grid-template-columns: minmax(0, 1fr);
        align-items: start;
    }

    .th-reviews-section__score {
        max-width: 24rem;
    }

    .th-reviews-section__grid {
        --th-reviews-cols: 2;
    }
}

@media (max-width: 700px) {
    .th-reviews-section__grid {
        --th-reviews-cols: 1;
    }

    .th-reviews-section__grid--stagger {
        padding-bottom: 0;
    }

    .th-reviews-section__grid--stagger .th-review:nth-child(even) {
        margin-top: 0;
    }

    .th-reviews-section__foot {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* ==========================================================================
   Reduced motion — keep the design, drop the movement.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    .th-section *,
    .th-section *::before,
    .th-section *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }

    .th-js .th-section [data-th-reveal],
    .th-js .th-figure[data-th-reveal="image"] img {
        opacity: 1 !important;
        transform: none !important;
        clip-path: none !important;
    }

    .th-word > span,
    .th-letter > span {
        transform: none !important;
    }

    .th-hero__media img,
    .th-hero__media video,
    .th-bakery__media img,
    .th-space__reveal img,
    .th-coffee__disc img {
        transform: none !important;
        animation: none !important;
    }

    /* The loop stays paused here (see initVideos), so hide it and let the still
       beneath carry the hero. */
    .th-hero__bg-video {
        display: none !important;
    }

    .th-section .th-manifesto__figure img {
        translate: none !important;
    }

    .th-hero__mark span,
    .th-hero__sub,
    .th-hero__foot,
    .th-hero__intro,
    .th-hero__actions,
    .th-hero__reel {
        transform: none !important;
        opacity: 1 !important;
        animation: none !important;
    }

    /* Strokes must land drawn, not stuck at their starting dash offset. */
    .th-hero__crest-draw,
    .th-hero__pour-draw,
    .th-hero__pour-fill {
        stroke-dashoffset: 0 !important;
        animation: none !important;
    }

    .th-hero__crest-steam path,
    .th-hero__pour-drops circle,
    .th-hero__reel-label i {
        animation: none !important;
    }

    .th-hero__crest-steam path {
        opacity: .7 !important;
    }

    /* The drops are authored at the cone's mouth and animate downward; parked
       still they need an explicit resting position between cone and cup. */
    .th-hero__pour-drops circle {
        opacity: .8 !important;
        transform: translateY(28px) !important;
    }

    .th-space__reveal {
        width: 100%;
    }

    .th-marquee__track {
        animation: none !important;
    }
}
