/* #region Fonts */
/* The house serves its own faces, from /fonts/. Loaded from Google's servers instead, every page
   view sends the visitor's IP address there — processing the privacy policy does not announce, and the
   one external request left on the site.

   These are variable files: one file per family covers the whole range of weights, which is why
   font-weight is a range rather than a number. It is also what makes the weights work that a hosted
   stylesheet does not load — a 200 used dozens of times across the CSS otherwise renders as 300, and
   the Plus Jakarta Sans italic is synthesized. Each range is the one the file is drawn in, never
   wider: Plus Jakarta Sans runs 200–800 and Playfair Display 400–900, so a lighter weight asked of
   Playfair is set in its 400.

   font-display: swap — the text appears at once in the fallback face and is swapped when the real one
   arrives. On a site whose copy is the product, waiting for a letter is worse than seeing it change. */
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/PlusJakartaSans-VariableFont_wght.ttf') format('truetype');
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/PlusJakartaSans-Italic-VariableFont_wght.ttf') format('truetype');
    font-weight: 200 800;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Playfair Display';
    src: url('/fonts/PlayfairDisplay-VariableFont_wght.ttf') format('truetype');
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Playfair Display';
    src: url('/fonts/PlayfairDisplay-Italic-VariableFont_wght.ttf') format('truetype');
    font-weight: 400 900;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Montserrat';
    src: url('/fonts/Montserrat-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}
/* #endregion */

/* #region Tokens */
:root {
    --site-header-h: 72px;
    --black: #050505;
    /* The one deliberate exception to the single house black: these shades give raised surfaces their
       depth against the page. Every other near-black on screen is #050505. */
    --black-soft: #0a0a0a;
    --black-mid: #101010;
    --black-deep: #070707;
    /* The house gold — champagne, settled against the gilding actually printed on the Alibi cards.
       It is the previous #BEAE7E quietened: the same hue (45° against 44°), two points less
       saturation and four points less lightness. Do not push it warmer or paler: at 31° it reads as brown,
       and below 20% saturation it stops being a colour at all and becomes a dirty white next to --white.

       Two properties are worth keeping when this is ever touched again. It carries text (eyebrows,
       the italic in headings), so it needs to hold contrast on near-black — this sits near 8:1. And
       it does two different jobs: hairlines and type on one side, filled shapes on the other. If a
       future shade suits one and looks weak in the other, add a second, stronger variant for fills
       rather than moving this token.

       --gold-rgb is the single source for every translucent shade. Write each of them against this
       token, never as a literal triplet: a literal repeated across the stylesheets is what stops
       the brand colour from being adjustable in one place. */
    --gold: #B6A574;
    --gold-rgb: 182, 165, 116;

    /* The brighter gold, and the second variant the note above anticipated. It does one job the
       working accent cannot: it glows. Rings, edges and the halo around the concierge orb are lit
       with it on near-black, where --gold reads as flat. It lived as the literal "200, 185, 122" in
       twenty-two places across six stylesheets — the very shape the token above exists to end — so
       it is named here and adjusted here. The same mark drawn by Odoardo.AI uses --gold instead;
       whether the two should meet is a decision for the house, and this is now the one line that
       would carry it. */
    --gold-bright: #C8B97A;
    --gold-bright-rgb: 200, 185, 122;

    --gold-glow: rgba(var(--gold-rgb), 0.18);
    --gold-subtle: rgba(var(--gold-rgb),0.10);
    --gold-dim: rgba(var(--gold-rgb),0.07);
    --gold-line: rgba(var(--gold-rgb),0.15);
    --gold-border: rgba(var(--gold-rgb),0.20);
    --gold-mid: rgba(var(--gold-rgb),0.30);
    /* The house's inner frame for a photograph, stated once. A picture in Odoardo carries a hairline
       set in from its edge — a mount drawn on the photograph — and nothing else: where this frame is
       present, a border around the figure is a second frame saying the same thing, and the two read
       as an accident rather than as a system.
       At rest the mount is white; under the hand it closes towards the edge and warms to gold, which is
       the whole of the hover a photograph gets. Two pictures on one page frame themselves alike only
       while every frame reads these tokens. */
    --photo-frame: rgba(245, 245, 245, 0.22);
    --photo-frame-hover: rgba(var(--gold-rgb), 0.55);
    --photo-frame-inset: clamp(.7rem, 1.6vw, 1.3rem);
    --gold-accent: rgba(var(--gold-rgb),0.40);
    --gold-dashed: rgba(var(--gold-rgb),0.55);
    --gold-hover: rgba(var(--gold-rgb),0.60);
    --gold-strong: rgba(var(--gold-rgb),0.70);
    --white: #F5F5F5;
    --white-subtle: rgba(245, 245, 245, 0.12);
    --white-dim: rgba(245, 245, 245, 0.20);
    --white-ghost: rgba(245, 245, 245, 0.30);
    --white-faint: rgba(245, 245, 245, 0.40);
    --white-soft: rgba(245, 245, 245, 0.70);
    --white-bright: rgba(245, 245, 245, 0.80);
    /* Gold arrives under the hand. At rest the house is drawn in white hairlines on black, and gold is
       kept for the one accent a heading carries and for whatever the visitor is touching — a line that
       draws itself, a ring that closes, a frame that warms. Gold everywhere at once is gold nowhere, so
       a resting border, divider or tint reads one of these and never a translucent gold. */
    --hairline-faint: rgba(245, 245, 245, 0.06);
    --hairline: rgba(245, 245, 245, 0.10);
    --hairline-mid: rgba(245, 245, 245, 0.16);
    --hairline-strong: rgba(245, 245, 245, 0.28);
    --tint: rgba(245, 245, 245, 0.03);
    --tint-raised: rgba(245, 245, 245, 0.05);
    /* The house's one curve: a long deceleration that settles without overshoot. Nothing springs,
       bounces or beats — a spring reads as a toy, and a toy is the opposite of a quiet object. */
    --ease-house: cubic-bezier(.22, 1, .36, 1);
    --motion-quick: .6s;
    --motion: .9s;
    --motion-slow: 1.4s;
    /* The resting pulse of the corner controls: one exhale every six seconds, in phase across them. */
    --breath-period: 6s;
    /* The house button is drawn, never filled: a filled surface — gold or white — is the loudest thing
       a black page can hold. Its two background layers are what answers the hand: a gold line opening
       from the middle of the lower edge and a breath of light rising from the foot. A button reads these
       at rest and, under the hand, sets `background-size: 100% 1px, 100% 100%` and
       `border-color: var(--button-border-hover)`. The gold layer is painted on the border box and the
       lower border goes transparent under the hand, so the gold line takes the place of the white edge
       instead of lying a pixel above it, where the brightened frame swallowed it. */
    --button-layers:
        linear-gradient(var(--gold), var(--gold)) center bottom / 0 1px no-repeat border-box,
        linear-gradient(rgba(245, 245, 245, .045), rgba(245, 245, 245, .045)) center bottom / 100% 0 no-repeat;
    --button-border: rgba(245, 245, 245, .5);
    --button-border-hover: var(--white) var(--white) transparent;
    --font:'Plus Jakarta Sans', sans-serif;
    --font-sans: var(--font);
    /* The display face, decided after a live Cormorant trial: Playfair Display stays. Every
       display-family rule points at this one token, so a future candidate is again a one-line
       change here. */
    --font-display: 'Playfair Display', serif;
    /* Referenced by several stylesheets, so it has to be defined here: undefined, those serif accents
       silently inherit their parent's face. Bound to the display face — one serif voice in the house. */
    --font-serif: var(--font-display);
    --font-mono: var(--font);
    --hero-content-max: 1400px;
    --hero-gutter: 5vw;
    /* Held under 5.6vw/6.5rem: on a wide screen that reaches a size where two words fill the whole left
       column and read as a poster rather than as a page opening. */
    --hero-title-size: clamp(3.1rem, 4.8vw, 5.4rem);
    --hero-title-line-height: 1.03;
    --section-content-max: var(--hero-content-max);
    --section-space: clamp(6rem, 10vw, 9rem);
    --section-title-size: clamp(2.8rem, 4.6vw, 5.4rem);
    --section-title-line-height: .98;
    /* The air between a section heading and the lead paragraph under it: one declaration,
       referenced everywhere. Written out per section instead, three headings on one page breathe
       differently and the tightest of them reads as a fault. The 3vh is the measure .h-title uses,
       so a heading reading this token is not pressed against its lead beside one that is not. A
       section that genuinely needs its own measure overrides this deliberately. */
    --section-lead-gap: clamp(1.75rem, 3vh, 2.75rem);
    /* The next gap down the page: from the whole heading block — eyebrow, title, lead — to what the
       section actually shows. One declaration, referenced everywhere. Written out at each section that
       needs it, one relationship ends up with six values — 3.4rem under the journal header, 3.6rem over
       the workshop films, 3.6rem over the commissions, 4rem over the places, 4rem over the artist list,
       3rem over the path — and nobody chooses those differences; they are the residue of writing the same
       rule six times.

       This is the standard section rhythm, not the only one. A heading that opens a chapter — the
       anatomy ladder on the home page, the growth section on Art, the deck on Alibi — stands on a
       deliberately larger scale of six to ten rem, and those keep their own measure: they are a
       different relationship that happens to be built from the same two elements. */
    --section-head-gap: clamp(2.6rem, 5.5vh, 4.2rem);
    /* And the gap above those two: eyebrow to title. One token, because left to each page it becomes a
       scatter of one-offs — 3vh, 1.4rem, 1rem — none of them chosen against the others. The value is the
       measure the Space lease heading is tuned to, the one place it was considered in isolation. */
    --section-tag-gap: clamp(1.2rem, 2.5vh, 2rem);
    --section-divider: var(--hairline);
    --hero-surface: #050505;
    /* Surface depth — the same deliberate exception as --black-soft and --black-deep above. */
    --surface-editorial: #070707;
    --surface-raised: #0a0a0a;
    --surface-card: #080808;
    --overlay: rgba(10, 10, 10, 0.72);
    --line: var(--hairline);
    --error: #D35050;
    --text-muted: rgba(245, 245, 245, 0.5);
    /* Alias for --text-muted, kept because the configurator and checkout summaries name --grey: undefined,
       every one of those declarations is dropped as invalid. One tone, one definition. */
    --grey: var(--text-muted);

    /* Photography, and the same argument as --section-tag-gap above. Left to each page, a photograph at
       rest takes a dozen different exposures — brightness from .52 to 1.0, saturation from .55 to 1.0 —
       none of them chosen against the others, so one file reads as a different photograph depending on
       which page opens it: the product shot at .88 in the hero, .84 in the pairing band, .70 in a use case
       and untouched on the sense card, with .b2b-img alone carrying .70 here and .82 in art.css.

       The house has three, and the first two are the ones a photograph shown for itself may take.
       The grade — saturation and contrast — is the same in all of them, because that is a look and
       not an exposure; only the brightness says what the picture is doing on the page.

       The third is the one case where a number really is doing work rather than being a taste: type
       laid directly on the picture. The journal's cards say so in their own comment — colour comes
       back on hover and the light goes down, because brightening a photograph under gold type is the
       natural thing to do and the wrong one. That exposure is not a look to be unified away; what it
       needed was to stop being written as .30, .34, .42 and .52 in four places.

       --photo-veil is the fifth member and the only one that is not a filter: a gradient darkening
       the foot of a frame where a caption sits, leaving the picture itself alone. That is the home page's
       own conclusion, and its strength is stated here so every page reads one value. */
    --photo-grade: saturate(.86) contrast(1.05);
    --photo-at-rest: brightness(.88) var(--photo-grade);
    --photo-lifted: brightness(1) saturate(.95) contrast(1.02);
    --photo-as-ground: brightness(.72) var(--photo-grade);
    --photo-under-type: brightness(.45) var(--photo-grade);
    /* Colour held back so that it can arrive on hover. One value, against .2/.25/.35/.45/.5. */
    --photo-mute: grayscale(.3);
    --photo-veil: linear-gradient(180deg, rgba(5, 5, 5, .06) 0%, rgba(5, 5, 5, .44) 100%);
}

@media (max-width: 760px) {
    :root {
        /* The lower bound must sit below 12vw at 360px (43.2px), or the title never scales on phones. */
        --hero-title-size: clamp(2.6rem, 12vw, 4.8rem);
        --section-space: 5.5rem;
        --section-title-size: clamp(2.55rem, 12vw, 3.65rem);
    }
}
/* #endregion */

/* #region Reset & Base */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* The native cursor disappears only once layout.js has a custom one to show in its place. */
body.has-custom-cursor,
body.has-custom-cursor * {
    cursor: none !important;
}

html {
    scroll-behavior: smooth;
    /* The header is fixed: an anchor target must land below it, not under it. */
    scroll-padding-top: var(--site-header-h, 80px);
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

body {
    background-color: var(--black);
    color: var(--white);
    font-family: var(--font);
    font-weight: 300;
    -webkit-font-smoothing: antialiased;
    /* clip instead of hidden: same guard against stray overflow, without breaking position: sticky. */
    overflow-x: clip;
}

/* Form controls do not inherit the page's face on their own — a button whose class names no family
   would speak in the phone's system sans (Roboto on Android). */
button,
input,
select,
textarea {
    font-family: inherit;
}

/* The browser's own scrollbar, brought into the palette — undressed it is the last grey object on a black
   page.
   Two mechanisms, because no single one covers every browser:

   scrollbar-color / scrollbar-width are the standard, and they are what Firefox has always understood
   and what Chrome, Edge and Safari understand today. Both are inherited properties, so declaring them
   on the root reaches every scrolling box on the site without naming one — including the rails that
   set `scrollbar-width: none` for themselves, which still win locally.

   The ::-webkit- pseudo-elements are the older mechanism, and they are here for the WebKit versions
   that predate the standard. Where a browser understands both, the standard wins and these are ignored;
   that costs nothing, because they are set to the same colours. */
:root {
    scrollbar-width: thin;
    scrollbar-color: rgba(245, 245, 245, .18) transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    /* The transparent border and the content-box clip are what inset the bar: without them a 10px
       thumb touches both edges of its gutter and reads as a solid rule rather than a handle. */
    border: 3px solid transparent;
    border-radius: 999px;
    background: rgba(245, 245, 245, .18);
    background-clip: content-box;
}

    ::-webkit-scrollbar-thumb:hover {
        background: rgba(var(--gold-rgb), .45);
        background-clip: content-box;
    }

/* An image dropped in without its own sizing rule must never be wider than the screen.
   The background is what a reader sees in the moment before the file arrives: the box already
   holds its place, and left to the browser that reserved space is a white rectangle on a black
   page — the one flash of white on the whole site, and on a slow connection not a brief one.
   Painting it in the page's own black turns a loading image into a quiet empty frame. Every
   photograph is opaque and covers this; a transparent logo sits on the same black it already sat on. */
img,
video {
    max-width: 100%;
    height: auto;
    background-color: var(--black);
}

    /* Applied through odoardoScrollLock(), which pins the body at the current scroll offset —
       plain overflow: hidden never stopped iOS Safari from scrolling the page under an overlay. */
    body.no-scroll {
        position: fixed;
        left: 0;
        right: 0;
        width: 100%;
        overflow: hidden;
    }

/* Every link on this site names its own colour. The browser's default violet is never one of them,
   so a link that inherits — one written inside a sentence in the footer, an e-mail address the
   concierge prints — reads as the text around it instead of as a stray hyperlink. */
a {
    color: inherit;
}

::selection {
    background: var(--gold);
    color: var(--black);
}

sup {
    font-size: 1.0em;
    line-height: 0;
    vertical-align: super;
}

    /* The mark is a legal notice, not part of the name: half the surrounding size everywhere.
       Display headings tune it down further where the type is large — the sizes below are the
       only place ™ is sized, so nothing has to fight an inline style any more.

       The floor matters as much as the ratio. Half of a display heading is still a legible glyph,
       but half of the 10px type in a tooltip or a caption is four pixels of smudge that reads as a
       rendering fault rather than as a trademark — so the mark never goes under .58rem, whatever
       it sits beside. */
    sup.tm {
        font-size: max(.5em, .58rem);
        line-height: 0;
        font-weight: inherit;
        letter-spacing: 0;
        /* Letter-spacing is added *after* every character, the last one included, so on a tracked
           line — an eyebrow at 8px — the mark drifts away from the name it belongs to. Half of that
           tracking is given back: a context that letter-spaces its text declares how much with
           --tm-tracking. Three quarters, not all — the mark is raised and half-sized, so returning
           the full amount slid it onto the final letter, while half of it left the mark visibly
           adrift on an 8px eyebrow. Doing it in the type keeps any wrapper element out of the
           markup. */
        margin-left: calc(2px - var(--tm-tracking, 0px) * .75);
    }

/* The mark inside the house's own link, and it belongs here because this is where the mark is tuned.
   .home-product-link tracks its type at .22em, so without --tm-tracking declared the rule above falls back
   to its default and ADDS two pixels where it should give ground: on every page carrying this link — the
   home page, the segments, Art, Space — the ™ then stands a visible gap off the name it marks. Declaring the
   hook is the whole of it, and it is what every other tracked context does. The tracking is .22em in both
   files
   that declare this class and is overridden nowhere, so one value is the truth.

   The distance on the mark's other side is the arrow's gap, and that is set per context — so the
   correction for it is too, beside the gap it corrects. */
.home-product-link {
    --tm-tracking: .22em;
}

.container {
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    position: relative;
}

/* The site's one entrance movement: a short lift out of nothing, on the shared easing. It runs in CSS
   alone, so the first screen of a page never waits for a script, and the stagger is a custom property
   rather than a new keyframe per section. */
.odo-enter {
    opacity: 0;
    transform: translateY(22px);
    animation: odoEnter var(--motion) var(--ease-house) forwards;
    animation-delay: var(--odo-enter-delay, 0s);
}

@keyframes odoEnter {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .odo-enter {
        opacity: 1;
        transform: none;
        animation: none;
    }
}

/* #region Micro-interactions */
/* Every call to action ends in an arrow, and the arrow answers the hand: it travels a few pixels a
   beat after the pointer arrives and takes the gold. One rule covers them all, so a new CTA gets the
   behaviour by using the class rather than by copying declarations. */
.hero-cta span,
.pricing-cta span,
.home-link span,
.home-product-link > span:last-child,
.home-book-strip-cta span,
.home-places-ask span,
.footer-contact-link span:not(.footer-contact-icon) {
    display: inline-block;
    transition: transform var(--motion) var(--ease-house) .06s, color var(--motion) var(--ease-house);
}

.hero-cta:hover span,
.hero-cta:focus-visible span,
.pricing-cta:hover span,
.pricing-cta:focus-visible span,
.home-link:hover span,
.home-link:focus-visible span,
.home-product-link:hover > span:last-child,
.home-product-link:focus-visible > span:last-child,
.home-book-strip-cta:hover span,
.home-book-strip-cta:focus-visible span,
.home-places-ask:hover span,
.home-places-ask:focus-visible span {
    transform: translateX(4px);
    color: var(--gold);
}

/* The underlined CTA. At rest a white hairline; under the hand a gold line draws itself over it from
   the left, and on leaving withdraws to the right, so the line always travels the way the text reads.
   Two background layers rather than a border: a border can only change colour all at once. The
   position flips only while the gold layer has no width, so the flip is never seen. */
.hero-cta,
.home-product-link {
    border-bottom: 0;
    background:
        linear-gradient(var(--gold), var(--gold)) right bottom / 0 1px no-repeat,
        linear-gradient(var(--hairline-strong), var(--hairline-strong)) left bottom / 100% 1px no-repeat;
    color: var(--white);
    transition: background-size var(--motion) var(--ease-house), color var(--motion) var(--ease-house);
}

    .hero-cta:hover,
    .hero-cta:focus-visible,
    .home-product-link:hover,
    .home-product-link:focus-visible {
        background-position: left bottom, left bottom;
        background-size: 100% 1px, 100% 1px;
        color: var(--white);
    }

@media (prefers-reduced-motion: reduce) {
    .hero-cta span,
    .pricing-cta span,
    .home-link span,
    .home-product-link span,
    .home-book-strip-cta span,
    .home-places-ask span {
        transition: none;
        transform: none;
    }
}

/* .hoverable marks the things a visitor can actually press — links, buttons, labels — and nothing
   else. That rule is not cosmetic: layout.js grows the custom cursor over this class, so putting it
   on a card, a chart or a photograph makes the pointer promise an action the element does not have.
   It sat on twenty such elements, one of them a picture standing beside identical pictures that
   correctly left the cursor alone, which is how the promise was noticed. Anything that only wants
   the shared easing asks for it by its own name, the way the two price boxes below do.

   What it gives is deliberately small. One shared easing, so every state change on the site moves
   at the same speed and in the same curve; a short lift for the things shaped like cards; and a
   slow drift on the two photographs whose frames actually clip. Anything louder would fight the
   house's own quiet, and anything per-page would drift apart again. */
.hoverable,
.inv-box,
.b2b-pricing-box {
    transition: transform var(--motion) var(--ease-house),
                border-color var(--motion) var(--ease-house),
                background-color var(--motion) var(--ease-house),
                color var(--motion) var(--ease-house);
}

/* The two price boxes answer from their own class, not from .hoverable: nothing in them is pressed
   but the button inside. They do not lift or cast a shadow — an object on a table does not rise to
   meet the hand. The hairline brightens and the surface takes a breath of light instead. */
.inv-box:hover,
.inv-box:focus-visible,
.b2b-pricing-box:hover,
.b2b-pricing-box:focus-visible {
    border-color: var(--hairline-strong);
    background-color: var(--tint);
}

/* A photograph comes alive under the cursor rather than jumping at it: a slow approach of two and a
   half percent while its colour returns — and only where the frame clips it. .home-intro-image is
   deliberately excluded: its overflow is visible, so a scaled image would spill past its own edge. */
.home-anatomy-image img {
    transition: transform 1.8s var(--ease-house), filter var(--motion-slow) var(--ease-house);
}

.home-anatomy-image:hover img,
.home-anatomy-image:focus-visible img {
    transform: scale(1.025);
    filter: var(--photo-lifted);
}

@media (prefers-reduced-motion: reduce) {
    .hoverable,
    .inv-box,
    .b2b-pricing-box,
    .home-anatomy-image img {
        transition: none;
    }

    .home-anatomy-image:hover img {
        transform: none;
    }

    .hero-cta,
    .home-product-link {
        transition: none;
    }
}
/* #endregion */

.reveal-elem {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 1s var(--ease-house), transform 1s var(--ease-house);
}

/* Scroll reveals are the one effect that has to be driven by script. Where there is no scripting at
   all, the page shows its content instead of a column of blank sections. */
@media (scripting: none) {
    .reveal-elem,
    .immediate-reveal {
        opacity: 1;
        transform: none;
    }
}

    .reveal-elem.visible {
        opacity: 1;
        transform: translateY(0);
    }

/* One tooltip for every control whose whole meaning is an icon. The text sits in data-tooltip next
   to the control's aria-label, so what a screen reader hears and what a pointer reveals are written
   in the same place and cannot drift apart. Anchored above by default; data-tooltip-align="right"
   pins it to the right edge for controls that sit against one. */
[data-tooltip] {
    position: relative;
}

    [data-tooltip]::after {
        content: attr(data-tooltip);
        position: absolute;
        bottom: calc(100% + 10px);
        left: 50%;
        z-index: 1200;
        transform: translate(-50%, 4px);
        padding: .45rem .7rem;
        border: 1px solid var(--hairline-mid);
        background: rgba(5, 5, 5, .96);
        color: var(--white-soft);
        font-family: var(--font-sans);
        font-size: .62rem;
        font-weight: 300;
        letter-spacing: .08em;
        line-height: 1.3;
        text-align: center;
        text-transform: none;
        white-space: nowrap;
        opacity: 0;
        pointer-events: none;
        transition: opacity .25s var(--ease-house), transform .25s var(--ease-house);
    }

    [data-tooltip][data-tooltip-align="right"]::after {
        left: auto;
        right: 0;
        transform: translate(0, 4px);
    }

    [data-tooltip]:hover::after,
    [data-tooltip]:focus-visible::after {
        opacity: 1;
        transform: translate(-50%, 0);
    }

    [data-tooltip][data-tooltip-align="right"]:hover::after,
    [data-tooltip][data-tooltip-align="right"]:focus-visible::after {
        transform: translate(0, 0);
    }

/* A finger cannot hover, so the tooltip would only ever flash on tap — the label stays for
   assistive technology and nothing is drawn. */
@media (hover: none), (pointer: coarse) {
    [data-tooltip]::after {
        content: none;
    }
}

/* Keyboard users' first stop: invisible until focused, then a plain white bar above the header with the
   gold focus ring round it. Gold is never a surface. */
.skip-link {
    position: absolute;
    top: -100%;
    left: 1rem;
    z-index: 1300;
    padding: 1rem 1.4rem;
    background: var(--white);
    color: var(--black);
    font-family: var(--font);
    font-size: .72rem;
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    text-decoration: none;
}

    .skip-link:focus-visible {
        top: 1rem;
        outline: 1px solid var(--gold);
        outline-offset: 4px;
    }

#main-content:focus {
    outline: none;
}
/* #endregion */

/* #region Breadcrumbs */
/* The house's one breadcrumb trail, and it belongs here rather than in the journal's own stylesheet: kept
   in article.css it is a trail only one page can show. The design is the journal's — no other was ever
   needed. What stays in article.css is what belongs to that page alone, the entrance and the space beneath
   it. */
.breadcrumbs ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.55rem 0.85rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-family: var(--font-mono);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 3px;
}

.breadcrumbs li {
    display: inline-flex;
    align-items: center;
    gap: 0.85rem;
    min-width: 0;
    min-height: 36px;
}

    .breadcrumbs li + li::before {
        content: '';
        width: 10px;
        height: 1px;
        background: var(--white-ghost);
        flex: none;
    }

.breadcrumbs a {
    color: var(--text-muted);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color var(--motion-quick) var(--ease-house), border-color var(--motion-quick) var(--ease-house);
}

    /* Gold only under a hand: the trail answers when it is being used and is quiet the rest of
       the time, which is the whole of what it is for. */
    .breadcrumbs a:hover {
        color: var(--gold);
        border-bottom-color: var(--gold-line);
    }

.breadcrumbs [aria-current="page"] {
    display: block;
    max-width: 32ch;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--white-ghost);
}

@media (max-width: 700px) {
    .breadcrumbs ol {
        letter-spacing: 2px;
    }

    .breadcrumbs [aria-current="page"] {
        max-width: 20ch;
    }
}

/* A trail at the top of a hero, above the copy rather than inside it — the way the journal article
   opens. It goes inside .hero-content and is taken out of the flow there, which is the whole point:
   the hero section is a centred flex row and .hero-content a two-column grid, so a trail left in the
   flow adds a grid row, makes the block taller and — because it is centred — pushes the headline and
   the exhibit down. A page then looked different depending on whether it had a trail at all.
   Absolute, it hangs in the content's own top padding (8vh, 17vh on a phone), so the headline sits
   exactly where it sits on a hero with no trail, and the trail lands above it either way. */
.hero-content > .breadcrumbs {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
}

/* Under 900px the hero stacks and grows past the screen, so the block stops being centred and nothing
   is pushed down by a row added above the headline. There the trail goes back into the flow as the
   first row of the content: a long trail wraps onto a second or third line on a phone, and a band of
   fixed height reserved for one line let the wrapped rows fall over the eyebrow below. In the flow, the
   trail takes exactly the height it needs and the headline follows it. */
@media (max-width: 900px) {
    .hero-cinematic .hero-content:has(> .breadcrumbs) {
        padding-top: 13vh;
    }

    .hero-content > .breadcrumbs {
        position: relative;
        top: auto;
        /* The stacked hero is a grid whose row gap already separates the trail from the copy. */
        grid-column: 1 / -1;
    }
}
/* #endregion */

/* #region Global button */
.odo-button {
    display: inline-flex;
    justify-content: center;
    padding: 18px 30px;
    border: 1px solid var(--button-border);
    background: var(--button-layers);
    color: var(--white);
    font-family: var(--font);
    font-size: 0.68rem;
    font-weight: 400;
    letter-spacing: 0.2em;
    text-decoration: none;
    text-transform: uppercase;
    transition: background-size var(--motion) var(--ease-house), border-color var(--motion) var(--ease-house), color var(--motion) var(--ease-house), transform .2s var(--ease-house);
}

    /* Drawn, never filled (see --button-layers): the frame brightens, light rises from the foot and a
       gold line opens along the lower edge. Pressed, it gives a pixel. */
    .odo-button:hover,
    .odo-button:focus-visible {
        background-size: 100% 1px, 100% 100%;
        border-color: var(--button-border-hover);
        color: var(--white);
    }

    .odo-button:active {
        transform: translateY(1px);
    }

    /* A button that cannot be pressed has to look it, on every page — not only in Odoardo ID. */
    .odo-button:disabled {
        opacity: .38;
        pointer-events: none;
    }

/* The second-level door: the same size and the same shape, because it is the same kind of act —
   only not the one the page is asking for. A fainter frame and softer letters, so a section can carry
   two without them competing, and so the quieter one is still a button rather than a line of small
   capitals nobody reads as clickable. It answers the hand the same way. */
.odo-button--quiet {
    border-color: var(--hairline-strong);
    color: var(--white-soft);
}

    .odo-button--quiet:hover,
    .odo-button--quiet:focus-visible {
        border-color: var(--button-border);
        color: var(--white);
    }
/* #endregion */

/* #region Global select — the site's one dropdown */
/* Every <select> on the site is drawn here rather than by the operating system — see select.js.
   The select underneath is still the form's answer, so everything in this region is presentation
   and nothing in it is state. With scripting off no picker is built and the select shows as it
   always did, which is why each area still styles its own <select> as well. */
.odo-picker {
    position: relative;
    display: block;
    width: 100%;
}

/* Hidden, not removed. A form refused by the server still calls focus() on the field it wants
   corrected, and a control taken out of the layout has nowhere to be focused — so it is clipped to
   nothing instead and select.js passes that focus on to the button. */
.odo-picker-native {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    opacity: 0;
    clip-path: inset(50%);
    pointer-events: none;
}

/* The same box every field on the site wears, so a row of fields keeps one height and one border.
   An area whose fields are cut differently — the book's offer card — states its own metrics for
   this class beside the ones it states for its <select>. */
.odo-picker-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    min-height: 3.4rem;
    padding: 1.05rem 1.1rem;
    border: 1px solid var(--line);
    border-radius: 0;
    background: rgba(245, 245, 245, .018);
    color: var(--white);
    cursor: pointer;
    font-family: var(--font);
    font-size: 1rem;
    letter-spacing: normal;
    text-align: left;
    text-transform: none;
    transition: border-color .3s var(--ease-house);
}

    /* The one thing the native control drew that this one has to draw itself. Set on the pseudo
       element so it turns without the label moving with it. */
    .odo-picker-toggle::after {
        content: "";
        flex: none;
        width: .42rem;
        height: .42rem;
        border-right: 1px solid var(--text-muted);
        border-bottom: 1px solid var(--text-muted);
        transform: translateY(-.14rem) rotate(45deg);
        transition: transform .3s var(--ease-house), border-color .3s var(--ease-house);
    }

    .odo-picker-toggle:hover,
    .odo-picker-toggle:focus-visible {
        border-color: var(--gold);
        outline: none;
    }

    /* The chosen answer, on the span select.js writes it into. Its own colour rather than the
       button's, so that nothing has been answered yet stays legible as that even on a form whose
       area states a colour of its own for its fields. */
    .odo-picker-label {
        /* A flex item does not shrink below its own text unless it is told it may, and some of these
           answers are a whole order line long. */
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

        .odo-picker-label.is-empty {
            color: var(--text-muted);
        }

    .odo-picker-toggle:disabled {
        color: var(--text-muted);
        cursor: not-allowed;
        opacity: 1;
    }

    .odo-picker-toggle[aria-expanded="true"] {
        border-color: var(--gold);
    }

        .odo-picker-toggle[aria-expanded="true"]::after {
            border-color: var(--gold);
            transform: translateY(.1rem) rotate(-135deg);
        }

.odo-picker-panel {
    position: absolute;
    z-index: 40;
    top: calc(100% + .4rem);
    right: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    padding: .6rem;
    border: 1px solid var(--hairline);
    /* Opaque: the list stands over the field below it, and a translucent panel would show the row
       it covers straight through the names it is offering. */
    background: var(--surface-card, #101010);
    box-shadow: 0 24px 60px rgba(5, 5, 5, .45);
}

    /* Stated because the rule above it sets a display of its own, and a display beats the browser's
       own [hidden] rule every time. Without this line the list is drawn open on load and the button
       that hides it appears to do nothing at all — which is exactly what it did. */
    .odo-picker-panel[hidden] {
        display: none;
    }

    .odo-picker-panel:focus {
        outline: none;
    }

/* The list takes the focus when there is no search box to take it, and the walked option is already
   drawn — a second ring around the whole list would only say the same thing twice, in the wrong place. */
.odo-picker-list:focus {
    outline: none;
}

.odo-picker-search {
    width: 100%;
    margin-bottom: .5rem;
    padding: .7rem .8rem;
    border: 1px solid var(--line);
    border-radius: 0;
    background: rgba(245, 245, 245, .018);
    color: var(--white);
    font-family: var(--font);
    font-size: .92rem;
}

    .odo-picker-search:focus {
        border-color: var(--gold);
        outline: none;
    }

    /* Below 16px iOS Safari zooms the page on focus and never zooms back out — and this box is
       focused the moment a long list is opened, which is the worst place on the site for that. */
    @media (max-width: 900px) {
        .odo-picker-search {
            font-size: 1rem;
        }
    }

.odo-picker-list {
    max-height: 15rem;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    list-style: none;
}

.odo-picker-option {
    padding: .58rem .8rem;
    color: var(--text-muted);
    cursor: pointer;
    font-size: .92rem;
    transition: color .2s var(--ease-house), background-color .2s var(--ease-house);
}

    /* One highlight for the pointer and for the arrow keys, so somebody who started typing and
       somebody who started pointing are looking at the same thing. */
    .odo-picker-option:hover,
    .odo-picker-option.is-active {
        background: rgba(var(--gold-rgb), .08);
        color: var(--white);
    }

    .odo-picker-option[aria-selected="true"] {
        color: var(--gold);
    }

.odo-picker-empty {
    margin: .4rem 0 .2rem;
    padding: 0 .8rem;
    color: var(--text-muted);
    font-size: .82rem;
}
/* #endregion */

/* #region Background & cursor */
.noise-overlay {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 9998;
    opacity: 0.06;
    background: url('data:image/svg+xml,%3Csvg viewBox%3D%220 0 512 512%22 xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cfilter id%3D%22noiseFilter%22%3E%3CfeTurbulence type%3D%22fractalNoise%22 baseFrequency%3D%221.8%22 numOctaves%3D%224%22 stitchTiles%3D%22stitch%22/%3E%3C/filter%3E%3Crect width%3D%22100%25%22 height%3D%22100%25%22 filter%3D%22url(%23noiseFilter)%22/%3E%3C/svg%3E');
    background-size: 256px 256px;
}

/* The dot is moved by `transform` alone — layout.js never writes `left`/`top` any more. Those two are
   layout properties: every pointer move re-laid out and repainted a fixed element, hundreds of times a
   second on a mouse that reports faster than the screen redraws, and on a machine with nothing to
   spare that is exactly the stutter the cursor was blamed for. A transform is composited, so the same
   movement costs one layer being placed. `will-change` gives it that layer up front rather than
   letting the browser discover it is needed on the first move. */
.custom-cursor {
    position: fixed;
    top: 0;
    left: 0;
    width: 8px;
    height: 8px;
    background-color: var(--gold);
    pointer-events: none;
    z-index: 9999;
    transform: translate3d(0, 0, 0) translate(-50%, -50%);
    transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1), height 0.3s cubic-bezier(0.16, 1, 0.3, 1), background-color 0.3s, opacity 0.5s;
    mix-blend-mode: difference;
    opacity: 0;
    will-change: transform;
}

    .custom-cursor.hover {
        width: 50px;
        height: 50px;
        background-color: transparent;
        border: 1px solid var(--gold);
    }

@media (hover: none), (pointer: coarse) {
    * {
        cursor: auto !important;
    }

    .custom-cursor {
        display: none !important;
    }
}
/* #endregion */

/* #region Lean — what a machine that cannot hold a frame stops being asked for
   `odo-lean` is set on <html> by site.js, and only for a machine that has been measured and found
   short of frames; see the block there for how the verdict is reached. Nothing in this region fires
   on a machine that keeps up, so a fast device renders the site exactly as it did before.

   Every rule here undoes the same kind of cost: an effect the compositor has to redo on every frame
   rather than once. They are written here, beside the cursor and the photograph tokens they answer
   to, rather than scattered through the page stylesheets that happen to use them — a page adding a
   filtered film later gets the lean answer without knowing this region exists. */

/* The blend mode is the expensive half of the cursor, and it is expensive for the whole page rather
   than for the dot: an element that blends with what is behind it has to be able to read back what is
   already drawn under it, which takes every film on the page off the compositor's own video path and
   puts each decoded frame through the full paint pipeline instead. On black — which is the ground this
   site is printed on — difference and normal draw the same gold dot anyway. */
html.odo-lean .custom-cursor {
    mix-blend-mode: normal;
    transition: opacity .5s;
}

/* A filter over a playing film is not computed once: it is computed for every frame that is decoded, at
   the film's own frame rate, for as long as it runs. No film on the site carries one — the workshop
   films have their grade in the files — and this rule is the net for one that does. */
html.odo-lean video {
    filter: none !important;
    transition: none !important;
}

/* The grain is a full-window layer standing above everything, films included, at six per cent. It is
   the cheapest thing here to give up and the least missed: at that opacity what goes is a texture
   nobody can name, and what comes back is the films' own compositing path. */
html.odo-lean .noise-overlay {
    display: none;
}
/* #endregion */

/* #region Header */
body > header {
    position: fixed;
    top: 0;
    width: 100%;
    /* The page runs under the notch (viewport-fit=cover), so a phone held sideways takes its inset. The
       gutter itself is the inner row's, below. */
    padding: 25px env(safe-area-inset-right, 0px) 25px env(safe-area-inset-left, 0px);
    z-index: 900;
    background: rgba(5, 5, 5, 0.85);
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    border-bottom: 1px solid transparent;
    transition: border-color var(--motion) var(--ease-house);
}

    body > header.scrolled {
        border-bottom-color: var(--hairline);
    }

/* The masthead's row is measured the way every section's is — min(90vw, the content measure), centred —
   so the wordmark and „Menu" stand on the same two edges as the page under them and the account's tab
   row. A padding of 5vw on each side measured differently: vw counts the scrollbar and a padded box does
   not, and the right edges parted by half a scrollbar on every laptop. */
body > header > .header-inner {
    width: min(90vw, 100%, var(--section-content-max));
    max-width: none;
}

.header-inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* No ™ in the masthead: the mark is quiet; the ™ lives on product names in running text.
   The wordmark is the drawing at /img/house/wordmark.svg, white, with its tracking cut into the curves —
   see the note in _Layout.cshtml. Gold is the house's accent and it used to carry the mark as well, which
   made every page open on the accent instead of on the name. The height is the mark's cap height: the file
   is drawn in Montserrat's own units, 720 tall for a 700-unit cap, so the drawing matches type of size S at
   0.72 × S — never at S itself, which is 39 % too large. The masthead was 18px type, hence 13px. */
.logo {
    display: inline-block;
    line-height: 0;
    text-decoration: none;
    transition: opacity var(--motion-quick) var(--ease-house);
}

    .logo img {
        display: block;
        width: auto;
        height: 13px;
    }

    .logo:hover {
        opacity: 0.7;
    }

.header-controls {
    display: flex;
    align-items: center;
    gap: 40px;
}

.lang-switch {
    display: flex;
    gap: 15px;
    font-family: var(--font-mono);
    font-size: .7rem;
    font-weight: 300;
    text-transform: uppercase;
    letter-spacing: 2px;
}

    .lang-switch a {
        color: var(--text-muted);
        text-decoration: none;
        transition: color var(--motion-quick) var(--ease-house);
        /* Same trick as .account-link: a finger-sized hit area without moving the visual layout. */
        display: inline-block;
        padding: 15px 6px;
        margin: -15px -6px;
    }

        .lang-switch a.active, .lang-switch a:hover {
            color: var(--gold);
        }

.account-link {
    position: relative;
    color: var(--white);
    font-family: var(--font);
    font-size: .7rem;
    letter-spacing: 4px;
    text-decoration: none;
    text-transform: uppercase;
    transition: color var(--motion) var(--ease-house);
    /* Same trick as .menu-trigger: a finger-sized hit area without moving the visual layout. */
    padding: 15px 10px;
    margin: -15px -10px;
}

.menu-trigger {
    position: relative;
    background: none;
    border: none;
    color: var(--white);
    font-family: var(--font);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 4px;
    outline: none;
    transition: color var(--motion) var(--ease-house);
    padding: 15px 10px;
    /* The right margin also takes back the tracking after the last letter, so the word — not the
       space after it — ends on the page's edge. */
    margin: -15px calc(-10px - 4px) -15px -10px;
}

    /* White at rest; under the hand the word takes the gold and a hairline draws itself beneath it from
       the left. The line is set inside the padded hit area, so it sits under the letters, and it stops
       short of the tracking after the last one. */
    .account-link::after,
    .menu-trigger::after {
        content: '';
        position: absolute;
        left: 10px;
        right: calc(10px + 4px);
        bottom: 11px;
        height: 1px;
        background: var(--gold);
        transform: scaleX(0);
        transform-origin: left;
        transition: transform var(--motion) var(--ease-house);
        pointer-events: none;
    }

    .account-link:hover,
    .account-link:focus-visible,
    .menu-trigger:hover {
        color: var(--gold);
    }

        .account-link:hover::after,
        .account-link:focus-visible::after,
        .menu-trigger:hover::after {
            transform: scaleX(1);
        }

    .menu-trigger:focus-visible,
    .close-menu:focus-visible {
        outline: 1px solid var(--gold-mid);
        outline-offset: 4px;
    }
/* #endregion */

/* #region Menu overlay */
.menu-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    background-color: var(--black);
    z-index: 950;
    display: flex;
    flex-direction: column;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-20px);
    transition: all 0.5s var(--ease-house);
    padding: 40px 5vw;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

    .menu-overlay.active {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
    }

.menu-header {
    display: flex;
    justify-content: flex-end;
    width: 100%;
}

.close-menu {
    background: none;
    border: none;
    color: var(--white);
    font-family: var(--font);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 4px;
    outline: none;
    transition: color var(--motion) var(--ease-house);
    padding: 15px 10px;
    margin: -15px -10px;
}

    .close-menu:hover {
        color: var(--gold);
    }

.menu-split {
    display: flex;
    width: 100%;
    height: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding-top: 8vh;
    align-items: center;
}

.menu-left {
    flex: 1.5;
    display: flex;
    flex-direction: column;
    gap: 3.5vh;
}

.menu-item-mega {
    display: flex;
    align-items: flex-start;
    gap: 20px;
    text-decoration: none;
    transition: transform var(--motion) var(--ease-house);
}

    @media (hover: hover) {
        .menu-item-mega:hover {
            transform: translateX(20px);
        }
    }

    /* The number is the item's one accent, and it takes the gold only while the item is under the hand. */
    .menu-item-mega .m-num {
        font-family: var(--font-mono);
        font-weight: 300;
        font-size: 0.8rem;
        color: rgba(245, 245, 245, .5);
        margin-top: 10px;
        transition: color var(--motion) var(--ease-house);
    }

    .menu-item-mega:hover .m-num,
    .menu-item-mega:focus-visible .m-num,
    .menu-item-mega[aria-current] .m-num {
        color: var(--gold);
    }

.m-text {
    display: flex;
    flex-direction: column;
}

.menu-item-mega h3 {
    font-family: var(--font-display);
    font-weight: 300;
    font-size: clamp(2rem, 3.5vw, 4.5rem);
    color: var(--white-soft);
    transition: color var(--motion) var(--ease-house);
    line-height: 1.1;
}

    .menu-item-mega h3 sup.tm,
    .menu-item-mega h3 sup {
        font-size: .28em;
        vertical-align: super;
        opacity: .55;
        letter-spacing: 0;
    }

.menu-item-mega:hover h3 {
    color: var(--white);
}

.m-tag {
    font-family: var(--font);
    font-size: 0.55rem;
    color: var(--white);
    text-transform: uppercase;
    letter-spacing: 3px;
    margin-top: 8px;
    opacity: 0.5;
    transition: all var(--motion) var(--ease-house);
    display: block;
}

/* No hover on touch: the category caption stays at full legibility. */
@media (hover: none) {
    .m-tag {
        opacity: 1;
    }
}

.menu-item-mega:hover .m-tag {
    opacity: 1;
    letter-spacing: 4px;
}

.menu-right {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6vh;
    border-left: 1px solid var(--line);
    padding-left: 5vw;
    height: 60%;
}

.menu-label {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 5px;
    color: rgba(245, 245, 245, .5);
    margin-bottom: 2vh;
    display: inline-block;
}

.menu-sub-links {
    display: flex;
    flex-direction: column;
    gap: 15px;
}

    .menu-sub-links a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        margin-block: -6px;
        color: var(--white-soft);
        text-decoration: none;
        font-size: 1.1rem;
        transition: color var(--motion-quick) var(--ease-house), border-color var(--motion-quick) var(--ease-house);
    }

        .menu-sub-links a:hover {
            color: var(--white);
        }

    .menu-sub-links .menu-filmable-link {
        display: grid;
        gap: 5px;
        margin: .8vh 0;
        padding: .9rem 1rem;
        border: 1px solid var(--hairline-mid);
        background: linear-gradient(90deg, var(--tint), transparent);
        color: var(--white);
    }

.menu-filmable-featured {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .55rem;
    padding: 1.35rem 1.5rem;
    overflow: hidden;
    border: 1px solid var(--hairline-mid);
    background: linear-gradient(135deg, var(--tint), transparent 65%);
    color: var(--white);
    text-decoration: none;
    transition: border-color var(--motion) var(--ease-house), background var(--motion) var(--ease-house);
}

    .menu-filmable-featured::before {
        content: '';
        position: absolute;
        inset: 0;
        z-index: 0;
        background: linear-gradient(120deg, transparent, rgba(var(--gold-rgb),.16), transparent);
        opacity: 0;
        transition: opacity var(--motion) var(--ease-house);
    }

    .menu-filmable-featured span {
        position: relative;
        z-index: 1;
    }

        .menu-filmable-featured span:first-child {
            display: flex;
            align-items: center;
            gap: .6rem;
            font-family: var(--font-display);
            font-size: 1.35rem;
            font-weight: 300;
        }

            .menu-filmable-featured span:first-child::after {
                content: '\2192';
                color: var(--white-soft);
                font-size: 1rem;
                transition: transform var(--motion) var(--ease-house) .06s, color var(--motion) var(--ease-house);
            }

        .menu-filmable-featured span.menu-filmable-open {
            color: rgba(245, 245, 245, .5);
            transition: color var(--motion) var(--ease-house);
            font-family: var(--font-mono);
            font-size: .58rem;
            letter-spacing: .22em;
            text-transform: uppercase;
        }

    .menu-filmable-featured:hover,
    .menu-filmable-featured:focus-visible {
        border-color: var(--gold);
        background: linear-gradient(135deg, var(--gold-subtle), rgba(var(--gold-rgb),.05) 65%);
    }

        .menu-filmable-featured:hover::before {
            opacity: 1;
        }

        .menu-filmable-featured:hover span:first-child::after,
        .menu-filmable-featured:focus-visible span:first-child::after {
            transform: translateX(4px);
            color: var(--gold);
        }

        .menu-filmable-featured:hover span.menu-filmable-open,
        .menu-filmable-featured:focus-visible span.menu-filmable-open {
            color: var(--gold);
        }

.menu-filmable-link span.menu-filmable-open {
    color: rgba(245, 245, 245, .5);
    font-family: var(--font-mono);
    font-size: .5rem;
    letter-spacing: .22em;
    text-transform: uppercase;
    transition: color var(--motion-quick) var(--ease-house);
}

.menu-sub-links .menu-filmable-link:hover,
.menu-sub-links .menu-filmable-link:focus-visible {
    border-color: var(--gold);
    color: var(--white);
}

    .menu-sub-links .menu-filmable-link:hover span.menu-filmable-open,
    .menu-sub-links .menu-filmable-link:focus-visible span.menu-filmable-open {
        color: var(--gold);
    }

.menu-lang {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    font-family: var(--font-mono);
    font-size: .7rem;
    font-weight: 300;
    text-transform: uppercase;
    letter-spacing: 2px;
}

    .menu-lang a {
        color: var(--text-muted);
        text-decoration: none;
        transition: color var(--motion-quick) var(--ease-house);
        padding: 15px 4px;
        margin: -15px -4px;
    }

        .menu-lang a.active, .menu-lang a:hover {
            color: var(--gold);
        }
/* #endregion */

/* #region Footer — shell */
/* The footer opens on the same measure as every other section rather than on 15vh of its own. That value is
   the largest single gap on the site and the only one tied to the viewport's height, so whatever ends above
   it — the book strip most visibly — appears to float in a band of nothing. */
footer {
    background-color: var(--black);
    padding: var(--section-space) max(5vw, env(safe-area-inset-right, 0px)) calc(4vh + env(safe-area-inset-bottom, 0px)) max(5vw, env(safe-area-inset-left, 0px));
    border-top: 1px solid var(--line);
    position: relative;
    z-index: 5;
    overflow: hidden;
}

.footer-watermark {
    position: absolute;
    bottom: 0;
    /* The mark itself, laid across the foot at 1.2 % — a texture rather than a thing to read. The name opens
       and closes on an O, and each edge of the page cuts its O exactly through the middle. In wordmark.svg the
       viewBox starts at x 54 and is 8003 wide, the first O is centred at 419 and the last at 7693, 7274 apart:
       so the drawing is 8003/7274 of the footer wide and starts (419 − 54)/7274 of it to the left. Percentages
       of the footer, not vw, which on Windows counts the scrollbar. */
    left: calc(-100% * 365 / 7274);
    width: calc(100% * 8003 / 7274);
    max-width: none;
    height: auto;
    opacity: 0.012;
    pointer-events: none;
    z-index: 0;
}
/* #endregion */

/* #region Footer — clocks */
.footer-clocks-wrapper {
    width: 100%;
    padding-bottom: 8vh;
    margin-bottom: 8vh;
    position: relative;
    z-index: 1;
}

/* Eight cities in one row, in the order the working day travels. The dial and the label scale with
   the viewport so the row holds together down to the breakpoints below, where it folds to four and
   then to two. */
.footer-clocks {
    display: grid;
    grid-template-columns: repeat(8, minmax(0, 1fr));
    gap: clamp(.5rem, 1.2vw, 1.5rem);
    width: 100%;
}

.clock-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.clock-city {
    font-family: var(--font-mono);
    font-weight: 300;
    /* Ten pixels at the least: the floor used to be eight, which is a size nobody reads. */
    font-size: clamp(.62rem, .62vw, .72rem);
    text-transform: uppercase;
    letter-spacing: clamp(1px, .3vw, 4px);
    text-align: center;
    white-space: nowrap;
    color: var(--text-muted);
}

.analog-clock {
    width: clamp(44px, 5.4vw, 80px);
    aspect-ratio: 1;
    position: relative;
    border-radius: 50%;
    border: 1px solid var(--hairline-mid);
    margin: 5px 0;
    transition: border-color var(--motion) var(--ease-house);
}

.clock-item:hover .analog-clock {
    border-color: var(--gold-hover);
}

/* The dial is drawn in white; its pivot is the one gold point, and the hands take the gold with the ring
   while the city is under the hand. */
.clock-hand {
    position: absolute;
    bottom: 50%;
    left: 50%;
    transform-origin: bottom;
    background-color: var(--white-soft);
    transform: translateX(-50%) rotate(0deg);
    transition: background-color var(--motion) var(--ease-house);
}

.clock-item:hover .clock-hand {
    background-color: var(--gold);
}

.hand-hour {
    width: 1px;
    height: 25%;
}

.hand-min {
    width: 1px;
    height: 42%;
}

.analog-clock::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3px;
    height: 3px;
    background-color: var(--gold);
    border-radius: 50%;
    transform: translate(-50%, -50%);
}

.clock-digital {
    font-family: var(--font-display);
    font-size: clamp(.85rem, 1.1vw, 1.1rem);
    color: var(--white-bright);
    transition: color var(--motion) var(--ease-house);
}

.clock-item:hover .clock-digital {
    color: var(--gold);
}
/* #endregion */

/* #region Footer — contact */
/* Three columns of equal standing: how to reach us, and the two lists of where to go. The letter is
   not a fourth thing inside the first column — it has a band of its own below. */
.footer-grid-luxury {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr;
    gap: 4vw;
    margin-bottom: 5vh;
    position: relative;
    z-index: 1;
}

.footer-newsletter {
    padding-right: 4vw;
}

/* The letter's own band, full width, separated from the columns by a rule: the copy on the left,
   the field on the right, so the form reads as one gesture rather than as a stack of four
   paragraphs in a narrow column. */
/* Only a rule above. The one below sat a few pixels from the footer's own bottom border and read as
   a doubled line. */
/* Its own band on its own ground, between the page and the footer. Inside the footer it takes the footer's
   background and the footer's padding, so nothing says where one ends and the other begins. A flat lighter
   ground and the rule above it say it — flat, because the house is flat: a gradient wash here is the only lit
   surface on the page. It holds one line of copy and one field, so it is paid for at a band's depth, not a
   section's. The footer draws its own top rule, so this one needs none below. */
.letters-band {
    position: relative;
    z-index: 1;
    padding: clamp(2.4rem, 4.5vh, 3.4rem) 0;
    border-top: 1px solid var(--hairline-mid);
    background: var(--black-soft);
}

    /* .container carries no side gutter; the band takes the house's measure like every other one. */
    .letters-band > .container {
        width: min(90vw, var(--section-content-max));
        max-width: none;
        margin-inline: auto;
    }

/* Centred, not top-aligned: the name of the letter belongs on the same line as the field a reader
   is about to type into, and align-items: start pushed it a whole heading's height above it. */
.footer-letter {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
    align-items: center;
}

.footer-letter-copy {
    min-width: 0;
}

.footer-letter-action {
    min-width: 0;
}

@media (max-width: 900px) {
    .footer-letter {
        grid-template-columns: 1fr;
        gap: 1.6rem;
    }
}

    .footer-newsletter .footer-contact-title {
        font-family: var(--font-display);
        font-weight: 300;
        font-size: clamp(1.9rem, 7vw, 2.5rem);
        color: var(--white);
        margin-bottom: 1.5vh;
    }

    /* 4vh here opened a gap the height of the contact block itself between the lead and the two
       lines it introduces — on a tall screen they read as two unrelated blocks. */
    .footer-newsletter p {
        font-size: 1rem;
        color: var(--text-muted);
        line-height: 1.7;
        margin-bottom: 2.2vh;
        max-width: 450px;
    }

/* Odoardo Letters™. The selectors are single-class: the form stands in a band of its own, outside the
   contact column, so it has nothing to outrank — a nested ".footer-newsletter p" is what forces
   specificity here. The band's ground and the rule above it belong to .letters-band further up, and the
   band itself stands above the footer rather than inside it. */
.footer-letter-title {
    color: var(--white);
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 2.4vw, 2rem);
    font-weight: 300;
    letter-spacing: 0;
    margin-bottom: 1vh;
}

.footer-letter-lead {
    color: var(--text-muted);
    font-size: 1rem;
    line-height: 1.7;
    margin: 0;
    max-width: 46ch;
}

.footer-letter-field {
    display: flex;
    gap: 10px;
    align-items: stretch;
    flex-wrap: wrap;
}

    /* The checkout's field, like every other one on the site — see .chk-field input. */
    .footer-letter-field input {
        flex: 1 1 220px;
        min-width: 0;
        padding: 1.05rem 1.1rem;
        border: 1px solid var(--line);
        background: rgba(245, 245, 245, .018);
        color: var(--white);
        font-family: var(--font);
        font-size: 1rem;
    }

        .footer-letter-field input:focus {
            border-color: var(--gold);
            outline: none;
        }

    .footer-letter-field button {
        padding: 12px 22px;
        border: 1px solid var(--hairline-strong);
        background: transparent;
        color: var(--white);
        cursor: pointer;
        font-family: var(--font);
        font-size: 0.62rem;
        letter-spacing: 0.2em;
        text-transform: uppercase;
        transition: border-color var(--motion-quick) var(--ease-house), color var(--motion-quick) var(--ease-house);
    }

        .footer-letter-field button:hover,
        .footer-letter-field button:focus-visible {
            border-color: var(--gold);
            color: var(--gold);
        }

        .footer-letter-field button:disabled {
            cursor: default;
            opacity: 0.5;
        }

/* The small print under the field: the consent clause and the note as one paragraph. */
.footer-letter-consent {
    font-size: 0.72rem;
    line-height: 1.6;
    margin: 1.5vh 0 0;
    color: var(--white-faint);
    max-width: 60ch;
}

/* The answer sits right under the field, so it is spaced off the input rather than off the note
   below it. Hidden until there is something to say: a line reserving its own height holds the form
   apart for the whole time there is nothing to report. */
.footer-letter-message {
    margin: .7rem 0 0;
    color: var(--white);
    font-size: 0.8rem;
    line-height: 1.5;
}

    /* A refused address is an error and is coloured like one. In --white-soft, the grey of the note
       below it, the one line the visitor has to act on is the quietest thing in the form. */
    .footer-letter-message.is-error {
        color: var(--error);
    }

    /* The entrance: a short rise, replayed by layout.js on every answer. */
    .footer-letter-message.is-shown {
        animation: footerLetterMessage .32s var(--ease-house) both;
    }

@keyframes footerLetterMessage {
    from {
        opacity: 0;
        transform: translateY(-.35rem);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* The field itself answers too: a rejected address must be visible as the thing to fix, not only
   described in a line beneath it. */
.footer-letter.has-error .footer-letter-field input {
    border-color: var(--error);
}

@media (prefers-reduced-motion: reduce) {
    .footer-letter-message.is-shown {
        animation: none;
    }
}

/* A honeypot: it has to exist in the tree and be fillable by a machine while not existing for a person —
   hence moving it off screen rather than display:none, which some bots recognise and skip. */
.footer-letter-trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.footer-contact-details {
    display: flex;
    flex-direction: column;
    gap: 1.5vh;
}

.footer-contact-link {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--white);
    text-decoration: none;
    font-size: 1rem;
    letter-spacing: 0.5px;
    transition: color var(--motion-quick) var(--ease-house);
}

    .footer-contact-link:hover,
    .footer-contact-link:focus-visible {
        color: var(--gold);
    }

        .footer-contact-link:hover .footer-contact-icon,
        .footer-contact-link:focus-visible .footer-contact-icon {
            color: var(--gold);
        }

/* A fixed square, because the marks are drawn rather than typed. 1.4em reserves room for a system glyph of
   unpredictable advance; an SVG has the size we give it, and giving both the same square is what makes the
   two lines align. */
.footer-contact-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    color: rgba(245, 245, 245, .6);
    transition: color var(--motion-quick) var(--ease-house);
}

    .footer-contact-icon svg {
        display: block;
        width: 100%;
        height: 100%;
    }

/* #endregion */

/* #region Footer — columns & links */
.footer-col .footer-col-title {
    font-family: var(--font-mono);
    font-weight: 300;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    color: rgba(245, 245, 245, .5);
    margin-bottom: 3vh;
}

.footer-col ul {
    list-style: none;
}

    .footer-col ul li {
        margin-bottom: 2vh;
    }

.footer-col a {
    font-size: 0.85rem;
    color: var(--text-muted);
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 2px;
    transition: color var(--motion-quick) var(--ease-house);
    display: inline-block;
    /* A finger-sized hit area without changing the rhythm of the list. */
    padding: 12px 0;
    margin: -12px 0;
}

    .footer-col a:hover {
        color: var(--gold);
    }

.footer-social-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 18px;
    flex-shrink: 0;
}

    .footer-social-row .social-tiles__item {
        display: flex;
        color: var(--text-muted);
        transition: color var(--motion-quick) var(--ease-house);
    }

        .footer-social-row .social-tiles__item svg {
            width: 15px;
            height: 15px;
            color: currentColor;
        }

    /* 15px glyphs are fine to look at, not to tap — pad the tile itself up to a finger-sized target. */
    .footer-social-row .social-tiles__item {
        padding: 12px;
        margin: -12px -4px;
    }

            /* The glyphs are the house's own paths with no fill of their own, so they take the tile's colour and
               follow it on hover. Stated once here rather than on each of the seven paths. */
            .footer-social-row .social-tiles__item svg path {
                fill: currentColor;
            }

        .footer-social-row .social-tiles__item:hover,
        .footer-social-row .social-tiles__item:focus-visible {
            color: var(--gold);
        }

/* The registration line art. 206 § 1 KSH requires on the company's own website. It closes the footer —
   last line on the page, and the quietest thing on it, because it is a disclosure rather than something
   a reader came for. It wraps rather than truncating: every element of it has to stay readable, which is
   also why the size and contrast stop here. Smaller or fainter and the data is present without being
   carried, which is the one thing this line may not be. */
.footer-registration {
    position: relative;
    z-index: 1;
    padding-top: 1.6vh;
}

    .footer-registration p {
        margin: 0;
        font-size: 0.58rem;
        line-height: 1.75;
        letter-spacing: 0.02em;
        color: rgba(245, 245, 245, .24);
    }

.footer-disclaimer {
    position: relative;
    z-index: 1;
    padding-top: 1.4vh;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4vw;
}

    .footer-disclaimer p {
        margin: 0;
        font-size: 0.72rem;
        line-height: 1.6;
        letter-spacing: 0.02em;
        text-transform: none;
        color: var(--text-muted);
        max-width: 86ch;
    }

        /* Where a line has room for a whole statement, each statement takes one. Below that the
           spans go back to running text — three orphaned half-lines are worse than a paragraph. */
        @media (min-width: 900px) {
            .footer-disclaimer p > span {
                display: block;
            }
        }

        /* The transparency link is part of that sentence and carries its colour, with an underline
           to say it leads somewhere. */
        .footer-disclaimer p a {
            color: var(--white-soft);
            text-decoration: underline;
            text-underline-offset: 2px;
            transition: color var(--motion-quick) var(--ease-house);
        }

            .footer-disclaimer p a:hover,
            .footer-disclaimer p a:focus-visible {
                color: var(--gold);
            }

.footer-bottom {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .5rem 2rem;
    padding-top: 4vh;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    color: var(--text-muted);
    position: relative;
    z-index: 1;
}

    .footer-bottom::before {
        content: '';
        position: absolute;
        top: 0;
        left: calc(50% - 50vw);
        right: calc(50% - 50vw);
        height: 1px;
        background: var(--white-subtle);
    }

.footer-legal-links {
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--motion-quick) var(--ease-house);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 25px;
}

    /* The copyright is a sentence, not a row of items: it keeps the colour and type of its siblings
       but flows as text, so the space after the year is a word space. */
    .footer-legal-copy {
        display: block;
    }

        /* The separator between the company and the creator beside it. Both are part of the same
           line, so the dot gets the sentence's own spacing rather than the 25px the row of legal
           links uses between things a reader picks from. */
        .footer-legal-dot {
            margin: 0 .45rem;
            color: var(--text-muted);
        }

    .footer-legal-links a {
        color: var(--text-muted);
        text-decoration: none;
        transition: color var(--motion-quick) var(--ease-house);
        display: inline-flex;
        align-items: center;
        min-height: 44px;
        margin-block: -12px;
    }

        .footer-legal-links a:hover {
            color: var(--gold);
        }
/* #endregion */

/* #region Responsive */
@media (max-width: 1100px) {
    .product-card:nth-child(3n+2) {
        margin-top: 0;
    }

    .product-card:nth-child(even) {
        margin-top: 8vh;
    }

    .footer-grid-luxury {
        grid-template-columns: repeat(2, 1fr);
        gap: 6vw;
    }

    .footer-newsletter {
        grid-column: span 2;
        padding-right: 0;
    }

    .menu-split {
        flex-direction: column;
        gap: 5vh;
        padding-top: 10vh;
        height: auto;
    }

    .menu-right {
        border-left: none;
        padding-left: 0;
        border-top: 1px solid var(--line);
        padding-top: 5vh;
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: space-between;
        gap: 4vh 3vw;
        width: 100%;
    }

    /* Eight across stops fitting here: two rows of four, still even. */
    .footer-clocks {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 4vh 3vw;
    }
}

@media (max-width: 780px) {
    .lang-switch {
        display: none;
    }

    .header-controls {
        gap: 24px;
    }
}

@media (max-width: 700px) {
    .footer-disclaimer {
        flex-direction: column;
        align-items: flex-start;
        gap: 2vh;
    }

    /* On a phone the button wraps under the field; it takes the field's width rather than hanging at
       the left under it. */
    .footer-letter-field button {
        flex: 1 0 100%;
    }

    /* Seven tiles do not fit a 320px column in one row, and the footer clips what sticks out. */
    .footer-social-row {
        flex-wrap: wrap;
        flex-shrink: 1;
        max-width: 100%;
        justify-content: flex-start;
        gap: 12px 14px;
    }

    /* The column is centred, so its flex rows and its bounded paragraph are centred with it. */
    .footer-contact-details,
    .menu-sub-links {
        align-items: center;
    }

    .footer-newsletter p {
        margin-inline: auto;
    }

    .scroll-indicator {
        display: none;
    }

    .showcase {
        padding-top: 15vh;
    }

    .product-card:nth-child(even), .product-card:nth-child(3n+2) {
        margin-top: 0;
    }

    /* Eight cities are a row on a wide screen; on a phone they became four screens-worth of small
       dials between the letters and the footer. The row belongs to the desktop. */
    .footer-clocks-wrapper {
        display: none;
    }

    .footer-grid-luxury {
        grid-template-columns: 1fr;
        text-align: center;
    }

    .footer-newsletter {
        grid-column: span 1;
    }

    .footer-bottom {
        flex-direction: column;
        gap: 3vh;
        text-align: center;
        line-height: 1.8;
    }

    .menu-right {
        flex-direction: column;
        gap: 4vh;
        text-align: center;
    }

    .menu-item-mega {
        justify-content: center;
    }

    .menu-lang {
        justify-content: center;
    }
}

@media (max-width: 480px) {
    /* The mark keeps its proportions and loses height, which is the only thing a drawing can lose. */
    .logo img {
        height: 11px;
    }

    .header-controls {
        gap: 16px;
    }

    .account-link, .menu-trigger {
        letter-spacing: 2px;
    }

    .menu-trigger {
        margin-right: calc(-10px - 2px);
    }

    .account-link::after,
    .menu-trigger::after {
        right: calc(10px + 2px);
    }

    /* 8px tracking makes a 20-character eyebrow wider than the screen. The ™ compensation follows
       the tracking down, or the mark would overlap the last letter here. */
    .h-tag {
        letter-spacing: 4px;
        --tm-tracking: 4px;
    }
}
/* #endregion */

/* #region Hero */
.hero-cinematic {
    position: relative;
    /* min-height, not height: a short laptop screen must grow the hero rather than clip the copy. */
    height: auto;
    min-height: 100vh;
    min-height: 100svh;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: var(--hero-surface);
    border-bottom: 1px solid var(--section-divider);
    z-index: 1;
}

.hero-bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: var(--hero-surface);
    z-index: 0;
}

.hero-content {
    position: relative;
    z-index: 2;
    text-align: center;
    max-width: 1000px;
    padding: 0 5vw;
    text-shadow: 0 10px 40px rgba(5,5,5,0.8);
}

/* The hero's entrance, and the one place it is written. The container is never hidden and each line
   of the copy comes in on its own, a beat apart, on the shared easing.

   Do not move this onto .hero-content. Lifting the whole half-screen as one block makes eyebrow,
   headline, paragraph and link arrive together, which reads as a slide rather than an entrance
   beside a right-hand column that reveals its lattice, its axis and its picture in three separate
   moves — and it holds the photograph at opacity 0 for the first two seconds, when that photograph
   is the page's LCP. The stagger is a custom property rather than a keyframe per element, so a hero
   with five children needs no new CSS, and any child may opt out by setting --hero-step to 0. */
.hero-copy > * {
    opacity: 0;
    transform: translateY(24px);
    animation: fadeUp 1.05s var(--ease-house) forwards;
    /* The first line waits half a second rather than a third of one: at .35s the eyebrow is still
       moving while the browser makes its first paint, so its entrance happens under cover of the
       page appearing at all and reads as no animation. The step is wide enough that four elements
       read as four separate arrivals. */
    animation-delay: calc(.5s + var(--hero-step, 0) * .16s);
}

.hero-copy > :nth-child(2) { --hero-step: 1; }
.hero-copy > :nth-child(3) { --hero-step: 2; }
.hero-copy > :nth-child(4) { --hero-step: 3; }
.hero-copy > :nth-child(5) { --hero-step: 4; }
.hero-copy > :nth-child(6) { --hero-step: 5; }
.hero-copy > :nth-child(n+7) { --hero-step: 6; }

@media (prefers-reduced-motion: reduce) {
    .hero-copy > * {
        opacity: 1;
        transform: none;
        animation: none;
    }
}

/* The right-hand column enters as well, and neither page's file may pin it with `animation: none`:
   copy arriving beside a picture that has simply always been there is half a hero moving, which is
   what reads as unfinished.

   It starts from nothing, by decision — a fade from part-visible reads as a flicker rather than an
   arrival. The cost is measured and accepted: an element at opacity 0 is not a candidate for Largest
   Contentful Paint, and this photograph is the LCP of the home page and of every product page, so
   that metric starts counting when the fade ends. The delay is kept short for exactly this reason. */
.home-hero-square,
.hero-exhibit {
    animation: heroExhibitEnter 1.25s .2s var(--ease-house) both;
}

@keyframes heroExhibitEnter {
    from {
        opacity: 0;
        transform: scale(1.035);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .home-hero-square,
    .hero-exhibit {
        animation: none;
    }
}

/* The right half's choreography — the lattice that fades in behind the exhibit and the axis that
   draws itself down the middle — and the one place it is written.

   Every hero on the site reads these rules and they are written nowhere else. Copied into home.css
   for .hero-cinematic--home and into product.css for .hero-cinematic--exhibit, one behaviour exists
   twice and the heroes drift apart, because a fix lands in whichever file is open. Those two files
   keep only what is genuinely theirs — the home page's photograph and constellation, the product
   pages' framed exhibit. */
.hero-cinematic--home .hero-bg::before,
.hero-cinematic--home .hero-bg::after,
.hero-cinematic--exhibit .hero-bg::before,
.hero-cinematic--exhibit .hero-bg::after {
    position: absolute;
    inset: 0;
    content: '';
    pointer-events: none;
}

.hero-cinematic--home .hero-bg::before,
.hero-cinematic--exhibit .hero-bg::before {
    right: 50%;
    background: none;
}

.hero-cinematic--home .hero-bg::after,
.hero-cinematic--exhibit .hero-bg::after {
    left: 50%;
    overflow: hidden;
    opacity: 0;
    background-color: var(--hero-surface);
    background-image: linear-gradient(45deg, transparent calc(50% - .5px), var(--hairline-strong) 50%, transparent calc(50% + .5px)), linear-gradient(-45deg, transparent calc(50% - .5px), var(--hairline-strong) 50%, transparent calc(50% + .5px));
    background-position: center;
    background-size: 72px 72px;
    -webkit-mask-image: radial-gradient(ellipse at center, #050505 18%, rgba(5, 5, 5, .72) 58%, transparent 100%);
    mask-image: radial-gradient(ellipse at center, #050505 18%, rgba(5, 5, 5, .72) 58%, transparent 100%);
    transform: scale(1.08);
    animation: heroExhibitLatticeReveal 1.8s .35s var(--ease-house) forwards;
}

.hero-cinematic--home::before,
.hero-cinematic--exhibit::before {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    width: 1px;
    z-index: 1;
    background: var(--section-divider);
    box-shadow: none;
    content: '';
    pointer-events: none;
    transform: scaleY(0);
    transform-origin: top;
    animation: heroExhibitAxisReveal 1.4s .25s var(--ease-house) forwards;
}

.hero-cinematic--home::after,
.hero-cinematic--exhibit::after {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: none;
    content: '';
    pointer-events: none;
}

@keyframes heroExhibitLatticeReveal {
    to {
        opacity: .82;
        transform: scale(1);
    }
}

@keyframes heroExhibitAxisReveal {
    to {
        transform: scaleY(1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .hero-cinematic--home .hero-bg::after,
    .hero-cinematic--exhibit .hero-bg::after {
        opacity: .82;
        transform: none;
        animation: none;
    }

    .hero-cinematic--home::before,
    .hero-cinematic--exhibit::before {
        transform: none;
        animation: none;
    }
}

.h-tag {
    font-family: var(--font-mono);
    font-weight: 400;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 8px;
    /* Declared alongside the tracking it mirrors: a ™ in an eyebrow ("Odoardo Atelier™") closes the
       8px the letter-spacing adds after the final letter. See sup.tm. */
    --tm-tracking: 8px;
    /* Room for the raised ™ when an eyebrow wraps on a phone: sup.tm takes no line height, so under
       the default leading a mark on the second line was drawn into the letters of the first. */
    line-height: 1.7;
    /* White, and led by a short gold stroke: the heading below already carries the section's one gold
       accent in its italic, and an eyebrow in gold beside it made two voices say the same thing. */
    color: rgba(245, 245, 245, .52);
    display: block;
    /* The gap to the title under it, and this declaration owns it. Written twice — here as the
       eyebrow's margin-bottom and again on the h2 as its margin-top — adjacent-sibling collapse
       quietly picks the larger of the two, so a page setting 3vh here and 1.5rem there gets neither
       number on purpose and editing the one you can see changes nothing. One owner: the eyebrow
       carries the gap, and an h2 that follows one has margin-top: 0. */
    margin-bottom: var(--section-tag-gap);
    /* No opacity here, deliberately. At .9 it has the same specificity as the hero's entrance rule
       and stands later in the file, so it overrides the starting opacity: 0 and the eyebrow is
       already visible when its arrival animation plays. */
}

    .h-tag::before {
        display: inline-block;
        width: 1.6rem;
        height: 1px;
        margin-right: .9rem;
        vertical-align: middle;
        background: var(--gold);
        opacity: .8;
        content: '';
    }

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* An amount inside running copy, written around it by AmountLineBreakHelpers. Thousands are grouped with a
   plain space (a no-break one draws as a box in some fonts), so without this a narrow column breaks
   „4 990 zł" into „4" at the end of one line and „990 zł" at the start of the next. */
.amount {
    white-space: nowrap;
}

.h-title {
    font-family: var(--font-display);
    font-weight: 300;
    font-size: var(--hero-title-size);
    color: var(--white);
    line-height: var(--hero-title-line-height);
    /* The same gap the shared section header gives its lead: a second value for one relationship is
       how two headings on one page come to breathe differently. */
    margin-bottom: var(--section-lead-gap);
}

/* Headings are never hyphenated. Justified body text may divide a long Polish compound — that is
   what hyphenation is for — but a display heading broken by a dash reads as a fault, and at these
   sizes the dash is as tall as a letter. Written once here, so a new section cannot reintroduce it
   by copying a neighbour's rule. */
h1, h2, h3, h4, h5, h6,
.h-title, .h-tag {
    -webkit-hyphens: manual;
    hyphens: manual;
}

/* Emphasis inside a heading is one thing across the whole site: the display italic, in champagne
   gold. It is written here once, for every heading level. Repeated locally per section — the home
   hero, the Filmable strip — each copy is a chance for one heading to keep the italic and quietly
   lose the colour. */
h1 i,
h2 i,
h3 i,
h4 i,
.h-title i {
    font-style: italic;
    font-weight: inherit;
    color: var(--gold);
}

.h-desc {
    color: var(--white-soft);
    font-family: var(--font);
    font-size: clamp(1rem, 1.15vw, 1.15rem);
    font-weight: 300;
    line-height: 1.75;
    max-width: 650px;
    margin: 0 auto;
}

@keyframes fadeUp {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (max-width: 1100px) {
    .hero-cinematic {
        height: auto;
        min-height: 100svh;
    }
}
/* #endregion */

/* #region Scroll indicator */
/* The cue runs into the hero's own bottom edge. Held at 4vh it stopped in mid-air, so the travelling
   dot finished its fall against nothing and the line read as a stray mark rather than as the thread
   between this screen and the next. */
.scroll-indicator {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 15px;
    z-index: 10;
    opacity: 0;
    animation: fadeInHero 1.2s 1.5s forwards;
}

/* The cue only fades. It is centred with translateX(-50%), so a keyframe that also wrote transform
   would drop it half its own width to the right the moment the animation finished — which is why
   this is its own keyframe rather than the shared fadeUp the hero copy uses. */
@keyframes fadeInHero {
    to {
        opacity: 1;
    }
}

.scroll-line {
    width: 1px;
    height: 60px;
    background-color: var(--white-subtle);
    position: relative;
    overflow: hidden;
}

.scroll-dot {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 40%;
    /* A soft streak of light that runs down the line, appears and goes out — an invitation, not a
       ticking hand. */
    background: linear-gradient(180deg, rgba(245, 245, 245, 0), rgba(245, 245, 245, .8));
    animation: scrollDot 2.8s var(--ease-house) infinite;
}

@keyframes scrollDot {
    0% {
        opacity: 0;
        transform: translateY(-100%);
    }

    20%, 75% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform: translateY(260%);
    }
}

@media (prefers-reduced-motion: reduce) {
    .scroll-dot {
        animation: none;
        opacity: 0;
    }
}
/* #endregion */

/* #region Concierge orb */
/* The corner controls — the concierge and the basket — share one idiom. At rest a white hairline ring
   that exhales once every --breath-period, in phase with its neighbour (odoardoSyncPulse sets the
   delay on the ring and the breath inherits it). Under the hand a gold line draws itself round the
   ring and the mark takes the gold. Nothing beats, springs or grows: a control that pulses every
   second is asking for attention, and the house never asks. */
@keyframes odo-breath {
    0% {
        opacity: 0;
        transform: scale(1);
    }

    25% {
        opacity: .55;
    }

    70%, 100% {
        opacity: 0;
        transform: scale(1.32);
    }
}

/* One circuit of gold round the ring: drawn in, then carried on and out, so it reads as a single pass
   of light rather than a ring switching on and off. 173 is the circumference of the r=27.5 circle. */
@keyframes odo-arc-sweep {
    0% {
        stroke-dashoffset: 173;
    }

    45% {
        stroke-dashoffset: 0;
    }

    100% {
        stroke-dashoffset: -173;
    }
}

@keyframes orb-rise {
    0%, 100% {
        transform: translateY(0);
    }

    40% {
        transform: translateY(-4px);
    }
}

/* The ring's gold outline, shared by the concierge and the basket. */
.odo-ring-arc {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 56px;
    height: 56px;
    overflow: visible;
    transform: translate(-50%, -50%) rotate(-90deg);
    pointer-events: none;
}

    .odo-ring-arc circle {
        fill: none;
        stroke: var(--gold);
        stroke-width: 1;
        stroke-dasharray: 173;
        stroke-dashoffset: 173;
        transition: stroke-dashoffset 1.1s var(--ease-house);
    }

.odo-orb {
    position: fixed;
    bottom: calc(2.4rem + env(safe-area-inset-bottom, 0px));
    right: calc(2.4rem + env(safe-area-inset-right, 0px));
    z-index: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    background: none;
    text-decoration: none;
    opacity: 0;
    pointer-events: none;
    transform: translateY(14px);
    transition: opacity var(--motion) var(--ease-house), transform var(--motion) var(--ease-house);
    overflow: visible;
}

    .odo-orb.is-visible {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0);
    }

    /* The hint after ten still seconds: one circuit of gold and a lift of four pixels, settling back
       without a bounce. */
    .odo-orb.is-nudging {
        animation: orb-rise 2.4s var(--ease-house);
        transition: none;
    }

        .odo-orb.is-nudging .odo-ring-arc circle {
            animation: odo-arc-sweep 2.4s var(--ease-house);
        }

    .odo-orb:focus-visible {
        outline: 1px solid rgba(var(--gold-rgb), .7);
        outline-offset: 4px;
    }

.odo-orb__ring {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 56px;
    height: 56px;
    background: rgba(5, 5, 5, .88);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--hairline-strong);
    border-radius: 50%;
    opacity: 1;
    transform: translate(-50%, -50%);
    transition: border-color var(--motion) var(--ease-house), opacity var(--motion-quick) var(--ease-house);
    pointer-events: none;
}

    .odo-orb__ring::before {
        position: absolute;
        inset: -1px;
        border: 1px solid rgba(245, 245, 245, .35);
        border-radius: 50%;
        content: '';
        pointer-events: none;
        animation: odo-breath var(--breath-period) var(--ease-house) infinite;
        animation-delay: inherit;
        transition: opacity var(--motion-quick) var(--ease-house);
    }

.odo-orb__svg {
    position: relative;
    width: 19px;
    height: 19px;
    display: block;
    overflow: visible;
    color: var(--white);
    opacity: .72;
    transition: opacity var(--motion-quick) var(--ease-house), color var(--motion) var(--ease-house);
}

.odo-orb:hover .odo-orb__svg,
.odo-orb:focus-visible .odo-orb__svg,
.odo-orb.is-nudging .odo-orb__svg {
    opacity: 1;
    color: var(--gold);
}

.odo-orb:hover .odo-ring-arc circle,
.odo-orb:focus-visible .odo-ring-arc circle {
    stroke-dashoffset: 0;
}

    .odo-orb:hover .odo-orb__ring::before,
    .odo-orb:focus-visible .odo-orb__ring::before {
        opacity: 0;
        animation-play-state: paused;
    }

.odo-orb__tooltip {
    position: absolute;
    right: calc(100% + 16px);
    top: 50%;
    transform: translateY(-50%) translateX(8px);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--motion) var(--ease-house), transform var(--motion) var(--ease-house);
    background: rgba(5, 5, 5, .92);
    border: 1px solid var(--hairline-mid);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    overflow: hidden;
    min-height: 72px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.odo-orb:hover .odo-orb__tooltip,
.odo-orb:focus-visible .odo-orb__tooltip {
    opacity: 1;
    transform: translateY(-50%) translateX(0);
}

.odo-orb__tooltip-name {
    display: block;
    padding: .6rem 1rem .4rem;
    font-family: var(--font);
    font-size: .52rem;
    font-weight: 400;
    letter-spacing: .32em;
    /* .32em of tracking is added after the final letter too, which pushed the ™ a third of a line
       away from the name. The mark gives that space back — see sup.tm. */
    --tm-tracking: .32em;
    text-transform: uppercase;
    color: rgba(245, 245, 245, .5);
    line-height: 1;
    transition: color var(--motion) var(--ease-house);
}

.odo-orb__tooltip-sub {
    display: block;
    padding: 0 1rem .6rem;
    font-family: var(--font-display);
    font-style: italic;
    font-size: .88rem;
    font-weight: 300;
    letter-spacing: .01em;
    color: rgba(245, 245, 245, .92);
    line-height: 1.2;
}

.odo-orb:hover .odo-orb__tooltip-name,
.odo-orb:focus-visible .odo-orb__tooltip-name {
    color: var(--gold);
}

.odo-orb:hover .odo-orb__tooltip-sub,
.odo-orb:focus-visible .odo-orb__tooltip-sub {
    color: var(--white);
}

.odo-orb__tooltip-nudge {
    display: none;
    padding: .3rem 1rem .6rem;
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 300;
    font-size: .88rem;
    letter-spacing: .01em;
    color: rgba(245, 245, 245, .95);
    border-top: 1px solid var(--hairline);
    line-height: 1.3;
    margin-top: .1rem;
}

.odo-orb.is-nudging .odo-orb__tooltip {
    opacity: 1;
    transform: translateY(-50%) translateX(0);
}

/* The hint keeps its own line for as long as any of the box can be seen: while it is shown and through
   the whole fade that follows. layout.js lifts is-nudge-leaving only once the box has finished fading. */
.odo-orb.is-nudging .odo-orb__tooltip-sub,
.odo-orb.is-nudge-leaving .odo-orb__tooltip-sub {
    display: none;
}

.odo-orb.is-nudging .odo-orb__tooltip-nudge,
.odo-orb.is-nudge-leaving .odo-orb__tooltip-nudge {
    display: block;
}

@media (max-width: 640px) {
    .odo-orb {
        right: calc(1rem + env(safe-area-inset-right, 0px));
        bottom: calc(2rem + env(safe-area-inset-bottom, 0px));
        width: 62px;
        height: 62px;
    }

    .odo-orb__ring,
    .odo-orb .odo-ring-arc {
        width: 50px;
        height: 50px;
    }

    /* max-content, or a wrapping tooltip beside a 62px button shrinks to its longest word. */
    .odo-orb__tooltip {
        width: max-content;
        white-space: normal;
        max-width: min(60vw, 17rem);
        text-align: left;
    }
}

/* On a tablet and a phone the footer's lines run under the concierge and the basket floating in the
   bottom right corner, the company's registration line among them — so there the footer ends below
   them. A desktop keeps its own foot: the buttons stand beside the text there, not over it. */
@media (max-width: 1100px) {
    footer {
        padding-bottom: calc(4vh + 7rem + env(safe-area-inset-bottom, 0px));
    }
}

@media (max-width: 640px) {
    footer {
        padding-bottom: calc(4vh + 10.5rem + env(safe-area-inset-bottom, 0px));
    }
}

@media (prefers-reduced-motion: reduce) {
    .odo-orb__ring::before {
        animation: none;
        opacity: 0;
    }

    .odo-orb.is-nudging,
    .odo-orb.is-nudging .odo-ring-arc circle {
        animation: none;
    }
}
/* #endregion */

/* #region SEO knowledge block */
.seo-knowledge {
    /* .container carries no padding of its own — without this the block runs edge to edge on phones. */
    padding: var(--section-space) 5vw;
    background: var(--surface-editorial);
    border-top: 1px solid var(--line);
    /* Positioned on purpose, and that is what keeps the seam above this block visible. The section
       before it is almost always a .reveal-elem: it starts thirty pixels lower than its own box,
       fades in as it travels back up, and carries `position: relative` with a ground of its own. A
       positioned element paints above a static sibling's border, so left static this block has its
       rule drawn, shown for a moment and then covered as the neighbour arrives over it. Coming later
       in the document, it only has to be positioned to win — same stacking level, later in paint
       order. A heavier line does not fix it; the weight is not the problem. */
    position: relative;
    z-index: 1;
}

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

.seo-knowledge-summary p {
    max-width: 40ch;
}

.seo-knowledge-aside {
    display: flex;
    flex-direction: column;
    gap: clamp(2.2rem, 3.5vw, 3.4rem);
}

.seo-knowledge-facts h2 {
    font-size: clamp(1.1rem, 1.5vw, 1.3rem);
    letter-spacing: 0;
}

/* No rule under the heading. It ran the width of the list and sat directly beneath the title, so it
   read as an underline drawn under the words rather than as the top edge of a table — and the facts
   below carry no rules of their own for it to belong to. */
.seo-knowledge-facts dl {
    margin: 0;
    max-width: 40ch;
}

/* #region House ledger */
/* The engraved number, shown on the home page and in the manifesto from one partial. The two
   figures are the argument, so they are set in the display face at heading size — a range that
   belongs to the workshop, and the single number where a customer's objects begin. */
.house-ledger {
    padding: var(--section-space) 0;
    border-top: 1px solid var(--section-divider);
    background: var(--hero-surface);
}

/* Two columns: the argument on the left, the thing it argues about on the right. A section about an
   engraved number has to show the number. */
.house-ledger-inner {
    width: min(90vw, var(--section-content-max));
    max-width: none;
    margin-inline: auto;
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
    gap: clamp(2.5rem, 6vw, 6rem);
    align-items: center;
}

@media (max-width: 900px) {
    .house-ledger-inner {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* The entry itself: a plate of dark oak-black with the hairline frame the house engraves inside its
   borders, the number at the size of the argument, and under it the three columns the book keeps
   against it. The fields stay empty — a specimen, never a record of somebody. */
.house-ledger-plate {
    position: relative;
    overflow: hidden;
    margin: 0;
    /* Tight at the top, generous everywhere else. The number is the first thing on the plate and it
       turns: a figure rolling up out of the top of its window reads as a wheel continuing past the
       edge, and a hand's width of empty plate above it turns that into a figure floating in a box.
       The measure is set just under the mount's own hairline, so the wheels run from the frame. */
    padding: clamp(1rem, 1.8vw, 1.4rem) clamp(2rem, 4vw, 3.2rem) clamp(2rem, 4vw, 3.2rem);
    border: 1px solid var(--hairline-mid);
    background: linear-gradient(150deg, var(--tint), transparent 55%), #050505;
    box-shadow: 0 30px 70px rgba(5, 5, 5, .5);
    text-align: center;
    transition: transform var(--motion-quick) var(--ease-house), border-color var(--motion) var(--ease-house);
}

    /* The plate does not rise to meet the hand: its frame warms to gold and nothing else moves. */
    .house-ledger-plate:hover {
        border-color: var(--gold);
    }

    .house-ledger-plate::before {
        position: absolute;
        inset: .7rem;
        border: 1px solid rgba(245, 245, 245, .06);
        content: "";
        pointer-events: none;
    }

/* The number, engraved: gold Playfair at the scale of a headline, tracked open the way a stamped
   figure is. This is the one thing the section is about. */
.house-ledger-plate-number {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: .12em;
    /* No top margin: nothing stands above the number, so one only adds itself to the plate's own padding
       and sits the figure low under a hand's width of nothing. */
    margin: 0 0 clamp(1.2rem, 2.5vh, 2rem);
    color: var(--gold);
    font-family: var(--font-display);
    font-size: clamp(3.6rem, 8vw, 6.4rem);
    font-weight: 200;
    letter-spacing: .12em;
    line-height: 1;
}

    /* The mark a ledger writes in front of a figure, at the size a mark takes beside it. */
    .house-ledger-plate-number i {
        font-size: .34em;
        font-style: normal;
        letter-spacing: 0;
        opacity: .75;
        transform: translateY(-.9em);
    }

/* The four wheels, and each is simply the figure standing on it. The tracking between them is a flex
   gap rather than letter-spacing, because letter-spacing is trailing air after the last glyph as well
   and would push the number off its own centre. The width is fixed at one character so a wheel does
   not change the width of the plate as it counts — the face is set in tabular figures, where 1ch is
   the advance of every digit and not only of the zero it is measured on. */
.house-ledger-digits {
    display: flex;
    gap: .12em;
    font-variant-numeric: tabular-nums;
    font-weight: 200;
    letter-spacing: 0;
}

.house-ledger-digit {
    display: inline-block;
    width: 1ch;
    text-align: center;
}

/* The invitation, and it appears only once the machine has something to advance from — offering a
   press before the first number has landed is offering nothing. */
.house-ledger-plate-action {
    display: block;
    margin-top: clamp(1.1rem, 2vh, 1.6rem);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: .56rem;
    letter-spacing: .2em;
    text-transform: uppercase;
    opacity: 0;
    transition: opacity .8s var(--ease-house) 1.9s, color var(--motion-quick) var(--ease-house);
}

.house-ledger-plate.is-struck .house-ledger-plate-action {
    opacity: .75;
}

.house-ledger-plate:hover .house-ledger-plate-action {
    color: var(--gold);
}

/* The press itself: the plate takes the blow and comes back. Nothing else moves — a card that slides
   or glows on a click is a button, and this is a machine being operated. */
.house-ledger-plate.is-struck {
    cursor: pointer;
    user-select: none;
}

.house-ledger-plate.is-striking {
    transform: translateY(-2px) scale(.994);
    transition-duration: .12s;
}

/* The object is rewritten while the wheels are still turning, so it goes out and comes back rather
   than changing under the reader's eye — the clerk lifts the pen before writing the next line. */
.house-ledger-plate.is-striking .house-ledger-plate-fields > div:first-child dd {
    opacity: 0;
    transition-duration: .18s;
    transition-delay: 0s;
}

/* No flash when the count stops. The number climbing to its own figure is the whole gesture; a
   glow through the digits at the end turned a numbering machine into a notification. */

.house-ledger-plate-fields {
    display: grid;
    gap: .55rem;
    margin: 0;
    padding-top: clamp(1.1rem, 2vh, 1.6rem);
    border-top: 1px solid var(--hairline);
    text-align: left;
}

    .house-ledger-plate-fields > div {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        gap: .8rem;
        align-items: baseline;
    }

    .house-ledger-plate-fields dt {
        color: var(--text-muted);
        font-family: var(--font-mono);
        font-size: .56rem;
        letter-spacing: .2em;
        text-transform: uppercase;
        white-space: nowrap;
    }

    /* The ruled line a clerk writes on, with the entry written on it. The rule is a pseudo-element
       rather than a border, because the line is drawn when the section arrives and text cannot be
       scaled from nothing along with it. */
    /* What is written on the line, at the weight of something written rather than of a caption. At .7rem —
       smaller than the label naming it — the entry reads as the small print of its own field name. The value
       is the point of a ledger line; the label is the printed part of the form. */
    .house-ledger-plate-fields dd {
        position: relative;
        margin: 0;
        padding-bottom: .55rem;
        color: var(--white);
        font-family: var(--font);
        font-size: .95rem;
        font-weight: 300;
        letter-spacing: .02em;
    }

        /* The object gets the display face, because it is the only line on this plate that names one
           of ours — and because a plate carrying one thing set in Playfair and a date set beside it
           reads as an entry, while two lines in the same face read as a table. White: the number above
           is the plate's one gold. */
        .house-ledger-plate-object {
            color: var(--white);
            font-family: var(--font-display);
            font-size: clamp(1.15rem, 1.6vw, 1.5rem);
            letter-spacing: .01em;
            line-height: 1.25;
        }

        .house-ledger-plate-fields dd::after {
            position: absolute;
            right: 0;
            bottom: 0;
            left: 0;
            height: 1px;
            background: rgba(245, 245, 245, .12);
            content: "";
        }

/* The plate is struck rather than displayed: the number rolls onto its wheels and the rules are drawn
   under it in turn — the order in which a clerk would actually enter it. Everything here hangs off the
   .visible class site.js already sets on .reveal-elem, so the sequence starts when the visitor reaches
   the section and never before.

   There is no pass of light across the plate, and there is not going to be one. A gradient sweeping a
   dark surface is the house style of every subscription page on the internet — it says „premium" by
   imitation, and imitation is the one thing this section cannot afford, because its whole argument is
   that the object is real. Oak does not shimmer. The movement here is mechanical: figures turning and
   a rule being drawn. */

/* The number arrives, and then it turns. The wheels are the movement; a second gesture over them —
   tracking opening wide and closing as the figure appears — only muddies it. */
.house-ledger-plate-number {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 1s var(--ease-house) .15s, transform 1.1s var(--ease-house) .15s;
}

.house-ledger-inner.visible .house-ledger-plate-number {
    opacity: 1;
    transform: none;
}

/* The clerk writes: the rule is drawn first, and the entry appears on it a beat later — one line
   after another, in the order the book is filled in. */
.house-ledger-plate-fields dd {
    opacity: 0;
    transition: opacity .7s var(--ease-house);
}

    .house-ledger-plate-fields dd::after {
        transform: scaleX(0);
        transform-origin: left center;
        transition: transform var(--motion) var(--ease-house);
    }

.house-ledger-inner.visible .house-ledger-plate-fields dd {
    opacity: 1;
}

.house-ledger-inner.visible .house-ledger-plate-fields dd::after {
    transform: scaleX(1);
}

.house-ledger-inner.visible .house-ledger-plate-fields > div:nth-child(1) dd::after {
    transition-delay: .8s;
}

.house-ledger-inner.visible .house-ledger-plate-fields > div:nth-child(1) dd {
    transition-delay: 1.1s;
}

.house-ledger-inner.visible .house-ledger-plate-fields > div:nth-child(2) dd::after {
    transition-delay: .95s;
}

.house-ledger-inner.visible .house-ledger-plate-fields > div:nth-child(2) dd {
    transition-delay: 1.25s;
}

.house-ledger-inner.visible .house-ledger-plate-fields > div:nth-child(3) dd::after {
    transition-delay: 1.1s;
}

.house-ledger-inner.visible .house-ledger-plate-fields > div:nth-child(3) dd {
    transition-delay: 1.4s;
}

@media (prefers-reduced-motion: reduce) {
    .house-ledger-plate,
    .house-ledger-plate-number,
    .house-ledger-plate-fields dd {
        transition: none;
    }

    .house-ledger-plate:hover {
        transform: none;
    }

    .house-ledger-inner.visible .house-ledger-plate::after {
        animation: none;
    }

    .house-ledger-plate-number {
        opacity: 1;
        letter-spacing: .12em;
        transform: none;
    }

    /* The entry is simply there, written and ruled, with nothing arriving. */
    .house-ledger-plate-fields dd {
        opacity: 1;
    }

        .house-ledger-plate-fields dd::after {
            transform: scaleX(1);
            transition: none;
        }
}

/* The house's section heading, stated the way every other band on the page states it: the eyebrow at
   its own distance, the title at the section size and the lead under it at reading size. Two sizes
   down, a whole band of the manifesto opens in the type of a card directly under a section that
   opened properly. The eyebrow needs no rule of its own here — .h-tag already gives every eyebrow on
   the site its `display: block` and its distance. */

.house-ledger-copy h2 {
    margin: 0;
    color: var(--white);
    font-family: var(--font-display);
    font-size: var(--section-title-size);
    font-weight: 300;
    letter-spacing: -.035em;
    line-height: var(--section-title-line-height);
}

    .house-ledger-copy h2 i {
        color: var(--gold);
        font-weight: 300;
    }

.house-ledger-lead {
    max-width: 36rem;
    margin: clamp(2rem, 4vh, 3.5rem) 0 0;
    color: var(--text-muted);
    font-size: clamp(1rem, 1.15vw, 1.12rem);
    font-weight: 300;
    line-height: 1.8;
}

/* What the number is worth, at the weight of the lead it continues: this is the argument of the
   section, not a footnote to it. */
.house-ledger-value {
    max-width: 36rem;
    margin: 1.4rem 0 0;
    color: var(--text-muted);
    font-size: clamp(1rem, 1.15vw, 1.12rem);
    font-weight: 300;
    line-height: 1.8;
}

/* #endregion */

/* Label above the value, not beside it. Two columns split an already narrow aside in half, so the
   right-hand side wrapped a sentence every three or four words while the left kept a two-word label
   on a line of its own. Stacked, the value gets the full width and the label reads as what it is —
   a caption, not a second column of content. */
/* No rules between the entries. Stacked label-over-value already separates them, and a line under
   every pair turned three short facts into a small table. */
.seo-knowledge-fact {
    padding: 0 0 1.1rem;
}

    .seo-knowledge-fact dt {
        margin-bottom: .25rem;
        color: var(--text-muted);
        font-family: var(--font);
        font-size: .6rem;
        font-weight: 400;
        letter-spacing: .16em;
        line-height: 1.5;
        text-transform: uppercase;
    }

    .seo-knowledge-fact dd {
        margin: 0;
        color: var(--white-soft);
        font-family: var(--font);
        font-size: 1rem;
        font-weight: 300;
        line-height: 1.7;
    }

        /* The one piece of colour in a column of grey lines, and the only reason it is here: a fact
           table is skimmed, and a mark this size is what makes somebody read the line it sits on.
           The hairline keeps the white half from bleeding into the dark ground.

           The mark is a square, and both sides are stated rather than left to `height: auto` and
           the viewBox ratio — the shape is the point here, so it does not depend on how a browser
           resolves the intrinsic ratio of an inline SVG. It is narrower than a 5:3 flag: a square at
           that width stands half again as tall as the line it sits in, and this width keeps roughly
           the optical weight the row is balanced around. */
        .seo-knowledge-fact dd .seo-fact-flag {
            width: .95em;
            height: .95em;
            margin-right: .5em;
            border: 1px solid var(--line);
            vertical-align: -.16em;
        }

        /* Several countries in one value — the artists' catalogue lists where its creators come from.
           Each name holds its own flag, so the pair never breaks across a line. */
        .seo-knowledge-fact dd .seo-fact-country {
            display: inline-block;
            margin-right: 1.1em;
            white-space: nowrap;
        }

/* Closer to the heading it introduces than the site-wide eyebrow spacing: this one sits above a
   2.3rem heading in a text column, not above a hero with a screen to fill. Shared by all three
   blocks of the section, so the pairs stay identical to one another. */
.seo-knowledge-eyebrow {
    margin-bottom: 1rem;
}

.seo-knowledge h2 {
    margin: 0 0 1.4rem;
    color: var(--white);
    font-family: var(--font-display);
    font-size: clamp(1.7rem, 2.6vw, 2.3rem);
    font-weight: 300;
    letter-spacing: -.01em;
    line-height: 1.2;
}

.seo-knowledge-summary p,
.seo-knowledge-faq p {
    color: var(--white-soft);
    font-family: var(--font);
    font-size: 1rem;
    font-weight: 300;
    line-height: 1.9;
}

    /* A link in the summary or an answer: full white over the soft white of the sentence, with a
       hairline under it, and the gold arrives under the hand. Under the global `color: inherit` it was
       indistinguishable from the sentence around it, so a reader never found out that a product name
       could be opened. No weight of its own: a link reads as a link by its tone and its line.
       A sense named in a page's own copy — a step, a manifesto, a section's lead — is linked by the same
       helper and looks the same, wherever on the site it stands. */
    .seo-knowledge-summary p a,
    .seo-knowledge-faq p a,
    a[data-analytics="ContentProductLink"] {
        color: var(--white);
        text-decoration: none;
        border-bottom: 1px solid var(--hairline-strong);
        transition: border-color var(--motion-quick) var(--ease-house), color var(--motion-quick) var(--ease-house);
        overflow-wrap: anywhere;
    }

        .seo-knowledge-summary p a:hover,
        .seo-knowledge-summary p a:focus-visible,
        .seo-knowledge-faq p a:hover,
        .seo-knowledge-faq p a:focus-visible,
        a[data-analytics="ContentProductLink"]:hover,
        a[data-analytics="ContentProductLink"]:focus-visible {
            border-bottom-color: var(--gold);
            color: var(--gold);
        }

.seo-knowledge-faq {
    margin-top: 0;
}

    .seo-knowledge-faq details {
        position: relative;
        overflow: hidden;
        border-bottom: 1px solid var(--line);
        transition: background-color .4s var(--ease-house);
    }

        .seo-knowledge-faq details::before {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            width: 1px;
            background: var(--gold);
            content: "";
            transform: scaleY(0);
            transform-origin: top;
            transition: transform .45s var(--ease-house);
        }

        .seo-knowledge-faq details:first-of-type {
            border-top: 1px solid var(--line);
        }

        .seo-knowledge-faq details[open] {
            background: linear-gradient(90deg, rgba(var(--gold-rgb),.07), rgba(var(--gold-rgb),0) 55%);
        }

            .seo-knowledge-faq details[open]::before {
                transform: scaleY(1);
            }

    .seo-knowledge-faq summary {
        position: relative;
        padding: 1.2rem clamp(2.6rem, 11vw, 4rem) 1.2rem 0;
        color: var(--white-bright);
        font-family: var(--font);
        font-size: 1rem;
        font-weight: 400;
        letter-spacing: .01em;
        line-height: 1.5;
        list-style: none;
        cursor: pointer;
        transition: color .35s var(--ease-house), padding-left .4s var(--ease-house);
    }

        .seo-knowledge-faq summary::marker,
        .seo-knowledge-faq summary::-webkit-details-marker {
            display: none;
        }

        .seo-knowledge-faq summary::before {
            position: absolute;
            top: 50%;
            right: 0;
            width: 30px;
            aspect-ratio: 1;
            border: 1px solid var(--hairline-mid);
            border-radius: 50%;
            content: "";
            transform: translateY(-50%);
            transition: background .4s var(--ease-house), border-color .4s var(--ease-house);
        }

        /* The cross is white at rest and takes the gold with the ring, under the hand or once open. */
        .seo-knowledge-faq summary::after {
            position: absolute;
            top: 50%;
            right: 8px;
            width: 14px;
            height: 14px;
            content: "";
            background: linear-gradient(var(--white-soft), var(--white-soft)) center / 100% 1px no-repeat, linear-gradient(var(--white-soft), var(--white-soft)) center / 1px 100% no-repeat;
            transform: translateY(-50%) rotate(0deg);
            transition: transform .5s var(--ease-house);
        }

    .seo-knowledge-faq details[open] summary {
        color: var(--gold);
        padding-left: 1.6rem;
    }

        .seo-knowledge-faq details[open] summary::before {
            background: var(--gold-dim);
            border-color: var(--gold-mid);
        }

        .seo-knowledge-faq details[open] summary::after {
            transform: translateY(-50%) rotate(135deg);
        }

        .seo-knowledge-faq details[open] summary::after,
        .seo-knowledge-faq summary:hover::after {
            background-image: linear-gradient(var(--gold), var(--gold)), linear-gradient(var(--gold), var(--gold));
        }

    .seo-knowledge-faq summary:hover {
        color: var(--gold);
    }

        .seo-knowledge-faq summary:hover::before {
            border-color: var(--gold-mid);
        }

    .seo-knowledge-faq summary:focus-visible {
        outline: 1px solid var(--gold-mid);
        outline-offset: 4px;
    }

    .seo-knowledge-faq details p {
        max-width: 62ch;
        margin: -.2rem 0 0;
        padding: 0 4rem 1.4rem 0;
        animation: seoFaqReveal .5s var(--ease-house);
    }

    .seo-knowledge-faq details[open] p {
        padding-left: 1.6rem;
    }

@keyframes seoFaqReveal {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .seo-knowledge-faq details p {
        animation: none;
    }
}

@media (max-width: 900px) {
    .seo-knowledge-grid {
        grid-template-columns: 1fr;
    }

    .seo-knowledge-summary p {
        max-width: 62ch;
    }

    .seo-knowledge-facts dl {
        max-width: 62ch;
    }

    .seo-knowledge-faq {
        margin-top: clamp(2rem, 4vw, 3.5rem);
    }
}

@media (max-width: 480px) {
    .seo-knowledge-fact {
        grid-template-columns: 1fr;
        gap: .25rem;
    }
}
/* #endregion */

/* #region Hero traits marquee */
.hero-traits {
    position: relative;
    padding: clamp(1.1rem, 1.8vw, 1.6rem) 0;
    overflow: hidden;
    background: var(--black);
    border-bottom: 1px solid var(--section-divider);
}

.hero-traits-viewport {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #050505 8%, #050505 92%, transparent);
    mask-image: linear-gradient(90deg, transparent, #050505 8%, #050505 92%, transparent);
}

.hero-traits-track {
    display: flex;
    gap: clamp(1.6rem, 3vw, 3rem);
    width: max-content;
    animation: heroTraitsScroll 60s linear infinite;
}

.hero-traits-list {
    display: flex;
    align-items: center;
    gap: clamp(1.6rem, 3vw, 3rem);
    margin: 0;
    padding: 0;
    list-style: none;
}

.hero-traits-item {
    display: flex;
    align-items: center;
    gap: clamp(1.6rem, 3vw, 3rem);
    color: var(--white-soft);
    font-family: var(--font);
    font-size: .72rem;
    font-weight: 300;
    letter-spacing: .22em;
    text-transform: uppercase;
    white-space: nowrap;
}

    .hero-traits-item::before {
        flex: none;
        width: 4px;
        height: 4px;
        background: var(--gold);
        border-radius: 50%;
        content: "";
        opacity: .7;
    }

@keyframes heroTraitsScroll {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(-50%);
    }
}

@media (prefers-reduced-motion: reduce) {
    .hero-traits-track {
        animation: none;
    }
}
/* #endregion */

/* #region Partner consent */
.partner-consent {
    position: fixed;
    inset: auto 1.5rem calc(1.5rem + env(safe-area-inset-bottom, 0px)) auto;
    z-index: 1200;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    max-width: 380px;
    padding: 1.4rem 1.6rem;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-mid);
    color: var(--white-bright);
    font-family: var(--font);
}

.partner-consent-text {
    margin: 0;
    font-size: .82rem;
    font-weight: 300;
    line-height: 1.6;
    color: var(--white-soft);
}

.partner-consent-actions {
    display: flex;
    align-items: center;
    gap: 1.2rem;
}

.partner-consent-accept {
    min-height: 44px;
    padding: .55rem 1.4rem;
    background: transparent;
    border: 1px solid var(--hairline-strong);
    color: var(--white);
    font-family: var(--font);
    font-size: .72rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    cursor: pointer;
    transition: border-color .2s var(--ease-house), color .2s var(--ease-house);
}

    .partner-consent-accept:hover,
    .partner-consent-accept:focus-visible {
        border-color: var(--gold-hover);
        color: var(--gold);
    }

.partner-consent-decline {
    min-height: 44px;
    padding: .55rem .5rem;
    background: transparent;
    border: 0;
    color: var(--text-muted);
    font-family: var(--font);
    font-size: .72rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color .2s var(--ease-house);
}

    .partner-consent-decline:hover {
        color: var(--white-soft);
    }

@media (max-width: 760px) {
    .partner-consent {
        inset: auto 1rem calc(1rem + env(safe-area-inset-bottom, 0px)) 1rem;
        max-width: none;
    }
}
/* #endregion */

/* #region Reduced motion */
/* One place for every entrance and idle animation the layout owns; the product pages keep their own. */
@media (prefers-reduced-motion: reduce) {
    .hero-content {
        animation: none;
        opacity: 1;
        transform: none;
    }

    /* Separated from .hero-content on purpose: transform is what centres the cue, so here it may
       lose the animation but never the transform. */
    .scroll-indicator {
        animation: none;
        opacity: 1;
    }

    .scroll-dot {
        animation: none;
    }

    .odo-orb.is-nudging {
        animation: none;
    }

    .menu-overlay {
        transition: none;
        transform: none;
    }

    .reveal-elem {
        opacity: 1;
        transform: none;
        transition: none;
    }

    /* The lean region names the cursor by two classes, so it has to be named by two here as well or
       a visitor who asked for less motion and landed on a slow machine would get the fade back. */
    .custom-cursor,
    html.odo-lean .custom-cursor,
    .m-tag,
    .menu-item-mega {
        transition: none;
    }
}
/* #endregion */

/* #region Print */
@media print {
    /* Printouts are pure black on pure white (#000 on #fff), never the screen's #050505/#F5F5F5. */
    body > header,
    footer,
    .menu-overlay,
    .odo-orb,
    .cart-root,
    .noise-overlay,
    .custom-cursor,
    .partner-consent,
    .skip-link,
    .scroll-indicator {
        display: none !important;
    }

    body {
        background: #fff;
        color: #000;
    }

    body * {
        color: #000 !important;
        background: transparent !important;
        text-shadow: none !important;
        box-shadow: none !important;
    }

    .reveal-elem,
    .hero-content {
        opacity: 1;
        transform: none;
        animation: none;
    }

    .hero-cinematic {
        min-height: 0;
        border-bottom: 0;
    }

    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: .8em;
    }
}
/* #endregion */

/* #region Constellation — the map of the house */
/* Five quiet points on the left edge, one per sense, drawn in white. A visited room fills with gold; five
   visited rooms close the circle. Desktop only — on a phone the edge belongs to the thumb. */
.odo-constellation {
    position: fixed;
    top: 50%;
    left: 1.1rem;
    z-index: 60;
    display: flex;
    flex-direction: column;
    gap: 1.05rem;
    transform: translateY(-50%);
}

.odo-constellation__point {
    position: relative;
    display: block;
    width: 8px;
    height: 8px;
    border: 1px solid var(--white-faint);
    border-radius: 50%;
    background: transparent;
    transition: background var(--motion-quick) var(--ease-house), border-color var(--motion-quick) var(--ease-house);
}

    .odo-constellation__point.is-visited {
        border-color: var(--gold);
        background: var(--gold);
    }

    /* The point does not grow under the hand; its ring takes the gold and the name appears. */
    .odo-constellation__point:hover,
    .odo-constellation__point:focus-visible {
        border-color: var(--gold);
        outline: none;
    }

.odo-constellation__name {
    position: absolute;
    top: 50%;
    left: calc(100% + .7rem);
    padding: .3rem .6rem;
    border: 1px solid var(--hairline-mid);
    background: rgba(5, 5, 5, .92);
    color: var(--white);
    font-family: var(--font-sans);
    font-size: .58rem;
    font-weight: 400;
    letter-spacing: .18em;
    text-transform: uppercase;
    white-space: nowrap;
    transform: translateY(-50%);
    opacity: 0;
    transition: opacity var(--motion-quick) var(--ease-house);
    pointer-events: none;
}

.odo-constellation__point:hover .odo-constellation__name,
.odo-constellation__point:focus-visible .odo-constellation__name {
    opacity: 1;
}

/* Its names appear on hover alone, so a touch screen of any width would show five nameless dots. */
@media (max-width: 1100px), (hover: none) {
    .odo-constellation {
        display: none;
    }
}
/* #endregion */

/* #region Midnight */
/* Between midnight and two the wordmark in the header breathes, faintly — a detail for whoever
   is still awake with the house. */
body.odo-midnight header > div > a {
    animation: odoMidnightBreath 7s ease-in-out infinite;
}

@keyframes odoMidnightBreath {
    0%, 100% {
        opacity: 1;
    }

    50% {
        opacity: .55;
    }
}

@media (prefers-reduced-motion: reduce) {
    body.odo-midnight header > div > a {
        animation: none;
    }
}
/* #endregion */

/* #region Share bar */
/* Four ways out of a page: three networks and the address itself. Shared, because the journal article
   and the Filmable profile offer exactly the same set — each page decides only where the bar sits. */
.share-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 20px;
    margin-bottom: 0;
}

.share-label {
    font-family: var(--font);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 4px;
    color: rgba(245, 245, 245, 0.4);
}

.share-buttons {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.share-icon-btn {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    gap: 8px;
    font-family: var(--font);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    color: rgba(245, 245, 245, 0.5);
    cursor: pointer;
    border: 1px solid rgba(245, 245, 245, 0.1);
    background: transparent;
    padding: 10px 16px;
    border-radius: 40px;
    transition: border-color var(--motion-quick) var(--ease-house), color var(--motion-quick) var(--ease-house);
    text-decoration: none;
}

    .share-icon-btn svg {
        width: 15px;
        height: 15px;
        flex-shrink: 0;
    }

    .share-icon-btn:hover,
    .share-icon-btn:focus-visible {
        border-color: var(--gold);
        color: var(--gold);
    }

/* Shown only when the browser refuses the clipboard, so the address can still be selected by hand. */
.share-manual-url {
    flex-basis: 100%;
    width: 100%;
    padding: 10px 16px;
    color: rgba(245, 245, 245, .75);
    font-family: var(--font);
    /* Below 16px iOS Safari zooms the page on focus and never zooms back out. */
    font-size: max(16px, .78rem);
    background: transparent;
    border: 1px solid rgba(245, 245, 245, .18);
    border-radius: 40px;
}

.share-manual-note {
    flex-basis: 100%;
    margin: 0;
    color: rgba(245, 245, 245, .5);
    font-family: var(--font);
    font-size: .72rem;
}

@media (prefers-reduced-motion: reduce) {
    .share-icon-btn {
        transition: none;
    }
}
/* #endregion */

/* #region Consent checkbox — the house's one box for a declaration somebody is held to: Odoardo ID's forms
   (id.css places it in them) and the Lens guest's statement before recording, a page that loads no other
   stylesheet of ours. */
.id-check {
    /* The real checkbox is hidden with position: absolute. Without a positioned label it anchored to
       whatever ancestor happened to be positioned, so clicking the box focused an input sitting
       somewhere else on the page and the browser scrolled the form away. */
    position: relative;
    display: grid;
    grid-template-columns: 18px 1fr;
    align-items: start;
    gap: 12px;
    margin-top: 2px;
    cursor: pointer;
    font-family: var(--font);
    font-size: .85rem;
    font-weight: 400;
    line-height: 1.6;
    letter-spacing: normal;
    text-transform: none;
    color: var(--text-muted);
}

.id-check input {
    position: absolute;
    top: 0;
    left: 0;
    opacity: 0;
    width: 0;
    height: 0;
}

.id-check-box {
    position: relative;
    display: block;
    width: 18px;
    height: 18px;
    margin-top: 3px;
    border: 1px solid var(--white-subtle);
    background: #050505;
    transition: border-color .25s ease, background .25s ease;
}

    .id-check-box::after {
        content: '';
        position: absolute;
        inset: 4px;
        background: var(--gold);
        opacity: 0;
        transition: opacity .2s ease;
    }

.id-check input:checked ~ .id-check-box {
    border-color: var(--gold);
    background: var(--gold);
    box-shadow: inset 0 0 0 3px #050505;
}

    .id-check input:checked ~ .id-check-box::after {
        opacity: 1;
    }

.id-check input:focus-visible ~ .id-check-box {
    outline: 1px solid var(--gold);
    outline-offset: 2px;
}

.id-check-text a {
    color: var(--white);
    text-decoration: none;
    border-bottom: 1px solid var(--hairline-strong);
    transition: color var(--motion-quick) var(--ease-house), border-color var(--motion-quick) var(--ease-house);
}

    .id-check-text a:hover,
    .id-check-text a:focus-visible {
        color: var(--gold);
        border-bottom-color: var(--gold);
    }
/* #endregion */
