/* =================================================================== REQUEST MODAL — global css ===================================================================

   The popup every "Request an invite" link opens, laid out to the popup design
   (client screenshot, 2026-08-20): the dark notched box with its heading above
   a single column of fields.

   ⚠️ It holds no form of its own. request-modal.js moves the whole `.request`
   section in here and puts it back on close — there is one request form on
   this page and this is it, seen in a second place.

   ⚠️ The SECTION moves rather than the form alone, and that is what keeps this
   file short. Everything laying the form out — `.request__row`'s two columns,
   the 45px gaps, the submit, the note — is written under `.request` in
   request.css; lifting the form out on its own left all of it behind (measured:
   the paired row collapsed and every gap vanished). With the section carried,
   its stylesheet comes too and the only thing left to say here is what the
   popup does differently: one column instead of two, and no intro copy.

   =================================================================== */

:root {
    /* The design puts the popup on a mid grey, and it has to be mid grey: the
       box is --ink, so a dark scrim leaves it edgeless — over the hero, which
       is also --ink, the notched corners disappeared completely. Verified in
       the build before this value was set.

       Built from the two palette ends rather than typed as a grey hex, per the
       "greys are never a hex" rule (CLAUDE.md 2): --ink at 45% against --white
       lands on ~#919191, the design's own value. The outer mix holds back 8% so
       a trace of the page still reads behind it — the design shows none, but
       fully opaque stops being a scrim. */
    --scrim: color-mix(in srgb,
                       color-mix(in srgb, var(--ink) 45%, var(--white)) 92%,
                       transparent);
}

.request-modal {
    /* A <dialog> ships with a UA border, padding, a shrink-to-fit box and
       centring margins. All of it is cleared: the panel inside does the
       sizing, so the dialog is just the top-layer surface. */
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    color: inherit;
    overflow: hidden;

    /* Fade in and out. A <dialog> is added to and removed from the top layer
       the instant showModal()/close() is called, so opacity alone would have
       nothing to animate on the way out — the element is already gone. The two
       discrete transitions are what hold it there: `display` keeps it rendered
       for the duration, and `overlay` keeps it in the top layer while it
       happens. `@starting-style` supplies the frame before it opens, which is
       what the entry animates from.

       request-modal.js reads this duration off the element and waits it out
       before moving the section back to the page — otherwise the box empties
       halfway through its own fade. */
    opacity: 0;
    transition: opacity var(--ease-out),
                display var(--ease-out) allow-discrete,
                overlay var(--ease-out) allow-discrete;

    &[open] {
        opacity: 1;

        @starting-style { opacity: 0; }
    }

    &::backdrop {
        background: var(--scrim);
        opacity: 0;
        transition: opacity var(--ease-out),
                    display var(--ease-out) allow-discrete,
                    overlay var(--ease-out) allow-discrete;
    }

    &[open]::backdrop {
        opacity: 1;

        @starting-style { opacity: 0; }
    }

    /* The scroller. `safe center` keeps the box centred while it fits and
       falls back to start-aligned once it does not: plain `center` on an
       overflowing scroller pushes the top of the content past the scroll
       origin, where it cannot be reached. Measured at 390, where it cut off
       the heading and the first fields with no way to scroll up to them. */
    & .request-modal__panel {
        display: grid;
        align-content: safe center;
        width: 100%;
        height: 100%;
        padding: var(--sp40);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* Fixed rather than absolute: the panel is the scrolling element, so an
       absolutely placed button would scroll away from a long form. Inside a
       modal <dialog> `fixed` resolves against the viewport, which is what the
       top layer is. It paints its own --ink square, with the 5px `.notch` off
       the markup, so it reads at any scroll position. */
    & .request-modal__close {
        position: fixed;
        inset-block-start: var(--sp30);
        inset-inline-end: var(--sp30);
        display: flex;
        align-items: center;
        justify-content: center;
        width: var(--sp50);
        height: var(--sp50);
        padding: 0;
        background: var(--ink);
        border: 0;
        color: var(--text-invert);
        cursor: pointer;
        transition: var(--transition);

        &:hover { background: var(--primary); }

        &:focus-visible {
            outline: 2px solid var(--primary);
            outline-offset: 2px;
        }
    }

    & .section-title-wrap{
        margin-bottom: 0;
    }
    & .request__box{
        &::before{
            display: none;
        }
                
    }
}

/* =================================================================== the section, as it appears in here =================================================================== */
.request-modal {
    /* Band rhythm and the page colour mean nothing inside a dialog; the box is
       the popup. */
    & .request {
        padding-block: 0;
        background: none;
    }

    /* The panel already spends the outer inset, so the container adds nothing
       but a second set of gutters. */
    & .container {
        max-width: none;
        padding-inline: 0;
    }

    /* One column, per the design — and --g100 is a column gap in the section,
       so it has to come down or it becomes 100px between heading and form.
       Width taken off the design by proportion: the heading runs a little over
       half the box, which at the global h2 size puts the box at ~860. */
    & .request__box {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--sp40);
        width: min(100%, 860px);
        margin-inline: auto;
        padding: var(--sp60);
    }

    /* The heading stays; the section's two paragraphs of intro copy do not —
       the popup design carries the form alone. They are the section's content,
       not the popup's, so they are hidden rather than moved out. */
    & .request__intro {
        max-width: none;

        /* request.css centres this column with `margin: 0 auto`, and an auto
           inline margin on a grid item overrides the default stretch — the
           block shrinks to its content and sits centred, which put the heading
           in the middle of the popup instead of on its left edge. Measured:
           470px wide at x565 inside a 740px content box. */
        margin-inline: 0;

        & p { display: none; }
    }

    /* In the section the form is the right-hand column: 578px, pushed right,
       bottom-aligned. In here it is the whole content. */
    & .request__form {
        max-width: none;
        margin-left: 0;
        align-self: stretch;
    }

    /* title-reveal.js (8.0.2) splits `main h1, main h2` into masked lines and
       holds each below its mask until the heading's ScrollTrigger fires. In
       here that trigger can never fire, so an unscrolled-to heading opens as an
       empty box — measured at 390, where the h2's second line was missing.
       Pinned in CSS rather than nudged once in JS because `autoSplit` re-splits
       on a font load or a resize and re-arms the hold. `!important` is what it
       takes to beat GSAP's inline transform. The page keeps its reveal — this
       only ever applies while the section is in here. */
    & .title-line { transform: none !important; }
}

/* The fade is hand-written, so unlike MotionFlow it needs its own guard
   (CLAUDE.md 8). The popup still opens and closes; it just arrives. The script
   reads the duration off the element, so it sees 0 here and stops waiting. */
@media (prefers-reduced-motion: reduce) {
    .request-modal {
        transition: none;

        &::backdrop { transition: none; }
    }
}

/* =================================================================== responsive =================================================================== */
@media (max-width: 767.98px) {
    .request-modal {
        /* the box takes the width back once there is none to spare */
        & .request-modal__panel { padding: var(--sp60) var(--sp15) var(--sp15); }

        & .request-modal__close {
            inset-block-start: var(--sp15);
            inset-inline-end: var(--sp15);
        }
    }

    .request-modal {
        /* --sp* are halved at this breakpoint (7.1), so this is 30/20 in real
           pixels — the section's own --sp110 box padding came out far too wide
           for a 390 screen. */
        & .request__box { padding: var(--sp80) var(--sp60) }
    }
}
