/* hub.css — everything the Hub authors locally, against design-system.css's tokens.
 *
 * Linked AFTER design-system.css, never edited into it. That separation is what
 * makes the byte-equality assertion on the vendored sheet possible
 * (hub/tests/test_design_system_parity.py): Hub chrome lives here, the design
 * system stays a verbatim copy, and drift in either direction is visible.
 *
 * Seeded from the approved prototype's working draft (.cj/prototypes/624/
 * _common.py, HUB_CSS) — the prototype is authoritative for the focal element of
 * each Hub screen, and this sheet is a by-product of it rather than a
 * description of it.
 *
 * ===========================================================================
 * PROMOTION CANDIDATE FOR THE END-OF-BRANCH DESIGN REVIEW — the app shell.
 *
 * The `-- the app shell` block below (`body.has-sidebar`, `.app-content`,
 * `#app-sidebar` and the whole `.sb-*` family) is the Atlas shell, and #656 gave
 * it its SECOND consumer: the rules live in `platform/app/static/style.css` too,
 * because that sheet is the Platform's own fork of the design system and the Hub
 * refuses to vendor it (`tests/test_design_system_parity.py` — two competing
 * sheets is the cost it exists to avoid). So the Hub re-expresses the shell on
 * the design system's own tokens, here, matching the Platform's 252/64 geometry.
 *
 * That makes it a promotion candidate on the rule of two, exactly as
 * `.badge { white-space: nowrap }` was (decision #143) — and #656 deliberately
 * does NOT promote it: `shared/design-system/` and the Platform's `style.css` are
 * both out of scope for that ticket, and moving a shell two consumers depend on
 * is the design review's call to make, not an implementer's. Flagged, not done.
 *
 * RULED 2026-08-12 by the design review: **not promoted — backlogged as DR47**
 * with a unification plan. The rule of two is met, but the promotion mechanism
 * cannot reach both consumers: the Hub vendors `design-system.css` byte-identical
 * while the Platform consumes the system *by authorship*, so moving these rules
 * into the spec sheet would reconcile the Hub and leave `style.css` a third copy.
 * And the two copies are not pixel-equal — four values below resolve 1px away
 * from the Platform's (the brand sub-line 11px vs 10px, `.sb-item` and
 * `.sb-menu-item` padding-inline 8px vs 9px, `.sb-profile` gap 8px vs 9px,
 * `.sb-menu-divider` margin-block 4px vs 5px), because the Platform's are
 * off-scale prototype-tuned literals that no token spells (DR23). Closing that
 * gap is CJ's ruling on four brand-tuned numbers, not a review's mechanical
 * fold-in. See `shared/design-system/design/decisions.md` #146 + DR47.
 * ===========================================================================
 */

/* -- nothing to declare for the caution colour ------------------------------
 * Resolved upstream, so this sheet carries no override.
 *
 * Research #620 §5.3 flagged the spec sheet as missing --warning/
 * --warning-surface/--warning-border/--notification-strong; PR #626 restored
 * all four under the token-parity guard. That left .badge--warn still painted
 * in ACCENT — the colour that means active/selected everywhere else — which the
 * Hub overrode locally, because "License expires soon / expired" must read as
 * neither danger (nothing is gated) nor selected. PR #628 then repointed the
 * whole .warn family onto the warning tokens in the spec sheet itself, so the
 * override is gone and the Hub inherits the correct reading.
 *
 * Both of #620 §5.2's design-system costs are now retired upstream. What
 * remains below is Hub chrome only: things the spec sheet was never going to
 * carry, not fixes to it. */

/* -- the app shell --------------------------------------------------------- (#656)
 * The Platform's Atlas shell, re-expressed on the design system's tokens. See the
 * PROMOTION CANDIDATE note in this file's header for why it is authored here
 * rather than taken from `platform/app/static/style.css` or added to the design
 * system.
 *
 * Two kinds of number appear below. Spacing, radius, type and colour go through
 * tokens. **Geometry does not**: 252/64 is the Atlas rail's width open and
 * collapsed, and 64px again the rail head's height, 36/34/30/22/18 the mark,
 * collapse button, avatar, icon slot and glyph. Those are component dimensions
 * with no token to name them, and inventing spacing-token spellings for them
 * would make the rail agree with the Platform's by coincidence rather than by
 * intent. They are literal here for the same reason they are literal there.
 *
 * `.sb-mark`'s `font-weight: 800` is the **one exception on the token side**, and
 * it is called out at the declaration: the ramp's heaviest weight is
 * `--fw-bold: 700`, so the only way to match the Platform's brand mark is the
 * off-scale literal. Every other weight, size and colour below goes through a token.
 *
 * `svg.ico { display: block }` is carried across deliberately: an inline SVG sits
 * on a text baseline and its host reserves descender space below it, so a
 * centring control centres the taller box and the mark shrinks to a few px. The
 * design system's `.ico-svg` is a different class on a different element, so it
 * does not cover the glyphs `icons.js` stamps. */
svg.ico { display: block; }

/* #app-sidebar's containing block is the body, so the body must grow with the
 * content for a sticky rail to have room to stick — otherwise it is capped at one
 * viewport and the nav scrolls away. */
body.has-sidebar { display: flex; min-height: 100vh; height: auto; margin: 0; }
.app-content { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#app-sidebar {
  flex: none; width: 252px; display: flex; flex-direction: column; gap: var(--space-1);
  padding: 0; background: var(--surface-raised);
  border-right: 1px solid var(--border);
  /* Pin the rail and let IT scroll (not the page) when its own content exceeds
   * the screen — 100dvh so mobile browser chrome never clips the bottom item. */
  position: sticky; top: 0; height: 100dvh; overflow: visible;
  transition: width var(--motion-fast);
}
#app-sidebar.collapsed { width: 64px; }

.sb-rail-head { flex: none; min-height: 64px; display: flex; align-items: center;
  gap: var(--space-5); padding: var(--space-5); }
.sb-brand { min-width: 0; display: flex; align-items: center; gap: var(--space-5);
  color: var(--text); text-decoration: none; overflow: hidden; }
.sb-brand:hover { text-decoration: none; }
/* `font-weight: 800` is a **literal on purpose**, and the one weight in this sheet
 * that is. The token ramp stops at `--fw-bold: 700` (design-system.css); the
 * Platform's own `.sb-mark` is 800, and 700 in a 36px reversed tile renders as a
 * visibly lighter "Y" — the brand mark beside an identical one. So it goes literal
 * for the same reason the geometry above does: taking `--fw-bold` would make the
 * two marks disagree, and minting an `--fw-black` token for a single glyph would be
 * a design-system change made from a consumer (see the PROMOTION CANDIDATE note in
 * this file's header — same call, same answer). */
.sb-mark { width: 36px; height: 36px; display: grid; place-items: center;
  flex: none; border-radius: var(--radius-md); color: var(--surface-raised);
  background: var(--text); font-size: var(--fs-title); font-weight: 800; }
.sb-brand-copy { min-width: 0; }
.sb-brand-copy strong, .sb-brand-copy span { display: block; white-space: nowrap; }
.sb-brand-copy strong { font-size: var(--fs-title); }
/* The Platform's own sub-line is a 10px mono label; --fs-eyebrow (11px) is the
 * ramp's floor and the token equivalent of "smallest label text". */
.sb-brand-copy span { color: var(--text-muted); font-family: var(--mono);
  font-size: var(--fs-eyebrow); line-height: 1.35; letter-spacing: .05em; }
.sb-collapse { width: 34px; height: 34px; margin-left: auto; padding: 0;
  display: grid; place-items: center; flex: none; color: var(--text-muted);
  background: transparent; border-color: transparent; }
.sb-collapse:hover { color: var(--text); background: var(--surface-hover); }

.sb-nav-scroll { min-height: 0; flex: 1 1 auto; overflow-y: auto;
  padding: var(--space-1) var(--space-5) var(--space-6); }
.sb-nav { display: flex; flex-direction: column; gap: var(--space-1); }
.sb-item {
  display: flex; align-items: center; gap: var(--space-5);
  min-height: 38px; padding: var(--space-4); border-radius: var(--radius);
  font-size: var(--fs-body); color: var(--text); text-decoration: none;
  white-space: nowrap; overflow: hidden;
}
.sb-item:hover { background: var(--surface-hover); text-decoration: none; }
.sb-item.active { background: var(--accent-surface); color: var(--accent-text); font-weight: var(--fw-emph); }
.sb-item:focus-visible, .sb-collapse:focus-visible,
.sb-brand:focus-visible, .sb-profile:focus-visible {
  outline: 2px solid var(--focus-ring); outline-offset: 1px;
}
.sb-ico { width: 22px; display: grid; place-items: center; flex: none; }
.sb-ico svg { width: 18px; height: 18px; }
/* The Unclaimed count, carried over from the retired `.hub-nav .count` rule
 * unchanged. It sits INSIDE .sb-label (hub-sidebar.js), so the collapsed rail
 * hides it with the label and no second rule is needed. */
.sb-count {
  margin-left: var(--space-3); font-family: var(--mono); font-size: var(--fs-eyebrow);
  border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0 var(--space-3);
}

.sb-rail-foot { flex: none; position: relative;
  padding: var(--space-4) var(--space-5) var(--space-5);
  border-top: 1px solid var(--border); }
.sb-profile { width: 100%; min-height: 40px; display: flex; align-items: center;
  gap: var(--space-4); padding: var(--space-3); border-color: transparent;
  border-radius: var(--radius); background: transparent; color: var(--text);
  text-align: left; }
.sb-profile:hover { background: var(--surface-hover); }
.sb-avatar { width: 30px; height: 30px; display: grid; place-items: center;
  flex: none; border-radius: var(--radius-pill); color: var(--accent-text);
  background: var(--accent-surface); font-weight: var(--fw-emph); }
.sb-profile-copy { min-width: 0; flex: 1; }
.sb-profile-copy strong { display: block; overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis; font-size: var(--fs-body-sm); }
.sb-profile-more { display: grid; place-items: center; color: var(--text-muted); }
.sb-profile-menu { position: absolute; left: calc(100% + var(--space-4));
  bottom: var(--space-5); z-index: var(--z-popover); min-width: 190px;
  padding: var(--space-3);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface-raised); box-shadow: var(--shadow-popover); }
.sb-profile-menu[hidden] { display: none; }
.sb-menu-item { width: 100%; display: block; padding: var(--space-4); border: 0;
  border-radius: var(--radius-sm); background: transparent; color: var(--text);
  text-align: left; text-decoration: none; }
.sb-menu-item:hover { background: var(--surface-hover); text-decoration: none; }
.sb-menu-item.danger { color: var(--danger); }
.sb-menu-divider { height: 1px; margin: var(--space-2); background: var(--border); }
.sb-menu-form { margin: 0; }

/* Collapsed: the glyphs and nothing else. */
#app-sidebar.collapsed .sb-label,
#app-sidebar.collapsed .sb-brand-copy,
#app-sidebar.collapsed .sb-profile-copy,
#app-sidebar.collapsed .sb-profile-more,
#app-sidebar.collapsed .sb-collapse { display: none; }
#app-sidebar.collapsed .sb-rail-head,
#app-sidebar.collapsed .sb-profile { justify-content: center; }
#app-sidebar.collapsed .sb-brand { justify-content: center; }
#app-sidebar.collapsed .sb-nav-scroll,
#app-sidebar.collapsed .sb-rail-foot { padding-inline: var(--space-5); }
#app-sidebar.collapsed .sb-item { justify-content: center; padding-inline: var(--space-4); }

/* -- page shell ------------------------------------------------------------
 * The topbar keeps its place and loses its contents (#656): navigation and the
 * profile went to the rail, Dark mode to /settings, so a console screen's topbar
 * is a `.badge` naming the screen plus a spacer — the Platform's own idiom. The
 * `.brand` rule stays for /login, the one screen with no rail (ruling (E)) and
 * therefore the one place the product's name still has to be written. */
.hub-topbar {
  display: flex; align-items: center; gap: var(--space-8);
  padding: var(--space-5) var(--space-9);
  border-bottom: 1px solid var(--border); background: var(--surface-raised);
}
.hub-topbar .brand { font-size: var(--fs-brand); font-weight: var(--fw-bold); letter-spacing: -.015em; }
.hub-topbar .spacer { flex: 1; }

/* Wider than .admin-wrap's 760px — three stacked panels of tabular data with an
 * advisory lane need the room. The rail does now compete for it, and collapses to
 * 64px when a reader wants all of it back; see
 * tests/test_design_system_parity.py::test_the_hub_wrap_is_a_thousand_pixels.
 *
 * `width: 100%` is load-bearing and arrived with the rail. Inside `.app-content`
 * this is a **flex item**, and a flex item with `auto` margins on the cross axis
 * does not get `stretch` — so `max-width` had nothing to cap and the wrap
 * shrink-to-fit its own content: measured at **796px** of the 1028px available at
 * a 1280px viewport, narrower than the 1000px this sheet and its test both claim.
 * A definite cross size restores the cap, and the auto margins still centre it. */
.hub-wrap { width: 100%; max-width: 1000px; margin: var(--space-9) auto var(--space-10); padding: 0 var(--space-9); }
.hub-wrap h1 { font-size: var(--fs-h1); margin: 0 0 var(--space-2); }
.hub-wrap .sub { color: var(--text-muted); margin: 0 0 var(--space-9); max-width: 66ch; }
.hub-stack { display: flex; flex-direction: column; gap: var(--space-8); }
.hub-back { display: inline-block; font-size: var(--fs-body-sm); margin-bottom: var(--space-6); }

/* -- table affordances ----------------------------------------------------- */
.row-actions { display: flex; gap: var(--space-3); justify-content: flex-end; }
.table td.acts { width: 1%; white-space: nowrap; }
.table .sub-line { color: var(--text-muted); font-size: var(--fs-meta); margin-top: var(--space-1); }
.mono { font-family: var(--mono); font-size: var(--fs-meta); }

/* Whole-row navigation. The prototype spelled this per row as an inline
 * onclick plus style="cursor:pointer"; production carries the affordance in the
 * sheet and the destination in a data attribute, with one delegated listener on
 * the panel. Same behaviour, same pointer, no inline handlers. */
.table tbody tr[data-href] { cursor: pointer; }

/* The Organizations list's two own rules, from the prototype's page CSS block.
 * The name is the row's subject, so it carries the emphasis weight; the count is
 * a number in a column of numbers, so its figures line up. */
.org-name { font-weight: var(--fw-emph); }
.dep-count { font-variant-numeric: tabular-nums; }

/* The Organization detail page's two, from its prototype's page CSS block.
 *
 * The Deployment name is the subject of its row, exactly as .org-name is — one
 * column of names is the whole table, so the weight is what makes it scannable.
 *
 * The License STRIP is the same .panel-head as every other panel carrying a little
 * MORE vertical space — --space-7 (14px) per edge against the design system's own
 * --space-6 (12px), so 2px taller top and bottom. It holds four facts on one line
 * instead of heading a table, so the extra room is what stops it reading as a label
 * strip above a panel whose contents failed to arrive. The value is the prototype's
 * own, carried literally.
 *
 * (The prototype's third rule, .lineage, is deliberately not carried: the row's
 * sub-line uses .sub-line above, which declares that rule's colour and size plus a
 * margin-top of --space-1 — so the line sits 2px lower than the prototype drew it,
 * on the spacing every other sub-line in this console already uses.) */
.dep-name { font-weight: var(--fw-emph); }
.lic-strip .panel-head {
  padding-top: var(--space-7); padding-bottom: var(--space-7);
}

/* The advisory fence. Everything a Deployment says about itself is unverified
 * (the Hub-minted dep_ id is identity; label/url/version are display). It is
 * rendered in a visually separate lane, never mixed into a Hub-observed
 * column, and the column group says so out loud. */
.table th.observed { color: var(--success); }
.table th.reported { color: var(--text-muted); }
.table .lane-split { border-left: 1px solid var(--border); }
.reported-cell { color: var(--text-muted); font-size: var(--fs-meta); }
.reported-cell .unnamed { font-style: italic; }

/* -- the registration-key block --------------------------------------------
 * Ported from platform/app/static/style.css's .key-reveal, with the raw
 * literals re-expressed on the scale tokens. Accent, not danger — "calm, never
 * scary" (DESIGN.md).
 *
 * NOTE: this is not a one-TIME reveal. An unspent key is readable on its
 * Deployment's page for as long as it is unspent, so the block is a durable
 * display, not a ceremony. The name is kept because the CSS is unchanged and
 * the Platform precedent it came from still carries it. */
.key-reveal {
  border: 1px solid var(--accent); background: var(--accent-surface);
  border-radius: var(--radius-md); padding: var(--space-7) var(--space-8);
  display: flex; flex-direction: column; gap: var(--space-5);
}
.key-reveal .eyebrow { color: var(--accent-text); }
.key-reveal code {
  display: block; font-family: var(--mono); font-size: var(--fs-body);
  letter-spacing: .04em; word-break: break-all; user-select: all;
  background: var(--surface-raised); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--space-6) var(--space-7);
}
.key-reveal .terms { color: var(--accent-text); font-size: var(--fs-meta); }
.key-reveal .warn-line { color: var(--text-muted); font-size: var(--fs-meta); }
.key-reveal .acts { display: flex; gap: var(--space-4); align-items: center; }

/* -- the mint / create row -------------------------------------------------
 * .new-row is in the design system; this only lets a second control ride along. */
.new-row .grow { flex: 1; }
.new-row .lbl { font-size: var(--fs-meta); color: var(--text-muted); align-self: center; }

/* -- key/value block -------------------------------------------------------
 * The Deployment page's Status panel and its fenced advisory lane are the only
 * consumers: the License the draft named is a strip in a .panel-head, not a
 * panel of fields. So the value carried is that page's own — 190px, from its
 * prototype's page CSS block, which is this sheet's authority for it (the
 * draft's 180px came from a License-panel sketch that never shipped).
 *
 * The Deployment ID reads at --fs-body-sm rather than .mono's --fs-meta: it is a
 * value in a row of values rather than a sub-line, and it is the one string a
 * support call asks to have read down the phone. Scoped to the .kv value, so the
 * table sub-lines that share .mono keep their own size. */
.kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-8); }
.kv .k { font-size: var(--fs-meta); color: var(--text-muted); margin-bottom: var(--space-2); }
.kv .v { font-size: var(--fs-body); }
.kv .v.mono { font-size: var(--fs-body-sm); }

/* A value that is not there yet — "not yet supplied", "not reported". The
 * prototype's `.lineage`, renamed: `lineage` is the name of the
 * replaces_deployment_id idea the spec killed, and `.sub-line` (the shipped
 * spelling of this colour and size) carries a margin-top an inline value inside
 * a .kv cell must not have. The same two declarations the prototype drew. */
.kv .v .absent { color: var(--text-muted); font-size: var(--fs-meta); }

/* The Deployment page's heading row: CJ's name for the machine, its sub-line
 * under it. Carried from that page's own prototype CSS block. */
.dep-head { display: flex; align-items: baseline; gap: var(--space-6); margin-bottom: var(--space-2); }
.dep-head h1 { margin: 0; }

/* -- panel foot ------------------------------------------------------------ */
.panel-foot {
  display: flex; align-items: center; gap: var(--space-5);
  padding: var(--space-6) var(--space-8); border-top: 1px solid var(--border);
}
.panel-foot .note { flex: 1; color: var(--text-muted); font-size: var(--fs-meta); }
.panel-head .spacer { flex: 1; }
.panel-head input[type="search"] { min-width: 260px; }

/* The Unclaimed queue's own three rules, from its prototype's page CSS block.
 *
 * The contact email is the subject of its row — the same emphasis .org-name and
 * .dep-name carry on the two screens whose subject is a name — and here it is the
 * leading column *and* the filter, because two rows from one customer gather into
 * one Claim decision.
 *
 * .queue-tools is the panel head's cluster: the filter, the Show stale checkbox and
 * (the one sanctioned addition to this screen) the unbound-key button, on one
 * baseline. Its search field is 240px against the lookup's 260px — the prototype's
 * own value, and it wins on equal specificity by sitting after the rule above.
 *
 * (The prototype's other two, .dep-id and .filter-note, are deliberately not
 * carried: .mono already declares .dep-id's two properties, and .sub-line declares
 * .filter-note's plus a margin-top of --space-1 — the same substitutions #635 made
 * for .lineage, so the queue's sub-lines sit 2px apart on the spacing every other
 * sub-line in this console already uses.) */
.email { font-weight: var(--fw-emph); }
.queue-tools { display: flex; align-items: center; gap: var(--space-6); }
.queue-tools input[type="search"] { min-width: 240px; }

/* The queue's `dep_…` is a LINK to the Deployment's page — the prototype's row has
 * no route there, because in the prototype every row has already registered and
 * there is nothing on that page to go and read. The unbound-key control's own row
 * has a live Registration Key waiting on it.
 *
 * It carries the text colour rather than the accent, so it reads exactly as the
 * prototype's `.dep-id` does: the row's subject is the email above it, and an
 * accent-painted identifier under a bold address competes with it for the eye. The
 * affordance is the pointer and the hover underline the design system already
 * gives every link. */
.table a.mono { color: inherit; }

/* -- nothing to declare for a pill that does not wrap -----------------------
 * The Unclaimed queue's *Awaiting registration* badge sits inline in a narrow
 * column beside a relative time and broke across two lines, which reads as two
 * badges. This sheet scoped `white-space: nowrap` to that one cell and flagged
 * it as a promotion candidate for the end-of-branch review.
 *
 * The 2026-08-11 design review PROMOTED it: `--radius-pill` assumes one line, so
 * a wrapping label is a defect in the primitive rather than a need of this
 * screen — and `Awaiting registration` is in a `td` on the Organization detail
 * screen too, with no rule to save it. `.badge` in the design system now carries
 * the declaration and this sheet carries none. See
 * `shared/design-system/design/decisions.md`. */

/* -- the Settings screen ----------------------------------------------------
 * The Platform Admin's Settings composition (its #419 "Variant A — Inset
 * index"), adopted for this screen by CJ's ruling of 2026-08-15 (#687): an
 * inset section index beside the composed surface, one section visible at a
 * time, the page locked to the viewport so the index runs full height and the
 * stage scrolls inside it. The values are the Platform's own (style.css),
 * re-authored here on the tokens because the Hub refuses that forked sheet and
 * writes its shell CSS itself (#656) — spelled through --space-* / --fs-* /
 * --radius* where a token carries the exact value, and carried literally where
 * the Platform's value sits between tokens (3px gaps, the 226px index, the 16px card
 * pad, the 28px stage pad, the 42px/20px button geometry), so the two consoles' screens measure the same. */
body.settings-page.has-sidebar { height: 100vh; overflow: hidden; }
.settings-page .app-content { height: 100vh; min-height: 0; }
.settings-wrap { flex: 1; min-height: 0; display: flex; align-items: stretch; }
.settings-index {
  flex: none; width: 226px; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 3px;
  padding: var(--space-8) var(--space-6); overflow-y: auto;
  background: var(--surface); border-right: 1px solid var(--border);
}
.settings-index-head { padding: 1px var(--space-5) 13px; }
.settings-index-head strong { display: block; font-size: var(--fs-title); }
.settings-index-head span { display: block; color: var(--text-muted); font-size: var(--fs-eyebrow); }
.settings-index-list { display: flex; flex-direction: column; gap: 3px; }
.settings-index-btn {
  width: 100%; display: grid; grid-template-columns: 20px minmax(0, 1fr);
  align-items: center; gap: var(--space-4); min-height: 42px; padding: var(--space-4) 9px;
  color: var(--text-muted); text-align: left; font-family: inherit;
  background: none; border: 1px solid transparent; border-radius: var(--radius);
  cursor: pointer;
}
.settings-index-btn > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-index-btn:hover { color: var(--text); background: var(--surface-hover); }
.settings-index-btn.active { color: var(--text); background: var(--accent-surface); font-weight: var(--fw-bold); }
.settings-index-btn.active .ico { color: var(--primary); }
.settings-index-btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.settings-stage { flex: 1; min-width: 0; overflow-y: auto; padding: 28px clamp(20px, 4vw, 48px) 120px; }
.settings-sec { width: min(960px, 100%); }

/* page-head per section: kicker + heading + description */
.settings-page-head { margin-bottom: 20px; }
.settings-kicker { color: var(--primary); font-size: var(--fs-eyebrow); font-weight: var(--fw-bold); letter-spacing: .1em; text-transform: uppercase; }
.settings-page-head h1 { margin: 2px 0 4px; font-size: var(--fs-h1); }
.settings-page-head p { margin: 0; max-width: 640px; color: var(--text-muted); }

/* flat configuration Card — an ordinary settings surface stays FLAT (the
 * Platform's #401): no ornamental elevation. */
.settings-card {
  padding: 16px; margin-bottom: 13px;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface-raised);
}
.settings-card-head { display: flex; align-items: flex-start; gap: var(--space-5); margin-bottom: 13px; }
.settings-card-ico { flex: none; margin-top: 1px; color: var(--primary); display: inline-grid; place-items: center; }
.settings-card-head > div { min-width: 0; }
.settings-card-head strong { display: block; }
.settings-card-head span { display: block; margin-top: 2px; color: var(--text-muted); font-size: var(--fs-meta); }

/* the password form — the Admin's narrow write-only column (#687) */
.settings-form-narrow { display: flex; flex-direction: column; gap: var(--space-5);
  max-width: 360px; }
.settings-actions { display: flex; gap: var(--space-4); align-items: center;
  margin-top: var(--space-4); flex-wrap: wrap; }

/* the three-state Dark mode segmented control — the Admin's dm-group */
.dm-group { display: inline-flex; align-self: flex-start; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.dm-opt { border: none; border-radius: 0; background: var(--surface-raised); padding: var(--space-3) var(--space-7); display: inline-flex; align-items: center; justify-content: center; }
.dm-opt + .dm-opt { border-left: 1px solid var(--border); }
.dm-opt:hover { background: var(--surface); }
.dm-opt.active { background: var(--primary); color: var(--on-primary); }
.dm-opt:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }

/* Below 680px the index collapses to a wrapped section bar above the content,
 * as the Platform's does. */
@media (max-width: 680px) {
  body.settings-page.has-sidebar { height: auto; overflow: visible; }
  .settings-page .app-content { height: auto; }
  .settings-wrap { flex-direction: column; }
  .settings-index {
    width: auto; flex-direction: row; flex-wrap: wrap; gap: var(--space-3);
    align-items: center; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--border);
  }
  .settings-index-head { display: none; }
  .settings-index-list { flex-direction: row; flex-wrap: wrap; gap: var(--space-3); }
  .settings-index-btn { min-width: max-content; min-height: 36px; grid-template-columns: 18px auto; }
  .settings-stage { padding: 20px var(--space-7) 120px; }
  .settings-sec { width: 100%; }
}
