/* ===========================================================
   SignalPage — brand token layer (Layer 0)
   -----------------------------------------------------------
   The single source of truth for the brand's colour and type
   tokens on every surface where SignalPage speaks as itself:
   the admin panel, the customer portal, the staff dashboard and
   the signup funnel. DESIGN.md is the written system; the
   marketing site carries the same values in
   platform/marketing-content/site.css.

   2026-10-15 rebrand: the old "Calibrated Instrument" world
   (paper ground, mono uppercase labels, amber-means-verified) is
   retired. The token NAMES are kept so the ~80 call sites and an
   agency's white-label overrides keep working; only the values
   and the component rules below changed.

   NOT loaded by tenant public sites. A tenant's site uses its
   own palette from site_settings; the old guide's layout rules
   live on, for tenants who chose it, as the "instrument" design
   preset (site/settings.php::getDesignStyles()), which only ever
   references --color-* tokens.

   THIS FILE EXISTS TWICE, byte-for-byte identical:
       assets/brand.css            (CMS core tree)
       platform/assets/brand.css   (platform tree)
   Edit one, copy to the other — enforced by
   `php admin/tools/check-brand-layering.php`.

   -----------------------------------------------------------
   TOKENS ARE ROLES, NOT PIGMENTS.
   --ink is "primary text", --paper is "surface" (cards, the top
   bar, the admin sidebar, inputs) and --grey is "canvas" (the page
   behind them). In dark mode the roles hold and the values flip.

   Every text token clears WCAG AA (4.5:1) on both --paper and
   --grey in both themes; badge text clears 4.5:1 on its own
   tint; --input-border clears 3:1 against --paper.
   =========================================================== */

/* ---- Light (default) ---- */
:root {
    color-scheme: light;

    /* Neutrals */
    --paper: #FFFFFF;   /* surface: cards, top bar, inputs */
    --grey:  #F5F7FB;   /* canvas: page background, sidebar, wells */
    --line:  #E3E8F0;   /* dividers and card edges */
    --ink:   #0E1726;   /* primary text (17.96:1 paper) */
    --stone: #5A6B82;   /* secondary text (5.44:1 paper, 5.07:1 grey) */
    --input-border: #7F8DA1; /* a field's edge must read: 3.37:1 */

    /* The one action colour: buttons, links, focus, active nav.
       A fill form and a text form, because the fill needs 4.5:1
       against its white label and the text needs 4.5:1 against the
       page; one value cannot do both across two themes. */
    --cobalt:       #1F5FE0;  /* fill (white label 5.57:1) */
    --cobalt-hover: #1749C4;
    --cobalt-text:  #1F5FE0;  /* link text (5.57:1 paper, 5.19:1 grey) */
    --cobalt-soft:  #EAF0FD;  /* active-nav and selection wash */

    /* Status badges: text on its own tint, all >= 5.7:1. */
    --ok-text:      #0B6B45;  --ok-bg:      #E3F5EC;  --ok-dot:   #12A15A;
    --warn-text:    #7A4A00;  --warn-bg:    #FFF3D6;  --warn-dot: #C98500;
    --bad-text:     #B42318;  --bad-bg:     #FDECEA;
    --neutral-text: #475467;  --neutral-bg: #EEF1F6;

    /* Retired names, kept as aliases so nothing that still reads them
       breaks. Amber no longer means "verified"; it is simply gone. */
    --amber:      var(--ok-dot);
    --amber-text: var(--ok-text);

    /* The one failure colour (buttons, validation). */
    --flag-red: #C2261D;          /* white label 5.85:1 */
    --flag-red-label: #FFFFFF;

    /* Type: one family. Monospace only for code and real payloads,
       from the system stack (no webfont). */
    --font-body: 'Mona Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Geometry and depth: soft, navy-tinted shadows. */
    --radius:  8px;
    --radius-lg: 12px;
    --shadow:    0 1px 2px rgba(14, 23, 38, .06), 0 1px 3px rgba(14, 23, 38, .08);
    --shadow-lg: 0 2px 4px rgba(14, 23, 38, .04), 0 12px 24px -6px rgba(14, 23, 38, .10);
}

/* ---- Dark ----
   The same roles on a navy ground. The canvas is the darkest layer and
   surfaces sit one step up, so cards still lift without a shadow. */
:root[data-bs-theme="dark"] {
    color-scheme: dark;

    --paper: #111A2C;
    --grey:  #0B1220;
    --line:  #24304A;
    --ink:   #E6ECF5;   /* 14.64:1 paper */
    --stone: #9FB0C8;   /* 7.88:1 paper */
    --input-border: #6B7C99;

    --cobalt:       #2563EB;  /* white label 5.17:1, 3.36:1 against paper */
    --cobalt-hover: #3B76F0;
    --cobalt-text:  #7FA6FF;  /* 7.29:1 paper */
    --cobalt-soft:  #162449;

    --ok-text:      #6EE7B7;  --ok-bg:      #0E2A22;  --ok-dot:   #34D399;
    --warn-text:    #FFC46B;  --warn-bg:    #2E2410;  --warn-dot: #F5B83D;
    --bad-text:     #FF9A8F;  --bad-bg:     #361717;
    --neutral-text: #C3CEDD;  --neutral-bg: #1B2538;

    --flag-red: #F07167;
    --flag-red-label: #0E1726;   /* dark label on the lifted red: 6.21:1 */

    /* Navy-tinted like the light theme's, just deeper. */
    --shadow:    0 1px 2px rgba(3, 8, 20, .45);
    --shadow-lg: 0 12px 24px -6px rgba(3, 8, 20, .55);
}

/* ===========================================================
   Bootstrap bridge
   -----------------------------------------------------------
   Bootstrap 5.3 is the structural base (grid, collapse, dropdown
   JS); its visual defaults are re-pointed at the tokens so existing
   markup converts without editing call sites.
   =========================================================== */
:root, :root[data-bs-theme="dark"] {
    --bs-body-bg: var(--grey);
    --bs-body-color: var(--ink);
    --bs-body-font-family: var(--font-body);
    --bs-font-monospace: var(--font-mono);
    --bs-code-color: var(--stone);   /* refs, slugs and keys are data, not a pink accent */
    --bs-emphasis-color: var(--ink);
    --bs-secondary-color: var(--stone);
    --bs-secondary-bg: var(--grey);
    --bs-tertiary-bg: var(--grey);
    --bs-border-color: var(--line);
    --bs-border-color-translucent: var(--line);
    --bs-border-radius: var(--radius);
    --bs-border-radius-sm: 6px;
    --bs-border-radius-lg: var(--radius-lg);
    --bs-border-radius-xl: var(--radius-lg);
    --bs-border-radius-pill: 999px;
    --bs-link-color: var(--cobalt-text);
    --bs-link-hover-color: var(--cobalt-hover);
    --bs-primary: var(--cobalt);
    --bs-primary-rgb: 31, 95, 224;
    --bs-danger: var(--flag-red);
    --bs-danger-rgb: 194, 38, 29;
    --bs-card-bg: var(--paper);
    --bs-card-border-color: var(--line);
    --bs-box-shadow-sm: var(--shadow);
    --bs-box-shadow: var(--shadow);
    --bs-box-shadow-lg: var(--shadow-lg);
}
/* Tables sit on whatever card holds them, not on the canvas colour.
   Bootstrap re-declares these on .table itself, so they are set there. */
.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--ink);
    --bs-table-active-bg: color-mix(in srgb, var(--cobalt) 7%, transparent);
    --bs-table-active-color: var(--ink);
}
.table > thead > tr > th {
    color: var(--stone);
    font-size: .8125rem;
    font-weight: 600;
    border-bottom-color: var(--line);
}
:root[data-bs-theme="dark"] { --bs-primary-rgb: 37, 99, 235; --bs-danger-rgb: 240, 113, 103; }
body { -webkit-font-smoothing: antialiased; }
::selection { background: var(--cobalt-soft); color: var(--ink); }

/* Buttons: solid blue for the action, white with a soft edge for the
   rest, 8px corners, no gradient. */
.btn {
    --bs-btn-font-family: var(--font-body);
    --bs-btn-font-weight: 600;
    --bs-btn-border-radius: var(--radius);
    --bs-btn-box-shadow: none;
    --bs-btn-focus-box-shadow: 0 0 0 4px color-mix(in srgb, var(--cobalt) 25%, transparent);
    background-image: none;
}
.btn-primary {
    --bs-btn-bg: var(--cobalt);
    --bs-btn-border-color: var(--cobalt);
    --bs-btn-color: #fff;
    --bs-btn-hover-bg: var(--cobalt-hover);
    --bs-btn-hover-border-color: var(--cobalt-hover);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--cobalt-hover);
    --bs-btn-active-border-color: var(--cobalt-hover);
    --bs-btn-disabled-bg: var(--cobalt);
    --bs-btn-disabled-border-color: var(--cobalt);
    box-shadow: var(--shadow);
}
/* Every outline variant gets the same neutral edge, so Bootstrap's stock
   green/yellow/cyan never leak through. The variant still picks its own
   label colour (admin_styles.css maps those onto tokens). */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-success,
.btn-outline-danger,
.btn-outline-warning,
.btn-outline-info,
.btn-outline-light,
.btn-outline-dark {
    --bs-btn-bg: var(--paper);
    --bs-btn-border-color: color-mix(in srgb, var(--line) 70%, var(--stone));
    --bs-btn-hover-bg: var(--grey);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--line) 50%, var(--stone));
    --bs-btn-hover-color: var(--ink);
    --bs-btn-active-bg: var(--grey);
    --bs-btn-active-border-color: color-mix(in srgb, var(--line) 50%, var(--stone));
    --bs-btn-active-color: var(--ink);
    --bs-btn-disabled-border-color: var(--line);
    box-shadow: var(--shadow);
}
.btn-outline-primary {
    --bs-btn-color: var(--cobalt-text);
    --bs-btn-hover-bg: var(--cobalt);
    --bs-btn-hover-border-color: var(--cobalt);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--cobalt-hover);
    --bs-btn-active-border-color: var(--cobalt-hover);
    --bs-btn-active-color: #fff;
}
.btn-outline-secondary { --bs-btn-color: var(--ink); }
/* The selected segment of a button group (queue filters, view switches). */
.btn-outline-secondary.active, .btn-check:checked + .btn-outline-secondary {
    --bs-btn-active-bg: var(--cobalt-soft);
    --bs-btn-active-color: var(--cobalt-text);
    --bs-btn-active-border-color: color-mix(in srgb, var(--cobalt) 35%, var(--line));
    font-weight: 600;
}

/* Destructive actions keep their red fill on hover, so "Delete" never
   looks like "Cancel" at the moment of clicking. */
.btn-outline-danger {
    --bs-btn-color: var(--flag-red);
    --bs-btn-hover-bg: var(--flag-red);
    --bs-btn-hover-border-color: var(--flag-red);
    --bs-btn-hover-color: var(--flag-red-label);
    --bs-btn-active-bg: var(--flag-red);
    --bs-btn-active-border-color: var(--flag-red);
    --bs-btn-active-color: var(--flag-red-label);
}

/* Solid semantic fills the brand has no hue for become the neutral
   surface treatment; a filled action should be .btn-primary. */
.btn-success, .btn-warning, .btn-info, .btn-light, .btn-secondary {
    --bs-btn-bg: var(--paper);
    --bs-btn-border-color: color-mix(in srgb, var(--line) 70%, var(--stone));
    --bs-btn-color: var(--ink);
    --bs-btn-hover-bg: var(--grey);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--line) 50%, var(--stone));
    --bs-btn-hover-color: var(--ink);
    --bs-btn-active-bg: var(--grey);
    --bs-btn-active-border-color: color-mix(in srgb, var(--line) 50%, var(--stone));
    --bs-btn-active-color: var(--ink);
    box-shadow: var(--shadow);
}
.btn-danger {
    --bs-btn-bg: var(--flag-red);
    --bs-btn-border-color: var(--flag-red);
    --bs-btn-color: var(--flag-red-label);
    /* Mixes toward --ink, which is near-black in light and near-white in
       dark, so the fill deepens in one and lifts in the other. */
    --bs-btn-hover-bg: color-mix(in srgb, var(--flag-red) 85%, var(--ink));
    --bs-btn-hover-border-color: color-mix(in srgb, var(--flag-red) 85%, var(--ink));
    --bs-btn-hover-color: var(--flag-red-label);
    --bs-btn-active-bg: color-mix(in srgb, var(--flag-red) 85%, var(--ink));
    --bs-btn-active-border-color: color-mix(in srgb, var(--flag-red) 85%, var(--ink));
    --bs-btn-active-color: var(--flag-red-label);
}

.card {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
}

/* Alerts take the badge palette: a tint, its text colour, no stock hues. */
.alert { border-radius: var(--radius); border-width: 1px; }
.alert-primary, .alert-info { --bs-alert-bg: var(--cobalt-soft); --bs-alert-color: var(--ink); --bs-alert-border-color: color-mix(in srgb, var(--cobalt) 25%, var(--cobalt-soft)); --bs-alert-link-color: var(--cobalt-text); }
.alert-success   { --bs-alert-bg: var(--ok-bg);   --bs-alert-color: var(--ok-text);   --bs-alert-border-color: color-mix(in srgb, var(--ok-text) 20%, var(--ok-bg));   --bs-alert-link-color: var(--ok-text); }
.alert-warning   { --bs-alert-bg: var(--warn-bg); --bs-alert-color: var(--warn-text); --bs-alert-border-color: color-mix(in srgb, var(--warn-text) 20%, var(--warn-bg)); --bs-alert-link-color: var(--warn-text); }
.alert-danger    { --bs-alert-bg: var(--bad-bg);  --bs-alert-color: var(--bad-text);  --bs-alert-border-color: color-mix(in srgb, var(--bad-text) 20%, var(--bad-bg));  --bs-alert-link-color: var(--bad-text); }
.alert-secondary, .alert-light { --bs-alert-bg: var(--neutral-bg); --bs-alert-color: var(--neutral-text); --bs-alert-border-color: var(--line); }

/* A field's edge has to be visible (1.4.11): --line alone is 1.23:1. */
.form-control, .form-select { border-color: var(--input-border); background-color: var(--paper); color: var(--ink); }
.form-control::placeholder { color: var(--stone); }   /* 5.44:1 light, 7.88:1 dark */
.form-control:focus, .form-select:focus {
    border-color: var(--cobalt);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--cobalt) 18%, transparent);
}
.form-check-input { border-color: var(--input-border); }
.form-check-input:checked { background-color: var(--cobalt); border-color: var(--cobalt); }

/* ===========================================================
   Typography
   =========================================================== */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--font-body);
    font-weight: 650;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--ink);
}

/* ===========================================================
   Components
   =========================================================== */

/* Logo mark: three ascending bars, the tallest lit. The one element
   kept from the previous identity. */
.signal-mark {
    display: inline-flex;
    align-items: flex-end;
    gap: 2px;
    height: 16px;
    vertical-align: -2px;
}
.signal-mark i { width: 4px; border-radius: 1px; background: color-mix(in srgb, var(--stone) 45%, var(--paper)); display: block; }
.signal-mark i:nth-child(1) { height: 6px; }
.signal-mark i:nth-child(2) { height: 11px; }
.signal-mark i:nth-child(3) { height: 16px; background: var(--cobalt); }

/* ---- Status badges ----------------------------------------
   Rendered by state_chip() in admin/lib/state.php (duplicated at
   platform/lib/state.php), never by hand. Sentence case, one tint
   per meaning:

       .state-live     green   live / connected / confirmed
       .state-on       green   published, active, featured
       .state-pending  amber   waiting, needs attention
       .state-off      grey    draft, hidden, disabled
       .state-failed   red     a genuine failure

   Counts (state_count) are blue: an unread count is something to act
   on, not something broken. mono_label() is the neutral grey badge for
   plain data (a template name, a redirect type).
   ---------------------------------------------------------- */
.state {
    display: inline-flex;
    align-items: center;
    gap: .4em;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: .75rem;
    letter-spacing: 0;
    text-transform: none;
    padding: .2em .65em;
    border: 0;
    border-radius: 999px;
    background: var(--neutral-bg);
    color: var(--neutral-text);
    white-space: nowrap;
    line-height: 1.5;
}
.state-live, .state-on { background: var(--ok-bg); color: var(--ok-text); }
.state-pending         { background: var(--warn-bg); color: var(--warn-text); }
.state-off             { background: var(--neutral-bg); color: var(--neutral-text); }
.state-failed          { background: var(--bad-bg); color: var(--bad-text); }

.state-count {
    display: inline-block;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: .75rem;
    min-width: 1.5em;
    text-align: center;
    padding: .1em .5em;
    border-radius: 999px;
    background: var(--cobalt);
    color: #fff;
    line-height: 1.5;
}

/* The dot takes its badge's text colour, so it always matches. */
.sdot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
    display: inline-block;
}
.state-pending .sdot { background: var(--warn-dot); }

/* ---- Detail panel (formerly the "readout") ---------------
   A card with a header and label/value rows: plan details, DNS
   records, ticket metadata. Labels are sentence-case sans; values are
   monospace only when they are literal data (add .is-code). */
.readout {
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--paper);
    box-shadow: var(--shadow);
    overflow: hidden;
}
.readout-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--line);
    font-family: var(--font-body);
    font-size: .9375rem;
    font-weight: 600;
    color: var(--ink);
}
.readout-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .65rem 1rem;
    border-bottom: 1px solid var(--line);
    font-family: var(--font-body);
    font-size: .9rem;
}
.readout-row:last-child { border-bottom: 0; }
.readout-key {
    color: var(--stone);
    font-weight: 500;
}
.readout-val {
    color: var(--ink);
    font-weight: 500;
    text-align: right;
}
.readout-val.is-code { font-family: var(--font-mono); font-size: .85rem; }

/* ---- Stacked tables on phones ------------------------------
   Add .table-stack to a list table and data-label to its cells: below
   576px each row becomes a block of label/value lines, so status, dates
   and row actions stay on screen instead of behind a sideways scroll.
   A cell with an empty data-label (the title, the actions) shows no label. */
@media (max-width: 575.98px) {
    .table-stack thead { display: none; }
    .table-stack, .table-stack tbody, .table-stack tr, .table-stack td { display: block; width: 100%; }
    .table-stack tr { padding: .75rem 0; border-bottom: 1px solid var(--line); }
    .table-stack > :not(caption) > * > * { border-bottom: 0; }
    .table-stack td { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: .3rem .75rem; text-align: right; }
    .table-stack td::before { content: attr(data-label); font-family: var(--font-body); color: var(--stone); font-size: .8125rem; font-weight: 600; text-align: left; }
    .table-stack td[data-label=""] { justify-content: flex-start; text-align: left; }
    .table-stack td[data-label=""]::before { display: none; }
}

/* ---- Label / detail list -----------------------------------
   Short definition rows (a plan's inclusions, a support summary). */
.spec-list { border-top: 1px solid var(--line); }
.spec-row {
    display: flex;
    gap: 1.5rem;
    padding: .85rem 0;
    border-bottom: 1px solid var(--line);
}
.spec-label {
    flex: 0 0 34%;
    font-weight: 600;
    color: var(--ink);
}
.spec-detail { flex: 1; color: var(--stone); }
@media (max-width: 575.98px) {
    .spec-row { flex-direction: column; gap: 0.25rem; }
    .spec-label { flex: none; }
}

/* ===========================================================
   Layering rule (enforced by admin/tools/check-brand-layering.php)
   -----------------------------------------------------------
   BRAND layer  — this file. SignalPage's own surfaces only, never a
                  tenant site.
   PATTERN layer — the .pb-* classes in assets/styles.css and the
                  "instrument" preset in getDesignStyles(), expressed
                  through a TENANT's --color-* tokens. No .pb-* rule
                  may name a token from this file.
   =========================================================== */
