/* type3 subdomain (type3.aiquniq.com) — everything this host styles itself.
 *
 * REPLACES TWO SHEETS, type3/main.css and type3/subdomain.css, and most of what
 * they held is simply gone rather than moved:
 *
 *   .structure / .inner      the content bands. fx.css's .fx-section / .fx-wrap
 *                            do this now, with a type scale and a rule between
 *                            sections, which is what those two never had.
 *   .split / .w-30 / .w-40   artwork beside copy at a percentage width, plus a
 *   .w-60 + the 1200px       breakpoint to undo it. The artwork sits in
 *   media query               .fx-stage frames now, which are full measure, so
 *                            there is no width to pick and nothing to stack.
 *   .divider + 4 variants    decorative hairlines between bands. Every section
 *                            and every row carries its own rule now, so these
 *                            were a second line saying the same thing. The
 *                            figure was nice work; git history has it if a page
 *                            ever wants it back.
 *   .type3-contact-fab       the floating "Contact us" button. Deleted with its
 *                            Blade partial — it existed to scroll to a form in
 *                            the open tab panel, and there are no panels. The
 *                            two pages with a form now reach it by anchor.
 *
 * What is left is in seven parts: the reCAPTCHA badge, the hero parallax, the
 * landing's manifesto band, RARM's pinned narrative and featured asset, the
 * media stages and asset status pills, and the offer form.
 *
 * LOAD ORDER. This sheet must come last — after main.css, banner.css,
 * wireframes/landing.css and fx.css. The form rules below restate landing.css's
 * #offerForm declarations against class hooks, and the .fx-* overrides have the
 * same specificity as fx.css's own, so load order is the only thing that makes
 * them win. See pages/type3/partials/head.blade.php.
 *
 * SCOPE. Everything that could collide with a shared sheet is .type3-site
 * scoped — the class pages/type3/shell.blade.php puts on the content wrapper
 * alongside .fx-site. landing.css owns these same form class names for the apex
 * forms and must not change.
 */


/* ── reCAPTCHA badge ─────────────────────────────────────────────────────────
 *
 * Google pins its badge to the viewport corner for the life of the page, and it
 * is not inside .type3-site, so these two are deliberately unscoped. Hidden by
 * default; addons/type3.js puts .captcha-visible on <body> while an offer form
 * is on screen, which is the only time the badge's notice is required. */
.grecaptcha-badge                      { visibility: hidden !important;  z-index: 9999 !important; }
body.captcha-visible .grecaptcha-badge { visibility: visible !important; z-index: 9999 !important; }


/* ── Hero parallax ───────────────────────────────────────────────────────────
 *
 * The hero clip drifts as the page scrolls. REQUIRED, not decoration: fx.css
 * sizes every .fx-site hero image and clip taller than its frame by
 * --fx-hero-travel in BOTH directions and pulls it up by half of that, so the
 * media still covers the banner at every point of the drift. With nothing
 * animating it, the clip simply sits 12vh off-centre in a 100vh frame for the
 * life of the page — which is what this subdomain shipped the moment it started
 * loading fx.css and is what this block fixes.
 *
 * ON THE APEX, AND ON RARM, the movement comes from addons/motion.js, which
 * parallaxes .banner images. It cannot serve the landing: motion.js bails on any
 * .banner containing a <video> (see pickImg), because driving a clip from a
 * scroll event leaves it a frame behind the page, and that lag reads as judder
 * the moment a stationary edge appears below the banner. A scroll-driven CSS
 * animation runs on the compositor and cannot fall behind.
 *
 * FLoCK solves this across two sheets — flock/subdomain.css names the timeline
 * and declares the animation, flock/site.css re-points animation-name at local
 * keyframes to retune the amplitude. type3 had NEITHER half: its own
 * subdomain.css never carried a parallax, because until this subdomain moved
 * onto fx.css its hero was banner.css's plain 100vh with nothing to compensate
 * for. So the whole thing is declared here, in one block, already at the
 * amplitude fx.css sizes for.
 *
 * BOTH CLIPS, which is where this differs from FLoCK's. That hero's narrow
 * variant is a still image; config/type3.php gives the landing a mobile clip
 * too, and banner.css shows exactly one of the two per viewport — so animating
 * both is one rule covering whichever is on screen, rather than a breakpoint.
 *
 * The @supports guard is load-bearing, not decoration: a browser that does not
 * know animation-timeline still honours `animation: … both`, and with no
 * duration that would snap the clip to the `to` keyframe and park it 12vh down
 * permanently. Inside the guard, unsupporting browsers get no parallax at all,
 * which is the right fallback — the clip rests where fx.css put it and
 * .banner's overflow:hidden makes that read as framing rather than as a gap. */
@supports (animation-timeline: view()) {
    /* The timeline subject is .banner, and .fx-hero above it deliberately
     * declares no overflow: a timeline resolves against its subject's nearest
     * scrollport, so a clipping wrapper there would become one and freeze the
     * animation at its first keyframe. See the note in fx.css. */
    .type3-site .banner {
        view-timeline-name: --type3-hero;
    }

    .type3-site .banner-video,
    .type3-site .banner-video-mobile {
        animation: type3-hero-parallax linear both;
        /* Named rather than a bare view(), so the timeline is unambiguously the
         * banner's own box and never the clip's own transformed one. */
        animation-timeline: --type3-hero;
        animation-range: cover 0% cover 100%;
    }

    /* Reads --fx-hero-travel instead of hard-coding the amplitude, so the
     * keyframes cannot drift from the sizing in fx.css they exist to stay
     * inside. Custom properties in keyframes resolve against the animating
     * element, which inherits the value from .fx-site. */
    @keyframes type3-hero-parallax {
        from { transform: translate3d(0, calc(var(--fx-hero-travel) * -1), 0); }
        to   { transform: translate3d(0, var(--fx-hero-travel), 0); }
    }

    /* motion.js clears its transforms under reduced motion; match that here.
     * type3-loader.js already declines to attach the sources in that case, so
     * what stays still is the poster. */
    @media (prefers-reduced-motion: reduce) {
        .type3-site .banner-video,
        .type3-site .banner-video-mobile {
            animation: none;
        }
    }
}


/* ── Manifesto band ──────────────────────────────────────────────────────────
 *
 * The landing's "what and why" — the one block on that page that is not
 * information, and the only visual beat between the banner and the footer.
 *
 * It is here rather than in fx.css because it is not general yet: the shared
 * system has .fx-hero for an opening and .fx-cta-band for a closing, and
 * nothing for a full-bleed statement in the MIDDLE of a page. If the apex ever
 * wants one, this is the rule it wants and it should move rather than be
 * copied.
 *
 * Three layers, bottom to top: the plate, the scrim, the copy. The section
 * carries `isolation: isolate` so the two negative-z layers resolve inside the
 * band's own stacking context — without it they would drop behind the page
 * ground and the band would render as plain type on black. */
.type3-site .fx-manifesto {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    /* Not --fx-pad. A band this size needs the air to read as a held breath
     * rather than as another section; the tokens are tuned for type on a
     * ground, which is the opposite case. */
    padding-top: 150px;
    padding-bottom: 150px;
}

.type3-site .fx-manifesto-art {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* The galactic core sits low and right in the plate. Centring the crop
     * there keeps the one bright thing in the picture on screen at every width,
     * instead of cropping to empty sky on a narrow viewport. */
    object-position: 58% 62%;
}

.type3-site .fx-manifesto-scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        /* ACROSS. The copy is ranged left, where this plate is darkest anyway,
         * so the horizontal pass only has to guarantee it — and it clears by
         * ~62% so the core on the right is left alone. Scrim the whole frame
         * evenly and the picture stops being worth including. */
        linear-gradient(to right,
            rgba(10, 10, 10, 0.90) 0%,
            rgba(10, 10, 10, 0.62) 30%,
            rgba(10, 10, 10, 0.12) 62%,
            rgba(10, 10, 10, 0.12) 100%),
        /* DOWN. Dissolves the band into the page ground at both edges, so it
         * reads as the page opening onto the sky rather than as a photograph
         * pasted into a rectangle. Same move .fx-hero-scrim makes at the
         * bottom of the hero. */
        linear-gradient(to bottom,
            var(--fx-bg) 0%,
            rgba(10, 10, 10, 0) 20%,
            rgba(10, 10, 10, 0) 80%,
            var(--fx-bg) 100%);
}

.type3-site .fx-manifesto .fx-label {
    margin-bottom: 40px;
    color: rgba(255, 255, 255, 0.58);
}

/* A STEP ABOVE THE PAGE'S LEDE, and no more.
 *
 * This started at 28px in near-solid white, which was an over-correction: three
 * earlier versions had set the same copy at 15px inside a grid where it read as
 * a footnote, so the fix reached for display size. But the band already has the
 * sky carrying it — the presence is the full-bleed plate, not the type — and at
 * 28px/#f5f5f5 over a photograph the statements shouted against everything
 * around them and broke the page's register.
 *
 * 22px sits just above .fx-lede's 20px, which is the largest body text on the
 * page (the mission statement above this one). Close enough to belong to the
 * same document, far enough to still be the thing being declared.
 *
 * 0.78 white rather than --fx-fg (0.96) or --fx-muted (0.62): the first is hot
 * enough to vibrate against the stars behind it, the second is where the page
 * sets supporting copy and would drop this below the mission statement it is
 * supposed to answer. Still ~12:1 on the scrimmed ground, so the softening
 * costs no legibility.
 *
 * 46ch rather than 38: the measure follows the size down, or the smaller type
 * would run the same short lines and read as a pull-quote. */
.type3-site .fx-manifesto-line {
    max-width: 46ch;
    margin: 0;
    font-size: clamp(17px, 1.7vw, 22px);
    line-height: 1.5;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.78);
}

/* Down from 44px with the type: the gap was set for display size and at 22px it
 * left the two statements looking like separate sections rather than a pair. */
.type3-site .fx-manifesto-line + .fx-manifesto-line {
    margin-top: 32px;
    padding-top: 32px;
    border-top: 1px solid rgba(255, 255, 255, 0.22);
}

@media (max-width: 860px) {
    .type3-site .fx-manifesto {
        padding-top: 96px;
        padding-bottom: 96px;
    }

    .type3-site .fx-manifesto-line + .fx-manifesto-line {
        margin-top: 26px;
        padding-top: 26px;
    }
}


/* ── The exhibit: copy on the left, one slab of artwork on the right ──────
 *
 * RARM's argument. The copy scrolls; the artwork holds beside it and swaps as
 * each block takes the middle of the viewport.
 *
 * THIS IS THE SECOND VERSION OF THE SAME IDEA. The first put the media in a
 * 520px .fx-stage inside the 1180px measure. The mechanic was right and the
 * scale was wrong twice over: the plate came out ~300px tall against ~1200px of
 * scrolling copy, so the right half of the page was empty for most of the
 * section, and .fx-stage's title bar and three dots are FLoCK's software-canvas
 * frame — a crater shot from orbit should not arrive looking like a screenshot.
 *
 * So the media is a full-height slab bleeding off the right edge of the screen,
 * and the frame is gone. The section gives up its right padding to do it, which
 * is why the grid below sets the left inset itself rather than using .fx-wrap.
 *
 * Here rather than in fx.css for the same reason as the manifesto band: the
 * shared system has no pinned-media pattern yet, and one page is not enough to
 * generalise from. If the apex ever wants one, this moves rather than gets
 * copied. */

.type3-site .fx-exhibit {
    /* The slab runs to the viewport edge; .fx-section's 24px would gap it. */
    padding-right: 0;
    padding-left: 0;
    /* Its own clip, so the oversized plate cannot widen the page. `clip` and not
     * `hidden`: hidden would make this a scroll container and the sticky slab
     * inside would pin to IT rather than to the viewport, which parks the
     * artwork at the top of the section and never moves it again. */
    overflow-x: clip;
}

.type3-site .fx-exhibit-grid {
    display: grid;
    /* 45vw, measured rather than picked: at 1440 the slab takes 648px and the
     * other track keeps 728, which is the (1440 - 1180) / 2 left inset plus the
     * count column plus ~520px of copy -- about 58 characters, which is a
     * measure. At 52vw it came out nearer 45ch and still read as a ribbon,
     * which was half of what was wrong with the version before this one. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 45vw);
    gap: 56px;
    align-items: start;
}

/* ── The copy ─────────────────────────────────────────── */

/* Picks up the left inset .fx-wrap would have given it, so the headings here
 * line up with every other section's on the page. max() rather than a plain
 * calc so a narrow window falls back to the section's own 24px gutter instead
 * of a negative inset. */
.type3-site .fx-exhibit-copy {
    padding-left: max(24px, calc((100vw - var(--fx-max)) / 2));
}

/* Each block keeps the numbered shape the rest of the page uses: the count in a
 * narrow left column, the copy beside it. Narrower than .fx-row's 220px — this
 * grid has already given half its width to the slab. */
.type3-site .fx-story-block {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    gap: 24px;
    align-items: start;
    counter-increment: fx-row;
}

/* A real measure, which the 520px-panel version could not afford: the copy
 * column was ~48ch and read as a ribbon. */
.type3-site .fx-story-block .fx-body {
    max-width: 56ch;
}

.type3-site .fx-story-block + .fx-story-block {
    margin-top: 80px;
    padding-top: 80px;
    border-top: 1px solid var(--fx-rule);
}

.type3-site .fx-story-block .fx-h {
    margin-bottom: 20px;
}

/* ── The slab ─────────────────────────────────────────── */

/* Both panes share one grid cell, so the slab is one window onto whichever
 * plate is current and nothing shifts when they swap.
 *
 * The sticky offset clears the fixed nav; the height is what is left of the
 * screen under it. position:sticky needs no clipping ancestor and there is
 * none — see the note on .fx-exhibit's overflow above, and main.css only sets
 * .content's overflow-x under 768px, below the width this layout applies at. */
.type3-site .fx-exhibit-media {
    display: grid;
    position: sticky;
    top: var(--fx-nav-h);
    height: calc(100vh - var(--fx-nav-h));
    /* Short landscape windows: hold a floor so the plate never collapses to a
     * letterbox strip. */
    min-height: 520px;
}

.type3-site .fx-story-pane {
    grid-area: 1 / 1;
    position: relative;
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.5s ease, visibility 0.5s ease;
}

/* The first pane carries this in the markup, so the slab is never empty —
 * including when the script never runs. */
.type3-site .fx-story-pane.is-active {
    opacity: 1;
    visibility: visible;
}

/* Fills the slab whatever the source's own ratio is: the crater is 3:2 and the
 * asteroid clip is 16:9, and both have to hold the same tall window. */
.type3-site .fx-exhibit-plate {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* The crater sits a little high in its frame; this keeps the rim centred
     * rather than the empty desert above it. */
    object-position: 50% 54%;
}

/* A quiet index of what is on screen, bottom left of the slab, over a gradient
 * that exists only to keep it legible against a bright frame. 11px tracked
 * uppercase — .fx-label's own figures, so it reads as the system's small label
 * and not a second vocabulary. */
.type3-site .fx-exhibit-caption {
    position: absolute;
    left: 28px;
    bottom: 24px;
    z-index: 1;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.72);
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.9);
}

/* Both edges that meet the page need softening: the bottom, where the caption
 * sits, and the left, where the plate butts against the copy column. */
.type3-site .fx-story-pane::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background:
        linear-gradient(to top,
            rgba(10, 10, 10, 0.75) 0%,
            rgba(10, 10, 10, 0) 26%),
        linear-gradient(to right,
            rgba(10, 10, 10, 0.45) 0%,
            rgba(10, 10, 10, 0) 16%);
}

@media (prefers-reduced-motion: reduce) {
    .type3-site .fx-story-pane {
        transition: none;
    }
}

/* ── Stacked ──────────────────────────────────────────
 *
 * One column below 1000px, which is where a half-screen slab and a readable
 * measure stop fitting side by side. Everything that made the pinning work is
 * undone: the slab un-pins, the panes stop sharing a cell, and every one of
 * them shows. A phone gets the copy then both plates, which is the same content
 * in the same order and depends on nothing. */
@media (max-width: 1000px) {
    .type3-site .fx-exhibit {
        padding-left: 24px;
        padding-right: 24px;
    }

    .type3-site .fx-exhibit-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 48px;
    }

    .type3-site .fx-exhibit-copy {
        padding-left: 0;
    }

    .type3-site .fx-exhibit-media {
        position: static;
        display: grid;
        gap: 20px;
        height: auto;
        min-height: 0;
    }

    .type3-site .fx-story-pane {
        grid-area: auto;
        opacity: 1;
        visibility: visible;
    }

    /* Freed from the full-height slab, the plates take their own ratio back. */
    .type3-site .fx-exhibit-plate {
        height: auto;
        aspect-ratio: 3 / 2;
    }

    .type3-site .fx-story-block {
        grid-template-columns: minmax(0, 1fr);
        gap: 12px;
    }

    .type3-site .fx-story-block .fx-body {
        max-width: none;
    }
}


/* ── SERAPHIM, over its own artwork ────────────────────────────
 *
 * The same construction as the landing's manifesto band — full-bleed art, a
 * scrim, copy inside the normal measure on top — and for the same reason: this
 * is artwork carrying copy rather than artwork sitting next to it.
 *
 * It earns the treatment here because of what the file is. seraphim.png is a
 * sunlit debris field that is almost entirely black, with the glow at the far
 * left edge. At 420px beside a paragraph that read as a dark rectangle; at full
 * bleed it reads as space, and the copy can simply sit in it. The scrim below
 * is doing far less work than the manifesto's for exactly that reason. */
.type3-site .fx-seraphim {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding-top: 128px;
    padding-bottom: 128px;
    border-top: 1px solid var(--fx-rule);
}

.type3-site .fx-seraphim-art {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Holds the sun at the left edge and the debris field across the middle as
     * the band gets wider or narrower. */
    object-position: 30% 50%;
}

/* Darkens the right half, where the copy sits, and closes both page edges so
 * the band dissolves into the ground rather than stopping at a seam. The art is
 * dark enough that this is mostly about the edges. */
.type3-site .fx-seraphim-scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        /* Across: the copy starts at the midpoint, so the darkening has to be
         * all but complete BY the midpoint rather than still on its way there.
         * At 0.55 the field read straight through the paragraphs. */
        linear-gradient(to left,
            rgba(10, 10, 10, 0.92) 0%,
            rgba(10, 10, 10, 0.88) 38%,
            rgba(10, 10, 10, 0.35) 64%,
            rgba(10, 10, 10, 0) 86%),
        /* Down: dissolves both edges into the page ground. Long enough to read
         * as the band emerging rather than as a crossfade at a seam. */
        linear-gradient(to bottom,
            var(--fx-bg) 0%,
            rgba(10, 10, 10, 0) 26%,
            rgba(10, 10, 10, 0) 74%,
            var(--fx-bg) 100%);
}

/* Right half of the measure: the left is where the glow is. */
.type3-site .fx-seraphim-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}

.type3-site .fx-seraphim-copy {
    grid-column: 2;
    max-width: 52ch;
}

@media (max-width: 1000px) {
    .type3-site .fx-seraphim {
        padding-top: 88px;
        padding-bottom: 88px;
    }

    .type3-site .fx-seraphim-inner {
        grid-template-columns: minmax(0, 1fr);
    }

    .type3-site .fx-seraphim-copy {
        grid-column: 1;
        max-width: none;
    }

    /* With the copy back across the full measure there is no clear side left
     * for the glow, so the scrim has to carry the whole band. */
    .type3-site .fx-seraphim-scrim {
        background:
            linear-gradient(to bottom,
                var(--fx-bg) 0%,
                rgba(10, 10, 10, 0.72) 22%,
                rgba(10, 10, 10, 0.72) 78%,
                var(--fx-bg) 100%);
    }
}


/* ── The fleet, as a 2x2 register ──────────────────────────────
 *
 * Four spacecraft. They were four .fx-row, which opens with a 220px label
 * column holding nothing but a two-digit number, and closed on a ~60ch measure
 * — so each one spent a third of the page on an empty gutter and another third
 * on empty right margin. Stacked four deep that is a thin ribbon of text down
 * the middle of a very wide dark page.
 *
 * Two columns and the number inline recover both. Separation is the hairline
 * cross between the cells and nothing else: no cards, no fills, same as the
 * rest of the system. */
.type3-site .fx-assets {
    /* The spacecraft are their own sequence. See the note in rarm.blade.php: a
     * page-wide counter is right for a document whose sections are one argument
     * in order, and wrong for an inventory that would then open at 04. */
    counter-reset: fx-row;
}

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

.type3-site .fx-fleet-item {
    padding: 44px 0;
    border-top: 1px solid var(--fx-rule);
    counter-increment: fx-row;
}

/* The vertical half of the cross. Only the left column draws it, so the page's
 * right edge stays clean. */
.type3-site .fx-fleet-item:nth-child(odd) {
    padding-right: 48px;
    border-right: 1px solid var(--fx-rule);
}

.type3-site .fx-fleet-item:nth-child(even) {
    padding-left: 48px;
}

/* Count, codename and status on one line — the count is no longer worth a
 * column of its own at this width. Wraps to two lines when a long codename and
 * a long status cannot share. */
.type3-site .fx-fleet-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
}

.type3-site .fx-fleet-head .fx-row-num {
    margin: 0;
}

.type3-site .fx-fleet-head .fx-h--mid {
    margin: 0;
}

.type3-site .fx-fleet-copy > p:first-child {
    margin-top: 0;
}

@media (max-width: 860px) {
    .type3-site .fx-fleet {
        grid-template-columns: minmax(0, 1fr);
    }

    .type3-site .fx-fleet-item:nth-child(odd) {
        padding-right: 0;
        border-right: none;
    }

    .type3-site .fx-fleet-item:nth-child(even) {
        padding-left: 0;
    }
}


/* ── Media in a stage ────────────────────────────────────────────────────────
 *
 * fx.css frames an exhibit (.fx-stage) and sizes an <iframe> inside it
 * (.fx-stage-frame, a fixed height because an embedded document has no
 * intrinsic one). An image or a clip does have one, so it gets a rule of its
 * own instead: full width, natural height, and the frame's own overflow:hidden
 * plus radius does the clipping.
 *
 * Unscoped by name but harmless: .fx-stage-media appears on no other site, and
 * naming it in the system's vocabulary is deliberate — the day the apex frames
 * a still rather than an embed, this is the rule it wants, and it should move to
 * fx.css at that point rather than being copied.
 *
 * The black ground is the stage's, showing through while a poster or a clip
 * decodes, so the frame does not flash as it paints. */
.fx-stage-media {
    display: block;
    width: 100%;
    height: auto;
}


/* ── Asset codename + status ─────────────────────────────────────────────────
 *
 * The one part of the old tab panel that was already right, kept as it was. Five
 * spacecraft and one piece of software, each with a development status that
 * belongs on the heading's line rather than in a sentence under it.
 *
 * Codename and status on one line, wrapping to two when the codename is long.
 * The heading is deliberately not flex: 1, so a title too long to share the line
 * wraps the badge onto its own row instead of squeezing it. */
.type3-site .asset-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 15px;
    /* Stands in for the heading's own margins, which fx.css zeroes, and pays the
     * gap to the first paragraph below. */
    margin: 0 0 20px;
}

/* The heading inside it is .fx-h--mid, which carries a 32px top margin for the
 * mid-row pivots it was cut for. Here it is the first thing in the block. */
.type3-site .asset-head .fx-h--mid {
    margin-top: 0;
}

/* 11px, 700, uppercase, .14em — the same figures as .fx-label, so the pill reads
 * as the system's small state label rather than a second vocabulary, on the
 * 25px radius the panel already used. Quiet on purpose: a hairline ring, a
 * barely-there fill, and the dot doing the signalling.
 *
 * The dot is positioned, not a flex item: a flex box takes its baseline from its
 * first item, and a dot has no text — its baseline is its bottom edge, which
 * drags the whole pill down wherever anything aligns to it. The left padding is
 * what reserves its room. */
.type3-site .status {
    position: relative;
    display: inline-block;
    padding: 8px 18px 8px 34px;
    border: 1px solid var(--fx-rule-strong);
    border-radius: 25px;
    background-color: rgba(255, 255, 255, 0.08);
    color: var(--fx-muted);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    white-space: nowrap;
}

.type3-site .status::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 18px;
    transform: translateY(-50%);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: #ffb020;
}


/* ── A row opening a section that already has a header ───────────────────────
 *
 * fx.css pays the gap BETWEEN capability rows (.fx-row + .fx-row) and nothing
 * above the first one, because on FLoCK and the apex a row is always the first
 * thing inside its .fx-wrap — there is never a heading for it to clear.
 *
 * The landing's programmes band has both: a label and a heading naming the band,
 * then the two programmes as rows. With no rule for that case the first row's
 * label sat directly under the heading's baseline and "Main Objectives" ran into
 * "03 / IN DEVELOPMENT".
 *
 * 56px, which is .fx-section--tight's padding — the same beat the system uses
 * everywhere else for "related, but a step down". */
.type3-site .fx-wrap > .fx-h + .fx-row {
    margin-top: 56px;
}


/* ─── Offer form ─────────────────────────────────────────────────────────────
 *
 * Two columns: the ask on the left, the fields on the right. A field is a label
 * over a bottom rule — no fill, no box, no radius — and focus brightens that
 * rule, the same move the nav links and the asset rows make. Submit takes the
 * primary button's treatment at full width.
 *
 * THIS IS FLOCK'S FORM, SELECTOR FOR SELECTOR, with .flock-site swapped for
 * .type3-site. It is duplicated rather than shared for the same reason the
 * consent checkbox is duplicated between flock/site.css and
 * elements/fx-form.css: the sheets that have to be overridden differ per host
 * and all of them load after fx.css, which is the only sheet the three sites
 * share. KEEP THE THREE IN STEP — a change to the field treatment on one is a
 * change the other two want.
 *
 * This works only because the section is NOT given the id 'offer-form':
 * landing.css hangs a scroll-reactive light-state block off that id. See the
 * note on the include in pages/type3/shell.blade.php. */

.type3-site .offer-form-section {
    /* landing.css centres this as a flex column; the grid inside does the layout
     * now, and `block` keeps the band a plain full-width strip. */
    display: block;
    padding: var(--fx-pad) 24px;
    background: var(--fx-bg);
    border-top: 1px solid var(--fx-rule);
}

.type3-site .fx-offer {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 500px);
    gap: 80px;
    align-items: start;
    width: 100%;
    max-width: var(--fx-max);
    margin: 0 auto;
}

/* ── The ask, on the left ──────────────────────────────────────────────────── */

.type3-site .offer-form-header {
    /* landing.css centres it and caps it with a 40px gap meant for a stacked
     * layout. Here it is a column of its own. */
    text-align: left;
    margin-bottom: 0;
    max-width: 30ch;
}

.type3-site .offer-form-header h2 {
    margin: 0 0 14px;
    font-size: clamp(28px, 3.4vw, 46px);
    line-height: 1.08;
    font-weight: 400;
    color: var(--fx-fg);
}

.type3-site .offer-form-header p {
    margin: 0;
    font-size: clamp(15px, 1.4vw, 17px);
    line-height: 1.55;
    color: var(--fx-muted);
}

/* ── The fields, on the right ──────────────────────────────────────────────── */

.type3-site .offer-form-wrap {
    /* landing.css caps this at 520px for a centred layout; the grid track is the
     * cap now. */
    max-width: none;
}

/* The gaps. subdomain.css declared 14px, which is sized for filled boxes;
 * hairline fields need the air.
 *
 * GAP ONLY on the row — landing.css lays it out as a two-column grid and stacks
 * it itself at 560px, so overriding `display` here would take that media query
 * out of play and need it rewritten below. The form's own flex column, though,
 * has to be stated: landing.css declares it on #offerForm, and these forms are
 * class-hooked, which is what type3/subdomain.css existed to patch up. */
.type3-site .type3-offer-form,
.type3-site .offer-field-row {
    gap: 26px;
}

.type3-site .type3-offer-form {
    display: flex;
    flex-direction: column;
    transition: opacity 0.5s ease;
}

/* type3.js adds this before it swaps in the thank-you text. */
.type3-site .type3-offer-form.fade-out {
    opacity: 0;
}

.type3-site .offer-field {
    gap: 0;
}

/* The field label is the page's micro-label pulled tight to its input —
 * .fx-label's own 20px is sized for standing above a whole section. */
.type3-site .offer-field .fx-label {
    margin: 0 0 8px;
    transition: color 0.2s ease;
}

.type3-site .offer-field input,
.type3-site .offer-field select {
    /* background-COLOR, not the shorthand. The shorthand also resets
     * background-repeat to `repeat`, and it outranks landing.css's no-repeat on
     * the select — which tiled the dropdown arrow across the whole field. */
    background-color: transparent;
    border: none;
    border-bottom: 1px solid var(--fx-rule);
    border-radius: 0;
    padding: 9px 0;
    /* 16px, not 0.9rem: iOS zooms the viewport on focus for anything smaller,
     * which on a form this far down the page is a jarring jump. */
    font-size: 16px;
    font-family: inherit;
    /* Stated on both, so the select and the inputs are the same height. A select
     * takes its line-height from the UA stylesheet and an input does not, which
     * left the country field a couple of pixels taller than the row above it. */
    line-height: 1.5;
    height: auto;
    color: var(--fx-fg);
    transition: border-color 0.2s ease;
}

/* "optional" beside a field label. Lower case against the label's uppercase and
 * a step down in contrast, so it reads as an aside to the label rather than as
 * part of the field's name — this is the one field on the form that is not
 * required, and saying so quietly is the whole job. */
.type3-site .offer-field .offer-optional {
    margin-left: 8px;
    font-weight: 400;
    letter-spacing: 0.04em;
    text-transform: lowercase;
    color: rgba(255, 255, 255, 0.32);
}

.type3-site .offer-field input::placeholder {
    color: rgba(255, 255, 255, 0.3);
}

/* Focus: the rule steps up and the label comes out of grey.
 *
 * Deliberately NOT the --fx-accent ring fx.css gives every other control: this
 * field has no box, so a rectangle drawn 3px off it sits in empty space and
 * points at nothing. The indicator is the field's own rule, which is the only
 * edge it has — a 24%-white rule and a white label against a near-black ground,
 * where the resting state is a 12% rule and a 45% label. Scoped to these fields
 * only; every other control on the page keeps its ring. */
.type3-site .offer-field input:hover,
.type3-site .offer-field select:hover {
    border-bottom-color: var(--fx-rule-strong);
}

.type3-site .offer-field input:focus,
.type3-site .offer-field select:focus {
    border-bottom-color: var(--fx-rule-strong);
    outline: none;
}

.type3-site .offer-field input:focus-visible,
.type3-site .offer-field select:focus-visible {
    outline: none;
}

/* The label is the other half of it. :focus-within, because the label is a
 * sibling of the input rather than an ancestor — .offer-field is what both sit
 * in. */
.type3-site .offer-field:focus-within .fx-label {
    color: var(--fx-fg);
}

.type3-site .offer-field input.input-error,
.type3-site .offer-field select.input-error {
    border-bottom-color: var(--fx-danger);
}

/* appearance:none (landing.css) removed the native arrow, so the sheet draws
 * one. Flush right, because the field no longer has a box to be inset from. */
.type3-site .offer-field select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23ffffff' fill-opacity='0.45'/%3E%3C/svg%3E");
    /* Restated rather than inherited from landing.css: the background-color
     * above is a longhand now, but keeping this next to the image it governs is
     * what stops the next edit re-tiling it. */
    background-repeat: no-repeat;
    background-position: right 2px center;
    padding-right: 26px;
    cursor: pointer;
}

.type3-site .offer-field select option {
    /* The open dropdown is painted by the OS, not the page: on a transparent
     * select these inherit white-on-white in most browsers. */
    background: #141414;
    color: var(--fx-fg);
}

/* ── Terms ─────────────────────────────────────────────────────────────────── */

.type3-site .offer-terms {
    gap: 14px;
    margin-top: 2px;
    cursor: pointer;
}

/* THE BOX IS DRAWN HERE, not by the browser. The page does not declare a dark
 * color-scheme, so Chromium draws the light-theme checkbox — a SOLID WHITE
 * SQUARE when unchecked, the brightest thing in the form, reading as already
 * ticked. On a consent box that is the one mistake worth avoiding. Drawing it
 * also fixes a 4px misalignment: the native widget carries its own inset, so the
 * box sat right of the left edge every field above it starts at.
 *
 * Same control as .flock-site .offer-terms and .fx-form .terms-label in
 * elements/fx-form.css — see the note at the top of this block about keeping the
 * three in step. */
.type3-site .offer-terms input[type="checkbox"] {
    flex: none;
    position: relative;
    width: 16px;
    height: 16px;
    /* Centres the box on the first line's cap height: (13px x 1.6) - 16 is
     * about 5, half of that, plus a hair. */
    margin: 3px 0 0;
    padding: 0;
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 1px solid var(--fx-rule-strong);
    border-radius: 2px;
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}

.type3-site .offer-terms input[type="checkbox"]:hover {
    border-color: var(--fx-fg);
}

/* Checked is the page inverted, the same move the submit button makes. */
.type3-site .offer-terms input[type="checkbox"]:checked {
    background: #ffffff;
    border-color: #ffffff;
}

.type3-site .offer-terms input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 4px;
    height: 8px;
    border: 2px solid #0a0a0a;
    border-top: none;
    border-left: none;
    transform: translate(-50%, -60%) rotate(45deg);
}

.type3-site .offer-terms input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--fx-accent);
    outline-offset: 3px;
}

/* It has a border to recolour now, so the invalid state is the border — the
 * same signal every other field in this form gives. */
.type3-site .offer-terms input[type="checkbox"].input-error {
    border-color: var(--fx-danger);
}

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

/* Legal links keep their underline — the one place on the page that does. A
 * terms link that reads as body copy is a terms link nobody opens. */
.type3-site .offer-terms span a {
    color: var(--fx-muted);
    text-decoration: underline;
    text-underline-offset: 2px;
    transition: color 0.2s ease;
}

.type3-site .offer-terms span a:hover {
    color: var(--fx-fg);
}

/* ── Submit ────────────────────────────────────────────────────────────────── */

.type3-site .offer-submit {
    /* landing.css right-aligns a pill. Full width instead. */
    display: block;
    margin-top: 6px;
}

.type3-site .offer-submit-btn {
    width: 100%;
    box-sizing: border-box;
    padding: 14px 28px;
    border: 1px solid transparent;
    border-radius: 4px;
    background: #ffffff;
    color: #0a0a0a;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.type3-site .offer-submit-btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.82);
}

/* Not landing.css's opacity:0.5, which fades the black label into the grey and
 * leaves "Sending…" barely legible at the moment it matters most. */
.type3-site .offer-submit-btn:disabled {
    background: rgba(255, 255, 255, 0.3);
    color: rgba(0, 0, 0, 0.55);
    opacity: 1;
    cursor: not-allowed;
}

/* ── Processing / success states ───────────────────────────────────────────────
 * type3.js sets display on these inline, so they keep landing.css's flex and
 * only their alignment, colour and type change here. */

.type3-site .offer-form-text {
    align-items: flex-start;
    text-align: left;
    gap: 6px;
    margin-bottom: 24px;
}

.type3-site .offer-form-text h3 {
    font-size: 17px;
    font-weight: 600;
    color: var(--fx-fg);
}

.type3-site .offer-form-text span {
    font-size: 14px;
    color: var(--fx-muted);
}

.type3-site .offer-success {
    align-items: flex-start;
    padding: 8px 0;
}

.type3-site .offer-success-text {
    font-size: 15px;
    color: var(--fx-fg);
}

@media (prefers-reduced-motion: reduce) {
    .type3-site .type3-offer-form,
    .type3-site .offer-field .fx-label,
    .type3-site .offer-field input,
    .type3-site .offer-field select,
    .type3-site .offer-terms input[type="checkbox"],
    .type3-site .offer-submit-btn,
    .type3-site .offer-terms span a {
        transition: none;
    }
}


/* ─── Responsive ─────────────────────────────────────────────────────────────
 *
 * Stacks at 900px rather than the 1000px the .fx-row grids use: this grid's
 * right track is a fixed 500px, so it survives further down than a pair of
 * fluid columns would. */
@media (max-width: 900px) {
    .type3-site .fx-offer {
        grid-template-columns: minmax(0, 1fr);
        gap: 44px;
    }

    .type3-site .offer-form-header {
        max-width: 46ch;
    }
}
