/* BHG operator console -- the bridge between this console's own class
 * vocabulary and Sneat's.
 *
 * Sneat (Bootstrap 5, MIT, vendored under ./sneat) supplies the shell, the
 * grid, the components and the palette. This file does four things and should
 * not grow a fifth:
 *
 *   1. points the font stack at the system faces, with Arabic appended
 *   2. teaches Bootstrap the class names 70 existing templates already use
 *      -- .notice, .stat, .table-wrap, .field, .badge-ok and the rest -- so
 *      they inherit the theme without being rewritten
 *   3. carries the dark palette, which Sneat's free edition does not ship
 *   4. keeps the print rules
 *
 * It loads *after* the theme, and every rule here is either a name Bootstrap
 * has never heard of or a deliberate override of one it has. Where the two
 * collide -- .card, .btn, .badge, .small, .table all mean different things in
 * the two vocabularies -- the collision is handled at the point of use and
 * commented there, because that is the part a later reader will get wrong.
 *
 * Class map for template authors. Anything not listed is plain Bootstrap, and
 * new pages should prefer plain Bootstrap:
 *   header     .page-head .page-title .page-actions .page-foot .subnav
 *   messages   .flashes .flash-tag .flash-text
 *              .notice .notice-ok|warn|error .notice-title .notice-body .notice-loud
 *   cards      .card .card-head .card-title .card-sub .card-foot .card-flush
 *   stats      .stats .stat .stat-value .stat-label .stat-note (.is-warn .is-error)
 *   tables     .table-wrap (.tall) .num .nowrap .empty  table.grid table.narrow
 *   forms      .form .form-wide .form-grid .form-inline .filters
 *              .field .field-label .help .field-check .field-row .field-inline
 *              .form-actions .req .check .checkrow
 *              .choice .choice-body|title|sub|meta  (a radio list of cards)
 *   buttons    .btn .btn-primary .btn-danger .btn-sm .btn-link  (bare .btn = secondary)
 *   badges     .badge .badge-neutral|ok|warn|error
 *   code       code pre .mono .copy-row .code-block .codes .secret .wrap
 *   charts     .chart .chart-svg .chart-empty .chart-row  figure figcaption
 *   utility    .muted .small .inline .stack .cluster .right .dl .kv .negative
 *              .grid-2 .grid-3 .prose .section-title .checklist .narrow
 *
 * :has() is used once, for the .card padding rule, and is the reason this file
 * wants a 2023-or-later browser. That is a safe assumption for an internal
 * console on managed laptops and an unsafe one for anything public.
 */

/* --------------------------------------------------------------------- */
/* 1. Tokens                                                              */
/* --------------------------------------------------------------------- */

/* Semantic surfaces, so section 13 can repaint the console by redefining
 * eight values rather than by chasing Sneat's hardcoded whites through a
 * megabyte of stylesheet. Light values are Sneat's own. */
:root {
  --bhg-bg: #f5f5f9;
  --bhg-surface: #fff;
  --bhg-surface-2: #f9fafb;
  --bhg-text: #697a8d;
  --bhg-heading: #566a7f;
  --bhg-muted: #a1acb8;
  --bhg-border: #d9dee3;
  --bhg-shadow: 0 2px 6px 0 rgba(67, 89, 113, 0.12);

  /* Sneat asks for Public Sans over a CDN. This console does not load web
   * fonts -- it runs inside a hospital network that may not reach Google, and
   * a console that renders in Times because DNS was slow is a console nobody
   * trusts. The system stack is what Sneat itself falls back to; the two
   * Arabic faces are appended because half of what this renders is Arabic and
   * Sneat's stack has no fallback that covers it. */
  --bs-font-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans Arabic", "Noto Naskh Arabic", sans-serif;
  --bs-font-monospace: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Sneat's own accent. One line to rebrand, and the label tints below it are
   * the other three. Changing it here does not repaint the theme's own
   * .btn-primary -- that hardcodes #696cff -- so a real rebrand means editing
   * theme-default.css too. */
  --bhg-accent: #696cff;
}

body {
  background-color: var(--bhg-bg);
  color: var(--bhg-text);
}

/* Skipped straight to the content, before the menu's forty links. */
.skip-link { position: absolute; left: -9999px; }
.skip-link:focus {
  left: 8px; top: 8px; z-index: 1090; padding: 8px 12px;
  background: var(--bhg-surface); color: var(--bhg-text);
  border: 1px solid var(--bhg-accent); border-radius: 6px;
}

/* --------------------------------------------------------------------- */
/* 2. Shell chrome                                                        */
/* --------------------------------------------------------------------- */

.page-head { margin-bottom: 1rem; }
/* Colour only. The size comes from the .h4 the heading also carries, so the
 * page title tracks the theme's scale instead of pinning its own. */
.page-title { color: var(--bhg-heading); }
.page-foot { font-size: 0.8125rem; color: var(--bhg-muted); }
.subnav:not(:empty) { margin-bottom: 1.25rem; }
.flashes { margin-bottom: 0.5rem; }

/* The navbar shows the page title too, and on a wide screen -- the only width
 * at which the navbar has room for it -- showing it twice reads as a rendering
 * bug. So the in-page copy goes.
 *
 * Clipped, not `display: none`. The navbar's copy is a <span>; this one is the
 * page's <h1>, and hiding it outright would leave every console page with no
 * heading at all in the accessibility tree and no top level in its document
 * outline. Clipping takes it off the screen and leaves it in both. */
@media (min-width: 1200px) {
  .page-head .page-title {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
    border: 0;
  }
  /* With the title clipped, a head that has no buttons in it is a 1rem gap
     above the first card and nothing else. */
  .page-head:not(:has(.page-actions > *)) { margin-bottom: 0; }
}

.user-chip { color: var(--bhg-heading); }

/* The sidebar brand mark: a glyph rather than Sneat's demo SVG logo. */
.app-brand-logo .bx { font-size: 1.6rem; color: var(--bhg-accent); }
.app-brand-text { color: var(--bhg-heading); letter-spacing: -0.02em; }

/* Sneat's own demo.css does this and the layout needs it: without the padding
 * a fixed navbar sits on top of the first card. Copied rather than vendored --
 * the rest of demo.css is spacing helpers for the component gallery. */
.layout-navbar-fixed .layout-wrapper:not(.layout-horizontal):not(.layout-without-menu) .layout-page {
  padding-top: 76px !important;
}
.content-wrapper .navbar { z-index: auto; }
.menu .app-brand.demo { height: 64px; margin-top: 12px; }

#theme-toggle {
  border: 1px solid var(--bhg-border);
  color: var(--bhg-muted);
  background: transparent;
}
#theme-toggle:hover { color: var(--bhg-accent); border-color: var(--bhg-accent); }

/* --------------------------------------------------------------------- */
/* 3. Cards                                                               */
/* --------------------------------------------------------------------- */

.card { margin-bottom: 1.5rem; box-shadow: var(--bhg-shadow); }

/* The collision that matters most. 179 templates put their content straight
 * inside .card; Bootstrap expects a .card-body to carry the padding. So .card
 * pads itself only when it has no Bootstrap section inside it -- which means a
 * natively converted page is never padded twice, and an old one never renders
 * flush to its own border. display:block restores the pre-Bootstrap box model
 * for those, so paragraph margins collapse the way the pages were written
 * expecting. */
.card:not(:has(> .card-body, > .card-header, > .card-footer)) {
  display: block;
  padding: 1.5rem;
}
.card > :last-child { margin-bottom: 0; }

.card-head {
  display: flex; align-items: baseline; gap: 0.625rem; flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.card-head .btn, .card-head form { margin-left: auto; }
.card-title { margin: 0; font-size: 1.0625rem; font-weight: 600; color: var(--bhg-heading); }
.card-sub { margin: 0; font-size: 0.8125rem; color: var(--bhg-muted); }
.card-foot {
  margin-top: 1rem; padding-top: 0.75rem;
  border-top: 1px solid var(--bhg-border);
}

/* A card whose whole body is one table: the table meets the card's edge, and
 * only the heading is inset. */
.card.card-flush { padding: 0; overflow: hidden; }
.card.card-flush > .card-head { padding: 1.5rem 1.5rem 0; }
.card.card-flush .table-wrap { margin: 0; border: 0; border-radius: 0; box-shadow: none; }

.section-title {
  margin: 1.5rem 0 0.5rem; font-size: 0.9375rem; font-weight: 600;
  color: var(--bhg-heading);
}

/* --------------------------------------------------------------------- */
/* 4. Notices                                                             */
/* --------------------------------------------------------------------- */
/* .notice predates the theme and is the console's standing "read this before
 * you touch anything" block -- dry run, missing credentials, live-with-no-
 * allowlist. Rendered as a Sneat alert with a left rule, because these are
 * read at a glance and the tint alone is too quiet for the loud ones. */

.notice {
  position: relative;
  padding: 0.9375rem 1rem;
  margin-bottom: 1rem;
  border: 0 solid transparent;
  border-left: 3px solid var(--bhg-border);
  border-radius: 0.375rem;
  background-color: var(--bhg-surface-2);
  color: var(--bhg-text);
}
.notice > :last-child { margin-bottom: 0; }
.notice-title { margin: 0 0 0.25rem; font-size: 0.9375rem; font-weight: 600; }
.notice-body { margin: 0 0 0.5rem; font-size: 0.875rem; }
.notice-loud { padding: 1.25rem 1.375rem; }
.notice-loud .notice-title { font-size: 1.125rem; }

.notice-ok    { background-color: #e8fadf; border-left-color: #71dd37; }
.notice-warn  { background-color: #fff2d6; border-left-color: #ffab00; }
.notice-error { background-color: #ffe0db; border-left-color: #ff3e1d; }
.notice-ok    .notice-title { color: #5faf2b; }
.notice-warn  .notice-title { color: #cc8900; }
.notice-error .notice-title { color: #e63917; }
.notice-ok, .notice-warn, .notice-error { color: #566a7f; }

/* --------------------------------------------------------------------- */
/* 5. Stat tiles                                                          */
/* --------------------------------------------------------------------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.stat {
  background-color: var(--bhg-surface);
  border-radius: 0.5rem;
  box-shadow: var(--bhg-shadow);
  padding: 1rem 1.25rem;
}
.stat-value {
  font-size: 1.625rem; font-weight: 600; line-height: 1.2;
  font-variant-numeric: tabular-nums;
  color: var(--bhg-heading);
}
.stat-label {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--bhg-muted);
}
.stat-note, .stat-help { font-size: 0.8125rem; color: var(--bhg-muted); }

/* A tile that is itself the alarm. The word still carries the state -- the
 * tint is the second signal, never the only one. */
.stat.is-warn  { background-color: #fff2d6; }
.stat.is-error { background-color: #ffe0db; }
.stat.is-warn .stat-value  { color: #cc8900; }
.stat.is-error .stat-value { color: #e63917; }

/* --------------------------------------------------------------------- */
/* 6. Tables                                                              */
/* --------------------------------------------------------------------- */
/* The wrapper scrolls, never the page. A sticky header sticks to its scroll
 * box, so it only earns its keep on a .tall wrapper. */

.table-wrap {
  overflow-x: auto;
  margin-bottom: 1.5rem;
  background-color: var(--bhg-surface);
  border-radius: 0.5rem;
  box-shadow: var(--bhg-shadow);
}
.table-wrap.tall { max-height: 70vh; overflow-y: auto; }

/* The same cap for Bootstrap's own wrapper, which only scrolls sideways. A
 * sticky header sticks to its scroll box, so it is only worth pinning once
 * that box has a height to scroll inside. */
.table-responsive.tall { max-height: 70vh; overflow-y: auto; }
.table-responsive.tall > .table > thead > tr > th {
  position: sticky; top: 0; z-index: 2;
  background-color: var(--bhg-surface);
}

/* Most pages write a bare <table>; Bootstrap only styles .table. Rather than
 * add a class to 55 templates, every table inside a wrapper or a card gets the
 * .table treatment here. */
.table-wrap > table,
.card > table,
table.grid {
  width: 100%;
  margin-bottom: 0;
  color: var(--bhg-text);
  vertical-align: top;
  border-color: var(--bhg-border);
  font-size: 0.875rem;
}
.table-wrap > table > * > tr > *,
.card > table > * > tr > * {
  padding: 0.625rem 1.25rem;
  border-bottom: 1px solid var(--bhg-border);
  line-height: 1.4;
}
.table-wrap > table thead th,
.card > table thead th {
  position: sticky; top: 0; z-index: 1;
  background-color: var(--bhg-surface);
  color: var(--bhg-muted);
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; white-space: nowrap;
  text-align: left;
  border-bottom: 1px solid var(--bhg-border);
}
.table-wrap > table tbody tr:hover,
.card > table tbody tr:hover { background-color: rgba(67, 89, 113, 0.04); }
.table-wrap > table tbody tr:last-child > *,
.card > table tbody tr:last-child > * { border-bottom: 0; }

/* A borderless two-column key/value table. Used where a <dl> would be right
 * but the value needs a third column of commentary. */
table.grid > * > tr > * { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--bhg-border); }
table.grid th[scope="row"] { font-weight: 500; color: var(--bhg-muted); text-align: left; }
table.narrow { max-width: 46rem; }

.num { text-align: right; font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }
.empty { padding: 1.25rem; color: var(--bhg-muted); font-style: italic; }
td .btn, td button { white-space: nowrap; }

/* --------------------------------------------------------------------- */
/* 7. Forms                                                               */
/* --------------------------------------------------------------------- */
/* Label above input, help under it, column capped so a text field is not
 * 1600px wide on a big monitor. */

.form { max-width: 40rem; }
.form-wide, .form-wide .field { max-width: 100%; }

.field { display: block; max-width: 40rem; margin-bottom: 1rem; }
.field-label {
  display: block; margin-bottom: 0.25rem;
  font-size: 0.875rem; font-weight: 500; color: var(--bhg-heading);
}
.req { color: #ff3e1d; }
.help, .field-help {
  display: block; margin-top: 0.25rem;
  font-size: 0.8125rem; line-height: 1.45; color: var(--bhg-muted);
}

/* Bootstrap only dresses .form-control. The macros in _macros.html emit it,
 * but plenty of pages hand-write their inputs, so every bare control gets the
 * same treatment here. Excluding the ones already carrying a Bootstrap class
 * keeps this from fighting a natively converted page. */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="hidden"]):not(.form-control):not(.form-check-input):not(.btn),
select:not(.form-select):not(.form-control),
textarea:not(.form-control) {
  display: block; width: 100%;
  padding: 0.4375rem 0.875rem;
  font-family: inherit; font-size: 0.9375rem; line-height: 1.53;
  color: var(--bhg-text);
  background-color: var(--bhg-surface);
  border: 1px solid var(--bhg-border);
  border-radius: 0.375rem;
  appearance: none;
}
textarea:not(.form-control) { min-height: 6rem; line-height: 1.6; resize: vertical; }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--bhg-accent);
  box-shadow: 0 0 0.25rem 0.05rem rgba(105, 108, 255, 0.1);
  outline: 0;
}
input:disabled, select:disabled, textarea:disabled {
  background-color: var(--bhg-surface-2); color: var(--bhg-muted);
}
input::placeholder, textarea::placeholder { color: var(--bhg-muted); opacity: 1; }

/* No width here. The rule above already excludes checkboxes and radios from
 * the 100%-wide treatment, and setting `width: auto` as well used to override
 * Bootstrap's own 1.2em on .form-check-input -- which, inside the flex row
 * below, then shrank to two pixels. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--bhg-accent); }

.field-check, .check {
  display: flex; gap: 0.625rem; align-items: flex-start;
  max-width: 40rem; margin-bottom: 1rem;
}
/* flex: none for the same reason: a box that may shrink, in a row with a
 * paragraph of help text beside it, will. */
.field-check > input[type="checkbox"], .check > input[type="checkbox"] {
  flex: none; margin-top: 0.2rem;
}
.field-check .field-label, .check .field-label { margin-bottom: 0; }
.field-check .help { margin-top: 0.125rem; }
.check { margin-bottom: 0; align-items: center; }
.checkrow { display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem; margin-bottom: 0.5rem; }

.field-row, .form-grid {
  display: flex; flex-wrap: wrap; gap: 0 1rem;
}
.field-row > .field, .form-grid > .field { flex: 1 1 12rem; max-width: none; }

/* A filter bar: the fields sit on one line with the button, and each label is
 * above its own control rather than beside it. */
.filters, .form-inline {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: 0.75rem; margin-bottom: 1.5rem; max-width: 100%;
}
.filters .field, .form-inline .field, .field-inline {
  margin-bottom: 0; max-width: 16rem; flex: 0 1 auto;
}

/* A radio list where each option is a card rather than a line: the agent
 * archetype chooser, where every option carries a title, a sentence and a line
 * of metadata, and the difference between them is the whole decision. The
 * selected one is marked by its border and its tint as well as by the radio,
 * because the radio is 18px across and the card is the thing being read. */
.choice {
  display: flex; gap: 0.75rem; align-items: flex-start;
  padding: 0.875rem 1rem; margin-bottom: 0.625rem;
  border: 1px solid var(--bhg-border); border-radius: 0.5rem;
  cursor: pointer;
}
.choice:hover { border-color: var(--bhg-accent); }
.choice:has(input:checked) {
  border-color: var(--bhg-accent);
  background-color: rgba(105, 108, 255, 0.06);
}
/* flex: none for the same reason the checkbox above needs it -- a control that
 * may shrink, in a row beside three lines of prose, will. */
.choice > input[type="radio"] { flex: none; margin-top: 0.25rem; }
.choice-body { display: block; min-width: 0; }
.choice-title { display: block; font-weight: 600; color: var(--bhg-heading); }
.choice-sub { display: block; margin-top: 0.125rem; }
.choice-meta { display: block; margin-top: 0.25rem; }

fieldset {
  margin: 0 0 1rem; padding: 1rem 1.25rem;
  border: 1px solid var(--bhg-border); border-radius: 0.5rem;
}
fieldset.field { max-width: 40rem; }
legend { float: none; width: auto; padding: 0 0.375rem; font-size: 0.875rem; font-weight: 600; }

.form-actions { display: flex; gap: 0.625rem; align-items: center; margin-top: 1.25rem; flex-wrap: wrap; }
form.inline, form.inline-form { display: inline; margin: 0; }

/* --------------------------------------------------------------------- */
/* 8. Buttons                                                             */
/* --------------------------------------------------------------------- */

/* A bare .btn is the secondary style on purpose -- the console's convention
 * long before Bootstrap arrived, and 103 buttons rely on it. Bootstrap's own
 * .btn with no variant is transparent with a transparent border, which reads
 * as plain text. The :not() chain names every variant in use rather than
 * matching on [class*="btn-"], because .btn-sm is a size and would otherwise
 * knock a small secondary button back to invisible. */
.btn:not(.btn-primary):not(.btn-secondary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-dark):not(.btn-light):not(.btn-link):not(.btn-icon):not(.btn-close):not([class*="btn-outline-"]):not([class*="btn-label-"]) {
  color: var(--bhg-text);
  background-color: transparent;
  border-color: var(--bhg-border);
}
.btn:not(.btn-primary):not(.btn-secondary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-dark):not(.btn-light):not(.btn-link):not(.btn-icon):not(.btn-close):not([class*="btn-outline-"]):not([class*="btn-label-"]):hover {
  color: var(--bhg-heading);
  background-color: var(--bhg-surface-2);
  border-color: var(--bhg-muted);
}

/* .btn-small is a typo for .btn-sm that reached three templates. Aliased
 * rather than corrected in place, so neither spelling can render full-size. */
.btn-small { padding: 0.175rem 0.75rem; font-size: 0.8125rem; border-radius: 0.25rem; }

/* A submit button inside a dropdown -- the sign-out form in the navbar. */
.dropdown-menu form.inline { display: block; }
.dropdown-item { cursor: pointer; }

/* --------------------------------------------------------------------- */
/* 9. Badges                                                              */
/* --------------------------------------------------------------------- */
/* A dot alone is not a status -- the word is. The dot is decoration for
 * somebody scanning, and the tints come from Sneat's own label palette so a
 * badge and a .bg-label-* chip on the same page are the same colour. */

.badge {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 0.3em 0.65em;
  font-size: 0.75rem; font-weight: 600; line-height: 1.4;
  border-radius: 50rem; white-space: nowrap;
  color: var(--bhg-text);
  background-color: rgba(67, 89, 113, 0.08);
}
.badge::before {
  content: ""; flex: none;
  width: 0.4375rem; height: 0.4375rem;
  border-radius: 50%; background-color: currentColor;
}
.badge + .badge { margin-left: 0.25rem; }

.badge-neutral { color: #566a7f; background-color: rgba(67, 89, 113, 0.08); }
.badge-ok      { color: #5faf2b; background-color: #e8fadf; }
.badge-warn    { color: #cc8900; background-color: #fff2d6; }
.badge-error   { color: #e63917; background-color: #ffe0db; }

/* Sneat's own chips carry their colour with !important and have no dot. */
.badge[class*="bg-label-"]::before, .badge[class*="bg-"]:not([class*="bg-label-"])::before { display: none; }

/* --------------------------------------------------------------------- */
/* 10. Code                                                               */
/* --------------------------------------------------------------------- */

code, kbd, .mono, .secret { font-family: var(--bs-font-monospace); font-size: 0.8125rem; }
code {
  padding: 0.1rem 0.35rem;
  color: var(--bhg-heading);
  background-color: var(--bhg-surface-2);
  border: 1px solid var(--bhg-border);
  border-radius: 0.25rem;
}
code.wrap { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
pre, .code-block {
  margin: 0 0 0.75rem; padding: 0.875rem 1rem;
  overflow-x: auto;
  color: var(--bhg-text);
  background-color: var(--bhg-surface-2);
  border: 1px solid var(--bhg-border);
  border-radius: 0.5rem;
  line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: 0.8125rem;
}
pre code { padding: 0; background: none; border: 0; }

.copy-row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.5rem; }
.copy-row code { flex: 1 1 20rem; padding: 0.4375rem 0.625rem; overflow-x: auto; }

/* One-time recovery codes: a printed list, so it wraps into columns and each
 * code is on its own line rather than in a paragraph somebody has to parse. */
.codes {
  list-style: none; margin: 0 0 1rem; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 0.5rem;
}
.codes code { display: block; text-align: center; padding: 0.5rem; font-size: 0.9375rem; }
.secret { letter-spacing: 0.08em; font-size: 1rem; }

/* Second-factor enrolment: the QR code and the typed secret, side by side on
 * anything wide enough and stacked otherwise. They are two routes to the same
 * secret rather than two steps, so neither is allowed to look like the
 * heading of the other. */
.enrol { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; }
.enrol-qr { flex: 0 0 auto; text-align: center; }
.enrol-qr p { margin: 0.375rem 0 0; }
.enrol-secret { flex: 1 1 18rem; min-width: 0; }
.enrol-secret p:first-child { margin-top: 0; }

/* The one drawing in this console that does not take its colour from the
 * palette: it paints its own white ground in the SVG, because a reader
 * thresholds the image before it decodes anything and an inverted code
 * defeats some of them. The padding is the quiet zone's white continuing to
 * the edge of the border, so the border never crowds the symbol.
 * Width is capped rather than fluid -- past about 12rem a QR code is not
 * easier to scan, only larger. */
.qr {
  display: block; width: 11.5rem; max-width: 100%; height: auto;
  background: #ffffff; border-radius: 0.25rem;
}

/* --------------------------------------------------------------------- */
/* 11. Charts                                                             */
/* --------------------------------------------------------------------- */
/* Server-rendered inline SVG, and still server-rendered: adopting the theme
 * did not mean adopting ApexCharts. The colour comes from currentColor, so the
 * dark palette and the print block both get it right without a second
 * declaration to keep in step. */

.chart { margin: 0 0 1.25rem; color: var(--bhg-accent); }
.chart figcaption { margin-bottom: 0.25rem; color: var(--bhg-muted); font-size: 0.8125rem; }
.chart-svg { width: 100%; height: auto; display: block; }
.chart-empty .empty { margin: 0.375rem 0 0; }
.chart-row { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }

/* --------------------------------------------------------------------- */
/* 12. Utilities                                                          */
/* --------------------------------------------------------------------- */

.muted { color: var(--bhg-muted) !important; }
/* A saving that came out below zero -- the agent cost more than it replaced.
 * Worn by a .stat-value and by table cells, so it sets colour only and lets
 * whatever it is on keep its own size. The minus sign is still the statement;
 * this is so the sign is not the only thing carrying it. */
.negative { color: #e63917; }
/* Bootstrap's .small is 0.875em, which compounds when nested inside a table
 * cell that is already 0.875rem. Pinned to an absolute size for that reason. */
.small { font-size: 0.8125rem; }
.right { text-align: right; }
.stack { display: grid; gap: 0.75rem; }
/* Was .row until the theme arrived: Bootstrap's .row is a grid container with
 * negative gutters, which stacked these children full-width. Six templates
 * were renamed rather than fight the collision -- see git history. */
.cluster { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: 1rem; }
.grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 1rem; }

.dl, .kv {
  display: grid; grid-template-columns: max-content 1fr;
  gap: 0.25rem 1rem; margin: 0; font-size: 0.875rem;
}
.dl dt, .kv dt { color: var(--bhg-muted); font-weight: 500; }
.dl dd, .kv dd { margin: 0; }

.checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.625rem; }
.checklist > li { display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }

.prose p, .prose li { max-width: 68ch; line-height: 1.65; }

/* Arabic and English in the same cell, each running its own way. */
[dir="auto"], [dir="rtl"] { unicode-bidi: plaintext; }

/* --------------------------------------------------------------------- */
/* 13. Dark palette                                                       */
/* --------------------------------------------------------------------- */
/* Sneat's free edition is light-only, so this is ours. It is keyed off
 * .dark-style on <html> -- Sneat's own class name, which keeps its
 * Helpers.isLightStyle() answering correctly -- and the class is set before
 * first paint by the inline script in _layout.html.
 *
 * The neutrals are Sneat Pro's dark values, so the two stay recognisably the
 * same product. Everything below is either a token from section 1 or one of
 * the theme's hardcoded light surfaces being repainted; there is no third
 * category, and a new rule that is neither belongs further up this file. */

.dark-style {
  --bhg-bg: #232333;
  --bhg-surface: #2b2c40;
  --bhg-surface-2: #33344a;
  --bhg-text: #a3a4cc;
  --bhg-heading: #cbcbe2;
  --bhg-muted: #7071a4;
  --bhg-border: #444564;
  --bhg-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.4);

  --bs-body-bg: #232333;
  --bs-body-color: #a3a4cc;
  color-scheme: dark;
}

.dark-style body { background-color: var(--bhg-bg); color: var(--bhg-text); }

/* Shell surfaces. */
.dark-style .bg-menu-theme,
.dark-style .bg-navbar-theme,
.dark-style .bg-footer-theme,
.dark-style .card,
.dark-style .stat,
.dark-style .table-wrap,
.dark-style .dropdown-menu,
.dark-style .modal-content,
.dark-style .offcanvas { background-color: var(--bhg-surface) !important; }

.dark-style .menu-inner-shadow { display: none !important; }
.dark-style .layout-menu { border-right: 1px solid var(--bhg-border); }

/* Menu and navbar text. */
.dark-style .bg-menu-theme .menu-link,
.dark-style .bg-menu-theme .menu-header-text { color: var(--bhg-text); }
/* The active entry keeps the theme's treatment -- a soft accent tint with
 * accent-coloured text -- but the text has to be lifted: Sneat's #696cff on a
 * 16%-alpha tint over a dark sidebar is the one place in the console where you
 * cannot tell which page you are on. Same hue, raised until it reads. */
.dark-style .bg-menu-theme .menu-inner > .menu-item.active > .menu-link { color: #a9abff; }
/* Sneat paints a *white* background on an active sub-menu entry, which the
 * !important tint above only overrides for top-level ones. The nav is flat
 * today, so nothing hits this -- it is here so that the first page to grow a
 * sub-menu does not arrive with a white bar across a dark sidebar. */
.dark-style .bg-menu-theme .menu-item.active > .menu-link:not(.menu-toggle) {
  background-color: rgba(105, 108, 255, 0.16);
}
.dark-style .bg-menu-theme .menu-link:hover { background-color: rgba(255, 255, 255, 0.06); }
.dark-style .app-brand-text,
.dark-style .text-heading,
.dark-style h1, .dark-style h2, .dark-style h3,
.dark-style h4, .dark-style h5, .dark-style h6 { color: var(--bhg-heading) !important; }
.dark-style .text-muted { color: var(--bhg-muted) !important; }

/* Type and rules. */
.dark-style hr, .dark-style .dropdown-divider { border-color: var(--bhg-border); }
.dark-style a:not(.btn):not(.menu-link):not(.dropdown-item) { color: #8f92ff; }

/* Tables. */
.dark-style .table,
.dark-style .table-wrap > table,
.dark-style .card > table,
.dark-style table.grid { color: var(--bhg-text); border-color: var(--bhg-border); }
.dark-style .table-wrap > table thead th,
.dark-style .card > table thead th { background-color: var(--bhg-surface); }
.dark-style .table-wrap > table tbody tr:hover,
.dark-style .card > table tbody tr:hover { background-color: rgba(255, 255, 255, 0.04); }
.dark-style .table > :not(caption) > * > * { background-color: transparent; color: var(--bhg-text); }

/* Controls. */
.dark-style .form-control,
.dark-style .form-select,
.dark-style input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not(.btn),
.dark-style select,
.dark-style textarea {
  background-color: var(--bhg-surface-2);
  border-color: var(--bhg-border);
  color: var(--bhg-text);
}
.dark-style .form-control:disabled,
.dark-style input:disabled, .dark-style select:disabled, .dark-style textarea:disabled {
  background-color: #2a2b3d; color: var(--bhg-muted);
}
/* The chevron on a <select> is a baked-in dark SVG; it vanishes on a dark
 * field, so it is redrawn light rather than tinted. */
.dark-style .form-select, .dark-style select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%237071a4' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
}
/* Same problem, same fix: Bootstrap's close glyph is a dark SVG. */
.dark-style .btn-close { filter: invert(1) grayscale(100%) brightness(200%); }

/* Buttons that are not a solid colour. */
.dark-style .btn:not(.btn-primary):not(.btn-secondary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-dark):not(.btn-light):not(.btn-link):not(.btn-icon):not(.btn-close):not([class*="btn-outline-"]):not([class*="btn-label-"]) {
  color: var(--bhg-text); border-color: var(--bhg-border);
}
.dark-style .btn:not(.btn-primary):not(.btn-secondary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-dark):not(.btn-light):not(.btn-link):not(.btn-icon):not(.btn-close):not([class*="btn-outline-"]):not([class*="btn-label-"]):hover {
  color: var(--bhg-heading); background-color: rgba(255, 255, 255, 0.06);
}
.dark-style .dropdown-item { color: var(--bhg-text); }
.dark-style .dropdown-item:hover, .dark-style .dropdown-item:focus {
  background-color: rgba(255, 255, 255, 0.06); color: var(--bhg-heading);
}

/* Tinted blocks. The light sheet uses near-white tints that glow on a dark
 * surface; these are the same hues at low alpha over the dark one. */
.dark-style .notice { background-color: var(--bhg-surface-2); color: var(--bhg-text); }
.dark-style .notice-ok    { background-color: rgba(113, 221, 55, 0.14); }
.dark-style .notice-warn  { background-color: rgba(255, 171, 0, 0.14); }
.dark-style .notice-error { background-color: rgba(255, 62, 29, 0.14); }
.dark-style .notice-ok, .dark-style .notice-warn, .dark-style .notice-error { color: var(--bhg-text); }
.dark-style .notice-ok    .notice-title { color: #8ce35a; }
.dark-style .notice-warn  .notice-title { color: #ffc44d; }
.dark-style .notice-error .notice-title { color: #ff7a63; }

.dark-style .stat.is-warn  { background-color: rgba(255, 171, 0, 0.14) !important; }
.dark-style .stat.is-error { background-color: rgba(255, 62, 29, 0.14) !important; }
.dark-style .stat.is-warn .stat-value  { color: #ffc44d; }
.dark-style .stat.is-error .stat-value { color: #ff7a63; }
.dark-style .negative { color: #ff7a63; }
.dark-style .choice { border-color: var(--bhg-border); }
.dark-style .choice:has(input:checked) { background-color: rgba(105, 108, 255, 0.12); }

.dark-style .badge, .dark-style .badge-neutral {
  color: var(--bhg-text); background-color: rgba(255, 255, 255, 0.08);
}
.dark-style .badge-ok    { color: #8ce35a; background-color: rgba(113, 221, 55, 0.16); }
.dark-style .badge-warn  { color: #ffc44d; background-color: rgba(255, 171, 0, 0.16); }
.dark-style .badge-error { color: #ff7a63; background-color: rgba(255, 62, 29, 0.16); }

.dark-style .alert-success { background-color: rgba(113, 221, 55, 0.16); color: #8ce35a; }
.dark-style .alert-warning { background-color: rgba(255, 171, 0, 0.16); color: #ffc44d; }
.dark-style .alert-danger  { background-color: rgba(255, 62, 29, 0.16); color: #ff7a63; }
.dark-style .alert-info    { background-color: rgba(3, 195, 236, 0.16); color: #4ad9f7; }

.dark-style .bg-label-primary   { background-color: rgba(105, 108, 255, 0.16) !important; color: #9b9dff !important; }
.dark-style .bg-label-success   { background-color: rgba(113, 221, 55, 0.16) !important; color: #8ce35a !important; }
.dark-style .bg-label-danger    { background-color: rgba(255, 62, 29, 0.16) !important; color: #ff7a63 !important; }
.dark-style .bg-label-warning   { background-color: rgba(255, 171, 0, 0.16) !important; color: #ffc44d !important; }
.dark-style .bg-label-info      { background-color: rgba(3, 195, 236, 0.16) !important; color: #4ad9f7 !important; }
.dark-style .bg-label-secondary { background-color: rgba(133, 146, 163, 0.16) !important; color: #a8b3c1 !important; }

/* Code, and the two blocks that borrow its surface. */
.dark-style code, .dark-style pre, .dark-style .code-block {
  background-color: var(--bhg-surface-2);
  border-color: var(--bhg-border);
  color: var(--bhg-text);
}
.dark-style code { color: #d8b3ff; }

.dark-style fieldset { border-color: var(--bhg-border); }
.dark-style .card-foot { border-top-color: var(--bhg-border); }

/* --------------------------------------------------------------------- */
/* 14. Print                                                              */
/* --------------------------------------------------------------------- */
/* Savings reports get printed and signed off, so this is a real output, not a
 * courtesy. Everything that is navigation goes; everything that is evidence
 * stays, on white, whichever palette the screen was on. */

@media print {
  #layout-menu, .layout-navbar, .content-footer, .layout-overlay,
  .page-actions, .nav-pills, .btn-close, .skip-link { display: none !important; }
  /* The page title is clipped on a wide screen because the navbar carries it.
     The navbar is not on the paper, so it comes back. */
  .page-head .page-title { position: static; width: auto; height: auto; margin: 0; clip: auto; clip-path: none; }

  .layout-page, .layout-navbar-fixed .layout-wrapper .layout-page { padding: 0 !important; }
  .content-wrapper, .container-xxl { padding: 0 !important; margin: 0 !important; max-width: none !important; }

  /* Printing from the dark palette must not put pale grey text on white paper,
     and a report that goes to a signatory is a real output rather than a
     courtesy. Rather than fight forty !important dark rules one selector at a
     time -- `.dark-style .card` outranks a bare `.card` and no amount of
     !important changes that -- the dark tokens are restated as ink on white.
     Every rule in section 13 is written in terms of these, so every one of
     them repaints itself. */
  .dark-style {
    --bhg-bg: #fff;
    --bhg-surface: #fff;
    --bhg-surface-2: #fff;
    --bhg-text: #000;
    --bhg-heading: #000;
    --bhg-muted: #333;
    --bhg-border: #ccc;
    --bhg-shadow: none;
  }

  html, body, .card, .stat, .table-wrap {
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
  }

  /* The handful of dark rules that name a literal colour rather than a token:
     the tinted chips, links and inline code, all of which are light hues
     chosen to sit on a dark surface and none of which reads on paper. The word
     is the status here and the colour never was, so on paper it is just ink. */
  .dark-style a, .dark-style code, .dark-style .badge,
  .dark-style [class*="badge-"], .dark-style [class*="bg-label-"],
  .dark-style .notice-title, .dark-style .stat-value,
  .dark-style h1, .dark-style h2, .dark-style h3,
  .dark-style h4, .dark-style h5, .dark-style h6,
  .dark-style .text-muted, .dark-style .muted { color: #000 !important; }

  .card, .table-wrap, .stat { border: 1px solid #ccc !important; }
  /* Tints survive on paper -- pale over white, and they are the only thing
     marking an alarm tile once the palette is gone. */
  .badge, [class*="bg-label-"] { border: 1px solid #ccc; }
  .chart-svg, .card, .stat { break-inside: avoid; }
  a[href]::after { content: ""; }
}
