@charset "UTF-8";
/* ==========================================================================
   NexaCore VIP
   Hand-written CSS. No framework, no build step, no preprocessor.

   Contents
     1.  Fonts
     2.  Tokens
     3.  Reset and base
     4.  Typography
     5.  Layout
     6.  The Thread
     7.  Header and navigation
     8.  Hero
     9.  Positioning statement
     10. Pillars and service cards
     11. Why clients stay
     12. Who we serve
     13. Contact and form
     14. Footer
     15. Buttons, links, shared components
     16. Motion
   ========================================================================== */


/* 1. Fonts ================================================================= */

/*
   Self-hosted, Latin-subset, woff2. No request leaves this origin.

   Marcellus: inscriptional Roman capitals. The logo wordmark is cut in this
   register — monument and seal, not fashion Didone — and a true Didone's
   hairlines optically thin and break up on a black field at heading sizes.

   Archivo: a grotesque drawn for legibility at small sizes. Variable weight
   axis, width axis pinned at build time to keep the file at 25 KB.
*/
@font-face {
    font-family: "Marcellus";
    src: url("../fonts/marcellus-latin-400.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Archivo";
    src: url("../fonts/archivo-latin-var.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}


/* 2. Tokens ================================================================ */

:root {
    /* ---- Colour ---------------------------------------------------------
       Sampled from the logo artwork, not guessed. The brand gold sits at
       hue 40-44 degrees with saturation around 0.45 — a warm brass, nowhere
       near #FFD700. The logo's field black is faintly cool, so the page black
       keeps that cast and only the panels are warmed, which makes panels
       advance without a brightness step doing the work.

       Contrast against --ink, measured:
         --gold       8.20:1   passes AA at any size
         --champagne 13.17:1
         --bone      12.15:1
         --muted      6.59:1
    */
    --ink:        #0B0B0D;
    --ink-panel:  #17140F;
    --gold:       #C9A24E;
    --champagne:  #E3D2AA;
    --bone:       #CFCBC2;
    --muted:      #9A958A;

    /* Derived. Rules and hairlines only — never text. */
    --rule:        rgba(201, 162, 78, 0.22);
    --rule-strong: rgba(201, 162, 78, 0.45);
    --rule-faint:  rgba(207, 203, 194, 0.12);
    --panel-edge:  rgba(207, 203, 194, 0.08);

    /* The logo's actual foil gradient. Used once, on the h1. */
    --foil: linear-gradient(
        104deg,
        #7A6132 0%,
        #C9A24E 22%,
        #EBDCB4 46%,
        #C9A24E 62%,
        #836939 84%,
        #D8C284 100%
    );

    /* ---- Type ----------------------------------------------------------- */
    --font-display: "Marcellus", "Times New Roman", Times, serif;
    --font-body:    "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    --fs-xs:   0.75rem;
    --fs-sm:   0.8125rem;
    --fs-base: clamp(1rem, 0.96rem + 0.18vw, 1.0625rem);
    --fs-md:   clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
    --fs-lg:   clamp(1.1875rem, 1.1rem + 0.5vw, 1.375rem);
    --fs-xl:   clamp(1.375rem, 1.2rem + 0.8vw, 1.75rem);
    --fs-2xl:  clamp(1.875rem, 1.35rem + 2.3vw, 3rem);
    --fs-3xl:  clamp(2.375rem, 1.25rem + 4.6vw, 4.75rem);

    --tracking-eyebrow: 0.2em;
    --tracking-display: 0.005em;

    /* ---- Space ----------------------------------------------------------- */
    --space-2xs: 0.375rem;
    --space-xs:  0.625rem;
    --space-sm:  1rem;
    --space-md:  1.5rem;
    --space-lg:  2.25rem;
    --space-xl:  3.5rem;
    --space-2xl: clamp(4rem, 8vw, 7rem);
    --space-3xl: clamp(5rem, 11vw, 9.5rem);

    /* ---- Layout ----------------------------------------------------------
       --rail-w is the gutter the Thread lives in. Zero below 1024px, where
       there is no room for it and the numerals move inline instead.
    */
    --wrap-max: 78rem;
    --gutter:   clamp(1.25rem, 4vw, 2.5rem);
    --rail-w:   0rem;
    --header-h: 4.25rem;
    --measure:  62ch;

    --radius: 2px;

    --ease: cubic-bezier(0.22, 0.7, 0.24, 1);
}

@media (min-width: 64rem) {
    :root {
        --rail-w:   5rem;
        --header-h: 5rem;
    }
}


/* 3. Reset and base ======================================================== */

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Anchored headings must clear the fixed header. */
    scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
    margin: 0;
    /* Containing block for the absolutely positioned Thread. */
    position: relative;
    background: var(--ink);
    color: var(--bone);
    font-family: var(--font-body);
    font-size: var(--fs-base);
    font-weight: 400;
    line-height: 1.65;
    font-synthesis-weight: none;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

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

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
    font: inherit;
    color: inherit;
    margin: 0;
}

fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; }

/* Focus. Gold, offset, and never removed — this is the only indicator a
   keyboard user has. Applied on :focus-visible so a mouse click on a button
   does not draw a ring. */
:focus-visible {
    outline: 2px solid var(--gold);
    outline-offset: 3px;
    border-radius: 1px;
}

/* Browsers that do not support :focus-visible keep the default ring. */
:focus:not(:focus-visible) { outline: none; }

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

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

.skip-link {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -110%);
    z-index: 200;
    padding: 0.75rem 1.5rem;
    background: var(--gold);
    color: var(--ink);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    transition: transform 0.2s var(--ease);
}

.skip-link:focus { transform: translate(-50%, 0); }


/* 4. Typography ============================================================ */

.eyebrow {
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--gold);
    margin-bottom: var(--space-sm);
}

.section__title,
.positioning__heading {
    font-family: var(--font-display);
    font-size: var(--fs-2xl);
    font-weight: 400;
    line-height: 1.1;
    letter-spacing: var(--tracking-display);
    color: var(--champagne);
    text-transform: uppercase;
}

.section__lede {
    margin-top: var(--space-md);
    max-width: 54ch;
    font-size: var(--fs-md);
    color: var(--muted);
}

.link {
    color: var(--bone);
    text-decoration: underline;
    text-decoration-color: var(--rule-strong);
    text-underline-offset: 0.28em;
    text-decoration-thickness: 1px;
    transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}

.link:hover {
    color: var(--champagne);
    text-decoration-color: var(--gold);
}


/* 5. Layout ================================================================ */

.wrap {
    width: min(100% - (var(--gutter) * 2), var(--wrap-max));
    margin-inline: auto;
    /* Reserves the Thread's rail. Zero below 1024px. */
    padding-left: var(--rail-w);
}

.section {
    padding-block: var(--space-3xl);
    scroll-margin-top: calc(var(--header-h) + 1rem);
}

.section--panel {
    background: var(--ink-panel);
    border-block: 1px solid var(--panel-edge);
}

.section__head { margin-bottom: var(--space-2xl); }


/* 6. The Thread ============================================================
   The signature. One hairline running the full height of the document in the
   left rail, filling as the page scrolls, terminating in the fleuron at the
   foot of the page — the same ornament that closes the logo.

   Positioned against the body rather than the viewport so it aligns with the
   content edge exactly; a fixed element measured in vw would sit a scrollbar's
   width out of true. The left value is the same expression .wrap resolves to,
   plus half the rail.
*/

.thread {
    position: absolute;
    top: 0;
    bottom: 0;
    left: max(
        calc(var(--gutter) + (var(--rail-w) / 2)),
        calc(50% - (var(--wrap-max) / 2) + (var(--rail-w) / 2))
    );
    width: 1px;
    z-index: 1;
    display: none;
    pointer-events: none;
}

@media (min-width: 64rem) {
    .thread { display: block; }
}

.thread__track,
.thread__fill {
    position: absolute;
    inset-inline: 0;
    width: 1px;
}

.thread__track {
    top: 0;
    bottom: 0;
    background: var(--rule);
}

/* Height is set by the script from the scroll position. Starts at zero and
   simply never grows if the script does not run, which leaves the track — a
   quiet full-height hairline — as the fallback. */
.thread__fill {
    top: 0;
    height: 0;
    background: linear-gradient(
        180deg,
        rgba(201, 162, 78, 0.15) 0%,
        var(--gold) 12%,
        var(--gold) 100%
    );
}


/* 7. Header and navigation ================================================= */

.site-header {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 100;
    height: var(--header-h);
    background: rgba(11, 11, 13, 0.92);
    border-bottom: 1px solid var(--rule);
    /* Cheap on compositing, and degrades to the solid colour above. */
    backdrop-filter: saturate(140%) blur(10px);
    -webkit-backdrop-filter: saturate(140%) blur(10px);
}

.site-header__inner {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    height: 100%;
    /* The header bar spans the rail; only page content is indented by it. */
    padding-left: 0;
}

.brand {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-right: auto;
    flex-shrink: 0;
    /* Above the mobile overlay, which is a sibling inside this same header and
       would otherwise paint over both the brand and the close button. */
    position: relative;
    z-index: 95;
}

.brand__mark {
    width: 2.25rem;
    height: 2.25rem;
    flex-shrink: 0;
}

.brand__text { display: flex; flex-direction: column; line-height: 1.05; }

.brand__name {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--champagne);
}

.brand__sub {
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--gold);
    margin-top: 0.2em;
}

.nav__list {
    display: flex;
    align-items: center;
    gap: clamp(0.75rem, 1.6vw, 1.75rem);
}

.nav__link {
    position: relative;
    display: block;
    padding: 0.4rem 0;
    font-size: var(--fs-sm);
    font-weight: 500;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--muted);
    white-space: nowrap;
    transition: color 0.25s var(--ease);
}

/* The active-section marker: a short gold rule, the Thread's own vocabulary
   rather than a new one. */
.nav__link::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1px;
    background: var(--gold);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s var(--ease);
}

.nav__link:hover { color: var(--champagne); }

.nav__link[aria-current] { color: var(--champagne); }

.nav__link[aria-current]::after,
.nav__link:hover::after { transform: scaleX(1); }

/* Shown only inside the mobile overlay. */
.nav__direct { display: none; }

/* Hidden on mobile, where the header holds the brand and the menu toggle and
   nothing else fits. The descendant selector is deliberate: .btn sets its own
   display later in this file, and a single-class rule here would lose to it on
   source order and silently do nothing. */
.site-header__inner .site-header__cta {
    display: none;
    flex-shrink: 0;
}

@media (min-width: 64rem) {
    .site-header__inner .site-header__cta { display: inline-flex; }
}

.nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    margin-right: -0.625rem;
    padding: 0;
    background: none;
    border: 0;
    color: var(--champagne);
    cursor: pointer;
    /* Must stay above the overlay it opens — it doubles as the close button. */
    position: relative;
    z-index: 95;
}

.nav-toggle .icon { width: 1.5rem; height: 1.5rem; }
.nav-toggle__close { display: none; }

/* -- Below 1024px ---------------------------------------------------------
   Without JavaScript the toggle stays hidden and the list renders inline and
   wrapped, so every anchor is still reachable. The overlay only exists once
   the script has set the "js" class.
*/
@media (max-width: 63.999rem) {

    .nav__list {
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 0.4rem 0.9rem;
        padding: 0.35rem 0;
    }

    .nav__link { font-size: 0.75rem; }

    html.js .nav-toggle { display: inline-flex; }

    /*
     * The overlay must escape the header to fill the screen.
     *
     * .site-header sets backdrop-filter, and any non-none filter, transform or
     * backdrop-filter makes an element the containing block for its
     * position:fixed descendants. So this panel was being clipped to the
     * 68px-tall header bar — inset:0 resolved against the header, not the
     * viewport — showing two links and letting the page show through beneath.
     *
     * Dropping the blur while the menu is open removes that containing block.
     * Nothing is lost: the overlay behind the bar is opaque, so there is no
     * backdrop left to blur.
     */
    html.js[data-nav-open] .site-header {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: transparent;
        border-bottom-color: transparent;
    }

    html.js .nav {
        position: fixed;
        inset: 0;
        z-index: 90;
        display: none;
        flex-direction: column;
        /* Top-aligned, not centred. Centring a column that overflows puts the
           first items above the scroll origin, where they cannot be reached by
           scrolling at all — which is the other half of what went wrong here. */
        justify-content: flex-start;
        gap: var(--space-lg);
        padding: calc(var(--header-h) + var(--space-md)) var(--gutter) var(--space-2xl);
        background: var(--ink);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    html.js[data-nav-open] .nav { display: flex; }

    html.js[data-nav-open] .nav-toggle__open  { display: none; }
    html.js[data-nav-open] .nav-toggle__close { display: block; }

    html.js[data-nav-open] body { overflow: hidden; }

    html.js .nav .nav__list {
        flex-direction: column;
        align-items: flex-start;
        justify-content: flex-start;
        gap: 0;
        width: 100%;
    }

    html.js .nav .nav__item {
        width: 100%;
        border-bottom: 1px solid var(--rule-faint);
    }

    html.js .nav .nav__link {
        padding: 1.05rem 0;
        font-family: var(--font-display);
        font-size: 1.5rem;
        font-weight: 400;
        letter-spacing: 0.06em;
        color: var(--champagne);
    }

    html.js .nav .nav__link::after { display: none; }

    html.js .nav .nav__link[aria-current] { color: var(--gold); }

    html.js .nav .nav__direct {
        display: flex;
        flex-direction: column;
        gap: var(--space-sm);
    }

    .nav__direct-link {
        display: inline-flex;
        align-items: center;
        gap: 0.7rem;
        font-size: var(--fs-base);
        color: var(--bone);
    }

    .nav__direct-link .icon {
        width: 1.125rem;
        height: 1.125rem;
        color: var(--gold);
    }
}


/* 8. Hero ================================================================== */

.hero {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 100svh;
    padding-top: calc(var(--header-h) + var(--space-2xl));
    padding-bottom: var(--space-2xl);
    scroll-margin-top: var(--header-h);
}

/* Falls back for engines without svh. */
@supports not (min-height: 100svh) {
    .hero { min-height: 100vh; }
}

.hero__inner { position: relative; z-index: 2; max-width: 100%; }

/* -- Optional hero photograph ---------------------------------------------
   The type is set against a scrim, not against the photograph. The gradient
   below holds the left column at very close to full page-black, so the
   measured contrast of the h1 and lede is the same with the image as without
   it — no image can push body text under 4.5:1.
*/
.hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
}

.hero__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 70% center;
}

.hero__scrim {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(
            90deg,
            rgba(11, 11, 13, 0.98) 0%,
            rgba(11, 11, 13, 0.95) 38%,
            rgba(11, 11, 13, 0.72) 68%,
            rgba(11, 11, 13, 0.55) 100%
        ),
        linear-gradient(
            0deg,
            var(--ink) 0%,
            rgba(11, 11, 13, 0.35) 30%,
            rgba(11, 11, 13, 0.2) 60%,
            rgba(11, 11, 13, 0.75) 100%
        );
}

/* Tablet width runs the same asymmetric layout as desktop, but the headline
   occupies a larger share of a narrower hero, so its right edge reaches
   further into the horizontal gradient's low-protection zone. Measured
   against the live photograph, the worst point behind the headline read
   2.62:1 at 768px — under the 3.0 large-text minimum — while the same layout
   at 900px and above was already a safe 3.36:1. This tightens the horizontal
   curve specifically for the gap between them; 64rem and up keeps the
   original above, which is what desktop was designed and measured against. */
@media (min-width: 48rem) and (max-width: 63.999rem) {
    .hero__scrim {
        background:
            linear-gradient(
                90deg,
                rgba(11, 11, 13, 0.98) 0%,
                rgba(11, 11, 13, 0.97) 42%,
                rgba(11, 11, 13, 0.88) 68%,
                rgba(11, 11, 13, 0.65) 100%
            ),
            linear-gradient(
                0deg,
                var(--ink) 0%,
                rgba(11, 11, 13, 0.35) 30%,
                rgba(11, 11, 13, 0.2) 60%,
                rgba(11, 11, 13, 0.75) 100%
            );
    }
}

/* Narrow screens don't get a scrim at all — they get a different layout.
   Earlier this darkened the image behind the full-width headline instead, and
   it had to go to 91% opacity ink to hold contrast, which made a genuine
   problem worse than it needed to be: the jet's lit cabin doorway is one of
   the brightest points in the whole photograph, and on a narrow viewport it
   sits directly behind the headline text with nowhere to hide. Even at 95%
   opacity that patch barely cleared 3:1. No gradient curve fixes a hotspot
   directly behind the text; it only trades legibility against visibility of
   the one detail worth showing.

   The asymmetric desktop hero works because the text lives in a narrow left
   column and the photograph has the open right two-thirds to itself — two
   zones, only one of them needs protecting. Mobile has no such split; the
   text runs the full width, so "protect the text" and "hide the whole image"
   became the same instruction.

   Below this width the photograph is pulled out of the text's way instead:
   a plain banner above the copy, same idea as the pillar plates further down
   the page, at close to full brightness since nothing sits on top of it. The
   headline then renders on flat --ink, where the foil gradient's darkest stop
   measures a flat 3.36:1 — a fixed number, not one that depends on where a
   future photograph happens to be bright. */
@media (max-width: 47.999rem) {
    .hero {
        min-height: 0;
        padding-top: var(--header-h);
        padding-bottom: var(--space-xl);
    }

    .hero--image { padding-top: var(--header-h); }

    .hero__media {
        /* relative, not static: this still sits in normal flow (nothing here
           depends on top/left), but it keeps .hero__media as the containing
           block for .hero__scrim below. Without that the scrim's inset:0
           resolves against .hero instead, several times the banner's height —
           harmless by accident on the current copy length, but one word of
           headline growth away from painting over the lede. */
        position: relative;
        inset: auto;
        width: 100%;
        height: clamp(12rem, 56vw, 20rem);
        overflow: hidden;
    }

    .hero__img {
        object-position: 50% center;
        /* The same restraint applied to the pillar plates, lighter here since
           this photograph carries the page rather than punctuating it. */
        filter: saturate(0.88) brightness(0.9) contrast(1.02);
    }

    /* No text sits on the image in this layout, so nothing needs hiding under
       it. A thin edge only, at the banner's own bottom, to stop a hard seam
       against the ink below. */
    .hero__scrim {
        background: linear-gradient(0deg, var(--ink) 0%, rgba(11, 11, 13, 0) 30%);
    }

    .hero__inner { padding-top: var(--space-lg); }
}

.hero__eyebrow { color: var(--gold); }

.hero__title {
    max-width: 17ch;
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-3xl);
    font-weight: 400;
    line-height: 1.04;
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    text-wrap: balance;

    /* The one element that carries the logo's real foil gradient. The plain
       colour underneath is what any engine that cannot clip a background to
       glyph shapes will paint — champagne, which is a perfectly good headline
       in its own right. This degrades to legible, never to invisible. */
    color: var(--champagne);
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
    .hero__title {
        background: var(--foil);
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        -webkit-text-fill-color: transparent;
    }
}

/* Where the Thread enters the page. */
.hero__rule {
    width: clamp(6rem, 22vw, 15rem);
    height: 1px;
    margin: var(--space-lg) 0 var(--space-md);
    background: linear-gradient(90deg, var(--gold), rgba(201, 162, 78, 0));
}

.hero__lede {
    max-width: 48ch;
    font-size: var(--fs-md);
    color: var(--muted);
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-md);
    margin-top: var(--space-xl);
}

.hero__scroll {
    position: absolute;
    left: 50%;
    bottom: clamp(1.25rem, 3vh, 2.5rem);
    transform: translateX(-50%);
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    transition: color 0.25s var(--ease);
}

.hero__scroll:hover { color: var(--champagne); }

.hero__scroll .icon {
    width: 1rem;
    height: 1rem;
    color: var(--gold);
}

@media (max-width: 47.999rem) {
    .hero__scroll { display: none; }
}


/* 9. Positioning statement ================================================= */

.positioning { padding-block: var(--space-2xl); }

.positioning__inner {
    display: grid;
    gap: var(--space-lg);
    padding-top: var(--space-xl);
    border-top: 1px solid var(--rule-faint);
}

@media (min-width: 48rem) {
    .positioning__inner {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr);
        gap: var(--space-xl);
    }
}

.positioning__heading {
    font-size: var(--fs-xl);
    text-transform: none;
    letter-spacing: 0.01em;
}

.positioning__body {
    display: grid;
    gap: var(--space-md);
    max-width: var(--measure);
    font-size: var(--fs-md);
    color: var(--bone);
}


/* 10. Pillars and service cards ============================================ */

.pillar {
    padding-block: var(--space-3xl);
    scroll-margin-top: calc(var(--header-h) + 1rem);
}

.pillar--panel {
    background: var(--ink-panel);
    border-block: 1px solid var(--panel-edge);
}

.pillar__inner { position: relative; }

/* The numeral node, sitting on the Thread in the rail. */
.pillar__numeral {
    display: none;
    position: absolute;
    left: 0;
    top: 0.15em;
    width: var(--rail-w);
    text-align: center;
    font-family: var(--font-display);
    font-size: 0.9375rem;
    letter-spacing: 0.1em;
    color: var(--gold);
}

/* A short hairline either side, so the numeral reads as a node on the line
   rather than a number floating beside it. */
.pillar__numeral::before,
.pillar__numeral::after {
    content: "";
    position: absolute;
    left: 50%;
    width: 1px;
    height: 1.1rem;
    background: var(--rule-strong);
}

.pillar__numeral::before { bottom: 100%; margin-bottom: 0.45rem; }
.pillar__numeral::after  { top: 100%;    margin-top: 0.45rem; }

@media (min-width: 64rem) {
    .pillar__numeral { display: block; }
}

.pillar__numeral-inline {
    display: inline-block;
    margin-right: 0.75em;
    font-size: 0.5em;
    letter-spacing: 0.12em;
    color: var(--gold);
    vertical-align: 0.35em;
}

@media (min-width: 64rem) {
    .pillar__numeral-inline { display: none; }
}

.pillar__head { margin-bottom: var(--space-2xl); }

.pillar__title {
    font-family: var(--font-display);
    font-size: var(--fs-2xl);
    font-weight: 400;
    line-height: 1.05;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--champagne);
}

.pillar__lede {
    margin-top: var(--space-md);
    max-width: 58ch;
    font-size: var(--fs-md);
    color: var(--muted);
}

.cards {
    display: grid;
    gap: 1px;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
    /* A single hairline grid: cards are separated by the background showing
       through a 1px gap, so there is one continuous rule system rather than
       nineteen boxes each with its own border. */
    background: var(--rule-faint);
    border: 1px solid var(--rule-faint);
}

/* Two-card pillars: wider cards rather than a three-column grid with a hole. */
@media (min-width: 48rem) {
    .cards--sparse { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.card {
    display: flex;
    flex-direction: column;
    padding: var(--space-lg) var(--space-md) var(--space-md);
    background: var(--ink);
    transition: background 0.35s var(--ease);
}

.pillar--panel .card { background: var(--ink-panel); }

.card:hover,
.pillar--panel .card:hover { background: #131215; }

.card__icon {
    display: block;
    margin-bottom: var(--space-md);
    color: var(--gold);
}

.card__icon .icon {
    width: 1.75rem;
    height: 1.75rem;
}

.card__title {
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: 0.02em;
    color: var(--champagne);
}

.card__desc {
    margin-top: var(--space-2xs);
    font-size: var(--fs-sm);
    line-height: 1.55;
    color: var(--muted);
}

.card__rule {
    height: 1px;
    margin: var(--space-md) 0;
    background: var(--rule);
}

.card__list {
    font-size: var(--fs-sm);
    line-height: 1.5;
    color: var(--bone);
}

.card__list li {
    position: relative;
    padding-left: 0.9rem;
    margin-bottom: 0.45rem;
    break-inside: avoid;
}

.card__list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.62em;
    width: 4px;
    height: 1px;
    background: var(--gold);
}

/* Long lists run in two columns so a nine-item list is five lines tall, not
   nine. Only where there is width for it. */
@media (min-width: 30rem) {
    .card__list--cols {
        columns: 2;
        column-gap: var(--space-md);
    }
}

@media (min-width: 48rem) and (max-width: 63.999rem) {
    .card__list--cols { columns: 2; }
}

.card__note {
    margin-top: auto;
    padding-top: var(--space-md);
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--muted);
}

.card__list + .card__note { margin-top: var(--space-md); }


/* -- Photographic plates ---------------------------------------------------
   Full-bleed punctuation between chapters. Short and wide on desktop so a
   plate is a breath rather than a full screen the reader has to scroll past;
   taller on mobile where a 21:9 crop would be a letterbox slit.
*/

.plate {
    position: relative;
    margin: 0;
    overflow: hidden;
}

.plate__img {
    width: 100%;
    height: clamp(14rem, 34vw, 26rem);
    object-fit: cover;
    /* Roughly half the source height is cropped away at this aspect, so the
       centre is rarely the right place to keep. Overridden per image below. */
    object-position: 50% 50%;
    /* Photography on this page is quiet: desaturated slightly and darkened so
       it sits with the palette instead of shouting over it. */
    filter: saturate(0.82) brightness(0.78) contrast(1.04);
}

/* Focal points, set against the actual photographs.
   arrival — the chauffeur's head sits high in frame and a centre crop removes it.
   sea     — the yacht sits low; centring clips its hull.
   suite   — the couple and the window read best just above centre. */
.plate--arrival .plate__img { object-position: 50% 26%; }
.plate--sea     .plate__img { object-position: 50% 62%; }
.plate--suite   .plate__img { object-position: 50% 46%; }

/* A gold hairline top and bottom, so a plate reads as part of the same rule
   system as the Thread and the card grid. */
.plate::before,
.plate::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    height: 1px;
    background: var(--rule);
    z-index: 2;
}

.plate::before { top: 0; }
.plate::after  { bottom: 0; }

.plate__caption {
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 2;
    width: 100%;
    padding: var(--space-xl) var(--gutter) var(--space-md);
    padding-left: max(var(--gutter), calc(50vw - (var(--wrap-max) / 2) + var(--rail-w)));
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    letter-spacing: 0.02em;
    color: var(--champagne);
    background: linear-gradient(0deg, rgba(11, 11, 13, 0.92), rgba(11, 11, 13, 0));
}


/* 11. Why clients stay ===================================================== */

.why__list {
    display: grid;
    gap: var(--space-lg) var(--space-xl);
}

@media (min-width: 40rem) {
    .why__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 64rem) {
    .why__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.why__item {
    padding-top: var(--space-md);
    border-top: 1px solid var(--rule);
}

.why__term {
    display: flex;
    align-items: baseline;
    gap: 0.65rem;
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    line-height: 1.25;
    color: var(--champagne);
}

.why__icon {
    flex-shrink: 0;
    color: var(--gold);
    /* Optically aligns the icon with the cap height of the text beside it. */
    transform: translateY(0.15em);
}

.why__icon .icon { width: 1.25rem; height: 1.25rem; }

.why__def {
    margin-top: var(--space-xs);
    font-size: var(--fs-sm);
    line-height: 1.6;
    color: var(--muted);
}


/* 12. Who we serve ========================================================= */

.who__list {
    border-top: 1px solid var(--rule-faint);
}

.who__item {
    display: grid;
    gap: 0.35rem var(--space-lg);
    padding-block: var(--space-md);
    border-bottom: 1px solid var(--rule-faint);
}

@media (min-width: 48rem) {
    .who__item {
        grid-template-columns: 3rem minmax(0, 15rem) minmax(0, 1fr);
        align-items: baseline;
        gap: var(--space-lg);
    }
}

.who__index {
    font-family: var(--font-display);
    font-size: var(--fs-sm);
    letter-spacing: 0.1em;
    color: var(--gold);
}

.who__title {
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    font-weight: 400;
    line-height: 1.25;
    color: var(--champagne);
}

.who__body {
    font-size: var(--fs-sm);
    line-height: 1.6;
    color: var(--muted);
    max-width: 58ch;
}


/* 13. Contact and form ===================================================== */

.contact__grid {
    display: grid;
    gap: var(--space-2xl);
}

@media (min-width: 62rem) {
    .contact__grid {
        grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
        gap: var(--space-2xl) var(--space-xl);
        align-items: start;
    }
}

.channels {
    display: grid;
    gap: var(--space-sm);
    margin-top: var(--space-xl);
}

.channels__link {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) 0;
    border-top: 1px solid var(--rule-faint);
}

.channels__item:last-child .channels__link { border-bottom: 1px solid var(--rule-faint); }

.channels__icon {
    flex-shrink: 0;
    color: var(--gold);
}

.channels__icon .icon { width: 1.25rem; height: 1.25rem; }

.channels__label {
    display: block;
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted);
}

.channels__value {
    display: block;
    font-size: var(--fs-md);
    color: var(--champagne);
    word-break: break-word;
}

a.channels__link:hover .channels__value { color: var(--gold); }

.channels__email { color: inherit; text-decoration: none; }
.channels__email:hover { color: var(--gold); }

.contact__note {
    margin-top: var(--space-md);
    font-size: var(--fs-sm);
    color: var(--muted);
}

.contact__form-wrap {
    padding: var(--space-lg) var(--space-md);
    background: var(--ink);
    border: 1px solid var(--rule);
}

@media (min-width: 40rem) {
    .contact__form-wrap { padding: var(--space-xl); }
}

.form { display: grid; gap: var(--space-md); }

.field { display: grid; gap: 0.4rem; }

.field__label {
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
}

.field__req { color: var(--gold); margin-left: 0.15em; }

.field__opt {
    margin-left: 0.4em;
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: none;
    color: rgba(154, 149, 138, 0.75);
}

.field__input {
    width: 100%;
    padding: 0.7rem 0.85rem;
    background: rgba(207, 203, 194, 0.04);
    border: 1px solid var(--rule-faint);
    border-radius: var(--radius);
    color: var(--bone);
    font-size: var(--fs-base);
    transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
    /* iOS zooms the page when a focused input is under 16px. */
    min-height: 2.9rem;
}

.field__input::placeholder { color: rgba(154, 149, 138, 0.6); }

.field__input:hover { border-color: var(--rule); }

.field__input:focus {
    border-color: var(--gold);
    background: rgba(207, 203, 194, 0.06);
    outline: 2px solid var(--gold);
    outline-offset: 1px;
}

.field__input[aria-invalid="true"] { border-color: #C8724A; }

.field__textarea {
    min-height: 9rem;
    resize: vertical;
    line-height: 1.6;
}

.field__select { position: relative; }

.field__select::after {
    content: "";
    position: absolute;
    right: 1rem;
    top: 50%;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 1px solid var(--gold);
    border-bottom: 1px solid var(--gold);
    transform: translateY(-70%) rotate(45deg);
    pointer-events: none;
}

.field__select select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.5rem;
}

/* The native dropdown list is drawn by the OS, so its options need a colour
   that works against the OS menu background rather than the page. */
.field__select option {
    background: #17140F;
    color: #CFCBC2;
}

.field__error {
    font-size: var(--fs-sm);
    line-height: 1.45;
    color: #E39A76;
}

.field--group { display: grid; gap: 0.6rem; }

.radios {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.radio { position: relative; }

.radio input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.radio label {
    display: block;
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--rule-faint);
    border-radius: var(--radius);
    font-size: var(--fs-sm);
    color: var(--muted);
    cursor: pointer;
    transition: all 0.2s var(--ease);
}

.radio input:checked + label {
    border-color: var(--gold);
    color: var(--champagne);
    background: rgba(201, 162, 78, 0.08);
}

.radio input:focus-visible + label {
    outline: 2px solid var(--gold);
    outline-offset: 2px;
}

/* Honeypot. Removed from view without display:none, which some bots detect,
   and kept out of the tab order in the markup. */
.hp {
    position: absolute !important;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.form__foot {
    display: grid;
    gap: var(--space-md);
    margin-top: var(--space-xs);
}

.form__privacy {
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--muted);
}

.form__submit[aria-busy="true"] { opacity: 0.6; cursor: progress; }

/* -- Notices -------------------------------------------------------------- */

.notice {
    padding: var(--space-md);
    margin-bottom: var(--space-md);
    border: 1px solid var(--rule);
    border-left-width: 2px;
    font-size: var(--fs-sm);
    line-height: 1.6;
}

.notice[hidden] { display: none; }

.notice--ok {
    border-left-color: var(--gold);
    background: rgba(201, 162, 78, 0.07);
    color: var(--champagne);
}

/* Informational, not a failure. Reads as a quiet note rather than an alarm. */
.notice--preview {
    border-color: var(--rule);
    border-left-color: var(--gold);
    background: rgba(201, 162, 78, 0.05);
    color: var(--muted);
}

.notice--preview strong { color: var(--champagne); font-weight: 600; }

.notice--error,
.notice--warn {
    border-color: rgba(200, 114, 74, 0.4);
    border-left-color: #C8724A;
    background: rgba(200, 114, 74, 0.07);
    color: #EAD9CF;
}

.notice__title {
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    font-weight: 400;
    color: var(--champagne);
    margin-bottom: var(--space-xs);
}

.notice p + p { margin-top: var(--space-xs); }

.notice__admin {
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid rgba(200, 114, 74, 0.3);
    font-size: 0.75rem;
    color: var(--muted);
}

.notice a { color: var(--gold); text-decoration: underline; text-underline-offset: 0.2em; }


/* 14. Footer =============================================================== */

.site-footer {
    position: relative;
    padding-bottom: var(--space-xl);
    background: var(--ink);
    border-top: 1px solid var(--rule-faint);
}

/* Where the Thread ends. */
.site-footer__terminus {
    display: flex;
    justify-content: center;
    padding-block: var(--space-xl);
    color: var(--gold);
}

.fleuron {
    width: 8rem;
    height: 2rem;
    opacity: 0.85;
}

.site-footer__top {
    display: grid;
    gap: var(--space-xl);
    padding-bottom: var(--space-xl);
    border-bottom: 1px solid var(--rule-faint);
}

@media (min-width: 48rem) {
    .site-footer__top {
        grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr);
        gap: var(--space-xl);
    }
}

.site-footer__mark {
    width: 3rem;
    height: 3rem;
    margin-bottom: var(--space-sm);
}

.site-footer__name {
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--champagne);
}

.site-footer__blurb {
    margin-top: var(--space-sm);
    max-width: 46ch;
    font-size: var(--fs-sm);
    line-height: 1.65;
    color: var(--muted);
}

.site-footer__heading {
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--gold);
    margin-bottom: var(--space-sm);
}

.site-footer__list {
    display: grid;
    /* Small, because the links inside carry their own vertical padding. */
    gap: 0.1rem;
    font-size: var(--fs-sm);
    color: var(--bone);
}

.site-footer__list--cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.1rem var(--space-sm);
}

/* A 13px link is a 14px-tall tap target, which is under the 24x24 minimum for
   pointer targets. These are standalone list items rather than links inside a
   sentence, so the inline exception does not apply and they need real padding
   rather than a larger font. */
.site-footer__list a,
.channels__email {
    display: inline-block;
    padding-block: 0.35rem;
}

.site-footer__based { color: var(--muted); }

.site-footer__legal {
    display: grid;
    gap: var(--space-sm);
    padding-top: var(--space-lg);
}

.site-footer__disclaimer,
.site-footer__privacy {
    max-width: 92ch;
    font-size: 0.75rem;
    line-height: 1.65;
    color: var(--muted);
}

.site-footer__copy {
    font-size: 0.75rem;
    color: var(--muted);
}


/* 15. Buttons and shared components ======================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
    padding: 0.85rem 1.6rem;
    border: 1px solid var(--gold);
    border-radius: var(--radius);
    background: none;
    font-family: var(--font-body);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--gold);
    cursor: pointer;
    transition: background 0.25s var(--ease), color 0.25s var(--ease);
}

.btn--primary:hover,
.btn--primary:focus-visible {
    background: var(--gold);
    color: var(--ink);
}

.btn--ghost {
    padding: 0.6rem 1.1rem;
    border-color: var(--rule-strong);
    color: var(--champagne);
    font-size: var(--fs-xs);
}

.btn--ghost:hover {
    border-color: var(--gold);
    color: var(--gold);
}

.btn--quiet {
    border-color: transparent;
    padding-inline: 0;
    color: var(--muted);
    letter-spacing: 0.08em;
    text-transform: none;
    font-weight: 400;
    font-size: var(--fs-base);
}

.btn--quiet:hover { color: var(--champagne); }

.btn--quiet .icon {
    width: 1.05rem;
    height: 1.05rem;
    color: var(--gold);
}

.icon {
    width: 1.25rem;
    height: 1.25rem;
    flex-shrink: 0;
}


/* 16. Motion ===============================================================
   Two effects and no more: a staged entrance in the hero, and a quiet fade for
   sections arriving on scroll. Both are opt-in through the "js" class, so with
   scripting off every element is simply visible from the start.
*/

@keyframes nx-rise {
    from { opacity: 0; transform: translateY(0.75rem); }
    to   { opacity: 1; transform: none; }
}

html.js .hero [data-seq] {
    opacity: 0;
    animation: nx-rise 0.85s var(--ease) forwards;
}

html.js .hero [data-seq="1"] { animation-delay: 0.05s; }
html.js .hero [data-seq="2"] { animation-delay: 0.15s; }
html.js .hero [data-seq="3"] { animation-delay: 0.42s; }
html.js .hero [data-seq="4"] { animation-delay: 0.52s; }
html.js .hero [data-seq="5"] { animation-delay: 0.62s; }
html.js .hero [data-seq="6"] { animation-delay: 0.95s; }

/* The rule under the h1 draws rather than fades — it is the Thread arriving. */
html.js .hero .hero__rule {
    animation: nx-draw 0.9s var(--ease) 0.42s forwards, nx-rise 0.01s linear 0.42s forwards;
    transform-origin: left;
}

@keyframes nx-draw {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

html.js .reveal {
    opacity: 0;
    transform: translateY(0.9rem);
    transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

html.js .reveal.is-visible {
    opacity: 1;
    transform: none;
}

/* -- Reduced motion -------------------------------------------------------
   Everything above is switched off: no scroll reveals, no entrance sequence,
   no smooth scrolling. Content is present and static.
*/
@media (prefers-reduced-motion: reduce) {

    html { scroll-behavior: auto; }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    html.js .hero [data-seq],
    html.js .reveal {
        opacity: 1;
        transform: none;
        animation: none;
    }

    html.js .hero .hero__rule { clip-path: none; }
}
