/* ==========================================================================
   SIGN-IN LANES  —  the two doors into the portal
   --------------------------------------------------------------------------
   Author: Sharmila Parthiban.  2 Sep 2026.

   THERE ARE TWO KINDS OF SIGN-IN AND THEY ARE FOR DIFFERENT PEOPLE.
   MDE and county staff sign in with their Maryland state account through
   Microsoft Entra. Everybody else -- drillers, homeowners, contractors --
   signs in with a portal password they registered for. That is not two ways
   to do one thing, it is two separate doors, and the previous login page
   presented it as one form with a button bolted above it. Somebody reading
   that page had to work out which one applied to them from a sentence of
   hint text. These rules give each route its own card, its own colour and
   its own explanation, so the answer to "which one am I?" is visible before
   anything is typed.

   ONE FILE, INCLUDED BY BOTH PAGES, so the two doors look identical wherever
   a visitor meets them:
       Views/Account/Login.cshtml   (on _PrototypeLayout)
       Views/Home/Index.cshtml      (on _Layout)

   ========== WHY EVERY VALUE BELOW HAS A FALLBACK ==========================
   Those two views are on DIFFERENT LAYOUTS with different stylesheets, and
   that is deliberate -- Views/Account/_ViewStart.cshtml explains why. The
   consequence for this file is concrete and easy to get wrong:

       tokens.css is loaded by _Layout ONLY.
       _PrototypeLayout has its OWN token block (prototype-final.css:161),
       which defines --c-primary, --c-ink, --focus-ring ... and does NOT
       define --sp-*, --fs-*, --radius-*, --shadow-* or --border-1.

   So `padding: var(--sp-3)` would silently collapse to nothing on the login
   page while looking correct on the landing page. An undefined custom
   property is not an error and leaves no trace anywhere to find it by.

   Everything is therefore mapped ONCE into local --ln-* properties on .lanes,
   each with the tokens.css value as its fallback. One place to maintain, and
   the component renders correctly under either layout.

   Where a token exists under BOTH layouts with different values -- --c-primary
   is #005ea2 in tokens.css and #1e40af in the prototype's block -- the lane
   takes the host page's value on purpose. Matching the page it sits on is the
   point; a hard-coded blue would make the component the one element on each
   page that belongs to neither design.

   TWO TOKENS THAT ARE SHORTHAND VALUES, NOT COLOURS. --border-1 is the whole
   declaration '1px solid #a9aeb1' and --focus-ring is a two-layer box-shadow.
   So it is `border: var(--ln-border)`, never `border: 1px solid ...`, and
   `box-shadow: var(--ln-focus)`, never `outline: var(--ln-focus)`. Both wrong
   forms parse as invalid and are DROPPED SILENTLY -- which in the focus case
   removes the visible focus indicator, an accessibility regression with no
   error message attached to it.

   NO TYPEFACE IS NAMED HERE. Both layouts already set one on <body>, and they
   are not the same declaration. Inheriting means this component can never be
   the reason a page shows a third family. The only exception is .lane__btn:
   <button> does not inherit font by default, so it is told to.

   NO ROLE PICKER, EVER. These cards choose a SIGN-IN METHOD. They do not
   choose a role, and no lane may ever gain a role control -- role comes from
   the signed cookie and CONFIG.UiFeatureRole, never from the browser. See the
   longer note in Views/Home/Index.cshtml.
   ========================================================================== */

/*  THE WIDTH OF THE SIGN-IN BLOCK, IN ONE PLACE. Reduced from 66rem to 54rem on
    3 Sep 2026 at the user's request ("reduce width of login").

    ON :root RATHER THAN ON .lanes, deliberately. Three separate rules need this
    number — .lanes, .lanes-wrap and .lanes-hd — and the latter two are SIBLINGS
    of .lanes, not descendants, so a custom property declared on .lanes would not
    reach them and two of the three would silently keep the old value. They must
    agree exactly: the notices and the heading above the cards are aligned to the
    card edges, and a mismatch shows up as a heading visibly off-centre relative
    to the boxes underneath it.

    WHY 54rem AND NOT LESS: the grid is repeat(auto-fit, minmax(19rem, 1fr)), so
    two lanes need 19 + 19rem plus the 1.5rem gap = 39.5rem before auto-fit drops
    them to one stacked column. 54rem leaves each lane about 26rem (~420px) —
    comfortable for the email and password fields — and keeps real headroom above
    the collapse point, so a browser at 125% zoom still shows two lanes side by
    side instead of suddenly reflowing. Much below 44rem and the two-column
    layout starts collapsing at ordinary zoom levels. */
:root {
    --ln-maxw: 54rem;
}

.lanes {
    /* ---- tokens in, with tokens.css values as the fallbacks -------------- */
    --ln-sp-05: var(--sp-05, 0.25rem);
    --ln-sp-1: var(--sp-1, 0.5rem);
    --ln-sp-15: var(--sp-15, 0.75rem);
    --ln-sp-2: var(--sp-2, 1rem);
    --ln-sp-3: var(--sp-3, 1.5rem);
    --ln-sp-4: var(--sp-4, 2rem);

    --ln-fs-2xs: var(--fs-2xs, 0.875rem);
    --ln-fs-xs: var(--fs-xs, 0.9375rem);
    --ln-fs-sm: var(--fs-sm, 1rem);
    --ln-fs-lg: var(--fs-lg, 1.375rem);

    --ln-ink: var(--c-ink, #1b1b1b);
    --ln-ink-muted: var(--c-ink-muted, #565c65);
    --ln-paper: var(--c-paper, #ffffff);
    --ln-paper-sunken: var(--c-paper-sunken, #f9f9f9);

    --ln-radius: var(--radius-lg, 8px);
    --ln-radius-sm: var(--radius-md, 4px);
    --ln-border: var(--border-1, 1px solid #a9aeb1);
    --ln-shadow: var(--shadow-1, 0 1px 2px rgba(0, 0, 0, .10));
    --ln-shadow-lift: var(--shadow-2, 0 2px 6px rgba(0, 0, 0, .14));
    --ln-focus: var(--focus-ring, 0 0 0 2px #ffffff, 0 0 0 6px #2491ff);

    /* ---- layout ---------------------------------------------------------- */
    /*  auto-fit, not a fixed 1fr 1fr. When Entra is not configured on an
        instance the staff lane is not rendered at all, and auto-fit collapses
        to a single full-width card without needing a second rule or a count
        the view would have to pass in. */
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
    gap: var(--ln-sp-3);
    align-items: stretch;

    /*  Capped and centred. Two cards stretched across a 1600px page put the
        email field and the state-account button a screen apart. The value is
        --ln-maxw on :root — see the note above this rule. */
    max-width: var(--ln-maxw);
    margin: 0 auto;
}

/* ------------------------------------------------------------------- lane */

.lanes .lane {
    /*  --ln-accent is set by the --staff / --public modifiers below and is
        used by the top bar, the icon, the button and the list ticks, so each
        lane is one colour decision rather than five. */
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--ln-sp-3);
    background: var(--ln-paper);
    border: var(--ln-border);
    border-radius: var(--ln-radius);
    box-shadow: var(--ln-shadow);
    color: var(--ln-ink);
}

/*  The accent bar. A pseudo-element rather than border-top so it can sit
    inside the rounded corners instead of squaring them off. */
.lanes .lane::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 4px;
    background: var(--ln-accent);
    border-radius: var(--ln-radius) var(--ln-radius) 0 0;
}

.lanes .lane--staff {
    --ln-accent: var(--c-primary-darker, #162e51);
    --ln-accent-bg: var(--c-primary-lighter, #d9e8f6);
}

.lanes .lane--public {
    --ln-accent: var(--c-primary, #005ea2);
    --ln-accent-bg: var(--c-paper-alt, #f0f0f0);
}

/* ---- lane head ----------------------------------------------------------- */

.lanes .lane__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    margin-bottom: var(--ln-sp-15);
    background: var(--ln-accent-bg);
    color: var(--ln-accent);
    border-radius: var(--ln-radius-sm);
    font-size: var(--ln-fs-sm);
    /*  flex-shrink guard: the icon is a fixed square and must not be squeezed
        into an oval when the card is narrow. */
    flex: 0 0 auto;
}

.lanes .lane__eyebrow {
    margin: 0 0 var(--ln-sp-05);
    font-size: var(--ln-fs-2xs);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ln-accent);
}

.lanes .lane__title {
    margin: 0 0 var(--ln-sp-1);
    font-size: var(--ln-fs-lg);
    font-weight: 600;
    line-height: var(--lh-tight, 1.25);
    color: var(--ln-ink);
}

.lanes .lane__lede {
    margin: 0 0 var(--ln-sp-2);
    font-size: var(--ln-fs-xs);
    line-height: var(--lh-normal, 1.55);
    color: var(--ln-ink-muted);
}

/* ---- the "what this gets you" list -------------------------------------- */

.lanes .lane__facts {
    margin: 0 0 var(--ln-sp-2);
    padding: 0;
    list-style: none;
    font-size: var(--ln-fs-xs);
    line-height: var(--lh-snug, 1.4);
    color: var(--ln-ink-muted);
}

.lanes .lane__facts li {
    position: relative;
    padding-left: 1.5rem;
    margin-bottom: var(--ln-sp-1);
}

/*  A tick drawn as text, not an icon font. FontAwesome is loaded by both
    layouts today, but a list marker that vanishes when an icon font fails to
    load takes the indentation with it and leaves the text hanging. */
.lanes .lane__facts li::before {
    content: "\2713";
    position: absolute;
    left: 0;
    top: 0;
    color: var(--ln-accent);
    font-weight: 700;
}

/* ---- fields, when a lane contains a real form --------------------------- */

/*  BOTH lanes now hold a real form: the login page's password lane always did,
    and the landing page's does too since the email/password prompt moved onto
    the front door.
    ------------------------------------------------------------------------
    WHY SOME FIELD PRIMITIVES ARE DECLARED HERE AFTER ALL.

    This section used to say that .lbl, .inp and .pwmask "come from the host
    layout's stylesheet and are not restyled here". That was true of ONE host
    layout and false of the other, and putting the form on the landing page is
    what exposed it:

      * .inp IS declared for both -- tokens.css for _Layout, prototype-final.css
        for _PrototypeLayout. Still not restyled here, for the original reason:
        an input that looks different inside a lane from every other input in
        the application is a worse outcome than a slightly plainer card.

      * .lbl and .hint exist ONLY in prototype-final.css. _Layout loads eight
        stylesheets and not one of them declares either, so a label on the
        landing page rendered as unstyled inline text with no weight, no colour
        and no line of its own -- the input appeared to belong to the paragraph
        above it.

      * .pwmask / .pwmask__btn exist only in prototype-account.css, which
        _Layout does not load, so the Show button rendered as bare text beside
        the field.

    So the three that are MISSING on one layout are declared here, scoped under
    .lanes, at the SAME VALUES prototype-final.css uses. Scoping under .lanes is
    what keeps this file's promise: nothing outside a sign-in lane is restyled
    on either layout.

    THE ONE KNOWN SIDE EFFECT, accepted deliberately. `.lanes .lbl` is (0,2,0)
    and prototype-final.css's `.lbl` is (0,1,0), so these rules also win on the
    LOGIN page, where prototype-final.css was previously the only voice. The
    values are copied from it, with one difference: --fs-floor and --fs-micro are
    prototype-only tokens that do not exist on _Layout, so the --ln-* mappings
    stand in. That nudges a login-page label from 13px to 14px. Two pages
    agreeing at 14px is better than the same component rendering at two sizes
    depending on which door the reader came through.

    Only the spacing between fields was ever this file's own business, and that
    part is unchanged. */
.lanes .lane__field {
    margin-bottom: var(--ln-sp-2);
}

/*  display:block is the load-bearing half. A <label> is inline by default, so
    without it the label, the asterisk, the "(required)" hint and the input all
    ran together on one line. */
.lanes .lbl {
    display: block;
    margin-bottom: var(--ln-sp-05);
    font-size: var(--ln-fs-2xs);
    font-weight: 600;
    color: var(--ln-ink);
}

/*  The required asterisk. #b50909 is the same red every validation message in
    the application uses (prototype-account.css's .field-validation-error), so
    "this is required" and "this was wrong" are one colour rather than two.
    It is aria-hidden in the markup -- the word "(required)" beside it is what
    a screen reader announces, because an asterisk is read as "star". */
.lanes .lbl .req {
    color: #b50909;
    margin-left: .15rem;
}

/*  "(required)" and any other short qualifier. Lighter and smaller than the
    label it sits inside, so the field's NAME still reads first. */
.lanes .hint {
    font-weight: 400;
    font-size: var(--ln-fs-2xs);
    line-height: var(--lh-snug, 1.4);
    color: var(--ln-ink-muted);
}

/*  THE PASSWORD UNMASK CONTROL. Copied from prototype-account.css at the same
    values so the button is the same object on both pages; it is wired by
    prototype-chrome.js, which _PrototypeLayout loads for every page and which
    the landing page now loads in its Scripts section.

    align-items:stretch, not center: the button matches the input's HEIGHT
    rather than being vertically centred against it, which is what stops it
    reading as a separate control that happens to sit nearby. */
.lanes .pwmask {
    display: flex;
    align-items: stretch;
    gap: .4rem;
}

.lanes .pwmask > .inp {
    flex: 1 1 auto;
    /*  min-width:0 on a flex item that is a text input. Without it the input
        refuses to shrink below its default ~20ch and pushes the button out of
        the card on a narrow phone. */
    min-width: 0;
}

.lanes .pwmask__btn {
    flex: 0 0 auto;
    border: 1px solid var(--c-line, #a9aeb1);
    background: var(--ln-paper-sunken);
    color: var(--c-primary, #005ea2);
    border-radius: var(--ln-radius-sm);
    padding: 0 .6rem;
    font: inherit;
    font-size: var(--ln-fs-2xs);
    font-weight: 700;
    cursor: pointer;
    /*  The label flips between "Show" and "Hide", which are different widths;
        nowrap stops the shorter one breaking mid-word in a narrow card. */
    white-space: nowrap;
}

.lanes .lane__field:last-of-type {
    margin-bottom: var(--ln-sp-15);
}

.lanes .lane__check {
    display: flex;
    align-items: flex-start;
    gap: var(--ln-sp-1);
    margin-bottom: var(--ln-sp-1);
    font-size: var(--ln-fs-xs);
    font-weight: 400;
    color: var(--ln-ink);
}

.lanes .lane__check input {
    /*  Nudged down onto the first line's baseline. A checkbox top-aligned
        against a two-line label reads as belonging to nothing. */
    margin-top: .2rem;
    flex: 0 0 auto;
}

.lanes .lane__hint {
    margin: 0 0 var(--ln-sp-2);
    font-size: var(--ln-fs-2xs);
    line-height: var(--lh-snug, 1.4);
    color: var(--ln-ink-muted);
}

/* ---- actions ------------------------------------------------------------- */

/*  margin-top:auto pins the actions to the bottom of the card, so the two
    lanes' primary buttons line up with each other however much prose is
    above them. Without it the state-account button floats halfway up beside
    a form four fields tall. */
.lanes .lane__acts {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: var(--ln-sp-1);
}

/*  THE STAFF LANE OPTS OUT OF THE BOTTOM PIN. Its only content above the button
    is the eyebrow, title, lede and the short "what you get" list — no form — so
    margin-top:auto stranded the state-account button at the bottom of the card
    with a wide empty gap above it, aligned to the password lane's button four
    fields down. That put the button far from the text explaining it and, on a
    short viewport, below the fold. A fixed top margin lets it sit directly under
    its list. The password lane KEEPS the pin: its form fills the card, so its
    button is at the foot either way, and the two no longer need to line up now
    that the staff button follows its own content instead. (0,3,0) out-specifies
    the (0,2,0) rule above.  Requested 8 Sep 2026 — "place it close to the text". */
.lanes .lane--staff .lane__acts {
    margin-top: var(--ln-sp-2);
}

/*  A lane's action may be wrapped in a <form> -- the state-account lane's button
    has to be a POST with an antiforgery token, it cannot be a link. The form is
    then the flex item and the button inside it is only as wide as its label,
    which puts a narrow button next to a full-width one in the other lane.
    Stretching the button here rather than with an inline style keeps the
    partial free of layout. display:contents on the <form> would be tidier and
    is not used deliberately: it has a history of breaking form submission and
    accessibility mapping in shipping browsers. */
.lanes .lane__acts > form {
    margin: 0;
}

.lanes .lane__acts > form > .lane__btn {
    width: 100%;
}

.lanes .lane__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ln-sp-1);
    /*  2.75rem = 44px, the WCAG 2.5.8 target minimum, held by min-height
        rather than by padding so a long label cannot shrink it. */
    min-height: 2.75rem;
    padding: var(--ln-sp-1) var(--ln-sp-2);
    border: 2px solid transparent;
    border-radius: var(--ln-radius-sm);
    font-family: inherit;
    font-size: var(--ln-fs-sm);
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}

.lanes .lane__btn--primary {
    background: var(--ln-accent);
    border-color: var(--ln-accent);
    color: #fff;
}

.lanes .lane__btn--primary:hover {
    /*  Darkened with a colour-mix over the accent instead of a second token,
        so it follows whichever --c-primary the host layout supplied. The
        fallback is the unhovered accent: no hover feedback is a cosmetic
        loss, a wrong colour is a visible defect. */
    background: color-mix(in srgb, var(--ln-accent) 85%, #000);
    border-color: color-mix(in srgb, var(--ln-accent) 85%, #000);
    color: #fff;
}

.lanes .lane__btn--outline {
    background: var(--ln-paper);
    border-color: var(--ln-accent);
    color: var(--ln-accent);
}

.lanes .lane__btn--outline:hover {
    background: var(--ln-accent-bg);
    color: var(--ln-accent);
}

.lanes .lane__btn--quiet {
    background: transparent;
    border-color: transparent;
    color: var(--ln-accent);
    font-weight: 500;
    min-height: 2.25rem;
    text-decoration: underline;
}

.lanes .lane__btn--quiet:hover {
    background: var(--ln-paper-sunken);
}

/*  box-shadow, because --focus-ring IS a box-shadow (see the header). The
    transparent outline is kept deliberately: in Windows High Contrast mode
    box-shadows are not painted, and this is what carries the focus indicator
    there -- forced-colors turns a transparent outline opaque. */
.lanes .lane__btn:focus-visible {
    outline: 3px solid transparent;
    outline-offset: 0;
    box-shadow: var(--ln-focus);
}

/* ---- lane foot ----------------------------------------------------------- */

.lanes .lane__foot {
    margin-top: var(--ln-sp-2);
    padding-top: var(--ln-sp-2);
    border-top: var(--ln-border);
    font-size: var(--ln-fs-2xs);
    line-height: var(--lh-snug, 1.4);
    color: var(--ln-ink-muted);
}

.lanes .lane__foot p {
    margin: 0 0 var(--ln-sp-1);
}

.lanes .lane__foot p:last-child {
    margin-bottom: 0;
}

.lanes .lane__foot a {
    color: var(--ln-accent);
    font-weight: 600;
}

/* ==========================================================================
   THE HEADING BLOCK ABOVE THE LANES
   Shared so the landing page's sign-in section and the login page's own
   header are the same shape. Not nested under .lanes because it is a sibling
   of it, so these three selectors are prefixed instead.
   ========================================================================== */

/*  The wrapper the login page uses instead of .acct. .acct caps at 34rem — it
    was written for a single stacked column — and two lanes inside it would be
    forced into one column on every screen size, which is the layout this
    change exists to replace. Kept to the SAME --ln-maxw as .lanes so the notices
    above the cards line up with their edges rather than running the full
    width of a 1600px page. Both read the one custom property precisely so they
    cannot drift apart in a later edit. */
.lanes-wrap {
    max-width: var(--ln-maxw);
    margin: 0 auto;
}

.lanes-hd {
    max-width: var(--ln-maxw);
    margin: 0 auto var(--sp-3, 1.5rem);
    text-align: center;
}

.lanes-hd h1,
.lanes-hd h2 {
    margin: 0 0 var(--sp-1, 0.5rem);
    line-height: var(--lh-tight, 1.25);
}

/*  CENTRING A CAPPED PARAGRAPH NEEDS BOTH HALVES.
    tokens.css:148 caps every <p> at --maxw-prose (68ch) with no auto margins.
    Because ch resolves against the element's OWN font-size, the small uppercase
    eyebrow came out ~508px wide inside a 1056px centred head — a narrow block
    sitting flush left, so its centred text landed nowhere near the heading above
    the lanes. Measured on the landing page at 1200px.

    Fixed here rather than by loosening the global rule, which is correct for body
    copy. margin-inline:auto centres any capped paragraph in this block; the
    eyebrow additionally drops the cap, because a measure limit on a single short
    line of tracked capitals only ever misaligns it.

    Worth knowing: this affects the LANDING page only. tokens.css is not loaded by
    _PrototypeLayout, so the login page's identical markup never had the cap —
    the same two-layout divergence that gives every value in this file a
    fallback. */
.lanes-hd > p {
    margin-inline: auto;
}

.lanes-hd .lp-eyebrow {
    max-width: none;
}

.lanes-hd__lede {
    /*  Measure-capped and centred. A centred paragraph running the full width
        of a 1600px page is unreadable no matter how good the type is. */
    max-width: 52ch;
    margin: 0 auto;
    font-size: var(--fs-sm, 1rem);
    line-height: var(--lh-normal, 1.55);
    color: var(--c-ink-muted, #565c65);
}

/* ==========================================================================
   NARROW SCREENS
   The grid already reflows to one column at 19rem per card; these are the
   adjustments that reflow alone does not give.
   ========================================================================== */

@media (max-width: 40rem) {
    .lanes {
        gap: var(--ln-sp-2);
    }

    .lanes .lane {
        padding: var(--ln-sp-2);
    }

    /*  Stacked, the second card is below the fold and the accent bar is the
        only thing announcing a new card has started, so it is thickened. */
    .lanes .lane::before {
        height: 6px;
    }

    .lanes-hd {
        text-align: left;
    }

    /*  `.lanes-hd > p`, not `.lanes-hd__lede`. The centring rule above is written
        as `.lanes-hd > p` (0,1,1), which OUT-SPECIFIES a bare class selector
        (0,1,0) even from inside a media query — a media query changes when a rule
        applies, never how strongly. Written as the class it lost, and the lede
        stayed auto-centred while the heading beside it went flush left, leaving
        the paragraph indented by about 40px for no reason. */
    .lanes-hd > p {
        margin-inline: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lanes .lane__btn {
        transition: none;
    }
}
