﻿/*
 * RECF Data Hub — the app's own components, on top of the RECF Aurora theme.
 *
 * Load order matters: recf-aurora.css first (palette, dark mode, chrome), this second (screens).
 *
 * BRAND COLOURS ARE FIXED IN BOTH THEMES. They are the tokens measured from recf.org and mirrored
 * in Infrastructure/Reporting/RecfBrand.cs so the site, the Excel exports and the PDFs agree —
 * change both together. A PDF has no dark mode, so these must not move with the theme.
 *
 * SURFACES AND INK ARE NOT. Everything a component paints with resolves through the semantic
 * tokens below, which are redefined under [data-bs-theme="dark"]. That is the whole mechanism: no
 * component rule names a grey directly, so adding a screen costs nothing extra to make work in both
 * themes, and forgetting is visible immediately rather than as one unreadable panel on one ground.
 *
 * Deliberate deviation from recf.org: it sets an 18px body. This is a dense internal data tool, so
 * the base is 16px to fit more rows on screen. Fonts and heading scale are unchanged.
 */

:root {
    /* Brand. Identical in both themes — see above. */
    --recf-navy: #1b365d;
    --recf-red: #d9272e;
    --recf-blue: #0075c9;
    --recf-blue-light: #049dd9;
    --recf-green: #42c24c;
    --recf-yellow: #f1b71c;

    --recf-font-body: "Lato", "Segoe UI", system-ui, sans-serif;
    --recf-font-heading: "Montserrat", "Segoe UI", system-ui, sans-serif;

    --recf-container: 1320px;

    /* Semantic surfaces and ink. Redefined for dark below; nothing else should hardcode a grey. */
    --recf-body: #212721;
    --recf-surface: #fff;
    --recf-surface-muted: #f7f7f7;
    --recf-surface-sunk: #ececec;
    --recf-line: #d9d9d8;
    --recf-ink-muted: #7d7c7a;
    --recf-ink-faint: #b2b1af;
    --recf-heading: #1b365d;

    /* A solid ground that always carries white text: table headers, primary buttons. Separate from
       --recf-heading, which is INK and goes light in dark mode — using one for the other paints
       white on near-white. */
    --recf-brand-surface: #1b365d;
    --recf-brand-surface-hover: #14294a;

    /* Accent tint behind a header strip or a selected row. */
    --recf-accent-wash: linear-gradient(180deg, #f3f8ff 0%, #e2ecfa 100%);
    --recf-accent-tint: #eef4fc;

    /* States. Readable on the ground they sit on, which is why they move with the theme even
       though the brand colours do not. */
    --recf-ok: #2f7d36;
    --recf-due: #a8161c;
    --recf-warn-bg: #fdf4e7;
    --recf-warn-bg-strong: #f9eddc;

    /* Traffic heat ramp, light to dark. */
    --recf-heat-0: #ececec;
    --recf-heat-1: #cfe0f2;
    --recf-heat-2: #9dc0e4;
    --recf-heat-3: #5d94cd;
    --recf-heat-4: #2f6bab;
    --recf-heat-5: #1b365d;

    /* Bootstrap overrides so stock components pick the brand up automatically. */
    --bs-primary: #1b365d;
    --bs-primary-rgb: 27, 54, 93;
    --bs-body-font-family: var(--recf-font-body);
}

/* Dark. Only the semantic tokens move — every component rule below is untouched by this block,
   which is the point of routing them through tokens in the first place. */
[data-bs-theme="dark"] {
    --recf-body: #e6e4e1;
    --recf-surface: #1a1d21;
    --recf-surface-muted: #23272d;
    --recf-surface-sunk: #2b3037;
    --recf-line: #3a4048;
    --recf-ink-muted: #9aa1ab;
    --recf-ink-faint: #6f7783;

    /* Navy headings vanish on a near-black ground, so headings take the violet accent that
       carries the dark theme across every RECF app. */
    --recf-heading: #c4b5fd;

    /* Deep violet rather than navy: navy is barely distinguishable from the dark ground, so a
       table header on it stops reading as a header at all. */
    --recf-brand-surface: #4c1d95;
    --recf-brand-surface-hover: #5b21b6;

    --recf-accent-wash: linear-gradient(180deg, #262232 0%, #1e1b28 100%);
    --recf-accent-tint: #2a2437;

    /* Lifted so they clear AA on the dark ground; the light values are too dim to read there. */
    --recf-ok: #4ade80;
    --recf-due: #f87171;
    --recf-warn-bg: rgba(240, 182, 92, .12);
    --recf-warn-bg-strong: rgba(240, 182, 92, .2);

    /* The ramp inverts: dark means quiet, bright means busy, so the busiest cells still shout. */
    --recf-heat-0: #2b3037;
    --recf-heat-1: #274263;
    --recf-heat-2: #2f6bab;
    --recf-heat-3: #4a8ccd;
    --recf-heat-4: #7cb0e0;
    --recf-heat-5: #b7d6f2;

    --bs-primary: #7c3aed;
    --bs-primary-rgb: 124, 58, 237;
}

body {
    font-family: var(--recf-font-body);
    font-size: 16px;
    line-height: 1.5;
}

h1, h2, h3, h4, h5, h6, .recf-heading {
    font-family: var(--recf-font-heading);
    font-weight: 600; /* recf.org uses 600, not bold */
    color: var(--recf-heading);
}

/* 16px base x 1.25 major-third scale, matching recf.org */
h1 { font-size: 3.052rem; }
h2 { font-size: 2.441rem; }
h3 { font-size: 1.953rem; }
h4 { font-size: 1.563rem; }
h5 { font-size: 1.25rem; }
h6 { font-size: 1rem; }

.container, .container-fluid.recf-container {
    max-width: var(--recf-container);
}

/* ---------- Header ---------- */

/* The bar follows the theme rather than staying solid navy, which is what makes this app sit
   alongside the other RECF apps instead of next to them. The brand is carried by the blue rule
   beneath it, the logo and the type — not by a block of colour that has to be fought in dark mode.
   Solid navy also forces white text, and white text on the light violet that --recf-heading becomes
   in dark mode is unreadable. */
.recf-navbar {
    background-color: var(--bs-tertiary-bg);
    border-bottom: 3px solid var(--recf-blue);
}

.recf-navbar .navbar-brand {
    font-family: var(--recf-font-heading);
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--recf-heading);
}

.recf-navbar .nav-link {
    font-family: var(--recf-font-heading);
    font-size: .875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bs-secondary-color);
}

.recf-navbar .nav-link:hover,
.recf-navbar .nav-link:focus,
.recf-navbar .nav-link.active {
    color: var(--bs-emphasis-color);
}

.recf-navbar .navbar-text {
    color: var(--bs-secondary-color);
    font-size: .875rem;
}

/* ---------- Buttons ---------- */

.btn {
    font-family: var(--recf-font-body);
    font-weight: 500;
    text-transform: uppercase;
    border-radius: 9px;
    border-width: 1.6px;
    padding: .5rem 1rem;
}

.btn-primary {
    background-color: var(--recf-brand-surface);
    border-color: var(--recf-brand-surface);
    color: #fff;
}

.btn-primary:hover, .btn-primary:focus {
    background-color: var(--recf-brand-surface-hover);
    border-color: var(--recf-brand-surface-hover);
    color: #fff;
}

.btn-outline-primary {
    color: var(--recf-heading);
    border-color: var(--recf-heading);
}

.btn-outline-primary:hover {
    background-color: var(--recf-brand-surface);
    border-color: var(--recf-brand-surface);
    color: #fff;
}

/* ---------- Page furniture ---------- */

.recf-page-header {
    border-bottom: 1px solid var(--recf-surface-sunk);
    padding-bottom: .75rem;
    margin-bottom: 1.25rem;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: .75rem;
}

.recf-page-header h1 {
    font-size: 1.953rem;
    margin: 0;
}

.recf-page-header .recf-subtitle {
    color: var(--recf-ink-muted);
    font-size: .9375rem;
}

/* Export button pair that sits on every report page. */
.recf-export-actions {
    display: flex;
    gap: .5rem;
}

/* ---------- Report tables ---------- */

.recf-table {
    width: 100%;
    border-collapse: collapse;
    font-size: .9375rem;
}

/* Wide report tables scroll inside this box rather than pushing the page sideways. It scrolls on
   BOTH axes deliberately: `overflow-x: auto` alone computes `overflow-y: auto` anyway, which makes
   the wrapper the scroll container and leaves `position: sticky; top: 0` on the header sticking to
   nothing. Giving it an explicit height is what makes the sticky header actually work. */
.recf-table-scroll {
    overflow: auto;
    max-height: 72vh;
    border: 1px solid var(--recf-surface-sunk);
    border-radius: 4px;
}

.recf-table thead th {
    background-color: var(--recf-brand-surface);
    color: #fff;
    font-family: var(--recf-font-heading);
    font-size: .8125rem;
    font-weight: 600;
    text-align: left;
    padding: .5rem .625rem;
    position: sticky;
    top: 0;
    z-index: 1;
    white-space: nowrap;
}

.recf-table tbody td {
    padding: .4rem .625rem;
    border-bottom: 1px solid var(--recf-surface-sunk);
    vertical-align: top;
}

/* Dates, codes and short codes read as one token; wrapping them mid-value costs more width than
   it saves. Event and organisation names are the columns allowed to wrap. */
.recf-table .nowrap {
    white-space: nowrap;
}

.recf-table tbody tr:nth-child(even) {
    background-color: var(--recf-surface-muted);
}

.recf-table .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.recf-table-empty {
    padding: 2rem;
    text-align: center;
    color: var(--recf-ink-muted);
}

footer.recf-footer {
    border-top: 1px solid var(--recf-surface-sunk);
    color: var(--recf-ink-muted);
    font-size: .875rem;
    padding: 1rem 0;
}

/* ---------- Brand mark ----------
   recf-logo.png is single-colour navy on transparency, which is invisible against the navy
   navbar, so it is flattened to white there. Same approach as RECFEventRegistrationENTRAID,
   which keeps one asset rather than two that have to be kept in sync. */

/* No filter here. The navbar follows the theme now, so the navy artwork reads correctly on the
   light ground, and recf-aurora.css inverts it to white under the dark theme. A blanket invert
   would make it a white shape on a white bar. */

/* ---------- Filter bar ----------
   Navy-tinted rather than solid navy: it sits directly above a navy table header, and two solid
   navy blocks stacked makes the page top-heavy. */

.recf-filter-bar {
    background: var(--recf-accent-wash);
    border: 1px solid rgba(27, 54, 93, .16);
    border-top: 3px solid var(--recf-navy);
    border-radius: 6px;
    padding: .875rem 1rem;
}

.recf-filter-bar .form-label {
    font-family: var(--recf-font-heading);
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--recf-heading);
    margin-bottom: .15rem;
}

/* ---------- Event fact list ---------- */

.recf-event-facts dt {
    font-family: var(--recf-font-heading);
    font-size: .8125rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--recf-ink-muted);
}

.recf-event-facts dd {
    margin-bottom: .35rem;
}

/* ---------- Payment state ----------
   Colour is spent only on rows somebody has to act on. Tinting the settled ones too would spend
   it on none — same reasoning as the RSM team report in RECFEventRegistrationENTRAID.
   Status is never carried by colour alone: the word is always present, for print and for
   colour-blind readers. */

.recf-pay {
    font-size: .8125rem;
    font-weight: 600;
    white-space: nowrap;
}

.recf-pay-ok {
    color: var(--recf-ok);
}

.recf-pay-due {
    color: var(--recf-due);
}

.recf-table tbody tr.recf-row-due td {
    background-color: var(--recf-warn-bg);
}

.recf-table tbody tr.recf-row-due:nth-child(even) td {
    background-color: var(--recf-warn-bg-strong);
}

.recf-num-due {
    color: var(--recf-due);
    font-weight: 600;
}

.recf-pay-note {
    color: var(--recf-ink-muted);
    cursor: help;
}

/* ---------- Account state ----------
   Same restraint as the payment pills: the revoked state carries colour because it is the one
   somebody may need to act on, and the word is always present so nothing rests on colour alone. */

.recf-state {
    font-size: .8125rem;
    font-weight: 600;
    white-space: nowrap;
}

.recf-state-on { color: var(--recf-ok); }
.recf-state-off { color: var(--recf-due); }

/* Reaching every event is not an error, but it is worth noticing on a list of accounts. */
.recf-state-wide { color: var(--recf-blue); }

.recf-mono-note {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .6875rem;
    color: var(--recf-ink-muted);
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.recf-form-narrow {
    max-width: 34rem;
}

.recf-form-wide {
    max-width: 52rem;
}

.alert.d-none-if-empty:empty {
    display: none;
}

/* ---------- Key reveal ----------
   The one screen where a secret is on display. Given weight so nobody scrolls past it: this is the
   only time the value exists, and the next screen cannot get it back. */

.recf-key-reveal {
    border: 1px solid var(--recf-line);
    border-left: 4px solid var(--recf-yellow);
    border-radius: 4px;
    background: var(--recf-surface-muted);
    padding: 1.25rem;
}

.recf-key-warning {
    font-weight: 600;
    color: var(--recf-body);
    margin-bottom: .875rem;
}

.recf-key-value {
    display: block;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 1rem;
    background: var(--recf-surface);
    border: 1px solid var(--recf-line);
    border-radius: 3px;
    padding: .75rem;
    overflow-wrap: anywhere;
    user-select: all;
    color: var(--recf-heading);
}

:root[data-theme="dark"] .recf-key-value,
:root:not([data-theme="light"]) .recf-key-value {
    background: var(--recf-surface-muted);
}

.recf-key-prefix {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .8125rem;
}

/* ---------- Grants ----------
   An Event Partner is one object with their keys inside it, rather than keys in a flat list. The
   question on this screen is always what a person holds, never what keys exist. */

.recf-grant {
    border: 1px solid var(--recf-line);
    border-radius: 4px;
    margin-bottom: 1rem;
}

.recf-grant-revoked {
    opacity: .82;
}

.recf-grant-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--recf-surface-sunk);
}

.recf-grant-name {
    font-family: var(--recf-font-heading);
    font-weight: 600;
    color: var(--recf-heading);
}

.recf-grant-keys {
    border: 0;
    border-radius: 0;
    max-height: none;
}

/* An identifier inside a table row: monospace so columns of them line up and a 0 is not an O, but
   at body size. Distinct from .recf-code-value below, which is sized to be read ALOUD. */
.recf-ref {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .875rem;
    letter-spacing: .01em;
}

/* Read aloud across a room, so it is set larger and more widely spaced than a key — which is only
   ever copied and pasted. */
.recf-code-value {
    display: inline-block;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 1.75rem;
    font-weight: 600;
    letter-spacing: .12em;
    background: var(--recf-surface);
    border: 1px solid var(--recf-line);
    border-radius: 3px;
    padding: .6rem 1rem;
    user-select: all;
    color: var(--recf-heading);
}

:root[data-theme="dark"] .recf-code-value,
:root:not([data-theme="light"]) .recf-code-value {
    background: var(--recf-surface-muted);
}

.recf-summary {
    font-family: var(--recf-font-heading);
    font-size: .875rem;
    font-weight: 600;
    color: var(--recf-heading);
    cursor: pointer;
}

/* ---------- Traffic heat map ----------
   One cell per minute per device. Fixed thresholds, not a scale relative to the busiest device: a
   relative scale paints a quiet hour in alarming colours and makes a genuinely busy one look no
   different. Throttled minutes break the ramp entirely and go red, because they are a different
   kind of fact — not "busier", but "being refused". */

.recf-heat-strip {
    white-space: nowrap;
    line-height: 0;
}

.recf-heat {
    display: inline-block;
    width: 7px;
    height: 18px;
    margin-right: 1px;
    border-radius: 1px;
    background: var(--recf-surface-sunk);
    vertical-align: middle;
}

.recf-heat-1 { background: var(--recf-heat-1); }
.recf-heat-2 { background: var(--recf-heat-2); }
.recf-heat-3 { background: var(--recf-heat-3); }
.recf-heat-4 { background: var(--recf-heat-4); }
.recf-heat-5 { background: var(--recf-heat-5); }
.recf-heat-reject { background: var(--recf-red); }

.recf-heat-legend {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
}

.recf-heat-legend .recf-heat {
    width: 10px;
    height: 12px;
    margin: 0 1px;
}

.callout-inline {
    border-left: 3px solid var(--recf-yellow);
    background: var(--recf-surface-muted);
    padding: .75rem 1rem;
    font-size: .875rem;
}

/* ---------- Wizard ---------- */

.recf-steps {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1.5rem;
    list-style: none;
    padding: 0 0 1rem;
    margin: 0 0 1.5rem;
    border-bottom: 1px solid var(--recf-surface-sunk);
}

.recf-step {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .875rem;
    color: var(--recf-ink-muted);
}

.recf-step-number {
    display: grid;
    place-items: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    border: 1.5px solid var(--recf-line);
    font-family: var(--recf-font-heading);
    font-size: .8125rem;
    font-weight: 600;
    flex: none;
}

.recf-step-current { color: var(--recf-heading); font-weight: 600; }
.recf-step-current .recf-step-number { border-color: var(--recf-heading); background: var(--recf-navy); color: #fff; }
.recf-step-done { color: var(--recf-body); }
.recf-step-done .recf-step-number { border-color: var(--recf-ok); color: var(--recf-ok); }

/* A completed step is a way back. It has to look clickable without turning the progress bar into
   a row of links — so the affordance is underline-on-hover rather than link colour, which would
   fight the tick and read as "this one needs attention". */
.recf-step-link {
    display: flex;
    align-items: center;
    gap: .5rem;
    color: inherit;
    text-decoration: none;
    border-radius: .25rem;
}

.recf-step-link:hover .recf-step-label,
.recf-step-link:focus-visible .recf-step-label { text-decoration: underline; }
.recf-step-link:focus-visible { outline: 2px solid var(--recf-heading); outline-offset: 3px; }

.recf-lede {
    max-width: 68ch;
    color: var(--recf-body);
    margin-bottom: 1.25rem;
}

/* ---------- Picker ----------
   Replaces a cramped <select>. The list an administrator scans is the main content of the page, so
   it gets the width and the height, and typing narrows it as fast as it is typed. */

.recf-picker {
    border: 1px solid var(--recf-line);
    border-radius: 4px;
    overflow: hidden;
}

.recf-picker-head {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .625rem .75rem;
    border-bottom: 1px solid var(--recf-surface-sunk);
    background: var(--recf-surface-muted);
}

.recf-picker-head .form-control { max-width: 30rem; }

.recf-picker-count {
    font-size: .8125rem;
    color: var(--recf-ink-muted);
    white-space: nowrap;
}

.recf-picker-list {
    max-height: 26rem;
    overflow-y: auto;
}

.recf-picker-row {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .55rem .75rem;
    border-bottom: 1px solid var(--recf-surface-sunk);
    cursor: pointer;
    margin: 0;
}

.recf-picker-row:last-child { border-bottom: 0; }
.recf-picker-row:hover { background: var(--recf-surface-muted); }

.recf-picker-row:has(input:checked) {
    background: var(--recf-accent-tint);
    box-shadow: inset 3px 0 0 var(--recf-navy);
}

.recf-picker-row:has(input:focus-visible) {
    outline: 2px solid var(--recf-blue);
    outline-offset: -2px;
}

.recf-picker-main { flex: 1; min-width: 0; }

.recf-picker-name {
    display: block;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
}

.recf-picker-meta {
    display: block;
    font-size: .8125rem;
    color: var(--recf-ink-muted);
}

.recf-picker-note { color: var(--recf-ink-faint); }
.recf-picker-state { flex: none; }

.recf-picker-empty {
    padding: 1.5rem;
    text-align: center;
    color: var(--recf-ink-muted);
}

/* The message an administrator sends on. Presented as text to copy, not as UI to read. */
.recf-handover {
    font-family: var(--recf-font-body);
    font-size: .875rem;
    line-height: 1.65;
    white-space: pre-wrap;
    background: var(--recf-surface-muted);
    border: 1px solid var(--recf-line);
    border-radius: 4px;
    padding: 1rem 1.25rem;
    color: var(--recf-body);
}

/* A secret that still has to be reachable, but is not the point of the page it is on. */
.recf-key-tuck > summary {
    cursor: pointer;
    padding: .625rem .875rem;
    border: 1px solid var(--recf-line);
    border-left: 3px solid var(--recf-green);
    border-radius: 4px;
    background: var(--recf-surface-muted);
    font-size: .9375rem;
}

.recf-key-tuck > summary:hover { background: var(--recf-surface-sunk); }
