/* ---------------------------------------------------------------------------
   identity.css — layer 1 of the cascade (frontend-coding-standards.md →
   Server-rendered surfaces). Structure and layout ONLY.

   Every colour here is var(--token); the values arrive from theme.css, which is
   generated per deployment and per tenant. There is deliberately not a single
   hex literal in this file — a colour here would mean changing the palette
   required editing layout.

   Design direction "Chart" (2026-09-04, replacing "Ledger").

   Ledger set the fields as a printed slip: baseline rules instead of boxes,
   labels tracked out in small caps. On screen that read as unfinished rather
   than institutional — an underlined field looks like a field that has not been
   styled yet, sitting under a solid button that has.

   Chart is built around the one question this screen has to answer before a
   credential is typed: WHOSE system is this? (R73.) So the page is split. A
   solid navy ground carries the organisation — product, tenant, the line the
   operator wrote — and the form sits on the card beside it with nothing else
   competing for attention. The weight of a filled panel is what makes the page
   read as a considered institutional surface instead of a floating box, and it
   is honest weight: every word on it is provenance the user is meant to check.

   Two things are inherited from Ledger unchanged, because they were right:
   focus is the loudest thing on the page (on a shared terminal at shift change,
   "where am I typing" is the real usability question), and the type is a system
   stack — a sign-in page makes no third-party request (BR §6.8).
   --------------------------------------------------------------------------- */

:root {
    --radius: 0.5rem;
    --rule-focus: 3px;
    --measure: 24rem;
    --step: 0.25rem;

    /* System stack: no third-party request from a sign-in page (BR §6.8), and no
       bundler in a Razor library. Declared adaptation in ui-ux-guidelines.md. */
    --font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-utility: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    /* The brand panel's ground. In the light palette --primary IS the institutional
       navy and can carry a full-bleed surface. In dark it is a bright accent meant
       for controls, and a panel of it glares — so the dark rule below sinks it into
       the page instead of painting with it. Both are derived from tokens, never
       written as values, so this file keeps its no-literals rule. */
    --brand-surface: var(--primary);
    --on-brand: var(--primary-foreground);

    /* Secondary text on that ground: mixed toward the surface rather than written
       as a translucent white. 80% holds well clear of the 4.5:1 floor on both
       palettes, with room for a darker brand navy than the default. */
    --on-brand-muted: color-mix(in srgb, var(--on-brand) 80%, var(--brand-surface));
}

@media (prefers-color-scheme: dark) {
    :root {
        --brand-surface: color-mix(in srgb, var(--primary) 18%, var(--background));
        --on-brand: var(--foreground);
    }
}

*,
*::before,
*::after { box-sizing: border-box; }

html {
    /* rem everywhere below, so 200% zoom reflows instead of clipping (WCAG 1.4.4). */
    font-size: 100%;
}

body {
    margin: 0;
    min-height: 100vh;
    background: var(--background);
    color: var(--foreground);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
}

.skip-link:focus {
    left: calc(var(--step) * 2);
    top: calc(var(--step) * 2);
    z-index: 2;
    padding: calc(var(--step) * 2) calc(var(--step) * 3);
    background: var(--card);
    color: var(--foreground);
    border-radius: var(--radius);
    outline: var(--rule-focus) solid var(--ring);
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------- page shell */

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

/* The split arrives only when there is room for both halves to breathe. Below
   this the panel stacks above the form, which puts provenance first in reading
   order — the order R73 wants anyway, so the narrow layout is not a lesser one. */
@media (min-width: 64rem) {
    .page {
        grid-template-rows: none;
        grid-template-columns: minmax(20rem, 2fr) 3fr;
    }
}

/* ------------------------------------------------------------- brand (left) */

/* Grid rather than space-between: with the identity pinned to the top and the
   support to the bottom, a tall viewport left a well of empty navy between them
   that read as unfinished. The identity now sits in the optical centre of the
   space it owns and the foot stays low, so the panel scales from a laptop to a
   ward monitor without either half drifting. */
.brand {
    display: grid;
    grid-template-rows: 1fr auto;
    gap: calc(var(--step) * 10);
    padding: calc(var(--step) * 10) calc(var(--step) * 8);
    background: var(--brand-surface);
    color: var(--on-brand);
}

@media (min-width: 64rem) {
    .brand { padding: calc(var(--step) * 16) calc(var(--step) * 14); }
}

.brand__identity { align-self: center; }

.brand__logo {
    display: block;
    max-width: calc(var(--step) * 44);
    max-height: calc(var(--step) * 16);
    margin-bottom: calc(var(--step) * 6);
}

.brand__eyebrow {
    margin: 0;
    font-size: 0.8125rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--on-brand-muted);
}

.brand__product {
    margin: calc(var(--step) * 2) 0 0;
    font-size: clamp(1.75rem, 1.2rem + 1.8vw, 2.5rem);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.15;
}

/* The tenant is the line that actually varies between two otherwise identical
   sign-in pages, so it is set as heavily as the product name rather than as a
   subtitle under it. */
.brand__tenant {
    margin: calc(var(--step) * 3) 0 0;
    font-size: 1.125rem;
    font-weight: 500;
}

.brand__note {
    margin: calc(var(--step) * 5) 0 0;
    max-width: 34ch;
    color: var(--on-brand-muted);
}

.brand__foot {
    font-size: 0.8125rem;
    color: var(--on-brand-muted);
}

.brand__support { margin: 0; }

.brand__support a {
    color: var(--on-brand);
    text-underline-offset: 0.2em;
}

.brand__build {
    margin: calc(var(--step) * 3) 0 0;
    font-family: var(--font-utility);
    font-size: 0.75rem;
}

/* -------------------------------------------------------------- form (right) */

.panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: calc(var(--step) * 12) calc(var(--step) * 6);
}

.panel__inner {
    width: 100%;
    max-width: var(--measure);
}

.panel__heading {
    margin: 0 0 calc(var(--step) * 8);
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.panel__note {
    margin: 0;
    color: var(--muted-foreground);
}

/* ------------------------------------------------------------------ messages */

.message {
    display: flex;
    gap: calc(var(--step) * 3);
    margin-bottom: calc(var(--step) * 6);
    padding: calc(var(--step) * 3) calc(var(--step) * 4);
    /* A left rule rather than a tinted fill: theme.css carries no error-surface
       token, and inventing one here would be the colour literal this file bans. */
    border-left: var(--rule-focus) solid var(--error);
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--background);
}

.message__mark {
    flex: none;
    font-weight: 700;
    color: var(--error);
}

.message__text { margin: 0; }

/* A completed operation, not a failure. The base .message is red-ruled, so an
   acknowledgement rendered without this modifier reads as an error even when its
   role is "status" — which is exactly how the forgot-password confirmation looked. */
.message--success {
    border-left-color: var(--success);
}

.message--success .message__mark {
    color: var(--success);
}

/* ----------------------------------------------------------------- providers */

.providers { margin-bottom: calc(var(--step) * 6); }

.providers__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: calc(var(--step) * 3);
}

.provider {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: calc(var(--step) * 3);
    min-height: calc(var(--step) * 11);
    padding: calc(var(--step) * 3) calc(var(--step) * 4);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--card);
    color: var(--foreground);
    text-decoration: none;
}

.provider:hover { border-color: var(--ring); }

.provider__hint {
    font-size: 0.8125rem;
    color: var(--muted-foreground);
}

.divider {
    display: flex;
    align-items: center;
    gap: calc(var(--step) * 3);
    margin: calc(var(--step) * 6) 0;
    font-size: 0.8125rem;
    color: var(--muted-foreground);
}

.divider::before,
.divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

/* -------------------------------------------------------------------- fields */

.field { margin-bottom: calc(var(--step) * 5); }

/* Sentence case, full size, above the input. Ledger's tracked-out small caps
   made every label shout at the same volume as the heading. */
.field__label {
    display: block;
    margin-bottom: calc(var(--step) * 2);
    font-size: 0.875rem;
    font-weight: 500;
}

/* A bounded box, not a baseline rule: WCAG 1.4.11 wants the control's own extent
   perceivable, and an empty input has nothing but its boundary to show it. */
.field__input {
    width: 100%;
    min-height: calc(var(--step) * 11);
    padding: calc(var(--step) * 3) calc(var(--step) * 3.5);
    border: 1px solid var(--input);
    border-radius: var(--radius);
    background: var(--card);
    color: var(--foreground);
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.4;
}

.field__input::placeholder { color: var(--placeholder); }

.field__input:hover { border-color: var(--muted-foreground); }

/* The loudest thing on the page, deliberately. Shared terminal, shift change:
   "where am I typing" is the question the design has to answer instantly. */
.field__input:focus-visible {
    outline: var(--rule-focus) solid var(--ring);
    outline-offset: 2px;
    border-color: var(--ring);
}

.field__input[aria-invalid="true"] { border-color: var(--error); }

/* --------------------------------------------------------------- action, link */

.actions { margin-top: calc(var(--step) * 7); }

.button--primary {
    display: block;
    width: 100%;
    min-height: calc(var(--step) * 12);
    padding: calc(var(--step) * 3) calc(var(--step) * 5);
    border: 0;
    border-radius: var(--radius);
    background: var(--primary);
    color: var(--primary-foreground);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: filter 120ms ease;
}

.button--primary:hover { filter: brightness(1.12); }

.button--primary:focus-visible {
    outline: var(--rule-focus) solid var(--ring);
    outline-offset: 2px;
}

/* --primary, not --muted-foreground. Muted grey on the page ground measures
   4.50:1 — it passes by five thousandths, which is not a margin worth defending
   on the one link a locked-out user needs to find. This also makes it read as an
   action rather than as a caption. */
.link {
    display: inline-block;
    margin-top: calc(var(--step) * 5);
    color: var(--primary);
    font-size: 0.875rem;
    text-underline-offset: 0.2em;
}

.link:hover { color: var(--foreground); }

.link:focus-visible {
    outline: var(--rule-focus) solid var(--ring);
    outline-offset: 2px;
    border-radius: calc(var(--radius) / 2);
}

/* The error page. Structure only — every colour comes from theme.css, like the rest of this file. */
.problem__status {
    margin: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    color: var(--muted-foreground);
}

.problem__heading {
    margin: calc(var(--step) * 2) 0 0;
    font-size: 1.375rem;
}

.problem__detail {
    margin: calc(var(--step) * 3) 0 0;
    color: var(--muted-foreground);
}

/* Selectable and monospaced: its only job is to be copied into a support request, where one
   transposed character makes it useless. */
.problem__reference {
    margin: calc(var(--step) * 5) 0 0;
    padding: calc(var(--step) * 3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.problem__reference-label {
    display: block;
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}

.problem__reference-value {
    display: block;
    margin-top: calc(var(--step) * 1);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    word-break: break-all;
    user-select: all;
}

/* Directly under the reference, because the two are used together: the address to write to and
   the identifier to quote in the message. */
.problem__support {
    margin: calc(var(--step) * 3) 0 0;
    color: var(--muted-foreground);
}

.problem__support a {
    color: var(--foreground);
    text-underline-offset: 0.2em;
}

.problem__action {
    margin-top: calc(var(--step) * 6);
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}
