/* ============================================================================
   Raptors Freight — the authentication screens.

   Sign in, verification, sign up, forgotten password. One stylesheet, because
   they are one flow and a person walks through several of them in a row: the
   ground, the type and the field treatment must not change under them.

   Standalone, like the public site: these pages load before there is a
   session, so they must not pull in the admin template. Tokens are restated
   from assets/css/rf_theme.css rather than imported.

   The layout is the design's split — the form on one side, a slow crossfade
   through the operation's own photographs on the other. Below the tablet
   breakpoint the picture panel stops being a column and becomes a short band
   above the form, because a half-height photograph on a phone pushes the
   password field under the fold.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600&family=Mulish:wght@400;500;600;700&display=swap');

/* ── The palette is the APPLICATION's, not a second copy of it ──────────────
   (owner, 2026-08-29: the sign-in screens must follow the theme too.)

   This block used to hold literal colours: #161826, #232532, #e9e9ed — the
   same values assets/css/rf_theme.css already holds under --rf-* names,
   written a second time. Declared once, dark, with no light counterpart, so
   these five screens could not obey a reader's choice however they had set it,
   and any change to the design tokens would have moved every screen except
   these.

   The names stay (every rule below is written against them, and renaming ~300
   references would be a rewrite for no reader's benefit) but each is now an
   ALIAS of the system token. rf_theme.css redefines those under
   html[data-rf-theme="light"], so light and dark both arrive here for free and
   there is exactly one place a colour is decided.

   The pages load rf_theme.css BEFORE this file. They use none of its component
   classes — no .btn, .card, .form-control anywhere in the five — so nothing it
   restyles can reach them; it is brought in for the tokens alone.

   color-scheme is deliberately absent: rf_theme.css sets it per theme, and a
   hardcoded `dark` here would tell the browser to draw dark scrollbars and
   form controls on the light ground. */
:root {
    --color-bg: var(--rf-bg);
    --color-surface: var(--rf-surface);
    --color-text: var(--rf-text);

    --color-accent: var(--rf-accent);
    --color-accent-100: var(--rf-a100);
    --color-accent-200: var(--rf-a200);
    --color-accent-300: var(--rf-a300);
    --color-accent-900: var(--rf-a900);

    --color-section: var(--rf-section);
    --color-section-glow: var(--rf-section-glow);

    --line: var(--rf-line);
    --muted: var(--rf-muted);
    --faint: var(--rf-faint);

    --ok: var(--rf-ok);
    --warn: var(--rf-warn);
    --bad: var(--rf-bad);

    --font-heading: var(--rf-font-heading);
    --font-body: var(--rf-font-body);

    --radius-sm: var(--rf-radius-sm);
    --radius-md: var(--rf-radius-md);
    --radius-lg: var(--rf-radius-lg);

    --shadow-md: var(--rf-shadow-md);
}

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

body {
    margin: 0;
    font-family: var(--font-body);
    font-size: 15px;
    line-height: 1.55;
    text-wrap: pretty;
    background:
        radial-gradient(1300px 780px at 88% -220px, color-mix(in srgb, var(--color-accent-900) 62%, transparent), transparent 60%),
        var(--color-bg);
    color: var(--color-text);
    min-height: 100vh;
}

h1, h2, h3 { font-family: var(--font-heading); font-weight: 500; letter-spacing: -0.02em; margin: 0; }

a { color: var(--color-accent-300); text-decoration: none; }
a:hover { color: var(--color-accent); }

:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* — the split — */

.rf-auth {
    min-height: 100vh;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}

.rf-auth-form {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(28px, 6vw, 88px);
}

.rf-auth-brand {
    display: flex;
    align-items: center;
    gap: 11px;
    margin-bottom: 44px;
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 17px;
    letter-spacing: -0.01em;
    color: var(--color-text);
}
/* NO `display` HERE. The mark is a light/dark pair (helpers/asset.php,
   cdp_authBrand) and the swap in rf_theme.css works by display — a `display:
   block` on this selector out-specifies `.rf-brand-dark { display: none }` and
   both pictures draw, one on top of the other. The parent is a flex container,
   so the images are blockified anyway and nothing is lost by leaving it out. */
.rf-auth-brand img { max-height: 44px; width: auto; }
.rf-auth-brand .sub {
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--faint);
    border-left: 1px solid var(--line);
    padding-left: 11px;
}

.rf-auth-title { font-size: clamp(28px, 3.6vw, 42px); line-height: 1.14; }
.rf-auth-lede { font-size: 15px; line-height: 24px; color: var(--muted); margin: 12px 0 30px; max-width: 42ch; }

/* — the picture panel — */

.rf-auth-side {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(760px 520px at 70% 20%, color-mix(in srgb, var(--color-section-glow) 72%, transparent), transparent 66%),
        var(--color-section);
    display: grid;
    grid-template-rows: minmax(140px, 1fr) auto;
    min-height: 420px;
}

.rf-signin-stage { position: relative; min-width: 0; overflow: hidden; }

/* — where the two halves meet —

   The form sits on --color-bg and the panel on --color-section, and the grid
   put the two straight up against each other: a hard vertical line down the
   middle of the screen with a photograph starting on one side of it. The join
   was the most conspicuous thing on the page.

   So the panel's own ground is dissolved into the form's across the first
   ~130px of it. Everything the panel draws — the saturated ground, the glow,
   the slideshow underneath — arrives out of the form's colour rather than at
   an edge, and the reader reads one surface with a picture in it.

   ::after, and last in the box, so it covers the picture layers: they are
   inset:0 and would otherwise reach the join at full strength. Both are
   position:absolute with no z-index, so painting order is document order.

   Only when the two ARE side by side. Stacked on a narrow screen the panel is
   above the form, and a left-edge fade would be a smear down one side. */
@media (min-width: 901px) {
    /* ONE LENGTH FOR THE WHOLE SEAM. The wash and the picture's own fade used
       to be measured differently — the wash ran over clamp(120px, 17%, 250px)
       and the mask over a flat 34% of the panel — so on a wide screen the wash
       ended around 250px and the picture did not arrive until ~460px. Between
       the two was a band of bare panel colour with no photograph in it and no
       fade left to explain it, which is the hard edge in the middle of the
       screen. Both now measure from --rf-seam, so the picture arrives exactly
       as the form's colour lets go. */
    .rf-auth-side { --rf-seam: clamp(150px, 22%, 320px); }

    .rf-auth-side::after {
        content: "";
        position: absolute;
        inset: 0 auto 0 0;
        width: var(--rf-seam);
        pointer-events: none;
        background: linear-gradient(90deg,
            var(--color-bg) 0%,
            color-mix(in srgb, var(--color-bg) 86%, transparent) 22%,
            color-mix(in srgb, var(--color-bg) 58%, transparent) 46%,
            color-mix(in srgb, var(--color-bg) 30%, transparent) 66%,
            color-mix(in srgb, var(--color-bg) 12%, transparent) 84%,
            transparent 100%);
    }

    /* And the photograph itself is dissolved, not merely covered. Painting a
       scrim of the form's colour over a bright picture greys it; masking the
       layer means the picture genuinely is not there at the join and arrives
       at full strength a little further in. The two together are what make
       the halves read as one surface.

       Eased, not linear: a straight ramp reads as a band with two visible ends,
       and the eye finds both. These stops are an ease-out — most of the change
       happens early, so there is no moment where the picture "starts". */
    .rf-signin-layer {
        -webkit-mask-image: linear-gradient(90deg,
            transparent 0%,
            rgba(0, 0, 0, .18) calc(var(--rf-seam) * .34),
            rgba(0, 0, 0, .52) calc(var(--rf-seam) * .62),
            rgba(0, 0, 0, .84) calc(var(--rf-seam) * .86),
            #000 var(--rf-seam));
        mask-image: linear-gradient(90deg,
            transparent 0%,
            rgba(0, 0, 0, .18) calc(var(--rf-seam) * .34),
            rgba(0, 0, 0, .52) calc(var(--rf-seam) * .62),
            rgba(0, 0, 0, .84) calc(var(--rf-seam) * .86),
            #000 var(--rf-seam));
    }

    /* And the form leans the same way, so the gradient starts before the join
       rather than at it. Its own ground, warmed a few percent towards the
       panel over the last stretch of the column. */
    .rf-auth-form {
        background: linear-gradient(90deg,
            transparent 62%,
            color-mix(in srgb, var(--color-section) 26%, transparent) 100%);
    }

    /* The fade is meant to cover the PICTURE, not the writing under it. The
       facts sit in the same box and would otherwise have their left-hand
       column washed out by it, so they are lifted over it. */
    .rf-auth-facts { position: relative; z-index: 1; }

    /* Sign-up reverses the columns' weights but not their order, so the seam
       is in the same place and behaves the same way. */
}

/* Each picture is one layer running the same keyframe at a different offset;
   helpers/login_images.php sets the duration and the delay, so the number of
   pictures is a data question rather than a CSS one. `lighten` keeps them
   sitting IN the saturated ground rather than on top of it.

   AND THAT BLEND MODE ONLY WORKS ON A DARK GROUND. `lighten` keeps whichever
   of the picture and the ground is brighter; against the dark panel that is
   the photograph, so it shows. Against the LIGHT panel it is the ground almost
   everywhere, so the photograph was erased — the light sign-in showed an empty
   lilac rectangle where the warehouse should be. `multiply` is the same idea
   the other way up: it keeps the darker of the two, so on a pale ground the
   picture comes through and is tinted in its highlights rather than its
   shadows. */
.rf-signin-layer {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    mix-blend-mode: lighten;
    opacity: 0;
    animation-name: rfSlideShow;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}

/* AND ON LIGHT, NO BLEND MODE AT ALL (owner, 2026-08-31: "the whitish filter
   is a little too thick ... more like how a fog covers something").

   `multiply` was the mirror of `lighten` and it was the wrong instrument. On
   the pale panel it keeps the DARKER of picture and ground, so a photograph
   lit by warehouse strip-lights — most of it brighter than #dedcf7 — was
   pulled towards the ground everywhere except its shadows. What survived was a
   lilac haze with a shape in it. The blend mode exists to seat the picture in
   a saturated dark ground; a pale ground does not need seating, so the light
   theme simply shows the photograph. */
html[data-rf-theme="light"] .rf-signin-layer { mix-blend-mode: normal; }

/* THE REAL KEYFRAME IS GENERATED, not this one. A layer's turn is 100/N of the
   cycle, so a fixed shape can only be right for one count — this is the N = 3
   case, kept as the fallback the .rf-signin-layer rule names. helpers/
   login_images.php emits rfSlideShowN for the actual count and points each
   layer at it; see the note there. */
@keyframes rfSlideShow {
    0%, 26% { opacity: 1; }
    33%, 93% { opacity: 0; }
    100% { opacity: 1; }
}

/* The pictures fade into the ground before the copy starts, so text never
   lands on a busy part of a photograph. */
.rf-signin-scrim {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, transparent 46%, color-mix(in srgb, var(--color-section) 72%, transparent) 78%, var(--color-section));
}

/* The same scrim reads completely differently on the two grounds. Dark: it is
   a vignette, and the photograph keeps its subject. Light: it is a wash of
   near-white poured over the bottom half — the second half of the fog. It
   still has a job (the picture must not stop at a hard line above the facts),
   so it is not removed, only held back: nothing until the last third, and full
   strength only at the very edge it has to meet. */
html[data-rf-theme="light"] .rf-signin-scrim {
    background: linear-gradient(180deg,
        transparent 64%,
        color-mix(in srgb, var(--color-section) 34%, transparent) 84%,
        color-mix(in srgb, var(--color-section) 76%, transparent) 95%,
        var(--color-section) 100%);
}

.rf-auth-facts { display: grid; gap: 18px; padding: 0 clamp(28px, 5vw, 64px) clamp(28px, 5vw, 56px); }
.rf-auth-facts .lead {
    display: flex;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
}
.rf-auth-facts .lead b {
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: clamp(28px, 4vw, 46px);
    letter-spacing: -0.03em;
    line-height: 1;
}
.rf-auth-facts .lead span {
    font-size: 13px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--color-text) 66%, transparent);
}
.rf-auth-hr {
    height: 1px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--color-text) 26%, transparent) 12%, color-mix(in srgb, var(--color-text) 26%, transparent) 88%, transparent);
}
.rf-auth-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 20px; }
.rf-auth-grid .n { font-family: var(--font-heading); font-size: 19px; font-weight: 500; }
.rf-auth-grid .l { font-size: 12px; color: color-mix(in srgb, var(--color-text) 60%, transparent); margin-top: 2px; }

/* — fields — */

.rf-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
/* The label is the one BARE span in a field. select2 and the reveal wrapper
   are also direct-child spans, and they must not be dressed as labels. */
.rf-field > span:not([class]) {
    font-size: 12px;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--muted);
}

.rf-input {
    width: 100%;
    min-height: 42px;
    padding: 9px 12px;
    font: inherit;
    font-size: 14px;
    color: var(--color-text);
    caret-color: var(--color-accent);
    background: color-mix(in srgb, var(--color-surface) 70%, transparent);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    transition: border-color .15s, box-shadow .15s;
}
.rf-input:hover { border-color: color-mix(in srgb, var(--color-text) 30%, transparent); }
.rf-input:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
.rf-input::placeholder { color: var(--faint); }

/* A password field with a reveal control inside it. */
.rf-input-wrap { position: relative; display: flex; align-items: center; }
.rf-input-wrap .rf-input { padding-right: 42px; }
.rf-reveal {
    position: absolute;
    right: 6px;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 0;
    background: transparent;
    color: var(--faint);
    cursor: pointer;
    border-radius: var(--radius-sm);
}
.rf-reveal:hover { color: var(--color-accent-200); }

.rf-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    padding: 10px 16px;
    cursor: pointer;
    font-family: var(--font-heading);
    font-weight: 500;
    font-size: 15px;
    color: #fff;
    background: var(--color-accent);
    border: 1px solid var(--color-accent);
    border-radius: var(--radius-md);
    transition: background .15s, border-color .15s;
}
.rf-btn:hover { background: color-mix(in srgb, var(--color-accent) 84%, white); }
.rf-btn:disabled { opacity: .55; cursor: not-allowed; }

.rf-btn-ghost {
    background: transparent;
    color: var(--color-accent-200);
    border-color: var(--line);
}
.rf-btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); border-color: var(--color-accent); }

/* — waiting —

   The spinner, the busy line and the busy button live in rf_theme.css: the
   same loader.gif was being written into a result div on nine screens behind
   the sign-in, and one waiting state cannot be defined in a stylesheet only
   the sign-in screens load. What is left here is the one row that is peculiar
   to the code screen.

   NOWRAP, and the message is the part that gives. Allowed to wrap, the row
   put the message on one line and the button on the next, so the row was 69px
   with the note in it and 38px with the sending line in it — a 31px jump every
   time the two traded places, which is the fault the loader.gif had and the
   whole point of moving it here. A message too long for the space now wraps
   inside its own box, which the button neither sees nor moves for. */
.cdp-otp-status {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 12px;
    min-height: 40px;
    margin-bottom: 16px;
}
.cdp-otp-status > button { flex: none; margin-left: auto; }
.cdp-otp-status > .rf-busy { min-width: 0; }
.cdp-otp-note {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    font-size: 12.5px;
    color: var(--faint);
}
.cdp-otp-note[hidden] { display: none; }

.rf-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 2px 0 14px;
    font-size: 13px;
    color: var(--muted);
    flex-wrap: wrap;
}
.rf-check { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.rf-check input { accent-color: var(--color-accent); width: 15px; height: 15px; }

.rf-note {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 30px;
    font-size: 12.5px;
    color: var(--faint);
}

.rf-alert {
    border-radius: var(--radius-md);
    border: 1px solid color-mix(in srgb, var(--bad) 42%, transparent);
    background: color-mix(in srgb, var(--bad) 14%, transparent);
    color: var(--bad);
    padding: 11px 14px;
    font-size: 13.5px;
    line-height: 20px;
    margin-bottom: 18px;
}
.rf-alert-ok {
    border-color: color-mix(in srgb, var(--ok) 42%, transparent);
    background: color-mix(in srgb, var(--ok) 14%, transparent);
    color: var(--ok);
}

.rf-secondary {
    display: flex;
    gap: 10px;
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px solid var(--line);
    flex-wrap: wrap;
}
.rf-secondary .rf-btn { width: auto; flex: 1 1 150px; min-height: 38px; font-size: 13px; }

/* — the verification card — */

.rf-card {
    width: 100%;
    max-width: 440px;
    padding: clamp(22px, 4vw, 34px);
    background: var(--color-surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    animation: rfFade .35s ease both;
}

@keyframes rfFade {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
}

.rf-centre { min-height: 100vh; display: grid; place-items: center; padding: clamp(24px, 5vw, 60px) 18px; }

.rf-channel {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 13px;
    border-radius: var(--radius-md);
    border: 1px solid var(--line);
    background: color-mix(in srgb, var(--color-text) 4%, transparent);
    margin-bottom: 8px;
}
.rf-channel .who { font-family: var(--font-heading); font-size: 13.5px; letter-spacing: .02em; }
.rf-channel .what { font-size: 11.5px; color: var(--faint); margin-top: 2px; }

/* Six boxes for six digits. They are one input each so a paste of the whole
   code can be split across them and a backspace can walk backwards. */
.rf-otp { display: flex; gap: 7px; margin-bottom: 15px; }
.rf-otp input {
    flex: 1;
    min-width: 0;
    height: 52px;
    text-align: center;
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 20px;
    color: var(--color-text);
    border-radius: var(--radius-md);
    border: 1px solid var(--line);
    background: color-mix(in srgb, var(--color-surface) 70%, transparent);
}
.rf-otp input:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
/* A box with a digit in it reads as done — six accents mean "full, sending". */
.rf-otp input.filled {
    border-color: color-mix(in srgb, var(--color-accent) 55%, var(--line));
    background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

/* The 90-day device toggle on the verification card. The switch itself is
   the shared .rf-switch/.rf-switch-slider component from rf_theme.css — this
   is only the row that seats it beside its wording. */
.cdp-remember-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 14px;
    font-size: 13px;
    color: var(--muted);
    -webkit-tap-highlight-color: transparent;
}
.cdp-remember-row .rf-switch { flex: none; }
.cdp-remember-row label { cursor: pointer; margin: 0; }
.cdp-remember-row:has(input:checked) { color: var(--color-text); }

/* ── Tablet and phone ─────────────────────────────────────────────────────
   The picture panel gives up its column and becomes a band. It keeps the
   crossfade — it is the only branding on the screen — but it stops competing
   with the form for vertical space. */

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

    .rf-auth-side {
        order: -1;
        min-height: 0;
        grid-template-rows: 150px auto;
    }
    .rf-auth-facts { padding: 0 clamp(20px, 6vw, 40px) 26px; gap: 14px; }
    .rf-auth-facts .lead b { font-size: 30px; }

    .rf-auth-form { padding: 32px clamp(20px, 6vw, 40px) 48px; }
    .rf-auth-brand { margin-bottom: 28px; }
}

@media (max-width: 480px) {
    .rf-auth-side { grid-template-rows: 110px auto; }
    /* Three facts across a phone is three one-word columns; one column reads. */
    .rf-auth-grid { grid-template-columns: 1fr; gap: 12px; }
    .rf-otp { gap: 5px; }
    .rf-otp input { height: 46px; font-size: 18px; }

    /* The verification card, on a phone. The nowrap status row that keeps the
       desktop card from jumping cannot hold a sentence AND a button in 320px —
       the message takes the full width and the button drops under it, right-
       aligned. The card also gives back some of its air so the boxes and the
       Verify button sit above the fold. */
    .rf-centre { padding: 16px 10px; align-items: start; }
    .rf-card { padding: 20px 16px; }
    .cdp-otp-status { flex-wrap: wrap; row-gap: 6px; min-height: 0; }
    .cdp-otp-status > button { margin-left: auto; }
    .rf-channel { padding: 9px 11px; margin-bottom: 6px; }
    .rf-channel .who { font-size: 13px; }
}

@media (prefers-reduced-motion: reduce) {
    .rf-signin-layer { animation: none; opacity: 1; }
    .rf-signin-layer ~ .rf-signin-layer { display: none; }
    .rf-card { animation: none; }
}

/* ============================================================================
   Sign up — the one long form in this flow.

   Sign in asks for two things; registration asks for sixteen. So the split
   changes shape: the form column takes the extra width, the picture panel
   pins itself to the viewport and stays put while the form scrolls past it,
   and the fields are grouped into four named steps so the length reads as
   four short asks rather than one long one.
   ========================================================================== */

.rf-auth--signup .rf-auth-form { justify-content: flex-start; padding-block: clamp(28px, 5vw, 64px); }
.rf-auth--signup .rf-auth-brand { margin-bottom: 28px; }

@media (min-width: 992px) {
    .rf-auth--signup { grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr); }
    .rf-auth--signup .rf-auth-side { position: sticky; top: 0; height: 100vh; }
}

/* — a named group of fields — */

.rf-group { margin: 0 0 26px; border: 0; padding: 0; min-width: 0; }
.rf-group > legend {
    display: flex;
    align-items: baseline;
    gap: 10px;
    width: 100%;
    margin: 0 0 14px;
    padding: 0 0 9px;
    font-family: var(--font-heading);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--color-text);
    border-bottom: 1px solid var(--line);
}
.rf-group > legend .n {
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    color: var(--color-accent-300);
}

/* — field rows —
   auto-fit, so the same markup is two-up on a laptop and one-up on a phone
   without a second set of classes. */

.rf-cols { display: grid; gap: 0 16px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); }
.rf-cols-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr)); }
.rf-cols .rf-span-2 { grid-column: span 2; }
@media (max-width: 640px) { .rf-cols .rf-span-2 { grid-column: auto; } }

.rf-req { color: var(--bad); margin-left: 2px; }
.hide { display: none !important; }

/* — file inputs —
   The browser default control is a grey button and a filename set in the
   host font; on this ground it looks like a bug. Restyled to read as a
   field with an action in it. */

.rf-input[type="file"] { padding: 8px 12px; line-height: 24px; cursor: pointer; }
.rf-input[type="file"]::file-selector-button {
    margin: 0 10px 0 0;
    padding: 5px 12px;
    font: inherit;
    font-size: 12.5px;
    color: var(--color-accent-200);
    background: color-mix(in srgb, var(--color-accent) 16%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-accent) 44%, transparent);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.rf-input[type="file"]::file-selector-button:hover {
    background: color-mix(in srgb, var(--color-accent) 26%, transparent);
}

/* — native select — */

select.rf-input {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 34px;
    background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                      linear-gradient(135deg, var(--muted) 50%, transparent 50%);
    background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}
select.rf-input option { background: var(--color-surface); color: var(--color-text); }

/* — password feedback —
   Six states, three readings: not there yet, acceptable, good. */

#password-strength-meter, #passwordMatch {
    font-size: 12px;
    line-height: 18px;
    margin: -8px 0 14px;
    min-height: 18px;
}
#password-strength-meter.weak, #password-strength-meter.weaks { color: var(--bad); }
#password-strength-meter.medium { color: var(--warn); }
#password-strength-meter.good,
#password-strength-meter.strong,
#password-strength-meter.very-strong { color: var(--ok); }
#passwordMatch { color: var(--bad) !important; }
#valid-msg { color: var(--ok); font-size: 12px; }
#error-msg { font-size: 12px; margin: -8px 0 12px; }

/* — the phone field —
   intl-tel-input wraps the input in a container of its own and drops a
   country list over it. Both were built for a light page. */

.iti { width: 100%; display: block; }
.iti__flag-container { border-right: 1px solid var(--line); }
.iti__selected-flag { border-radius: var(--radius-md) 0 0 var(--radius-md); }
.iti__selected-flag:hover,
.iti__selected-flag[aria-expanded="true"] {
    background: color-mix(in srgb, var(--color-text) 8%, transparent);
}
.iti__country-list {
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    max-height: 240px;
}
.iti__country.iti__highlight { background: color-mix(in srgb, var(--color-accent) 26%, transparent); }
.iti__divider { border-bottom-color: var(--line); }
.iti__dial-code { color: var(--faint); }
.rf-input.is-invalid { border-color: var(--bad); }

/* — select2 —
   Country, state and city are searched against the server, so they have to
   stay select2. Only its skin changes. */

.select2-container { width: 100% !important; }
.select2-container--default .select2-selection--single {
    height: 42px;
    background: color-mix(in srgb, var(--color-surface) 70%, transparent);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 40px;
    padding-left: 12px;
    color: var(--color-text);
}
.select2-container--default .select2-selection--single .select2-selection__placeholder { color: var(--faint); }
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 40px; right: 6px; }
.select2-container--default .select2-selection--single .select2-selection__arrow b { border-top-color: var(--muted); }
.select2-container--default .select2-selection--single .select2-selection__clear { color: var(--faint); }
.select2-container--default.select2-container--disabled .select2-selection--single { opacity: .55; }
.select2-container--open .select2-selection--single { border-color: var(--color-accent) !important; }

.select2-dropdown {
    background: var(--color-surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    color: var(--color-text);
}
.select2-search--dropdown { padding: 8px; }
.select2-container--default .select2-search--dropdown .select2-search__field {
    background: color-mix(in srgb, var(--color-bg) 60%, transparent);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    padding: 7px 10px;
}
.select2-container--default .select2-results__option { padding: 8px 12px; font-size: 14px; }
.select2-container--default .select2-results__option[aria-selected="true"],
.select2-container--default .select2-results__option--selected {
    background: color-mix(in srgb, var(--color-accent) 18%, transparent);
    color: var(--color-text);
}
.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted {
    background: var(--color-accent);
    color: #fff;
}
.select2-results__options { max-height: 240px; }

/* — dialogs on this page —
   The terms of service, the field errors and the sending state all come
   through SweetAlert, whose own dressing is white. */

.swal2-popup {
    background: var(--color-surface) !important;
    color: var(--color-text) !important;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg) !important;
}
.swal2-title { font-family: var(--font-heading) !important; color: var(--color-text) !important; font-size: 1.25rem !important; }
.swal2-html-container { color: var(--muted) !important; font-size: 14px !important; }
.swal2-html-container h5,
.swal2-html-container h6 { font-family: var(--font-heading); color: var(--color-text); }
.swal2-html-container hr { border-color: var(--line); }
.swal2-html-container strong { color: var(--color-text); }
.swal2-styled { border-radius: var(--radius-md) !important; font-family: var(--font-heading) !important; }
.swal2-loader { border-color: var(--color-accent) transparent var(--color-accent) transparent !important; }
.swal2-container { backdrop-filter: blur(2px); }

/* — a disabled select2 —
   State and City stay closed until the level above them is chosen. select2
   paints a disabled control #eee from a three-class selector, which is
   louder than the skin above, so it has to be answered directly. */

.select2-container--default.select2-container--disabled .select2-selection--single {
    background: color-mix(in srgb, var(--color-text) 5%, transparent);
    border-color: color-mix(in srgb, var(--color-text) 8%, transparent);
    cursor: not-allowed;
    opacity: 1;
}
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__rendered,
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__placeholder {
    color: var(--faint);
}

/* — checkboxes —
   The native control is drawn by the operating system in its own colours: on
   this ground an unticked box is a pale grey smudge you cannot tell from a
   disabled one. Drawn here instead, so ticked and unticked are both obvious. */

.rf-check input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    margin: 0;
    flex: none;
    display: inline-grid;
    place-content: center;
    cursor: pointer;
    background: color-mix(in srgb, var(--color-text) 7%, var(--color-surface));
    border: 1.5px solid color-mix(in srgb, var(--color-text) 40%, transparent);
    border-radius: var(--radius-sm);
    transition: background .12s, border-color .12s;
}
.rf-check input[type="checkbox"]::before {
    content: "";
    width: 10px;
    height: 10px;
    transform: scale(0);
    transition: transform .12s ease-in-out;
    background: #fff;
    clip-path: polygon(14% 44%, 0 65%, 43% 100%, 100% 22%, 82% 6%, 40% 65%);
}
.rf-check input[type="checkbox"]:checked {
    background: var(--color-accent);
    border-color: var(--color-accent);
}
.rf-check input[type="checkbox"]:checked::before { transform: scale(1); }
.rf-check input[type="checkbox"]:hover { border-color: var(--color-accent); }
.rf-check input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.rf-check > span { line-height: 20px; }

/* An empty message line should not hold a gap open. */
#password-strength-meter:empty, #passwordMatch:empty { display: none; }

/* — the split must be allowed to be narrow —
   A grid track written `1fr` is really `minmax(auto, 1fr)`, and `auto` there
   means "at least min-content". The registration form's field rows declare a
   210px minimum per column, so their min-content is two columns wide — and
   that measurement travelled up and forced the whole page to about 590px on
   a 390px phone, which is why every second field ran off the right edge.
   Floored at zero, the tracks shrink to the viewport and the field rows
   collapse to one column on their own. */

.rf-auth { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }
.rf-auth > * { min-width: 0; }
.rf-auth-form > form,
.rf-cols > * { min-width: 0; }

@media (max-width: 900px) {
    .rf-auth { grid-template-columns: minmax(0, 1fr); }

    /* On a phone the registration form is the errand; the facts beside it are
       already on the sign-in page the person just came from. The picture band
       stays, the copy under it goes, and the first field is reachable without
       a scroll. */
    .rf-auth--signup .rf-auth-side { grid-template-rows: 120px; min-height: 0; }
    .rf-auth--signup .rf-auth-facts { display: none; }
    .rf-auth--signup .rf-auth-form { padding-top: 26px; }

    .rf-group > legend { font-size: 12px; }
}
