/* ─────────────────────────────────────────────────────────────────────────────
   fx — the shared design system.

   Dark ground, no cards, no shadows, no fills. Separation is a 1px rule and
   space; type carries the hierarchy — a small uppercase label above a large
   light heading above quiet body copy.

   WHERE THIS CAME FROM. Every rule here was written for flock.aiquniq.com and
   lived in pages/software/flock/site.css. The apex now uses the same system, so
   the parts that were never flock-specific were lifted out verbatim and the
   scope class renamed .flock-site → .fx-site. flock/site.css keeps only what is
   genuinely its own — the video hero, the canvas stages, the tier columns, the
   comparison matrix and the offer form — loads AFTER this sheet, and its pages
   carry both classes on the wrapper.

   SCOPE. Three layers, and the distinction matters when adding rules:

     :root        the tokens, in main.css. The nav and the footer sit OUTSIDE
                  the page wrapper, so they cannot depend on .fx-site.
     .fx-nav      the bar. Scoped because main.css styles .nav globally for the
                  pages that have not been rebuilt.
     .fx-site     the page body. Scoped because main.css sets global h1/h2/p
                  colours and a 1.4rem paragraph size, and those are element
                  selectors a bare class would lose to.

   footer.fx-foot is its own case: the live five-column footer's .legal/.social
   rules in main.css carry `color: … !important`, so the footer here starts from
   a clean .fx-foot-* namespace rather than fighting !important on every rule.

   Tokens live in main.css. This sheet only consumes them.
   ────────────────────────────────────────────────────────────────────────── */

.fx-site {
    background: var(--fx-bg);
    color: var(--fx-muted);
    font-family: Arial, Helvetica, sans-serif;
    -webkit-font-smoothing: antialiased;

    /* NO overflow-x here, deliberately — see .flock-site in flock/site.css,
       which is where the clip this used to carry now lives. It was added for
       the pricing matrix, which no apex page has, and on the apex the wrapper
       is the <main> element with the inquiry and careers overlays inside it.
       A clipping ancestor is one of the things that can take a fixed overlay
       out of the viewport's coordinate space, and the clip buys nothing here. */
}

/* main.css sets global h1/h2/p colours and a 1.4rem paragraph size tuned for
   the tab shell's wide light sections. Reset inside this page only. */
.fx-site h1,
.fx-site h2,
.fx-site h3 {
    color: var(--fx-fg);
    font-weight: 500;
    letter-spacing: -0.015em;
    margin: 0;
}

.fx-site p {
    color: var(--fx-muted);
    font-size: 16px;
    line-height: 1.65;
    margin: 0;
}

.fx-site a {
    color: inherit;
}

/* ─── Shell ────────────────────────────────────────────────────────────────
   .fx-section is the full-bleed band; .fx-wrap is the measure inside it. The
   rule lives on the section's top edge so consecutive sections never double it
   and the first one after the hero needs no special case. */

.fx-section {
    width: 100%;
    box-sizing: border-box;
    padding: var(--fx-pad) 24px;
    border-top: 1px solid var(--fx-rule);
    /* main.css makes .content a column flexbox, and a flex item defaults to
       min-width:auto — so the 640px matrix inside would widen this band past
       the viewport instead of scrolling inside its own container, and take the
       whole page sideways with it. */
    min-width: 0;
}

.fx-section--flush {
    border-top: none;
}

.fx-section--tight {
    padding-top: 56px;
    padding-bottom: 56px;
}

/* Pricing's opening band. It clears the fixed nav itself — there is no hero
   image above it to do that — and closes tighter than --fx-pad, because the
   tier columns that follow bring their own top padding. */
.fx-section--hero {
    padding-top: calc(var(--fx-nav-h) + 72px);
    padding-bottom: 40px;
}

.fx-wrap {
    width: 100%;
    max-width: var(--fx-max);
    margin: 0 auto;
    min-width: 0;
}

/* A centred reading column.

   The apex home page is laid out around a centred masthead, and the inner
   pages' left-ranged column read wrong under it: a wordmark centred across the
   full width with the copy below it hugging the left edge and ~900px of empty
   page to its right looks unfinished rather than deliberate.

   LEFT-ALIGNED BUT CENTRED, and the distinction is the whole rule. Nothing here
   sets `text-align: center` — every line still starts at the same left edge, so
   the copy reads exactly as it does on every other page. What moves is the
   COLUMN: it sits on the page's centre line under the mark instead of against
   the left margin.

   That only holds if every block in the column resolves to the SAME width. A ch
   is relative to the element's own font-size, so .fx-lede at 20px and the 16px
   paragraphs under it turn 62ch into different pixel widths — centre both and
   their left edges land in different places, which reads as a mistake rather
   than as a column. One measure, in px, for all of them.

   Scoped under .fx-site so these beat .fx-hero-statement's own 20ch cap on the
   big heading, which is declared later in this file at equal specificity.

   Home only: every other page opens on a page head or a left-set hero and is
   ranged left down the whole page. */
.fx-wrap--center {
    --fx-measure: 660px;
}

.fx-site .fx-wrap--center > .fx-label,
.fx-site .fx-wrap--center > .fx-h,
.fx-site .fx-wrap--center > .fx-h-lg,
.fx-site .fx-wrap--center .fx-lede,
.fx-site .fx-wrap--center .fx-statement-body,
.fx-site .fx-wrap--center .fx-row-copy,
.fx-site .fx-wrap--center .fx-cta-actions {
    max-width: var(--fx-measure);
    margin-inline: auto;
}

/* ─── Type ─────────────────────────────────────────────────────────────────
   The micro-label is the workhorse: it names the row so the heading never has
   to, which is what lets the headings stay short and large. */

.fx-label {
    display: block;
    margin: 0 0 20px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fx-label);
}

.fx-h {
    font-size: clamp(28px, 3.4vw, 46px);
    line-height: 1.08;
}

.fx-h-lg {
    font-size: clamp(34px, 5vw, 62px);
    line-height: 1.04;
}

/* A heading that turns a corner INSIDE a row's copy rather than opening it —
   Careers uses one to pivot from "here is what we want" to "here is what that
   means for you". At full .fx-h size it would outrank the row's own opening,
   so it takes the step between a heading and body copy and the air a new
   thought needs above it.

   Scoped: the margin has to beat `.fx-site h1, h2, h3 { margin: 0 }` above,
   which is an element+class selector a bare class would lose to. */
.fx-site .fx-h--mid {
    font-size: clamp(20px, 1.9vw, 24px);
    line-height: 1.25;
    margin-top: 32px;
}

/* Scoped, like every .fx-* rule below that targets a <p>: the `.fx-site p`
   baseline above is an element+class selector and outranks a bare class. */
.fx-site .fx-lede {
    max-width: 62ch;
    font-size: clamp(17px, 1.6vw, 20px);
    line-height: 1.55;
    color: var(--fx-muted);
}

.fx-body > p + p {
    margin-top: 18px;
}

.fx-site .fx-note {
    font-size: 13px;
    line-height: 1.6;
    color: var(--fx-label);
}

.fx-site .fx-note + .fx-note {
    margin-top: 10px;
}

.fx-notes {
    margin-top: 32px;
}

.fx-site .fx-lede--spaced {
    margin-top: 28px;
}

/* ─── Capability row ───────────────────────────────────────────────────────
   Label in a narrow left column, copy in a wide right one — the layout that
   makes a long page of prose scannable. Collapses to stacked on tablet, where
   a 220px column would squeeze the measure below readable. */

/* Numbered from a CSS counter rather than the markup: the sequence is a
   property of the page's order, and hard-coding it in Blade would mean renaming
   every row to move one — and would need no translation either way. */
.fx-site {
    counter-reset: fx-row;
}

.fx-row {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    gap: 48px;
    align-items: start;
    counter-increment: fx-row;
}

.fx-row .fx-label::before {
    content: counter(fx-row, decimal-leading-zero);
    display: block;
    margin-bottom: 8px;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: rgba(255, 255, 255, 0.22);
}

.fx-row + .fx-row {
    margin-top: 72px;
    padding-top: 72px;
    border-top: 1px solid var(--fx-rule);
}

.fx-row .fx-label {
    margin: 6px 0 0;
}

/* A section label introducing a block that is not a .fx-row — the four-reasons
   table, folded into the warning-to-order section rather than given a band of
   its own. Takes the rule and the spacing a row would have brought with it. */
.fx-label--band {
    margin-top: 72px;
    padding-top: 72px;
    border-top: 1px solid var(--fx-rule);
}

.fx-row .fx-h {
    margin-bottom: 20px;
}

.fx-row-copy {
    max-width: 68ch;
}

/* The opening paragraph states the claim and the ones after it qualify — so it
   is set a step up, and the row reads as a lede plus detail rather than an
   undifferentiated block. */
.fx-site .fx-row-copy > p:first-of-type {
    font-size: 18px;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.76);
}

/* A row whose left column is the count alone.

   FLoCK's rows are named by a one- or two-word .fx-label and the heading
   follows on the right. The apex's policy pages — Covenant, Fairness practices,
   Requirements — are sequences of titled clauses whose titles are sentences
   ("A fair stake that reflects our impact"), and a sentence set in 11px tracked
   uppercase inside a 220px column runs four lines and reads as shouting.

   So the title stays a real heading on the right, and the left column keeps
   only the numeral — which is the part that makes the clauses read as one
   ordered set rather than a pile of unrelated sections. Same counter as
   .fx-label::before, so a page may mix the two kinds of row and the sequence
   still runs straight through. */
.fx-row-num {
    display: block;
    margin: 6px 0 0;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: rgba(255, 255, 255, 0.22);
}

.fx-row-num::before {
    content: counter(fx-row, decimal-leading-zero);
}

/* ─── Hero ─────────────────────────────────────────────────────────────────
   The banner partial is shared with the live tabs, so nothing about its markup
   can change. .fx-hero is a wrapper this page adds around it, which is what the
   scrim and the cue position against.

   --fx-hero-travel is the parallax amplitude, and it is load-bearing: the clip
   has to be taller than its frame by twice this, or the translate exposes an
   edge at the extremes. Both numbers below derive from it. */

.fx-site {
    /* Full viewport. The shortened hero read as a cropped banner rather than an
       opening — at this scale the clip has to own the first screen. */
    --fx-hero-h: 100vh;
    --fx-hero-travel: 12vh;
}

.fx-hero {
    position: relative;
    /* No overflow here, deliberately. subdomain.css drives the clip from a
       view() timeline named on .banner, and a timeline resolves against its
       subject's nearest SCROLLPORT — an `overflow: hidden` wrapper becomes one,
       which freezes the animation at its first keyframe. .banner already clips
       the oversized clip itself, and the scrim and cue are both inside the
       hero's own box, so there is nothing here left to clip. */
}

.fx-site .banner {
    /* banner.css sets 100vh — on a tall display, the entire screen before a
       word of copy. This page's argument is the reading below the hero. */
    height: var(--fx-hero-h);
    /* Short landscape windows: 100vh can leave the headline crowded against the
       nav, so hold a floor. */
    min-height: 540px;
    /* banner.css also sets a 50px top margin, which under a transparent nav
       showed as a band of empty page above the clip. */
    margin-top: 0;

    /* banner.css gives .banner `position: relative; z-index: 0`, which opens a
       stacking context and seals its children inside it — so the scrim, a
       SIBLING of .banner, painted over the hero copy no matter how high that
       copy's z-index went. `auto` keeps the positioning and drops the context,
       letting the three layers below order against each other directly. */
    z-index: auto;
}

/* The layer order the scrim depends on: clip, scrim, copy. The clip has to be
   pushed down explicitly — banner.css's `.banner > *:not(img)` rule puts every
   non-image child, the <video> included, at z-index 2. */
.fx-site .banner video,
.fx-site .banner img {
    z-index: 0;
}

.fx-site .banner img,
.fx-site .banner video {
    /* Taller than the frame by the full parallax travel in both directions, and
       pulled up by half of it, so the clip covers the banner at every point of
       the animation instead of dragging an empty edge into view. This is what
       was broken: subdomain.css animates ±35vh for a 100vh hero, and at 72vh
       that left a visible gap before a single pixel had been scrolled. */
    height: calc(var(--fx-hero-h) + var(--fx-hero-travel) * 2 + 4px);
    min-height: calc(540px + var(--fx-hero-travel) * 2 + 4px);
    margin-top: calc(var(--fx-hero-travel) * -1 - 2px);
}

/* Two jobs in one element, as two stacked gradients.

   Across: the headline sits on the left, and the clip's content there is road
   and containers — busy, mid-tone, and whatever frame is on screen is the one
   the copy has to survive. This darkens that side only.

   Down: dissolves the clip into the page ground, so the hero ends rather than
   simply stopping at a hard edge.

   Above the video, below the hero text — banner.css puts that at z-index 2 and
   the overrides here lift it to 3. */
.fx-hero-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        linear-gradient(to right,
            rgba(10, 10, 10, 0.78) 0%,
            rgba(10, 10, 10, 0.42) 26%,
            rgba(10, 10, 10, 0) 56%),
        linear-gradient(to bottom,
            rgba(10, 10, 10, 0) 52%,
            rgba(10, 10, 10, 0.55) 76%,
            var(--fx-bg) 100%);
}

/* Scroll cue — a chevron, not a rule.
   It stays away for the first few seconds so the hero is uninterrupted, arrives
   only if the visitor has not moved, and leaves for good on the first scroll
   (fx-site.js adds .is-gone). Nothing here is interactive: it is a hint. */
.fx-hero-cue {
    position: absolute;
    left: 50%;
    bottom: 34px;
    z-index: 3;
    width: 34px;
    height: 34px;
    margin-left: -17px;
    pointer-events: none;
    opacity: 0;
    /* 2.6s of nothing, then fade up over 0.6s. */
    animation: fx-cue-in 0.6s ease 2.6s forwards;
}

.fx-hero-cue.is-gone {
    opacity: 0;
    /* Overrides the arrival animation once scrolling starts, so it cannot fade
       back in behind the reader. */
    animation: none;
    transition: opacity 0.3s ease;
}

/* The chevron itself: two borders on a rotated square. */
.fx-hero-cue span {
    position: absolute;
    top: 8px;
    left: 50%;
    width: 15px;
    height: 15px;
    margin-left: -7.5px;
    border-right: 1.5px solid var(--fx-fg);
    border-bottom: 1.5px solid var(--fx-fg);
    transform: rotate(45deg);
    animation: fx-cue-bob 2s ease-in-out 3.2s infinite;
}

@keyframes fx-cue-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 0.75; transform: none; }
}

@keyframes fx-cue-bob {
    0%, 100% { transform: rotate(45deg) translate(0, 0); }
    50%      { transform: rotate(45deg) translate(4px, 4px); }
}

/* Hero copy. banner.css sizes .banner-h1 for the live tabs; at this scale the
   headline should carry the page. */
.fx-site .banner-text {
    left: max(24px, calc((100% - var(--fx-max)) / 2));
    padding: 0;
    z-index: 3;
}

.fx-site .banner-h1 {
    /* The 48px floor is what a phone gets: 5.6vw only overtakes it above 857px,
       so everything from there up is unchanged and there is no step at any
       breakpoint. It used to floor at 38px, which left the hero headline
       smaller on a phone than the h1 of every section below it. */
    font-size: clamp(48px, 5.6vw, 76px);
    font-weight: 500;
    line-height: 1.02;
    letter-spacing: -0.03em;
    margin: 0 0 14px;
}

.fx-site .banner-p {
    font-size: clamp(15px, 1.5vw, 19px);
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.78);
    margin: 0;
    max-width: 34ch;
}


/* The home masthead.

   The apex home page is the one hero that is not a page title and not dark: a
   near-white paper relief with the wordmark centred on it in black.

   IT RUNS UNDER THE BAR, like every other hero on the estate. It used to start
   below one: the bar was solid from the first frame here, an opaque band needs
   clearance, and this element paid for it with a top padding of one nav height.
   That left the page opening on a black strip with a hard edge across the top
   of the artwork — the one thing on the home page that looked bolted on rather
   than designed.

   The bar floats over it now, and it is the ordinary fx bar while it does —
   transparent, white ink, the same gradient scrim every other hero gets. One
   bar, estate-wide, with no page-specific variant. fx-site.js measures this
   element for the threshold exactly as it measures .fx-hero elsewhere.

   That does put white links over near-white artwork for the length of the
   hero, carried by the scrim alone. Deliberate: the bar is identical on every
   page, and this is the page that pays for it.

   Nothing is left to declare — .fx-site .banner above already zeroes
   banner.css's 50px top margin and holds the 100vh height — so this class is
   now only a hook: the element fx-site.js measures to find where the hero ends.
   It stays a class rather than becoming an id or a data attribute because the
   script selects it alongside .fx-hero in one querySelector. */

/* A call to action in the hero. Only the software page has one; it rides the
   same intro animation as the copy above it, so it is declared before that
   rule rather than after. */
.fx-hero-btn {
    margin-top: 26px;
}

/* Intro. Runs once on load — the headline first, the line under it just behind.
   Plain CSS animation rather than the JS reveal: this is above the fold and has
   to be moving before any observer could fire. */
.fx-site .banner-h1,
.fx-site .banner-p {
    animation: fx-hero-in 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

.fx-site .banner-p {
    animation-delay: 0.12s;
}

@keyframes fx-hero-in {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .fx-site .banner-h1,
    .fx-site .banner-p {
        animation: none;
    }
}

@media (max-width: 768px) {
    .fx-hero-cue {
        display: none;
    }

    /* Phone hero. The copy moves toward the middle of the screen in BOTH axes
       and grows, but stops deliberately short of dead centre.

       Vertically: banner.css parks it at 70vh, which on a mobile still sits
       low enough to land on whatever the artwork's lower third holds. 58vh
       lifts it clear. (The base rule's translateY(-50%) means this is the
       block's centre, not its top.) Not 50vh — dead centre lands on the subject
       of both heroes we have, which is the one thing worth not covering.

       Horizontally: the text stays LEFT-aligned and the block starts at 18%
       instead of a 24px gutter, so a short word like FLoCK™ reads as sitting
       near the middle rather than jammed into the corner — offset, not centred.
       Left-aligned matters: .fx-hero-scrim darkens the left 56% with a
       left-to-right gradient precisely so white text reads there, and centring
       the copy would push half of it past where that gradient has faded out. */
    .fx-site .banner-text {
        left: 18%;
        right: 24px;
        top: 58vh;
        /* banner.css's mobile rule adds margin-right: 5% on top of whatever
           `right` says, which would quietly inset the block further than the
           24px written here. */
        margin-right: 0;
    }

    .fx-site .banner-p {
        font-size: 16px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fx-hero-cue {
        animation: none;
        opacity: 0.6;
    }

    .fx-hero-cue span {
        animation: none;
    }
}

.fx-hero-statement .fx-h-lg {
    max-width: 20ch;
    margin-bottom: 28px;
}

/* ─── Canvas stages ────────────────────────────────────────────────────────
   A framed exhibit: a caption bar naming the claim, then the thing itself —
   FLoCK puts its canvas scenes in one, the apex software page its embedded
   product demos.

   Full-bleed was the mistake in the first pass: an unlabelled black band
   between two text sections reads as a gap rather than an exhibit. Framing it
   inside the content measure, with a caption bar naming the claim above it,
   makes it legible as the product doing the thing just described. */

.fx-stage {
    margin: 0;
    border: 1px solid var(--fx-rule);
    border-radius: 6px;
    overflow: hidden;
    background: #000;
}

.fx-stage-bar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 16px;
    height: 40px;
    border-bottom: 1px solid var(--fx-rule);
    background: var(--fx-bg-raised);
}

.fx-stage-dots {
    display: inline-flex;
    gap: 6px;
}

.fx-stage-dots i {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.14);
}

.fx-stage-name {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fx-label);
}

/* An embedded demo filling a stage. The software page has five of them at four
   different heights, which used to be four width/height pairs in software.css
   plus three breakpoints' worth of overrides — the frames were laid out BESIDE
   their prose at percentage widths, so every one of them needed its own rule at
   every width. Inside a stage the frame is simply full width, and the only
   thing that varies is how tall the exhibit wants to be: --fx-stage-h, set per
   stage where the default does not fit. */
.fx-stage-frame {
    display: block;
    width: 100%;
    height: var(--fx-stage-h, 460px);
    border: 0;
    background: #000;
}

/* A stage closing the capability row above it rather than opening a band of its
   own. Takes the gap a second row would have taken, so the exhibit reads as
   part of the argument it follows instead of as the next section. */
.fx-stage--row {
    margin-top: 56px;
}

@media (max-width: 768px) {
    /* The embeds are fixed-width documents; below this they are being scaled
       into a column narrower than they were drawn for, and holding the desktop
       height just adds empty black. */
    .fx-stage-frame {
        height: var(--fx-stage-h-mob, 380px);
    }
}

/* ─── Prose ────────────────────────────────────────────────────────────────
   Long-form copy that arrives as raw HTML from a lang file — the privacy
   policy, the terms, the cookie policy. The Blade view cannot put a class on
   anything inside it, so this styles the elements directly within one wrapper.

   WHY THE LEGAL PAGES CHANGED GROUND. They used to set `.tc { background:
   white }` with black type: three white pages in an otherwise black estate,
   reached from a black nav that stayed black above them. The reasoning was
   presumably readability, but the rest of the site reads fine dark and these
   pages are the ones a reader is most likely to arrive at from another page —
   the flash between the two was the worst of it.

   So they are dark like everything else, and legibility is bought the way the
   rest of the system buys it: a 68ch measure, generous leading, and headings
   that are a size apart rather than a colour apart.

   Only the tags the copy actually uses are covered — p, b, i, u, a, h2, h3 and
   the two classes the translators use inline. There is no <ul>, <ol> or
   <table> anywhere in en, cz or sk. */

/* ─── The document column ──────────────────────────────────────────────────
   These are the only pages on the site a reader is expected to work THROUGH
   rather than scan, and the first pass at them got the easy half right (dark
   ground, one measure) and the hard half wrong: the column sat hard against the
   left edge of an 1180px wrap with 500px of empty page beside it, the body ink
   was --fx-muted at 0.62 over sixteen screens of clauses, and every heading was
   a large caps line with nothing marking where one section ended.

   CENTRED COLUMN, RANGED LEFT — the same distinction the home page makes.
   Nothing here sets text-align; what moves is the column, onto the page's
   centre line, where a document belongs.

   ONE MEASURE IN PIXELS, shared by the title, the date and the body. The old
   68ch on .fx-prose resolved against the prose font-size alone, so the heading
   above it and the copy below it were different widths. */

.fx-doc {
    --fx-measure: 760px;
}

.fx-site .fx-doc > .fx-h-lg,
.fx-site .fx-doc > .fx-page-date,
.fx-site .fx-doc > .fx-prose {
    max-width: var(--fx-measure);
    margin-inline: auto;
}

.fx-prose {
    /* Standalone fallback for a prose column outside .fx-doc. */
    max-width: 68ch;
    /* The reading ink. Brighter than --fx-muted, which is mixed for a paragraph
       or two under a heading, not for a document somebody has to get through —
       and these are the pages where "I could not read it" is a legal problem
       and not only a design one. */
    --fx-doc-ink: rgba(255, 255, 255, 0.80);
}

.fx-site .fx-prose p {
    font-size: 17px;
    line-height: 1.8;
    color: var(--fx-doc-ink);
}

/* The opening paragraph of the privacy policy takes .fx-lede, which caps itself
   at 62ch — about 550px at this size, against the column's 760. Two left-ranged
   blocks of different widths under one heading read as a mistake rather than as
   a lede, and the column already holds the measure. */
.fx-site .fx-prose .fx-lede {
    max-width: none;
    color: var(--fx-doc-ink);
}

.fx-site .fx-prose p + p {
    margin-top: 20px;
}

/* h1 as well as h2: the translators head each section with an <h1> inside the
   copy in the privacy policy and an <h2> in the terms and the cookie policy,
   and that is not something a stylesheet can fix. Both are section headings, so
   both are set as one; the page's real <h1> is in the page head above, which
   this column does not contain.

   A RULE ABOVE EACH ONE. The copy sets these in caps, and a caps line at 28px
   is a shout with no structure; at 20px over a hairline it is a section head in
   a document, which is what it is. The rule is the same one every band on the
   estate separates with. */
.fx-site .fx-prose h1,
.fx-site .fx-prose h2 {
    margin: 68px 0 24px;
    padding-top: 30px;
    border-top: 1px solid var(--fx-rule);
    font-size: 20px;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.35;
    color: var(--fx-fg);
    /* The policy's own contents list jumps to these; without this the fixed bar
       lands on top of whichever heading you asked for. */
    scroll-margin-top: calc(var(--fx-nav-h) + 40px);
}

/* The terms and the cookie policy open on their first section, so that one
   would carry a rule directly under the page head's own. */
.fx-site .fx-prose > h1:first-child,
.fx-site .fx-prose > h2:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.fx-site .fx-prose h3 {
    margin: 38px 0 12px;
    font-size: 16px;
    font-weight: 600;
    color: var(--fx-fg);
}

/* The empty <div> the view emits before each section, which is what #1p…#16p
   actually point at. */
.fx-prose .fx-anchor {
    scroll-margin-top: calc(var(--fx-nav-h) + 40px);
}

/* ─── "In Short:" ──────────────────────────────────────────────────────────
   Every section of the privacy policy opens with a one-sentence precis wrapped
   in <i>, and it is the one thing in these documents a reader actually reads.
   It was an italic line in the flow, indistinguishable from the clause under
   it. The rule makes it the section's standfirst.

   `i:only-child` and not `.fx-prose i`: nine of the italics across the three
   locales are inline emphasis mid-sentence, and those must stay inline.

   `p:not(.padding-p)` because :only-child counts ELEMENTS, not nodes. The
   defined-term entries below are `<p class="padding-p"><i>Term.</i> body…</p>`,
   where the body is a bare text node — so their <i> is an only CHILD ELEMENT
   and matched this rule, handing every defined term the precis's left rule and
   a 20px indent off the column. */
.fx-site .fx-prose p:not(.padding-p) > i:only-child {
    display: block;
    padding-left: 20px;
    border-left: 2px solid var(--fx-rule-strong);
    color: var(--fx-fg);
}

/* ─── Table of contents ────────────────────────────────────────────────────
   Privacy only, and the view wraps the lang string to give it this hook. The
   copy is sixteen <p>s each holding one link, which under the prose rules above
   came out as sixteen underlined paragraphs 20px apart — a page and a half of
   loose blue-less links where a contents list should be. Rows on a hairline,
   no underline, the way the footer columns and the positions list are set. */

.fx-toc {
    margin: 44px 0 8px;
}

.fx-site .fx-prose .fx-toc h2 {
    margin: 0;
    padding: 0 0 6px;
    border-top: none;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    color: var(--fx-label);
}

.fx-site .fx-prose .fx-toc p {
    margin: 0;
    border-top: 1px solid var(--fx-rule);
}

.fx-site .fx-prose .fx-toc p:last-child {
    border-bottom: 1px solid var(--fx-rule);
}

.fx-site .fx-prose .fx-toc a {
    display: block;
    padding: 13px 0;
    font-size: 14px;
    color: var(--fx-muted);
    text-decoration: none;
    transition: color 0.2s ease;
}

.fx-site .fx-prose .fx-toc a:hover,
.fx-site .fx-prose .fx-toc a:focus-visible {
    color: var(--fx-fg);
}

/* The one place in the system where a link has to look like a link: these pages
   are full of running prose with references inside it, and the hairline-only
   treatment the nav and footer use would make them invisible mid-sentence. */
.fx-site .fx-prose a {
    color: var(--fx-fg);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-color: var(--fx-rule-strong);
    transition: text-decoration-color 0.2s ease;
}

.fx-site .fx-prose a:hover {
    text-decoration-color: var(--fx-fg);
}

.fx-site .fx-prose b {
    color: var(--fx-fg);
    font-weight: 600;
}

/* ─── Clause lists ────────────────────────────────────────────────────────
   .padding-p is the only indent the translators have, and they use it for list
   items: 117 of them in the English privacy policy, 79% under 70 characters,
   nearly all opening with a literal "- ". Giving each one a left rule and 18px
   of air turned a six-item list ("- first name", "- surname", …) into six
   separate quoted asides running half a screen. They are set as a list now —
   a hanging indent so the dash sits outside the text and wrapped lines align
   under it, and the spacing of a list rather than of paragraphs.

   The border moved to the "In Short" precis above, which is the one thing on
   these pages that genuinely is an aside. */
.fx-site .fx-prose .padding-p {
    margin: 0;
    padding-left: 26px;
    text-indent: -14px;
    /* Tighter than running prose. At 1.8 a column of one-line items sits 38px
       apart and stops reading as a group. */
    line-height: 1.55;
    border-left: none;
}

/* Specificity note: all three beat `.fx-site .fx-prose p + p` (0,2,2) on class
   count, which is what otherwise puts 20px between every list item. */
.fx-site .fx-prose .padding-p + .padding-p {
    margin-top: 8px;
}

.fx-site .fx-prose p + .padding-p {
    margin-top: 18px;
}

.fx-site .fx-prose .padding-p + p {
    margin-top: 24px;
}

/* ─── Defined terms ───────────────────────────────────────────────────────
   The same .padding-p carries a SECOND shape the translators use, and it is not
   a list item: a term in <i>, then the paragraph that defines it.

       <p class="padding-p"><i>Log and Usage Data.</i> Log and usage data is…</p>
       <p class="padding-p"><i>Device Data.</i> We collect device data such as…</p>
       <p class="padding-p"><i>Location Data.</i> We collect location data such…</p>

   Three of them run back to back under "The information we collect includes:",
   each one a full paragraph long, and the list rules above gave them a tight
   1.55 leading and 8px of air — so the term that opens each entry sat directly
   under the last line of the previous entry with nothing between them. Three
   definitions ran together as one wall.

   They get the treatment one level down from a section head: a rule across the
   column, then the term on its own line, then its paragraph at reading leading.
   No indent — a full-width divider with an indented body under it reads as a
   mistake, and these are sub-sections, not items in a list.

   `:has(> i:first-child)` is what separates the two shapes, and it is exact:
   across en, cz and sk there are 9 paragraphs that open with an <i> and 397
   that do not, and none that are an <i> alone (which is the "In Short" precis
   above, and never a .padding-p). Where :has is unsupported these simply stay
   list items — tight, but not broken. */
.fx-site .fx-prose .padding-p:has(> i:first-child) {
    margin-top: 32px;
    padding: 26px 0 0;
    text-indent: 0;
    line-height: 1.8;
    border-top: 1px solid var(--fx-rule);
}

/* The term. Not italic: it is a label, not emphasis, and the italic was doing
   the whole job of marking it on its own. The two resets are belt and braces
   against the precis rule above ever matching here again. */
.fx-site .fx-prose .padding-p > i:first-child {
    display: block;
    margin-bottom: 8px;
    padding-left: 0;
    border-left: none;
    font-style: normal;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--fx-fg);
}

/* The cookie inventory. A near-white rounded panel in legal.css, which on this
   ground would be the brightest object on the page — it is a definition list in
   everything but markup, so it is set as one. */
.fx-site .fx-prose .cookie-list {
    margin: 0 0 18px;
    padding: 22px 0 0;
    border: none;
    border-top: 1px solid var(--fx-rule);
    border-radius: 0;
    background: none;
}

.fx-site .fx-prose .cookie-list h3 {
    margin: 0 0 10px;
}

.fx-site .fx-prose .cookie-list p {
    margin-top: 0;
    font-size: 15px;
    color: var(--fx-label);
}

/* ─── FAQ ──────────────────────────────────────────────────────────────────
   Keeps elements/faq.css's class names so addons/faq.js binds to it unchanged —
   only the paint differs, and the old sheet stays correct for the pages still
   using it.

   What it replaces: each question was a dark rounded pill that inverted to a
   white fill and slid 1% right on hover, and each answer a LIGHT GREY panel
   with black text. On a near-black page, opening a question lit a white box
   halfway down the screen — the single loudest thing in the design.

   Here a question is a line, the rule under it is the separation, and the
   answer is the paragraph it reveals. Nothing moves but the disclosure. */

.fx-faq {
    margin-top: 48px;
}

.fx-faq .faq-item {
    margin: 0;
    border-top: 1px solid var(--fx-rule);
}

.fx-faq .faq-item:last-child {
    border-bottom: 1px solid var(--fx-rule);
}

.fx-faq .faq-question {
    padding: 24px 32px 24px 0;
    background: none;
    border-radius: 0;
    font-size: 17px;
    line-height: 1.4;
    color: var(--fx-fg);
    transition: color 0.2s ease;
}

.fx-faq .faq-question:hover {
    background: none;
    color: var(--fx-muted);
    transform: none;
}

.fx-faq .faq-question::after {
    font-size: 10px;
    color: var(--fx-label);
}

/* Scoped past `.fx-site p`-style element selectors the same way the rest of the
   sheet is, and past faq.css's own (0,1,0) and (0,3,0) rules. The padding is
   CSS's again — see the note in addons/faq.js. */
.fx-site .fx-faq .faq-answer {
    margin: 0;
    padding: 0;
    background: none;
    border-radius: 0;
    font-size: 15px;
    line-height: 1.65;
    color: var(--fx-muted);
}

.fx-site .fx-faq .faq-item.active .faq-answer {
    padding: 0 32px 26px 0;
}

/* ─── Buttons ──────────────────────────────────────────────────────────────
   Primary inverts the page: white fill, black text. On a ground this dark that
   is the strongest possible emphasis and needs no colour. */

.fx-btn {
    display: inline-block;
    /* There is no universal border-box reset in this project — main.css sets it
       on individual elements only. Without it, `width: 100%` on a button (the
       CTA band, the tier columns) resolves against the CONTENT box, so the 28px
       side padding and the 1px border render 58px past the container: the
       pricing button hung exactly that far past the plan list above it. */
    box-sizing: border-box;
    padding: 14px 28px;
    border: 1px solid transparent;
    border-radius: 4px;
    font-size: 15px;
    font-weight: 600;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

/* Scoped under .fx-site so these beat the `.fx-site a { color: inherit }`
   above — an element+class selector, which a bare .fx-btn--* would lose to, and
   losing it paints white text on the white primary button. */
.fx-site .fx-btn--primary {
    background: #ffffff;
    color: #0a0a0a;
}

.fx-site .fx-btn--primary:hover {
    background: rgba(255, 255, 255, 0.82);
}

.fx-site .fx-btn--ghost {
    background: transparent;
    color: var(--fx-fg);
    border-color: var(--fx-rule-strong);
}

.fx-site .fx-btn--ghost:hover {
    border-color: #ffffff;
    background: rgba(255, 255, 255, 0.06);
}

/* ─── Facts strip ──────────────────────────────────────────────────────────
   Sits under the opening statement. Two columns of hairline-separated lines
   rather than pills: the entries are phrases, not tags, and a row of rounded
   chips would be the one soft shape on the page. */

/* The statement's supporting paragraphs, folded up from what used to be a
   separate first row that repeated this section's own headline. */
.fx-statement-body {
    margin-top: 22px;
    max-width: 62ch;
}

.fx-facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 56px;
    list-style: none;
    margin: 48px 0 0;
    padding: 0;
    max-width: 840px;
}

.fx-facts li {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 13px 0;
    font-size: 14px;
    color: var(--fx-muted);
    border-top: 1px solid var(--fx-rule);
}

.fx-facts li::before {
    content: "";
    flex: none;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--fx-accent);
    transform: translateY(-2px);
}

@media (max-width: 760px) {
    .fx-facts {
        grid-template-columns: 1fr;
        column-gap: 0;
        margin-top: 36px;
    }
}

/* ─── CTA band ─────────────────────────────────────────────────────────────
   The page's only handoff, so it gets the one tinted ground on the page and a
   price summary — enough for a reader who has scrolled this far to decide
   without a second page load. */

.fx-cta-band {
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.022), rgba(255, 255, 255, 0));
}

.fx-cta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 56px;
}

.fx-cta-text {
    max-width: 44ch;
}

.fx-cta-text .fx-h {
    margin-bottom: 14px;
}

.fx-cta-side {
    flex: 0 1 320px;
}

.fx-cta-tiers {
    list-style: none;
    margin: 0 0 28px;
    padding: 0;
}

.fx-cta-tiers li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--fx-rule);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fx-fg);
}

.fx-cta-price {
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--fx-label);
}

.fx-cta-side .fx-btn {
    display: block;
    width: 100%;
}

/* A second, quieter destination under the first — the home page sends readers
   to two sectors rather than one. Spaced, not stacked flush: two full-width
   buttons touching read as a segmented control, which would imply they are
   alternatives to the same action rather than different places. */
.fx-cta-second {
    margin-top: 12px;
}

/* ─── Sector buttons ───────────────────────────────────────────────────────
   The home page's handoff: Industry and Space, as a pair.

   A grid, and the columns are CAPPED rather than fluid. The labels are one word
   each — Industry / Space, Průmysl / Vesmír, Priemysel / Vesmír — so `1fr`
   columns would stretch two short words across the full 660px measure and the
   pair would read as a segmented control rather than as two destinations.

   NEITHER IS PRIMARY. The two sectors are peers; a filled button beside a ghost
   one says one of them is where to start, which on a holding group's home page
   is not true of either. */
.fx-cta-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 200px));
    gap: 12px;
    margin-top: 36px;
}

@media (max-width: 520px) {
    .fx-cta-actions {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 860px) {
    .fx-cta-side {
        flex: 1 1 100%;
    }
}

/* ─── Nav ──────────────────────────────────────────────────────────────────
   main.css styles .nav globally for the whole site. Everything here is scoped
   to .fx-nav, which only the experiment's own nav partial carries — the live
   tier tabs keep the gradient bar untouched.

   The MARKUP is deliberately identical to the live nav. core.js binds
   .hamburger, .mobile-nav .nav-links, .overlay and .api-fixed with no null
   check, so dropping any one of them throws and takes the rest of the page's
   JS down with it. Only the paint changes. */

.fx-nav {
    box-sizing: border-box;
    /* main.css sets `position: fixed` and no `top`, so the bar falls back to its
       STATIC position — which is inside body's content box, and therefore moves
       whenever body's content box does. The home masthead below made that
       visible: a top margin on the page's first in-flow element collapses out
       to body and pushes the content box down, taking the "fixed" bar with it
       and leaving a band of page above it. Pinning it ends that whole class of
       bug. */
    top: 0;
    padding: 0 24px;
    /* Transparent by default so the product page's hero runs under it; .is-solid
       is added on scroll. The pricing page has no hero and gets .is-solid on the
       first frame, so it never flashes transparent. */
    background: transparent;
    background-image: none;
    border-bottom: 1px solid transparent;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}

.fx-nav.is-solid {
    background: var(--fx-bg);
    border-bottom-color: var(--fx-rule);
}

/* Legibility scrim for the transparent state. The hero is a video, so any frame
   of it can put a bright surface directly behind the wordmark — this keeps the
   bar readable over all of them without giving it a visible edge. Fades out as
   the solid ground arrives, so the two never stack.

   .nav carries z-index 1000 and so opens a stacking context: z-index -1 puts
   this behind the bar's own content but still above the page. */
.fx-nav::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: calc(var(--fx-nav-h) + 48px);
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0));
    transition: opacity 0.2s ease;
}

.fx-nav.is-solid::before {
    opacity: 0;
}

.fx-nav .base-nav {
    height: var(--fx-nav-h);
    align-items: center;
    max-width: var(--fx-max);
    margin: 0 auto;
    width: 100%;
}

/* Wordmark. main.css sets 1.8rem, which next to 14px links reads as a banner
   rather than a mark. */
.fx-nav .nav-left a {
    font-size: 1.25rem;
    color: var(--fx-fg);
    padding: 0;
    margin: 0;
}

.fx-nav .nav-left a:hover {
    color: var(--fx-muted);
}

.fx-nav .nav-divider {
    background: var(--fx-rule);
    height: 16px;
    margin: 0 14px;
}

/* ─── Lang switcher ────────────────────────────────────────────────────────
   main.css sizes the trigger at 16px/bold and nudges the whole switcher down
   2px to sit against a 1.8rem wordmark. Next to 14px links and a 1.25rem mark
   that made "EN" the heaviest thing in the bar, and the nudge threw it off the
   baseline it was meant to hit. Both are undone here. */

.fx-nav .nav-left .lang-switcher {
    transform: none;
}

.fx-nav .lang-trigger {
    padding: 8px 10px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--fx-muted);
    border-radius: 6px;
    border-color: transparent;
}

/* main.css inverts the trigger to a white fill on hover, which in this bar
   reads as a button press rather than a menu opening. */
.fx-nav .lang-trigger:hover,
.fx-nav .lang-switcher.open .lang-trigger,
.fx-nav .lang-switcher:hover .lang-trigger {
    color: var(--fx-fg);
    background: rgba(255, 255, 255, 0.06);
    border-color: var(--fx-rule);
}

.fx-nav .lang-caret {
    font-size: 10px;
}

/* The dropdown, in the same hairline language as the pages. */
.fx-nav .lang-menu {
    min-width: 178px;
    padding: 6px;
    border-radius: 8px;
    border-color: var(--fx-rule);
    background: var(--fx-bg-raised);
    background-image: none;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6);
}

.fx-nav .lang-menu .lang-option {
    font-size: 13px;
    border-radius: 5px;
    color: var(--fx-muted);
}

.fx-nav .lang-menu .lang-option:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--fx-fg);
}

.fx-nav .lang-menu .lang-option.active {
    background: rgba(255, 255, 255, 0.05);
    color: var(--fx-fg);
}

.fx-nav .nav-right {
    align-items: center;
    gap: 4px;
    padding-right: 0;
}

.fx-nav .nav-right a {
    font-size: 14px;
    font-weight: 400;
    color: var(--fx-muted);
    padding: 8px 12px;
    margin: 0;
    border-bottom: none;
    transition: color 0.2s ease;
}

.fx-nav .nav-right a:hover {
    color: var(--fx-fg);
}

/* The page you are on. No underline — at this weight a colour shift is enough,
   and it keeps the bar free of a second line competing with the hairline. */
.fx-nav .nav-right a.fx-nav-current {
    color: var(--fx-fg);
}

/* iOΞN. main.css fills it and inverts on hover; here it matches .fx-btn--ghost
   so the nav carries one button language with the pages. */
.fx-nav .api {
    padding: 8px 16px;
    font-size: 13px;
    background: transparent;
    color: var(--fx-fg);
    border: 1px solid var(--fx-rule-strong);
    border-radius: 999px;
    transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.fx-nav .api:hover {
    background: rgba(255, 255, 255, 0.06);
    border-color: #ffffff;
    color: var(--fx-fg);
}

/* Mobile bar + drawer. The drawer's width, transform and .active mechanics are
   core.js's and stay exactly as main.css has them. */
.fx-nav .mobile-nav {
    height: var(--fx-nav-h);
    align-items: center;
}

.fx-nav .mobile-nav .h-text {
    font-size: 1.25rem;
    color: var(--fx-fg);
}

.fx-nav .mobile-nav .nav-links {
    background: var(--fx-bg);
    background-image: none;
    border-right: 1px solid var(--fx-rule);
    padding: 96px 24px 24px;
}

.fx-nav .mobile-nav .nav-links a {
    font-size: 1.05rem;
    color: var(--fx-muted);
    margin-bottom: 0;
    padding: 14px 0;
    border-bottom: 1px solid var(--fx-rule);
}

.fx-nav .mobile-nav .nav-links a:last-child {
    border-bottom: none;
}

.fx-nav .hamburger {
    margin-right: 0;
}

.fx-nav .hamburger span {
    background: var(--fx-fg);
}

@media (prefers-reduced-motion: reduce) {
    .fx-nav,
    .fx-nav .nav-right a,
    .fx-nav .api {
        transition: none;
    }
}


/* ─── Footer ───────────────────────────────────────────────────────────────
   Its own class namespace rather than the shared .footer-container / .legal /
   .social: those carry `color: … !important` in main.css, so reusing the names
   would mean fighting !important on every rule. Same reason the pricing here is
   .fx-tier-* and not .pricing-*.

   Only the experiment's pages give <footer> the .fx-foot class, so the live
   tabs' five-column footer is untouched. */

footer.fx-foot {
    background: var(--fx-bg);
    background-image: none;
    border-top: 1px solid var(--fx-rule);
    padding: 72px 24px 28px;
    color: var(--fx-muted);
}

.fx-foot-inner {
    max-width: var(--fx-max);
    margin: 0 auto;
}

/* Identity left, links right. Three equal columns across the full measure —
   the first attempt — opened gaps wide enough that the columns stopped reading
   as a set, and left the entity block with nowhere to sit. */
.fx-foot-top {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.6fr);
    gap: 64px;
    padding-bottom: 56px;
}

.fx-foot-mark {
    font-size: 22px;
    letter-spacing: -0.01em;
    color: var(--fx-fg);
    margin-bottom: 18px;
}

.fx-foot-cols {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 32px;
}

/* The apex has four groups to FLoCK's three. It needs no breakpoint of its own:
   by 1000px .fx-foot-top has already given the columns the full measure, and the
   860px rule below collapses every variant to two. Declared before that rule so
   the media query — equal specificity, later in the file — still wins. */
.fx-foot-cols--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 28px;
}

.fx-foot-col h2 {
    margin: 0 0 20px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fx-label);
}

.fx-foot-col ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.fx-foot-col li {
    margin: 0 0 10px;
}

.fx-foot-col a {
    font-size: 14px;
    color: var(--fx-muted);
    text-decoration: none;
    transition: color 0.2s ease;
}

.fx-foot-col a:hover {
    color: var(--fx-fg);
}

/* Registered-entity block. Quieter than the link columns — it is reference
   detail, not navigation. */
.fx-site .fx-foot-entity,
.fx-foot-entity {
    margin: 0;
    font-size: 13px;
    line-height: 1.7;
    color: var(--fx-label);
}

.fx-foot-entity strong {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--fx-muted);
}

.fx-foot-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding-top: 24px;
    border-top: 1px solid var(--fx-rule);
}

.fx-foot-copy {
    margin: 0;
    font-size: 13px;
    color: var(--fx-label);
}

.fx-foot-social {
    display: flex;
    align-items: center;
    gap: 14px;
}

/* Reuses the live footer's icon classes — they are only `content: url(…)` plus
   a 40px box and carry no !important, so this two-class selector wins. No new
   image assets. */
.fx-foot-social .social-icon-x,
.fx-foot-social .social-icon-in,
.fx-foot-social .social-icon-yt {
    width: 22px;
    height: 22px;
    opacity: 0.7;
    transition: opacity 0.2s ease;
}

.fx-foot-social a:hover {
    opacity: 1;
}

@media (max-width: 1000px) {
    .fx-foot-top {
        grid-template-columns: 1fr;
        gap: 40px;
    }
}

@media (max-width: 860px) {
    footer.fx-foot {
        padding: 48px 24px 24px;
    }

    .fx-foot-top {
        padding-bottom: 40px;
    }

    /* Two columns rather than one: at three links a column, a single stack
       turns the footer into a long scroll of its own. */
    .fx-foot-cols {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 32px 24px;
    }

    .fx-foot-bar {
        flex-direction: column;
        align-items: flex-start;
        gap: 18px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fx-foot-col a,
    .fx-foot-social .social-icon-x,
    .fx-foot-social .social-icon-in,
    .fx-foot-social .social-icon-yt {
        transition: none;
    }
}

/* ─── Reveal on scroll ─────────────────────────────────────────────────────
   .fx-reveal is applied by fx-site.js, never by the markup, so a page whose
   JS did not run shows everything rather than nothing. --fx-delay is set per
   tier column to stagger the pricing row. */

.fx-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition:
        opacity 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) var(--fx-delay, 0ms),
        transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) var(--fx-delay, 0ms);
}

.fx-reveal.is-in {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .fx-reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ─── Capability rows: the label holds position ────────────────────────────
   The label names the block; keeping it in view while its copy scrolls is what
   makes a long page of prose navigable without a sidebar. Desktop only — in the
   stacked layout it sits directly above its own text already. */

@media (min-width: 1001px) {
    .fx-row .fx-label {
        position: sticky;
        top: calc(var(--fx-nav-h) + 28px);
    }
}

/* ─── Footer link hover ────────────────────────────────────────────────────
   No underline. A wiping rule under every footer link turned the column into a
   row of moving parts on the way past, and an underline is the one decoration
   this design does not otherwise use.

   Instead the link steps aside: a short dash slides into the space on its left
   while the text moves over to make room. One motion, in the direction you
   read, and the column stays still until you actually point at something. */

.fx-foot-col a {
    display: inline-block;
    position: relative;
    padding-left: 0;
    transition: padding-left 0.22s cubic-bezier(0.22, 0.61, 0.36, 1), color 0.2s ease;
}

.fx-foot-col a::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 8px;
    height: 1px;
    margin-top: -0.5px;
    background: var(--fx-accent);
    opacity: 0;
    transform: translateX(-6px);
    transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.fx-foot-col a:hover {
    padding-left: 16px;
}

.fx-foot-col a:hover::before {
    opacity: 1;
    transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
    .fx-foot-col a,
    .fx-foot-col a::before,
    .fx-site .fx-tier-tagline,
    .fx-tier-features li {
        transition: none;
    }

    /* No reflow on hover either — the dash alone carries it. */
    .fx-foot-col a:hover {
        padding-left: 16px;
    }
}

/* ─── Focus ────────────────────────────────────────────────────────────────
   :focus-visible only, so a mouse click never paints a ring — but every
   keyboard path through the nav, the tier CTAs, the matrix and the footer has
   one. The pages had none before this pass. */

.fx-site a:focus-visible,
.fx-site button:focus-visible,
.fx-site input:focus-visible,
.fx-site select:focus-visible,
.fx-nav a:focus-visible,
.fx-nav button:focus-visible,
.fx-foot a:focus-visible {
    outline: 2px solid var(--fx-accent);
    outline-offset: 3px;
    border-radius: 2px;
}

/* ─── Grain ────────────────────────────────────────────────────────────────
   A flat near-black field of this size bands on 8-bit displays. A fixed, very
   low-opacity noise tile breaks the gradients up. Inert to pointers and sits
   under the nav's z-index, so it changes nothing but the surface.

   The most obviously optional thing here — delete this block and the page is
   unchanged in structure. */

.fx-site::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    opacity: 0.022;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* The page's own bands have to sit above the grain.

   Enumerated rather than written as `.fx-site > *`, which is what it was while
   this lived on the FLoCK subdomain and every direct child of the wrapper was a
   band. On the apex it is not: a page's children also include the inquiry
   overlay and its floating trigger, the cookie banner's siblings and the
   careers overlay, all of which are `position: fixed` — and `position:
   relative` at equal specificity, from a sheet that loads after main.css, would
   quietly turn every one of them into an element that scrolls away with the
   page. Listing the band classes leaves anything positioned alone. */
.fx-site > .fx-hero,
.fx-site > .fx-section,
.fx-site > .research-stage {
    position: relative;
    z-index: 2;
}

/* ═══ Brief components ═════════════════════════════════════════════════════
   Everything below was added when the pages were rebuilt from the product &
   positioning brief. Same rules as the rest of the sheet: no cards, no shadows,
   separation by hairline and space. */

/* ─── Page head (inner pages) ──────────────────────────────────────────────
   The overview keeps the video hero; Access and Pricing open on
   type, so they need their own clearance under the fixed nav. */

.fx-page-head {
    padding-top: calc(var(--fx-nav-h) + 96px);
    /* --fx-pad, like every other band, rather than the 8px this used to carry.
       The rule below the header is a section divider, and at 8px it sat against
       the lede's last line while holding 96px of air on its far side — so it
       read as an underline on the header rather than the edge between two
       sections. The token also means it tightens to 56px on a phone with
       everything else, instead of needing its own breakpoint. */
    padding-bottom: var(--fx-pad);
}

/* "Last updated …" under a legal page's title. It was set in <i> at 1.3rem,
   which made the date line heavier than the policy it dated. */
.fx-site .fx-page-date {
    margin-top: 16px;
}

.fx-page-kicker {
    margin-top: 18px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--fx-accent);
}

/* ─── Facts strip, wide variant ────────────────────────────────────────────
   Four short delivery facts rather than six phrases — they fit one row. */

.fx-facts--wide {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: 32px;
}

@media (max-width: 1000px) {
    .fx-facts--wide {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ─── The two products ─────────────────────────────────────────────────────
   Side by side, divided by one rule. The relationship between them is the
   argument, so they have to be readable against each other. */

.fx-split {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 56px;
    margin-top: 56px;
    padding-top: 56px;
    border-top: 1px solid var(--fx-rule);
}

.fx-split-col {
    display: flex;
    flex-direction: column;
}

.fx-split-col + .fx-split-col {
    padding-left: 56px;
    border-left: 1px solid var(--fx-rule);
}

.fx-split-kicker {
    display: block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--fx-accent);
}

.fx-split-title {
    margin: 16px 0 14px;
    font-size: clamp(24px, 2.4vw, 32px);
    line-height: 1.1;
}

.fx-site .fx-split-lede {
    font-size: 16px;
    line-height: 1.6;
}

.fx-split-points {
    flex: 1 1 auto;
    list-style: none;
    margin: 28px 0 32px;
    padding: 0;
}

.fx-split-points li {
    padding: 11px 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--fx-muted);
    border-top: 1px solid var(--fx-rule);
}

.fx-split-col .fx-btn {
    align-self: flex-start;
}

@media (max-width: 900px) {
    .fx-split {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .fx-split-col + .fx-split-col {
        margin-top: 48px;
        padding-top: 48px;
        padding-left: 0;
        border-left: none;
        border-top: 1px solid var(--fx-rule);
    }
}

/* ─── Pillars ──────────────────────────────────────────────────────────────
   Claim on top, proof underneath in a quieter register. The proof line is the
   whole point of the section, so it is set apart rather than run on. */

.fx-pillars {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 56px;
    margin-top: 56px;
}

.fx-pillar {
    padding: 32px 0;
    border-top: 1px solid var(--fx-rule);
}

.fx-pillar-title {
    margin: 0 0 12px;
    font-size: 19px;
    line-height: 1.3;
}

.fx-site .fx-pillar-body {
    font-size: 15px;
    line-height: 1.6;
}

.fx-site .fx-pillar-proof {
    margin-top: 16px;
    padding-left: 14px;
    border-left: 1px solid var(--fx-accent);
    font-size: 13px;
    line-height: 1.55;
    color: var(--fx-label);
}

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

/* ─── Plans (overview) ─────────────────────────────────────────────────────
   Named, scoped, described — and deliberately priceless. The numbers are the
   pricing page's job. */

.fx-plans {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 32px;
    margin-top: 48px;
}

.fx-plan {
    padding-top: 22px;
    border-top: 1px solid var(--fx-rule-strong);
}

.fx-plan-name {
    display: block;
    font-size: 15px;
    font-weight: 600;
    color: var(--fx-fg);
}

.fx-plan-scope {
    display: block;
    margin: 6px 0 14px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--fx-accent);
}

.fx-site .fx-plan p {
    font-size: 14px;
    line-height: 1.6;
}

@media (max-width: 860px) {
    .fx-plans {
        grid-template-columns: 1fr;
        gap: 28px;
    }
}

/* ─── Callout ──────────────────────────────────────────────────────────────
   For the rules the brief says to state out loud — the commission guarantee,
   the remembered refusal.

   THIRD ATTEMPT, and the two failures are worth keeping because they bracket
   the answer.

   It began as a tinted panel with a 2px accent bar down its left edge: a
   docs-site admonition, the only filled box on a page otherwise built from
   hairlines, and its padding pushed the text 30px right of the paragraphs above
   it — a second left edge running alongside the one every other element shares.

   The fix for that was to strip it to a hairline and a tracked label. It fitted
   perfectly and it disappeared: indistinguishable from any other labelled
   paragraph, which costs a callout the only thing it is for.

   So the shape was wrong both times, and the weight was only wrong once. What
   this needed was the page's OWN emphasis grammar, which already existed and
   which neither attempt used — .fx-tier--featured: a 2px accent rule along the
   TOP edge and a wash beneath it that fades out within the first third. It is
   the established way this design says "this one matters", so the callout now
   says it the same way, and the two read as one system.

   A top rule also solves what the left bar could not. The original's problem
   was never the fill — it was a vertical edge competing with the prose edge
   right beside it. A horizontal rule has no such edge, so the block can carry
   real padding and still read as starting where the rule starts. */

.fx-callout {
    margin: 36px 0 0;
    /* On FLoCK every callout sits inside a row's copy column, which already
       holds the measure. The apex puts one straight into a .fx-wrap — About
       closes on it — where it would otherwise run the full 1180px and set the
       longest line on the page. */
    max-width: 74ch;
    padding: 26px 28px 28px;
    box-shadow: inset 0 2px 0 0 var(--fx-accent);
    background-image: linear-gradient(to bottom,
        rgba(77, 124, 255, 0.07) 0%,
        rgba(77, 124, 255, 0) 38%);
}

/* Scoped: the title is an <h3>, and `.fx-site h3 { color: var(--fx-fg) }` at
   the top of this sheet is an element+class selector that a bare class loses
   to — which is why the accent did not land when this was a tracked label.

   Set as a small heading rather than a label: the accent is already spent on
   the rule above, and a second accent element in a block this size competes
   with it. Sentence case, because it is a sentence. */
.fx-site .fx-callout-title {
    margin: 0 0 10px;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.35;
    color: var(--fx-fg);
}

.fx-site .fx-callout p {
    font-size: 15px;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.78);
}

.fx-site .fx-callout-note {
    margin-top: 12px;
    font-size: 13px;
    color: var(--fx-label);
}

.fx-callouts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 28px;
    margin-top: 64px;
}

.fx-callouts .fx-callout {
    margin-top: 0;
}

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

/* A button closing a capability row, rather than a section. Sits under the
   copy column, not under the label. */
.fx-row-cta {
    margin-top: 28px;
}

/* ─── Journeys ─────────────────────────────────────────────────────────────
   Numbered, because they are sequences. The counter sits outside the text
   column so the steps align on one left edge. */

.fx-journeys {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 64px;
}

.fx-journeys--single {
    grid-template-columns: minmax(0, 760px);
}

.fx-steps {
    counter-reset: fx-step;
    list-style: none;
    margin: 32px 0 0;
    padding: 0;
}

.fx-steps li {
    position: relative;
    counter-increment: fx-step;
    padding: 16px 0 16px 44px;
    font-size: 15px;
    line-height: 1.6;
    color: var(--fx-muted);
    border-top: 1px solid var(--fx-rule);
}

.fx-steps li::before {
    content: counter(fx-step);
    position: absolute;
    left: 0;
    top: 16px;
    width: 26px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--fx-accent);
}

@media (max-width: 900px) {
    .fx-journeys {
        grid-template-columns: 1fr;
        gap: 48px;
    }
}

/* ─── Glossary ─────────────────────────────────────────────────────────────
   The eight words the industry catalog is built from. Four across, because the
   terms are one word each and the definitions are one line. */

.fx-glossary {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0 32px;
    margin: 48px 0 0;
}

.fx-glossary-item {
    padding: 22px 0;
    border-top: 1px solid var(--fx-rule);
}

.fx-glossary dt {
    font-size: 15px;
    font-weight: 600;
    color: var(--fx-fg);
}

.fx-glossary dd {
    margin: 8px 0 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--fx-label);
}

@media (max-width: 900px) {
    .fx-glossary {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ─── Generic table ────────────────────────────────────────────────────────
   The roles, the warning reasons, the delivery concerns. Same hairline language
   as the pricing matrix, without its tier-column machinery. */

.fx-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
    margin-top: 40px;
}

.fx-table {
    width: 100%;
    min-width: 640px;
    border-collapse: collapse;
    font-size: 14px;
    text-align: left;
}

.fx-table th,
.fx-table td {
    padding: 18px 20px 18px 0;
    vertical-align: top;
    border-bottom: 1px solid var(--fx-rule);
}

.fx-table thead th {
    padding-top: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fx-label);
    border-bottom-color: var(--fx-rule-strong);
}

.fx-table tbody th {
    font-weight: 400;
    color: var(--fx-fg);
    white-space: nowrap;
}

.fx-table tbody td {
    color: var(--fx-muted);
    line-height: 1.6;
}

.fx-table .fx-table-narrow {
    white-space: nowrap;
}

/* Row hover. A grey wash sliding under the row is the admin-panel idiom, and on
   a page made of hairlines it was the loudest thing in the design — worse, it
   stuck after a tap on touch, where :hover has no way to clear.

   So: no fill. The row's own rule brightens into a ruler under the line you are
   reading, and its text lifts out of muted. The same two moves the tier columns
   and the footer links already use, and both revert cleanly. */
@media (hover: hover) {
    /* On the cells, not the row: both properties are set on th/td, and a
       transition declared on the <tr> would never apply to them. */
    .fx-table tbody th,
    .fx-table tbody td {
        transition: color 0.15s ease, border-color 0.15s ease;
    }

    .fx-table tbody tr:hover th,
    .fx-table tbody tr:hover td {
        border-bottom-color: var(--fx-rule-strong);
        color: var(--fx-fg);
    }
}

/* Identifiers that really are identifiers — role names, workspace paths,
   warning reasons — set as code so they are not mistaken for prose. */
.fx-site code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.92em;
    color: var(--fx-fg);
}

.fx-site .fx-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 14px;
    color: var(--fx-label);
    letter-spacing: -0.01em;
}

/* ─── Tags ─────────────────────────────────────────────────────────────────
   The machine-readable surfaces. Filenames, so they are set as such. */

.fx-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 22px 0;
    padding: 0;
}

.fx-tags li {
    padding: 6px 12px;
    border: 1px solid var(--fx-rule);
    border-radius: 4px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
    color: var(--fx-muted);
}

/* ─── Partner credits ──────────────────────────────────────────────────────
   Three ways the price moves, under the tier columns on the pricing page.

   Built from the same parts as .fx-axes rather than as cards: a credit is a
   term, not a product, and giving it a bordered panel would make it compete
   with the four columns directly above it for the same kind of attention. The
   accent is spent on the figure, which is the part a reader is looking for. */

.fx-credits {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 32px;
    margin-top: 48px;
}

.fx-credit {
    padding-top: 22px;
    border-top: 1px solid var(--fx-rule-strong);
}

.fx-credit-name {
    display: block;
    font-size: 15px;
    font-weight: 600;
    color: var(--fx-fg);
}

.fx-site .fx-credit-body {
    margin-top: 12px;
    font-size: 14px;
    line-height: 1.6;
    color: var(--fx-muted);
}

.fx-site .fx-credit-value {
    margin-top: 16px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--fx-accent);
}

.fx-site .fx-credits-note {
    margin-top: 36px;
}

@media (max-width: 900px) {
    .fx-credits {
        grid-template-columns: 1fr;
        gap: 28px;
    }
}

/* ─── Permission axes ──────────────────────────────────────────────────────
   Three columns, because the brief's point is that the three questions are
   independent — stacking them would imply an order they do not have. */

.fx-axes {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 32px;
    margin-top: 48px;
}

.fx-axis {
    padding-top: 22px;
    border-top: 1px solid var(--fx-rule-strong);
}

.fx-axis-name {
    display: block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fx-accent);
}

.fx-site .fx-axis-q {
    margin-top: 12px;
    font-size: 16px;
    color: var(--fx-fg);
    line-height: 1.4;
}

.fx-site .fx-axis-v {
    margin-top: 12px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--fx-label);
}

@media (max-width: 900px) {
    .fx-axes {
        grid-template-columns: 1fr;
        gap: 28px;
    }
}

/* ─── Responsive ───────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    .fx-row {
        grid-template-columns: 1fr;
        gap: 16px;
    }

    .fx-row .fx-label {
        margin: 0 0 4px;
    }
}

@media (max-width: 860px) {
    .fx-site {
        --fx-pad: 56px;
    }

    .fx-row + .fx-row {
        margin-top: 48px;
        padding-top: 48px;
    }

    /* Stretch, not flex-start: turning the main axis vertical makes width the
       CROSS axis, and flex-start there shrink-wraps both children to their
       max-content — which leaves the button looking oversized next to a
       collapsed text block. The text keeps its own max-width, so stretching
       costs it nothing. */
    .fx-cta {
        flex-direction: column;
        align-items: stretch;
        gap: 40px;
    }
}

/* The stage's caption bar. 40px of chrome above a panel that is itself getting
   shorter reads as a title bar rather than a label at this width. */
@media (max-width: 768px) {
    .fx-stage-bar {
        height: 36px;
        padding: 0 12px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fx-btn,
    .fx-table tbody th,
    .fx-table tbody td {
        transition: none;
    }
}

/* ─── Phone ────────────────────────────────────────────────────────────────
   Everything above this point stacks correctly on a phone and still reads
   badly, which are different problems. In a 342px column the page is one
   undifferentiated grey slab: display leading calibrated for a 46px heading
   that runs two lines closes up when the same heading runs four at 28px, the
   first-paragraph size step makes the densest paragraph the largest one, and
   body copy at 62% white is dim enough on a phone to cost real legibility.

   This block is the reading pass. It changes no layout — only type, contrast
   and the rhythm between a row's parts. The one structural change is the
   tables, which are stacked rather than panned.

   IT MUST STAY LAST IN THIS FILE. Almost everything it overrides is declared at
   the same specificity as the rule it replaces — `.fx-table`, `.fx-callout`,
   `.fx-h` — so the cascade is doing the work, and a media query adds no weight
   of its own. Put this block where the other responsive blocks live, halfway up
   the sheet, and the component definitions below it silently win instead. */

@media (max-width: 700px) {

    /* Contrast. The token values are tuned against a desktop panel; a phone is
       held at arm's length, often outdoors, and usually with the brightness
       fighting something. Redefined on .fx-site rather than :root so the nav
       and footer, which are legible already, are untouched. */
    .fx-site {
        --fx-muted: rgba(255, 255, 255, 0.72);
        --fx-label: rgba(255, 255, 255, 0.52);
    }

    /* Display leading. The single biggest cause of the crowding. */
    .fx-h {
        font-size: 26px;
        line-height: 1.2;
    }

    .fx-h-lg {
        font-size: 31px;
        line-height: 1.14;
    }

    /* The first paragraph keeps its rank through colour, not size — at this
       width the extra point only makes the heaviest block heavier. */
    .fx-site .fx-row-copy > p:first-of-type {
        font-size: 17px;
        line-height: 1.62;
        color: rgba(255, 255, 255, 0.88);
    }

    .fx-site .fx-lede {
        font-size: 17px;
        line-height: 1.62;
    }

    .fx-body > p + p {
        margin-top: 17px;
    }

    /* Air between a row's three parts: numeral, label, heading. They were
       stacked 8px and 20px apart under a heading now four lines tall. */
    .fx-row {
        gap: 22px;
    }

    .fx-row .fx-label::before {
        margin-bottom: 10px;
    }

    .fx-row .fx-h {
        margin-bottom: 22px;
    }

    .fx-row + .fx-row {
        margin-top: 52px;
        padding-top: 52px;
    }

    /* A path set at 14px wraps mid-arrow in this column. */
    .fx-site .fx-mono {
        font-size: 13px;
        line-height: 1.7;
    }

    /* ── Tables, stacked ───────────────────────────────────────────────────
       A 640px table in a 342px column is 298px of horizontal panning to read
       three columns, one of which you cannot see while reading another. These
       tables are all the same shape — an identifier plus descriptions of it —
       so on a phone each row becomes a block, with the column heading carried
       down as a label from data-label (set in Blade from the very same lang
       keys the <th scope="col"> uses, so the two cannot disagree). */

    .fx-table-scroll {
        overflow-x: visible;
        margin-top: 32px;
    }

    .fx-table,
    .fx-table tbody,
    .fx-table tr,
    .fx-table th,
    .fx-table td {
        display: block;
    }

    .fx-table {
        min-width: 0;
        width: 100%;
    }

    /* The headings move into the rows, so the header row is now duplication. */
    .fx-table thead {
        display: none;
    }

    .fx-table tbody tr {
        padding: 24px 0;
        border-top: 1px solid var(--fx-rule);
    }

    .fx-table tbody tr:first-child {
        border-top: none;
        padding-top: 0;
    }

    .fx-table th,
    .fx-table td {
        padding: 0;
        border-bottom: none;
    }

    /* The row's identifier becomes its heading. nowrap was there to stop a
       narrow column breaking a name; there is no narrow column now, and keeping
       it would push long values off the side. */
    .fx-table tbody th,
    .fx-table .fx-table-narrow {
        white-space: normal;
    }

    .fx-table tbody th[scope="row"] {
        margin-bottom: 14px;
        font-size: 16px;
        color: var(--fx-fg);
    }

    .fx-table tbody td + td {
        margin-top: 16px;
    }

    .fx-table tbody td[data-label]::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 5px;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--fx-label);
    }

    /* ── Callout ───────────────────────────────────────────────────────────
       Side padding down from 28px: in a 342px column that costs the callout
       56px of measure the prose around it keeps, so it wraps two words earlier
       a line and reads as the narrowest thing on the page. */
    .fx-callout {
        margin-top: 30px;
        padding: 22px 18px 24px;
    }

    .fx-site .fx-callout-title {
        font-size: 15px;
    }

    /* ── Canvas stage, full bleed ──────────────────────────────────────────
       The scenes are scaled to fit by viewport/reserveW, so every pixel of
       width is worth the same proportion of legible type. Breaking the stage
       out of the section's 24px gutters returns 48px of a 390px screen — about
       14% more scale — and the panel reads as a deliberate full-width exhibit
       rather than a shrunken desktop one. The side borders and the corner
       radius go with it; there is no longer an edge for them to sit on.

       flock-site-canvas.js does the other half, dropping each scene to two
       columns at this same 700px mark. */
    .fx-section--stage {
        padding-left: 0;
        padding-right: 0;
    }

    /* No border at all once it is full bleed — not just the sides.

       A 1px rule on four sides is a FRAME; the same rule on two sides, running
       the full width of the viewport, is a divider, and the page already has
       those. Measured around the first stage, the band was contributing three
       extra full-width hairlines of exactly the section-divider weight, and its
       bottom one landed 56px above the real divider below it — two parallel
       lines with nothing between them, which is the part that looked wrong.

       So the band is defined by its ground instead: the caption bar sits a
       shade above the page (--fx-bg-raised), the canvas a shade below it
       (#000), and the only rule left is the bar's own bottom edge, which reads
       as part of the component because it has the bar's lighter ground directly
       above it. The section divider below is then the only page-level line in
       the neighbourhood, which is what it should have been all along. */
    .fx-stage {
        border: none;
        border-radius: 0;
    }
}
