/* The Cogito Systems auth surface: the "split panel" layout (option 1a) from the design system's
   explorations/Login options.html, plus the primitives that exploration shares with its other two
   options. Tokens come from tokens/*.css, ported verbatim; nothing here should hard-code a colour,
   a radius or a step of the spacing scale.

   Two things about the shape of this file:

   The component primitives are all scoped under `.auth`, which _AuthLayout puts on its wrapper.
   That is not cosmetic — `.btn`, `.card` and friends collide by name with Bootstrap's, and the
   Duende management pages still run on Bootstrap under _Layout. Scoping lets both layouts link
   this one stylesheet: the management pages pick up the tokens and `.notice`, and nothing else.

   NOTE (Opus 5): the exploration carries most of its values in inline style="" attributes. Those
   cannot survive here — SecurityHeadersAttribute sets "default-src 'self'" and style-src inherits
   it, so an inline style attribute is blocked by the browser and the page renders unstyled. Every
   value the exploration inlines has been given a class below. Do not reintroduce style="". */

@import "fonts.css";
@import "tokens/colors.css";
@import "tokens/typography.css";
@import "tokens/spacing.css";
@import "tokens/radius.css";
@import "tokens/shadows.css";
@import "tokens/motion.css";

/* ═══════════════════════════════════════════ global — both layouts ═══════ */

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

body { margin: 0; }

/* The provider/passkey icon sprite. Kept out of the grid flow rather than positioned with a style
   attribute, which the CSP would block. */
.svg-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.is-hidden { display: none; }

.notice {
    padding: var(--space-3) var(--space-4);
    border: 1px solid;
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
}

.notice strong { display: block; font-weight: var(--weight-semibold); }
.notice ul { margin: var(--space-1) 0 0; padding-left: var(--space-4); }
.notice--danger { background: var(--danger-subtle); border-color: var(--danger-muted-border); color: var(--danger-fg); }
.notice--success { background: var(--success-subtle); border-color: var(--success-muted-border); color: var(--success-fg); }
.notice--warning { background: var(--warning-subtle); border-color: var(--warning-muted-border); color: var(--warning-fg); }
.notice--info { background: var(--accent-subtle); border-color: var(--accent-muted-border); color: var(--accent-fg); }

/* ═══════════════════════════════════════════ the split-panel shell ═══════ */

.auth {
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-height: 100vh;
    font-family: var(--font-sans);
    font-size: var(--text-body);
    line-height: var(--leading-normal);
    color: var(--fg-default);
    background: var(--surface-canvas);
}

.auth-panel {
    /* Swap the photograph or retune the shade here — nothing else refers to either. The shade is
       --gray-950 at opacity, so it agrees with the background-color underneath it. */
    --panel-image: url("../img/banner.jpg");
    --panel-shade: rgba(10, 12, 15, .72);

    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: var(--space-16);
    color: var(--fg-onEmphasis);
    position: relative;
    overflow: hidden;

    /* The colour is the floor: it holds the panel dark while the photograph loads, and if the
       request ever fails the panel degrades to the flat --gray-950 the design started from. */
    background-color: var(--gray-950);
    background-image: linear-gradient(var(--panel-shade), var(--panel-shade)), var(--panel-image);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* The glow the exploration anchors to the panel's bottom-left corner. */
.auth-panel::after {
    content: "";
    position: absolute;
    inset: auto -20% -35% -20%;
    height: 70%;
    background: radial-gradient(60% 100% at 30% 100%, rgba(59, 91, 254, .5), transparent 70%);
}

.auth-quote { position: relative; z-index: 1; max-width: 30ch; }

.auth-quote p {
    margin: 0;
    font-size: var(--text-2xl);
    font-weight: var(--weight-medium);
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-tight);
    color: var(--gray-0);
}

.auth-quote span {
    display: block;
    margin-top: var(--space-4);
    font-size: var(--text-sm);
    /* One step lighter than the design's --gray-400. That token was chosen against a flat
       --gray-950 panel, where it measured 7.7:1; over the photograph the backdrop here is roughly
       #43464A and it falls to 3.8:1, under AA for text this size. --gray-300 restores it to 5.6:1
       without darkening the photograph further. Retune if --panel-shade changes much. */
    color: var(--gray-300);
}

.auth-meta {
    position: relative;
    z-index: 1;
    display: flex;
    gap: var(--space-6);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--gray-500);
}

.auth-form {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-16);
}

.auth-form > .auth-column {
    width: 100%;
    max-width: 352px;
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

/* Consent lists more scopes than a sign-in form has fields, so it gets a wider column. */
.auth-form > .auth-column--wide { max-width: 520px; }

/* ────────────────────────────────────────────────────── the word mark ─── */

.auth .mark { display: flex; align-items: center; gap: var(--space-2); }
.auth .mark-logo { height: 60px; width: 60px; object-fit: contain; display: block; }

/* Lifted above .auth-panel::after, which is absolutely positioned and would otherwise paint over
   it — the quote and the meta line already sit on the same layer. */
.auth-panel .mark { gap: var(--space-3); position: relative; z-index: 1; }
.auth-panel .mark-logo { height: 96px; width: 96px; }

/* Stands in for the panel's mark once the panel is hidden — see the media query at the foot. */
.auth .mark--compact { display: none; }

.auth .mark-name {
    font-size: var(--text-md);
    font-weight: var(--weight-regular);
    color: var(--fg-subtle);
    letter-spacing: var(--tracking-normal);
}

.auth-panel .mark-name { font-size: var(--text-lg); color: var(--gray-400); }

/* ─────────────────────────────────────────────────────────────── type ─── */

.auth h1 {
    margin: 0;
    font-size: var(--text-2xl);
    font-weight: var(--weight-bold);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-tight);
}

.auth .sub { margin: var(--space-2) 0 0; font-size: var(--text-sm); color: var(--fg-subtle); }

.auth a { color: var(--fg-link); text-decoration: none; }
.auth a:hover { color: var(--fg-link-hover); text-decoration: underline; }

.auth .stack { display: flex; flex-direction: column; gap: var(--space-4); }

/* ───────────────────────────────────────────────────────────── fields ─── */

.auth .field { display: flex; flex-direction: column; gap: var(--space-2); }

.auth .lab {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--fg-muted);
    margin: 0;
}

.auth .lab-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }

.auth .lab-aside {
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    letter-spacing: var(--tracking-normal);
    text-transform: none;
}

.auth .lab-aside--off { color: var(--gray-400); cursor: not-allowed; }

.auth .inp {
    width: 100%;
    padding: 10px var(--space-3);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    font: var(--weight-regular) var(--text-body)/1.4 var(--font-sans);
    color: var(--fg-default);
    background: var(--surface-canvas);
    outline: none;
    transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}

.auth .inp::placeholder { color: var(--gray-400); }
.auth .inp:focus { border-color: var(--border-emphasis); box-shadow: var(--shadow-focus); }
.auth .inp[aria-invalid="true"] { border-color: var(--danger-emphasis); }

.auth .hint { font-size: var(--text-xs); color: var(--fg-subtle); }

/* Real checkbox rather than the exploration's decorative <i>, so it stays operable and labelled. */
.auth .chk { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--fg-muted); }

.auth .chk input[type="checkbox"] {
    width: 15px;
    height: 15px;
    margin: 0;
    flex: none;
    accent-color: var(--brand-primary);
}

.auth .chk input[type="checkbox"]:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

/* ──────────────────────────────────────────────────────────── buttons ─── */

.auth .btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    min-height: 40px;
    padding: 10px var(--space-4);
    border-radius: var(--radius-md);
    font: var(--weight-semibold) var(--text-body)/1 var(--font-sans);
    cursor: pointer;
    border: 1px solid transparent;
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}

.auth .btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

.auth .btn--primary { background: var(--brand-primary); border-color: var(--brand-primary); color: var(--fg-onEmphasis); }
.auth .btn--primary:hover { background: var(--brand-primary-hover); border-color: var(--brand-primary-hover); }
.auth .btn--primary:active { background: var(--brand-primary-active); border-color: var(--brand-primary-active); }

.auth .btn--ghost { background: var(--surface-canvas); border-color: var(--border-default); color: var(--fg-default); font-weight: var(--weight-medium); }
.auth .btn--ghost:hover { border-color: var(--border-strong); background: var(--gray-50); }
.auth a.btn--ghost:hover { color: var(--fg-default); text-decoration: none; }

.auth .btn svg { width: 17px; height: 17px; flex: none; }
.auth .btn--muted-icon svg { color: var(--fg-muted); }

.auth .btn--sm { font-size: var(--text-sm); gap: 6px; padding: 10px var(--space-2); }
.auth .btn--sm svg { width: 15px; height: 15px; }

/* The provider buttons and the password-reset link render as designed but do nothing: no external
   identity provider can be configured and there is no reset flow. Disabled rather than removed so
   the gap is visible rather than silently absent. */
.auth .btn:disabled {
    cursor: not-allowed;
    opacity: .5;
    background: var(--surface-canvas-inset);
    border-color: var(--border-muted);
    color: var(--fg-subtle);
}

.auth .btn:disabled:hover { background: var(--surface-canvas-inset); border-color: var(--border-muted); }

.auth .btn-row { display: flex; gap: var(--space-2); }
.auth .btn-row > .btn { width: auto; flex: 1; }

/* ────────────────────────────────────────────── rules and providers ───── */

.auth .rule {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--gray-400);
}

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

.auth .providers { display: grid; gap: var(--space-2); }
.auth .providers--row { grid-template-columns: repeat(3, 1fr); }

.auth .foot { font-size: var(--text-xs); color: var(--fg-subtle); line-height: var(--leading-snug); }
.auth .foot a { color: var(--fg-muted); text-decoration: underline; text-decoration-color: var(--border-strong); }

/* ──────────────────────────────────────────────────────────── consent ─── */

/* Option 2b of the design system's explorations/Consent options.html: one row per capability, in
   plain language, rather than the bordered ledger 2a kept. The row carries the meaning, so there is
   no box around the list — `.perms` replaced `.scopes`, which nothing renders any more. */

.auth .perms { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.auth .perms > li {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: var(--space-3);
    align-items: start;
    padding: var(--space-4) 0;
    border-bottom: 1px solid var(--border-muted);
}
.auth .perms > li:first-child { padding-top: 0; }
.auth .perms > li:last-child { border-bottom: 0; }

.auth .perm-icon {
    width: 28px;
    height: 28px;
    border-radius: var(--radius-full);
    background: var(--accent-subtle);
    color: var(--accent-fg);
    display: grid;
    place-items: center;
    flex: none;
}
.auth .perm-icon svg { width: 15px; height: 15px; }
/* Amber tracks Emphasize, the same flag that earns the "Sensitive" word beside the title. */
.auth .perm-icon--warn { background: var(--warning-subtle); color: var(--warning-fg); }

.auth .perm-title {
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    flex-wrap: wrap;
    font-size: var(--text-body);
    font-weight: var(--weight-medium);
}
.auth .perm-note { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--fg-subtle); line-height: var(--leading-snug); }
.auth .perm-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-top: 2px;
    font-size: var(--text-xs);
    color: var(--fg-muted);
    white-space: nowrap;
}
.auth .perm-toggle input[type="checkbox"] { width: 15px; height: 15px; margin: 0; accent-color: var(--brand-primary); }
.auth .perm-locked { padding-top: 2px; font-size: var(--text-xs); color: var(--fg-subtle); white-space: nowrap; }

.auth .scope-emphasis {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--warning-fg);
}
.auth .scope-value { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--fg-subtle); }

.auth .resources { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: var(--space-2); }
.auth .resources-label { font-size: var(--text-xs); color: var(--fg-subtle); }
.auth .chip {
    padding: 2px var(--space-2);
    border: 1px solid var(--border-muted);
    border-radius: var(--radius-full);
    background: var(--surface-canvas-inset);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--fg-muted);
}

.auth .divider { height: 1px; margin: 0; border: 0; background: var(--border-default); }

.auth .destination { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--fg-subtle); }
.auth .destination svg { width: 14px; height: 14px; flex: none; color: var(--fg-muted); }
.auth .destination b { font-family: var(--font-mono); font-weight: var(--weight-medium); color: var(--fg-default); }

.auth .revoke { margin: 0; font-size: var(--text-xs); color: var(--fg-subtle); }

/* ───────────────────────────────────────────────────────── device flow ─── */
/* explorations/Device flow.html — 3a code entry, 3b confirmation, 3c success. */

/* The one input on any of these pages that is transcribed rather than composed: mono so O and 0 are
   distinguishable at a glance, tracked out so eight characters read as eight, and uppercased in the
   field so what is typed matches what the device showed. The transform is cosmetic — the value still
   posts as typed, which is why the page normalises it server-side. */
.auth .inp--code {
    padding: var(--space-4) var(--space-3);
    font-family: var(--font-mono);
    font-size: var(--text-2xl);
    font-weight: var(--weight-medium);
    letter-spacing: .22em;
    text-align: center;
    text-transform: uppercase;
}
.auth .inp--code::placeholder { letter-spacing: .22em; color: var(--gray-300); }
.auth .inp[aria-invalid="true"] { border-color: var(--danger-emphasis); }
.auth .hint { margin: 0; font-size: var(--text-xs); color: var(--fg-subtle); }

/* The code repeated back on the approval page. This is the whole security value of the ceremony —
   it is what stops a code phished onto someone else's screen being approved by them — so it sits
   above the form rather than inside the prose. */
.auth .code-echo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-canvas-inset);
}
.auth .code-echo-label { font-size: var(--text-xs); color: var(--fg-subtle); line-height: var(--leading-snug); }
.auth .code-echo-value {
    font-family: var(--font-mono);
    font-size: var(--text-lg);
    font-weight: var(--weight-medium);
    letter-spacing: .12em;
    color: var(--fg-default);
    white-space: nowrap;
}

.auth .done { display: flex; flex-direction: column; gap: var(--space-5); align-items: flex-start; }
.auth .done-head { display: flex; align-items: center; gap: var(--space-3); }
.auth .status-icon {
    width: 26px;
    height: 26px;
    flex: none;
    border-radius: var(--radius-full);
    display: grid;
    place-items: center;
    background: var(--success-subtle);
    color: var(--success-fg);
}
.auth .status-icon svg { width: 15px; height: 15px; }

.auth .summary { width: 100%; margin: 0; padding: 0; border: 1px solid var(--border-default); border-radius: var(--radius-md); }
/* The rows are <div>s wrapping dt/dd, which is the only grouping a <dl> permits. */
.auth .summary > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-muted);
    font-size: var(--text-sm);
}
.auth .summary > div:last-child { border-bottom: 0; }
.auth .summary dt { margin: 0; color: var(--fg-subtle); }
.auth .summary dd { margin: 0; font-weight: var(--weight-medium); text-align: right; }
.auth .summary .mono { font-family: var(--font-mono); font-weight: var(--weight-regular); }

.auth .group-label {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--fg-muted);
    margin: 0 0 var(--space-2);
}

.auth .client-logo img { max-height: 48px; max-width: 160px; object-fit: contain; }

.auth .request-id { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--fg-subtle); }

.auth .signout-frame { display: none; width: 0; height: 0; border: 0; }

/* ───────────────────────────────────────────────────────── responsive ─── */

@media (max-width: 900px) {
    .auth { grid-template-columns: 1fr; }
    .auth-panel { display: none; }

    /* Deliberately unlike the exploration's mobile frame, which pins the form to the top left. With
       the panel gone there is nothing for it to align against, so it keeps the centring the base
       rule already gives it and only the padding tightens. Centring is safe against tall content
       here because .auth is min-height rather than height — the grid row grows to fit, so the
       cross-axis never overflows and clips the top of the form. */
    .auth-form { padding: var(--space-6); }

    .auth-form > .auth-column { gap: var(--space-5); }
    .auth .mark--compact { display: flex; }
    .auth h1 { font-size: var(--text-xl); }
    .auth .btn, .auth .inp { min-height: 44px; }
    .auth .inp { padding: 12px var(--space-3); font-size: var(--text-md); }

    /* After the .inp rule above, which would otherwise take the code field down to body size. */
    .auth .inp--code { font-size: var(--text-xl); padding: var(--space-4) var(--space-3); }
}

@media (prefers-reduced-motion: reduce) {
    .auth .btn, .auth .inp { transition: none; }
}
