/* Styles for this site's two screens: the sign-in page, which renders without _Layout as a
   full-bleed two-column split, and the portal chooser that follows it. The gradient and the "PI"
   mark deliberately match the three portals' own login pages.

   Each portal's accent below is lifted from that portal's own login page, so choosing a portal
   hands off to something that looks like where you are going. */

:root {
    --pit-ink: #240046;
    --pit-violet: #3a0ca3;
    --pit-blue: #4361ee;

    --pit-buyer-from: #3a0ca3;
    --pit-buyer-to: #4361ee;
    --pit-supplier-from: #0d3b66;
    --pit-supplier-to: #1f7a8c;
    --pit-admin-from: #2d2d44;
    --pit-admin-to: #4a4a68;
}

html,
body {
    height: 100%;
}

body.login-body {
    margin: 0;
    background-color: #f6f7fb;
}

.login-split {
    min-height: 100vh;
}

/* ---------- Left: brand panel ---------- */

.login-brand-panel {
    position: relative;
    overflow: hidden;
    color: #fff;
    background: linear-gradient(160deg, var(--pit-ink) 0%, var(--pit-violet) 55%, var(--pit-blue) 100%);
}

/* Two soft glows plus a faint engineering grid, so the panel has depth without any image asset. */
.login-brand-panel::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(42rem 42rem at 85% 8%, rgba(67, 97, 238, 0.55), transparent 60%),
        radial-gradient(30rem 30rem at 8% 92%, rgba(114, 9, 183, 0.5), transparent 62%);
    pointer-events: none;
}

.login-brand-panel::after {
    content: "";
    position: absolute;
    inset: -1px;
    background-image:
        linear-gradient(to right, rgba(255, 255, 255, 0.07) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
    background-size: 3rem 3rem;
    mask-image: radial-gradient(120% 100% at 20% 0%, #000 25%, transparent 75%);
    -webkit-mask-image: radial-gradient(120% 100% at 20% 0%, #000 25%, transparent 75%);
    pointer-events: none;
}

.login-brand-inner {
    position: relative;
    z-index: 1;
    max-width: 30rem;
}

.login-mark {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.7rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    letter-spacing: 0.02em;
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(2px);
}

.login-headline {
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
}

.login-feature-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.login-feature-list li {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.55rem 0;
}

.login-feature-list i {
    flex: 0 0 auto;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 0.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.18);
}

.login-portal-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.login-portal-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    border-radius: 2rem;
    font-size: 0.8rem;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.22);
}

/* ---------- Right: form panel ---------- */

/*
    *** POSITIONED SO THE MONEY FIELD CAN LIVE INSIDE IT (Bradley, 2026-08-23: "the initial login does
    show anything"). *** This panel is opaque white and the brand panel beside it is an opaque gradient, so
    between them they cover the entire viewport - and a background layer sitting BEHIND the page had
    nothing to show through. The forgot-password page works because it is a card on the flat body; this
    page has no flat body left to see.

    SO ON THIS PAGE THE DRIFT GOES IN THE PANEL RATHER THAN BEHIND IT - see .login-money-field-inset, and
    .login-form-inner below, which has to be lifted above it.
*/
.login-form-panel {
    position: relative;
    background-color: #fff;
}

.login-form-inner {
    /* ABOVE THE DRIFT. Without this the form is painted at the same level as the pattern layer and the
       inputs pick up coins behind their own borders. */
    position: relative;
    z-index: 1;

    width: 100%;
    max-width: 24rem;
}

/* Compact brand bar shown only when the panel is stacked on small screens. */
.login-mark-compact {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.65rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    background: linear-gradient(135deg, var(--pit-violet), var(--pit-blue));
}

.login-form-panel .form-control {
    border-radius: 0.6rem;
}

.login-form-panel .form-floating > .form-control:focus {
    border-color: var(--pit-blue);
    box-shadow: 0 0 0 0.2rem rgba(67, 97, 238, 0.18);
}

/* Reveal toggle sits inside the password field, clear of the floating label. */
.login-password-wrap {
    position: relative;
}

.login-password-toggle {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 2.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: none;
    color: var(--bs-secondary-color);
    border-radius: 0 0.6rem 0.6rem 0;
}

.login-password-toggle:hover {
    color: var(--pit-violet);
}

.login-password-wrap .form-control {
    padding-right: 2.9rem;
}

.login-submit {
    border: 0;
    border-radius: 0.6rem;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, var(--pit-violet), var(--pit-blue));
    transition: filter 0.15s ease-in-out, transform 0.15s ease-in-out;
}

.login-submit:hover,
.login-submit:focus {
    color: #fff;
    filter: brightness(1.08);
}

.login-submit:active {
    transform: translateY(1px);
}

.login-submit:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 0.25rem rgba(67, 97, 238, 0.35);
}

.login-secure-note {
    font-size: 0.8rem;
}

/* ---------- Shared chrome (_Layout: chooser, impersonation, errors) ---------- */

body.chrome-body {
    background-color: #f6f7fb;
}

.chrome-header {
    color: #fff;
    background: linear-gradient(100deg, var(--pit-ink) 0%, var(--pit-violet) 60%, var(--pit-blue) 100%);
}

.chrome-tagline {
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.6);
    line-height: 1.2;
}

.chrome-signout {
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.1);
}

.chrome-signout:hover,
.chrome-signout:focus {
    color: var(--pit-ink);
    background: #fff;
    border-color: #fff;
}

.chrome-footer {
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    border-top: 1px solid #e7e9f2;
    background-color: #fff;
}

/* ---------- Portal chooser ---------- */

.portal-hero {
    position: relative;
    overflow: hidden;
    border-radius: 1rem;
    padding: 2rem;
    color: #fff;
    background: linear-gradient(135deg, var(--pit-ink) 0%, var(--pit-violet) 60%, var(--pit-blue) 100%);
}

.portal-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(24rem 24rem at 88% 10%, rgba(67, 97, 238, 0.6), transparent 62%),
        radial-gradient(18rem 18rem at 4% 96%, rgba(114, 9, 183, 0.45), transparent 65%);
    pointer-events: none;
}

.portal-hero-inner {
    position: relative;
    z-index: 1;
}

.portal-hero-eyebrow {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.7rem;
    border-radius: 2rem;
    font-size: 0.75rem;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.22);
}

.portal-hero-title {
    font-weight: 700;
    letter-spacing: -0.02em;
    font-size: clamp(1.5rem, 3vw, 2.15rem);
    margin: 0;
}

/* The card IS the submit button, so every button default has to be unwound here. text-decoration
   included: this class is worn by more than one kind of element, and Bootstrap underlines every anchor -
   an underline running the width of a card reads as a rendering fault, not as a link. */
.portal-card {
    position: relative;
    overflow: hidden;
    text-decoration: none;
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    width: 100%;
    text-align: left;
    padding: 1.25rem;
    border: 1px solid #e3e6f0;
    border-radius: 1rem;
    background: #fff;
    box-shadow: 0 0.15rem 0.5rem rgba(36, 0, 70, 0.05);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

/* Accent strip along the top edge, in the target portal's own colours. */
.portal-card::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: linear-gradient(90deg, var(--card-from), var(--card-to));
}

.portal-card:hover,
.portal-card:focus-visible {
    transform: translateY(-2px);
    border-color: var(--card-to);
    box-shadow: 0 0.75rem 1.75rem rgba(36, 0, 70, 0.14);
}

.portal-card:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 0.25rem rgba(67, 97, 238, 0.3);
}

.portal-card:active {
    transform: translateY(0);
}

.portal-card--buyer {
    --card-from: var(--pit-buyer-from);
    --card-to: var(--pit-buyer-to);
}

.portal-card--supplier {
    --card-from: var(--pit-supplier-from);
    --card-to: var(--pit-supplier-to);
}

.portal-card--admin {
    --card-from: var(--pit-admin-from);
    --card-to: var(--pit-admin-to);
}

.portal-card-icon {
    flex: 0 0 auto;
    width: 3rem;
    height: 3rem;
    border-radius: 0.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.35rem;
    color: #fff;
    background: linear-gradient(135deg, var(--card-from), var(--card-to));
}

.portal-card-body {
    flex: 1 1 auto;
    min-width: 0;
}

.portal-card-title {
    display: block;
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--bs-body-color);
}

.portal-card-subtitle {
    display: block;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--card-to);
    margin-top: 0.1rem;
}

.portal-card-blurb {
    display: block;
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    margin-top: 0.35rem;
}

.portal-card-cta {
    flex: 0 0 auto;
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--card-to);
    white-space: nowrap;
}

.portal-card-cta i {
    transition: transform 0.15s ease;
}

.portal-card:hover .portal-card-cta i,
.portal-card:focus-visible .portal-card-cta i {
    transform: translateX(3px);
}

/* AN UNAVAILABLE CARD IS STILL A CONTROL - it opens that portal's own downtime page - so it keeps the
   hover lift and the pointer every other card has, and only the colour changes.

   PAINTED IN BOOTSTRAP'S SUBTLE WARNING PAIR: #664d03 on #fff3cd, about 7:1. The version this replaces
   used .text-warning on white, which is #ffc107 on #fff at roughly 1.9:1 - illegible rather than merely
   low - and then dimmed the whole card with .opacity-75, which dragged every other ratio down with it.
   Neither is coming back. */
.portal-card--down {
    background: var(--bs-warning-bg-subtle);
    border-color: var(--bs-warning-border-subtle);
}

/* The company name and the administrator's message, carried into the warning ink. The name is normally
   the portal's accent colour, which is about 4.5:1 on a white card and only just passes; on the warning
   background it drops below AA. The accent still shows on the icon and the strip along the top edge. */
.portal-card--down .portal-card-subtitle,
.portal-card--down .portal-card-message {
    color: var(--bs-warning-text-emphasis);
}

/* The maintenance sentence and the scheduled-window warning, in the warning colour rather than the
   muted blurb grey - it is the point of the card, not a footnote to it. */
.portal-card-notice {
    color: var(--bs-warning-text-emphasis);
    font-weight: 500;
}

/* SAYS THE NOTICE OPENS. It does the same job as the CTA on an available card, so it gets the same
   weight and the same arrow nudge - a hover lift alone means nothing on a touch screen. */
.portal-card-more {
    color: var(--bs-warning-text-emphasis);
    font-weight: 600;
    margin-top: 0.5rem;
}

.portal-card-more i {
    transition: transform 0.15s ease;
}

.portal-card:hover .portal-card-more i,
.portal-card:focus-visible .portal-card-more i {
    transform: translateX(3px);
}

/* The administrator's own words, wrapped as typed: the message is composed in a textarea in the
   Administrator portal, so its line breaks are deliberate. Same treatment as the portals' own
   downtime page. */
.portal-card-message {
    white-space: pre-wrap;
}

.portal-card-countdown {
    flex: 0 0 auto;
    align-self: center;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    color: var(--bs-warning-text-emphasis);
    white-space: nowrap;
}

.portal-card-countdown-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Tabular figures so the seconds tick without the clock's width jumping about. */
.portal-card-clock {
    font-variant-numeric: tabular-nums;
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.2;
}

.portal-impersonate {
    padding: 1.25rem;
    border-radius: 1rem;
    background: #fff;
    border: 1px solid var(--bs-warning-border-subtle);
    border-left: 3px solid var(--bs-warning);
}

.portal-impersonate-icon {
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.65rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #b57500;
    background: var(--bs-warning-bg-subtle);
}

/* ---------- Impersonation ---------- */

.impersonate-notice {
    display: flex;
    gap: 1rem;
    padding: 1rem 1.25rem;
    border-radius: 1rem;
    background: var(--bs-warning-bg-subtle);
    border: 1px solid var(--bs-warning-border-subtle);
    border-left: 3px solid var(--bs-warning);
}

.impersonate-notice-icon {
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.65rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    background: #b57500;
}

.impersonate-panel {
    padding: 1.25rem;
    border-radius: 1rem;
    background: #fff;
    border: 1px solid #e3e6f0;
    box-shadow: 0 0.15rem 0.5rem rgba(36, 0, 70, 0.05);
}

.impersonate-panel-head,
.impersonate-panel-foot {
    background: #fafbff;
}

.impersonate-panel-head {
    border-bottom: 1px solid #e3e6f0;
}

.impersonate-panel-foot {
    border-top: 1px solid #e3e6f0;
}

.impersonate-table > thead th {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
    border-bottom-color: #e3e6f0;
}

.impersonate-table > tbody > tr:last-child > td {
    border-bottom: 0;
}

.impersonate-avatar {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, var(--pit-violet), var(--pit-blue));
}

.impersonate-username {
    font-size: 0.8rem;
    padding: 0.15rem 0.4rem;
    border-radius: 0.3rem;
    color: var(--pit-violet);
    background: rgba(67, 97, 238, 0.08);
}

.impersonate-empty-icon {
    font-size: 2rem;
    color: var(--bs-secondary-color);
    opacity: 0.5;
}

/* Target summary at the top of the reason dialog. */
.impersonate-target {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem;
    border-radius: 0.75rem;
    background: #f6f7fb;
    border: 1px solid #e3e6f0;
}

@media (prefers-reduced-motion: reduce) {
    .portal-card,
    .portal-card-cta i,
    .portal-card-more i,
    .login-submit {
        transition: none;
    }

    .portal-card:hover,
    .portal-card:focus-visible {
        transform: none;
    }
}

/* Cross-sell to the Travel product, below the portal strip. Separated by a hairline rule rather
   than spacing alone, so it reads as "a different product" instead of a fourth PurchaseIT portal. */
.login-travel-punt {
    border-top: 1px solid rgba(255, 255, 255, 0.14);
}

/* The chip is a static badge everywhere else on this page; as a link it needs to look pressable. */
a.login-portal-chip {
    color: inherit;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

a.login-portal-chip:hover,
a.login-portal-chip:focus-visible {
    background: rgba(255, 255, 255, 0.22);
    border-color: rgba(255, 255, 255, 0.4);
}

/* --- THE MONEY FIELD ---------------------------------------------------------------------------------

    THE SAME DRIFTING COINS AND BANKNOTES AS THE GUEST BID PAGE (Bradley, 2026-08-23), on the sign-in page
    and the portal chooser. Same artwork, same speeds, same faintness - the two sites should feel like one
    product, and this is the cheapest way to say so.

    THE TILES ARE THIS PROJECT'S OWN FILES, in wwwroot/img, byte-identical to the guest app's copies rather
    than shared across projects: each app ships what it serves, so neither can be broken by a change to the
    other.

    ONLY `transform` IS ANIMATED, and each layer travels exactly one tile before it repeats - so the loop
    is invisible and the compositor never has to repaint. See the guest app's site.css for the longer note;
    the numbers here are deliberately the same ones.

    WHERE IT SHOWS, WHICH IS NOT EVERYWHERE ON THE SIGN-IN PAGE. That page is a two-column split whose left
    half is an opaque brand gradient with its own glows and grid; it paints over this. So the drift appears
    on the light right-hand column behind the form, and on the chooser it appears around the cards. Both
    are the flat #f6f7fb this was added to relieve.
   -------------------------------------------------------------------------------------------------- */

/*
    TWO PLACEMENTS, BECAUSE THIS SITE HAS TWO KINDS OF PAGE.

    .login-money-field        FIXED, BEHIND EVERYTHING. For pages that are cards on the flat body - the
                              portal chooser, forgot password, reset password. The body colour shows around
                              the card and that is where the drift lives.

    .login-money-field-inset  ABSOLUTE, INSIDE AN OPAQUE PANEL. For the sign-in page, which is a two-column
                              split of an opaque gradient and an opaque white panel: there is no visible
                              body background on it at all, so a layer behind the page is a layer nobody
                              can see. Its parent needs `position: relative` and the content above it needs
                              `z-index: 1` - see .login-form-panel.
*/
.login-money-field,
.login-money-field-inset {
    overflow: hidden;
    pointer-events: none;
}

.login-money-field {
    position: fixed;
    inset: 0;
    z-index: -1;
}

.login-money-field-inset {
    position: absolute;
    inset: 0;

    /* NOT NEGATIVE. Inside a positioned parent, -1 would put it behind that parent's own white
       background - which is the bug this class exists to fix, reintroduced one level down. */
    z-index: 0;
}

.login-money-field::before,
.login-money-field::after,
.login-money-field-inset::before,
.login-money-field-inset::after {
    content: "";
    position: absolute;

    /* Oversized by more than a tile on every side, so a translating edge is never on screen. */
    inset: -30%;
    background-repeat: repeat;
    will-change: transform;
}

/* COINS: the smaller, quicker layer. */
.login-money-field::before,
.login-money-field-inset::before {
    background-size: 300px 300px;
    background-image: url("../img/money-coins.svg");
    animation: login-coins-drift 78s linear infinite;
}

/* BANKNOTES: the larger, slower layer, drifting the other way. */
.login-money-field::after,
.login-money-field-inset::after {
    background-size: 460px 460px;
    background-image: url("../img/money-notes.svg");
    animation: login-notes-drift 124s linear infinite;
}

/* The travel is one tile per axis - change a background-size above and this must change with it, or the
   pattern visibly jumps once per cycle. */
@keyframes login-coins-drift {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(-300px, -300px, 0); }
}

@keyframes login-notes-drift {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(460px, -460px, 0); }
}

/* Stops dead for anybody who asked for that, and keeps the pattern: the objection reduced motion
   expresses is to movement, not to decoration. */
@media (prefers-reduced-motion: reduce) {
    .login-money-field::before,
    .login-money-field::after,
    .login-money-field-inset::before,
    .login-money-field-inset::after {
        animation: none;
    }
}

@media print {
    .login-money-field,
    .login-money-field-inset { display: none; }
}

/* ---------------------------------------------------------------------------------------------------
   SSO (2026-08-24). The "or continue with" rule and the provider buttons.

   THE DIVIDER IS ONE ELEMENT WITH A CENTRED LABEL, drawn with a border on two pseudo-elements rather
   than as an <hr> plus absolutely positioned text: the label has to sit ON the rule and stay centred
   at every width, and a positioned overlay of the panel background breaks the moment the panel is not
   opaque - which on this page it is not, because the drifting money layer sits behind it.

   NEUTRAL BUTTONS, NOT BRANDED ONES. Reproducing each provider's own button colours would put two
   competing accents next to a gradient primary action, and both Microsoft's and Google's brand
   guidelines constrain how their marks may be coloured and spaced. An outline button with the icon is
   unambiguous and stays inside both sets of rules.
   --------------------------------------------------------------------------------------------------- */

.login-sso-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    color: var(--bs-secondary-color);
    font-size: 0.8rem;
}

.login-sso-divider::before,
.login-sso-divider::after {
    content: "";
    flex: 1 1 auto;
    border-top: 1px solid var(--bs-border-color);
}

.login-sso-btn {
    border-radius: 0.6rem;
    font-weight: 500;
    border-color: var(--bs-border-color);
    background-color: #fff;
    color: var(--bs-body-color);
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, transform 0.15s ease-in-out;
}

.login-sso-btn:hover,
.login-sso-btn:focus {
    border-color: var(--pit-violet);
    background-color: #fff;
    color: var(--pit-violet);
}

.login-sso-btn:active {
    transform: translateY(1px);
}

/* The same focus ring the primary action uses, so keyboard focus reads identically wherever it lands
   on this form. */
.login-sso-btn:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 0.25rem rgba(67, 97, 238, 0.35);
}

.login-sso-btn i {
    font-size: 1.05rem;
    line-height: 1;
}
