        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            /* One gold family. Every colour on the page is one of these, the neutral text tones, or --error-red. */
            --primary: #FFD700; /* Pure gold */
            --luxury-gold: #DAA520;
            --champagne: #F7E7CE;
            --bronze: #CD7F32;
            --platinum: #E5E4E2;
            --bg-dark: #0a0a0a;
            --bg-darker: #050505;
            --text-light: #FAFAFA;
            --text-gold: #FFD700;
            --text-dim: #B8860B;                      /* small labels and meta in the gold family (6.1:1 on --bg-dark) */
            --text-muted: rgba(250, 250, 250, 0.72);  /* reading text: intros, descriptions, modal body (9.6:1) */
            --text-faint: rgba(250, 250, 250, 0.55);  /* notes and hints (5.9:1) */
            --glow-gold: #FFC700;
            --glass: rgba(255, 255, 255, 0.01);
            --nebula-purple: #4B0082;
            --nebula-blue: #000080;
            --error-red: #FF4444;
            /* Hairlines. Every frame, rule and divider on the page is 1 px of one of these two. */
            --edge: rgba(255, 215, 0, 0.22);
            --edge-strong: rgba(255, 215, 0, 0.8);
            /* Cut corners share one slope (2:1) at three sizes: buttons, cards, the modal; the contact panel
               is a parallelogram. A CSS border is clipped away along the diagonal by clip-path, so each frame
               draws its hairline as a ::before clipped to a ring: the cut polygon minus the same polygon inset
               1 px (even-odd, joined by a zero-width seam at the first corner). The element keeps the cut and
               its glass fill; the ring sits on top, 1 px wide all the way round. */
            --cut-button: polygon(0 0, calc(100% - 32px) 0, 100% 16px, 100% 100%, 32px 100%, 0 calc(100% - 16px));
            --ring-button: polygon(evenodd,
                0 0, calc(100% - 32px) 0, 100% 16px, 100% 100%, 32px 100%, 0 calc(100% - 16px), 0 0,
                1px 1px, calc(100% - 32.2px) 1px, calc(100% - 1px) 16.6px, calc(100% - 1px) calc(100% - 1px),
                32.2px calc(100% - 1px), 1px calc(100% - 16.6px), 1px 1px);
            --cut-card: polygon(0 0, 100% 0, 100% calc(100% - 24px), calc(100% - 48px) 100%, 0 100%);
            --ring-card: polygon(evenodd,
                0 0, 100% 0, 100% calc(100% - 24px), calc(100% - 48px) 100%, 0 100%, 0 0,
                1px 1px, calc(100% - 1px) 1px, calc(100% - 1px) calc(100% - 24.6px), calc(100% - 48.2px) calc(100% - 1px),
                1px calc(100% - 1px), 1px 1px);
            --cut-modal: polygon(0 0, calc(100% - 40px) 0, 100% 20px, 100% 100%, 40px 100%, 0 calc(100% - 20px));
            --ring-modal: polygon(evenodd,
                0 0, calc(100% - 40px) 0, 100% 20px, 100% 100%, 40px 100%, 0 calc(100% - 20px), 0 0,
                1px 1px, calc(100% - 40.2px) 1px, calc(100% - 1px) 20.6px, calc(100% - 1px) calc(100% - 1px),
                40.2px calc(100% - 1px), 1px calc(100% - 20.6px), 1px 1px);
            --cut-panel: polygon(5% 0, 100% 0, 95% 100%, 0 100%);
            --ring-panel: polygon(evenodd,
                5% 0, 100% 0, 95% 100%, 0 100%, 5% 0,
                calc(5% + 1px) 1px, calc(100% - 1px) 1px, calc(95% - 1px) calc(100% - 1px), 1px calc(100% - 1px), calc(5% + 1px) 1px);
            /* Vertical rhythm: one section measure, one header gap */
            --section-pad: clamp(120px, 10vw, 176px);
            --header-gap: 96px;
        }

        /* Keyboard focus: one gold ring for every control. Inputs use their own border + glow instead. */
        :focus-visible {
            outline: 1px solid var(--primary);
            outline-offset: 4px;
        }

        .form-control:focus-visible {
            outline: none;
        }

        /* Backstop against horizontal overflow: `clip` clips without creating a scroll
           container (unlike `hidden`), so scrollWidth stays equal to the viewport width. */
        html {
            overflow-x: clip;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            background: var(--bg-dark);
            color: var(--text-light);
            overflow-x: hidden;
            overflow-x: clip;
            position: relative;
        }

        /* No text selection on the page (client rule). The form's fields keep it so typed text can be
           edited; site.js closes the keyboard route (Ctrl/Cmd+A outside a field). */
        body {
            -webkit-user-select: none;
            user-select: none;
        }

        input,
        textarea {
            -webkit-user-select: text;
            user-select: text;
        }

        /* Custom cursor gate — the JS gate in universe.js (createCursor) adds `html.has-cursor`
           once it is actually driving the custom cursor on a fine primary pointer. Only then is
           the native cursor hidden. A page that does not load the scene (privacy, error) has no
           class and keeps its pointer; so does the front page if universe.js itself never runs (if only WebGL is refused, universe.js still
           drives the custom cursor on its fallback path). The
           `(pointer: fine)` media query alone used to hide the pointer on every page, and the
           privacy page had none at all. */
        .cursor,
        .cursor-follower,
        .cursor-trail {
            display: none;
        }

        @media (pointer: fine) {
            html.has-cursor * {
                cursor: none !important;
            }

            html.has-cursor .cursor,
            html.has-cursor .cursor-follower,
            html.has-cursor .cursor-trail {
                display: block;
            }
        }

        /* Background layers: a static deep-space gradient (also the no-WebGL
           fallback) beneath the single WebGL canvas. Both sit below all content.
           Their height is the LARGE viewport (100lvh; 100vh is the same thing on every phone
           browser and the window on a desktop), not 100 % of a fixed box, which is the layout
           viewport and grows and shrinks with a phone's URL bar: sized to the large viewport they
           already cover the rows the bar reveals when it collapses, so nothing is uncovered and
           nothing is resized — universe.js draws the canvas at this box and composes the scene
           for the containing block (the 100svh the hero fills), the rest being the same image
           continued (measureView). */
        #space-bg {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100vh;
            height: 100lvh;
            z-index: 1;
            pointer-events: none;
            background:
                radial-gradient(ellipse 80% 60% at 50% 45%, rgba(24, 22, 60, 0.9) 0%, rgba(8, 8, 24, 0.6) 45%, rgba(0, 0, 0, 0) 100%),
                radial-gradient(ellipse 60% 50% at 80% 20%, rgba(75, 0, 130, 0.18) 0%, rgba(0, 0, 0, 0) 100%),
                #030308;
        }

        #universe {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100vh;
            height: 100lvh;
            z-index: 2;
            display: block;
            pointer-events: none;
        }

        .no-webgl #universe {
            display: none;
        }

        /* Cinematic Vignette (the large viewport too, so its darkening stands still as the bar moves) */
        .vignette {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100vh;
            height: 100lvh;
            pointer-events: none;
            z-index: 50;
            background: radial-gradient(ellipse at center,
                transparent 0%,
                transparent 40%,
                rgba(0, 0, 0, 0.4) 80%,
                rgba(0, 0, 0, 0.8) 100%);
        }

        @media (max-width: 768px) {
            .vignette {
                background: radial-gradient(ellipse at center,
                    transparent 0%,
                    transparent 60%,
                    rgba(0, 0, 0, 0.2) 90%,
                    rgba(0, 0, 0, 0.4) 100%);
            }
        }

        /* Film grain and nebula haze are rendered inside the WebGL scene (universe.js);
           no full-screen CSS filters or blend modes remain in the background stack. */

        /* The loader is the veil. It lifts in 700 ms, plainly — no flare, no blur — on a scene that
           is already running, and its rings turn to the end (status, not decoration). site.js adds
           .hidden and html.is-arrived at the same moment: that is the arrival clock every entrance
           below starts from, so nothing can blur in under the veil. */
        .loader {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: var(--bg-dark);
            z-index: 10000;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: opacity 700ms cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 700ms;
        }

        .loader.hidden {
            opacity: 0;
            visibility: hidden;
        }

        .loader-content {
            text-align: center;
        }

        /* Three hairline rings turning at steady, Keplerian speeds (inner fastest): the same language as
           the wordmark's tracked caps and glow, and the planet's rings and three moons in the scene. */
        .loader-ring {
            width: 150px;
            height: 150px;
            border: 1px solid transparent;
            border-top-color: var(--primary);
            border-right-color: var(--luxury-gold);
            border-radius: 50%;
            animation: loader-rotate 3s linear infinite;
            margin: 0 auto 36px;
            position: relative;
            filter: drop-shadow(0 0 16px rgba(255, 215, 0, 0.6));
        }

        .loader-ring::before,
        .loader-ring::after {
            content: '';
            position: absolute;
            border-radius: 50%;
            border: 1px solid transparent;
        }

        .loader-ring::before {
            width: 130px;
            height: 130px;
            top: 9px;
            left: 9px;
            border-left-color: var(--champagne);
            border-bottom-color: var(--bronze);
            animation: loader-rotate 2.1s linear infinite reverse;
        }

        .loader-ring::after {
            width: 110px;
            height: 110px;
            top: 19px;
            left: 19px;
            border-right-color: var(--platinum);
            border-top-color: var(--luxury-gold);
            animation: loader-rotate 1.4s linear infinite;
        }

        .loader-text {
            font-size: 1.1rem;
            font-weight: 200;
            letter-spacing: 0.3em;
            color: var(--primary);
            opacity: 0.8;
            animation: pulse 2s ease-in-out infinite;
        }

        /* Disable loader text animation on mobile */
        @media (max-width: 768px) {
            .loader-text {
                animation: none;
            }
        }

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

        @keyframes pulse {
            0%, 100% { opacity: 0.8; }
            50% { opacity: 0.4; }
        }

        /* Custom cursor: positioned by universe.js with transform writes only
           (translate3d + scale), so no layout work and no transition on transform. */
        .cursor {
            width: 20px;
            height: 20px;
            background: radial-gradient(circle,
                rgba(255, 215, 0, 1) 0%,
                rgba(255, 215, 0, 0.8) 30%,
                rgba(218, 165, 32, 0.3) 60%,
                transparent 100%);
            border-radius: 50%;
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 999999;
            mix-blend-mode: screen;
            transform: translate3d(-100px, -100px, 0) translate(-50%, -50%);
            will-change: transform;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .cursor-follower {
            width: 40px;
            height: 40px;
            border: 1px solid rgba(255, 215, 0, 0.3);
            border-radius: 50%;
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 999998;
            transition: opacity 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
            background: radial-gradient(circle,
                transparent 30%,
                rgba(255, 215, 0, 0.1) 100%);
            box-shadow:
                0 0 20px rgba(255, 215, 0, 0.3),
                inset 0 0 20px rgba(255, 215, 0, 0.15);
            transform: translate3d(-100px, -100px, 0) translate(-50%, -50%);
            will-change: transform;
            opacity: 0;
        }

        .cursor.is-visible,
        .cursor-follower.is-visible {
            opacity: 1;
        }

        .cursor-follower.is-hover {
            border-color: var(--luxury-gold);
            background: radial-gradient(circle,
                rgba(255, 215, 0, 0.3) 0%,
                transparent 70%);
        }

        /* Click-and-hold pan (universe.js adds html.is-panning while one is live): the follower
           closes to a grab — its size is the JS's damped scale (transform only, like its motion);
           here the line firms and the glow draws in, on the transition the ring already has. */
        html.is-panning .cursor-follower {
            border-color: rgba(255, 215, 0, 0.55);
            box-shadow:
                0 0 10px rgba(255, 215, 0, 0.2),
                inset 0 0 8px rgba(255, 215, 0, 0.2);
        }

        /* Pooled trail sparks; animated with the Web Animations API (transform + opacity only) */
        .cursor-trail {
            position: fixed;
            top: 0;
            left: 0;
            width: 16px;
            height: 16px;
            border-radius: 50%;
            pointer-events: none;
            z-index: 999997;
            opacity: 0;
            background: radial-gradient(circle,
                #FFD700 0%,
                rgba(255, 215, 0, 0.6) 30%,
                transparent 70%);
            transform: translate3d(-100px, -100px, 0) translate(-50%, -50%);
            will-change: transform, opacity;
        }

        /* Navigation - Cinematic Style */
        nav {
            position: fixed;
            top: 0;
            width: 100%;
            padding: 40px 60px;
            z-index: 10000; /* Increased z-index to stay above everything */
            /* No backdrop-filter. The bar used to frost the scene behind it (blur(20px) saturate(180%)),
               which cost the GPU process 13–15 ms per second — about a third of what the whole WebGL
               scene costs — and showed nothing: over a near-black sky behind a bar that is 80 % black at
               rest and 95 % once scrolled, blur on and off differ by 0.6–2.8 levels of 255 on average,
               with at most 2 % of the bar's pixels more than 8 levels apart (measured 2026-09-07). */
            background: linear-gradient(to bottom,
                rgba(10, 10, 10, 0.8),
                rgba(10, 10, 10, 0));
            transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        }

        nav.scrolled {
            padding: 20px 60px;
            background: rgba(10, 10, 10, 0.95);
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
        }

        nav::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            height: 1px;
            background: linear-gradient(90deg,
                transparent,
                var(--primary) 30%,
                var(--luxury-gold) 50%,
                var(--primary) 70%,
                transparent);
            /* The hairline glows when something happens: --flare is the scene's flare (universe.js writes it
               on <html> through a tidal event, 0.35 + 0.45 at the peak) and nothing else moves it. */
            opacity: calc(0.35 + 0.45 * var(--flare, 0));
        }

        .nav-container {
            max-width: 1400px;
            margin: 0 auto;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .nav-links {
            display: flex;
            gap: 40px;
            align-items: center;
            list-style: none;
        }

        /* Links keep their text size; the padding (cancelled by the margin) gives a 45 px hit area for touch */
        .nav-link {
            display: inline-block;
            padding: 12px 4px;
            margin: -12px -4px;
            color: var(--text-light);
            text-decoration: none;
            font-weight: 300;
            letter-spacing: 0.1em;
            line-height: 1.3;
            transition: color 0.3s ease;
            position: relative;
        }

        .nav-link::after {
            content: '';
            position: absolute;
            bottom: 7px;
            left: 4px;
            width: 0;
            height: 1px;
            background: var(--primary);
            transition: width 0.3s ease;
            box-shadow: 0 0 10px var(--primary);
        }

        .nav-link:hover::after {
            width: calc(100% - 8px);
        }

        .nav-link:hover {
            color: var(--primary);
        }

        /* Language switch: the fourth nav item, set apart by a hairline and the quieter text tone */
        .nav-lang {
            margin-left: 8px;
            padding: 13px 4px 13px 28px; /* 44 px hit area at 0.9 rem */
            color: var(--text-muted);
            font-size: 0.9rem;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            border-left: 1px solid var(--edge);
        }

        .nav-lang::after {
            left: 28px;
        }

        .nav-lang:hover::after {
            width: calc(100% - 32px);
        }

        /* Mobile Menu */
        .mobile-menu-toggle {
            display: none;
            background: transparent;
            border: none;
            color: var(--primary);
            font-size: 24px;
            cursor: pointer;
            padding: 10px;
            z-index: 10001; /* Increased z-index */
            transition: transform 0.3s ease;
            position: relative;
        }

        .mobile-menu-toggle:hover {
            transform: scale(1.1);
        }

        .mobile-menu-toggle svg {
            width: 30px;
            height: 30px;
            display: block;
        }

        .mobile-menu-toggle .menu-bar-1,
        .mobile-menu-toggle .menu-bar-2,
        .mobile-menu-toggle .menu-bar-3 {
            transition: all 0.3s ease;
            transform-origin: center;
        }

        .mobile-menu-toggle:hover .menu-bar-1 {
            transform: translateY(-2px);
        }

        .mobile-menu-toggle:hover .menu-bar-3 {
            transform: translateY(2px);
        }

        /* When menu is active, transform to X */
        .nav-links.active ~ .mobile-menu-toggle .menu-bar-1 {
            transform: rotate(45deg) translate(5px, 5px);
        }

        .nav-links.active ~ .mobile-menu-toggle .menu-bar-2 {
            opacity: 0;
            transform: scaleX(0);
        }

        .nav-links.active ~ .mobile-menu-toggle .menu-bar-3 {
            transform: rotate(-45deg) translate(5px, -5px);
        }

        @media (max-width: 768px) {
            /* Closed, the panel is off-canvas and also visibility:hidden, so its links cannot take focus
               or be read until it opens (the visibility flips after the slide on close, before it on open) */
            .nav-links {
                position: fixed;
                top: 0;
                right: -100%;
                width: 80%;
                max-width: 300px;
                height: 100vh;
                height: 100dvh;
                background: rgba(10, 10, 10, 0.98);
                backdrop-filter: blur(20px);
                flex-direction: column;
                padding: 80px 30px;
                gap: 8px;
                visibility: hidden;
                overscroll-behavior: contain;
                transition: right 0.3s ease, visibility 0s linear 0.3s;
                z-index: 9999; /* High z-index for mobile menu */
                box-shadow: -5px 0 20px rgba(0, 0, 0, 0.8);
                pointer-events: auto; /* the bar takes no pointer on a phone (the mobile nav rule); the panel does */
            }

            .nav-links.active {
                right: 0;
                visibility: visible;
                transition: right 0.3s ease, visibility 0s;
            }

            /* Menu links: block, 45 px tall, no negative margins */
            .nav-links .nav-link {
                display: block;
                padding: 12px 8px;
                margin: 0;
                text-align: center;
            }

            .nav-links .nav-lang {
                margin-top: 16px;
                padding-left: 8px;
                border-left: 0;
                border-top: 1px solid var(--edge);
                padding-top: 20px;
            }

            .nav-links .nav-link::after {
                display: none;
            }

            /* The burger is the whole top bar on a phone (the mobile nav rule further down hides the bar's
               ground and the wordmark), so it floats alone over the scene and carries its own ground: the
               cards' dark glass — a 62 % black fill under a 10 px backdrop blur — with a hairline ring in
               the gold family (an inset shadow, so the box stays 46 px: the 30 px glyph plus 8 px of
               padding) and a soft drop shadow that lifts it off the planet's limb and off open sky
               alike. It takes the pointer back from the bar. */
            .mobile-menu-toggle {
                display: block !important;
                position: relative;
                z-index: 10002 !important;
                pointer-events: auto;
                background: rgba(10, 10, 10, 0.62);
                backdrop-filter: blur(10px);
                box-shadow:
                    inset 0 0 0 1px rgba(255, 215, 0, 0.16),
                    0 6px 18px rgba(0, 0, 0, 0.45);
                border-radius: 10px;
                padding: 8px;
            }

            .nav-container {
                display: flex;
                justify-content: flex-end; /* the burger alone, at the right */
                align-items: center;
                width: 100%;
                max-width: 100%;
                margin: 0;
                padding: 0;
            }
        }

        .logo {
            font-size: 24px;
            font-weight: 200;
            letter-spacing: 8px;
            color: var(--primary);
            text-transform: uppercase;
            text-decoration: none; /* a link to the language root */
            display: inline-block;
            padding: 8px 0; /* 45 px hit area on touch; the margin cancels the layout change */
            margin: -8px 0;
            position: relative;
            text-shadow:
                0 0 10px var(--primary),
                0 0 20px var(--primary),
                0 0 30px var(--primary);
            animation: logo-glow 3s ease-in-out infinite;
        }

        @keyframes logo-glow {
            0%, 100% {
                text-shadow:
                    0 0 10px var(--primary),
                    0 0 20px var(--primary),
                    0 0 30px var(--primary);
            }
            50% {
                text-shadow:
                    0 0 20px var(--primary),
                    0 0 30px var(--primary),
                    0 0 40px var(--primary);
            }
        }

        /* Disable logo glow animation on mobile */
        @media (max-width: 768px) {
            .logo {
                animation: none;
                text-shadow: 0 0 15px var(--primary);
            }
        }

        /* Hero Section - Cinematic Epic */
        .hero {
            height: auto;
            min-height: 100vh;
            min-height: 100svh; /* the visible screen on phones, not the URL-bar-less one */
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            z-index: 10;
            overflow-x: clip; /* the ::before glow (920px, 544px on mobile — the baked blur widened it) must not widen the page */
        }

        /* The glow behind the wordmark. It was an 800 px three-stop gradient under filter: blur(40px); the
           blur is now baked into the stops (the gradient convolved with a 40 px gaussian, sampled every 8 px,
           in the premultiplied space CSS interpolates in) and the box is the blurred extent, so the pulse
           animates a plain gradient layer and the compositor no longer re-blurs an 800 px surface every frame
           (audit O2). Proven pixel-identical at 0 % and 50 % of the pulse. */
        .hero::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 920px;
            height: 920px;
            background: radial-gradient(circle,
                rgba(249, 206, 6, 0.1705) 0px,
                rgba(249, 206, 6, 0.1702) 8px,
                rgba(248, 206, 6, 0.1693) 16px,
                rgba(248, 205, 6, 0.1679) 24px,
                rgba(247, 205, 7, 0.1660) 32px,
                rgba(247, 204, 7, 0.1636) 40px,
                rgba(246, 203, 8, 0.1607) 48px,
                rgba(245, 202, 9, 0.1576) 56px,
                rgba(244, 200, 10, 0.1541) 64px,
                rgba(243, 199, 11, 0.1504) 72px,
                rgba(242, 197, 12, 0.1465) 80px,
                rgba(240, 195, 13, 0.1425) 88px,
                rgba(239, 193, 14, 0.1384) 96px,
                rgba(237, 191, 15, 0.1342) 104px,
                rgba(235, 189, 17, 0.1299) 112px,
                rgba(234, 186, 18, 0.1256) 120px,
                rgba(232, 184, 20, 0.1214) 128px,
                rgba(230, 182, 21, 0.1171) 136px,
                rgba(229, 179, 23, 0.1129) 144px,
                rgba(227, 177, 24, 0.1088) 152px,
                rgba(226, 175, 25, 0.1047) 160px,
                rgba(224, 173, 27, 0.1007) 168px,
                rgba(223, 172, 28, 0.0968) 176px,
                rgba(222, 170, 29, 0.0929) 184px,
                rgba(221, 169, 29, 0.0892) 192px,
                rgba(220, 168, 30, 0.0855) 200px,
                rgba(220, 167, 31, 0.0818) 208px,
                rgba(219, 166, 31, 0.0782) 216px,
                rgba(219, 166, 31, 0.0746) 224px,
                rgba(218, 166, 32, 0.0711) 232px,
                rgba(218, 165, 32, 0.0675) 240px,
                rgba(218, 165, 32, 0.0640) 248px,
                rgba(218, 165, 32, 0.0605) 256px,
                rgba(218, 165, 32, 0.0570) 264px,
                rgba(218, 165, 32, 0.0535) 272px,
                rgba(218, 165, 32, 0.0500) 280px,
                rgba(218, 165, 32, 0.0465) 288px,
                rgba(218, 165, 32, 0.0430) 296px,
                rgba(218, 165, 32, 0.0396) 304px,
                rgba(218, 165, 32, 0.0361) 312px,
                rgba(218, 165, 32, 0.0327) 320px,
                rgba(218, 165, 32, 0.0293) 328px,
                rgba(218, 165, 32, 0.0260) 336px,
                rgba(218, 165, 32, 0.0228) 344px,
                rgba(218, 165, 32, 0.0198) 352px,
                rgba(218, 165, 32, 0.0169) 360px,
                rgba(218, 165, 32, 0.0141) 368px,
                rgba(218, 165, 32, 0.0117) 376px,
                rgba(218, 165, 32, 0.0094) 384px,
                rgba(218, 165, 32, 0.0075) 392px,
                rgba(218, 165, 32, 0.0058) 400px,
                rgba(218, 165, 32, 0.0044) 408px,
                rgba(218, 165, 32, 0.0032) 416px,
                rgba(218, 165, 32, 0.0023) 424px,
                rgba(218, 165, 32, 0.0016) 432px,
                rgba(218, 165, 32, 0.0011) 440px,
                rgba(218, 165, 32, 0.0007) 448px,
                transparent 456px);
            transform: translate(-50%, -50%);
            animation: hero-pulse 6s ease-in-out infinite;
        }

        @keyframes hero-pulse {
            0%, 100% {
                transform: translate(-50%, -50%) scale(1);
                opacity: 0.3;
            }
            50% {
                transform: translate(-50%, -50%) scale(1.3);
                opacity: 0.1;
            }
        }

        /* Disable hero pulse on mobile */
        @media (max-width: 768px) {
            @keyframes hero-pulse {
                0%, 100% {
                    transform: translate(-50%, -50%) scale(1);
                    opacity: 0.2;
                }
            }
        }

        .hero-content {
            text-align: center;
            z-index: 10;
            opacity: 0;
            /* Starts 150 ms after the veil begins to lift and takes 1.8 s: at 3 s on the slower curve,
               after a 0.3 s wait, the wordmark was barely there for its first second and read as late
               (client, 2026-09-06); at 0 ms its first 0.4 s was a blurred smear under the still-
               translucent veil (QA, 2026-09-07). It is legible about a second after the veil starts to
               lift, and the tagline follows while it is still settling rather than after a pause. */
            animation: epic-reveal 1.8s cubic-bezier(0.6, 0, 0.2, 1) 150ms both;
        }

        /* One clock (site.js initLoader). Every entrance in the hero and the chrome is held at its
           first frame until html.is-arrived, the moment the veil starts to lift: the wordmark at
           +0.15 s, the tagline at +1.3 s, the button at +2.3 s, the controls at +3.4 s and the consent
           banner (site.js) last. A paused animation waits through its delay as well, so the delays
           count from the arrival, and the phone and reduced-motion rules that set `animation: none`
           are untouched by this. */
        html:not(.is-arrived) .hero-content,
        html:not(.is-arrived) .tagline,
        html:not(.is-arrived) .premium-button,
        html:not(.is-arrived) .render-control,
        html:not(.is-arrived) .sound-control {
            animation-play-state: paused;
        }

        @keyframes epic-reveal {
            0% {
                opacity: 0;
                transform: translateY(100px) scale(0.8);
                filter: blur(20px);
            }
            50% {
                filter: blur(5px);
            }
            100% {
                opacity: 1;
                transform: translateY(0) scale(1);
                filter: blur(0);
            }
        }

        .luxury-title {
            font-size: clamp(3rem, 8.5vw, 8rem); /* 8 rem from 1506 px; below that the wordmark keeps side margins */
            font-weight: 100;
            text-transform: uppercase;
            letter-spacing: 0.3em;
            line-height: 1;
            margin-bottom: 36px;
            position: relative;
            background: linear-gradient(135deg,
                var(--primary) 0%,
                var(--champagne) 25%,
                var(--luxury-gold) 50%,
                var(--glow-gold) 75%,
                var(--primary) 100%);
            background-size: 200% 200%;
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            filter: drop-shadow(0 0 50px rgba(255, 215, 0, 0.7));
            animation: title-shimmer 4s ease-in-out infinite;
        }

        @keyframes title-shimmer {
            0%, 100% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
        }

        /* Disable title shimmer on mobile */
        @media (max-width: 768px) {
            @keyframes title-shimmer {
                0%, 100% { background-position: 0% 50%; }
            }
        }

        .luxury-title::before {
            content: attr(data-text);
            position: absolute;
            left: 0;
            top: 0;
            z-index: -1;
            background: linear-gradient(135deg,
                var(--primary) 0%,
                var(--champagne) 50%,
                var(--luxury-gold) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            filter: blur(5px);
            opacity: 0.7;
            animation: title-glow 3s ease-in-out infinite;
        }

        /* Opacity only: scaling the blurred ghost doubled the letters at 8 rem */
        @keyframes title-glow {
            0%, 100% { opacity: 0.45; }
            50% { opacity: 0.75; }
        }

        /* The tagline does the headline's work: sentence tracking and a measure. If the copy ever carries an
           emphasised span (.tagline-hold) it is set in the same gold as the cards' outcome lines. */
        .tagline {
            font-size: clamp(1.25rem, 0.95rem + 0.85vw, 1.85rem);
            font-weight: 300;
            letter-spacing: 0.08em;
            line-height: 1.45;
            opacity: 0.9;
            color: var(--champagne);
            max-width: 30em;
            margin: 0 auto 56px;
            text-wrap: balance;
            position: relative;
            animation: tagline-fade 2s ease 1300ms both;
        }

        .tagline-hold {
            color: var(--primary);
        }

        /* A short drift (0.14 → 0.08 em, about 45 px at 1440) so the line never wraps and snaps */
        @keyframes tagline-fade {
            from {
                opacity: 0;
                letter-spacing: 0.14em;
            }
            to {
                opacity: 0.9;
                letter-spacing: 0.08em;
            }
        }

        /* The call to action follows the tagline. Opacity only, so the box the scene measures for the
           star's corridor (eventGeometry in universe.js) never moves. The same fade brings in the two
           bottom-right controls a second later (.render-control, .sound-control). */
        .premium-button {
            animation: arrive-fade 900ms ease 2300ms both;
        }

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

        /* Buttons: the hero CTA and the form's submit share one frame, one fill, one hover.
           ::before is the hairline ring; ::after is the shine sweep, under the label.
           Hover: the ring brightens, the fill warms, a 3 px lift. Nothing changes width. */
        .premium-button,
        .submit-button {
            display: inline-block;
            padding: 20px 56px;
            margin: 0;
            background: linear-gradient(135deg,
                rgba(255, 215, 0, 0.1) 0%,
                rgba(255, 215, 0, 0.04) 100%);
            backdrop-filter: blur(10px);
            border: 0;
            color: var(--primary);
            font-family: inherit;
            text-decoration: none;
            text-transform: uppercase;
            letter-spacing: 0.25em;
            font-weight: 300;
            font-size: 1rem;
            line-height: 1.4;
            position: relative;
            isolation: isolate;
            overflow: hidden;
            transition: box-shadow 0.4s ease, transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
            clip-path: var(--cut-button);
        }

        .premium-button::before,
        .submit-button::before {
            content: '';
            position: absolute;
            inset: 0;
            pointer-events: none;
            background: var(--edge);
            clip-path: var(--ring-button);
            transition: background-color 0.4s ease;
        }

        /* The flare lights the hero button's ring: --edge (0.22) plus half the scene's flare, so at the peak
           it is nearly the hover ring, which still wins. */
        .premium-button::before {
            background: rgba(255, 215, 0, calc(0.22 + 0.5 * var(--flare, 0)));
        }

        .premium-button::after,
        .submit-button::after {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            z-index: -1;
            background: linear-gradient(90deg,
                transparent,
                rgba(255, 215, 0, 0.25),
                transparent);
            transition: left 0.6s ease;
        }

        .premium-button:hover,
        .premium-button:focus-visible,
        .submit-button:hover,
        .submit-button:focus-visible {
            box-shadow: inset 0 0 40px rgba(255, 215, 0, 0.14);
            transform: translateY(-3px);
        }

        .premium-button:hover::before,
        .premium-button:focus-visible::before,
        .submit-button:hover::before,
        .submit-button:focus-visible::before {
            background: var(--edge-strong);
        }

        .premium-button:hover::after,
        .submit-button:hover::after {
            left: 100%;
        }

        /* Services Section - Cinematic */
        .services {
            padding: var(--section-pad) 60px;
            position: relative;
            z-index: 10;
            background: linear-gradient(to bottom,
                transparent,
                rgba(10, 10, 10, 0.8) 50%,
                transparent);
        }

        .container {
            max-width: 1400px; /* same measure as .nav-container */
            margin: 0 auto;
        }

        .section-header {
            text-align: center;
            margin-bottom: var(--header-gap);
            overflow-x: clip; /* the title's flanking hairlines sit outside its box and must not widen the page */
        }

        /* The header fades up when it enters, not at load (site.js initReveal(), the cards' mechanism:
           backwards fill, so once played the header is back on its normal styles). */
        .section-header.reveal-pending {
            opacity: 0;
        }

        .section-header.is-revealed {
            animation: fadeInUp 1s ease backwards;
        }

        @keyframes fadeInUp {
            from { opacity: 0; transform: translateY(30px); }
            to   { opacity: 1; transform: translateY(0); }
        }

        /* Section titles: gradient caps with one static hairline either side (inline-block, so the lines
           flank the words rather than the column). The contact title is the same at a smaller size. */
        .section-title,
        .contact-title {
            display: inline-block;
            font-weight: 100;
            letter-spacing: 0.2em;
            line-height: 1.1;
            background: linear-gradient(135deg,
                var(--primary) 0%,
                var(--champagne) 50%,
                var(--luxury-gold) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            position: relative;
            filter: drop-shadow(0 0 30px rgba(255, 215, 0, 0.4));
        }

        .section-title {
            font-size: 4rem;
            margin-bottom: 28px;
        }

        .contact-title {
            font-size: 2.75rem;
            letter-spacing: 0.15em;
            margin-bottom: 22px;
        }

        .section-title::before,
        .section-title::after,
        .contact-title::before,
        .contact-title::after {
            content: '';
            position: absolute;
            top: 50%;
            width: 120px;
            height: 1px;
            opacity: 0.5;
        }

        .section-title::before,
        .contact-title::before {
            left: -160px;
            background: linear-gradient(90deg, transparent, var(--primary));
        }

        .section-title::after,
        .contact-title::after {
            right: -160px;
            background: linear-gradient(90deg, var(--primary), transparent);
        }

        .contact-title::before,
        .contact-title::after {
            width: 80px;
        }

        .contact-title::before {
            left: -112px;
        }

        .contact-title::after {
            right: -112px;
        }

        /* Section intros: reading text, a measure, balanced wrap */
        .section-subtitle,
        .contact-subtitle {
            font-size: 1.2rem;
            font-weight: 300;
            letter-spacing: 0.02em;
            line-height: 1.6;
            color: var(--text-muted);
            max-width: 36em;
            margin: 0 auto;
            text-wrap: balance;
        }

        .contact-subtitle {
            margin-bottom: 56px;
        }

        /* Service cards: hairline frame with a cut corner (see --cut-card), icon / title / description
           stacked, the outcome line held to the bottom so the three read level. Hover: the frame brightens,
           the fill warms, a 6 px lift; the same gesture as the buttons. */
        .services-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
            gap: 48px;
        }

        .service-card {
            display: flex;
            flex-direction: column;
            background: linear-gradient(135deg,
                rgba(255, 255, 255, 0.03) 0%,
                rgba(255, 255, 255, 0.01) 100%);
            backdrop-filter: blur(20px);
            padding: 64px 48px 48px;
            position: relative;
            isolation: isolate;
            overflow: hidden;
            transition: box-shadow 0.5s ease, transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
            clip-path: var(--cut-card);
        }

        .service-card::before {
            content: '';
            position: absolute;
            inset: 0;
            pointer-events: none;
            background: rgba(255, 215, 0, calc(0.22 + 0.5 * var(--flare, 0))); /* --edge, lit by the flare (see .premium-button::before) */
            clip-path: var(--ring-card);
            transition: background-color 0.5s ease;
        }

        .service-card:hover {
            box-shadow: inset 0 0 90px rgba(255, 215, 0, 0.07);
            transform: translateY(-6px);
        }

        .service-card:hover::before {
            background: var(--edge-strong);
        }

        /* Scroll reveal (site.js toggles the classes). The entrance is a keyframe animation
           with fill-mode "backwards", so once it has played the card is back on its normal
           styles and the hover lift / border transition work as designed. */
        .service-card.reveal-pending {
            opacity: 0;
        }

        .service-card.is-revealed {
            animation: card-reveal 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) backwards;
        }

        @keyframes card-reveal {
            from { opacity: 0; transform: translateY(50px); }
            to   { opacity: 1; transform: translateY(0); }
        }

        .service-icon {
            margin-bottom: 32px;
            display: inline-block;
            filter: drop-shadow(0 0 24px rgba(255, 215, 0, 0.55));
            transition: filter 0.5s ease;
        }

        .service-card:hover .service-icon {
            filter: drop-shadow(0 0 28px rgba(255, 215, 0, 0.85));
        }

        /* Card icons: inline SVG diagrams in the scene's line language (1.25 hairline strokes on a 64 box, gold via
           currentColor; the only fills are the brass dots where a mass sits). The glow is the .service-icon filter above. */
        .service-icon svg {
            width: 72px;
            height: 72px;
            display: block;
            color: var(--primary);
        }

        .service-icon .icon-mass {
            fill: var(--bronze);
            stroke: none;
        }

        .service-icon .icon-dot {
            fill: currentColor;
            stroke: none;
        }

        .service-title {
            font-size: 1.4rem;
            font-weight: 300;
            letter-spacing: 0.08em;
            line-height: 1.3;
            color: var(--champagne);
            margin-bottom: 16px;
            -webkit-hyphens: auto;
            hyphens: auto; /* "Teknologirådgivning" (19 chars, no wrap point) may break at the card's minimum width */
        }

        .service-description {
            font-size: 1rem;
            font-weight: 300;
            line-height: 1.7;
            color: var(--text-muted);
            margin-bottom: 36px;
        }

        /* The outcome: one line, gold like the tagline's promise, above a hairline, pinned to the bottom */
        .service-outcome {
            margin-top: auto;
            padding-top: 22px;
            min-height: calc(3em + 22px); /* two lines, so the three hairlines sit level whether the line wraps or not */
            border-top: 1px solid var(--edge);
            font-size: 0.95rem;
            font-weight: 300;
            letter-spacing: 0.02em;
            line-height: 1.5;
            color: var(--primary);
            opacity: 0.85;
        }

        /* Disable epic reveal on mobile */
        @media (max-width: 768px) {
            .hero-content {
                animation: none;
                opacity: 1;
                transform: none;
                filter: none;
            }
        }

        /* Contact Section - Epic */
        .contact {
            padding: var(--section-pad) 60px;
            position: relative;
            z-index: 10;
            text-align: center;
        }

        /* The panel: a parallelogram (--cut-panel) framed like a ring seen edge-on. Two hairlines: a faint
           outer one on the cut, and 5 px in a brighter one whose stroke is lit from the top-left and fades
           along the edge (a gradient shows only through the ring polygon). Four short ticks mark the corners
           of the inner line (.panel-ticks). The ground lifts very softly toward the top-left. Felt, not noticed. */
        .contact-container {
            max-width: 1000px;
            margin: 0 auto;
            background:
                radial-gradient(70% 55% at 18% 0%, rgba(255, 215, 0, 0.055), transparent 70%),
                linear-gradient(135deg,
                    rgba(255, 255, 255, 0.02) 0%,
                    rgba(255, 255, 255, 0.01) 100%);
            backdrop-filter: blur(30px);
            padding: 96px 80px;
            position: relative;
            isolation: isolate;
            overflow: hidden;
            clip-path: var(--cut-panel);
        }

        .contact-container::before,
        .contact-container::after {
            content: '';
            position: absolute;
            pointer-events: none;
            clip-path: var(--ring-panel);
        }

        .contact-container::before {
            inset: 0;
            background: rgba(255, 215, 0, 0.1);
        }

        /* The panel is lit when you reach it. The outer hairline is always there; the inner ring's light runs
           from the corner it is lit from (top-left, ~308deg from the box centre in conic space at the panel's
           aspect) clockwise around the frame in 1.1 s, and the ticks appear last. The sweep is a conic mask
           whose edge is a registered <angle> (@property) so it can transition; a 6deg soft edge, one direction,
           under 1.4 s, so it reads as light and never as a spinner. Without @property, --lit is an untyped custom
           property and the mask is still valid: fully transparent at -6deg, so the ring is hidden while
           pending and appears at once on reveal, without the draw (a silent fallback, not a broken one). site.js toggles the classes; on phones the ring is
           display: none and the panel gets a quiet rise instead (below). */
        @property --lit {
            syntax: '<angle>';
            inherits: false;
            initial-value: 360deg;
        }

        .contact-container::after {
            inset: 5px;
            background: linear-gradient(135deg,
                rgba(255, 215, 0, 0.6) 0%,
                rgba(255, 215, 0, 0.28) 30%,
                rgba(255, 215, 0, 0.1) 60%,
                rgba(255, 215, 0, 0.22) 100%);
            --lit: 360deg;
            -webkit-mask: conic-gradient(from 308deg, #000 var(--lit), transparent calc(var(--lit) + 6deg));
            mask: conic-gradient(from 308deg, #000 var(--lit), transparent calc(var(--lit) + 6deg));
        }

        .contact-container.reveal-pending::after {
            --lit: -6deg; /* the soft edge too: nothing of the ring before the light arrives */
        }

        .contact-container.is-revealed::after {
            transition: --lit 1100ms cubic-bezier(0.4, 0, 0.2, 1);
        }

        .panel-ticks {
            position: absolute;
            inset: 5px;
            pointer-events: none;
            background:
                linear-gradient(var(--edge-strong), var(--edge-strong)) 5% 0 / 18px 1px no-repeat,
                linear-gradient(var(--edge-strong), var(--edge-strong)) 100% 0 / 18px 1px no-repeat,
                linear-gradient(var(--edge-strong), var(--edge-strong)) 0 100% / 18px 1px no-repeat,
                linear-gradient(var(--edge-strong), var(--edge-strong)) 95% 100% / 18px 1px no-repeat;
        }

        .contact-container.reveal-pending .panel-ticks {
            opacity: 0;
        }

        .contact-container.is-revealed .panel-ticks {
            transition: opacity 400ms ease 1000ms; /* after the light has come round */
        }

        /* Contact Form Styles */
        .contact-form {
            max-width: 600px;
            margin: 0 auto;
            position: relative;
            z-index: 10;
        }

        .form-group {
            margin-bottom: 32px;
            position: relative;
            text-align: left;
        }

        /* Underline fields: one hairline under the text, the label floating above once the field is in use.
           Lighter than the boxed inputs, so the panel reads quieter than the cards. 48 px tall. */
        .form-control {
            width: 100%;
            padding: 18px 16px 14px;
            background: transparent;
            border: 0;
            border-bottom: 1px solid var(--edge);
            color: var(--text-light);
            font-family: inherit;
            font-size: 1rem;
            font-weight: 300;
            letter-spacing: 0.04em;
            line-height: 1.4;
            transition: border-color 0.3s ease, box-shadow 0.3s ease;
            outline: none;
            border-radius: 0;
        }

        /* Focus: the underline goes gold with a soft glow beneath; no movement, so tabbing through stays still */
        .form-control:focus {
            border-bottom-color: var(--primary);
            box-shadow:
                0 1px 0 0 rgba(255, 215, 0, 0.35),
                0 14px 22px -14px rgba(255, 215, 0, 0.45);
        }

        .form-control::placeholder {
            color: rgba(255, 255, 255, 0.5);
            letter-spacing: 0.06em;
        }

        /* The label rises above the field once it is focused or filled: small gold caps, no backing box */
        .form-label {
            position: absolute;
            top: -14px;
            left: 16px;
            color: var(--text-dim);
            font-size: 0.72rem;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            font-weight: 300;
            opacity: 0;
            transform: translateY(4px);
            transition: opacity 0.3s ease, transform 0.3s ease, color 0.3s ease;
        }

        .form-control:focus ~ .form-label,
        .form-control:not(:placeholder-shown) ~ .form-label {
            opacity: 1;
            transform: none;
            color: var(--primary);
        }

        textarea.form-control {
            min-height: 132px;
            resize: vertical;
        }

        .form-row {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
        }

        @media (max-width: 768px) {
            .form-row {
                grid-template-columns: 1fr;
            }
        }

        /* Submit: the shared button rule above, full width */
        .submit-button {
            width: 100%;
            margin-top: 8px;
            cursor: pointer;
        }

        .submit-button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
        }

        .form-note {
            margin-top: 22px;
            font-size: 0.85rem;
            font-weight: 300;
            letter-spacing: 0.04em;
            line-height: 1.6;
            color: var(--text-faint);
        }

        /* Modal Styles */
        .modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.9);
            backdrop-filter: blur(10px);
            z-index: 100000;
            display: none;
            opacity: 0;
            transition: opacity 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        }

        .modal-overlay.active {
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .modal-overlay.show {
            opacity: 1;
        }

        /* The modal is the form's frame at the same hairline, cut like the buttons (--cut-modal) */
        .modal-content {
            max-width: 600px;
            width: 90%;
            background: rgba(10, 10, 10, 0.97);
            backdrop-filter: blur(30px);
            padding: 64px 60px 56px;
            position: relative;
            isolation: isolate;
            transform: scale(0.9) translateY(24px);
            opacity: 0;
            transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94), opacity 0.5s ease;
            clip-path: var(--cut-modal);
        }

        .modal-content::before {
            content: '';
            position: absolute;
            inset: 0;
            pointer-events: none;
            background: var(--edge);
            clip-path: var(--ring-modal);
        }

        .modal-overlay.show .modal-content {
            transform: scale(1) translateY(0);
            opacity: 1;
        }

        .modal-close {
            position: absolute;
            top: 16px;
            right: 16px;
            width: 44px;
            height: 44px;
            background: transparent;
            border: 1px solid var(--edge);
            border-radius: 50%;
            cursor: pointer;
            transition: transform 0.3s ease, border-color 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .modal-close::before,
        .modal-close::after {
            content: '';
            position: absolute;
            width: 20px;
            height: 2px;
            background: var(--primary);
            transition: all 0.3s ease;
        }

        .modal-close::before {
            transform: rotate(45deg);
        }

        .modal-close::after {
            transform: rotate(-45deg);
        }

        .modal-close:hover,
        .modal-close:focus-visible {
            transform: rotate(90deg);
            border-color: var(--edge-strong);
        }

        .modal-icon {
            width: 80px;
            height: 80px;
            margin: 0 auto 30px;
            position: relative;
        }

        .modal-icon.success {
            animation: success-pulse 1s ease;
        }

        @keyframes success-pulse {
            0% {
                transform: scale(0);
                opacity: 0;
            }
            50% {
                transform: scale(1.2);
            }
            100% {
                transform: scale(1);
                opacity: 1;
            }
        }

        .modal-icon.error {
            animation: error-shake 0.5s ease;
        }

        @keyframes error-shake {
            0%, 100% {
                transform: translateX(0);
            }
            20%, 60% {
                transform: translateX(-10px);
            }
            40%, 80% {
                transform: translateX(10px);
            }
        }

        .modal-title {
            font-size: 2rem;
            font-weight: 200;
            letter-spacing: 0.15em;
            line-height: 1.2;
            margin-bottom: 18px;
            text-align: center;
            background: linear-gradient(135deg,
                var(--primary) 0%,
                var(--champagne) 50%,
                var(--luxury-gold) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .modal-message {
            font-size: 1.1rem;
            font-weight: 300;
            line-height: 1.6;
            text-align: center;
            color: var(--text-muted);
            max-width: 32em;
            margin: 0 auto;
            text-wrap: balance;
        }

        /* Error styles */
        .form-error {
            color: var(--error-red);
            font-size: 0.85rem;
            font-weight: 300;
            letter-spacing: 0.03em;
            margin-top: 8px;
            display: none;
            animation: error-fade 0.3s ease;
        }

        @keyframes error-fade {
            from {
                opacity: 0;
                transform: translateY(-10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .form-control.error {
            border-bottom-color: var(--error-red);
        }

        /* Footer: the facts, under the same hairline the nav carries at the top of the page */
        footer {
            padding: 72px 60px 64px;
            text-align: center;
            font-size: 0.9rem;
            color: var(--text-dim);
            letter-spacing: 0.1em;
            line-height: 1.8;
            font-weight: 300;
            position: relative;
            z-index: 10;
        }

        footer::before {
            content: '';
            position: absolute;
            top: 0;
            left: 50%;
            width: min(360px, 70%);
            height: 1px;
            transform: translateX(-50%);
            background: linear-gradient(90deg, transparent, var(--primary) 50%, transparent);
            opacity: 0.35;
        }

        .footer-content {
            max-width: 800px;
            margin: 0 auto;
        }

        /* Links: colour to gold, a hairline grows in from the left (same as the nav) */
        .cvr-link {
            display: inline-flex !important;
            align-items: center;
            gap: 8px;
            font-size: 0.85rem;
            color: var(--text-dim);
            text-decoration: none;
            margin-top: 6px;
            padding: 10px 4px; /* 44 px hit area */
            position: relative;
            transition: color 0.3s ease;
        }

        .cvr-link::after {
            content: '';
            position: absolute;
            bottom: 6px;
            left: 0;
            width: 0;
            height: 1px;
            background: var(--primary);
            transition: width 0.3s ease;
        }

        .cvr-link:hover {
            color: var(--primary);
        }

        .cvr-link:hover::after {
            width: 100%;
        }

        .cvr-link img {
            filter: brightness(0.7);
            transition: filter 0.3s ease;
        }

        .cvr-link:hover img {
            filter: brightness(1);
        }

        /* Mobile Responsive Optimizations */
        @media (max-width: 768px) {
            /* Navigation: on a phone the top bar is the burger alone (client, 2026-09-07). The bar's
               ground, its shadow and its gold hairline are gone and the wordmark is not rendered — the
               hero carries the big one, and the menu still lists every link and the language switch —
               so the burger floats over the scene at the top right (its own ground is in the menu
               block above). The bar keeps its box: universe.js reads its height for the event corridor
               and the consent-banner lift's cap (navBottomPx), and the hero's 80 px of padding is
               measured against it. It takes no pointer, so a tap on the strip reaches what scrolls
               under it; the burger and the menu panel take theirs back. */
            nav,
            nav.scrolled {
                position: fixed !important;
                top: 0 !important;
                left: 0 !important;
                right: 0 !important;
                padding: 15px 20px;
                background: transparent !important;
                box-shadow: none;
                pointer-events: none;
                z-index: 10000 !important;
            }

            nav::after {
                display: none;
            }

            .logo {
                display: none;
            }

            /* Hero Section */
            .hero {
                padding-top: 80px; /* Account for fixed nav */
                transition: padding-bottom 0.4s ease; /* makes room with the consent banner's rise, not before it */
            }

            .hero::before {
                /* the 400 px gradient under the same 40 px blur, baked the same way (see the desktop rule) */
                width: 544px;
                height: 544px;
                background: radial-gradient(circle,
                    rgba(240, 195, 13, 0.1415) 0px,
                    rgba(240, 195, 13, 0.1410) 8px,
                    rgba(240, 195, 13, 0.1393) 16px,
                    rgba(239, 194, 14, 0.1366) 24px,
                    rgba(238, 192, 15, 0.1330) 32px,
                    rgba(237, 190, 16, 0.1285) 40px,
                    rgba(235, 188, 17, 0.1233) 48px,
                    rgba(234, 186, 18, 0.1176) 56px,
                    rgba(232, 184, 20, 0.1114) 64px,
                    rgba(230, 182, 21, 0.1049) 72px,
                    rgba(229, 179, 23, 0.0982) 80px,
                    rgba(227, 177, 24, 0.0914) 88px,
                    rgba(225, 175, 26, 0.0845) 96px,
                    rgba(224, 173, 27, 0.0777) 104px,
                    rgba(223, 171, 28, 0.0708) 112px,
                    rgba(222, 170, 29, 0.0641) 120px,
                    rgba(221, 169, 30, 0.0575) 128px,
                    rgba(220, 168, 30, 0.0510) 136px,
                    rgba(219, 167, 31, 0.0448) 144px,
                    rgba(219, 166, 31, 0.0388) 152px,
                    rgba(219, 166, 31, 0.0331) 160px,
                    rgba(218, 166, 32, 0.0278) 168px,
                    rgba(218, 165, 32, 0.0230) 176px,
                    rgba(218, 165, 32, 0.0186) 184px,
                    rgba(218, 165, 32, 0.0147) 192px,
                    rgba(218, 165, 32, 0.0114) 200px,
                    rgba(218, 165, 32, 0.0087) 208px,
                    rgba(218, 165, 32, 0.0064) 216px,
                    rgba(218, 165, 32, 0.0046) 224px,
                    rgba(218, 165, 32, 0.0032) 232px,
                    rgba(218, 165, 32, 0.0022) 240px,
                    rgba(218, 165, 32, 0.0014) 248px,
                    rgba(218, 165, 32, 0.0009) 256px,
                    rgba(218, 165, 32, 0.0006) 264px,
                    transparent 272px);
                animation: none; /* Disable pulsing on mobile */
            }

            .luxury-title {
                font-size: clamp(2.5rem, 12vw, 4rem);
                letter-spacing: 0.05em;
                animation: none;
                background: var(--primary);
                -webkit-background-clip: text;
                -webkit-text-fill-color: transparent;
                margin-bottom: 20px;
                filter: none; /* Remove drop shadow on mobile */
                text-shadow: none;
            }

            .luxury-title::before {
                display: none;
            }

            .tagline {
                font-size: 1.15rem;
                letter-spacing: 0.06em;
                margin-bottom: 40px;
                max-width: 20em;
                padding: 0 16px;
                animation: none; /* Disable animation on mobile */
                opacity: 0.9; /* Set static opacity */
            }

            .premium-button {
                padding: 15px 40px;
                font-size: 0.9rem;
                letter-spacing: 0.15em;
                animation: none; /* no entrance on phones, like the wordmark and the tagline */
            }

            /* Cut corners off on mobile: a plain 1 px border replaces each polygon ring */
            .premium-button,
            .submit-button,
            .service-card,
            .contact-container,
            .modal-content {
                clip-path: none;
                border: 1px solid var(--edge);
            }

            .premium-button::before,
            .submit-button::before,
            .service-card::before,
            .contact-container::before,
            .contact-container::after,
            .panel-ticks,
            .modal-content::before {
                display: none;
            }

            /* the flare lights the plain borders as it lights the rings (hover still wins, below) */
            .premium-button,
            .service-card {
                border-color: rgba(255, 215, 0, calc(0.22 + 0.5 * var(--flare, 0)));
            }

            .premium-button:hover,
            .premium-button:focus-visible,
            .submit-button:hover,
            .submit-button:focus-visible,
            .service-card:hover {
                border-color: var(--edge-strong);
            }

            /* Scroll reveal on phones: the header and the contact panel (no ring here) rise quietly when they enter */
            .contact-container.reveal-pending {
                opacity: 0;
            }

            .section-header.is-revealed,
            .contact-container.is-revealed {
                animation: quiet-rise 700ms ease backwards;
            }

            @keyframes quiet-rise {
                from { opacity: 0; transform: translateY(12px); }
                to   { opacity: 1; transform: translateY(0); }
            }

            /* Services Section */
            .services {
                padding: 100px 20px;
            }

            .section-header {
                margin-bottom: 60px;
            }

            .section-title {
                font-size: 2.5rem;
                letter-spacing: 0.1em;
            }

            .contact-title {
                font-size: 2rem;
                letter-spacing: 0.1em;
            }

            .section-title::before,
            .section-title::after,
            .contact-title::before,
            .contact-title::after {
                display: none;
            }

            .section-subtitle,
            .contact-subtitle {
                font-size: 1.05rem;
            }

            .contact-subtitle {
                margin-bottom: 44px;
            }

            .services-grid {
                grid-template-columns: 1fr;
                gap: 24px;
            }

            .service-card {
                padding: 40px 28px 32px;
                backdrop-filter: blur(10px);
                margin: 0 auto;
                max-width: 100%;
            }

            .service-icon {
                margin-bottom: 24px;
            }

            .service-icon svg {
                width: 56px;
                height: 56px;
            }

            .service-description {
                margin-bottom: 28px;
            }

            .service-outcome {
                padding-top: 18px;
            }

            /* Contact Section */
            .contact {
                padding: 100px 20px;
            }

            .contact-container {
                backdrop-filter: blur(10px);
                padding: 56px 24px;
            }

            .modal-content {
                padding: 48px 28px 40px;
            }

            .form-control {
                padding: 15px 14px 12px; /* 44 px tall */
            }

            .form-label {
                left: 14px;   /* stays in line with the field's text indent */
            }

            /* Footer */
            footer {
                padding: 48px 20px 40px;
            }

            .cvr-link {
                font-size: 0.8rem;
                margin-top: 2px;
                padding: 11px 4px; /* 45 px hit area at 0.8 rem */
            }

            /* The three facts stack, one per line, instead of breaking after a middle dot */
            .footer-facts span {
                display: block;
            }

            .footer-facts .footer-sep {
                display: none;
            }
        }

        /* Small Mobile Devices */
        @media (max-width: 480px) {
            .luxury-title {
                font-size: 2rem;
            }

            .tagline {
                font-size: 1.05rem;
            }

            .premium-button {
                padding: 12px 30px;
                font-size: 0.85rem;
            }

            .section-title {
                font-size: 2rem;
            }

            .contact-title {
                font-size: 1.75rem;
            }

            .service-card {
                padding: 32px 22px 28px;
            }

            .contact-container {
                padding: 48px 18px;
            }

            .modal-content {
                padding: 40px 20px;
            }
        }

        /* Body scroll lock while the mobile menu is open (site.js toggles html.menu-open) */
        html.menu-open,
        html.menu-open body {
            overflow: hidden;
        }

        /* Single-column cards keep a reading measure instead of spanning a tablet (audit 10) */
        @media (min-width: 601px) and (max-width: 847px) {
            .services-grid {
                max-width: 640px;
                margin: 0 auto;
            }
        }

        /* Two columns between 848 and 1235 px: the third card sits centred on its own row instead of
           orphaned bottom-left (audit 3). Above 1235 px three columns fit (3 × 340 + 2 × 48 + 120). */
        @media (min-width: 848px) and (max-width: 1235px) {
            .services-grid {
                grid-template-columns: 1fr 1fr;
            }

            .service-card:last-child {
                grid-column: 1 / -1;
                width: calc(50% - 24px);
                justify-self: center;
            }
        }

        /* Tablets with the desktop layout: a tighter panel and a smaller contact title so "Det starter med en
           samtale" and "Start with a conversation" stay on one line; the flanking hairlines would not fit */
        @media (min-width: 769px) and (max-width: 1024px) {
            .contact-container {
                padding: 72px 48px;
            }

            .contact-title {
                font-size: 2.25rem;
            }

            .contact-title::before,
            .contact-title::after {
                display: none;
            }
        }

        /* Tighter card padding on small desktops (audit 9) */
        @media (min-width: 769px) and (max-width: 1365px) {
            .service-card {
                padding: 56px 40px 40px;
            }
        }

        /* Short laptop viewports: the nav takes its scrolled height from the start (audit 7) */
        @media (min-width: 769px) and (max-height: 800px) {
            nav {
                padding-top: 20px;
                padding-bottom: 20px;
            }
        }

        /* Landscape phones and any viewport under 520 px tall: a 60 px nav, the hero fitted to the screen
           with the wordmark at a third of its size, everything inside the visible height (audit 1, 11) */
        @media (max-height: 520px) {
            nav,
            nav.scrolled {
                padding-top: 12px;
                padding-bottom: 12px;
            }

            .logo {
                font-size: 18px;
                letter-spacing: 5px;
                padding: 11px 0;
                margin: -11px 0;
            }

            .hero {
                padding: 72px 24px 40px;
            }

            .hero-content {
                animation: none;
                opacity: 1;
                transform: none;
                filter: none;
            }

            .luxury-title {
                font-size: clamp(2rem, 6vw, 3.25rem);
                margin-bottom: 14px;
            }

            .luxury-title::before {
                display: none;
            }

            .tagline {
                font-size: 1.05rem;
                margin-bottom: 22px;
                animation: none;
                opacity: 0.9;
            }

            .premium-button {
                padding: 13px 36px;
                font-size: 0.9rem;
                animation: none;
            }

            .render-control {
                right: 12px;
                bottom: 12px;
            }
        }

        /* Large screens at 100 % scaling: the type and the containers grow with the screen (audit 8) */
        @media (min-width: 2560px) {
            html {
                font-size: 18px;
            }

            .container {
                max-width: 1600px;
            }

            .services-grid {
                grid-template-columns: repeat(3, 1fr); /* auto-fit would make four columns for three cards */
            }

            .contact-container {
                max-width: 1120px;
            }

            .contact-form {
                max-width: 680px;
            }

            .luxury-title {
                font-size: clamp(3rem, 8.5vw, 10rem);
            }
        }

        @media (min-width: 3440px) {
            html {
                font-size: 20px;
            }
        }

        /* Render quality control: fixed bottom-right button + popover (site.js).
           Above the background stack (z 50), below the mobile menu (9998), nav and modal. */
        .render-control {
            position: fixed;
            right: 20px;
            bottom: 20px;
            z-index: 9000;
            font-size: 0.75rem;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            transition: opacity 0.3s ease, visibility 0s linear 0.3s;
            /* Arrives after the hero's sequence (3.4 s after html.is-arrived; held before that by the
               paused-animation gate beside .hero-content). `backwards` only: once it is in, the cascade
               owns the opacity again, so .is-hidden and the quiet state work exactly as before. */
            animation: arrive-fade 600ms ease 3400ms backwards;
        }

        /* Hidden while the contact form's submit button is in view (site.js) */
        .render-control.is-hidden {
            opacity: 0;
            visibility: hidden;
            pointer-events: none;
        }

        .render-toggle {
            min-height: 44px;
            min-width: 44px;
            padding: 0 18px;
            background: rgba(10, 10, 10, 0.85);
            border: 1px solid var(--edge);
            color: var(--text-dim);
            font: inherit;
            font-weight: 300;
            letter-spacing: inherit;
            text-transform: inherit;
            transition: color 0.3s ease, border-color 0.3s ease;
        }

        .render-toggle:hover,
        .render-toggle:focus-visible,
        .render-toggle[aria-expanded="true"] {
            color: var(--primary);
            border-color: var(--edge-strong);
        }

        .render-toggle:disabled {
            opacity: 0.5;
        }

        /* Quiet state (site.js, after 4 s without pointer/keyboard interaction): the label fades and a
           1 px gold hairline marks the spot; the button stays 44 px, focusable, with its aria-label.
           Hover, focus or an open popover bring it back to full. */
        .render-toggle {
            position: relative;
        }

        .render-toggle-label {
            transition: opacity 0.3s ease;
        }

        .render-toggle::before {
            content: '';
            position: absolute;
            left: 50%;
            top: 50%;
            width: 18px;
            height: 1px;
            margin-left: -9px;
            background: var(--primary);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .render-control.is-quiet .render-toggle {
            background: transparent;
            border-color: transparent;
        }

        .render-control.is-quiet .render-toggle-label {
            opacity: 0;
        }

        .render-control.is-quiet .render-toggle::before {
            opacity: 0.6;
        }

        .render-control.is-quiet:hover .render-toggle,
        .render-control.is-quiet:focus-within .render-toggle {
            background: rgba(10, 10, 10, 0.85);
            border-color: var(--edge-strong);
        }

        .render-control.is-quiet:hover .render-toggle-label,
        .render-control.is-quiet:focus-within .render-toggle-label {
            opacity: 1;
        }

        .render-control.is-quiet:hover .render-toggle::before,
        .render-control.is-quiet:focus-within .render-toggle::before {
            opacity: 0;
        }

        .render-popover {
            position: absolute;
            right: 0;
            bottom: calc(100% + 10px);
            width: min(340px, calc(100vw - 40px));
            padding: 18px 20px;
            background: rgba(10, 10, 10, 0.96);
            border: 1px solid var(--edge);
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
            text-transform: none;
            letter-spacing: 0.04em;
            font-weight: 300;
        }

        .render-popover-title {
            font-size: 0.7rem;
            letter-spacing: 0.25em;
            text-transform: uppercase;
            color: var(--text-dim);
            margin-bottom: 8px;
        }

        .render-option {
            display: grid;
            grid-template-columns: 16px 1fr;
            column-gap: 12px;
            padding: 9px 0;
            border-top: 1px solid rgba(255, 215, 0, 0.1);
        }

        .render-option input {
            accent-color: var(--primary);
            margin: 3px 0 0;
        }

        .render-option input:focus-visible {
            outline: 1px solid var(--primary);
            outline-offset: 2px;
        }

        .render-option-name {
            color: var(--text-light);
            font-size: 0.9rem;
        }

        .render-option input:checked ~ .render-option-name {
            color: var(--primary);
        }

        .render-option-note {
            display: block;
            font-style: normal;
            font-size: 0.72rem;
            color: var(--text-dim);
        }

        .render-option-req {
            grid-column: 2;
            font-size: 0.72rem;
            line-height: 1.45;
            color: var(--text-faint);
        }

        .render-info {
            margin-top: 12px;
            padding-top: 12px;
            border-top: 1px solid rgba(255, 215, 0, 0.2);
            display: grid;
            grid-template-columns: auto 1fr;
            gap: 4px 12px;
            font-size: 0.72rem;
            color: var(--text-faint);
        }

        .render-info dt {
            font-size: 0.62rem;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--text-dim);
            padding-top: 2px;
        }

        .render-info dd {
            margin: 0;
            word-break: break-word;
        }

        .no-webgl .render-popover {
            display: none !important;
        }

        @media (max-width: 768px) {
            /* No entrance on phones (quiet from the start, site.js); it glides with the consent
               banner's own rise instead of jumping when the banner lifts it. */
            .render-control {
                right: 12px;
                bottom: 12px;
                animation: none;
                transition: opacity 0.3s ease, visibility 0s linear 0.3s, bottom 0.4s ease;
            }
        }

        @media (prefers-reduced-motion: reduce) {
            .render-control,
            .render-toggle,
            .render-toggle-label,
            .render-toggle::before {
                animation: none;
                transition: none;
            }
        }

        /* Reduced motion: decorative animations settle to their final state immediately.
           The loader ring keeps spinning (it is status, not decoration). */
        @media (prefers-reduced-motion: reduce) {
            /* A short veil, then everything is simply present */
            .loader {
                transition: opacity 300ms ease, visibility 0s linear 300ms;
            }

            .hero-content {
                animation: none;
                opacity: 1;
                transform: none;
                filter: none;
            }

            .tagline {
                animation: none;
                opacity: 0.9;
                letter-spacing: 0.08em;
            }

            .premium-button {
                animation: none;
            }

            .luxury-title {
                animation: none;
                background-position: 0% 50%;
            }

            .luxury-title::before {
                animation: none;
                opacity: 0.6;
                transform: none;
            }

            /* Scroll reveals settle at once: site.js initReveal() adds no classes here; these hold if it ever does */
            .section-header.reveal-pending,
            .contact-container.reveal-pending {
                opacity: 1;
                transform: none;
            }

            .contact-container.reveal-pending::after {
                --lit: 360deg;
            }

            .contact-container.reveal-pending .panel-ticks {
                opacity: 1;
            }

            .hero::before,
            .logo,
            nav::after,
            .section-header.is-revealed,
            .service-card.is-revealed,
            .contact-container.is-revealed,
            .rocket-flame,
            .light-rays,
            .orbit-particle-1,
            .orbit-particle-2,
            .orbit-particle-3,
            .loader-text,
            .modal-icon.success,
            .modal-icon.error,
            .form-error {
                animation: none !important;
            }

            .hero::before {
                opacity: 0.2;
                transform: translate(-50%, -50%);
            }

            /* Hover and focus still change colour; nothing moves */
            .premium-button,
            .premium-button::before,
            .premium-button::after,
            .submit-button,
            .submit-button::before,
            .submit-button::after,
            .service-card,
            .service-card::before,
            .service-icon,
            .form-control,
            .form-label,
            .modal-overlay,
            .modal-content,
            .modal-close,
            .nav-link,
            .nav-link::after,
            .cvr-link,
            .cvr-link::after,
            .mobile-menu-toggle,
            .nav-links,
            .nav-lang,
            .contact-container::before,
            .contact-container::after,
            .panel-ticks {
                transition: none !important;
            }

            .premium-button:hover,
            .premium-button:focus-visible,
            .submit-button:hover,
            .submit-button:focus-visible,
            .service-card:hover,
            .modal-close:hover,
            .modal-close:focus-visible {
                transform: none;
            }

            .modal-content {
                transform: none;
            }
        }

        /* ==================================================================================
           Consent, the privacy page and the footer tools row.
           Added with the analytics layer; nothing above this line was touched when the CSS
           moved out of index.php. All of it is the same gold-on-dark hairline idiom: 1 px of
           --edge at rest, --edge-strong on hover and focus, nothing moves on interaction.
           ================================================================================== */

        /* The consent UI is server-rendered but starts hidden; site.js decides. `hidden` has to
           win over the display rules below, so it is stated once, here. */
        [hidden] {
            display: none !important;
        }

        /* ---------- footer tools: the privacy link and the privacy toggle ---------- */
        .footer-tools {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 18px;
            margin-top: 10px;
        }

        .footer-tool {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            min-height: 44px;
            padding: 10px 4px;
            background: none;
            border: 0;
            font: inherit;
            font-size: 0.8rem;
            letter-spacing: 0.12em;
            color: var(--text-dim);
            text-decoration: none;
            position: relative;
            transition: color 0.3s ease;
        }

        .footer-tool::after {
            content: '';
            position: absolute;
            left: 4px;
            right: 4px;
            bottom: 8px;
            height: 1px;
            background: var(--primary);
            transform: scaleX(0);
            transform-origin: left;
            opacity: 0.5;
            transition: transform 0.3s ease;
        }

        .footer-tool:hover,
        .footer-tool:focus-visible {
            color: var(--primary);
        }

        .footer-tool:hover::after {
            transform: scaleX(1);
        }

        .footer-tool-icon {
            min-width: 44px;
            padding: 10px;
        }

        .footer-tool-icon::after {
            content: none;
        }

        .footer-tool-icon svg {
            display: block;
            overflow: visible;
        }

        /* ---------- the ambient-sound control (sound.js) ---------- */
        /* The page renders the wrapper and the strings; sound.js fills in the toggle and the hint.
           It sits to the left of the render control — sound.js measures that control and publishes
           the gap as --sound-shift — and shares its quiet-after-4s behaviour, so the two settle
           together. Everything here mirrors .render-control on purpose. */
        .sound-control {
            position: fixed;
            right: calc(20px + var(--sound-shift, 210px));
            bottom: 20px;
            z-index: 9000;
            transition: opacity 0.3s ease, visibility 0s linear 0.3s;
            animation: arrive-fade 600ms ease 3400ms backwards;   /* with the render control, see there */
        }

        /* The privacy page has no veil to arrive from: its control is simply there. */
        .legal-page .sound-control {
            animation: none;
        }

        .sound-control .sound-toggle {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 44px;
            height: 44px;
            padding: 0;
            background: rgba(10, 10, 10, 0.85);
            border: 1px solid var(--edge);
            color: var(--text-dim);
            transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, opacity 0.3s ease;
        }

        .sound-control .sound-toggle:hover,
        .sound-control .sound-toggle:focus-visible {
            color: var(--primary);
            border-color: var(--edge-strong);
        }

        .sound-control .sound-glyph svg {
            width: 22px;
            height: 22px;
        }

        /* The label beside the glyph — the render control's own caps, faded in the
           quiet state and dropped on phones, where the two controls stack. */
        .sound-control .sound-toggle {
            width: auto;
            min-width: 44px;
            gap: 10px;
            padding: 0 14px;
            font: inherit;             /* a <button> otherwise falls back to the UA font */
            cursor: pointer;
        }

        .sound-control .sound-toggle-label {
            font-size: 0.75rem;
            font-weight: 300;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            white-space: nowrap;
            transition: opacity 0.3s ease;
        }

        .sound-control.is-quiet .sound-toggle-label {
            opacity: 0;
        }

        .sound-control.is-quiet:hover .sound-toggle-label,
        .sound-control.is-quiet:focus-within .sound-toggle-label {
            opacity: 1;
        }

        /* Quiet: the same hairline retreat the render control makes. */
        .sound-control.is-quiet .sound-toggle {
            background: transparent;
            border-color: transparent;
            opacity: 0.5;
        }

        .sound-control.is-quiet:hover .sound-toggle,
        .sound-control.is-quiet:focus-within .sound-toggle {
            opacity: 1;
            background: rgba(10, 10, 10, 0.85);
            border-color: var(--edge);
        }

        /* Hidden while the contact form's submit button is in view, exactly like the render control */
        .sound-control.is-hidden {
            opacity: 0;
            visibility: hidden;
            pointer-events: none;
        }

        /* The one-time hint sits above the button and never widens the page */
        .sound-control .sound-hint {
            position: absolute;
            right: 0;
            bottom: calc(100% + 10px);
            width: max-content;
            max-width: 230px;
            margin: 0;
            padding: 10px 14px;
            background: rgba(10, 10, 10, 0.96);
            border: 1px solid var(--edge);
            color: var(--text-faint);
            font-size: 0.72rem;
            line-height: 1.5;
            letter-spacing: 0.04em;
        }

        /* ---------- consent banner ---------- */
        /* Bottom left, so it can never sit over the render control and the sound control (both
           bottom right) or the hero call to action (centred). It is a region, not a dialog: it
           never traps focus and never blocks the page or the scene. */
        .consent-banner {
            position: fixed;
            left: 20px;
            bottom: 20px;
            z-index: 9500;
            width: min(380px, calc(100vw - 40px));
            padding: 22px 24px 20px;
            background: rgba(8, 8, 8, 0.94);
            border: 1px solid var(--edge);
            box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
            backdrop-filter: blur(14px) saturate(140%);
        }

        /* Never taller than the viewport, on any layout: the body scrolls inside it. On a landscape phone
           (844x390) the banner stood 434 px tall with its title and first lines above the screen (audit D2);
           the phone rule further down caps it tighter still. */
        .consent-banner {
            max-height: calc(100vh - 32px);
            overflow-y: auto;
            overscroll-behavior: contain;
        }

        /* `backwards`, not `both`: the rise ends in the banner's own resting style, so nothing is held
           after it — and a held animated opacity would win over .is-leaving and, cancelled, would not
           start the transition from its value (the exit snapped to 0 that way, measured 2026-09-07). */
        @media (prefers-reduced-motion: no-preference) {
            .consent-banner {
                animation: consentRise 0.4s ease backwards;
            }
        }

        @keyframes consentRise {
            from { opacity: 0; transform: translateY(14px); }
            to   { opacity: 1; transform: translateY(0); }
        }

        /* Leaving (site.js hideBanner): the page takes its room back the moment the visitor answers —
           the hero's foot and the planet start down at once — and the banner itself settles out over
           250 ms, the mirror of its rise. */
        .consent-banner.is-leaving {
            opacity: 0;
            transform: translateY(8px);
            transition: opacity 0.25s ease, transform 0.25s ease;
            pointer-events: none;
        }

        .consent-banner-title {
            font-size: 0.8rem;
            font-weight: 400;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--text-dim);
            margin-bottom: 12px;
        }

        .consent-banner-body {
            font-size: 0.85rem;
            line-height: 1.65;
            font-weight: 300;
            color: var(--text-muted);
        }

        .consent-banner-link,
        .consent-dialog-link {
            display: inline-block;
            margin-top: 12px;
            font-size: 0.8rem;
            letter-spacing: 0.06em;
            color: var(--primary);
            text-decoration: none;
            border-bottom: 1px solid var(--edge);
            padding-bottom: 2px;
            transition: border-color 0.3s ease;
        }

        .consent-banner-link:hover,
        .consent-banner-link:focus-visible,
        .consent-dialog-link:hover,
        .consent-dialog-link:focus-visible {
            border-bottom-color: var(--edge-strong);
        }

        .consent-actions {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-top: 20px;
        }

        /* The three answers carry the same weight: one full-width row each, same size, same
           hairline, same fill — nothing here reads as the preferred answer. */
        .consent-actions .consent-button {
            flex: 1 1 100%;
        }

        .consent-button {
            flex: 1 1 auto;
            min-height: 44px;
            padding: 11px 16px;
            background: var(--glass);
            border: 1px solid var(--edge);
            font: inherit;
            font-size: 0.72rem;
            font-weight: 400;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--champagne);
            cursor: pointer;
            transition: border-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
        }

        .consent-button:hover,
        .consent-button:focus-visible {
            border-color: var(--edge-strong);
            color: var(--primary);
            box-shadow: inset 0 0 24px rgba(255, 215, 0, 0.07);
        }

        .consent-button-primary {
            min-width: 140px;
            flex: 0 0 auto;
        }

        /* ---------- consent settings dialog ---------- */
        .consent-overlay {
            position: fixed;
            inset: 0;
            z-index: 100001;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 24px;
            background: rgba(0, 0, 0, 0.82);
            backdrop-filter: blur(6px);
        }

        .consent-dialog {
            position: relative;
            width: min(560px, 100%);
            max-height: calc(100vh - 48px);
            overflow-y: auto;
            padding: 44px 44px 36px;
            background: var(--bg-darker);
            border: 1px solid var(--edge);
            box-shadow: 0 30px 80px rgba(0, 0, 0, 0.7);
        }

        @media (prefers-reduced-motion: no-preference) {
            .consent-dialog {
                animation: consentRise 0.3s ease both;
            }
        }

        .consent-dialog-title {
            font-size: 1.3rem;
            font-weight: 200;
            letter-spacing: 0.14em;
            color: var(--champagne);
            margin-bottom: 26px;
            padding-right: 44px;
        }

        /* Same close control as the modal: a 44 px hit area, two hairlines crossing. */
        .consent-dialog-close {
            position: absolute;
            top: 18px;
            right: 18px;
            width: 44px;
            height: 44px;
            background: none;
            border: 0;
            cursor: pointer;
            transition: opacity 0.3s ease;
            opacity: 0.6;
        }

        .consent-dialog-close::before,
        .consent-dialog-close::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 17px;
            height: 1px;
            background: var(--primary);
        }

        .consent-dialog-close::before {
            transform: translate(-50%, -50%) rotate(45deg);
        }

        .consent-dialog-close::after {
            transform: translate(-50%, -50%) rotate(-45deg);
        }

        .consent-dialog-close:hover,
        .consent-dialog-close:focus-visible {
            opacity: 1;
        }

        .consent-categories {
            list-style: none;
            margin: 0;
            padding: 0;
        }

        .consent-category {
            padding: 20px 0;
            border-top: 1px solid rgba(255, 215, 0, 0.12);
        }

        .consent-category:last-child {
            border-bottom: 1px solid rgba(255, 215, 0, 0.12);
        }

        .consent-category-head {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 16px;
            min-height: 32px;
        }

        .consent-category-name {
            font-size: 0.95rem;
            font-weight: 300;
            letter-spacing: 0.1em;
            color: var(--text-light);
        }

        .consent-category-state {
            font-size: 0.7rem;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--text-dim);
        }

        .consent-category-text {
            margin-top: 10px;
            font-size: 0.85rem;
            line-height: 1.65;
            font-weight: 300;
            color: var(--text-faint);
            max-width: 44em;
        }

        /* The switch is a real checkbox: the input keeps its semantics and its keyboard, and is
           only visually replaced by the track. Focus is drawn on the track. */
        .consent-switch {
            display: inline-flex;
            align-items: center;
            min-height: 44px;
            padding: 10px 0;
            cursor: pointer;
        }

        .consent-switch input {
            position: absolute;
            width: 1px;
            height: 1px;
            margin: -1px;
            padding: 0;
            border: 0;
            overflow: hidden;
            clip: rect(0 0 0 0);
            clip-path: inset(50%);
            white-space: nowrap;
        }

        .consent-switch-track {
            display: block;
            position: relative;
            width: 52px;
            height: 24px;
            border: 1px solid var(--edge);
            background: rgba(255, 255, 255, 0.02);
            transition: border-color 0.3s ease, background-color 0.3s ease;
        }

        .consent-switch-knob {
            position: absolute;
            top: 3px;
            left: 3px;
            width: 16px;
            height: 16px;
            background: var(--text-dim);
            transition: transform 0.3s ease, background-color 0.3s ease;
        }

        .consent-switch input:checked + .consent-switch-track {
            border-color: var(--edge-strong);
            background: rgba(255, 215, 0, 0.1);
        }

        .consent-switch input:checked + .consent-switch-track .consent-switch-knob {
            transform: translateX(26px);
            background: var(--primary);
        }

        .consent-switch input:focus-visible + .consent-switch-track {
            outline: 1px solid var(--primary);
            outline-offset: 4px;
        }

        .consent-dialog-actions {
            display: flex;
            justify-content: flex-end;
            margin-top: 26px;
        }

        .consent-status {
            margin-top: 14px;
            min-height: 1.2em;
            font-size: 0.78rem;
            line-height: 1.6;
            color: var(--text-faint);
            text-align: right;
        }

        .consent-status:empty {
            margin-top: 0;
            min-height: 0;
        }

        /* ---------- the privacy page ---------- */
        .legal {
            position: relative;
            z-index: 10;
            padding: 180px 60px var(--section-pad);
        }

        .legal-container {
            max-width: 760px;
            margin: 0 auto;
        }

        .legal-title {
            display: inline-block;
            font-size: clamp(2.25rem, 5vw, 3.25rem);
            font-weight: 100;
            letter-spacing: 0.2em;
            line-height: 1.1;
            background: linear-gradient(135deg,
                var(--primary) 0%,
                var(--champagne) 50%,
                var(--luxury-gold) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            filter: drop-shadow(0 0 30px rgba(255, 215, 0, 0.4));
            margin-bottom: 26px;
        }

        .legal-meta {
            font-size: 1rem;
            line-height: 1.8;
            font-weight: 300;
            color: var(--text-muted);
            max-width: 36em;
            margin-bottom: 8px;
        }

        .legal-version {
            color: var(--text-dim);
            letter-spacing: 0.06em;
        }

        .legal-heading {
            margin-top: 56px;
            margin-bottom: 18px;
            padding-top: 22px;
            border-top: 1px solid rgba(255, 215, 0, 0.12);
            font-size: 1.1rem;
            font-weight: 300;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--champagne);
        }

        .legal-body {
            font-size: 0.95rem;
            line-height: 1.85;
            font-weight: 300;
            color: var(--text-muted);
            max-width: 40em;
            margin-bottom: 18px;
        }

        .legal-body strong {
            display: block;
            font-weight: 400;
            letter-spacing: 0.04em;
            color: var(--primary);
        }

        .legal-note {
            margin-top: 32px;
            font-size: 0.82rem;
            line-height: 1.7;
            color: var(--text-faint);
        }

        .legal-consent-open {
            min-height: 44px;
            padding: 11px 22px;
            background: var(--glass);
            border: 1px solid var(--edge);
            font: inherit;
            font-size: 0.72rem;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--champagne);
            cursor: pointer;
            transition: border-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
        }

        .legal-consent-open:hover,
        .legal-consent-open:focus-visible {
            border-color: var(--edge-strong);
            color: var(--primary);
            box-shadow: inset 0 0 24px rgba(255, 215, 0, 0.07);
        }

        /* ---------- the error page (error.php) ---------- */
        /* The privacy page's frame with one line and one link. The page is a few lines tall, so
           the body is a column and the footer keeps the foot of the screen instead of floating
           halfway up the gradient. */
        body#error {
            min-height: 100vh;
            min-height: 100svh;
            display: flex;
            flex-direction: column;
        }

        body#error .legal {
            flex: 1 0 auto;
        }

        /* The way home: the consent button's frame as a link, 44 px tall, the label centred. */
        .legal-home {
            display: inline-flex;
            align-items: center;
            min-height: 44px;
            margin-top: 32px;
            padding: 0 22px;
            background: var(--glass);
            border: 1px solid var(--edge);
            font-size: 0.72rem;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            text-decoration: none;
            color: var(--champagne);
            transition: border-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
        }

        .legal-home:hover,
        .legal-home:focus-visible {
            border-color: var(--edge-strong);
            color: var(--primary);
            box-shadow: inset 0 0 24px rgba(255, 215, 0, 0.07);
        }

        /* The storage table scrolls inside its own box; the page never scrolls sideways. */
        .legal-table-wrap {
            overflow-x: auto;
            margin-bottom: 8px;
            border: 1px solid rgba(255, 215, 0, 0.12);
        }

        .legal-table {
            width: 100%;
            min-width: 620px;
            border-collapse: collapse;
            font-size: 0.85rem;
            font-weight: 300;
            font-variant-numeric: tabular-nums;
        }

        .legal-table th,
        .legal-table td {
            padding: 13px 16px;
            text-align: left;
            vertical-align: top;
            border-bottom: 1px solid rgba(255, 215, 0, 0.08);
            color: var(--text-muted);
        }

        .legal-table thead th {
            font-size: 0.7rem;
            font-weight: 400;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--text-dim);
            white-space: nowrap;
        }

        .legal-table tbody th {
            font-weight: 400;
            color: var(--text-light);
            white-space: nowrap;
        }

        .legal-table tbody tr:last-child th,
        .legal-table tbody tr:last-child td {
            border-bottom: 0;
        }

        .legal-table code {
            font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
            font-size: 0.8rem;
            color: var(--champagne);
            user-select: text;
            -webkit-user-select: text;
        }

        /* ---------- phones ---------- */
        @media (max-width: 768px) {
            .consent-banner {
                left: 12px;
                right: 12px;
                bottom: 12px;
                width: auto;
                padding: 18px 18px 16px;
            }

            /* The banner is a wide strip at the bottom of a phone, so it is capped and its body
               scrolls rather than growing over the whole screen. */
            .consent-banner {
                max-height: 58vh;
                overflow-y: auto;
                overscroll-behavior: contain;
            }

            /* On a phone the two controls stack rather than sit side by side, and the sound
               control keeps the glyph only. */
            .sound-control {
                right: 12px;
                bottom: 66px;
                animation: none;
                transition: opacity 0.3s ease, visibility 0s linear 0.3s, bottom 0.4s ease;
            }

            .sound-control .sound-toggle {
                width: 44px;
                padding: 0;
            }

            .sound-control .sound-toggle-label {
                display: none;
            }

            /* While the banner is up it must not cover either of them. site.js measures the
               banner and publishes its height; the sound control keeps its 54 px step above the
               render control. */
            html.consent-banner-open .render-control {
                bottom: calc(var(--consent-banner-h, 0px) + 24px);
            }

            html.consent-banner-open .sound-control {
                bottom: calc(var(--consent-banner-h, 0px) + 78px);
            }

            /* …and it must not cover the hero's call to action either: the hero is a centred
               flex box, so padding at its foot lifts the whole block clear while the banner is
               up and gives it back the moment the visitor answers. */
            html.consent-banner-open .hero {
                padding-bottom: calc(var(--consent-banner-h, 0px) + 28px);
            }

            .consent-dialog {
                padding: 40px 22px 26px;
            }

            .consent-category-head {
                flex-wrap: wrap;
            }

            .legal {
                padding: 130px 24px 100px;
            }

            .legal-heading {
                margin-top: 40px;
            }
        }

        /* Landscape phones and any viewport under 520 px tall: the banner sits 8 px up and is capped so its
           top stays below the 48-60 px nav (viewport - nav - 8 - slack), with tighter padding (audit D2). */
        @media (max-height: 520px) {
            .consent-banner {
                bottom: 8px;
                max-height: calc(100vh - 68px);
                padding: 14px 16px 12px;
            }
        }

        /* A landscape phone has no row to spare: at 844x390 the copy fills 121-288 of 390 px and the
           wordmark's glyphs 173-671 of 844, so the 380 px banner covered the wordmark's left third and
           the call to action until answered. Here it takes the right, and the hero makes room for it
           the way it does at its foot on a portrait phone: padding-right, transitioned, so the copy
           slides left of the banner as it rises and back when the visitor answers. The wordmark is
           0.59 vw wide (6 vw per em, 9.84 em with its tracking, up to the clamp's 3.25 rem at 867 px),
           the banner 41 vw - 54 px and the padding 20 px more, which leaves the content box 10 px of
           slack — a shortfall would wrap ORBIT to a second line — and the banner 12 px clear of the
           glyphs: at 844x390 the wordmark sits at 29-527, the banner at 540 (measured 2026-09-07).
           Its body scrolls (the base rule); the controls under it wait, as on a short portrait phone. */
        @media (max-height: 520px) and (orientation: landscape) {
            .consent-banner {
                left: auto;
                right: 12px;
                width: calc(41vw - 54px);
            }

            .hero {
                transition: padding-right 0.4s ease;
            }

            html.consent-banner-open .hero {
                padding-right: calc(41vw - 34px);
            }
        }

        /* Short phones (under 600 px tall) with the banner up: the render and sound controls, lifted above it,
           landed on the tagline and the call to action (audit D8: 320x568). Both are non-essential until the
           banner is answered, so they wait for it — on a landscape phone too, where the banner has the
           corner they live in. The banner is capped at 50 vh here: at 58 vh its top covered the call to
           action's lower 15 px on a 320x568 phone (the hero's slack, 323 px, is less than the padding the
           banner asks for, so the copy cannot rise clear of it); at 50 vh the button clears it by 25 px.
           The banner's body scrolls either way (its natural height there is 469 px). */
        @media (max-width: 768px) and (max-height: 600px), (max-height: 520px) and (orientation: landscape) {
            html.consent-banner-open .render-control,
            html.consent-banner-open .sound-control {
                visibility: hidden;
            }
        }

        @media (max-width: 768px) and (max-height: 600px) {
            .consent-banner {
                max-height: 50vh;
            }
        }

        /* ---------- reduced motion ---------- */
        @media (prefers-reduced-motion: reduce) {
            .hero,
            .sound-control,
            .sound-control .sound-toggle,
            .sound-control .sound-toggle-label,
            .consent-banner,
            .consent-dialog,
            .consent-button,
            .consent-switch-track,
            .consent-switch-knob,
            .consent-dialog-close,
            .footer-tool,
            .footer-tool::after,
            .legal-consent-open,
            .legal-home {
                animation: none;
                transition: none;
            }
        }
