/*  auth.css — the skin for the sign-in surface. Fix 361, 16 Sep 2026, as
    wwwroot/css/experiments/login-alt.css; renamed here by fix 436 (18 Sep 2026) when Aaron adopted
    the design: "I'm thinking about moving the auth screens to that new design ... go for the auth
    pages." The rules below did not change with the name — this is the same sheet, at the address
    the auth screens keep. Its one reader is Pages/Shared/_LayoutSignIn.cshtml, which fix 436 step 4
    renamed from _LayoutLoginAlt.cshtml.

    THAT DOCUMENT IS THE ONLY AUTH DOCUMENT SINCE FIX 537 (Aaron, 22 Sep 2026: "we need to iron out
    silly confusions like this. we want one auth layout, with a set of auth pages in it. that is
    all. simple, understandable."). So this sheet dresses the two OAuth terminals and the two error
    pages as well as the twelve sign-in screens, and the second document it used to sit beside —
    _LayoutAuth.cshtml, with WpAuthShell inside it — is deleted. Three registers were added for the
    joiners and each says so at its own rule: .la-submit--quiet, .la-card and .la-scopes.

    IT LIVES IN css/wp/ AS A PAGE SHEET, not as a design-system tier: external-sign.css,
    report-popout.css and vpp-paper.css are its neighbours, and like them it is hand-authored CSS
    for one document rather than part of tokens/brand/base. The paragraph below still governs what
    is inside it.

    Aaron, 16 Sep 2026: "I asked Claude Design to come up with a refreshed version of the login
    page ... Could you create a second version of the login page? I don't want it to replace the
    login page as it is — I just want to see this implementation of it ... Don't use our new fonts
    and stuff to make it part of the design process — don't write it into the design process yet,
    because it's just an experiment."

    SO THIS FILE IS DELIBERATELY OUTSIDE THE DESIGN SYSTEM, and that is the one thing about it
    worth defending in a review:

      - No --wp-* token is read here and none is declared. The palette below is the design's own
        (Claude Design, "Wealth Portal Login.dc.html", artboards 1A/1B/1C), lifted as literal hex
        because it was a proposal rather than a theme.

        THAT IS NOW THE OPEN QUESTION ON THIS FILE (fix 436, 18 Sep 2026). It was the right answer
        for an experiment nobody was themed onto; the design has been adopted, so a per-firm theme
        still cannot reach the sign-in screen, and per-firm theming is the end goal. The way out is
        the one this header always named: these values become Tier 2 tokens and the sheet reads
        them. Nobody has ruled on it, it is not a re-skin, and fix 436 was a re-skin — so it is
        written down here rather than done quietly.
      - Almost every selector is la-* (the prefix the design was given as login-alt), so nothing
        here can collide with, or be collided with by, the house sheets — which this document does
        not link at all. The exception is the block near the form rules that dresses the two design
        system controls the screens kept for their BEHAVIOUR, WpPasswordField and WpOtpInput: those
        arrive as plain unstyled HTML because no house sheet is linked, and this file is what
        dresses them. See that block's own header.
      - HAND-AUTHORED CSS WITH NO SASS SOURCE. Every file under wwwroot is source now (fix 409,
        18 Sep 2026 — the Node asset pipeline, compilerconfig.json and bundleconfig.json are all
        gone), so this is the ordinary case rather than the exception it was when the file was
        written. Edit this file; there is nothing to rebuild.

    Geometry is the design's: 63/37 split, 52px/56px panel padding, 48px fields, a 52px button,
    3px radii, a display serif for display and a body sans for everything else (the house pair,
    Newsreader and IBM Plex Sans, loaded by _LayoutSignIn.cshtml's head the way the design's own
    helmet loads them).

    BOTH FACES ARE THE FIRM'S WHEN THE FIRM HAS THEM (fix 535, Aaron 22 Sep 2026 — the display
    face first, then "body font should follow the firm font too"). Every display rule reads
    --auth-display and the page's own font-family reads --auth-body; each property is declared
    once, on .la-page below, holding the house face, and a themed firm's document head
    re-declares whichever of the two the theme sets on the same element after this sheet loads.
    So this file names the house pair in exactly one place each, and nothing here has to know a
    theme exists.

    MOBILE. Conductor ruling 6 (16 Sep 2026) wrote the first small-screen frame with no drawing to
    follow — the design's three artboards are all 1240x780. Aaron sent the phone mock on 18 Sep
    2026 and fix 436 rewrote the breakpoint against it: one rounded card, hero over form, the
    backdrop picker as a bottom sheet. The block at the foot of this file carries the detail,
    including what the mock confirmed and what it changed.
*/

.la-page {
    /* The design's palette (1A/1B/1C), named for what it does here. */
    --la-ground: #ECE8E1;
    --la-panel: #F7F5F1;
    --la-panel-glass: rgba(247, 245, 241, 0.6); /* fix 364: the panel at rest, the video showing through; 0.78 until fix 366 ("more transparent") */
    --la-card: #FFFFFF;
    --la-ink: #10151C;
    --la-ink-hover: #1D2530;
    --la-label: #4A4F57;
    --la-muted: #6B6F76;
    --la-faint: #8A8F96;
    --la-line: #D3CCC0;
    --la-line-soft: #E2DDD4;
    --la-link: #8A6A3E;
    --la-media: #0C1118;
    --la-accent: #C79A5B;
    --la-bad: #8C2F26;
    --la-warn-bg: #FBF3E4;

    /* THE ONE PLACE EACH HOUSE FACE IS WRITTEN DOWN (fix 535, Aaron 22 Sep 2026: "font family is
       Newsreader, so it looks different from the firm theme. maybe the main font should be the
       firm font? i like the title in the top left, but use the firm font", then, on the question
       of whether the prose should follow as well, "body font should follow the firm font too").

       DISPLAY is the firm title, the hero tagline, the firm-letter mark and the panel's heading;
       BODY is everything else, inherited from .la-page. A themed firm reaches all of them by
       re-declaring these two values — which _LayoutSignIn.cshtml does, on .la-page, after this
       sheet loads, from the theme's HeadingFontFamily and FontFamily respectively. The house face
       stays at the back of whatever the head puts in front of it, so a Google face that fails to
       arrive lands on the house pair rather than on the browser's defaults. */
    --auth-display: "Newsreader", Georgia, serif;
    --auth-body: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

    margin: 0;
    background: var(--la-ground);
    color: var(--la-ink);
    font-family: var(--auth-body);
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

.la-page *,
.la-page *::before,
.la-page *::after {
    box-sizing: border-box;
}

.la-page a {
    color: var(--la-link);
    text-decoration: none;
}

.la-page a:hover {
    color: var(--la-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.la-page :focus-visible {
    outline: 2px solid var(--la-ink);
    outline-offset: 2px;
}

.la-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ── The frame ─────────────────────────────────────────────────────────────────────────────── */

/* Fix 364 (Aaron, 16 Sep 2026: "make the side panel partly transparent so can see the video"):
   the frame is a grid of one row and two columns. The backdrop spans both columns of that row and
   the two columns sit on it, so the sign-in panel can be glass without the columns knowing about
   each other. Under 48rem the same grid turns into two rows and the backdrop keeps to the banner. */
.la-frame {
    position: relative;
    display: grid;
    grid-template-columns: 63% 37%;
    grid-template-rows: minmax(100vh, auto);
    grid-template-rows: minmax(100dvh, auto);
    background: var(--la-panel);
}

/* ── The backdrop: the frame's, under both columns ─────────────────────────────────────────── */

.la-backdrop {
    position: relative;
    grid-column: 1 / -1;
    grid-row: 1;
    z-index: 0;
    background: var(--la-media);
    overflow: hidden;
}

/* ── Left: the photograph column's furniture ───────────────────────────────────────────────── */

.la-media {
    position: relative;
    grid-column: 1;
    grid-row: 1;
    z-index: 1;
    overflow: hidden;
}

.la-backdrop__still,
.la-backdrop__video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 0;
}

.la-backdrop__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(8, 11, 16, 0.62) 0%, rgba(8, 11, 16, 0.18) 38%, rgba(8, 11, 16, 0.74) 100%);
    pointer-events: none;
}

.la-media__inner {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 24px;
    padding: 44px 48px;
}

.la-mark {
    display: flex;
    align-items: center;
    gap: 14px;
}

/* Fix 535 (Aaron, 22 Sep 2026: "the initial in the box is slightly misaligned vertically - it is
   closer to the top than the bottom"). Centring a flex box centres the LINE BOX, and a line box
   is the face's ascent plus its descent — an asymmetry every serif has, and now a DIFFERENT
   asymmetry per firm, because the face is the theme's. No px nudge can be right for two faces at
   once, so the line box is trimmed instead: text-box cuts it back to this letter's own cap-height
   and baseline, and the square then centres the LETTER rather than the em box it sits in. Where
   the browser has no text-box yet, the flex centring still runs and the result is exactly today's
   rendering, so the rule can only improve it. line-height: 1 keeps the untrimmed box a known
   height whatever face arrives. */
.la-mark__glyph {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    border: 1px solid rgba(255, 255, 255, 0.55);
    font-family: var(--auth-display);
    font-size: 17px;
    line-height: 1;
    color: #FFFFFF;
}

/* Fix 635 (Aaron, 24 Sep 2026, the same F still high under Newsreader). Fix 535's trim sat on the
   square itself, and the square is a flex container: text-box trims the line boxes of a block or
   inline box, and a flex container has none of its own - its text lives in an anonymous flex item
   the rule never reached, so the line box stayed the full 17px em box (measured on 5029: 7.5px
   above the ink, 12.5px below). The letter is now its own block, the trim is on it, and the square
   centres that trimmed block: 10.30px above, 10.31px below. */
.la-mark__letter {
    display: block;
    text-box: trim-both cap alphabetic;
}

.la-mark__logo {
    max-height: 40px;
    max-width: 220px;
}

/* The design's two-tone wordmark: the firm's display name may carry one <b>, and that half is
   the white one, the rest of the line softened — so the tag is honoured rather than stripped
   (WpAuthShell's own wordmark rule, in this experiment's own colours). */
.la-mark__name {
    margin: 0;
    font-family: var(--auth-display);
    font-size: 25px;
    font-weight: 400;
    letter-spacing: 0.01em;
    color: rgba(255, 255, 255, 0.72);
}

.la-mark__name b {
    font-weight: 400;
    color: #FFFFFF;
}

.la-media__say {
    max-width: 520px;
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.la-tagline {
    margin: 0;
    font-family: var(--auth-display);
    font-size: 40px;
    line-height: 1.16;
    font-weight: 300;
    color: #FFFFFF;
    text-wrap: pretty;
}

.la-eyebrow {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.68);
}

.la-eyebrow::before {
    content: "";
    width: 22px;
    height: 1px;
    background: rgba(255, 255, 255, 0.45);
}

/* ── The backdrop button and its picker ────────────────────────────────────────────────────── */

.la-backdrop-btn {
    position: absolute;
    right: 24px;
    bottom: 24px;
    display: flex;
    align-items: center;
    gap: 9px;
    height: 34px;
    padding: 0 14px;
    border: 1px solid rgba(255, 255, 255, 0.32);
    border-radius: 2px;
    background: rgba(10, 14, 20, 0.45);
    backdrop-filter: blur(8px);
    font-family: inherit;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.86);
    cursor: pointer;
}

.la-backdrop-btn:hover {
    border-color: rgba(255, 255, 255, 0.6);
    color: #FFFFFF;
}

.la-backdrop-btn__bars {
    display: flex;
    align-items: flex-end;
    gap: 2px;
}

.la-backdrop-btn__bars span {
    width: 3px;
    background: rgba(255, 255, 255, 0.8);
}

.la-backdrop-btn__bars span:nth-child(1) { height: 8px; }
.la-backdrop-btn__bars span:nth-child(2) { height: 12px; }
.la-backdrop-btn__bars span:nth-child(3) { height: 6px; }

.la-picker {
    position: absolute;
    left: 32px;
    right: 32px;
    bottom: 28px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 22px 24px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 4px;
    background: rgba(9, 13, 19, 0.82);
    backdrop-filter: blur(14px);
    color: #FFFFFF;
}

.la-picker__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
}

/* The title and the hint are wrapped so the phone's bottom sheet can reorder around them (fix
   436). On a desktop the wrapper is not a box at all: the head is the same three-item baseline
   row it was drawn as. */
.la-picker__heading {
    display: contents;
}

.la-picker__title {
    margin: 0;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #FFFFFF;
}

.la-picker__hint {
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.72);
}

.la-picker__close {
    border: 0;
    background: none;
    padding: 0 0 0 12px;
    font-family: inherit;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.72);
    cursor: pointer;
}

.la-picker__close:hover {
    color: #FFFFFF;
}

.la-picker__tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.la-picker__tab {
    height: 26px;
    padding: 0 12px;
    border: 1px solid rgba(255, 255, 255, 0.24);
    border-radius: 2px;
    background: none;
    font-family: inherit;
    font-size: 12px;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.78);
    cursor: pointer;
}

.la-picker__tab[aria-selected="true"] {
    border-color: var(--la-accent);
    color: #FFFFFF;
}

/* Fix 436 (Aaron, 18 Sep 2026, on a screenshot of the picker showing two rows behind a scrollbar:
   "make the backdrop taller, no point having scrollbars on it if you don't need to"). The cap was a
   flat 264px, which is under two rows of thumbnails (92px shot + 9px gap + a 19px label = 120px a
   row, 14px between rows), so every tab scrolled however much room the screen had. It is the
   VIEWPORT's now: the grid grows with its content and only scrolls when the sheet would otherwise
   leave the screen.

   The 175px is this sheet's own chrome, measured off the rules in this file rather than guessed:
     28px  the sheet's gap from the bottom of the frame (.la-picker's bottom)
   + 28px  the same gap kept at the top, so a tall sheet never runs off the head of the screen
   + 44px  the sheet's vertical padding (22px twice)
   +  2px  its top and bottom border
   + 28px  the two 14px column gaps between head, tabs and grid
   + 19px  the head row (.la-picker__hint at 12.5px on the page's 1.5 line-height is its tallest)
   + 26px  the tab row (.la-picker__tab's height)
   A wrapped second row of tabs eats into the grid rather than pushing the sheet off-screen, which
   is the right way round. */
.la-picker__grid {
    /* A scroll container is a containing block (fix 447, 19 Sep 2026; see WpPage.razor.css). */
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
    max-height: calc(100dvh - 175px);
    overflow-y: auto;
}

.la-picker__thumb {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 0;
    border: 0;
    background: none;
    font-family: inherit;
    text-align: left;
    color: rgba(255, 255, 255, 0.78);
    cursor: pointer;
}

.la-picker__shot {
    position: relative;
    height: 92px;
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 3px;
    overflow: hidden;
}

.la-picker__thumb[aria-pressed="true"] .la-picker__shot {
    border: 2px solid var(--la-accent);
}

.la-picker__thumb[aria-pressed="true"] {
    color: #FFFFFF;
}

.la-picker__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.la-picker__tick {
    position: absolute;
    right: 7px;
    top: 7px;
    display: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--la-accent);
    color: var(--la-ink);
    font-size: 11px;
    line-height: 18px;
    text-align: center;
}

.la-picker__thumb[aria-pressed="true"] .la-picker__tick {
    display: block;
}

.la-picker__label {
    font-size: 12.5px;
}

.la-notice {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin: 0;
    padding: 12px 14px;
    border: 1px solid var(--la-line);
    border-radius: 3px;
    background: var(--la-warn-bg);
    font-size: 13px;
    color: var(--la-label);
}

.la-notice__close {
    margin-left: auto;
    border: 0;
    background: none;
    padding: 0;
    font-family: inherit;
    font-size: 13px;
    color: var(--la-muted);
    cursor: pointer;
}

/* ── Right: the form panel ─────────────────────────────────────────────────────────────────── */

.la-panel {
    position: relative;
    grid-column: 2;
    grid-row: 1;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 40px;
    padding: 52px 56px;
    background: var(--la-panel-glass);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    transition: background-color 320ms ease;
    overflow-y: auto;
}

/* Aaron: "hover darkens it to white" — the glass settles to solid white under the pointer. Only
   under a pointer: the email field takes focus on load, so a :focus-within trigger had the panel
   white before anyone had moved (fix 365, the conductor's first paint of fix 364), and a phone's
   sticky :hover after a tap would do the same, so the rule exists only where hovering is a thing. */
@media (hover: hover) {
    .la-panel:hover {
        background: var(--la-card);
    }
}

.la-panel__top {
    display: flex;
    flex-direction: column;
    gap: 34px;
}

.la-panel__bottom {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.la-head {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.la-title {
    margin: 0;
    font-family: var(--auth-display);
    font-size: 30px;
    font-weight: 400;
    color: var(--la-ink);
}

.la-lede {
    margin: 0;
    font-size: 14px;
    line-height: 1.55;
    color: var(--la-muted);
    text-wrap: pretty;
}

.la-back {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--la-muted);
}

.la-back::before {
    content: "";
    width: 14px;
    height: 1px;
    background: currentColor;
}

.la-form {
    display: flex;
    flex-direction: column;
    gap: 34px;
    margin: 0;
}

.la-fields {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.la-field {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.la-field__label {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--la-label);
}

.la-field__input {
    height: 48px;
    width: 100%;
    padding: 0 14px;
    border: 1px solid var(--la-line);
    border-radius: 3px;
    background: var(--la-card);
    font-family: inherit;
    font-size: 15px;
    color: var(--la-ink);
}

.la-field__input:focus {
    outline: none;
    border-color: var(--la-ink);
    box-shadow: 0 0 0 3px rgba(16, 21, 28, 0.07);
}

.la-field__input[type="password"] {
    letter-spacing: 0.2em;
}

/* ── A la-field hosting a Wp control (fix 436, 18 Sep 2026) ────────────────────────────────── */

/*  TWO CONTROLS COME ACROSS FROM THE DESIGN SYSTEM, and only two: WpPasswordField and WpOtpInput.
    Every other box on these screens is a plain <input> in the grammar above, because a plain box
    is all the old screen had. These two are different — they carry BEHAVIOUR a visitor would
    notice going missing:

      - WpPasswordField's reveal, and the live five-rule checklist on a password being set. The
        rules are the ones CompleteRegistration/ResetPassword/ChangePassword carried verbatim
        before the design system existed; re-deriving them here would be the copy rule
        (docs/CODE-DOCTRINE.md) broken in the most expensive possible place.
      - WpOtpInput's six boxes: typing advances, Backspace retreats, a paste or a phone's own
        autofill of the whole code splits across them. That is the two-step screen's whole
        ergonomics and it is a hundred lines of script nobody should write twice.

    SO THE PAGES MOUNT THE COMPONENTS AND THIS SHEET SKINS THEM, rather than the components'
    appearance coming across too. This document still links no house stylesheet — not tokens,
    not brand, not base, not the scoped-CSS bundle, not FontAwesome — so what each component
    renders here is its plain, unstyled HTML, and the rules below dress that HTML in the design's
    own grammar. The component root is display: contents, so its label, control and checklist
    become the .la-field's own flex children and sit on the field's 8px rhythm exactly as a
    hand-written label and box would.

    The two collocated scripts (WpPasswordField.razor.js, WpOtpInput.razor.js) are loaded by this
    document, the way the retired _LayoutAuth used to load them (fix 537, 22 Sep 2026). They are
    the only reason the components are here; a page that renders neither pays nothing for them.   */

.la-field .wp-password,
.la-field .wp-otp {
    display: contents;
}

/* base.css declares this and base.css is not linked here, so the sheet declares it — the "*"
   asterisks' "(required)" text and the reveal's own label depend on it. Same recipe as .la-sr. */
.wp-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.la-field .wp-password__label,
.la-field .wp-otp__label {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--la-label);
}

.la-field .wp-password__required,
.la-field .wp-otp__required {
    color: var(--la-accent);
}

.la-field .wp-password__help,
.la-field .wp-otp__help {
    font-size: 12.5px;
    color: var(--la-muted);
}

.la-field .wp-password__control {
    position: relative;
}

.la-field .wp-password__input,
.la-field .wp-otp__input {
    height: 48px;
    width: 100%;
    padding: 0 14px;
    border: 1px solid var(--la-line);
    border-radius: 3px;
    background: var(--la-card);
    font-family: inherit;
    font-size: 15px;
    color: var(--la-ink);
}

.la-field .wp-password__input {
    /* Room for the reveal, which sits inside the box at its right-hand end. */
    padding-right: 116px;
    letter-spacing: 0.2em;
}

.la-field .wp-password__input:focus,
.la-field .wp-otp__input:focus {
    outline: none;
    border-color: var(--la-ink);
    box-shadow: 0 0 0 3px rgba(16, 21, 28, 0.07);
}

/*  THE REVEAL IS A WORD, NOT AN EYE. The component draws a FontAwesome glyph and this document
    links no icon font, so rather than import one for a single control the button shows the label
    it already carries for assistive tech — "Show password", which its own script rewrites to
    "Hide password" on the way in and back again on the way out. One control, one source of truth
    for what it says, and no 300KB of icon font on the sign-in screen. */
.la-field .wp-password__reveal {
    position: absolute;
    right: 1px;
    top: 1px;
    bottom: 1px;
    display: flex;
    align-items: center;
    padding: 0 14px;
    border: 0;
    border-left: 1px solid var(--la-line-soft);
    background: none;
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--la-muted);
    cursor: pointer;
}

.la-field .wp-password__reveal:hover {
    color: var(--la-ink);
}

.la-field .wp-password__reveal i {
    display: none;
}

/* The button's accessible name, shown: it is the only text it has, and it is always current. */
.la-field .wp-password__reveal .wp-sr-only {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
}

/* ── The password checklist ────────────────────────────────────────────────────────────────── */

/*  One list, wherever WpPasswordRulesPlacement puts it — Above on every set-a-password screen, so
    the new and confirm boxes sit together beneath it (Aaron's ruling, 9 Sep 2026: "put both
    beneath the rule checker"). The component's own script toggles .is-met on each rule; the two
    icon glyphs it draws are hidden and a mark is set on the rule itself, so the list reads without
    an icon font. */
.la-field .wp-password__rules {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    margin: 0 0 4px 0;
    padding: 0;
    list-style: none;
    font-size: 12.5px;
    color: var(--la-muted);
}

.la-field .wp-password__rule {
    display: flex;
    align-items: center;
    gap: 7px;
}

.la-field .wp-password__rule i {
    display: none;
}

.la-field .wp-password__rule::before {
    content: "\2022";
    width: 12px;
    text-align: center;
    color: var(--la-faint);
}

.la-field .wp-password__rule.is-met {
    color: var(--la-ink);
}

.la-field .wp-password__rule.is-met::before {
    content: "\2713";
    color: var(--la-accent);
}

/* ── The one-time code boxes ───────────────────────────────────────────────────────────────── */

/*  The component posts ONE field; the six boxes are the enhancement its script draws in front of
    the real input, which goes type="hidden" the moment they appear. A page with no script keeps
    the single box above, still labelled and still working, which is why .wp-otp__input is skinned
    as a full-width field rather than left bare. */
.la-field .wp-otp__boxes {
    display: flex;
    gap: 10px;
}

.la-field .wp-otp__box {
    width: 100%;
    min-width: 0;
    height: 56px;
    padding: 0;
    border: 1px solid var(--la-line);
    border-radius: 3px;
    background: var(--la-card);
    font-family: inherit;
    font-size: 20px;
    text-align: center;
    color: var(--la-ink);
}

.la-field .wp-otp__box:focus {
    outline: none;
    border-color: var(--la-ink);
    box-shadow: 0 0 0 3px rgba(16, 21, 28, 0.07);
}

.la-field .wp-otp__boxes.is-invalid .wp-otp__box {
    border-color: var(--la-bad);
}

/* A field's own message, for the day a page passes one. The summary is still the error surface
   these screens use (the old ones showed no per-field message either). */
.la-field .wp-password__error,
.la-field .wp-otp__error {
    margin: 0;
    font-size: 12.5px;
    color: var(--la-bad);
}

.la-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

/* A row with one link (fix 481, 20 Sep 2026: the sign-in's "Keep me signed in" went) keeps the
   link where it sat - at the row's end. */
.la-row--end { justify-content: flex-end; }

.la-check {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    color: var(--la-label);
}

.la-check input {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--la-ink);
}

.la-link {
    font-size: 14px;
}

.la-do {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.la-submit {
    height: 52px;
    width: 100%;
    border: none;
    border-radius: 3px;
    background: var(--la-ink);
    color: #FFFFFF;
    font-family: inherit;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: 0.04em;
    cursor: pointer;
    position: relative;   /* the busy ring below is placed against the button (fix 484) */
}

.la-submit:hover {
    background: var(--la-ink-hover);
}

.la-submit[disabled] {
    opacity: 0.6;
    cursor: default;
}

/* THE SECOND ACTION (fix 537, 22 Sep 2026 — one of three registers this grammar had no word for
   when the OAuth and error screens joined it). Every screen this document held until today had
   ONE action, so .la-submit was the whole button register and the house rule — one primary action
   per surface — needed no second half to express. The consent screen has two: a person deciding
   whether a connector may read their wealth data must be able to refuse in the same place they
   agree. The quiet one is the same geometry with the ink as an outline rather than a fill, which
   is what btn-outline-secondary said before fix 375 and WpButton's Secondary variant after it.
   Its busy ring is the ink's, because the rule below paints a white one for a white-on-navy
   button and signin.js sets aria-busy on every submit button in the form it guards. */
.la-submit--quiet {
    background: transparent;
    border: 1px solid var(--la-line);
    color: var(--la-ink);
}

.la-submit--quiet:hover {
    background: var(--la-card);
    border-color: var(--la-ink);
}

.la-submit--quiet[aria-busy="true"]::after {
    border-color: var(--la-line);
    border-top-color: var(--la-ink);
}

/* THE BUSY RING (fix 484, Aaron, 20 Sep 2026: "Used to have a spinner icon on logon button
   clicked, bring it back?"). signin.js has disabled the button and set aria-busy on it at submit
   since the chunk-1 facelift; nothing drew that state. This document links no icon font by
   design (see _LayoutSignIn), so the ring is CSS: the word gives way to a turning ring the
   button's own height allows, on Continue here and on the 2FA step, which share the class. The
   state is the attribute the script already writes, so the script is untouched. */
.la-submit[aria-busy="true"] {
    color: transparent;
    opacity: 1;
}

.la-submit[aria-busy="true"]::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: la-spin 0.8s linear infinite;
}

@keyframes la-spin {
    to { transform: rotate(360deg); }
}

.la-note {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--la-muted); /* fix 368: --la-faint read as marginal on the 0.6 glass over a dark backdrop */
}

/* ── A standing block of paper, and the list it holds ──────────────────────────────────────── */

/* FIX 537, 22 Sep 2026 — the other two registers the OAuth screens needed and this grammar had no
   word for. The consent screen states what a connector will be allowed to do, as a list, and that
   list is neither an error (.la-alert, which wears the failure rule down its left edge) nor a note
   (.la-note, which is the small grey aside under a form). It is the one thing on the screen a
   person is being asked to read before they decide, so it takes the card colour the alert borrows
   for its own ground — paper, on the glass panel — with no status edge on it.

   .la-scopes is the list inside: no bullet, a drawn tick instead, because this document links no
   icon font (see _LayoutSignIn's header) and the FontAwesome check-circle the screen carried
   before fix 537 had nothing to load it. The mark is CSS, so it is decoration the accessibility
   tree never sees, which is what the aria-hidden on the old <i> was asking for anyway. */
.la-card {
    padding: 16px 18px;
    border: 1px solid var(--la-line-soft);
    border-radius: 3px;
    background: var(--la-card);
}

.la-card__title {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--la-label);
}

.la-scopes {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
    color: var(--la-ink);
}

.la-scopes li {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.la-scopes li::before {
    content: "\2713";
    color: var(--la-accent);
    font-size: 13px;
    line-height: 1;
}

/* ── The error surface ─────────────────────────────────────────────────────────────────────── */

.la-alert {
    margin: 0;
    padding: 14px 16px;
    border: 1px solid var(--la-line);
    border-left: 3px solid var(--la-bad);
    border-radius: 3px;
    background: var(--la-card);
    font-size: 14px;
    color: var(--la-ink);
}

.la-alert--warn {
    border-left-color: var(--la-accent);
    background: var(--la-warn-bg);
}

.la-alert__list {
    margin: 0;
    padding-left: 18px;
}

/* ── The foot of the panel ─────────────────────────────────────────────────────────────────── */

.la-apps {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* Fix 364: the live footer's store badges (131x39 PNGs) at their natural height. */
.la-app {
    display: block;
    line-height: 0;
    border-radius: 6px;
}

.la-app:hover {
    opacity: 0.88;
}

.la-app:focus-visible {
    outline: 2px solid var(--la-ink);
    outline-offset: 2px;
}

.la-app__badge {
    display: block;
    height: 39px;
    width: auto;
}

.la-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding-top: 20px;
    border-top: 1px solid var(--la-line-soft);
    font-size: 12px;
    color: var(--la-muted); /* fix 368: as .la-note */
}

/* Fix 535 (Aaron, 22 Sep 2026: "the copyright text finovate should be a link in new tab"). The
   credit line is a credit, not a call to action, so the anchor keeps the footer's quiet ink
   rather than taking the sheet's link brown, and earns its underline on hover — the same
   restraint the live footer's company name has always had. */
.la-foot a {
    color: inherit;
    text-decoration: none;
}

.la-foot a:hover,
.la-foot a:focus-visible {
    color: var(--la-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ── The phone register: one card, hero over form (fix 436) ────────────────────────────────── */

/*  Under 48rem the two panels stack. Conductor ruling 6 (16 Sep 2026) wrote the first version of
    this block without a drawing to follow — the design's three artboards are fixed at 1240x780 —
    and Aaron sent the phone mock on 18 Sep 2026, so the stack below is now a drawing being
    followed rather than an answer invented for it. What the mock changed, and what it confirmed:

      CONFIRMED, so the rules are the ones ruling 6 already wrote — the hero on top with the
      photograph behind it, the brand lockup at its top-left, the tagline and the "— WEALTH PORTAL"
      eyebrow at its bottom-left, the form beneath on the light ground with its uppercase labels,
      full-width boxes, the checkbox-and-link row, the full-width dark button, the ruled footer.

      CHANGED — the whole thing is now ONE CARD with rounded corners floating on the ground rather
      than a full-bleed stack; the backdrop button is a square icon at the hero's TOP-RIGHT rather
      than a labelled chip at its bottom-right; the video does not play on a phone (the still it
      already carries as a poster is the hero image the mock draws); the app-store strip is not on
      the phone at all; and the backdrop picker is a bottom sheet over the card rather than a panel
      inside the banner that made the banner grow.

      NOT DRAWN HERE — the mock's second, outlined "Sign in with Face ID" button. This page offers
      no such sign-in (there is no WebAuthn, passkey or biometric path anywhere in the web app), so
      a button for it would do nothing; it is omitted rather than drawn dead.                     */

@media (max-width: 48rem) {
    /* The ground shows around the card on all four sides. */
    .la-page {
        padding: 12px;
    }

    .la-frame {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto minmax(0, 1fr);
        min-height: calc(100dvh - 24px);
        border-radius: 14px;
        /* The hero's photograph is the card's own top corners — the backdrop is clipped by the
           card rather than bleeding past it. */
        overflow: hidden;
    }

    /* The backdrop keeps to the hero's row, so the photograph is composed for the hero. */
    .la-backdrop {
        grid-column: 1;
        grid-row: 1;
    }

    /* A phone gets the still, not the film: the mock draws a photographic hero, and a looping
       video behind a form is a data bill and a battery cost for a picture that does not move in
       the drawing. The <video> already carries this same still as its poster, so there is nothing
       to load that was not loading anyway. */
    .la-backdrop__video {
        display: none;
    }

    .la-media {
        grid-column: 1;
        grid-row: 1;
        /* "Top half is the hero" — a share of the screen rather than a fixed band, so the picture
           keeps its proportion on a small phone and a large one alike. */
        min-height: 40dvh;
    }

    .la-media__inner {
        padding: 22px 20px;
        gap: 16px;
    }

    .la-tagline {
        font-size: 24px;
    }

    /* No pointer to hover with and nothing behind the panel but the card: solid, and no blur
       for a phone to pay for. */
    .la-panel {
        grid-column: 1;
        grid-row: 2;
        gap: 32px;
        padding: 32px 20px 40px 20px;
        background: var(--la-panel);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
        overflow-y: visible;
    }

    /* The store badges are the desktop panel's foot. A phone visitor is already on the phone the
       badges would send them to, and the mock's footer is the rule, the credit and "Need help?"
       and nothing else. */
    .la-apps {
        display: none;
    }

    /* iOS Safari zooms the whole page when a focused input is under 16px, and the design's 15px
       box sits exactly the wrong side of that line. A point bigger on a phone, nowhere else. */
    .la-field__input {
        font-size: 16px;
    }

    /* The trigger is a square in the hero's top-right corner, the bars alone. */
    .la-backdrop-btn {
        top: 12px;
        right: 12px;
        bottom: auto;
        justify-content: center;
        width: 34px;
        padding: 0;
        border-radius: 3px;
    }

    /* Hidden from the eye, not from the accessibility tree — the icon button still announces
       itself as "Backdrop". Same recipe as .la-sr. */
    .la-backdrop-btn__text {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    /* ── The picker is a bottom sheet ──────────────────────────────────────────────────────── */

    /*  It rises over the card from the bottom of the SCREEN, so it is fixed rather than absolute:
        the banner no longer has to grow to hold it (the :has() rule that did that is gone with
        this), and the sheet is the same height whatever the hero is doing. Its own rule already
        sets display: flex and the [hidden] override at the foot of this file still wins over it
        (fix 363), so the script goes on toggling one attribute and knowing nothing about layout. */
    .la-picker {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        top: auto;
        z-index: 5;
        padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
        gap: 12px;
        border-width: 1px 0 0 0;
        border-radius: 14px 14px 0 0;
    }

    /* The drag handle the mock draws above the heading. It is decoration — the sheet is dismissed
       by its own button and by Escape, never by a drag — so it is drawn rather than marked up. */
    .la-picker::before {
        content: "";
        width: 36px;
        height: 4px;
        margin: 0 auto 4px auto;
        border-radius: 2px;
        background: rgba(255, 255, 255, 0.34);
    }

    /* The head stops being a box so its two halves can be ordered independently: the heading keeps
       its own line, and the Close button drops to the foot of the sheet as the mock's full-width
       action. Explicit orders, because a contents-child's order is read from the sheet. */
    .la-picker__head {
        display: contents;
    }

    .la-picker__heading {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 12px;
        order: 1;
    }

    .la-picker__tabs {
        order: 2;
    }

    .la-picker__grid {
        order: 3;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        /*  The sheet's own chrome, measured off the rules above rather than guessed:
              12px  the gap kept between the top of the sheet and the top of the screen
            + 32px  the sheet's vertical padding (16px twice; the bottom one plus any safe area)
            +  1px  its top border
            + 36px  the three 12px gaps between handle, heading, tabs, grid and button
            +  8px  the drag handle and its margin
            + 19px  the heading row (.la-picker__hint at 12.5px on the page's 1.5 line-height)
            + 26px  the tab row (.la-picker__tab's height)
            + 46px  the full-width Close button and the gap above it                              */
        max-height: calc(100dvh - 180px);
    }

    .la-picker__close {
        order: 4;
        height: 46px;
        padding: 0;
        border-radius: 3px;
        background: var(--la-ink);
        color: #FFFFFF;
    }

    .la-picker__close:hover {
        background: var(--la-ink-hover);
        color: #FFFFFF;
    }
}

/* The video is decoration; a visitor who has asked for less motion keeps the still. */
@media (prefers-reduced-motion: reduce) {
    .la-backdrop__video {
        display: none;
    }

    .la-panel {
        transition: none;
    }

    /* The busy ring holds still: a static ring is still "working", without the motion. */
    .la-submit[aria-busy="true"]::after {
        animation: none;
    }
}

/* Fix 363 (conductor's first paint of /login-alt on 5029, 16 Sep 2026): the picker opened by
   itself on every load. Its own rule sets display: flex, and an author display beats the
   browser's [hidden] { display: none } — so the hidden attribute the page and the script toggle
   was being ignored. The attribute wins again. */
.la-picker[hidden] {
    display: none;
}

/* Fix 366 (Aaron, 16 Sep 2026: "backdrop selector is not great" — a screenshot of every group's
   grid showing at once, each scrolling on its own): the same slip one level down. The group grid
   sets display: grid, so the hidden attribute the tab script toggles was being ignored and all
   the groups stacked up. The attribute wins again, and only the chosen tab's group shows. */
.la-picker__grid[hidden] {
    display: none;
}
