/* Admin console — one stylesheet, no build step (spec-admin-gui §3.0).
   Deliberately its own file rather than an import of `frontend-user/dist/css/*`: this is a separate
   origin (spec §3.0③) with a different audience, and sharing a stylesheet would make every user-
   facing visual change a console change too. The palette matches the user frontend so an operator
   moving between the two tabs is not re-learning colours. */

/*
   Self-hosted fonts (audit L-2, owner ruling 2026-10-10).

   Replaces `@import url("https://fonts.googleapis.com/...")`. That import had three problems and
   only the first is the obvious one: it fetched the CSS and the font files from a third party,
   leaking every visitor's IP and Referer to Google; it could not carry an SRI hash, so the bytes
   were trusted on transport alone; and — the one that mattered for CSP — a remote `@import` means
   the page's `style-src` and `font-src` must name an external origin, which is exactly the
   allowance `script-src 'self'` work wants to remove.

   Four files, not sixteen: Outfit and JetBrains Mono both ship as VARIABLE fonts, so all five
   Outfit weights and all three JetBrains weights resolve to one file per subset. Serving the
   per-weight copies Google's API returns would have been five identical downloads.

   Only `latin` and `latin-ext` are kept. The upstream CSS also declares cyrillic, greek and
   vietnamese subsets — none of which this market's UI can produce text in, and each of which would
   have been another 20-60 KB of font data per page load for glyphs no user will see.

   `font-display: swap` and the `unicode-range` declarations are copied from the upstream CSS
   unchanged. The ranges are load-bearing rather than descriptive: they are what tells the browser
   a `latin-ext` file need not be fetched for a page of plain ASCII.
*/
@font-face {
    font-family: "Outfit";
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url("../vendor/fonts/outfit-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Outfit";
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url("../vendor/fonts/outfit-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "JetBrains Mono";
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url("../vendor/fonts/jetbrains-mono-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "JetBrains Mono";
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url("../vendor/fonts/jetbrains-mono-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    --bg-dark: #0a0a0a;
    --bg-card: rgba(20, 20, 20, 0.95);
    --bg-card-solid: #141414;
    --bg-input: #0f0f0f;
    --border-dark: rgba(255, 255, 255, 0.12);
    --border-glow: rgba(0, 240, 255, 0.3);

    --cyan: #00f0ff;
    --cyan-bright: #5cffff;
    --cyan-glow: rgba(0, 240, 255, 0.4);
    --magenta: #ff007f;

    --green: #10b981;
    --red: #ef4444;
    --amber: #f59e0b;

    --text-primary: #f8fafc;
    --text-secondary: #94a3b8;
    --text-muted: #475569;

    --sidebar-w: 208px;
}

* { margin: 0; padding: 0; box-sizing: border-box; font-family: "Outfit", sans-serif; }

body {
    background: var(--bg-dark);
    color: var(--text-primary);
    min-height: 100vh;
}

/* `[hidden]` must beat any later `display` rule. The user-agent rule is a bare `display: none`
   and loses to any author rule that sets `display`, so a hidden element would still draw — the
   same trap `frontend-user/dist/css/app.css` documents. */
[hidden] { display: none !important; }

a { color: var(--cyan); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Layout ──────────────────────────────────────────────────────────────────── */
.layout { display: flex; min-height: 100vh; }

.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    background: var(--bg-card-solid);
    border-right: 1px solid var(--border-dark);
    padding: 20px 0;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}
.brand {
    font-size: 14px;
    font-weight: 600;
    color: var(--cyan);
    padding: 0 18px 16px;
    letter-spacing: 0.4px;
}
.nav-group {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--text-muted);
    padding: 14px 18px 6px;
}
.nav-item {
    display: block;
    padding: 9px 18px;
    font-size: 14px;
    color: var(--text-secondary);
    border-left: 2px solid transparent;
}
.nav-item:hover { background: rgba(255, 255, 255, 0.04); color: var(--text-primary); text-decoration: none; }
.nav-item.active { color: var(--cyan); border-left-color: var(--cyan); background: rgba(0, 240, 255, 0.06); }
.nav-foot { padding: 18px; margin-top: 12px; }

.main { flex: 1; padding: 26px 32px 64px; min-width: 0; }
.title { font-size: 24px; font-weight: 700; margin-bottom: 4px; }
.subtitle { font-size: 13px; color: var(--text-secondary); margin-bottom: 22px; line-height: 1.5; }

/* ── Cards ───────────────────────────────────────────────────────────────────── */
.card {
    background: var(--bg-card);
    border: 1px solid var(--border-dark);
    border-radius: 14px;
    padding: 18px;
    margin-bottom: 18px;
}
.card-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 14px;
}
.card-title .hint { font-size: 12px; font-weight: 400; color: var(--text-muted); }

.grid { display: grid; gap: 18px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* ── Key/value rows ──────────────────────────────────────────────────────────── */
.kv {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 7px 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    font-size: 13px;
}
.kv:last-child { border-bottom: none; }
.kv .k { color: var(--text-secondary); flex: 0 0 auto; }
.kv .v { font-family: "JetBrains Mono", monospace; text-align: right; word-break: break-all; }
.mono { font-family: "JetBrains Mono", monospace; }
.num { font-family: "JetBrains Mono", monospace; font-size: 15px; }

.v.ok { color: var(--green); }
.v.bad { color: var(--red); }
.v.warn { color: var(--amber); }
.v.dim { color: var(--text-muted); }
.accent { color: var(--cyan); }

/* ── Controls ────────────────────────────────────────────────────────────────── */
input, select, textarea {
    background: var(--bg-input);
    border: 1px solid var(--border-dark);
    border-radius: 8px;
    color: var(--text-primary);
    padding: 8px 10px;
    font-size: 13px;
    font-family: "JetBrains Mono", monospace;
    width: 100%;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--cyan); }
input:disabled, select:disabled { opacity: 0.45; cursor: not-allowed; }
label.field { display: block; font-size: 12px; color: var(--text-secondary); margin-bottom: 4px; }

/*
 * A date plus an hour and a minute, in one control group (the recovery panel's range).
 *
 * The parts are separate inputs rather than one `datetime-local` because the value has to be read
 * as UTC: a `datetime-local` is zone-free by construction, so the browser's own picker would draw
 * the operator's LOCAL clock faces and the page would then have to convert — which is the ambiguity
 * the control was changed to remove. Three explicit boxes with a UTC label have no such gap.
 *
 * `flex` on the children overrides the global `input { width: 100% }` (a `flex-basis` of 0 beats a
 * declared width), which is what lets the two number boxes sit narrow beside the date.
 */
.dt { display: flex; align-items: center; gap: 6px; }
.dt > input[type="date"] { flex: 1.9; min-width: 0; }
.dt > input[type="number"] { flex: 0 0 58px; text-align: center; padding: 8px 4px; }
.dt > .dt-sep { color: var(--text-muted); flex: 0 0 auto; }
/* The spinners are wider than the box they sit in at 58px and push the digits off-centre. */
.dt > input[type="number"]::-webkit-outer-spin-button,
.dt > input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.dt > input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

button {
    background: rgba(0, 240, 255, 0.1);
    border: 1px solid var(--border-glow);
    border-radius: 8px;
    color: var(--cyan);
    padding: 8px 14px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    font-family: "Outfit", sans-serif;
    white-space: nowrap;
}
button:hover:not(:disabled) { background: rgba(0, 240, 255, 0.18); }
button:disabled { opacity: 0.4; cursor: not-allowed; }
button.ghost { background: none; border-color: var(--border-dark); color: var(--text-secondary); }
button.ghost:hover:not(:disabled) { color: var(--text-primary); }
button.danger { background: rgba(239, 68, 68, 0.12); border-color: var(--red); color: #fca5a5; }
button.danger:hover:not(:disabled) { background: rgba(239, 68, 68, 0.22); }
button.primary { background: rgba(16, 185, 129, 0.12); border-color: var(--green); color: #6ee7b7; }
button.primary:hover:not(:disabled) { background: rgba(16, 185, 129, 0.22); }
button.small { padding: 5px 10px; font-size: 12px; }

.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row > .grow { flex: 1; min-width: 160px; }

/* ── Tables ──────────────────────────────────────────────────────────────────── */
/* Wide tables scroll inside their own box; the page body never scrolls sideways. */
.table-wrap { overflow-x: auto; border: 1px solid var(--border-dark); border-radius: 12px; }
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
th, td { padding: 9px 12px; text-align: left; white-space: nowrap; }
th {
    background: rgba(255, 255, 255, 0.03);
    color: var(--text-secondary);
    font-weight: 500;
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border-dark);
    position: sticky;
    top: 0;
}
td { border-bottom: 1px solid rgba(255, 255, 255, 0.05); font-family: "JetBrains Mono", monospace; }
tbody tr:hover { background: rgba(255, 255, 255, 0.03); }
td.right, th.right { text-align: right; }
.copy { cursor: pointer; border-bottom: 1px dotted var(--text-muted); }
.copy:hover { color: var(--cyan); }

/* ── Filters, pager ──────────────────────────────────────────────────────────── */
.filters { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.check { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-secondary); cursor: pointer; }
.check input { width: auto; }
/* The rule between two filter GROUPS was `.filters .group-sep`, deleted 2026-09-15 with the last
   element that used it. There are no groups left to draw: the four-round-old reading of the
   Positions tick-boxes as "five STATES, then Settled, then two DIRECTIONS" was wrong — `Settled`
   and the verdict boxes compose rather than exclude, `Expired, unjudged` and `Unsettled` overlap
   on the stuck rows, and every remaining apparent conflict is one column holding two values, which
   the query settles on its own. Eight boxes, eight independent tags, no boundary to mark — see
   `admin-lists.ts`'s filter note. The class is gone rather than left behind because a rule the
   stylesheet still carries but no page emits is the kind of thing the next reader goes looking for
   an element for. */
.pager { display: flex; align-items: center; gap: 12px; margin-top: 14px; font-size: 13px; color: var(--text-secondary); }

/* ── Audit stream ────────────────────────────────────────────────────────────── */
.audit-row {
    display: grid;
    grid-template-columns: 178px 190px 1fr;
    gap: 10px;
    padding: 6px 10px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    font-family: "JetBrains Mono", monospace;
    font-size: 12px;
    align-items: baseline;
}
.audit-row:hover { background: rgba(255, 255, 255, 0.03); }
.audit-row .ts { color: var(--text-muted); }
.audit-row .ev { color: var(--text-secondary); }
.audit-row .detail { color: var(--text-primary); white-space: pre-wrap; word-break: break-word; }
.audit-row.error .ev { color: var(--red); }
.audit-row.warn .ev { color: var(--amber); }
.audit-stream {
    max-height: 60vh;
    overflow-y: auto;
    border: 1px solid var(--border-dark);
    border-radius: 12px;
    background: var(--bg-card);
}

/* ── Notices ─────────────────────────────────────────────────────────────────── */
.notice {
    border-radius: 12px;
    padding: 11px 15px;
    font-size: 13px;
    line-height: 1.5;
    margin-bottom: 16px;
    border: 1px solid var(--border-dark);
}
.notice.warn { background: rgba(245, 158, 11, 0.1); border-color: var(--amber); color: #fcd34d; }
.notice.error { background: rgba(239, 68, 68, 0.1); border-color: var(--red); color: #fca5a5; }
.notice.info { background: rgba(0, 240, 255, 0.06); border-color: var(--border-glow); color: var(--cyan-bright); }
.notice code { font-family: "JetBrains Mono", monospace; }

.toast {
    position: fixed;
    right: 18px;
    bottom: 18px;
    z-index: 999;
    max-width: 420px;
    background: var(--bg-card-solid);
    border: 1px solid var(--border-dark);
    border-left: 3px solid var(--cyan);
    border-radius: 10px;
    padding: 11px 15px;
    font-size: 13px;
    line-height: 1.45;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
    white-space: pre-wrap;
}
.toast.error { border-left-color: var(--red); }
.toast.warn { border-left-color: var(--amber); }
.toast.ok { border-left-color: var(--green); }

pre.json {
    background: var(--bg-input);
    border: 1px solid var(--border-dark);
    border-radius: 10px;
    padding: 14px;
    font-size: 12px;
    font-family: "JetBrains Mono", monospace;
    overflow-x: auto;
    max-height: 48vh;
    overflow-y: auto;
    color: var(--text-secondary);
    white-space: pre-wrap;
    word-break: break-word;
}

.empty { color: var(--text-muted); font-size: 13px; padding: 14px; }

/* ── Sign-in page ────────────────────────────────────────────────────────────── */
.signin {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 24px;
}
.signin .card { width: 100%; max-width: 460px; margin: 0; }
.signin .title { font-size: 20px; }
.step { font-size: 13px; color: var(--text-secondary); line-height: 1.6; }

/* ── Narrow screens ──────────────────────────────────────────────────────────── */
/* The sidebar becomes a horizontal strip. Not a drawer: an operator's console is used at a
   desk, and a hamburger that hides the navigation would cost more than it saves. */
@media (max-width: 760px) {
    .layout { flex-direction: column; }
    .sidebar {
        width: 100%;
        flex: 0 0 auto;
        height: auto;
        position: static;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 2px;
        padding: 10px 12px;
        border-right: none;
        border-bottom: 1px solid var(--border-dark);
    }
    .brand { padding: 0 12px 0 0; }
    .nav-group { display: none; }
    .nav-item { border-left: none; border-bottom: 2px solid transparent; padding: 6px 10px; border-radius: 6px; }
    .nav-item.active { border-left: none; border-bottom-color: var(--cyan); }
    .nav-foot { padding: 0; margin: 0 0 0 auto; }
    .main { padding: 18px 16px 48px; }
    .audit-row { grid-template-columns: 1fr; gap: 2px; }
    .audit-row .ts { font-size: 11px; }
}
