:root {
  --aderis-bg: #030303;
  --aderis-ash: #262626;
  --aderis-ash-soft: rgba(38, 38, 38, 0.65);
  --aderis-card: #141414;
  --aderis-card-header: rgba(255, 255, 255, 0.06);
  --aderis-border: rgba(255, 255, 255, 0.08);
  --aderis-border-strong: rgba(255, 255, 255, 0.18);
  --aderis-text: #f5f5f5;
  --aderis-text-muted: #b3b3b3;
  --aderis-clean-green: #00b176;
  --aderis-terra-red: #b7410e;
  --aderis-blue: #0f87dc;
  --aderis-clearsky-blue: #1e8bf7;
  --aderis-orange: #f78a1e;
  --aderis-yellow: #ffc719;
  /* Warning ink, pushed to ~50deg so it clears the orange primary at 30deg. Kept separate from
     --aderis-yellow, which stays put as a fixed palette/brand colour (.text-bumblebee). */
  --aderis-lemon: #ffe14d;
  /* Crimson (~351deg), not the old tomato #e1523e (7deg): with orange promoted to primary, a
     danger sitting 22deg off it read as the same colour family. */
  --aderis-red: #ee4a63;
  --aderis-purple: #6d4aff;
  --aderis-networked-purple: #8e44ad;
  --aderis-midnight: #1b2538;
  --aderis-dialog: #141414;

  /* ── Alpha-composition channels (comma form, mirrors Bootstrap --bs-*-rgb) ──
     Used as rgba(var(--token), <opacity>) so the *hue* follows the host theme
     while each call site keeps its own opacity. Bridge targets in parens. */
  --aderis-on-surface-rgb: 255, 255, 255;   /* lightening ink for hovers/borders/raised surfaces · → --bs-body-color-rgb */
  --aderis-shadow-rgb: 0, 0, 0;             /* shadow ink (theme-neutral) */
  --aderis-green-rgb: 0, 177, 118;          /* → --bs-primary-rgb AND --bs-success-rgb */
  --aderis-orange-rgb: 247, 138, 30;        /* → --bs-link-color */
  --aderis-red-rgb: 238, 74, 99;            /* → --bs-danger-rgb */
  --aderis-lemon-rgb: 255, 225, 77;         /* → --bs-warning-rgb */
  --aderis-blue-rgb: 15, 135, 220;          /* info / random category, no longer a bridge target */
  --aderis-yellow-rgb: 255, 199, 25;
  --aderis-clearsky-blue-rgb: 30, 139, 247;
  --aderis-terra-red-rgb: 183, 65, 14;

  /* Derived raised surface (follows --aderis-on-surface-rgb automatically) */
  --aderis-surface-2: rgba(var(--aderis-on-surface-rgb), 0.04);

  /* ── Chrome surfaces (stay dark by decision · → --acuity-header-bg / --acuity-footer-bg) ── */
  --aderis-header-bg: linear-gradient(135deg, rgba(12, 12, 12, 0.98) 0%, rgba(18, 18, 18, 0.96) 100%);
  --aderis-footer-bg: rgba(12, 12, 12, 0.95);

  /* ── Content-dimming overlays ── */
  --aderis-scrim: rgba(0, 0, 0, 0.72);      /* modal backdrop */
  --aderis-veil: rgba(3, 3, 3, 0.75);       /* loading overlay */

  /* ── Neutral (non-brand) raised surface, e.g. default FAB ── */
  --aderis-surface-neutral: #1e1e1e;
  --aderis-surface-neutral-hover: #2a2a2a;

  /* ── Text drawn on a saturated brand fill ── */
  --aderis-on-accent: #ffffff;              /* on mid-dark fills (green / crimson / blue) */
  --aderis-on-accent-strong: #1a1200;       /* on bright fills (orange / yellow / lemon) */

  /* ── Semantic role layer (themeable; components consume these) ──────────────
     Each role points at a palette token below. Acuity's bridge re-points these
     roles to --bs-* at runtime; the palette tokens stay fixed for product /
     category use (ClearSky, Terra, random/live/forced, decoration). */
  /* Primary and success deliberately share the green: primary is an interaction colour reaching
     the eye as a solid fill or a 2px accent, success a state colour reaching it as a translucent
     chip, so form keeps them apart. Links were the pair that genuinely collided — green text that
     might be a link or might be a status — and they move to orange below. */
  --aderis-primary: var(--aderis-clean-green);
  --aderis-primary-rgb: var(--aderis-green-rgb);
  /* Shade for SOLID primary fills. The accent green is too light to carry text: white on it is
     2.8:1. Mixed 32% toward black it takes white at 5.5:1 at rest and 4.7:1 under the +8% white
     hover below, so every state clears AA body while the fill still reads 3.3:1 against the card.

     32% is the floor, not a preference: at 28% the hover drops to 4.4:1, and past 36% the fill
     stops separating from the card. Re-point --aderis-primary and this percentage has to be
     re-derived — each hue has its own floor, and orange's was 36%. Accents (tabs, focus rings,
     spinner, outline buttons) keep the bright --aderis-primary; this is only for filled surfaces. */
  --aderis-primary-fill: color-mix(in srgb, var(--aderis-primary), #000 32%);
  --aderis-on-primary: var(--aderis-on-accent);
  --aderis-secondary: var(--aderis-text-muted);
  --aderis-success: var(--aderis-clean-green);
  --aderis-success-rgb: var(--aderis-green-rgb);
  --aderis-danger: var(--aderis-red);
  --aderis-danger-rgb: var(--aderis-red-rgb);
  --aderis-warning: var(--aderis-lemon);
  --aderis-warning-rgb: var(--aderis-lemon-rgb);
  --aderis-info: var(--aderis-clearsky-blue);
  --aderis-info-rgb: var(--aderis-clearsky-blue-rgb);
  /* Orange, freed up when primary moved to green. Reads 7.6:1 on a card and 8.5:1 on the page
     ground, and it is the one role left in the 20–50deg warm band alongside warning — safe only
     because a link is inline text where warning is a chip or an alert border. */
  --aderis-link: var(--aderis-orange);               /* → --bs-link-color */
  --aderis-link-rgb: var(--aderis-orange-rgb);
}

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

html {
  color-scheme: dark;
}

body {
  background-color: var(--aderis-bg);
  color: var(--aderis-text);
  font-family: "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  margin: 0;
}

a {
  color: var(--aderis-link);
}

/* Derived from --aderis-link rather than a literal, which is what #00c987 used to be: a brighter
   green that silently contradicted the token the moment links stopped being green. Same expression
   .btn-link:hover uses, so the two hover identically. */
a:hover,
a:focus {
  color: color-mix(in srgb, var(--aderis-link) 70%, var(--aderis-text));
}

/* ── Minimal element reset (replaces Bootstrap normalize) ─────────────────── */

h1, h2, h3, h4, h5, h6 {
  margin-top: 0;
  margin-bottom: 0.5rem;
  font-weight: 600;
  line-height: 1.2;
  scroll-margin-top: 1.5rem;
}

h1 { font-size: 2rem; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.25rem; }
h4 { font-size: 1.125rem; }
h5 { font-size: 1rem; }
h6 { font-size: 0.875rem; }

p {
  margin-top: 0;
  margin-bottom: 1rem;
}

button {
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
}

input,
select,
textarea {
  font-family: inherit;
  font-size: inherit;
}

/* ── Form utility classes (no Bootstrap dependency) ──────────────────────── */

.form-control {
  display: block;
  width: 100%;
  min-height: 38px;
  padding: 0.45rem 0.85rem;
  background-color: var(--aderis-ash);
  color: var(--aderis-text);
  border: 1px solid var(--aderis-border-strong);
  border-radius: 8px;
  font-size: 0.9rem;
  line-height: 1.5;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  appearance: none;
  -webkit-appearance: none;
}

.form-control::placeholder {
  color: var(--aderis-text-muted);
  opacity: 1;
}

.form-control:focus {
  outline: none;
  border-color: var(--aderis-primary);
  box-shadow: 0 0 0 3px rgba(var(--aderis-primary-rgb), 0.15);
}

.form-control:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

img,
svg {
  max-width: 100%;
  vertical-align: middle;
}

table {
  border-collapse: collapse;
}


.ip-address {
  font-family: "Fira Mono", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  color: var(--aderis-purple);
}

/* Semantic badge classes */

.badge-live {
  background-color: rgba(var(--aderis-green-rgb), 0.2);
  color: var(--aderis-clean-green);
}

.badge-forced {
  background-color: rgba(var(--aderis-red-rgb), 0.2);
  color: var(--aderis-red);
}

.badge-random {
  background-color: rgba(var(--aderis-blue-rgb), 0.2);
  color: var(--aderis-blue);
}

.badge-pending {
  background-color: rgba(var(--aderis-on-surface-rgb), 0.12);
  color: var(--aderis-text-muted);
}

.badge-clearsky {
  background-color: rgba(var(--aderis-clearsky-blue-rgb), 0.2);
  color: var(--aderis-clearsky-blue);
}

.badge-terra {
  background-color: rgba(var(--aderis-terra-red-rgb), 0.2);
  color: var(--aderis-terra-red);
}

.badge-disabled {
  background-color: rgba(128, 128, 128, 0.2);
  color: var(--aderis-text-muted);
}

.badge-alarm {
  background-color: rgba(var(--aderis-red-rgb), 0.3);
  color: var(--aderis-red);
  border: 1px solid rgba(var(--aderis-red-rgb), 0.45);
}

.badge-warning {
  background-color: rgba(var(--aderis-yellow-rgb), 0.2);
  color: var(--aderis-yellow);
}

/* Semantic value classes */

.value-live {
  color: var(--aderis-clean-green);
  font-variant-numeric: tabular-nums;
}

.value-forced {
  color: var(--aderis-red);
  font-variant-numeric: tabular-nums;
}

.value-random {
  color: var(--aderis-blue);
  font-variant-numeric: tabular-nums;
}

.value-pending {
  color: var(--aderis-text-muted);
}

/* Text color utilities */

.text-terra {
  color: var(--aderis-red) !important;
}

.text-clean-green {
  color: var(--aderis-clean-green) !important;
}

.text-ash {
  color: var(--aderis-text) !important;
}

.text-bumblebee {
  color: var(--aderis-yellow) !important;
}

.text-sky {
  color: var(--aderis-blue) !important;
}

.text-muted {
  color: var(--aderis-text-muted) !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.ac-spinner {
  color: var(--aderis-primary);
  animation: ac-spinner-rotate 0.75s linear infinite;
  transform-origin: center;
}

@keyframes ac-spinner-rotate {
  to { transform: rotate(360deg); }
}

/* ── AC Utility Classes ──────────────────────────────────────────────────────
   Emitted by Aderis layout components. May also be used directly in markup.
   Prefix: ac- (Aderis Components)
────────────────────────────────────────────────────────────────────────────── */

/* Flex container */
.ac-flex        { display: flex;        box-sizing: border-box; }
.ac-inline-flex { display: inline-flex; box-sizing: border-box; }

/* Flex direction */
.ac-flex-row         { flex-direction: row; }
.ac-flex-col         { flex-direction: column; }
.ac-flex-row-reverse { flex-direction: row-reverse; }
.ac-flex-col-reverse { flex-direction: column-reverse; }

/* Align items (cross axis) */
.ac-align-start    { align-items: flex-start; }
.ac-align-center   { align-items: center; }
.ac-align-end      { align-items: flex-end; }
.ac-align-stretch  { align-items: stretch; }
.ac-align-baseline { align-items: baseline; }

/* Justify content (main axis) */
.ac-justify-start   { justify-content: flex-start; }
.ac-justify-center  { justify-content: center; }
.ac-justify-end     { justify-content: flex-end; }
.ac-justify-between { justify-content: space-between; }
.ac-justify-around  { justify-content: space-around; }
.ac-justify-evenly  { justify-content: space-evenly; }

/* Flex wrap */
.ac-nowrap      { flex-wrap: nowrap; }
.ac-wrap        { flex-wrap: wrap; }
.ac-wrap-reverse { flex-wrap: wrap-reverse; }

/* Spacer */
.ac-spacer { flex: 1 1 auto; }

/* Fill the parent's height — e.g. equal-height cards stretched to their grid/flex cell */
.ac-h-full { height: 100%; }

/* Grid container */
.ac-grid { display: grid; box-sizing: border-box; }

/* Grid template columns (1–12) */
.ac-grid-cols-1  { grid-template-columns: repeat(1,  minmax(0, 1fr)); }
.ac-grid-cols-2  { grid-template-columns: repeat(2,  minmax(0, 1fr)); }
.ac-grid-cols-3  { grid-template-columns: repeat(3,  minmax(0, 1fr)); }
.ac-grid-cols-4  { grid-template-columns: repeat(4,  minmax(0, 1fr)); }
.ac-grid-cols-5  { grid-template-columns: repeat(5,  minmax(0, 1fr)); }
.ac-grid-cols-6  { grid-template-columns: repeat(6,  minmax(0, 1fr)); }
.ac-grid-cols-7  { grid-template-columns: repeat(7,  minmax(0, 1fr)); }
.ac-grid-cols-8  { grid-template-columns: repeat(8,  minmax(0, 1fr)); }
.ac-grid-cols-9  { grid-template-columns: repeat(9,  minmax(0, 1fr)); }
.ac-grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
.ac-grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
.ac-grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }

/* Grid column span */
.ac-span-1  { grid-column: span 1; }
.ac-span-2  { grid-column: span 2; }
.ac-span-3  { grid-column: span 3; }
.ac-span-4  { grid-column: span 4; }
.ac-span-5  { grid-column: span 5; }
.ac-span-6  { grid-column: span 6; }
.ac-span-7  { grid-column: span 7; }
.ac-span-8  { grid-column: span 8; }
.ac-span-9  { grid-column: span 9; }
.ac-span-10 { grid-column: span 10; }
.ac-span-11 { grid-column: span 11; }
.ac-span-12 { grid-column: span 12; }

/* Responsive column span — sm ≥576px */
@media (min-width: 576px) {
  .ac-sm-span-1  { grid-column: span 1; }
  .ac-sm-span-2  { grid-column: span 2; }
  .ac-sm-span-3  { grid-column: span 3; }
  .ac-sm-span-4  { grid-column: span 4; }
  .ac-sm-span-5  { grid-column: span 5; }
  .ac-sm-span-6  { grid-column: span 6; }
  .ac-sm-span-7  { grid-column: span 7; }
  .ac-sm-span-8  { grid-column: span 8; }
  .ac-sm-span-9  { grid-column: span 9; }
  .ac-sm-span-10 { grid-column: span 10; }
  .ac-sm-span-11 { grid-column: span 11; }
  .ac-sm-span-12 { grid-column: span 12; }
}

/* Responsive column span — md ≥768px */
@media (min-width: 768px) {
  .ac-md-span-1  { grid-column: span 1; }
  .ac-md-span-2  { grid-column: span 2; }
  .ac-md-span-3  { grid-column: span 3; }
  .ac-md-span-4  { grid-column: span 4; }
  .ac-md-span-5  { grid-column: span 5; }
  .ac-md-span-6  { grid-column: span 6; }
  .ac-md-span-7  { grid-column: span 7; }
  .ac-md-span-8  { grid-column: span 8; }
  .ac-md-span-9  { grid-column: span 9; }
  .ac-md-span-10 { grid-column: span 10; }
  .ac-md-span-11 { grid-column: span 11; }
  .ac-md-span-12 { grid-column: span 12; }
}

/* Responsive column span — lg ≥992px */
@media (min-width: 992px) {
  .ac-lg-span-1  { grid-column: span 1; }
  .ac-lg-span-2  { grid-column: span 2; }
  .ac-lg-span-3  { grid-column: span 3; }
  .ac-lg-span-4  { grid-column: span 4; }
  .ac-lg-span-5  { grid-column: span 5; }
  .ac-lg-span-6  { grid-column: span 6; }
  .ac-lg-span-7  { grid-column: span 7; }
  .ac-lg-span-8  { grid-column: span 8; }
  .ac-lg-span-9  { grid-column: span 9; }
  .ac-lg-span-10 { grid-column: span 10; }
  .ac-lg-span-11 { grid-column: span 11; }
  .ac-lg-span-12 { grid-column: span 12; }
}

/* Responsive column span — xl ≥1200px */
@media (min-width: 1200px) {
  .ac-xl-span-1  { grid-column: span 1; }
  .ac-xl-span-2  { grid-column: span 2; }
  .ac-xl-span-3  { grid-column: span 3; }
  .ac-xl-span-4  { grid-column: span 4; }
  .ac-xl-span-5  { grid-column: span 5; }
  .ac-xl-span-6  { grid-column: span 6; }
  .ac-xl-span-7  { grid-column: span 7; }
  .ac-xl-span-8  { grid-column: span 8; }
  .ac-xl-span-9  { grid-column: span 9; }
  .ac-xl-span-10 { grid-column: span 10; }
  .ac-xl-span-11 { grid-column: span 11; }
  .ac-xl-span-12 { grid-column: span 12; }
}

/* Responsive column span — xxl ≥1400px */
@media (min-width: 1400px) {
  .ac-xxl-span-1  { grid-column: span 1; }
  .ac-xxl-span-2  { grid-column: span 2; }
  .ac-xxl-span-3  { grid-column: span 3; }
  .ac-xxl-span-4  { grid-column: span 4; }
  .ac-xxl-span-5  { grid-column: span 5; }
  .ac-xxl-span-6  { grid-column: span 6; }
  .ac-xxl-span-7  { grid-column: span 7; }
  .ac-xxl-span-8  { grid-column: span 8; }
  .ac-xxl-span-9  { grid-column: span 9; }
  .ac-xxl-span-10 { grid-column: span 10; }
  .ac-xxl-span-11 { grid-column: span 11; }
  .ac-xxl-span-12 { grid-column: span 12; }
}

/* Grid row span */
.ac-row-span-1 { grid-row: span 1; }
.ac-row-span-2 { grid-row: span 2; }
.ac-row-span-3 { grid-row: span 3; }
.ac-row-span-4 { grid-row: span 4; }
.ac-row-span-5 { grid-row: span 5; }
.ac-row-span-6 { grid-row: span 6; }

/* Gap — shorthand (declared before row/col gap so overrides work) */
.ac-gap-0 { gap: 0; }
.ac-gap-1 { gap: 0.25rem; }
.ac-gap-2 { gap: 0.5rem; }
.ac-gap-3 { gap: 0.75rem; }
.ac-gap-4 { gap: 1rem; }
.ac-gap-5 { gap: 1.5rem; }
.ac-gap-6 { gap: 2rem; }
.ac-gap-8 { gap: 3rem; }

/* Row gap only — declared after gap so these override gap's row-gap */
.ac-row-gap-0 { row-gap: 0; }
.ac-row-gap-1 { row-gap: 0.25rem; }
.ac-row-gap-2 { row-gap: 0.5rem; }
.ac-row-gap-3 { row-gap: 0.75rem; }
.ac-row-gap-4 { row-gap: 1rem; }
.ac-row-gap-5 { row-gap: 1.5rem; }
.ac-row-gap-6 { row-gap: 2rem; }
.ac-row-gap-8 { row-gap: 3rem; }

/* Column gap only */
.ac-col-gap-0 { column-gap: 0; }
.ac-col-gap-1 { column-gap: 0.25rem; }
.ac-col-gap-2 { column-gap: 0.5rem; }
.ac-col-gap-3 { column-gap: 0.75rem; }
.ac-col-gap-4 { column-gap: 1rem; }
.ac-col-gap-5 { column-gap: 1.5rem; }
.ac-col-gap-6 { column-gap: 2rem; }
.ac-col-gap-8 { column-gap: 3rem; }

/* Margin utility */
.ac-ms-auto { margin-left: auto !important; }

/* Text utilities — the sanctioned page-level text vocabulary (replaces Bootstrap
   text-secondary/small/fw-*/text-align). Layout/spacing stays on the ac- flex/grid/gap
   classes above and the Aderis layout components; prefer those over ad-hoc margins. */
.ac-text-muted  { color: var(--aderis-text-muted); }
.ac-text-sm     { font-size: 0.85rem; }
.ac-text-strong { font-weight: 600; }
.ac-text-center { text-align: center; }
.ac-text-end    { text-align: right; }
.ac-text-mono   { font-family: "Fira Mono", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }

/* App splash overlay — used by AderisSplash component */
.ac-app-splash {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--aderis-bg);
  z-index: 9999;
  /* 3s CSS fallback in case JS dismissal is delayed */
  animation: ac-splash-dismiss 0.55s 3s ease forwards;
  transition: opacity 0.55s ease, visibility 0.55s ease;
}

.ac-app-splash--out {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  animation: none;
}

@keyframes ac-splash-dismiss {
  to { opacity: 0; visibility: hidden; pointer-events: none; }
}


