/* The signed-out pages, redrawn from the 2026-09-14 mockups.
 *
 * Loaded by default.aspx, passwordRecovery.aspx, Blocked.aspx, Error.aspx and
 * termsandconditions.aspx -- every page a user can reach before signing in. They are one surface
 * to that user, and a tenant branded on the login but not on the page its "Forgot my password"
 * link leads to looks broken rather than white-labelled.
 *
 * Common.css and login.css still dress the SIGNED-IN app, so nothing here may be moved into them.
 *
 * The tenant's own values arrive as custom properties written onto .dbl by the markup, from
 * VoyagerThemeJsonLoginPage. Everything else is the same for every tenant by design -- the 38
 * live tenant stylesheets vary a logo, its box, and almost nothing else.
 *
 * Shared component vocabulary (buttons, inputs, tokens) comes from Content/ClientUi/datablaze.ui.css,
 * which this file loads after and is free to specialise. */

/* ================================================================================================
   Undoing the legacy page chrome.

   The markup still hangs off asp:Panel / asp:Table / asp:TableCell, because LoginCell is toggled
   by name from the code-behind and retyping it would mean hand-editing the generated designer
   file. They are laid out as if they were not there.
   ================================================================================================ */

body.loginBody {
    margin: 0;
    background: var(--dbl-ground, #211F1E);
    font-family: var(--dz-font-family, 'Poppins', 'Roboto', 'Segoe UI', Arial, sans-serif);
}

body.loginBody > form,
body.loginBody .loginImage,
body.loginBody .loginImage > tbody,
body.loginBody .loginImage > tbody > tr,
body.loginBody .loginImage > tbody > tr > td {
    display: block;
    width: auto;
    height: auto;
    padding: 0;
    margin: 0;
    border: 0;
    text-align: initial;
    vertical-align: initial;
}

/* ================================================================================================
   The page.
   ================================================================================================ */

.dbl {
    position: relative;
    overflow: hidden;
    min-height: 100vh;
    min-height: 100dvh;
    box-sizing: border-box;
    padding: var(--dbl-gap-top) 24px var(--dbl-gap-bottom);
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Top-anchored, not centred. The glow's bright core sits at the very top of the page and the
       mark is composed inside it; centring on a tall window drops the mark 70px out of it.
       MEASURED at 1440x1000: centred puts the column at 166px, the mockup puts it at 96px. */
    background: var(--dbl-ground);
    font-family: var(--dz-font-family, 'Poppins', 'Roboto', 'Segoe UI', Arial, sans-serif);
}

/* Freshchat injects #fc_frame as a static block until its own css lands; keep it out of flow so
   the viewport-tall page never overflows for those ~150 ms. Only position is set: an id selector
   here would outrank Freshchat's own right and bottom offsets. */
body.loginBody > #fc_frame {
    position: fixed;
}

/* A wash of the tenant's accent behind the mark. Its intensity is a separate answer from its
 * colour: a saturated red at the strong scale swamps a light ground, which is why the CM Tech
 * mockup runs a third of Periscope's. */
.dbl__glow {
    position: absolute;
    top: -320px;
    left: 50%;
    transform: translateX(-50%);
    width: 1400px;
    height: 760px;
    pointer-events: none;
    background: radial-gradient(ellipse at 50% 0%,
        rgba(var(--dbl-glow), var(--dbl-glow-near)) 0%,
        rgba(var(--dbl-glow), var(--dbl-glow-far)) 38%,
        rgba(var(--dbl-glow), 0) 70%);
}

.dbl__rule {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    pointer-events: none;
    background: linear-gradient(90deg,
        rgba(253, 213, 1, 0) 0%, #FDD501 18%, #E45325 50%, #ED1C24 82%, rgba(237, 28, 36, 0) 100%);
}

/* The vertical rhythm is computed from the window rather than fixed, so a short one stops
 * scrolling for space it does not need.
 *
 * Each value is a straight line between two anchors, clamped at both ends. Read them as
 * "<mockup value> at a 1000px-tall window, <tightened value> at an 800px one":
 *
 *     top gap     96px -> 50px      23vh - 134px
 *     bottom gap  64px -> 34px      15vh -  86px
 *     stack gap   34px -> 22px       6vh -  26px
 *
 * The slope is what a plain vh cannot express: 9vh hits 96px at 1067px tall but is still 72px at
 * 800px, which is most of what makes the page overflow in the first place.
 *
 * MEASURED at 1440 wide on the Datablaze page -- the tallest variant, because it alone carries the
 * marketing block -- as window height comes down. "over" is how far the page scrolls:
 *
 *     1200   over 0   top 96  bot 64  gap 34      the mockup's spacing, untouched
 *     1000   over 0   top 96  bot 64  gap 34      "
 *      900   over 0   top 73  bot 49  gap 28
 *      800   over 0   top 50  bot 34  gap 22
 *      760   over 0   top 41  bot 28  gap 20
 *      700   over 0   top 27  bot 19  gap 18      the last height that fits
 *      660   over 26  top 20  bot 16  gap 18      floors reached; it scrolls from here
 *
 * Before this the same page needed about 860px of window and scrolled below that, so the fold moved
 * from roughly 860px down to 700px. A tenant page, which has no marketing block, fits to 620px; the
 * phone layout below fits to 700px at 400 wide.
 *
 * The floors are not cosmetic. Past them the mark stops reading as a thing separate from the card,
 * so the page scrolls rather than compressing further.
 */
:root {
    --dbl-gap-top: clamp(14px, calc(23vh - 134px), 96px);
    --dbl-gap-bottom: clamp(12px, calc(15vh - 86px), 64px);
    --dbl-stack-gap: clamp(18px, calc(6vh - 26px), 34px);
}

/* ...AND THE SAME RAMP REACHES INSIDE THE CARD AND THE MARK, because the table above was measured
 * on the USERNAME step only and the page has two.
 *
 * Entering a username and pressing Next adds a second .dbl__field (66.9px plus the 16px fields gap
 * = 82.9) and a second card link (19.6 plus its 8px gap = 27.6). MEASURED at 1440x700 on the
 * Datablaze page: the card goes 346.3 -> 396.5 and the form 174.5 -> 285, so the column goes
 * 650.1 -> 760.6. The username step cleared 700 with 4px to spare; the password step overflowed it
 * by 107. The fold for the step a viewer actually types their password on was therefore ~110px
 * higher than the table above claims, and the three tokens up there were already at 27/19/18 with
 * only 10px left to give.
 *
 * So the gaps that were fixed numbers become ramps on the same slope. Read each as "<mockup value>
 * at a 1000px-tall window, <tightened value> at a 620px one":
 *
 *     card padding-y  32 -> 16        the card's own box, TOP AND BOTTOM ONLY - see the token
 *     card gap        20 -> 12        heading to form
 *     form gap        20 -> 12        fields to button to links
 *     fields gap      16 -> 10        between the two fields
 *     field gap        6 ->  4        label to input
 *     brand gap       16 ->  8        flame to wordmark
 *     flame           64 -> 36        the mark's own height
 *     promo padding   30 -> 12        the rule above the marketing block
 *     promo gap       16 ->  8        inside the marketing block
 *     footer padding  10 ->  4        above the copyright line
 *     input height    44 -> 38        both fields, and the DevExpress twin on the reset page
 *     button height   48 -> 42        Log In
 *     demo button     44 -> 40        GET A DEMO
 *
 * THE TWO PAGE FLOORS CAME DOWN WITH THEM, from 20/16 to 14/12 in the block above, so the last row
 * of that block's table no longer holds. --dbl-stack-gap keeps its 18px, for the reason stated
 * there.
 *
 * MEASURED at 1366 and 1440 wide on the PASSWORD step, which is the tall one, "over" being how far
 * it scrolls:
 *
 *     1000   over 0    the mockup's spacing, untouched: card pad 32, flame 64, input 44
 *      800   over 0
 *      700   over 0    was over 107 before this block
 *      640   over 0    a 1366x768 laptop with ordinary browser chrome
 *      625   over 0    the last height that fits
 *      620   over 3    every floor reached; it scrolls from here
 *      590   over 33   a 1280x720 laptop; the column needs 596.6 and cannot get under it
 *
 * 590 IS NOT REACHABLE BY SPACING. At that point the column is 596.6px of content - two labelled
 * fields, a button, two links, the mark, the marketing block and the footer - against 590px of
 * window, and every gap and control on the list above is already on its floor. Getting under it
 * means dropping something, and what to drop is an owner call rather than a number: the marketing
 * block is 147px at the floor and the read-only username field is 58, and either one alone clears
 * it with room. Both were considered and both were kept.
 *
 * WHY 620 AND NOT 685, which is where the first cut of this block stopped. 685 sounds low until you
 * put a real machine behind it: a 1366x768 laptop hands the page about 640px once the browser has
 * taken its chrome, and 1280x720 gives about 590. Those are the two commonest small laptops there
 * are, so a floor of 685 still scrolled on the hardware the complaint came from. The first cut had
 * ramped every gap and left every CONTROL at its full height, which is the mistake the shared
 * compact-density band already records: a band's height is its tallest control, so halving the space
 * around a 44px input stops helping well before the page has run out of things to give.
 *
 * NOTHING HERE HIDES CONTENT, which is the rule this block is measured against. The read-only
 * username field stays a field, the marketing block stays on the page, and every value is a
 * padding or a gap. A short window shows the same page more tightly; it does not show less of it.
 *
 * WHY THE RAMP STARTS AT 1000 RATHER THAN WHERE IT IS FIRST NEEDED. The password step did not
 * overflow until about 810, so compressing from 1000 is early by design: it matches the slope the
 * three tokens above already run on, and one continuous ramp cannot produce the visible step-change
 * a cliff at 810 would. A viewer dragging a window edge sees spacing tighten, not snap.
 *
 * MEASURE THIS WITH THE STYLESHEET CACHE-BUSTED. default.aspx stamps this file with
 * `?v=<%= Global.BuildRevision %>`, which is the ASSEMBLY version - so editing only the CSS leaves
 * the stamp identical and the browser keeps serving the copy it already has. A deploy rebuilds the
 * assembly and the stamp moves, so this costs nothing in production and a full round locally.
 *
 * WHAT IS DELIBERATELY NOT ON THE LIST. --dbl-stack-gap keeps its 18px floor. It is the gap that
 * separates the mark from the card, and the note above records why that floor is not cosmetic;
 * closing it would have been the easiest 18px on the page and it is the one the design cannot
 * spend. The read-only username field and the marketing block are owner calls that were made:
 * both stay.
 */
:root {
    /* VERTICAL ONLY. The card's side padding is a fixed 32 (24 on a phone) and is deliberately
       NOT on a ramp: horizontal padding buys no height, and ramping it made the input and the
       button grow 30px WIDER as the window got shorter - a sideways change nobody asked for,
       caused by a fix for a vertical problem. The card itself stays 420 either way, so the only
       thing the ramp moved was the controls inside it. */
    --dbl-card-padding-y: clamp(16px, calc(4.2105vh - 10.105px), 32px);
    --dbl-card-padding-x: 32px;
    --dbl-card-gap: clamp(12px, calc(2.1053vh - 1.053px), 20px);
    --dbl-form-gap: clamp(12px, calc(2.1053vh - 1.053px), 20px);
    --dbl-fields-gap: clamp(10px, calc(1.5789vh + 0.211px), 16px);
    --dbl-field-gap: clamp(4px, calc(0.5263vh + 0.737px), 6px);
    --dbl-brand-gap: clamp(8px, calc(2.1053vh - 5.053px), 16px);
    --dbl-flame-size: clamp(36px, calc(7.3684vh - 9.684px), 64px);
    --dbl-promo-padding: clamp(12px, calc(4.7368vh - 17.368px), 30px);
    --dbl-promo-gap: clamp(8px, calc(2.1053vh - 5.053px), 16px);
    --dbl-footer-padding: clamp(4px, calc(1.5789vh - 5.789px), 10px);
    /* THE CONTROLS RAMP TOO, and they are the entry this block thought hardest about.
       A band's height is its tallest control, so a page that halves the space around a 44px input
       and leaves the input alone stops getting shorter well before it has run out of things to
       give - which is exactly where the first cut of this block stalled, at a 685px floor.
       38/42/40 are still far above WCAG 2.5.8's 24px minimum target, and the phone layout below
       keeps the demo button's own 44px min-height regardless. */
    --dbl-input-height: clamp(38px, calc(1.5789vh + 28.211px), 44px);
    --dbl-button-height: clamp(42px, calc(1.5789vh + 32.211px), 48px);
    --dbl-demo-height: clamp(40px, calc(1.0526vh + 33.474px), 44px);
}

.dbl__col {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--dbl-stack-gap);
}

/* ================================================================================================
   The mark.
   ================================================================================================ */

.dbl__brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--dbl-brand-gap);
}

/* The wordmark keeps its 230px width and rides its own aspect ratio at 23px tall, so the flame is
 * the whole of the mark's vertical cost and the only half worth ramping. */
.dbl__flame {
    height: var(--dbl-flame-size);
    width: auto;
}

.dbl__wordmark {
    width: 230px;
    height: auto;
}

/* A tenant mark carries its own width and height from the contract, so this sets neither. The
 * live marks run 151-713 wide and 55-381 tall; there is no slot that fits them all. */
.dbl__logo {
    display: block;
    object-fit: contain;
}

/* ================================================================================================
   The card.
   ================================================================================================ */

.dbl__card {
    box-sizing: border-box;
    width: 100%;
    padding: var(--dbl-card-padding-y) var(--dbl-card-padding-x);
    background: #fff;
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    gap: var(--dbl-card-gap);
}

/* The card's treatment follows the ground's luminance rather than a flag of its own: a shadow
 * deep enough to sit on #211F1E reads as dirt on #F1EFEC, and the light ground needs the border
 * the dark one does not. */
.dbl--dark .dbl__card {
    box-shadow: 0 18px 48px rgba(0, 0, 0, .42);
}

.dbl--light .dbl__card {
    border: 1px solid #E2E0DD;
    box-shadow: 0 12px 34px rgba(58, 58, 58, .14);
}

.dbl__heading {
    margin: 0;
    font: 600 22px/1.25 'Poppins', sans-serif;
    color: var(--dz-ink, #31302F);
}

.dbl--light .dbl__heading {
    color: #3A3A3A;
}

/* ================================================================================================
   Fields.
   ================================================================================================ */

/* The card's own stack. pnlLogin is a server panel, so the gap has to be declared on it rather
   than inherited from .dbl__card, whose only children are the heading, the logged-out note and
   this. */
.dbl__form {
    display: flex;
    flex-direction: column;
    gap: var(--dbl-form-gap);
}

.dbl__fields {
    display: flex;
    flex-direction: column;
    gap: var(--dbl-fields-gap);
}

.dbl__field {
    display: flex;
    flex-direction: column;
    gap: var(--dbl-field-gap);
}

.dbl__label {
    font: 500 13px/1.3 'Poppins', sans-serif;
    color: var(--dz-subhead, #4C4948);
}

.dbl__input {
    box-sizing: border-box;
    width: 100%;
    height: var(--dbl-input-height);
    padding: 0 12px;
    border: 1px solid var(--dz-border, #C4C0BE);
    border-radius: var(--dz-radius-sm, 6px);
    background: #fff;
    font: 400 14px/1.4 'Roboto', Arial, sans-serif;
    color: var(--dz-ink, #31302F);
    outline: none;
}

.dbl__input::placeholder {
    color: #9B9694;
}

.dbl__input:focus {
    border-color: var(--dbl-accent);
    box-shadow: 0 0 0 3px rgba(var(--dbl-glow), .35);
}

/* The username is read-only once the flow has moved past it. It is still shown, because the step
 * it identifies is the one being answered. */
.dbl__input[readonly] {
    background: var(--dz-sunken, #F0EEEC);
    color: var(--dz-body, #666261);
}

/* ================================================================================================
   Buttons.
   ================================================================================================ */

.dbl__button {
    box-sizing: border-box;
    width: 100%;
    height: var(--dbl-button-height);
    padding: 0 18px;
    border: 1px solid var(--dbl-accent);
    border-radius: var(--dz-radius-sm, 6px);
    background: var(--dbl-accent);
    color: var(--dbl-accent-ink, #fff);
    font: 600 15px/1 'Poppins', sans-serif;
    cursor: pointer;
    transition: filter .12s ease;
}

.dbl__button:hover:not(:disabled) {
    filter: brightness(.92);
}

.dbl__button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--dbl-glow), .4);
}

.dbl__button:disabled {
    background: #DFDAD5;
    border-color: #DFDAD5;
    color: #9B9694;
    cursor: not-allowed;
    opacity: 1;
}

/* The mockup draws this at a flat 170x44, which works for "GET A DEMO". A tenant supplies its own
   label -- "Learn More About Wifi In Motion" is a live one -- so 170px is the floor rather than the
   width, and the label stays on one line until the viewport is too narrow for it. */
.dbl__button--demo {
    width: auto;
    min-width: 170px;
    max-width: 100%;
    height: var(--dbl-demo-height);
    padding: 0 20px;
    font-size: 14px;
    white-space: nowrap;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Datablaze's own sign-in page only (LoginTheme.PromoLight): the demo button is white so it stands
   apart from the orange Sign In button. Two classes, so it beats .dbl__button wherever it sits in
   the file; size comes from .dbl__button--demo and the narrow-screen rule, which it does not touch.
   Hover and the focus ring are inherited from .dbl__button. */
.dbl__button.dbl__button--promo-light {
    background: #FFFFFF;
    border-color: #FFFFFF;
    color: #31302F;
}

/* Shown by the mark's onerror handler when a tenant's logo URL 404s. */
.dbl__logo-fallback {
    display: none;
    font: 600 26px/1.25 'Poppins', sans-serif;
    color: #fff;
    text-align: center;
}

.dbl--light .dbl__logo-fallback {
    color: #1A1A1A;
}

/* ================================================================================================
   Links inside the card, and the ways back out of a step.
   ================================================================================================ */

.dbl__cardlinks {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    font: 400 14px/1.4 'Roboto', Arial, sans-serif;
    color: var(--dz-body, #666261);
}

.dbl__cardlinks a {
    color: var(--dbl-link);
    text-decoration: none;
}

.dbl__cardlinks a:hover {
    text-decoration: underline;
}

.dbl--light .dbl__cardlinks a {
    text-decoration: underline;
}

/* ================================================================================================
   Feedback. Three separate server-side labels land here, only ever one at a time.
   ================================================================================================ */

/* display:contents, not a box: three server labels land here and usually none of them render.
   As a box it would still take one of .dbl__form's 20px gaps; as contents it takes none, and the
   one label that does appear becomes a flex item of the form and is spaced like everything else. */
.dbl__alert {
    display: contents;
    font: 400 13px/1.45 'Roboto', Arial, sans-serif;
}

.dbl__alert .textAlertNew,
.dbl__alert .feedbackSpan {
    display: block;
    padding: 10px 12px;
    border-radius: var(--dz-radius-sm, 6px);
    background: #FBEAE5;
    color: #A32B0C;
}

.dbl__alert .messageAlert {
    display: block;
    padding: 10px 12px;
    border-radius: var(--dz-radius-sm, 6px);
    background: var(--dz-sunken, #F0EEEC);
    color: var(--dz-subhead, #4C4948);
}

.dbl__alert .textGrey {
    display: block;
    margin-top: 8px;
    color: #797573;
    font-size: 11px;
}

/* ================================================================================================
   Below the card.
   ================================================================================================ */

.dbl__promo {
    width: 100%;
    padding-top: var(--dbl-promo-padding);
    border-top: 1px solid rgba(255, 255, 255, .14);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--dbl-promo-gap);
    text-align: center;
}

.dbl--light .dbl__promo {
    border-top-color: #DDD9D5;
}

.dbl__promo-head {
    font: 600 16px/1.4 'Poppins', sans-serif;
    color: #fff;
}

.dbl--light .dbl__promo-head {
    color: #1A1A1A;
}

.dbl__promo-copy {
    max-width: 380px;
    font: 400 16px/1.55 'Roboto', Arial, sans-serif;
    color: #DFDAD5;
    text-wrap: pretty;
}

.dbl--light .dbl__promo-copy {
    color: var(--dz-subhead, #4C4948);
}

/* The footer is one line, so it is allowed out of the 420px column the rest of the page keeps to.
   Wrapping "(c) 2026 Datablaze. All rights reserved. | Privacy Policy | Terms of Service" onto two
   lines reads as two separate footers. */
.dbl__footer {
    width: max-content;
    max-width: none;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px 16px;
    padding-top: var(--dbl-footer-padding);
    font: 400 13px/1.4 'Roboto', Arial, sans-serif;
    color: var(--dbl-meta);
    text-align: center;
}

.dbl__footer a {
    color: var(--dbl-meta);
    text-decoration: none;
}

.dbl__footer a:hover {
    text-decoration: underline;
}

.dbl__footer-sep {
    color: var(--dz-subhead, #4C4948);
}

.dbl--light .dbl__footer-sep {
    color: var(--dz-border, #C4C0BE);
}

/* ================================================================================================
   The account-linking note under the login form.
   ================================================================================================ */

.dbl__signedout {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    text-align: center;
}

.dbl__signedout-body {
    font: 400 14px/1.5 'Roboto', Arial, sans-serif;
    color: var(--dz-body, #666261);
}

/* ================================================================================================
   Narrow screens. The column is already 420px; below that it is the page padding that has to give.
   ================================================================================================ */

@media (max-width: 480px) {
    /* A phone is short as well as narrow, and its column is taller because the copy wraps, so
       the ceilings come down to 56/40/26 on the same ramp. */
    :root {
        --dbl-gap-top: clamp(16px, calc(14vh - 82px), 56px);
        --dbl-gap-bottom: clamp(16px, calc(10vh - 60px), 40px);
        --dbl-stack-gap: clamp(18px, calc(4vh - 14px), 26px);
        /* The card's padding is a TOKEN here rather than the flat `padding: 24px` this block used
           to write, for the reason the ramp exists at all: a flat value beats the clamp outright,
           so a phone would have kept 24px of card padding at every height while everything around
           it tightened. 24 is still the ceiling - it is the phone's mockup value - and it comes
           down to 16 on the same slope. */
        --dbl-card-padding-y: clamp(16px, calc(2.667vh - 2.667px), 24px);
        --dbl-card-padding-x: 24px;
    }

    .dbl {
        padding-left: 16px;
        padding-right: 16px;
    }

    .dbl__footer {
        width: auto;
        max-width: 100%;
    }

    .dbl__button--demo {
        min-width: 0;
        white-space: normal;
        height: auto;
        min-height: 44px;
        padding: 10px 16px;
    }
}

/* ================================================================================================
   The other signed-out pages.

   Everything above dresses default.aspx. What follows is what passwordRecovery, Blocked, Error and
   termsandconditions need on top of it -- they reuse .dbl, .dbl__col, .dbl__card and the mark
   wholesale, so this section is only the parts the login page has no use for.
   ================================================================================================ */

/* A line of explanation under a heading. The login page never needs one, because "Sign in to X"
   over a username field explains itself; every step of the reset flow does, because the user has
   to be told what was sent where. */
.dbl__subhead {
    margin: -8px 0 0;
    font: 400 14px/1.5 'Roboto', Arial, sans-serif;
    color: var(--dz-body, #666261);
}

.dbl--light .dbl__subhead {
    color: #6B6B6B;
}

/* The reCAPTCHA widget is a fixed 304x78 iframe that cannot be restyled, so it is centred and
   given room rather than dressed. */
.dbl__captcha {
    display: flex;
    justify-content: center;
}

.dbl__captcha > div {
    max-width: 100%;
}

/* A step counter above the heading, so the flow says where it is. The login page is one step and
   says nothing. */
.dbl__step {
    font: 600 12px/1 'Poppins', sans-serif;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--dbl-meta, #9B9694);
}

/* ================================================================================================
   DevExpress controls, wearing the card's clothes.

   passwordRecovery is built on ASPxTextBox and ASPxButton and has to stay that way: the flow reads
   txtEmail.IsValid, drives SetEnabled from ClientSideEvents, and its step-2 code check is recent
   security work (ADO #144). Swapping them for asp:TextBox would re-open all of that to style a
   page, so the controls stay and the CSS reaches into what they render.

   MEASURED against the live page rather than assumed, because the shape is not obvious:

     ASPxTextBox  -> table.dxeRoot_<Theme>
                       td.dxeControlsCell_<Theme>
                         table.dxeTextBox_<Theme>#<id>     <- the visible box
                           td.dxic > input.dxeEditArea_<Theme>
                       td.dxeErrorCell_<Theme>             <- the error icon, hidden until invalid
     ASPxButton   -> div.dxbButton_<Theme>#<id>
                       div.dxb > input.dxb-hb + span.dx-vam

   The selectors match on a class SUBSTRING (dxeTextBox, not dxeTextBox_MetropolisBlue) so that
   changing or dropping the Theme attribute does not silently undress the page. They are scoped
   under .dbl, so nothing here can reach the signed-in app. */

/* The outer table and its cells are layout scaffolding: make them carry no width of their own.
   position:relative so the validation icon can be lifted out of the table's own layout below. */
.dbl [class*="dxeRoot"] {
    position: relative;
    width: 100%;
    border-collapse: collapse;
}

.dbl [class*="dxeControlsCell"] {
    width: 100%;
    padding: 0;
}

/* The inner table is the box the user sees, so it takes .dbl__input's treatment. DevExpress puts
   its default width on a CLASS (dxeTextBoxDefaultWidthSys) rather than inline once Width is left
   unset in the markup, which is why this needs no !important -- and why the markup drops the
   Width="250px" it used to carry. */
.dbl [class*="dxeTextBox"] {
    box-sizing: border-box;
    width: 100%;
    height: var(--dbl-input-height);
    border: 1px solid var(--dz-border, #C4C0BE);
    border-radius: var(--dz-radius-sm, 6px);
    background: #fff;
    border-collapse: separate;
}

.dbl [class*="dxeTextBox"] td.dxic {
    padding: 0;
}

/* The input itself keeps none of its own chrome -- the table above is drawing the box. */
.dbl input[class*="dxeEditArea"] {
    box-sizing: border-box;
    width: 100%;
    height: 42px;
    padding: 0 12px;
    border: 0;
    outline: 0;
    background: transparent;
    font: 400 14px/1.4 'Roboto', Arial, sans-serif;
    color: var(--dz-ink, #31302F);
}

/* Focus lands on the inner input, so the ring has to be drawn by the table that wraps it. :has()
   is the only way to reach an ancestor from the focused element, and every browser this app
   supports has shipped it; the rule simply does nothing where it has not. */
.dbl [class*="dxeTextBox"]:has(input:focus) {
    border-color: var(--dbl-accent);
    box-shadow: 0 0 0 3px rgba(var(--dbl-glow), .35);
}

/* Both password fields are disabled once the reset succeeds, so this is the last thing the flow
   shows and not an edge case. It takes the same treatment as a read-only field on the login page
   rather than DevExpress's own grey, which does not belong on this card. */
.dbl [class*="dxeDisabled"],
.dbl [class*="dxeTextBox"][class*="dxeDisabled"] {
    background: var(--dz-sunken, #F0EEEC);
}

.dbl [class*="dxeDisabled"] input[class*="dxeEditArea"] {
    background: transparent;
    color: var(--dz-body, #666261);
}

/* The validation icon cell, LIFTED OUT of the table rather than collapsed.
   MEASURED: width:0 does not work. It holds a 16px image under white-space:nowrap, and a table
   cell cannot render narrower than its content, so it kept 18px and the field came out 338px wide
   inside a 356px card -- visibly short of the button beneath it. Nor can it simply be hidden: with
   ErrorDisplayMode="ImageWithTooltip" this icon is the ONLY feedback a field-level validator gives,
   so removing it would cost "please enter a valid email address" entirely.
   Taking it out of flow gives the field the full width and floats the icon inside its right edge,
   which is where an input usually carries its status anyway. */
.dbl [class*="dxeErrorCell"] {
    position: absolute;
    top: 0;
    right: 10px;
    bottom: 0;
    width: auto;
    padding: 0;
    display: flex;
    align-items: center;
}

/* The button. The div is the button; the input inside it is the submit and is laid over the label,
   so both have to be told to fill the box or the click target is 170px wide on a 420px card.

   width and height are !important, which is load-bearing and not laziness. ASPxButton writes
   "width:352px;height:44px" INLINE, and it does so from script AFTER the page loads -- the server's
   own HTML for this button carries neither. So there is no markup attribute to set instead and no
   specificity that beats it; an ordinary rule loses to the inline style every time. MEASURED: the
   button sat 4px narrower than the field above it and 4px shorter than the login page's. */
.dbl [class*="dxbButton"] {
    box-sizing: border-box;
    display: block;
    width: 100% !important;
    height: 48px !important;
    border: 1px solid var(--dbl-accent);
    border-radius: var(--dz-radius-sm, 6px);
    background: var(--dbl-accent);
    color: var(--dbl-accent-ink, #fff);
    font: 600 15px/1 'Poppins', sans-serif;
    cursor: pointer;
    transition: filter .12s ease;
    overflow: hidden;
}

.dbl [class*="dxbButton"] > div.dxb {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    position: relative;
}

.dbl [class*="dxbButton"] input.dxb-hb {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: transparent;
    font: inherit;
    cursor: pointer;
}

.dbl [class*="dxbButton"] span.dx-vam {
    color: var(--dbl-accent-ink, #fff);
    font: inherit;
    pointer-events: none;
}

.dbl [class*="dxbButton"]:hover {
    filter: brightness(.92);
}

/* DevExpress adds its own hover/pressed/disabled classes by script (ASPx.AddHoverItems), and they
   carry the MetropolisBlue background. Disabled has to win here: the step buttons START disabled
   and only the captcha or a valid field enables them, so this is the state the page opens in. */
.dbl [class*="dxbDisabled"],
.dbl [class*="dxbButton"][class*="dxbDisabled"] {
    background: #DFDAD5;
    border-color: #DFDAD5;
    color: #9B9694;
    cursor: not-allowed;
    filter: none;
}

.dbl [class*="dxbDisabled"] span.dx-vam {
    color: #9B9694;
}

.dbl [class*="dxbDisabled"] input.dxb-hb {
    cursor: not-allowed;
}

/* The "which account?" popup, for an email that matches more than one user. DevExpress draws the
   window; this only stops it clashing with the card behind it. */
.dbl [class*="dxpcLite"],
.dbl [class*="dxpc-content"] {
    font-family: 'Poppins', 'Roboto', Arial, sans-serif;
}

/* ================================================================================================
   The notice pages: Blocked and Error.

   Both are a card with a sentence in it and no form, so they take .dbl__card and add only the
   things a form would otherwise have provided -- a body voice, and a list of ways out.
   ================================================================================================ */

.dbl__notice {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.dbl__notice-body {
    margin: 0;
    font: 400 15px/1.6 'Roboto', Arial, sans-serif;
    color: var(--dz-body, #666261);
}

/* The ways out of an error. A list, because there are three of them and they are alternatives;
   unbulleted, because the card is already a bounded thing and bullets inside it read as debris. */
.dbl__notice-links {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.dbl__notice-links li {
    font: 400 14px/1.5 'Roboto', Arial, sans-serif;
    color: var(--dz-body, #666261);
}

.dbl__notice-links a {
    color: var(--dbl-link, #0A6188);
    text-decoration: none;
    font-weight: 500;
}

.dbl__notice-links a:hover {
    text-decoration: underline;
}

/* A support code, for the user to quote. Quiet, because it is for us and not for them. */
.dbl__notice-code {
    margin: 0;
    font: 400 12px/1.4 'Roboto', Arial, sans-serif;
    color: var(--dbl-meta, #9B9694);
    text-align: right;
}

/* ================================================================================================
   The document page: terms and conditions.

   Opened from the login footer in a new tab, so it is the same page furniture around a long piece
   of text. It is the one signed-out page that is not 420px wide.
   ================================================================================================ */

.dbl__col--doc {
    max-width: 860px;
}

.dbl__doc {
    box-sizing: border-box;
    width: 100%;
    padding: 40px;
    background: #fff;
    border-radius: 16px;
    font: 400 15px/1.7 'Roboto', Arial, sans-serif;
    color: var(--dz-body, #4C4948);
}

.dbl--dark .dbl__doc {
    box-shadow: 0 18px 48px rgba(0, 0, 0, .42);
}

.dbl--light .dbl__doc {
    border: 1px solid #E2E0DD;
    box-shadow: 0 12px 34px rgba(58, 58, 58, .14);
}

.dbl__doc h1,
.dbl__doc h2,
.dbl__doc h3 {
    font-family: 'Poppins', sans-serif;
    color: var(--dz-ink, #31302F);
    line-height: 1.3;
}

.dbl__doc h1 {
    margin: 0 0 24px;
    font-size: 26px;
    font-weight: 600;
}

.dbl__doc h2 {
    margin: 32px 0 12px;
    font-size: 18px;
    font-weight: 600;
}

.dbl__doc h3 {
    margin: 24px 0 8px;
    font-size: 15px;
    font-weight: 600;
}

.dbl__doc p {
    margin: 0 0 14px;
}

.dbl__doc a {
    color: var(--dbl-link, #0A6188);
}

.dbl__doc ul,
.dbl__doc ol {
    margin: 0 0 14px;
    padding-left: 22px;
}

.dbl__doc li {
    margin-bottom: 8px;
}

/* The accept/decline row a signed-in user sees when the terms are presented for agreement. */
.dbl__doc-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 28px;
}

.dbl__doc-actions .dbl__button {
    width: auto;
    min-width: 160px;
}

/* Back to the top of a long document. Sits clear of the card rather than over its text. */
.dbl__totop {
    position: fixed;
    right: 20px;
    bottom: 20px;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: 50%;
    background: var(--dbl-accent);
    color: var(--dbl-accent-ink, #fff);
    font: 600 18px/1 'Poppins', sans-serif;
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
}

.dbl__totop.is-shown {
    display: flex;
}

@media (max-width: 720px) {
    .dbl__doc {
        padding: 24px;
    }

    .dbl__doc-actions .dbl__button {
        width: 100%;
    }
}
