/* File: shared/css/portal-auth.css
 *
 * The parts of a sign-in screen that must behave identically on all three portals.
 *
 * Only mechanics live here — the waiting overlay, the error slot, the Microsoft button's
 * anatomy, focus rings, reduced-motion. Everything that makes a portal look like itself
 * (composition, hero, colour weighting, type scale) belongs to that portal's own
 * stylesheet, which loads after this one.
 *
 * Two rules this file exists to enforce:
 *
 *   No layout shift. The error slot occupies its space from the first paint (empty, not
 *   absent), and the waiting state is a fixed overlay, so nothing on the page moves when
 *   either appears. A button that jumps as the person reaches for it is a real failure,
 *   not a cosmetic one.
 *
 *   Nothing private is painted early. Screens ship with the content root hidden and the
 *   guard reveals it; the rules below make `hidden` mean hidden even on elements whose
 *   layout class sets display.
 */

/* [hidden] must win over any display: flex/grid a layout class sets, everywhere. This is
 * load-bearing: it is what stops a protected page flashing before its guard has run. */
[hidden] {
    display: none !important;
}

/* ------------------------------------------------------------------ *
 * Waiting state
 *
 * Up before anything else when Microsoft returns, and up until replace() navigates away.
 * A live region, so a screen-reader user hears "Signing you in" rather than silence, and
 * aria-busy while the work is outstanding.
 * ------------------------------------------------------------------ */

.auth-overlay {
    --auth-overlay-bg: #f5f5f3;
    --auth-overlay-text: #17191b;
    --auth-overlay-note: #52585b;
    --auth-spinner-track: rgba(23, 25, 27, .2);
    --auth-spinner-head: #17191b;
    --auth-spinner-pulse: rgba(23, 25, 27, .54);
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 20px;
    padding: 24px;
    background: var(--auth-overlay-bg);
    color: var(--auth-overlay-text);
    text-align: center;
}

/* Authentication is a full-screen system state, so its palette must not inherit
 * --ecv-ink: that identity token intentionally inverts in dark mode. Explicit auth
 * tokens keep every part of the waiting state on the same contrast pair. */
:root.dark-theme .auth-overlay,
:root[data-theme="dark"] .auth-overlay,
html.dark-theme .auth-overlay,
html[data-theme="dark"] .auth-overlay {
    --auth-overlay-bg: #0f1113;
    --auth-overlay-text: #ffffff;
    --auth-overlay-note: #c4c8ca;
    --auth-spinner-track: rgba(255, 255, 255, .25);
    --auth-spinner-head: #ffffff;
    --auth-spinner-pulse: rgba(255, 255, 255, .58);
}

.auth-spinner {
    width: 34px;
    height: 34px;
    border: 3px solid var(--auth-spinner-track);
    border-top-color: var(--auth-spinner-head);
    border-radius: 50%;
    animation: auth-spin .8s linear infinite;
}

@keyframes auth-spin {
    to { transform: rotate(360deg); }
}

.auth-status {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .18em;
    text-transform: uppercase;
    margin: 0;
    color: var(--auth-overlay-text);
}

/* Arabic is never letter-spaced or uppercased — the identity's rule, and typographically
 * wrong for the script. */
html[dir="rtl"] .auth-status {
    letter-spacing: normal;
    text-transform: none;
    font-size: 14px;
}

.auth-status-note {
    margin: 0;
    max-width: 34ch;
    font-size: 13px;
    line-height: 1.6;
    color: var(--auth-overlay-note);
}

/* A person who has asked for less motion gets a pulse instead of a spin — still clearly
 * "working", without rotation. */
@media (prefers-reduced-motion: reduce) {
    .auth-spinner {
        animation: auth-pulse 1.4s ease-in-out infinite;
        border-top-color: var(--auth-spinner-track);
        background: var(--auth-spinner-pulse);
    }

    @keyframes auth-pulse {
        0%, 100% { opacity: .35; }
        50% { opacity: 1; }
    }
}

/* ------------------------------------------------------------------ *
 * Microsoft button
 *
 * The four coloured squares are Microsoft's mark, used as their branding guidance
 * requires. They are the one place colour appears on these screens, and they are not
 * ECVALLA's colour — they identify whose sign-in this is.
 * ------------------------------------------------------------------ */

.auth-ms-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    min-height: 52px;
    padding: 0 22px;
    border: 1px solid transparent;
    border-radius: 10px;
    background: var(--ecv-ink, #17191b);
    color: #fff;
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: background-color .18s ease, opacity .18s ease;
}

.auth-ms-btn:hover:not(:disabled) {
    background: var(--ecv-ink-soft, #2b2e30);
}

.auth-ms-btn:disabled {
    opacity: .55;
    cursor: progress;
}

.auth-ms-btn:focus-visible {
    outline: 2px solid var(--ecv-ink, #17191b);
    outline-offset: 3px;
}

/* The mark keeps its own square footprint whatever the button's type size does. */
.auth-ms-btn svg {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
}

/* ------------------------------------------------------------------ *
 * Error slot
 *
 * Present in the layout from the first paint. `hidden` empties it without removing its
 * box, so revealing a message never moves the button underneath it.
 * ------------------------------------------------------------------ */

.auth-error {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-height: 0;
    margin: 0;
    padding: 12px 14px;
    border: 1px solid var(--ecv-red-line, #efc8c4);
    border-radius: 10px;
    background: var(--ecv-red-wash, #fff0ee);
    color: var(--ecv-red, #ad291f);
    font-size: 13px;
    line-height: 1.55;
    text-align: start;
}

.auth-error::before {
    content: "!";
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 18px;
    height: 18px;
    margin-top: 1px;
    border-radius: 50%;
    background: var(--ecv-red, #ad291f);
    color: #fff;
    font-size: 12px;
    font-weight: 700;
}

/* Reserves the error's height so the card does not change size when a message appears.
 * Screens that would rather not reserve it simply omit the modifier. */
.auth-error-reserve {
    min-height: 66px;
}

/* ------------------------------------------------------------------ *
 * Notes under the button
 * ------------------------------------------------------------------ */

.auth-note {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.65;
    color: var(--ecv-muted, #73787b);
    text-align: start;
}

.auth-note-strong {
    color: var(--ecv-ink, #17191b);
    font-weight: 700;
}

/* ------------------------------------------------------------------ *
 * Skip link
 *
 * Every portal's navigation is followed by content; a keyboard user must be able to pass
 * it. Off-screen until focused, then a real, visible target.
 * ------------------------------------------------------------------ */

.skip-link {
    position: absolute;
    inset-inline-start: 16px;
    top: -60px;
    z-index: 10000;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 16px;
    border-radius: 0 0 8px 8px;
    background: var(--ecv-ink, #17191b);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    text-decoration: none;
    transition: top .15s ease;
}

.skip-link:focus-visible {
    top: 0;
    outline: 2px solid #fff;
    outline-offset: -4px;
}

/* ------------------------------------------------------------------ *
 * Unauthorized page
 *
 * Shared structure, portal-specific skin. Wording and layout are the same problem on all
 * three portals — somebody signed in, in the wrong place — so the shape is shared and each
 * portal only recolours it.
 * ------------------------------------------------------------------ */

.denied {
    min-height: 100svh;
    display: grid;
    grid-template-rows: auto 1fr;
}

.denied-body {
    display: grid;
    place-items: center;
    padding: clamp(24px, 6vw, 72px) 20px 80px;
}

.denied-card {
    width: 100%;
    max-width: 620px;
    background: var(--ecv-paper, #fff);
    border: 1px solid var(--ecv-line, #e5e6e4);
    border-radius: 16px;
    padding: clamp(24px, 4vw, 40px);
}

.denied-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 18px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--ecv-soft, #eff0ee);
    color: var(--ecv-ink, #17191b);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
}

html[dir="rtl"] .denied-badge {
    letter-spacing: normal;
    text-transform: none;
    font-size: 12px;
}

.denied-card h1 {
    margin: 0 0 12px;
    font-size: clamp(22px, 3.4vw, 30px);
    letter-spacing: -.015em;
    line-height: 1.2;
}

.denied-card p {
    margin: 0 0 18px;
    color: var(--ecv-muted, #73787b);
    font-size: 14.5px;
    line-height: 1.7;
}

.denied-reasons {
    margin: 0 0 26px;
    padding: 18px 20px;
    border-radius: 12px;
    background: var(--ecv-canvas, #f5f5f3);
}

.denied-reasons h2 {
    margin: 0 0 6px;
    font-size: 13px;
    letter-spacing: .04em;
}

.denied-reasons p:last-child {
    margin-bottom: 0;
}

.denied-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.denied-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    padding: 0 20px;
    border: 1px solid var(--ecv-ink, #17191b);
    border-radius: 10px;
    background: var(--sys-action-primary, var(--ecv-ink, #17191b));
    color: var(--sys-action-primary-text, #fff);
    font-size: 13.5px;
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
    font-family: inherit;
}

.denied-btn.is-ghost {
    background: transparent;
    color: var(--ecv-ink, #17191b);
    border-color: var(--ecv-line, #e5e6e4);
}

.denied-btn:focus-visible {
    outline: 2px solid var(--ecv-ink, #17191b);
    outline-offset: 3px;
}

/* ------------------------------------------------------------------ *
 * Shared navigation mechanics
 *
 * Not the look — each portal styles its own bar entirely. These are the behaviours a top
 * bar needs whatever it looks like: a keyboard-reachable account menu, and a mark that
 * inverts cleanly on a dark band.
 * ------------------------------------------------------------------ */

.pnav-mark {
    height: 30px;
    width: auto;
    display: block;
}

.pnav-mark.is-inverted {
    filter: invert(1);
    mix-blend-mode: screen;
}

.pnav-menu {
    position: relative;
}

.pnav-menu-panel {
    position: absolute;
    inset-inline-end: 0;
    top: calc(100% + 8px);
    z-index: 60;
    min-width: 236px;
    padding: 8px;
    border: 1px solid var(--ecv-line, #e5e6e4);
    border-radius: 12px;
    background: var(--ecv-paper, #fff);
    box-shadow: 0 18px 44px rgba(23, 25, 27, .16);
}

.pnav-menu-panel p {
    margin: 0;
    padding: 8px 10px 10px;
    color: var(--ecv-muted, #73787b);
    font-size: 12px;
    line-height: 1.5;
    word-break: break-word;
}

.pnav-menu-panel a,
.pnav-menu-panel button {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 42px;
    padding: 0 10px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--ecv-ink, #17191b);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 700;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.pnav-menu-panel a:hover,
.pnav-menu-panel button:hover {
    background: var(--ecv-soft, #eff0ee);
}

.pnav-menu-panel a:focus-visible,
.pnav-menu-panel button:focus-visible {
    outline: 2px solid var(--ecv-ink, #17191b);
    outline-offset: -2px;
}

.pnav-divider {
    height: 1px;
    margin: 6px 4px;
    background: var(--ecv-line, #e5e6e4);
}

/* ------------------------------------------------------------------ *
 * No flash of the sign-in form on the way back from Microsoft
 *
 * The inline script in each sign-in page's <head> stamps data-auth-return on <html> when
 * the URL carries a code or a token. These two rules act on that stamp before any module
 * has loaded, so the very first paint of a returning session is the waiting state — never
 * the form the person has already used, which reads as a rejection.
 *
 * !important because they must outrank the layout classes on the same elements, and
 * because auth-screen.js later takes over by removing the stamp.
 * ------------------------------------------------------------------ */

html[data-auth-return="1"] #authCard,
html[data-auth-return="1"] [data-auth-card] {
    display: none !important;
}

html[data-auth-return="1"] #authOverlay {
    display: flex !important;
}
