/* GENERATED by `npm run design:build` from styles/ (scripts/design.ts, design/css.ts). Do not edit: change styles/. */

@layer base {

/* ── styles/base/reset.css ── */
/* base/reset.css: Element defaults: box model, page, body text. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  height: 100%;
  background: var(--ds-surface);
  color: var(--ds-text);
  font-family: var(--ds-font-ui);
  font-size: 14px;
  /* 14px text at a 20px line (Atlassian font.body 14/20, measured on Jira); a ratio, so text that
     only sets a font-size keeps a matching line. */
  line-height: var(--ds-line-height-body);
  overflow: hidden;
}
/* These "mono" values should read bold and clear — every element using
--font-mono (including inline styles like font-family:var(--font-mono))
gets weight 600 so nothing looks thin. */
[style*="font-mono"] { font-weight: 600; letter-spacing: 0.1px; }
/* ═══ Light theme ═══════════════════════════════════════════════════════ */
:root[data-theme="light"] body { background: var(--ds-surface); }
[draggable="true"] { -webkit-user-drag: element; }
body {
  height: 100%;
  font-size: 14px;
  overflow: hidden;
  background: var(--ds-surface);
  color: var(--ds-text);
  font-family: var(--ds-font-ui);
}
/* Code samples */
samp { font-family: var(--ds-font-code); font-size: 12px; }
[onclick],
[role="tab"],
summary,
th[data-sort],
[data-panel],
[data-act],
[data-filter],
[data-view],
[data-go],
tr[data-id] {
  cursor: pointer;
}
:disabled, [aria-disabled="true"] { cursor: not-allowed; }
:where(:focus-visible) { outline-offset: 2px; }

/* ── styles/base/forms.css ── */
/* base/forms.css: Native form fields: inputs, selects, textareas, checkboxes, autofill, the select chevron. */

/* Autofill override */
input:-webkit-autofill, input:-webkit-autofill:hover {
  -webkit-text-fill-color: var(--ds-text);
  box-shadow: 0 0 0 1000px var(--ds-surface-hovered) inset;
  border-color: var(--ds-border-bold);
  caret-color: var(--ds-text);
}
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ds-text);
  caret-color: var(--ds-text);
  border-color: var(--ds-border-focused);
  box-shadow: 0 0 0 1px var(--ds-border-focused);
}
input[type="search"]:focus,
input[type="number"]:focus,
input[type="url"]:focus,
input[type="tel"]:focus {
  border-color: var(--ds-brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ds-brand) 10%, transparent);
}
input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus {
  border-color: var(--ds-brand);
}
input::placeholder, textarea::placeholder { color: var(--ds-text-subtlest); }
/* keep autofill readable in light mode */
:root[data-theme="light"] input:-webkit-autofill { -webkit-text-fill-color: var(--ds-text); }
/* ── Inputs ──────────────────────────────────────────────────────────────── */
button, input { font-family: inherit; }
input:not([type]):focus,
input:is([type="text"], [type="password"], [type="email"], [type="search"], [type="number"], [type="url"], [type="tel"], [type="date"]):focus {
  border-color: var(--ds-border-focused);
  background-color: var(--ds-surface);
}
::placeholder { color: var(--ds-text-subtlest); }
/* A disabled or read-only field must not look editable: faded, neutral border, no ring. */
input:disabled, textarea:disabled { opacity: 0.5; border-color: var(--ds-border); box-shadow: none; }
select:disabled { cursor: not-allowed; opacity: 0.5; border-color: var(--ds-border); box-shadow: none; }
input[readonly]:not([type="checkbox"], [type="radio"]), textarea[readonly] {
  border-color: var(--ds-border);
  box-shadow: none;
}
input[type="number"],
input[type="url"],
input[type="tel"],
input[type="date"],
input[type="datetime-local"] {
  background: var(--ds-surface-hovered);
  outline: none;
  width: 100%;
  transition: border-color 0.2s, box-shadow 0.2s;
  appearance: none;
  background-color: var(--ds-surface-sunken);
  color: var(--ds-text);
  border: 1px solid var(--ds-border-bold);
  border-radius: var(--ds-radius-control);
  font-family: var(--ds-font-ui);
  font-size: 14px;
  height: 36px;
  padding: 0 12px;
  line-height: 34px;
  box-sizing: border-box;
}
input[type="checkbox"], input[type="radio"] {
  vertical-align: middle;
  margin: 0;
  appearance: auto;
  width: 16px;
  height: 16px;
  accent-color: var(--ds-brand);
  cursor: pointer;
}
select {
  background: var(--ds-surface-hovered);
  outline: none;
  width: 100%;
  transition: border-color 0.2s, box-shadow 0.2s;
  background-color: var(--ds-surface-sunken);
  color: var(--ds-text);
  border: 1px solid var(--ds-border-bold);
  border-radius: var(--ds-radius-control);
  font-family: var(--ds-font-ui);
  font-size: 14px;
  height: 36px;
  padding: 0 12px;
  line-height: 34px;
  box-sizing: border-box;
  appearance: none;
  padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ds-text-subtle) 50%), linear-gradient(135deg, var(--ds-text-subtle) 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
select:hover {
  appearance: none;
  padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ds-text-subtle) 50%), linear-gradient(135deg, var(--ds-text-subtle) 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  border-color: var(--ds-border-bold);
  background-color: var(--ds-surface-hovered);
}
select:focus {
  background-color: var(--ds-surface);
  appearance: none;
  padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ds-text-subtle) 50%), linear-gradient(135deg, var(--ds-text-subtle) 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  border-color: var(--ds-border-focused);
  box-shadow: 0 0 0 1px var(--ds-border-focused);
}
select:hover:focus { background-color: var(--ds-surface-hovered); }
select:disabled:hover { border-color: var(--ds-border-bold); background-color: var(--ds-surface-sunken); }
select option { background: var(--ds-surface-overlay); color: var(--ds-text); }
select option:checked { background: var(--ds-surface-selected); color: var(--ds-link); }
input[type="file"] { font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtle); cursor: pointer; }
input[type="file"]::file-selector-button {
  height: 32px;
  margin-right: 12px;
  padding: 0 12px;
  cursor: pointer;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  background: transparent;
  color: var(--ds-text-subtle);
  font: 500 14px/20px var(--ds-font-ui);
}
input[type="file"]::file-selector-button:hover { background: var(--ds-surface-hovered); color: var(--ds-text); }
button:not(:disabled), [role="button"], [role="option"], label[for], input[type="color"] { cursor: pointer; }
input[type="text"],
input[type="password"],
input[type="email"],
input[type="search"],
input:not([type]) {
  background: var(--ds-surface-hovered);
  outline: none;
  width: 100%;
  transition: border-color 0.2s, box-shadow 0.2s;
  appearance: none;
  background-color: var(--ds-surface-sunken);
  color: var(--ds-text);
  border: 1px solid var(--ds-border-bold);
  border-radius: var(--ds-radius-control);
  font-family: var(--ds-font-ui);
  font-size: 14px;
  height: 36px;
  padding: 0 12px;
  line-height: 34px;
  box-sizing: border-box;
  cursor: text;
}
textarea {
  background: var(--ds-surface-hovered);
  outline: none;
  width: 100%;
  transition: border-color 0.2s, box-shadow 0.2s;
  appearance: none;
  background-color: var(--ds-surface-sunken);
  color: var(--ds-text);
  border: 1px solid var(--ds-border-bold);
  border-radius: var(--ds-radius-control);
  font-family: var(--ds-font-ui);
  font-size: 14px;
  padding: 8px 12px;
  line-height: 20px;
  min-height: 72px;
  box-sizing: border-box;
  cursor: text;
}
/* One focus ring for every text field: 1px blue, as selects and the global search. */
input:focus {
  border-color: var(--ds-border-focused);
  box-shadow: 0 0 0 1px var(--ds-border-focused);
  outline: none;
}
textarea:focus {
  background-color: var(--ds-surface);
  border-color: var(--ds-border-focused);
  box-shadow: 0 0 0 1px var(--ds-border-focused);
  outline: none;
}

/* ── styles/base/typography.css ── */
/* base/typography.css: Headings and inline text elements. */

/* Bold is Atlassian's bold weight (653, --ds-font-weight-bold), never the browser's 700: the app
   uses four weights only, 400/500/600/653 (@atlaskit/tokens 20.6.0 font.weight.*). */
b, strong, th, h1, h2, h3, h4, h5, h6 { font-weight: var(--ds-font-weight-bold); }

/* Code samples */
code, kbd { font-family: var(--ds-font-code); font-size: 12px; }
:not(pre) > code {
  padding: 1px 4px;
  border-radius: var(--ds-radius-small);
  background: var(--ds-surface-sunken);
  color: var(--ds-text);
}
pre {
  font-family: var(--ds-font-code);
  font-size: 12px;
  padding: 12px;
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface-sunken);
  border: 1px solid var(--ds-border);
  line-height: 18px;
  overflow: auto;
}
a[href] { cursor: pointer; }

/* ── styles/base/scrollbars.css ── */
/* base/scrollbars.css: Scrollbars. */

/* ── Scrollbars ──────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--ds-surface-pressed); border-radius: var(--ds-radius-small); }
::-webkit-scrollbar-thumb:hover { background: var(--ds-border-bold); }

} /* @layer base */

@layer layout {

/* ── styles/layout/shell.css ── */
/* layout/shell.css: The app frame: app body and the panel container. */

/* ── App Shell ───────────────────────────────────────────────────────────── */
#app { display: flex; flex-direction: column; height: 100vh; }
/* ── App Body ─────────────────────────────────────────────────────────────── */
.app-body { display: flex; flex: 1; overflow: hidden; }
/* ── Panel Container ──────────────────────────────────────────────────────── */
.panel-container { flex: 1; overflow: hidden; position: relative; }
.panel.active { display: flex; }
/* One page scroll (docs/STRUCTURE.md): the panel is the page and the only scroller. Its children
   keep their natural height, so a table card grows with its rows instead of shrinking to the
   window and scrolling inside itself. A full-height tool (docs tree, graph, alert columns) opts
   back in by giving its own child flex: 1 and min-height: 0. */
.panel > * { flex-shrink: 0; }
.panel {
  display: none;
  height: 100%;
  overflow-y: auto;
  padding: 24px 28px;
  flex-direction: column;
  gap: 20px;
  background: var(--ds-surface);
}
/* Phone: 16px gutters, so a list keeps its columns. */
@media (max-width: 640px) {
  .panel { padding-left: 16px; padding-right: 16px; }
}

/* ── styles/layout/topbar.css ── */
/* layout/topbar.css: Top bar: brand, the ⌘K field, icon buttons, bell. */

.topbar {
  display: flex;
  align-items: center;
  padding: 0;
  flex-shrink: 0;
  z-index: 100;
  height: 56px;
  background: var(--ds-surface);
  border-bottom: 1px solid var(--ds-border);
  box-shadow: none;
}
.logo-sm { display: flex; align-items: center; gap: 10px; }
/* The Shield/Node mark (public/brand/): the light-background drawing (ink core) in the light theme,
   the dark-background one (gradient core) in the dark theme. Also the whole brand block on the rail. */
.logo-mark-sm {
  flex-shrink: 0;
  background: url(/brand/mark-light.svg?v=7) center / contain no-repeat;
  width: 24px;
  height: 24px;
}
:root[data-theme="dark"] .logo-mark-sm { background-image: url(/brand/mark-dark.svg?v=7); }
.brand { font: 600 15px var(--ds-font-ui); letter-spacing: 0; color: var(--ds-text); text-transform: none; }
.topbar-left {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 100%;
  padding: 0 18px;
  border-right: 1px solid var(--ds-border);
  width: 248px;
  flex-shrink: 0;
  padding-left: 16px;
}
/* With the 52px icon rail (1024px and below, layout/sidebar.css) the brand block is the rail's width:
   the logo only, its divider over the rail's border. */
/* Collapse sidebar / Expand sidebar: the first thing in the top bar, as Atlassian's
   SideNavToggleButton ("It should be used in the top bar"). Collapsed, the brand block is the rail's
   width and holds only this control (layout/sidebar.css). */
.ds-side-toggle { flex-shrink: 0; }
@media (min-width: 1025px) {
  html[data-sidebar="collapsed"] .topbar-left { width: 52px; padding: 0; justify-content: center; }
  html[data-sidebar="collapsed"] .logo-sm { display: none; }
}
@media (max-width: 1024px) {
  .topbar-left { width: 52px; padding: 0; justify-content: center; }
  .brand { display: none; }
  /* The rail is the only form here: nothing to collapse or expand. Two classes, so it wins over
     .ds-top-btn's display: grid later in this file (one class would lose to it by source order). */
  .ds-top-btn.ds-side-toggle { display: none; }
}
.topbar-center {
  flex: 1;
  display: flex;
  align-items: center;
  max-width: 640px;
  /* May shrink below its text: on a phone the search field gives way (its label ellipsises),
     so the bell and the account avatar stay inside the bar. */
  min-width: 0;
  padding: 0 16px;
}
.topbar-right {
  display: flex;
  align-items: center;
  margin-left: auto;
  flex-shrink: 0;
  gap: 4px;
  padding-right: 16px;
}
.ds-top-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: none;
  border-radius: var(--ds-radius-control);
  background: none;
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.ds-top-btn:hover { background: var(--ds-surface-hovered); color: var(--ds-text); }
.ds-top-count {
  position: absolute;
  top: 3px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--ds-radius-xsmall);   /* Atlassian radius.xsmall: badges */
  background: var(--ds-danger-bold);
  color: var(--ds-text-inverse);
  font: var(--ds-font-weight-bold) 10px/16px var(--ds-font-ui);
  text-align: center;
}
.ds-top-me { border-radius: 50%; }
.ds-top-me[aria-expanded="true"] { background: var(--ds-surface-selected); }

/* ── styles/layout/sidebar.css ── */
/* layout/sidebar.css: Sidebar: one entry per area, grouped in collapsible sections; footer. */

/* keep footer intact when the sidebar scrolls on short viewports */
.sidebar-footer { margin-top: auto; padding: 16px 20px; border-top: 1px solid var(--ds-border); flex-shrink: 0; }
.sys-version {
  font-family: var(--ds-font-ui, 'Inter', system-ui, sans-serif);
  font-size: 10px;
  font-weight: 500;
  color: var(--ds-text-subtlest);
  letter-spacing: 0.4px;
}
.nav-item.flash-alert { animation: navFlash 0.7s ease-in-out 3; }
.nav-item:hover .nav-icon { color: var(--ds-text); }
.nav-item.active .nav-icon { color: var(--ds-brand); }
.nav-section.collapsed .nav-section-chevron { transform: rotate(-90deg); }
.nav-section.collapsed .nav-items { padding-top: 0; padding-bottom: 0; max-height: 0; }
@media (prefers-reduced-motion: reduce) {
  .nav-items { transition: none; }
}
.sidebar {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  width: 248px;
  padding: 8px 0 12px;
  background: var(--ds-surface-sunken);
  border-right: 1px solid var(--ds-border);
}
.nav-section {
  overflow: hidden;
  flex-shrink: 0;
  contain: layout style;
}
.nav-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  user-select: none;
  padding: 14px 18px 6px;
  cursor: pointer;
}
/* Section titles (Main, Infrastructure, IT…): small caps with a divider above every
   section but the first, so the groups read apart from the items inside them. */
.nav-section + .nav-section > .nav-section-header { border-top: 1px solid var(--ds-border); margin: 8px 18px 0; padding: 16px 0 8px; }
.nav-section-header .nav-label {
  padding: 0;
  transition: color 0.15s;
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: var(--ds-font-weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ds-text-subtle);
}
.nav-section-header:hover .nav-label, .nav-section-header:hover .nav-section-chevron { color: var(--ds-text); }
.nav-section-chevron { flex-shrink: 0; width: 14px; height: 14px; color: var(--ds-text-subtle); transition: color 0.15s, transform 0.15s; }
.nav-items {
  overflow: hidden;
  position: relative;
  max-height: 360px;
  transition: max-height 0.18s ease;
  contain: layout paint;
  padding: 0 10px 2px;
}
.nav-item {
  transition: all 0.15s;
  font-family: var(--ds-font-ui);
  text-decoration: none;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  position: relative;
  display: flex;
  align-items: center;
  white-space: nowrap;
  height: 36px;
  margin: 1px 0;
  padding: 0 10px;
  gap: 12px;
  border-radius: var(--ds-radius-control);
  font-size: 14px;
  font-weight: 400;
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.nav-item:hover { background: var(--ds-surface-hovered); color: var(--ds-text); }
/* The current area: colour only, no side bar and no bold (atlassian.design side navigation). */
.nav-item.active { background: var(--ds-surface-selected); color: var(--ds-link); }
.nav-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  fill: currentColor;
  color: var(--ds-text-subtle);
}
.nav-badge {
  margin-left: auto;
  min-width: 16px;
  height: 16px;
  padding: 0 6px;
  border-radius: var(--ds-radius-xsmall);   /* Atlassian radius.xsmall: badges */
  font: 600 11px/16px var(--ds-font-ui);
  text-align: center;
  background: var(--ds-tone-neutral-subtle);
  color: var(--ds-text-subtle);
}
.nav-item.active .nav-badge { color: inherit; }
.nav-item:focus-visible { outline-offset: -2px; }
/* Responsive rules last: every base rule above would otherwise override them. At 1024px and
   below the sidebar is the 52px icon rail. The step must sit above the desktop app's minimum
   window (960×600, HANDOFF round 2 rule 1): with the 248px sidebar that window leaves a list
   656px and the Inventory, Domains and People tables overflow (smoke test, 29/10); 1024 is the
   first common viewport width above 960. */
@media (max-width: 1024px) {
  .sidebar { width: 52px; }
  .nav-item span:not(.nav-icon) { display: none; }
  .nav-section-header .nav-label { display: none; }
  .nav-badge { display: none; }
  .sidebar-footer { display: none; }
  .nav-item { padding: 0; justify-content: center; gap: 0; }
  /* The rail shows icons only: the section titles are hidden, so their headers keep no padding and
     the dividers only the 8px (space.100) around them. All 13 entries, Settings included, then fit
     the desktop app's 960×600 window (544px under the top bar). */
  .nav-section-header { justify-content: center; padding: 0; }
  .nav-section + .nav-section > .nav-section-header { margin: var(--ds-space-100) var(--ds-space-100); padding: 0; }
  /* No loose collapse chevrons, and every section stays open (a section folded in the full sidebar
     would otherwise hide its icons with no way to reopen it). */
  .nav-section-chevron { display: none; }
  .nav-section.collapsed .nav-items { max-height: 360px; }
}
/* Collapsed by choice: the same 52px icon rail at any wider window, so a small display gives the
   page (and its tables) the room. The Collapse sidebar control in the top bar, Ctrl+[ or [ toggles
   it and this device remembers it (11-shell.js initSidebarToggle), as in Atlassian's navigation
   system (@atlaskit/navigation-system 10.6.0: SideNavToggleButton, useSideNavToggleKeyboardShortcut)
   and Jira ("["). At 1024px and below the rail is the only form (above), so this applies above it. */
@media (min-width: 1025px) {
  html[data-sidebar="collapsed"] .sidebar { width: 52px; }
  html[data-sidebar="collapsed"] .nav-item span:not(.nav-icon) { display: none; }
  html[data-sidebar="collapsed"] .nav-section-header .nav-label { display: none; }
  html[data-sidebar="collapsed"] .nav-badge { display: none; }
  html[data-sidebar="collapsed"] .sidebar-footer { display: none; }
  html[data-sidebar="collapsed"] .nav-item { padding: 0; justify-content: center; gap: 0; }
  html[data-sidebar="collapsed"] .nav-section-header { justify-content: center; padding: 0; }
  html[data-sidebar="collapsed"] .nav-section + .nav-section > .nav-section-header { margin: var(--ds-space-100) var(--ds-space-100); padding: 0; }
  html[data-sidebar="collapsed"] .nav-section-chevron { display: none; }
  html[data-sidebar="collapsed"] .nav-section.collapsed .nav-items { max-height: 360px; }
}

/* ── styles/layout/page-header.css ── */
/* layout/page-header.css: Panel header: title, description, actions, filter row geometry. */

.select-ctrl:focus { background-color: var(--ds-surface); }
.select-ctrl:disabled { cursor: not-allowed; opacity: 0.55; }
.select-ctrl {
  height: 34px;
  min-width: 120px;
  padding: 0 10px;
  background-color: var(--ds-surface-hovered);
  cursor: pointer;
  appearance: none;
  padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ds-text-subtle) 50%), linear-gradient(135deg, var(--ds-text-subtle) 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.select-ctrl:hover {
  appearance: none;
  padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ds-text-subtle) 50%), linear-gradient(135deg, var(--ds-text-subtle) 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  border-color: var(--ds-border-bold);
  background-color: var(--ds-surface-hovered);
}
/* Page description under the title */
.panel-desc {
  margin: 0 0 16px;
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text-subtle);
  max-width: 860px;
}
.ds-section-title {
  margin: 0 0 12px;
  font: 600 16px var(--ds-font-ui);
  letter-spacing: 0;
  color: var(--ds-text);
}

} /* @layer layout */

@layer components {

/* ── styles/components/icons.css ── */
/* components/icons.css: Design-system icons and badges sized for a context (panel title, top bar, sidebar footer…). */

:is(.btn-primary, .btn-secondary, .btn-danger) > .ds-icon:first-child { margin-right: 0; }
.modal-close .ds-icon { width: 16px; height: 16px; margin: 0; }
/* Small select (pager "Per page"): 32px, sized to its numbers. */
select.ds-select-sm {
  width: auto;
  height: 32px;
  min-width: 88px;
  padding: 0 32px 0 10px;
  font-size: 14px;
  line-height: 30px;
  border-radius: var(--ds-radius-control);
}
.ds-menu-item .ds-status-icon { flex: 0 0 16px; margin-right: 6px; } /* lines up with a .ds-icon item */
.ds-section-msg > .ds-icon { color: var(--ds-tone-info); margin: 2px 0 0; }
.ds-section-msg.warning > .ds-icon { color: var(--ds-tone-warning); }
.mgmt-card-head .ds-icon { color: var(--ds-text-subtle); }
.ds-top-btn .ds-icon { width: 18px; height: 18px; margin: 0; }
/* Type chips get their type's icon in its tone colour; the label stays neutral. */
.type-badge .ds-icon { width: 14px; height: 14px; margin: 0; color: var(--ds-text-subtle); }
.alert-acked .ds-icon { margin: 0; }
.toast .toast-ico .ds-status-icon { width: 20px; height: 20px; }
.toast .toast-x .ds-icon { width: 16px; height: 16px; margin: 0; }
.data-table td .ds-row-act .ds-icon { margin: 0; }
.ds-row-link .ds-icon { width: 14px; height: 14px; margin: 0; }
.dash-card .card-head .ds-icon { margin: 0; color: var(--ds-text-subtle); }
.ds-who .ds-avatar { --size: 22px; font-size: 10px; box-shadow: none; }
.ds-type .ds-icon { margin: 0; color: var(--ds-text-subtle); }
.ds-menu-item .ds-icon { margin: 0; color: var(--ds-text-subtle); }
.ds-menu-item--danger .ds-icon { color: var(--ds-tone-danger-text); }

/* ── styles/components/buttons.css ── */
/* components/buttons.css: Buttons. */

.refresh-ico.spinning { animation: spin360 0.7s linear infinite; }
/* Anchor-styled buttons must never show the default link underline */
a.btn-primary, a.btn-secondary { text-decoration: none; }
.btn-secondary {
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ds-radius-control);
  font: 500 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  box-shadow: none;
  opacity: 1;
  white-space: nowrap;
  transition: background-color var(--ds-duration-fast) var(--ds-ease-out);
  background: var(--ds-button-default);
  color: var(--ds-text);
  border: 1px solid transparent;
}
.btn-secondary:hover:not(:disabled) { background: var(--ds-button-default-hovered); }
.btn-primary {
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ds-radius-control);
  font: 500 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  box-shadow: none;
  opacity: 1;
  white-space: nowrap;
  transition: background-color var(--ds-duration-fast) var(--ds-ease-out);
  background: var(--ds-brand);
  color: var(--ds-text-on-brand);
  border: none;
}
.btn-primary:hover:not(:disabled) { background: var(--ds-brand-hovered); opacity: 1; }
.btn-danger {
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ds-radius-control);
  font: 500 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  box-shadow: none;
  opacity: 1;
  white-space: nowrap;
  transition: background-color var(--ds-duration-fast) var(--ds-ease-out);
  background: var(--ds-button-default);
  color: var(--ds-tone-danger-text);
  border: 1px solid transparent;
}
.btn-danger:hover:not(:disabled) { background: var(--ds-tone-danger-subtle); }
:is(.btn-primary, .btn-secondary, .btn-danger):disabled { opacity: 0.5; cursor: not-allowed; }
.btn-danger-solid {
  border: none;
  cursor: pointer;
  font-family: var(--ds-font-ui);
  transition: filter 0.15s;
  background: var(--ds-danger-bold);
  color: var(--ds-text-inverse);
  font-weight: 500;
  letter-spacing: 0;
  filter: none;
}
.btn-danger-solid:hover {
  filter: none;
  background: color-mix(in srgb, var(--ds-danger-bold) 88%, var(--ds-ink));
}
.data-table td :is(.btn-secondary, .btn-danger) {
  border-color: transparent;
  background: transparent;
  color: var(--ds-text-subtle);
}
.data-table td :is(.btn-secondary, .btn-danger):hover:not(:disabled) {
  background: var(--ds-surface-hovered);
  color: var(--ds-text);
}
.data-table td .btn-danger:hover:not(:disabled) {
  background: var(--ds-tone-danger-subtle);
  color: var(--ds-tone-danger-text);
}
/* Row buttons (a button in a table cell): 28px, 13px/500, tight padding. */
.data-table td :is(.btn-primary, .btn-secondary, .btn-danger) {
  height: 28px;
  padding: 0 8px;
  font: 500 13px var(--ds-font-ui);
  letter-spacing: 0;
  line-height: 1;
  text-decoration: none;
  vertical-align: middle;
}
/* A row action written as a link (<a class="btn-primary|btn-secondary">: View Repo, View on GitHub)
   keeps 12px text and 6px 12px padding, unlike a <button> in the same cell. Deliberate; it used to be
   two override rules disagreeing. An a.btn-danger gets the button size. */
.data-table td a:is(.btn-primary, .btn-secondary) { font-size: 12px; padding: 6px 12px; }
/* Icon-only row buttons: 28px square, no border. */
.data-table td :is(.btn-primary, .btn-secondary, .btn-danger).ds-row-act {
  width: 28px;
  padding: 0;
  border-color: transparent;
}
/* Empty-state actions inside a table keep the default 32px button. */
.data-table td .ds-empty-state > :is(.btn-primary, .btn-secondary) {
  height: 32px;
  padding: 0 12px;
  font: 500 14px/20px var(--ds-font-ui);
}
@keyframes spin360 {to { transform: rotate(360deg); }}

/* ── styles/components/cards.css ── */
/* components/cards.css: Status, stat and dashboard cards, card heads, table cards. */

.card-head {
  border-bottom: 1px solid var(--ds-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 15px 18px;
}
/* When the number sits above its label (e.g. GitHub stat cards), give the
label breathing room instead of hugging the number. */
.dash-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 900px) {
  .dash-grid { grid-template-columns: 1fr; }
}
.dash-card:hover {
  border-color: var(--ds-border-card);
  transform: none;
  box-shadow: var(--ds-shadow-raised);
}
.card-title { font: 600 14px/20px var(--ds-font-ui); letter-spacing: 0; text-transform: none; color: var(--ds-text); }
.card-sub { font-weight: 500; margin-left: auto; font-size: 12px; color: var(--ds-text-subtlest); }
.dash-card {
  overflow: hidden;
  transition: box-shadow 0.16s ease, border-color 0.16s ease;
  background: var(--ds-surface-raised);
  border: 1px solid var(--ds-border-card);
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-raised);
  padding: 16px;
}
.dash-card .card-head {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  padding: 0 0 10px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--ds-border);
}
.dash-card .card-title { font: 600 16px var(--ds-font-ui); }
.dash-card .card-head .card-sub { margin-left: auto; }
/* A card clips its content to its rounded corners; an open dropdown in it must not be clipped,
   and one in the header's right end opens to the left, inside the page. */
.dash-card:has(.cs-open) { overflow: visible; }
.card-head .ie-sel-pop.ie-sel-filter { left: auto; right: 0; }

/* ── styles/components/table.css ── */
/* components/table.css: Data tables: cells, row actions, pager, sort, responsive column drops. */

.table-wrap::-webkit-scrollbar { width: 12px; height: 12px; }
.table-wrap::-webkit-scrollbar-track { background: var(--ds-surface-overlay); }
.table-wrap::-webkit-scrollbar-corner { background: var(--ds-surface-overlay); }
.table-wrap::-webkit-scrollbar-thumb {
  background: var(--ds-surface-pressed);
  border: 3px solid var(--ds-surface-overlay);
  border-radius: var(--ds-radius-card);
}
.table-wrap::-webkit-scrollbar-thumb:hover { background: var(--ds-border-bold); }
.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover td { background: var(--ds-surface-hovered); }
/* Organization chip in tables — single line, never breaks the name across rows. */
.org-tag {
  display: inline-block;
  white-space: nowrap;
  font-size: 10px;
  font-weight: var(--ds-font-weight-bold);
  padding: 3px 8px;
  border-radius: var(--ds-radius-small);
  background: color-mix(in srgb, var(--ds-tone-teal) 10%, transparent);
  color: var(--ds-tone-teal);
  border: 1px solid color-mix(in srgb, var(--ds-tone-teal) 30%, transparent);
  margin: 1px 3px 1px 0;
}
.data-table tbody tr { content-visibility: auto; contain-intrinsic-size: auto 46px; }
.table-wrap {
  overflow: auto;
  scrollbar-color: var(--ds-surface-pressed) var(--ds-surface-overlay);
  scrollbar-width: thin;
  contain: layout paint;
  /* A flat list surface: the page colour inside a 1px border, no raised fill or shadow (GitHub's
     list box, measured 29/10/2026 in ~/Documents/Infra Redesign/compare.html). */
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
}
.type-badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--ds-radius-small);
  white-space: nowrap;
  flex: none;
  gap: 6px;
  padding: 0;
  height: 20px;
  border: none;
  background: none;
  color: var(--ds-text);
  font: 400 13px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
}
.tag-pill {
  display: inline-block;
  margin: 1px;
  border: none;
  border-radius: var(--ds-radius-small);
  padding: 0 6px;
  line-height: 20px;
  background: var(--ds-tone-neutral-subtle);
  color: var(--ds-text-subtle);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0;
}
.data-table th {
  text-align: left;
  user-select: none;
  position: relative;
  /* Jira's column header, measured (compare.html): bold 12px/17px in the third grey, 10px padding,
     on the sunken fill. It scrolls away with the page (not sticky, as on GitHub, Jira and Shopify). */
  padding: 10px;
  white-space: nowrap;
  font: var(--ds-font-weight-bold) 12px/17px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ds-text-subtlest);
  background: var(--ds-surface-sunken);
  border-bottom: 1px solid var(--ds-border);
  cursor: default;
}
.data-table th:hover { color: var(--ds-text-subtlest); }
.data-table th[data-sort] { cursor: pointer; }
.data-table th[data-sort]:hover { color: var(--ds-text); }
.data-table td {
  color: var(--ds-text);
  vertical-align: middle;
  height: 40px;
  /* 10px sides, as the header (Jira cells: 5px 10px); 14px/20px text. */
  padding: 4px 10px;
  font: 400 14px/20px var(--ds-font-ui);
  border-bottom: 1px solid var(--ds-border);
}
.data-table tbody tr:hover > td { background: var(--ds-surface-hovered); }
.data-table td .ds-row-act:hover:not(:disabled) { background: var(--ds-surface-hovered); color: var(--ds-text); }
.data-table td .btn-danger.ds-row-act { color: var(--ds-text-subtle); }
.data-table td .btn-danger.ds-row-act:hover:not(:disabled) {
  background: var(--ds-tone-danger-subtle);
  color: var(--ds-tone-danger-text);
}
.ds-row-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--ds-link);
  text-decoration: none;
  white-space: nowrap;
}
.ds-row-link:hover { text-decoration: underline; }
.data-table .sort-ico { opacity: 0; }
.data-table th:hover .sort-ico, .data-table th[aria-sort] .sort-ico { opacity: 1; }
.row-actions { white-space: nowrap; text-align: right; }
.data-table th.row-actions { text-align: right; }
.data-table tbody tr:has(.ds-empty):hover > td { background: none; }
/* Table cells: a main line and a quiet second line; a person is an avatar + name. */
.ds-cell-main {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  color: var(--ds-text);
}
.ds-cell-sub { font-size: 12px; color: var(--ds-text-subtlest); }
td.ds-cell-sub { font-size: 14px; color: var(--ds-text-subtle); }
.ds-who {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-weight: 400;
  color: var(--ds-text);
  white-space: nowrap;
}
.ds-who-row { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Long values truncate instead of widening the table, as a last resort (Primer DataTable guidelines,
   "Consider small screens" and "Content truncation ... as a last resort", full value in a tooltip;
   Primer Truncate). A row link and a person's name stay on one line at their full width; only when
   a list is still wider than its room after TableFit (02-data-kit.js) has hidden what secondary
   columns it may does TableFit set data-cut on the box, and then a row link, a person's name and
   any .ds-truncate show one line ending in an ellipsis, with the whole value as the title. The cut
   is a one-line clamp rather than nowrap, so the value may break anywhere: its min-content is one
   character and the column can give way, while its max-content (what the column asks for when
   there is room) stays the whole value. A cell's second line wraps instead (Primer: wrapping is
   preferred, it hides nothing), and breaks anywhere so a long email there cannot widen the table.
   The record page shows every value in full. */
.data-table td .ds-cell-sub { overflow-wrap: anywhere; }
.ds-list-table[data-cut] .data-table td .ds-row-link:not(:has(> *)),
.ds-list-table[data-cut] .data-table td .ds-who > span:last-child,
.ds-list-table[data-cut] .data-table td .ds-truncate {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  overflow: hidden;
  overflow-wrap: anywhere;
  white-space: normal;
}
.ds-list-table[data-cut] .data-table td .ds-who,
.ds-list-table[data-cut] .data-table td .ds-row-link:has(> .ds-who) { max-width: 100%; min-width: 0; }
.ds-type { display: inline-flex; align-items: center; gap: 6px; color: var(--ds-text); }
/* Row actions: one ghost "⋯" opening an overlay menu (rowMenu in app.js); a single
visible action (Members, Restore, Revoke) stays a quiet 28px text button. */
.data-table td.row-actions { width: 1%; white-space: nowrap; }
.ds-menu.ds-row-menu-pop {
  position: fixed;
  top: 0;
  left: 0;
  right: auto;
  min-width: 200px;
}

/* ── styles/components/modal.css ── */
/* components/modal.css: Modal, confirm dialog, inline management cards. */

.modal-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 500;
  background: color-mix(in srgb, var(--ds-ink) 50%, transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.modal {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--ds-surface-overlay);
  border: none;
  border-radius: var(--ds-radius-overlay);
  box-shadow: var(--ds-shadow-overlay);
  width: 600px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 120px);
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 24px 24px 12px;
  gap: 12px;
  border-bottom: none;
  font: 600 20px/24px var(--ds-font-ui);
  letter-spacing: -0.01em;
  color: var(--ds-text);
}
.modal-head #modal-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.modal-body {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  background: transparent;
  box-shadow: none;
  padding: 4px 24px 24px;
  gap: 16px;
}
.modal-close {
  font-size: 16px;
  line-height: 1;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  flex-shrink: 0;
  border: none;
  border-radius: var(--ds-radius-control);
  background: none;
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.modal-close:hover {
  background: var(--ds-item-hovered);
  color: var(--ds-text);
  border-color: transparent;
}
.confirm-head { padding: 24px 24px 8px; font: 600 20px/24px var(--ds-font-ui); color: var(--ds-text); }
.confirm-body { padding: 0 24px 8px; }
.confirm-body p { margin: 4px 0; font-size: 14px; line-height: 20px; color: var(--ds-text); }
/* A one-field dialog (appPrompt: add/rename an organisation): the field under the question. */
.confirm-body .confirm-input { width: 100%; margin-top: var(--ds-space-100); }
.confirm-actions {
  display: flex;
  justify-content: flex-end;
  padding: 16px 24px 24px;
  gap: 8px;
  border-top: none;
  background: none;
}
/* A pick-many dialog (appPickMany: Share): the chips under the search, the optional message under them,
   the extra action (Copy link) pushed to the left of Cancel · OK. */
.confirm-pick-list { margin-top: var(--ds-space-100); }
.confirm-body .confirm-note { display: block; resize: vertical; }
.confirm-spacer { flex: 1; }
.confirm-actions button {
  min-width: 0;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ds-radius-control);
  font: 500 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
}
.mgmt-card {
  margin: 0 0 16px;
  background: var(--ds-surface-raised);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-raised);
  padding: 16px 20px;
}
.mgmt-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  font: 600 16px var(--ds-font-ui);
  color: var(--ds-text);
  gap: 8px;
}
.mgmt-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 40px;
  padding: 4px 4px 4px 12px;
  border-bottom: 1px solid var(--ds-border);
}
.mgmt-row:last-child { border-bottom: none; }
.mgmt-row-name { flex: 1; min-width: 0; font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); }
/* Icon-only buttons in a dialog or management card: 32px square. (Other dialog buttons are the
   default 32px .btn-* size.) */
.modal .ds-icon-only:is(.btn-primary, .btn-secondary, .btn-danger),
.mgmt-card .ds-icon-only:is(.btn-primary, .btn-secondary, .btn-danger) {
  width: 32px;
  padding: 0;
}
.confirm-box {
  width: 100%;
  color: var(--ds-text);
  overflow: hidden;
  font-family: var(--ds-font-ui);
  max-width: 400px;
  border: none;
  border-radius: var(--ds-radius-overlay);
  background: var(--ds-surface-overlay);
  box-shadow: var(--ds-shadow-overlay);
  animation: ds-fade var(--ds-duration-fast) var(--ds-ease-out);
}
.confirm-overlay {
  position: fixed;
  inset: 0;
  z-index: 100001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: color-mix(in srgb, var(--ds-ink) 50%, transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  animation: ds-fade var(--ds-duration-fast) var(--ds-ease-out);
}
@keyframes confirmFade {from { opacity: 0; } to { opacity: 1; }}

/* ── styles/components/form-controls.css ── */
/* components/form-controls.css: Form rows, labels and help, toggle switch, toggle chips, swatches, password eye. */

.span2 { grid-column: span 2; }
.form-row { display: flex; flex-direction: column; gap: 6px; }
.form-row label { font-size: 10px; letter-spacing: 0.3px; color: var(--ds-brand); font-weight: 600; }
/* Moved from pages/it-access.css (they were never IT-only: every form row, dialog and settings
   card uses them). */
/* ── Form labels and help text: small sentence-case grey, help under the field ── */
.form-row label:not(.switch):not(:has(input)),
.modal-body label:not(.switch):not(:has(input)),
.mgmt-card label:not(.switch):not(:has(input)) {
  font: 600 12px/16px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ds-text-subtlest);
}
/* A label that wraps a checkbox reads as the option's text, not a field label. */
.form-row label:has(input):not(.switch) {
  font: 400 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ds-text);
}
.switch input { position: absolute; opacity: 0; }
@media (max-width: 900px) {
  .span2 { grid-column: span 1; }
}
/* ── Password show/hide (eye) toggle ─────────────────────────────────────────
.pw-field wraps a password <input> so the eye button sits inside its right
edge. Added app-wide (incl. login) by the enhanceInputs sweep in app.js. */
.pw-field { position: relative; display: block; }
.pw-field > input { padding-right: 42px; width: 100%; }
/* The eye stays a flat icon inside the field: components sit above base/, so the global
   button and field rules cannot fill it. */
.pw-eye {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  min-width: 0;
  padding: 0;
  margin: 0;
  background: none;
  border: none;
  box-shadow: none;
  border-radius: var(--ds-radius-control);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  color: var(--ds-text-subtlest);
  opacity: 0.6;
}
.pw-eye:hover { opacity: 1; }
.pw-eye:active { transform: translateY(-50%); }
.form-actions {
  display: flex;
  justify-content: flex-end;
  padding-top: 8px;
  border-top: none;
  gap: 8px;
}
.modal-body > .form-actions:last-child {
  position: sticky;
  bottom: -24px;
  z-index: 1;
  margin: 8px -24px -24px;
  padding: 16px 24px 24px;
  background: var(--ds-surface-overlay);
}
.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--ds-text);
}
.switch .switch-track {
  flex-shrink: 0;
  position: relative;
  border-radius: var(--ds-radius-round);
  transition: background 0.18s, border-color 0.18s;
  width: 40px;
  height: 20px;
  border: none;
  background: var(--ds-border-bold);
}
.switch .switch-thumb {
  position: absolute;
  border-radius: 50%;
  transition: background 0.18s;
  top: 4px;
  left: 4px;
  width: 12px;
  height: 12px;
  background: var(--ds-surface-raised);
  box-shadow: none;
}
.switch input:checked + .switch-track { border-color: var(--ds-brand); background: var(--ds-brand); }
.switch input:checked + .switch-track .switch-thumb {
  transform: translateX(20px);
  background: var(--ds-text-on-brand);
}
.switch input:focus-visible + .switch-track {
  box-shadow: 0 0 0 2px var(--ds-surface-overlay), 0 0 0 4px var(--ds-border-focused);
}
/* Toggle chips (org, department, workbook, account and role pickers in dialogs): button[data-active]
   with .ds-toggle-chip; the toggle functions only flip data-active. 32px, selected = the blue selected fill. */
.ds-toggle-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ds-radius-control);
  font: 500 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  border: 1px solid var(--ds-border);
  background: transparent;
  color: var(--ds-text);
  cursor: pointer;
}
.ds-toggle-chip:hover:not(:disabled) { background: var(--ds-surface-hovered); color: var(--ds-text); }
/* A chip that cannot be changed (a department rule's group on the user record): no pointer, subtlest text. */
.ds-toggle-chip:disabled { cursor: default; color: var(--ds-text-subtlest); }
.ds-toggle-chip[data-active="true"]:disabled { color: var(--ds-text-subtle); }
.ds-toggle-chip[data-active="true"],
.ds-toggle-chip[data-active="true"]:hover:not(:disabled) {
  background: var(--ds-surface-selected);
  border-color: transparent;
  color: var(--ds-link);
}
/* Compact chip (EBET roles): 28px, 13px. */
/* Permission matrix cell (editUser): None / Read / Write, 64px wide, 12px. */
.ds-perm-chip { justify-content: center; width: 64px; height: 28px; padding: 0; font-size: 12px; }
/* The note after a field label ("(optional)", the owner-only asterisk, a checkbox caption):
   12px regular, subtlest. */
.form-row label > .label-note {
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ds-text-subtlest);
}

/* ── styles/components/menu.css ── */
/* components/menu.css: Menus (.ds-menu) and row menus. */

/* ── Menus (.ds-menu): overlay surface, 36px rows, neutral hover, status icons carry colour ── */
.ds-menu-anchor { position: relative; display: inline-flex; }
/* The menu button of a page header (More ▾) is a subtle button: transparent until hovered, as
   Jira's Export ▾ / Tools ▾ (compare.html (a), M). Atlassian background-neutral-subtle, -hovered,
   -pressed (the pressed value equals background-neutral-hovered, our button-default-hovered). A menu
   among the selection bar's buttons (Inventory's Monitoring ▾) keeps their default button look. */
.ds-menu-anchor > .btn-secondary[data-page-menu]:not(.ds-selectionbar *) { background: transparent; }
.ds-menu-anchor > .btn-secondary[data-page-menu]:not(.ds-selectionbar *):hover:not(:disabled) { background: var(--ds-item-hovered); }
.ds-menu-anchor > .btn-secondary[data-page-menu][aria-expanded="true"] { background: var(--ds-button-default-hovered); }
.ds-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 1500;
  min-width: 240px;
  padding: 4px;
  background: var(--ds-surface-overlay);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
}
.ds-menu.hidden { display: none; }
.ds-menu-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  width: 100%;
  height: 36px;
  padding: 0 12px;
  border: none;
  border-radius: var(--ds-radius-control);
  background: none;
  box-shadow: none;
  color: var(--ds-text);
  font: 400 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.ds-menu-item:hover {
  background: var(--ds-item-hovered);
  outline: none;
}
.ds-menu-item[aria-checked="true"] {
  background: var(--ds-surface-selected);
  color: var(--ds-link);
}
.ds-menu-sep { height: 1px; margin: 4px 0; background: var(--ds-border); }
.ds-menu-chev { margin: 0 0 0 4px; color: var(--ds-text-subtle); }
.ds-menu-item:focus-visible { background: var(--ds-item-hovered); outline: none; outline-offset: -2px; }
.ds-menu-item--danger { color: var(--ds-tone-danger-text); }
.ds-menu-item--danger:hover, .ds-menu-item--danger:focus-visible { background: var(--ds-tone-danger-subtle); }
/* A checkable item (the Columns ▾ picker): the check shows only while it is on. */
.ds-menu-item[aria-checked="false"] .ds-icon { visibility: hidden; }

/* ── styles/components/toast.css ── */
/* components/toast.css: Toasts. */

.toast.toast-action { cursor: pointer; }
#toast-stack {
  position: fixed;
  z-index: 100000;
  display: flex;
  flex-direction: column;
  bottom: 24px;
  right: 24px;
  gap: 8px;
  width: 400px;
  max-width: calc(100vw - 32px);
}
.toast {
  display: flex;
  transition: opacity 0.2s;
  animation: ds-fade var(--ds-duration-fast) var(--ds-ease-out);
  align-items: flex-start;
  gap: 12px;
  padding: 14px 12px 14px 16px;
  background: var(--ds-surface-overlay);
  color: var(--ds-text);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  font: 400 14px/20px var(--ds-font-ui);
}
.toast.error {
  align-items: flex-start;
  gap: 12px;
  padding: 14px 12px 14px 16px;
  background: var(--ds-surface-overlay);
  color: var(--ds-text);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  font: 400 14px/20px var(--ds-font-ui);
}
.toast.info {
  align-items: flex-start;
  gap: 12px;
  padding: 14px 12px 14px 16px;
  background: var(--ds-surface-overlay);
  color: var(--ds-text);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  font: 400 14px/20px var(--ds-font-ui);
}
.toast.success {
  align-items: flex-start;
  gap: 12px;
  padding: 14px 12px 14px 16px;
  background: var(--ds-surface-overlay);
  color: var(--ds-text);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  font: 400 14px/20px var(--ds-font-ui);
}
.toast.warning {
  align-items: flex-start;
  gap: 12px;
  padding: 14px 12px 14px 16px;
  background: var(--ds-surface-overlay);
  color: var(--ds-text);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  font: 400 14px/20px var(--ds-font-ui);
}
.toast > span:nth-child(2) { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.toast .toast-ico {
  font-size: 14px;
  display: inline-grid;
  place-items: center;
  height: 20px;
  flex-shrink: 0;
}
.toast .toast-x {
  font-size: 13px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin: -2px 0 0 auto;
  padding: 0;
  border: none;
  background: none;
  border-radius: var(--ds-radius-control);
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.toast .toast-x:hover { background: var(--ds-item-hovered); color: var(--ds-text); }
.toast.toast-action:hover {
  align-items: flex-start;
  gap: 12px;
  padding: 14px 12px 14px 16px;
  color: var(--ds-text);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  font: 400 14px/20px var(--ds-font-ui);
  background: var(--ds-surface-hovered);
}

/* ── styles/components/feed.css ── */
/* components/feed.css: The Dashboard's activity rows and the Alerts page's Live pill. */
/* The dashboard's recent activity grows with the page (15 seeded, live ones on top, 20 at most). */
.activity-feed {
  display: flex;
  flex-direction: column;
  padding: 0;
  gap: 0;
}
.activity-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  font-size: 14px;
  border-bottom: 1px solid var(--ds-border);
}
.activity-item:last-child { border-bottom: none; }
.activity-msg { flex: 1; color: var(--ds-text); }
.activity-msg b { font-weight: 500; }
.activity-time {
  flex-shrink: 0;
  font-size: 12px;
  color: var(--ds-text-subtle);
  font-variant-numeric: tabular-nums;
}
.live-pill {
  display: flex;
  align-items: center;
  height: 20px;
  padding: 0 6px;
  gap: 6px;
  border: none;
  border-radius: var(--ds-radius-small);
  background: var(--ds-tone-success-subtle);
  color: var(--ds-tone-success-text);
  font: var(--ds-font-weight-bold) 11px/20px var(--ds-font-ui);
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.live-dot {
  border-radius: 50%;
  width: 6px;
  height: 6px;
  box-shadow: none;
  background: var(--ds-tone-success);
  animation: none;
}
@keyframes navFlash {0%, 100% { background: transparent; } 50% { background: color-mix(in srgb, var(--ds-tone-danger) 18%, transparent); }}

/* ── styles/components/message.css ── */
/* components/message.css: Banners, section messages, empty states. */

/* Section message (callout): flat subtle tone, icon, no border */
.ds-section-msg {
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  border-radius: var(--ds-radius-card);
  background: var(--ds-tone-info-subtle);
  color: var(--ds-text);
  font-size: 13px;
  line-height: 20px;
}
.ds-section-msg a { color: var(--ds-link); }
.ds-section-msg.warning { background: var(--ds-tone-warning-subtle); }
/* Quiet helpers */
.ds-muted { color: var(--ds-text-subtlest); }
.ds-empty { padding: 16px 0; font-size: 14px; color: var(--ds-text-subtle); }
/* Out to the cell's edges: the cell's 10px side padding (.data-table td), no further, or an empty
   table scrolls 2px sideways inside its box. */
.data-table td > .ds-empty-center { margin: 0 -10px; }

/* ── styles/components/user-menu.css ── */
/* components/user-menu.css: Account menu, opened from the top-bar avatar (#top-me). */

.user-popup.hidden { display: none; }
.user-popup-id { min-width: 0; }
.user-popup-item .upi-label { flex: 1; }
.user-popup-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  margin: 0 0 4px;
  border-bottom: 1px solid var(--ds-border);
}
.user-popup-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font: 600 14px/20px var(--ds-font-ui);
  color: var(--ds-text);
}
.user-popup-role {
  font: 400 12px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ds-text-subtle);
}
.user-popup-item {
  display: flex;
  align-items: center;
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.13s, color 0.13s;
  text-decoration: none;
  height: 36px;
  padding: 0 12px;
  gap: 10px;
  border-radius: var(--ds-radius-control);
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text);
}
.user-popup-item .upi-ico {
  font-size: 16px;
  flex-shrink: 0;
  display: inline-grid;
  place-items: center;
  color: var(--ds-text-subtle);
}
.user-popup-item:hover { background: var(--ds-item-hovered); color: var(--ds-text); }
.user-popup-item .theme-state { font: 400 12px var(--ds-font-ui); color: var(--ds-text-subtle); }
.user-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  line-height: 1;
}
.user-popup {
  position: fixed;
  top: 60px;
  right: 16px;
  z-index: 1500;
  width: 260px;
  background: var(--ds-surface-overlay);
  border: none;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-overlay);
  padding: 4px;
  animation: ds-fade var(--ds-duration-fast) var(--ds-ease-out);
}
.user-popup-item:focus-visible { outline-offset: -2px; }

/* ── styles/components/list-page.css ── */
/* components/list-page.css: the page-type components (docs/STRUCTURE.md).
   One page scroll; page header (title, count, More ▾, one primary button); view tabs with counts
   and the in-page tab strip (.ds-tabs); the one filter bar (.ds-filterbar); the bulk selection
   bar (.ds-selectionbar); the in-page left menu (.ds-sidemenu, Admin). A page uses these and
   never rebuilds them: scripts/web-check.ts G11 rejects page CSS that styles them. */

/* ── List page frame: the panel is the page and scrolls; nothing inside it scrolls on its own ── */
.panel.ds-page-list { gap: 16px; padding-top: 0; }
.ds-page-list .ds-page-head { padding-top: 24px; }
/* The table card grows with its rows (no inner scroll box); its column header scrolls away with
   the page, as on GitHub, Jira and Shopify (user decision 29/10/2026). Cells wrap first
   (fit-content); only a table that still cannot fit widens the card, and then the page scrolls
   sideways, never the card. */
.ds-page-list .table-wrap.ds-list-table {
  overflow: visible;
  contain: none;
  width: fit-content;
  /* The first column's text lines up with the page title (compare.html "line up the first column
     with the title", Jira): the box hangs out by its border + the cell's 10px padding each side. */
  min-width: calc(100% + 22px);
  margin-inline: -11px;
}
/* The header fill follows the box's rounded top corners (the box does not clip here). */
.ds-list-table .data-table th:first-child { border-top-left-radius: var(--ds-radius-card); }
.ds-list-table .data-table th:last-child { border-top-right-radius: var(--ds-radius-card); }
.ds-page-list .ds-list-pager:empty { display: none; }
.ds-page-list .ds-list-pager { padding-bottom: 8px; }

/* ── Page header: title + count left; More ▾ and the one primary button right ── */
.ds-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  min-width: 0;
}
.ds-page-title {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 12px;
  min-width: 0;
  margin: 0;
  /* Jira's page title, measured: 500 24px/30px (compare.html). */
  font: var(--ds-font-weight-medium) 24px/30px var(--ds-font-ui);
  letter-spacing: 0;
  color: var(--ds-text);
}
.ds-page-count { font: 400 14px/20px var(--ds-font-ui); letter-spacing: 0; color: var(--ds-text-subtle); }
.ds-page-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.ds-page-actions .ds-menu { min-width: 220px; }

/* ── Tabs: view tabs with counts (buttons, filter one list) and the in-page tab strip of an
   area's sub-pages (links; the router marks the current one aria-current="page") ── */
.ds-tabs {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--ds-border);
}
.ds-tab {
  display: inline-flex;
  align-items: center;
  flex: none;
  gap: 8px;
  height: 36px;
  margin-bottom: -1px;
  padding: 0 12px;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text-subtle);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.ds-tab:hover { color: var(--ds-text); }
/* Active tab 600 14px, inactive 400 14px subtle; count pill 600 12px/18px (GitHub box header,
   compare.html (a), M). */
.ds-tab:is([aria-selected="true"], [aria-current="page"]) {
  border-bottom-color: var(--ds-brand);
  font-weight: var(--ds-font-weight-semibold);
  color: var(--ds-text);
}
.ds-tab-count {
  min-width: 20px;
  padding: 0 6px;
  border-radius: var(--ds-radius-round);
  background: var(--ds-tone-neutral-subtle);
  font: var(--ds-font-weight-semibold) 12px/18px var(--ds-font-ui);
  text-align: center;
  color: var(--ds-text-subtle);
}
.ds-tab[aria-selected="true"] .ds-tab-count { background: var(--ds-surface-selected); color: var(--ds-link); }
/* The area tab strip (11-shell.js renders it from AREAS): first in each panel of a multi-page
   area, above the page header, so the area's pages read as one place.
   One offset on every page that shows one, list page or not, so the strip and the title stay
   put when moving between the tabs of an area (Inventory › Assets ⇄ Relationship map). */
.panel:has(> .ds-area-tabs:not([hidden])) { padding-top: 0; gap: 16px; }
.panel > .ds-area-tabs { margin-top: 12px; }
.panel > .ds-area-tabs:not([hidden]) + * { margin-top: 8px; }
.panel > .ds-area-tabs:not([hidden]) + .ds-page-head { padding-top: 0; }

/* ── Filter bar: search first, then filter dropdowns, then Clear; result count on the right.
   Every control is one height (32px) with 6px gaps (Jira's filter row, measured). ── */
.ds-filterbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}
.ds-filter-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 260px;
  min-width: 0;
  max-width: 480px;
}
.ds-filter-search .ds-icon {
  position: absolute;
  left: 10px;
  width: 16px;
  height: 16px;
  color: var(--ds-text-subtlest);
  pointer-events: none;
}
.ds-filter-search input { height: 32px; padding: 0 12px 0 34px; line-height: 30px; }
.ds-filterbar .cs .cs-btn { height: 32px; }
.ds-filter-clear {
  height: 32px;
  padding: 0 8px;
  border: none;
  border-radius: var(--ds-radius-control);
  background: none;
  font: 500 14px/20px var(--ds-font-ui);
  color: var(--ds-link);
  cursor: pointer;
}
.ds-filter-clear:hover { background: var(--ds-surface-hovered); }
.ds-filter-count { margin-left: auto; font: 400 12px var(--ds-font-ui); color: var(--ds-text-subtle); white-space: nowrap; }

/* ── Selection bar: takes the filter bar's place while rows are selected ── */
.ds-selectionbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 32px;
  padding: 0 4px 0 12px;
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface-selected);
}
.ds-selection-count { margin-right: 8px; font: 500 14px/20px var(--ds-font-ui); color: var(--ds-link); }
.ds-selectionbar .ds-selection-clear { margin-left: auto; }

/* ── In-page left menu (Admin): grouped links beside the page body; stacks on narrow screens ── */
.ds-sidemenu-layout { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 24px; align-items: start; }
/* Sticky from the panel's content edge (its 24px padding), so it lines up with the page title. */
.ds-sidemenu { position: sticky; top: 0; display: flex; flex-direction: column; gap: 12px; }
.ds-sidemenu-title {
  padding: 0 8px 4px;
  font: var(--ds-font-weight-bold) 11px var(--ds-font-ui);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ds-text-subtle);
}
.ds-sidemenu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 32px;
  padding: 0 8px;
  border-radius: var(--ds-radius-control);
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text-subtle);
  text-decoration: none;
}
.ds-sidemenu-item:hover { background: var(--ds-surface-hovered); color: var(--ds-text); }
/* Selected: colour only, no side bar and no bold (atlassian.design), as in the sidebar. */
.ds-sidemenu-item[aria-current="page"] { background: var(--ds-surface-selected); color: var(--ds-link); }
.ds-sidemenu-item .ds-icon { flex: none; width: 16px; height: 16px; }

/* ── Admin: every Admin page is the side menu (one slot, filled from AREAS) beside the page ── */
.panel.ds-admin-page { padding-top: 24px; }
.ds-admin-page .ds-page-head { padding-top: 0; }
.ds-sidemenu-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.ds-admin-body { display: flex; flex-direction: column; gap: 16px; }
/* The form card and the page description share one measure (.panel-desc, 860px). */
.ds-admin-body .mgmt-card { margin: 0; max-width: 860px; }

/* At 1200px and below (the sidebar's own narrow-window step; the desktop app's 960×600 minimum
   window included):
   - a list's column headers and cells may wrap, so a table fits the page and no page scrolls
     sideways; a word longer than its column (an address, a URL) breaks rather than widen the page;
   - the Admin menu folds into one button (the current page ▾), so it never stacks a tall block
     above the page in a short window or on a phone. Opened, it lists every page; choosing one
     closes it. */
.ds-sidemenu-toggle { display: none; }
@media (max-width: 1200px) {
  .ds-list-table .data-table th { white-space: normal; }
  .ds-list-table .data-table td { overflow-wrap: break-word; }
  .ds-sidemenu-layout { grid-template-columns: minmax(0, 1fr); gap: var(--ds-space-200); }
  .ds-sidemenu { position: static; }
  .ds-sidemenu-toggle { display: inline-flex; align-self: flex-start; }
  .ds-sidemenu:not([data-open]) > div { display: none; }
}
/* A list whose columns do not fit side by side drops secondary columns first, one at a time from
   the right, until it fits (TableFit in 02-data-kit.js marks each dropped column's cells
   .ds-col-off and the box data-condensed; Primer DataTable "Remove less important columns", Polaris
   IndexTable's condensed form). Row actions stay. Only a list whose rows open a record drops
   columns, so each hidden value stays on the record page. */
.ds-list-table .ds-col-off:not(.row-actions) { display: none; }
@media (max-width: 640px) {
  /* A secondary column (it is also a filter) drops on a phone, so the rest keep their width. */
  .ds-list-table .ds-col-secondary { display: none; }
  /* 16px gutters leave no room to hang the box out: it lines up with the page edge instead. */
  .ds-page-list .table-wrap.ds-list-table { min-width: 100%; margin-inline: 0; }
  /* A long unbroken word (an address, a quoted id) breaks anywhere rather than widen the page. */
  .ds-list-table .data-table td { overflow-wrap: anywhere; }
  .ds-page-title { font-size: 20px; }
  .ds-filter-search { flex-basis: 100%; max-width: none; }
  .ds-filter-count { margin-left: 0; }
}

/* ── Pager: one row at the end of the list ── */
.ds-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin-top: 4px;
}
.ds-pager-nav { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.ds-pager-size { display: inline-flex; align-items: center; gap: 8px; }
.pager .btn-secondary { height: 32px; font: 500 14px/20px var(--ds-font-ui); }
.pager .btn-secondary .ds-icon { margin: 0; }
.pager-page { padding: 0 8px; font: 500 14px/20px var(--ds-font-ui); color: var(--ds-text); white-space: nowrap; }
.pager-meta { font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); white-space: nowrap; }
.pager-meta strong { font-weight: 500; color: var(--ds-text); }

/* ── styles/components/record-page.css ── */
/* components/record-page.css: the record page (docs/STRUCTURE.md "Record page anatomy"), built by
   PageKit.record() in public/js/app/01-ui-kit.js. One thing at its own address: a Back link, the
   title with its status under it, a main column of labelled fields beside a right-hand column, and
   a Cancel · Save bar that appears only after something has changed.
   Every value is cited: (M) measured in Infra Redesign/compare.html (Jira for the fields, GitHub
   for the layout, Shopify for the save bar), or a design/tokens.ts token (Atlassian's space scale).
   A page file may not restyle these (they are shared): change them here. */

/* The record panel scrolls like every page; its own bottom padding moves inside the record so the
   sticky save bar reaches the bottom edge of the window instead of stopping 24px above it. */
.panel.ds-record-page { padding-bottom: 0; }
.ds-record { display: flex; flex-direction: column; gap: var(--ds-space-200); min-width: 0; padding-bottom: var(--ds-space-300); }

/* ‹ Back to the list: a plain link (Cmd-click opens a tab), above the title (structure.html wireframe). */
.ds-record-back {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: var(--ds-space-050);
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-link);
  text-decoration: none;
}
.ds-record-back:hover { text-decoration: underline; }
.ds-record-back .ds-icon { width: 16px; height: 16px; }

.ds-record-head { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: var(--ds-space-150); min-width: 0; }
.ds-record-head > div:first-child { min-width: 0; }
/* Record title: Jira 400 24px/30px (M); the status sits under it (structure.html). */
.ds-record-title { margin: 0; font: var(--ds-font-weight-regular) 24px/30px var(--ds-font-ui); color: var(--ds-text); overflow-wrap: anywhere; }
.ds-record-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-100); margin-top: var(--ds-space-050); font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtle); }
.ds-record-meta:empty { display: none; }

/* Main column + right-hand column: GitHub 296px with a 24px gap (M). */
.ds-record-cols { display: grid; grid-template-columns: minmax(0, 1fr) 296px; gap: var(--ds-space-300); align-items: start; }
.ds-record-cols.ds-record-single { grid-template-columns: minmax(0, 1fr); }
/* Sections: no cards, no lines; 15px apart (Jira, M). */
.ds-record-main { display: flex; flex-direction: column; gap: 15px; min-width: 0; }
.ds-record-section { min-width: 0; }
/* Section heading: Jira 500 16px/20px (M). */
.ds-record-section > h2 { margin: 0 0 var(--ds-space-100); font: var(--ds-font-weight-medium) 16px/20px var(--ds-font-ui); color: var(--ds-text); }
.ds-record-desc { margin: 0 0 var(--ds-space-100); font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtle); }

/* A field: a 150px label column, 24px rows (2px padding + a 20px line), no line or box per row.
   Labels 400 14px/20px in the third grey (Jira, M). A row holding a 32px control grows with it. */
.ds-field { display: grid; grid-template-columns: 150px minmax(0, 1fr); align-items: center; min-height: 24px; padding: 2px 0; }
.ds-field-label { padding-right: var(--ds-space-100); font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtlest); overflow-wrap: anywhere; }
.ds-field-value { min-width: 0; font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); overflow-wrap: anywhere; }
/* A tall control (a text area, a chip group that wraps, a control with a hint under it): the label
   stays on the control's first line. */
.ds-field.ds-field-top { align-items: start; }
.ds-field.ds-field-top .ds-field-label { padding-top: 6px; }
/* A wide field (a template's steps): no label column, the control takes the section's width. */
.ds-field.ds-field-wide { grid-template-columns: minmax(0, 1fr); }
.ds-field-value > :is(input, select, textarea) { width: 100%; }
.ds-field-value textarea { resize: vertical; }
/* Help under a control: 12px/18px (Shopify, M). */
.ds-field-hint { margin-top: var(--ds-space-050); font: 400 12px/18px var(--ds-font-ui); color: var(--ds-text-subtle); }
.ds-chips { display: flex; flex-wrap: wrap; gap: var(--ds-space-100); }
/* A collapsed section (a user's Direct access, PageKit.record `collapsible`): the heading, its text
   and the Show button stay; the fields are hidden (still read by the record's values()). */
.ds-record-section[data-collapsed] > .ds-field { display: none; }
/* A heading inside a section (PageKit field type 'heading': a user's Direct access, grouped as a
   group's access is): the aside label's type (600 12px/18px subtle), a section's spacing above. */
.ds-field.ds-record-subhead { display: block; margin: var(--ds-space-200) 0 0; font: var(--ds-font-weight-semibold) 12px/18px var(--ds-font-ui); color: var(--ds-text-subtle); }
.ds-section-toggle { margin-bottom: var(--ds-space-100); }
/* The None/Read/Write matrix of a user's section permissions: one field row per section. */
.ds-perm-row .ds-chips { gap: var(--ds-space-050); }

/* Right-hand column: sections split by 1px dividers; labels 600 12px/18px muted (GitHub, M). */
.ds-record-aside { display: flex; flex-direction: column; min-width: 0; }
.ds-aside-section { padding: var(--ds-space-200) 0; border-top: 1px solid var(--ds-border); }
.ds-aside-section:first-child { padding-top: 0; border-top: none; }
.ds-aside-label { margin: 0 0 var(--ds-space-050); font: var(--ds-font-weight-semibold) 12px/18px var(--ds-font-ui); color: var(--ds-text-subtle); }
.ds-aside-value { font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); overflow-wrap: anywhere; }
/* A link in the side column (a workbook's site, an employee) wraps like the rest of the value: the
   record is where a value shows in full, and a one-line link wider than the column scrolled the page
   sideways (a long money-site URL by 206px at every window width). */
.ds-aside-value .ds-row-link { white-space: normal; }

/* Cancel · Save: shown only after a change (Shopify's save bar, M), stuck to the bottom of the
   window while the record scrolls. */
.ds-savebar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ds-space-100);
  padding: var(--ds-space-150) 0;
  border-top: 1px solid var(--ds-border);
  background: var(--ds-surface);
}
.ds-savebar-note { margin-right: auto; font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtle); }

/* A list inside a record (sessions, recent events): the list box, without the hang-out of a page list. */
.ds-record .table-wrap.ds-list-table { overflow: visible; }

/* The import page (PageKit.importPage): Upload → Preview → Result in the record frame. The steps
   sit under the title like a record's meta line (14px/20px); the current one is colour only, the
   selected-item rule of structure.html "Precedence rule" (no bar, no bold). */
.ds-steps { display: flex; flex-wrap: wrap; gap: var(--ds-space-200); margin: var(--ds-space-050) 0 0; padding: 0; list-style: none; font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtlest); }
.ds-steps [aria-current="step"] { color: var(--ds-text); }
.ds-import-status { margin-top: var(--ds-space-100); font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text-subtle); }
.ds-import-status:empty { display: none; }
.ds-import-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-100); margin-top: var(--ds-space-200); }
.ds-import-choice { display: flex; margin-top: var(--ds-space-150); }
.ds-record-desc pre { margin: var(--ds-space-050) 0 var(--ds-space-100); padding: var(--ds-space-100); overflow-x: auto; font: 400 12px/18px var(--ds-font-ui); background: var(--ds-surface-sunken); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-control); color: var(--ds-text); }
/* A list inside a record section (an email group's members): the list box, without the hang-out. */
.ds-record-section .table-wrap.ds-list-table { margin-top: var(--ds-space-100); }
/* An inline add row under such a list: the one control height, 6px apart (list-page filter bar rule). */
.ds-inline-add { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: var(--ds-space-100); }
/* The text box takes the free width; at its own (browser) width it wraps under the others. */
.ds-inline-add > input { flex: 1 1 auto; width: auto; min-width: 0; }
.ds-inline-add > select { flex: 0 0 auto; width: auto; }
/* A picture in a record's right-hand column (an equipment item): no taller than the column is
   wide (296px, GitHub M), so a portrait photo does not push the rest of the column down. */
.ds-aside-img { display: block; max-width: 100%; max-height: 296px; object-fit: contain; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-card); background: var(--ds-surface-raised); }
.ds-aside-actions { display: flex; flex-wrap: wrap; gap: var(--ds-space-100); margin-top: var(--ds-space-100); }
.ds-aside-thumbs { display: flex; flex-wrap: wrap; gap: var(--ds-space-100); margin-top: var(--ds-space-100); }
/* Thumbnails: Shopify's 40px list thumbnail (compare.html, M). */
.ds-aside-thumbs img { width: 40px; height: 40px; object-fit: contain; cursor: pointer; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-control); background: var(--ds-surface-raised); }

@media (max-width: 640px) {
  .ds-record-cols { grid-template-columns: minmax(0, 1fr); }
  /* Label over its control, a 4px step apart, and a 4px step between rows. */
  .ds-field { grid-template-columns: minmax(0, 1fr); row-gap: var(--ds-space-050); padding: var(--ds-space-050) 0; }
  .ds-field-label { padding-right: 0; }
  .ds-field.ds-field-top .ds-field-label { padding-top: 0; }
}

/* A one-time secret shown for copying (2FA key, backup codes): code font on the sunken surface. */
.ds-code-note { margin: var(--ds-space-100) 0 var(--ds-space-050); font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); }
.ds-code-box {
  padding: var(--ds-space-100);
  font: 400 14px/20px var(--ds-font-code);
  word-break: break-all;
  color: var(--ds-text);
  background: var(--ds-surface-sunken);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
}
.ds-code-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ds-space-100); }

/* ── styles/components/meter.css ── */
/* components/meter.css: the usage meter shared by Cloudflare › Usage and the Dashboard's "Closest to
   a limit" card (docs/DESIGN-SYSTEM.md: CSS used on 2+ panels is a component). Moved unchanged from
   pages/cfanalytics.css, whose header gives the sources: right-aligned tabular numbers (Primer
   DataTable, Polaris Table), the meter's tones (Polaris Progress: neutral, then warning, then
   critical); every length a space token (Infra decision, no published size). */

/* Numbers right-aligned, digits the same width. */
.cfa-num { text-align: right; font-variant-numeric: tabular-nums; }
/* A numeric column's header lines up with its numbers (Primer DataTable: the header follows the
   column's align 'end'; Polaris Table: numeric is right-aligned), as .row-actions does in table.css:
   .data-table th sets every header left-aligned. */
.data-table th.cfa-num { text-align: right; }

/* Closest to a limit: one item per metric, its name, used / included and %, then the bar. */
.cfa-limits { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ds-space-150); }
.cfa-limit { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--ds-space-100); }
.cfa-limit > :first-child { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.cfa-limit-pct { min-width: var(--ds-space-400); }

/* A metric's meter across the card, and the meter's track and tones (the table meter uses them too). */
.cfa-bar { display: block; width: 100%; height: var(--ds-space-050); margin-top: var(--ds-space-050); }
.cfa-meter-track { fill: var(--ds-tone-neutral-subtle); }
.cfa-meter-neutral { fill: var(--ds-border-bold); }
.cfa-meter-warning { fill: var(--ds-tone-warning); }
.cfa-meter-danger { fill: var(--ds-tone-danger); }

} /* @layer components */

@layer pages {

/* ── styles/pages/login.css ── */
/* pages/login.css: The sign-in screens: sign-in, 2FA set-up (QR, code, backup codes) and the forced
   new password. One split layout (Infra Redesign/brand/signin-v2/panel-h-final): the brand panel is
   ALWAYS dark (.ds-theme-dark), the form side ALWAYS light (.ds-theme-light), whatever the app theme;
   there is no theme toggle here. Under 900px the dark band sits on top of the form.
   Motion: slow, stops with prefers-reduced-motion, paused while the tab is hidden (.si-paused).
   scope: #force-pw-screen, #enrol-screen, #login-, .si- */

/* ── The screen: fixed over the app, scrolls when the window is shorter than the form ── */
.si-screen {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: flex-start;
  overflow: auto;
  background: var(--ds-surface);
}
.si-shell {
  display: grid;
  grid-template-columns: 55fr 45fr;
  width: 100%;
  min-height: 100%;
  font: 400 14px/20px var(--ds-font-ui);
  -webkit-font-smoothing: antialiased;
}

/* ── Brand panel: the hero mark and its constellation (no text) ── */
.si-brand {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(70% 60% at 50% 48%, var(--ds-surface-selected) 0%, transparent 70%),
    linear-gradient(165deg, var(--ds-surface) 0%, var(--ds-surface-sunken) 100%);
}
.si-brand::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(130% 100% at 50% 50%, transparent 55%, var(--ds-surface-sunken) 130%);
}
.si-hero { position: relative; z-index: 1; display: block; width: min(88%, 82vh, 760px); height: auto; overflow: visible; }
.si-nl { fill: none; stroke: var(--ds-brand-hovered); stroke-opacity: .13; stroke-width: 1; vector-effect: non-scaling-stroke; }
.si-feed { fill: none; stroke: var(--ds-brand-hovered); stroke-opacity: .2; stroke-width: 1; vector-effect: non-scaling-stroke; }
.si-nd { fill: var(--ds-brand-hovered); fill-opacity: .35; }
.si-np { fill: none; stroke: var(--ds-tone-teal); stroke-width: 1.6; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.si-np.si-blue { stroke: var(--ds-chart-1); }
/* Gradient stops and fills, from the tokens of the theme the element sits in. */
.si-st-teal { stop-color: var(--ds-tone-teal); }
.si-st-blue { stop-color: var(--ds-brand); }
.si-st-chart { stop-color: var(--ds-chart-1); }
.si-st-hi { stop-color: var(--ds-print-paper); }
.si-hi-fill { fill: var(--ds-print-paper); }
.si-hi-stroke { stroke: var(--ds-print-paper); }
.si-rings { stroke: var(--ds-brand-hovered); }
.si-ring-teal { stroke: var(--ds-tone-teal); }
.si-ring-chart { stroke: var(--ds-chart-1); }
.si-floor { fill: var(--ds-surface-sunken); fill-opacity: .9; }
.si-pl1 { fill: var(--ds-surface-sunken); fill-opacity: .6; stroke: var(--ds-brand-hovered); }
.si-pl2 { fill: var(--ds-surface-raised); fill-opacity: .75; stroke: var(--ds-brand-hovered); }
.si-pl3 { fill: var(--ds-surface-selected); fill-opacity: .85; stroke: var(--ds-brand-hovered); }
.si-core-edge { stroke: var(--ds-tone-teal-text); }
.si-ink { fill: var(--ds-text); }

/* Motion: the same timings as the design. Each feeder pulse lights its logo node on arrival
   (.si-arrive shares the pulse's duration and delay). */
.si-halo { transform-box: fill-box; transform-origin: center; animation: si-halo 12s ease-in-out infinite; }
.si-halo.si-h2 { animation-delay: -4s; }
.si-halo.si-h3 { animation-delay: -8s; }
@keyframes si-halo { 0%, 100% { opacity: .35; transform: scale(.9); } 50% { opacity: .85; transform: scale(1.15); } }
.si-core-glow { animation: si-core 10s ease-in-out infinite; }
@keyframes si-core { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
.si-aura { transform-box: fill-box; transform-origin: center; animation: si-aura 16s ease-in-out infinite; }
@keyframes si-aura { 0%, 100% { opacity: .7; transform: scale(.97); } 50% { opacity: 1; transform: scale(1.03); } }
.si-sweep { stroke-dasharray: 6 94; animation: si-sweep 20s linear infinite; }
.si-sweep.si-s2 { animation-duration: 18s; animation-direction: reverse; animation-delay: -6s; }
@keyframes si-sweep { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
.si-pulse { stroke-dasharray: 5 95; stroke-dashoffset: 100; animation: si-travel var(--si-d, 11s) linear infinite; animation-delay: var(--si-dl, 0s); }
@keyframes si-travel { to { stroke-dashoffset: 0; } }
.si-node-halo { transform-box: fill-box; transform-origin: center; animation: si-breathe 9s ease-in-out infinite; }
.si-node-halo.si-b2 { animation-delay: -3s; }
.si-node-halo.si-b3 { animation-delay: -6s; }
@keyframes si-breathe { 0%, 100% { opacity: .15; transform: scale(1); } 50% { opacity: .4; transform: scale(1.35); } }
.si-arrive { opacity: 0; animation: si-arrive var(--si-d, 11s) linear infinite; animation-delay: var(--si-dl, 0s); }
@keyframes si-arrive { 0% { opacity: .7; } 12% { opacity: 0; } 91% { opacity: 0; } 100% { opacity: .7; } }
.si-t1 { --si-d: 13s; --si-dl: -5s; }
.si-t2 { --si-d: 14s; --si-dl: -9s; }
.si-t3 { --si-d: 12s; --si-dl: -2s; }
.si-t4 { --si-d: 16s; --si-dl: -11s; }
.si-t5 { --si-d: 11s; --si-dl: -1s; }
.si-t6 { --si-d: 13s; --si-dl: -6s; }
.si-t7 { --si-d: 12s; --si-dl: -9.5s; }
.si-paused .si-brand * { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .si-halo, .si-core-glow, .si-aura, .si-step, .si-node-halo { animation: none; }
  .si-sweep, .si-pulse, .si-arrive { animation: none; opacity: 0; }
}

/* ── Form side ── */
.si-side {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 24px 32px;
  background: var(--ds-surface);
  color: var(--ds-text);
}
.si-center { flex: 1; display: flex; align-items: center; justify-content: center; padding: 32px 0; }
.si-wrap { width: 100%; max-width: 360px; }
.si-lockup { display: flex; justify-content: center; margin-bottom: 32px; }
.si-lockup svg { width: auto; height: 84px; }
.si-title {
  margin: 0 0 6px;
  font: 600 22px/28px var(--ds-font-ui);
  letter-spacing: -.01em;
  text-align: center;
  color: var(--ds-text);
}
.si-sub { margin: 0 0 28px; color: var(--ds-text-subtle); text-align: center; }
.si-field { margin-bottom: 16px; }
.si-label { display: block; margin-bottom: 6px; font: 600 13px/20px var(--ds-font-ui); color: var(--ds-text); }
.si-input-wrap { position: relative; }
.si-input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--ds-border-bold);
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface);
  color: var(--ds-text);
  font: 400 14px var(--ds-font-ui);
  transition: border-color .15s, box-shadow .15s;
}
.si-input:hover { border-color: var(--ds-text-subtle); }
.si-input:focus, .si-input:focus-visible { outline: none; border-color: var(--ds-brand); box-shadow: 0 0 0 1px var(--ds-brand); background: var(--ds-surface); }
.si-input-wrap.si-pw .si-input { padding-right: 64px; }
.si-show {
  position: absolute;
  top: 4px;
  right: 4px;
  height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ds-radius-small);
  background: transparent;
  color: var(--ds-brand);
  font: 600 13px var(--ds-font-ui);
  cursor: pointer;
}
.si-show:hover { background: var(--ds-surface-hovered); }
.si-err { display: none; margin-top: 6px; font-size: 13px; color: var(--ds-tone-danger); }
.si-field.si-invalid .si-input { border-color: var(--ds-tone-danger); }
.si-field.si-invalid .si-err { display: block; }
.si-btn {
  width: 100%;
  height: 40px;
  margin-top: 8px;
  border: 0;
  border-radius: var(--ds-radius-control);
  background: var(--ds-brand);
  color: var(--ds-text-on-brand);
  font: 600 14px var(--ds-font-ui);
  cursor: pointer;
  transition: background .15s;
}
.si-btn:hover { background: var(--ds-brand-hovered); }
.si-btn:disabled { opacity: .6; cursor: progress; }
/* A server answer (wrong password, too many attempts) and the session-replaced notice. */
#login-error, .si-msg { margin: 0 0 8px; font-size: 13px; line-height: 18px; color: var(--ds-tone-danger); }
#login-error:empty, .si-msg:empty { display: none; }
#login-error.info:not(:empty) {
  padding: 8px 12px;
  border-radius: var(--ds-radius-control);
  background: var(--ds-tone-info-subtle);
  color: var(--ds-tone-info-text);
}
.si-notes { display: grid; gap: 10px; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--ds-border); }
.si-note { display: grid; grid-template-columns: 16px 1fr; gap: 10px; font-size: 13px; line-height: 19px; color: var(--ds-text-subtle); }
.si-note svg { width: 16px; height: 16px; margin-top: 1.5px; color: var(--ds-text-subtlest); }
.si-foot { text-align: center; font-size: 12px; letter-spacing: .01em; color: var(--ds-text-subtlest); }
.si-step { animation: si-in .35s cubic-bezier(.2, .7, .2, 1); }
@keyframes si-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* Who is setting up (the code step's account chip). */
.si-who-row { display: flex; justify-content: center; }
.si-who {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 auto 24px;
  padding: 4px 10px 4px 4px;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-round);
  font-size: 13px;
  color: var(--ds-text-subtle);
}
.si-who b {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--ds-tone-teal-subtle);
  color: var(--ds-tone-teal-text);
  font-size: 11px;
  font-weight: 700;
}
/* The 6-digit code: one box a digit, a gap after the third. */
.si-code { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 8px; }
.si-code input {
  width: 100%;
  min-width: 0;
  height: 48px;
  padding: 0;
  border: 1px solid var(--ds-border-bold);
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface);
  color: var(--ds-text);
  font: 600 20px var(--ds-font-ui);
  text-align: center;
}
.si-code input:focus, .si-code input:focus-visible { outline: none; border-color: var(--ds-brand); box-shadow: 0 0 0 1px var(--ds-brand); background: var(--ds-surface); }
.si-code input:nth-child(3) { margin-right: 6px; }
.si-code.si-invalid input { border-color: var(--ds-tone-danger); }
.si-code-err { margin-bottom: 8px; font-size: 13px; text-align: center; color: var(--ds-tone-danger); }
.si-code-err:empty { display: none; }
.si-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ds-brand);
  font: 600 13px var(--ds-font-ui);
  cursor: pointer;
}
.si-link:hover { text-decoration: underline; }
.si-row-c { display: flex; justify-content: center; margin-top: 16px; }
.si-done { text-align: center; }
.si-tick {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--ds-tone-teal-subtle);
  color: var(--ds-tone-teal-text);
}
/* 2FA set-up: the QR is black on white in both themes (a scanning need), the key under it. */
.si-qr { display: flex; justify-content: center; margin-bottom: 16px; }
.si-qr-box { padding: 8px; line-height: 0; background: var(--ds-print-paper); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-control); }
.si-qr-none { display: grid; place-items: center; width: 180px; height: 180px; font: 400 12px/16px var(--ds-font-ui); color: var(--ds-print-ink); }
.si-key { margin-bottom: 20px; text-align: center; }
.si-key-label { margin-bottom: 6px; font: 600 13px/20px var(--ds-font-ui); color: var(--ds-text-subtle); }
.si-key .ds-code-box { letter-spacing: .04em; }
.si-codes { margin-bottom: 8px; text-align: left; }

@media (max-width: 900px) {
  .si-shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .si-brand { height: 180px; min-height: 0; }
  .si-hero { width: auto; height: 168px; }
  .si-n-outer { display: none; }
  .si-side { padding: 16px; }
}
@media (max-width: 480px) {
  .si-brand { height: 150px; }
  .si-hero { height: 140px; }
}

/* ── styles/pages/graph.css ── */
/* pages/graph.css: Relationship map (#panel-graph) and the email-group diagram (#panel-emailgroups).
   scope: #graph-, .eg-, .graph-, .legend, .legend-, .nd-, .node-detail */

/* ── Graph ───────────────────────────────────────────────────────────────── */
/* The page scrolls (docs/STRUCTURE.md "One page scroll"): the map and its side column take their
   own height; nothing is clipped inside a box. */
.graph-layout {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
.graph-sidebar {
  width: 240px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.legend {
  background: var(--ds-surface-overlay);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
  padding: 14px;
}
#graph-container {
  flex: 1;
  min-width: 0;
  align-self: stretch;
  min-height: 500px;
  background: var(--ds-surface-sunken);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
}
.graph-sidebar .legend {
  background: var(--ds-surface-raised);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
  box-shadow: none;
}
.node-detail {
  padding: 16px;
  background: var(--ds-surface-raised);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
  box-shadow: none;
}
.legend-title {
  font: 600 12px var(--ds-font-ui);
  color: var(--ds-text-subtle);
  letter-spacing: 0;
  text-transform: none;
  margin-bottom: 8px;
}
.legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--ds-text);
  padding: 3px 0;
}
.legend-swatch {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  background: none;
  color: var(--tone);
}
.legend-swatch .ds-icon { width: 16px; height: 16px; margin: 0; }
/* Relationship map: the explanatory line under the legend is text, not a legend row. */
.legend-hint { margin: 10px 0 0; font-size: 12px; line-height: 1.45; color: var(--ds-text-subtle); }
.nd-title {
  margin-bottom: 12px;
  font: 600 16px var(--ds-font-ui);
  color: var(--ds-text);
  word-break: normal;
  overflow-wrap: anywhere;
}
.nd-row {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 12px;
  align-items: center;
  padding: 6px 0;
  font-size: 14px;
  border-bottom: 1px solid var(--ds-border);
}
.nd-key { flex-shrink: 0; min-width: 0; color: var(--ds-text-subtle); }
.nd-val { flex: 1; color: var(--ds-text); word-break: normal; overflow-wrap: anywhere; }
.nd-empty { text-align: center; padding: 24px 0; font-size: 14px; color: var(--ds-text-subtle); }
.nd-link {
  gap: 4px;
  transition: all 0.2s;
  display: inline-flex;
  align-items: center;
  height: 32px;
  margin: 12px 8px 0 0;
  padding: 0 12px;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  background: transparent;
  color: var(--ds-link);
  font: 500 14px/20px var(--ds-font-ui);
  text-decoration: none;
}
.nd-link:hover { background: var(--ds-surface-hovered); }
/* Below 900px (the breakpoint the cards and forms use) the side column goes under the map. */
@media (max-width: 900px) {
  .graph-layout { flex-direction: column; align-items: stretch; }
  .graph-sidebar { width: auto; }
}
/* Email group diagram: the same sunken canvas as the Relationship Map, filling the window below
   the page header and filter bar (a canvas, not a scroll box). */
.eg-graph {
  height: calc(100vh - 300px);
  min-height: 420px;
  background: var(--ds-surface-sunken);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
}

/* ── styles/pages/inventory.css ── */
/* pages/inventory.css: Asset inventory: bulk selection (also the Domains and Recycle bin tick columns),
   owner-only columns.
   scope: #inv-, #inventory-, .bulk-, .inventory-table, .is-owner, .owner-only-col */

/* ─── Bulk select & action bar (Asset Inventory) ────────────────────── */
/* The tick column of a list with bulk selection (Inventory, Domains, Recycle bin). */
.bulk-col { width: 28px; text-align: center; }
.bulk-col input[type="checkbox"] { width: 14px; height: 14px; cursor: pointer; accent-color: var(--ds-brand); }
.owner-only-col { display: none; }
body.is-owner .owner-only-col { display: table-cell; }
tr.bulk-selected { background: color-mix(in srgb, var(--ds-brand) 6%, transparent); }
/* A neutral lozenge (a person's group on the Users list) on a selected row: the raised surface behind
   it, so it keeps its shape on the selected fill (light mode). */
tr.bulk-selected .ds-lozenge.ds-tone-neutral { background: var(--ds-surface-raised); }
/* The Assets table sizes its columns to their content. */
.inventory-table { table-layout: auto; }

/* ── styles/pages/alerts.css ── */
/* pages/alerts.css: Alerts (a list page, the shared list components) and an alert's record page.
   scope: #alert-, #alerts-, #panel-alerts */

/* The record's Details: the text as it was sent, its line breaks kept (a New Relic failure log runs
   to several lines). Body text of the record page: 400 14/20 (docs/STRUCTURE.md, Jira's fields). */
#alert-record .alert-record-detail {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text);
}

/* The Alert column gives way in a narrow window, so the dates keep one line (ds-nowrap) in a 960
   window: an alert's title (a New Relic condition can be a sentence) wraps, and its second line (the
   detail as it was sent, often one long JSON token) may break anywhere. */
#alerts-body .ds-cell-main { white-space: normal; -webkit-line-clamp: none; }
#alerts-body .ds-cell-sub { overflow-wrap: anywhere; -webkit-line-clamp: none; }

/* In the icon-rail window (1024px and below, the desktop app's 960×600) Count and Last seen give
   their room to the Alert column; both stay on the record. */
@media (max-width: 1024px) {
  #panel-alerts .alerts-col-wide { display: none; }
}

/* ── styles/pages/integrations.css ── */
/* pages/integrations.css: Cloudflare › Domains, Workers & Pages and DNS records (one list page) and
   the zone, Worker and Pages record pages (#panel-it-record).
   scope: #panel-integrations, .cf- */

/* The Cloudflare panel's tables aren't in a contained scroll wrapper, so deferred
row layout mis-positioned the cards after them (Sync History only appeared after
a reflow). These tables are small (paginated), so opt them out. */
#panel-integrations .data-table tbody tr { content-visibility: visible; contain-intrinsic-size: auto; }
/* A zone, worker or record name and its target can be one long unbroken string. */
.cf-name { color: var(--ds-text); word-break: break-all; }
.cf-target { word-break: break-all; }
/* The record a DNS search opened, in its zone's record: the selected-row ground (Atlassian
   background.selected, the Admin menu's current item). */
.cf-dns-hit td { background: var(--ds-surface-selected); }
/* A link in the Cloudflare pages and records (a zone, a Worker, Plan & limits): the link colour,
   underlined on hover, as the list's row links (.ds-row-link) and the record's ‹ Back. */
.cf-link { color: var(--ds-link); text-decoration: none; }
.cf-link:hover { text-decoration: underline; }

/* ── styles/pages/cfanalytics.css ── */
/* pages/cfanalytics.css: Cloudflare › Usage, the usage and cost meter (design-research.html A), in the
   order of Cloudflare's Billable Usage page: the context in the header (Account ▾, Period ▾), four
   figures, the daily chart of usage charges, then the list. Right-aligned tabular numbers (Primer
   DataTable, Polaris Table; components/meter.css). Colours: Atlassian's chart tokens (--ds-chart-*,
   categorical only: no status colour in the chart) and the tone tokens for the meter's state (Polaris
   Progress: neutral, then warning, then critical). No size here is published by GitHub, Atlassian or
   Shopify for these pages (design-research.html "Could not verify"), so every length is a space token
   or a multiple of one (Infra decision). Used on the list page and on its record pages (#panel-it-record).
   scope: #cfanalytics-, .cfa- */

/* The context controls in the header (Account ▾, Period ▾), before More ▾. */
.cfa-scope { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-100); min-width: 0; }

/* A record section holding the figures and their warning, spaced as the list page's sections. */
.cfa-stack { display: flex; flex-direction: column; gap: var(--ds-space-200); min-width: 0; }
/* The warning message: every line on a wide window; from 1200px down, its first line and Details. */
.cfa-msg-body { flex: 1 1 auto; min-width: 0; }
.cfa-msg-more { display: none; align-self: flex-start; padding: 0; border: 0; background: none; font: inherit; color: var(--ds-link); cursor: pointer; white-space: nowrap; }
.cfa-msg-more:hover { text-decoration: underline; }

/* The four figures: one row, a hint label over each number, no cards, no icons; two by two on a phone. */
.cfa-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ds-space-200) var(--ds-space-300); margin: 0; }
.cfa-strip dd { margin: 0; }
.cfa-fig { display: flex; flex-direction: column; gap: var(--ds-space-050); min-width: 0; }
/* The figure's number: the list page title's type (Jira, list-page.css, the page title: 500 24px/30px). */
.cfa-figure { font: var(--ds-font-weight-medium) 24px/30px var(--ds-font-ui); color: var(--ds-text); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* Over included's count opens its view tab: the figure's own type, underlined on hover. */
.cfa-fig-link { padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; }
.cfa-fig-link:hover { text-decoration: underline; }
.cfa-danger { color: var(--ds-tone-danger-text); }

/* The daily chart: a heading and the period total, the plot (y-axis labels, SVG bars, x-axis labels), a legend. */
.cfa-chart { display: flex; flex-direction: column; gap: var(--ds-space-150); min-width: 0; }
.cfa-chart-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--ds-space-050) var(--ds-space-200); }
/* The record section heading's type (Jira, record-page.css: 500 16px/20px). */
.cfa-chart-title { margin: 0; font: var(--ds-font-weight-medium) 16px/20px var(--ds-font-ui); color: var(--ds-text); }
.cfa-plot { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--ds-space-100); }
/* Y labels (top, middle, 0) spread over the plot's height; the first and last are moved half a line so
   each sits centred on its graph line. */
.cfa-yaxis { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; height: calc(var(--ds-space-400) * 4); font-variant-numeric: tabular-nums; white-space: nowrap; }
.cfa-yaxis > :first-child { transform: translateY(-50%); }
.cfa-yaxis > :last-child { transform: translateY(50%); }
.cfa-plot-main { display: flex; flex-direction: column; gap: var(--ds-space-050); min-width: 0; }
.cfa-chart-svg { display: block; width: 100%; height: calc(var(--ds-space-400) * 4); overflow: visible; }
/* One cell per day under its bar; a label is centred on its day (the first and last keep to the edges). */
.cfa-xaxis { display: flex; min-width: 0; }
.cfa-xaxis > span { flex: 1 1 0; min-width: 0; display: flex; justify-content: center; white-space: nowrap; }
.cfa-xaxis > :first-child { justify-content: flex-start; }
.cfa-xaxis > :last-child { justify-content: flex-end; }
.cfa-xaxis-today { color: var(--ds-text); }
/* Graph lines: top and middle dashed (Primer "graph lines"), the baseline solid, Today a solid rule
   behind the bars (drawn before them, so it shows only above a short bar). */
.cfa-grid { stroke: var(--ds-border); stroke-width: 1; stroke-dasharray: var(--ds-space-050) var(--ds-space-050); }
.cfa-baseline { stroke: var(--ds-border-bold); stroke-width: 1; }
.cfa-today { stroke: var(--ds-text-subtle); stroke-width: 1; }
/* A day's hover target (its tooltip: the day's total and each product). */
.cfa-hit { fill: var(--ds-surface); fill-opacity: 0; }
.cfa-legend { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--ds-space-100) var(--ds-space-200); }
.cfa-legend li { display: inline-flex; align-items: center; gap: var(--ds-space-050); }
.cfa-swatch { width: var(--ds-space-150); height: var(--ds-space-150); flex-shrink: 0; }
.cfa-c1 { fill: var(--ds-chart-1); }
.cfa-c2 { fill: var(--ds-chart-2); }
.cfa-c3 { fill: var(--ds-chart-3); }
.cfa-c4 { fill: var(--ds-chart-4); }
.cfa-c5 { fill: var(--ds-chart-5); }
.cfa-c0 { fill: var(--ds-chart-other); }

/* The meter in a table row: max = the included amount, then its number, right-aligned in a fixed width
   so every row's percent ends on the same line (its track and tones: components/meter.css). */
.cfa-meter-cell { display: inline-flex; align-items: center; gap: var(--ds-space-100); }
.cfa-meter { width: calc(var(--ds-space-400) * 2); height: var(--ds-space-050); flex-shrink: 0; }
.cfa-pct { min-width: calc(var(--ds-space-400) + var(--ds-space-100)); text-align: right; font-variant-numeric: tabular-nums; }

/* The Account column's link: the cell's own muted text (as Workers & Pages' plain Account), underlined
   on hover (.ds-row-link); the product link is the row's one strong link. */
.ds-row-link.cfa-quiet-link { color: var(--ds-text-subtle); }

/* Narrow windows (the list page's own steps, components/list-page.css: 1200px, then 640px): the
   Forecast and Billable columns go first (they are on the metric record), then the meter's bar
   (its number stays) and, as a secondary column, Est. cost (the figures above have the cost), so
   the nine columns never scroll sideways at 960×600 or on a phone. The chart drops to three quarters of
   its height and the warning to its first line (Details shows the rest), so the first rows show at
   960×600. The figures go two by two. */
@media (max-width: 1200px) {
  .cfa-col-wide { display: none; }
  .cfa-chart-svg, .cfa-yaxis { height: calc(var(--ds-space-400) * 3); }
  .cfa-msg-body:not(.is-open) { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; }
  .cfa-msg-more { display: inline; }
}
@media (max-width: 640px) {
  .cfa-meter { display: none; }
  .cfa-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── styles/pages/github.css ── */
/* pages/github.css: GitHub › Repositories, Pull requests and Commits (one list page).
   scope: #github-, #panel-github, .gh- */

/* Repository name: the row's main line. */
.gh-repo { color: var(--ds-text); font-weight: 500; text-decoration: none; }
.gh-repo:hover { color: var(--ds-link); text-decoration: underline; }
/* A link to a repository or a Cloudflare project: the link colour, underlined on hover (.ds-row-link). */
.gh-link { color: var(--ds-link); text-decoration: none; }
.gh-link:hover { text-decoration: underline; }

/* ── styles/pages/docs.css ── */
/* pages/docs.css: Documentation and IT Knowledgebase: folder tree, reader, editor, article body, image controls.
   scope: #doc-, .cl-howto, .cl-howto-ed, .cl-howto-editor, .cl-howto-toggle, .doc-, .docs-, .rich- */

:root[data-theme="light"] .docs-tree-col, :root[data-theme="light"] .docs-pane {
  --kb-col: var(--ds-surface-overlay);
  --kb-pane: var(--ds-surface-raised);
  --kb-raised: var(--ds-surface-raised);
  --kb-raised-hover: var(--ds-surface-hovered);
  --kb-row-hover: var(--ds-surface-hovered);
  --kb-sel: var(--ds-surface-pressed);
  --kb-btn-hover: var(--ds-surface-hovered);
}
.docs-tree-col {
  --kb-col: var(--ds-surface);
  --kb-pane: var(--ds-surface);
  --kb-raised: var(--ds-surface-raised);
  --kb-raised-hover: var(--ds-surface-overlay);
  --kb-row-hover: var(--ds-surface-hovered);
  --kb-sel: var(--ds-surface-hovered);
  --kb-btn-hover: var(--ds-surface-pressed);
  width: var(--docs-tree-w, 300px);
  flex-shrink: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--kb-col);
  border-right: 1px solid var(--ds-border);
  overflow: hidden;
  /* One page scroll (docs/STRUCTURE.md): the column stays in view while the article scrolls, and
     is never taller than the window under the top bar (56px, layout/topbar.css) less the panel's
     24px padding above and below it (layout/shell.css). */
  position: sticky;
  top: 0;
  max-height: calc(100vh - 56px - 48px);
}
.doc-tree-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 6px 8px; }
/* The space row: 44px, its own ground, and the home for the tree's controls. */
.doc-tree-root {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  flex: 0 0 44px;
  padding: 0 8px 0 12px;
  background: var(--kb-raised);
  border-bottom: 1px solid var(--ds-border);
  cursor: pointer;
}
.doc-tree-root-icon {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  border-radius: var(--ds-radius-small);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}
.doc-tree-root-name {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ds-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-tree-root-count {
  font-size: 11px;
  font-weight: 500;
  color: var(--ds-text-subtlest);
  background: var(--kb-row-hover);
  border-radius: var(--ds-radius-small);
  padding: 3px 6px;
  font-variant-numeric: tabular-nums;
}
/* Folder rows. Indent is padding, not margin, so the whole row stays a hit
target and the hover ground runs the full width of the column. */
.doc-tree-node { min-width: 0; }
.doc-tree-folder {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 30px;
  padding: 0 8px 0 6px;
  border-radius: var(--ds-radius-control);
  background: transparent;
  border: 1px solid transparent;
  transition: background .12s;
  cursor: pointer;
}
.doc-tree-folder:hover { background: var(--kb-row-hover); }
.doc-tree-pip { width: 3px; height: 16px; flex: 0 0 3px; border-radius: var(--ds-radius-xsmall); }
.doc-tree-name {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  line-height: 18px;
  font-weight: 500;
  color: var(--ds-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Depth is legible without a size change: a child folder is lighter. */
.doc-tree-folder[data-depth="1"] .doc-tree-name,
.doc-tree-folder[data-depth="2"] .doc-tree-name,
.doc-tree-folder[data-depth="3"] .doc-tree-name {
  font-weight: 400;
  color: var(--ds-text-subtle);
}
.doc-tree-count {
  font-size: 11px;
  line-height: 1;
  font-weight: 400;
  color: var(--ds-text-subtlest);
  font-variant-numeric: tabular-nums;
}
/* Selected — ground, not outline. */
.doc-tree-folder.selected { background: var(--ds-surface-selected); box-shadow: inset 2px 0 0 var(--ds-brand); }
.doc-tree-folder.selected .doc-tree-name { font-weight: 600; color: var(--ds-link); }
.doc-tree-folder.selected .doc-tree-count { font-weight: 500; color: var(--ds-text-subtle); }
.doc-tree-folder.selected .doc-tree-chev { color: var(--ds-text-subtle); }
.doc-tree-root.selected { box-shadow: inset 2px 0 0 var(--ds-brand); }
.doc-tree-btn:hover { background: var(--kb-btn-hover); color: var(--ds-text); }
.doc-tree-btn.del { color: var(--ds-text-subtlest); font-size: 12px; }
.doc-tree-btn.del:hover { color: var(--ds-tone-danger); }
.doc-tree-btn.dot { font-size: 0; }
.doc-tree-btn.dot::before {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: currentColor;
}
.doc-tree-acts { display: flex; gap: 2px; margin-right: -2px; }
.doc-tree-folder .doc-tree-acts { opacity: 0; transition: opacity .12s; }
.doc-tree-folder:hover .doc-tree-acts,
.doc-tree-folder:focus-within .doc-tree-acts,
.doc-tree-folder.selected .doc-tree-acts {
  opacity: 1;
}
/* Space-row buttons are always visible: they are the tree's own controls, not
a property of a row you have to find first. */
.doc-tree-root .doc-tree-btn { width: 24px; height: 24px; flex: 0 0 24px; font-size: 14px; }
.doc-tree-root .doc-tree-btn:hover { background: var(--kb-row-hover); }
/* Article cards, indented under their folder — never at the root. */
.doc-tree-kids { display: flex; flex-direction: column; gap: 4px; padding: 4px 0 6px 0; }
.doc-tree-item.active .doc-tree-title { font-weight: 600; }
.doc-tree-item.dragging { opacity: .4; }
.doc-tree-title {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--ds-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-tree-meta { font-size: 11px; line-height: 14px; color: var(--ds-text-subtlest); margin-top: 3px; }
.doc-tree-tags { margin-top: 5px; display: flex; flex-wrap: wrap; gap: 4px; }
.doc-tag {
  font-size: 10px;
  line-height: 12px;
  padding: 2px 5px;
  border-radius: var(--ds-radius-small);
  font-weight: 500;
  letter-spacing: .03em;
}
/* The search term, marked in the result it matched. */
.doc-hit {
  background: color-mix(in srgb, var(--ds-tone-warning) 22%, transparent);
  color: var(--ds-tone-warning);
  border-radius: var(--ds-radius-xsmall);
  padding: 0 2px;
}
/* Search results tighten the rows and drop ancestors to meta grey: they are
there for the path, they are not themselves results. */
.doc-tree-body.searching .doc-tree-folder { height: 26px; }
.doc-tree-body.searching .doc-tree-pip { height: 14px; }
.doc-tree-body.searching .doc-tree-name { font-size: 12px; line-height: 16px; color: var(--ds-text-subtlest); }
.doc-tree-body.searching .doc-tree-count { font-size: 10px; }
/* Empty states: one dashed block, one action, no illustration. */
.doc-tree-empty {
  margin: 2px 0 6px 0;
  padding: 10px;
  border: 1px dashed var(--ds-border);
  border-radius: var(--ds-radius-control);
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
  font-size: 12px;
  line-height: 16px;
  color: var(--ds-text-subtlest);
}
.doc-tree-empty.big { padding: 14px; gap: 8px; }
.doc-tree-empty-h { font-size: 13px; line-height: 18px; font-weight: 600; color: var(--ds-text); }
.doc-tree-empty-row { display: flex; gap: 6px; flex-wrap: wrap; }
.doc-mini-btn {
  height: 24px;
  padding: 0 9px;
  display: inline-flex;
  align-items: center;
  background: none;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  font-size: 11px;
  font-weight: 500;
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.doc-mini-btn:hover { background: var(--kb-row-hover); color: var(--ds-text); }
.doc-mini-btn.accent {
  background: var(--ds-brand);
  border-color: var(--ds-brand);
  color: var(--ds-text-on-brand);
  font-weight: 600;
}
.doc-mini-btn.accent:hover { box-shadow: inset 0 0 0 1px var(--ds-text); }
/* Inline rename: the label is swapped for an input, and the bar, chevron and
indent all stay put so the row does not jump. */
.doc-tree-rename {
  flex: 1;
  min-width: 0;
  height: 22px;
  padding: 0 6px;
  font-family: var(--ds-font-ui);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  color: var(--ds-text);
  background: var(--kb-col);
  border: 1px solid var(--ds-brand);
  border-radius: var(--ds-radius-small);
  outline: none;
}
.doc-tree-rename-hint { font-size: 10px; line-height: 1; color: var(--ds-text-subtlest); }
/* A folder being created: the same row, in the place the folder will occupy,
with the name typed where it will be read. Dashed, so it reads as not-yet-a-
folder — nothing has been written until Enter. */
.doc-tree-draft { border: 1px dashed var(--ds-tone-teal); background: var(--kb-row-hover); }
.doc-tree-draft:hover { background: var(--kb-row-hover); }
.doc-search input {
  flex: 1;
  min-width: 0;
  height: 100%;
  background: transparent;
  border: none;
  outline: none;
  padding: 0;
  font-family: var(--ds-font-ui);
  font-size: 12px;
  color: var(--ds-text);
}
.doc-search input::placeholder { color: var(--ds-text-subtlest); }
.doc-search-count {
  font-size: 10px;
  font-weight: 500;
  color: var(--ds-text-subtlest);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.doc-search-count.none { color: var(--ds-tone-danger); }
.doc-search-clear {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-size: 11px;
  font-weight: 500;
  color: var(--ds-text-subtlest);
  line-height: 1;
}
.doc-search-clear:hover { color: var(--ds-text); }
.doc-colour-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; }
.doc-colour-swatch { height: 30px; border: 1px solid var(--ds-border); border-radius: var(--ds-radius-control); cursor: pointer; }
/* Drag-over. Accent2 and dashed, never the green used for selection, so "where
this will land" can never be mistaken for "where I am". */
.doc-drop.drop-target {
  background: color-mix(in srgb, var(--ds-tone-teal) 10%, transparent);
  border: 1px dashed var(--ds-tone-teal);
  box-shadow: none;
}
.doc-drop.drop-target .doc-tree-count { display: none; }
.doc-drop.drop-target .doc-tree-acts { display: none; }
.doc-drop.drop-target::after {
  content: 'move here';
  font-size: 10px;
  line-height: 12px;
  font-weight: 500;
  letter-spacing: .03em;
  color: var(--ds-tone-teal);
  background: color-mix(in srgb, var(--ds-tone-teal) 16%, transparent);
  border-radius: var(--ds-radius-small);
  padding: 2px 5px;
  white-space: nowrap;
}
.docs-pane {
  --kb-col: var(--ds-surface);
  --kb-pane: var(--ds-surface);
  --kb-raised: var(--ds-surface-raised);
  --kb-raised-hover: var(--ds-surface-overlay);
  --kb-row-hover: var(--ds-surface-hovered);
  --kb-sel: var(--ds-surface-hovered);
  --kb-btn-hover: var(--ds-surface-pressed);
  flex: 1;
  min-width: 0;
  background: var(--kb-pane);
}
/* The breadcrumb: Space / Folder / Folder, above the title (GitHub Docs, Microsoft Learn). */
.doc-crumb {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  font-size: 12px;
  line-height: 18px;
  color: var(--ds-text-subtle);
}
.doc-crumb a { color: var(--ds-link); text-decoration: none; }
.doc-crumb a:hover { text-decoration: underline; }
/* Title left, Edit and More ▾ right; they wrap under the title in a narrow window. */
.doc-head { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
.doc-head .doc-title { flex: 1 1 240px; min-width: 0; margin: 0; overflow-wrap: anywhere; }
.doc-read-wrap { display: flex; align-items: flex-start; min-width: 0; }
.doc-read { flex: 1; min-width: 0; padding: 0 40px 40px 40px; }
.doc-measure { max-width: 640px; }
.doc-title {
  font-size: 24px;
  line-height: 30px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ds-text);
}
.doc-badges {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.doc-folder-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  line-height: 14px;
  font-weight: 500;
  color: var(--ds-text-subtle);
  background: var(--kb-raised-hover);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-small);
  padding: 3px 7px;
}
.doc-folder-dot { width: 3px; height: 10px; border-radius: var(--ds-radius-xsmall); flex: 0 0 3px; }
.doc-updated { font-size: 11px; line-height: 14px; color: var(--ds-text-subtlest); margin-left: 4px; }
.doc-rule { height: 1px; background: var(--ds-border); margin: 16px 0; }
/* The on-this-page rail. Its active marker is the article pane's one accent
surface, alongside Save. */
.doc-toc-rail {
  width: 200px;
  flex: 0 0 200px;
  border-left: 1px solid var(--ds-border);
  padding: 0 16px;
  /* Sticky beside the article, like the tree (same window height). */
  position: sticky;
  top: 0;
  max-height: calc(100vh - 56px - 48px);
  overflow-y: auto;
}
.doc-toc-eyebrow {
  font-size: 10px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ds-text-subtlest);
  margin-bottom: 10px;
}
.doc-toc-rail a {
  display: block;
  font-size: 12px;
  line-height: 16px;
  font-weight: 400;
  color: var(--ds-text-subtlest);
  padding: 5px 8px;
  border-radius: var(--ds-radius-control);
  text-decoration: none;
  margin-bottom: 2px;
}
.doc-toc-rail a.lvl3 { padding-left: 20px; }
.doc-toc-rail a:hover { color: var(--ds-text-subtle); background: var(--kb-raised); }
.doc-toc-rail a.here {
  color: var(--ds-text);
  font-weight: 500;
  background: var(--kb-raised-hover);
  box-shadow: inset 2px 0 0 var(--ds-brand);
}
@media (max-width: 1360px) {
  .doc-toc-rail { display: none; }
}
/* The toolbar: 36px, grouped, with hairline separators.
Sticky at the top of the scrolling editor, because a long article scrolled
the formatting controls off the screen exactly when they were needed. The
title and the metadata row are free to scroll away under it; the ground is
opaque and the z-index keeps the text behind it. */
.doc-toolbar {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 36px;
  padding: 0 6px;
  background: var(--kb-raised);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  flex-wrap: nowrap;
  overflow-x: auto;
  position: sticky;
  top: 0;
  z-index: 3;
  box-shadow: 0 4px 12px -6px color-mix(in srgb, var(--ds-ink) 35%, transparent);
}
.doc-toolbar button {
  height: 24px;
  min-width: 26px;
  padding: 0 6px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  border-radius: var(--ds-radius-small);
  font-family: var(--ds-font-ui);
  font-size: 12px;
  font-weight: 500;
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.doc-toolbar button:hover { background: var(--kb-sel); color: var(--ds-text); }
/* A button whose formatting the caret is currently inside. Ground plus the
accent, so it reads as ON rather than merely hovered — and deliberately NOT a
font-weight change, which would move the neighbouring buttons every time the
caret crossed a bold word. */
.doc-toolbar button[data-active="true"] {
  background: var(--kb-sel);
  color: var(--ds-brand);
  box-shadow: inset 0 0 0 1px var(--ds-brand), inset 0 -2px 0 var(--ds-brand);
}
.doc-toolbar .sep {
  width: 1px;
  height: 16px;
  background: var(--ds-border);
  margin: 0 6px;
  flex-shrink: 0;
}
/* Fields in this panel are a search box and rename boxes, not form controls.
   Their rules here beat the global field rules (base/forms.css) by layer, whatever the selector. */
.doc-search input.doc-search-in {
  font-size: 12px;
  width: auto;
  background: transparent;
  border: none;
  padding: 0;
  height: 100%;
  flex: 1;
  min-width: 0;
  border-radius: 0;
}
.doc-search input.doc-search-in:focus {
  border: none;
  border-color: var(--ds-border-focused);
  box-shadow: 0 0 0 1px var(--ds-border-focused);
  background-color: var(--ds-surface);
}
input.doc-tree-rename {
  width: auto;
  background: var(--kb-col);
  height: 22px;
  padding: 0 6px;
  border: 1px solid var(--ds-brand);
  border-radius: var(--ds-radius-small);
  font-size: 13px;
  font-weight: 500;
  flex: 1;
  min-width: 0;
}
input.doc-tree-rename:focus { border-color: var(--ds-brand); box-shadow: none; }
/* Step how-to: the dropdown under a step in a checklist… */
.cl-howto-toggle {
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ds-tone-teal);
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
}
.cl-howto-toggle:hover { color: var(--ds-brand); }
.cl-howto-toggle .chev { display: inline-block; }
.cl-howto-toggle.open .chev { transform: rotate(180deg); }
.cl-howto {
  margin-top: 8px;
  padding: 10px 14px;
  border: 1px solid var(--ds-border);
  border-left: 3px solid var(--ds-tone-teal);
  border-radius: var(--ds-radius-card);
  background: var(--ds-surface-overlay);
  font-size: 13px;
}
.cl-howto p:last-child, .cl-howto ul:last-child, .cl-howto ol:last-child { margin-bottom: 0; }
.cl-howto img { cursor: zoom-in; max-width: 100%; max-height: 420px; width: auto; }
.cl-howto-editor {
  margin: 2px 0 10px 14px;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
  background: var(--ds-surface-raised, var(--ds-surface-overlay));
  overflow: hidden;
}
.rich-toolbar {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px 6px;
  border-bottom: 1px solid var(--ds-border);
  background: var(--ds-surface-hovered);
  flex-wrap: wrap;
}
.rich-toolbar button {
  background: none;
  border: none;
  color: var(--ds-text-subtle);
  cursor: pointer;
  padding: 3px 7px;
  border-radius: var(--ds-radius-small);
  font-size: 12px;
  line-height: 1.4;
}
.rich-toolbar button:hover { background: var(--ds-surface-pressed); color: var(--ds-text); }
/* Same "the caret is inside this" state as the article toolbar — the how-to
boxes are the same editor, so they answer the same way. */
.rich-toolbar button[data-active="true"] {
  background: var(--ds-surface-pressed);
  color: var(--ds-brand);
  box-shadow: inset 0 0 0 1px var(--ds-brand), inset 0 -2px 0 var(--ds-brand);
}
.rich-toolbar .sep { width: 1px; height: 16px; background: var(--ds-border); margin: 0 4px; }
.rich-toolbar .hint { margin-left: auto; font-size: 10.5px; color: var(--ds-text-subtlest); padding-right: 4px; }
.cl-howto-ed {
  min-height: 88px;
  max-height: 380px;
  overflow-y: auto;
  padding: 10px 12px;
  outline: none;
  font-size: 13px;
  line-height: 1.7;
  color: var(--ds-text);
}
.cl-howto-ed:empty:before { content: attr(placeholder); color: var(--ds-text-subtlest); }
.doc-colour-swatch:hover {
  border-color: var(--ds-text);
  transform: scale(1.06);
  box-shadow: 0 0 0 2px var(--ds-border-bold);
}
.doc-tree-folder:focus-visible, .doc-tree-item:focus-visible { outline-offset: -2px; }
/* Toolbar: 16px icons in text-subtle; on = the blue selected fill, nothing else. */
:is(.doc-toolbar, .rich-toolbar) button { color: var(--ds-text-subtle); }
:is(.doc-toolbar, .rich-toolbar) button:hover { background: var(--ds-surface-hovered); color: var(--ds-text); }
:is(.doc-toolbar, .rich-toolbar) button[data-active="true"] {
  background: var(--ds-surface-selected);
  color: var(--ds-link);
  box-shadow: none;
}
:is(.doc-toolbar, .rich-toolbar) button.ds-icon-only { width: 28px; padding: 0; gap: 0; }
:is(.doc-toolbar, .rich-toolbar) button .ds-icon { width: 16px; height: 16px; margin: 0; }
/* How-to editor toolbar (template editor, inside a .mgmt-card): the H button is bold until the
   toolbar syncs. From the first sync every data-cmd button carries data-active and takes the
   32px toggle-chip look (the old dialog chip rule drew it), selected = the blue selected fill. */
.rich-toolbar button[data-val="h3"] { font-weight: var(--ds-font-weight-bold); }
.cl-howto-editor .rich-toolbar button[data-active] {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--ds-radius-control);
  font: 500 14px/20px var(--ds-font-ui);
  letter-spacing: 0;
  text-transform: none;
  border: 1px solid var(--ds-border);
  background: transparent;
  color: var(--ds-text-subtle);
  cursor: pointer;
}
.cl-howto-editor .rich-toolbar button[data-active]:hover:not(:disabled) { background: var(--ds-surface-hovered); color: var(--ds-text); }
.cl-howto-editor .rich-toolbar button[data-active="true"],
.cl-howto-editor .rich-toolbar button[data-active="true"]:hover:not(:disabled) {
  background: var(--ds-surface-selected);
  border-color: transparent;
  color: var(--ds-link);
}
.doc-tree-item {
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  padding: 7px 9px;
  cursor: pointer;
  transition: background .12s, border-color .12s, opacity .12s;
  background: none;
  border-color: transparent;
}
.doc-tree-item:hover { background: var(--ds-surface-hovered); }
.doc-tree-item.active { background: none; border-color: var(--ds-border-focused); }
.doc-tree-btn {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  border-radius: var(--ds-radius-small);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  font-family: var(--ds-font-ui);
  color: var(--ds-text-subtle);
}
.doc-tree-btn .ds-icon { width: 16px; height: 16px; }
.doc-tree-chev {
  font-size: 9px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 12px;
  flex: 0 0 12px;
  color: var(--ds-text-subtlest);
}
.doc-tree-chev .ds-icon { width: 12px; height: 12px; margin: 0; }
.doc-search .doc-search-ico {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  margin: 0;
  color: var(--ds-text-subtlest);
}
.doc-search {
  flex: 0 0 auto;
  margin: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 8px 0 10px;
  border: 1px solid var(--ds-border);
  height: 36px;
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface-sunken);
  border-color: var(--ds-border-bold);
}
.doc-search:focus-within {
  border-color: var(--ds-border-focused);
  box-shadow: 0 0 0 1px var(--ds-border-focused);
}
.doc-content h1 {
  color: var(--ds-text);
  font-family: var(--ds-font-ui);
  margin: 20px 0 8px;
  font-weight: 600;
  line-height: 22px;
  font-size: 18px;
}
.doc-content h2 {
  color: var(--ds-text);
  font-family: var(--ds-font-ui);
  margin: 20px 0 8px;
  font-weight: 600;
  line-height: 22px;
  font-size: 16px;
}
.doc-content h3 {
  color: var(--ds-text);
  font-family: var(--ds-font-ui);
  margin: 20px 0 8px;
  font-weight: 600;
  line-height: 22px;
  font-size: 14px;
}
.doc-content p {
  color: var(--ds-text);
  font-size: 14px;
  line-height: 22px;
  margin-bottom: 16px;
  text-wrap: pretty;
}
.doc-content ul, .doc-content ol {
  color: var(--ds-text);
  font-size: 14px;
  padding-left: 22px;
  margin-bottom: 16px;
  line-height: 22px;
}
.doc-content li { margin-bottom: 4px; }
.doc-content img {
  max-width: 100%;
  height: auto;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  margin: 8px 0;
  display: block;
}
.doc-content strong { color: var(--ds-text); font-weight: 600; }
.doc-content em { color: var(--ds-text); }
.doc-content a { color: var(--ds-tone-teal); text-decoration: underline; text-underline-offset: 2px; }
.doc-content a[href^="#doc:"] {
  color: var(--ds-brand);
  text-decoration: none;
  border-bottom: 1px dashed var(--ds-brand);
}
.doc-content pre {
  background: var(--kb-raised,var(--ds-surface-raised));
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  padding: 12px 14px;
  overflow-x: auto;
  font-family: var(--ds-font-ui);
  font-size: 12.5px;
  line-height: 20px;
  color: var(--ds-text);
  margin: 16px 0;
  position: relative;
}
.doc-content pre code { background: none; padding: 0; border: none; }
.doc-content code, .rich-editor code {
  background: var(--ds-surface-hovered);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-small);
  padding: 1px 5px;
  font-family: var(--ds-font-ui);
  font-size: 12px;
  color: var(--ds-text);
}
.rich-editor pre {
  background: var(--ds-surface-hovered);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  padding: 12px 14px;
  font-family: var(--ds-font-ui);
  font-size: 12.5px;
  white-space: pre-wrap;
  margin: 12px 0;
}
.doc-content blockquote, .rich-editor blockquote {
  border-left: 3px solid var(--ds-tone-teal);
  margin: 12px 0;
  padding: 6px 14px;
  color: var(--ds-text-subtle);
  background: color-mix(in srgb, var(--ds-tone-info) 6%, transparent);
  border-radius: 0 6px 6px 0;
}
.doc-content table, .rich-editor table { border-collapse: collapse; margin: 12px 0; font-size: 13px; }
.doc-content td, .rich-editor th, .rich-editor td {
  border: 1px solid var(--ds-border);
  padding: 6px 10px;
  text-align: left;
}
.doc-content th {
  border: 1px solid var(--ds-border);
  padding: 6px 10px;
  text-align: left;
  background: var(--ds-surface-hovered);
  color: var(--ds-text);
}
.doc-content kbd {
  background: var(--ds-surface-pressed);
  border: 1px solid var(--ds-border);
  border-bottom-width: 2px;
  border-radius: var(--ds-radius-small);
  padding: 0 5px;
  font-family: var(--ds-font-ui);
  font-size: 11px;
}
.doc-pre-copy {
  position: absolute;
  top: 6px;
  right: 6px;
  font-size: 10px;
  padding: 2px 8px;
  border-radius: var(--ds-radius-small);
  border: 1px solid var(--ds-border);
  background: var(--ds-surface-overlay);
  color: var(--ds-text-subtlest);
  cursor: pointer;
}
.doc-pre-copy:hover { color: var(--ds-text); }
.rich-editor img {
  max-width: 100%;
  height: auto;
  border-radius: var(--ds-radius-control);
  margin: 8px 0;
  display: block;
  cursor: pointer;
}
/* Articles saved by an earlier editor can still carry this class; it is stripped
on the next save, and until then it must not paint a selection ring. */
.rich-editor img.doc-img-selected, .doc-content img.doc-img-selected { outline: none; }
/* Image controls. The bar and the handle are positioned over the page from an
overlay on <body>, never parented into the editor — anything inside the
contenteditable is article content and would be saved into the row. */
#doc-img-ui { position: fixed; inset: 0; pointer-events: none; z-index: 60; }
#doc-img-ui .doc-img-bar {
  position: fixed;
  display: flex;
  align-items: center;
  gap: 2px;
  height: 32px;
  padding: 0 5px;
  pointer-events: auto;
  background: var(--ds-surface-overlay);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-card);
  box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--ds-ink) 55%, transparent);
}
#doc-img-ui button {
  height: 22px;
  min-width: 26px;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  border-radius: var(--ds-radius-small);
  color: var(--ds-text-subtle);
  font-family: var(--ds-font-ui);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
}
#doc-img-ui button:hover { background: var(--ds-surface-pressed); color: var(--ds-text); }
#doc-img-ui button[data-active="true"] {
  background: var(--ds-surface-pressed);
  color: var(--ds-brand);
  box-shadow: inset 0 -2px 0 var(--ds-brand);
}
#doc-img-ui button.danger:hover {
  background: color-mix(in srgb, var(--ds-tone-danger) 14%, transparent);
  color: var(--ds-tone-danger);
}
#doc-img-ui .sep { width: 1px; height: 14px; background: var(--ds-border); margin: 0 4px; }
#doc-img-ui .doc-img-frame {
  position: fixed;
  pointer-events: none;
  border: 2px solid var(--ds-brand);
  border-radius: var(--ds-radius-control);
  box-sizing: content-box;
  margin: -2px;
}
#doc-img-ui .doc-img-handle {
  position: fixed;
  width: 14px;
  height: 14px;
  pointer-events: auto;
  cursor: nwse-resize;
  background: var(--ds-brand);
  border: 2px solid var(--ds-surface);
  border-radius: var(--ds-radius-small);
}
body.doc-img-resizing { cursor: nwse-resize; user-select: none; }
.rich-editor.doc-drop-active { outline: 2px dashed var(--ds-brand); outline-offset: -6px; }
.rich-editor h2 { font-size: 18px; font-weight: var(--ds-font-weight-bold); color: var(--ds-text); margin: 16px 0 8px; }
.rich-editor h3 { font-size: 15px; font-weight: var(--ds-font-weight-bold); color: var(--ds-text); margin: 12px 0 6px; }
.rich-editor ul, .rich-editor ol { padding-left: 24px; margin-bottom: 12px; }
.rich-editor p { margin-bottom: 8px; }
.rich-editor:empty:before { content: attr(placeholder); color: var(--ds-text-subtlest); }

/* ── The reading site (docs/STRUCTURE.md "Documentation"): tree · article · On this page, in the
   page's one scroll; the tree and the rail are sticky. ── */
/* The layout fills the rest of the page (a full-height tool, layout/shell.css), and the tree column
   stretches down it, so the column runs to the bottom of the window however short the article is;
   its max-height still caps it at the window when the article is long. */
.docs-layout { display: flex; align-items: flex-start; flex: 1 0 auto; min-width: 0; }
.docs-layout > .docs-tree-col { align-self: stretch; }
.docs-layout[hidden] { display: none; }
/* The drag handle between the tree and the article (240–420px, 52-docs-editor.js). */
.docs-resize { width: 5px; flex-shrink: 0; align-self: stretch; cursor: col-resize; border-radius: var(--ds-radius-xsmall); }
/* All articles: the list-page parts, spaced by the list page's 16px (components/list-page.css). */
.docs-all { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.docs-all[hidden] { display: none; }
/* Preview as role: the section message (components/message.css) above the reading site, its Exit at the end. */
.docs-preview-bar { align-items: center; margin-bottom: 16px; }
.docs-preview-bar[hidden] { display: none; }
.docs-preview-text { flex: 1; min-width: 0; }
/* The home's view tabs sit above its lists; the article's "For" line sits under the meta line. */
.doc-home-views { margin-bottom: 16px; }
.doc-audience { margin-top: 6px; }
.doc-audience > .doc-updated, .doc-shared-line > .doc-updated { margin-left: 0; }
/* A tree article is a link to its address; its two lines stay lines. */
a.doc-tree-item { display: block; color: inherit; text-decoration: none; }
.doc-tree-item .doc-tree-title, .doc-tree-item .doc-tree-meta { display: block; }
/* The space home: Recently updated and the folders, as two plain lists. */
.doc-home-h { margin: 0 0 8px; font: var(--ds-font-weight-medium) 16px/20px var(--ds-font-ui); color: var(--ds-text); }
.doc-home-h + .doc-home-list { margin-bottom: 24px; }
.doc-home-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.doc-home-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; padding: 6px 0; border-bottom: 1px solid var(--ds-border); }
.doc-home-list a { color: var(--ds-link); text-decoration: none; font: 400 14px/20px var(--ds-font-ui); }
.doc-home-list a:hover { text-decoration: underline; }
.doc-home-folder { display: inline-flex; align-items: center; gap: 8px; padding: 0; border: none; background: none; cursor: pointer; font: 400 14px/20px var(--ds-font-ui); color: var(--ds-link); }
.doc-home-folder:hover { text-decoration: underline; }
.doc-home-all { color: var(--ds-link); font: 400 14px/20px var(--ds-font-ui); text-decoration: none; }
.doc-home-all:hover { text-decoration: underline; }
/* The editor page's body: the toolbar (sticky while the page scrolls) over the editing area. */
.doc-editor-box { display: flex; flex-direction: column; gap: 8px; }
/* The editing area is boxed like the other fields of the page (the toolbar's own border and radius),
   so where the body ends and Details begins is visible. */
.doc-editor { min-height: 340px; outline: none; color: var(--ds-text); font-size: 14px; line-height: 22px; font-family: var(--ds-font-ui);
  padding: var(--ds-space-100) var(--ds-space-150); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-control); }
.doc-editor:focus { border-color: var(--ds-border-focused); }
.doc-tb-underline { text-decoration: underline; }
/* The import and verify pages: the help list, and the report in the page. */
.doc-import-notes { margin: 8px 0; padding-left: 18px; }
.doc-report { margin-top: 8px; font-size: 13px; }
.doc-content .doc-num { text-align: right; }
@media (max-width: 1200px) {
  .doc-read { padding: 0 24px 24px; }
}
/* Phone: the tree sits above the article at full width and grows with the page. */
@media (max-width: 640px) {
  .docs-layout { flex-direction: column; align-items: stretch; }
  .docs-layout > .docs-tree-col { width: auto; position: static; max-height: none; border-right: none; border-bottom: 1px solid var(--ds-border); }
  .docs-resize { display: none; }
  .doc-read { padding: 16px 0 0; }
}

/* ── styles/pages/webhooks.css ── */
/* pages/webhooks.css: Admin › Webhooks (a table of endpoints and one of incoming events).
   scope: #panel-webhooks, .btn-copy, .wh- */

/* A webhook URL: one line cut with an ellipsis (the full URL is its title) and a copy button. */
.wh-url { display: flex; align-items: center; gap: 4px; max-width: 420px; min-width: 0; }
.wh-url-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 400 12px var(--ds-font-ui);
  color: var(--ds-text);
}
@media (max-width: 640px) { .wh-url { max-width: 200px; } }
.btn-copy {
  background: none;
  border: none;
  font-size: 13px;
  padding: 2px;
  flex-shrink: 0;
  cursor: pointer;
  border-radius: var(--ds-radius-control);
  color: var(--ds-text-subtle);
}
.btn-copy:hover { background: var(--ds-surface-hovered); color: var(--ds-text); border: none; }

/* ── styles/pages/it-access.css ── */
/* pages/it-access.css: IT access and IT equipment: EBET roles, access chips, the equipment
   picture column.
   scope: .ebet-, .eq-, .ll-, .ua- */

.ebet-group-tag {
  display: inline-block;
  border: none;
  border-radius: var(--ds-radius-small);
  padding: 0 6px;
  line-height: 20px;
  background: var(--ds-tone-neutral-subtle);
  color: var(--ds-text-subtle);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0;
}
.ebet-role, .ua-grant {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 20px;
  padding: 0 6px;
  margin: 2px 0;
  border: none;
  border-radius: var(--ds-radius-small);
  background: var(--ds-tone-neutral-subtle);
  color: var(--ds-text);
  font: 500 12px/20px var(--ds-font-ui);
  letter-spacing: 0;
  white-space: nowrap;
  vertical-align: middle;
}
button.ua-grant--more { cursor: pointer; background: transparent; color: var(--ds-link); border: none; }
button.ua-grant--more:hover { background: var(--ds-surface-hovered); }
/* IT equipment: the item's picture (or an empty frame) and a cell width cap. */
.eq-thumb-col { width: 44px; }
.eq-thumb {
  display: block;
  width: 34px;
  height: 34px;
  object-fit: contain;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface-sunken);
}
.eq-cell { max-width: 280px; }

/* Admin › Asset-label logos: the logo preview, one control high (32px, as the Upload button beside it). */
.ll-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 96px;
  height: 32px;
  overflow: hidden;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  background: var(--ds-surface-raised);
  font: 400 12px/16px var(--ds-font-ui);
}
.ll-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* ── styles/pages/onboarding.css ── */
/* pages/onboarding.css: People: the employee register table, checklist runs and templates, Employee fields.
   scope: .cl-, .onb- */

/* ── OnBoarding register: nine columns on a 14-inch laptop ───────────────────
The register carries nine columns, and on a 1280px screen (sidebar included,
the table gets 970px) the ACTIONS column alone claimed 342px for four
labelled, nowrap buttons. Everything else was crushed below its content:
names broke over three lines, access chips stacked one per line, rows grew to
214px, and the table STILL overflowed by 166px — so the last two buttons sat
off-screen behind a horizontal scrollbar.

Below 1600px (a 14-inch MacBook is 1512 CSS px, a 1080p 14-inch at 125% is
1536) the actions go icon-only — every one keeps its title, so hovering still
says what it does — the cells lose some padding, and `onbChipCap()` renders
fewer access chips behind the existing "+N more". The optional columns then
drop out at the same widths the equipment table uses. Column minimums stop
the browser shrinking a column below its content, and the table's own
min-width makes a genuinely too-narrow window scroll instead of crush. */
.onb-table { min-width: 860px; }
.onb-table th:nth-child(1), .onb-table td:nth-child(1) { min-width: 140px; }
/* EMPLOYEE     */
.onb-table th:nth-child(2), .onb-table td:nth-child(2) { min-width: 72px; }
/* ORG          */
.onb-table th:nth-child(3), .onb-table td:nth-child(3) { min-width: 112px; }
/* DEPARTMENT   */
.onb-table th:nth-child(4), .onb-table td:nth-child(4) { min-width: 116px; }
/* JOB POSITION */
.onb-table th:nth-child(5), .onb-table td:nth-child(5) { min-width: 88px; }
/* COMPANY      */
.onb-table th:nth-child(6), .onb-table td:nth-child(6) { min-width: 108px; }
/* The chips column: wide enough for two chips a line, so ten of them cannot
turn one row into a column. */
.onb-table td.onb-access { min-width: 126px; max-width: 420px; }
@media (max-width: 1600px) {
  /* The row menu button: 14px glyph, 2px apart. */
  .onb-table td.onb-actions :is(.btn-primary, .btn-secondary, .btn-danger) { margin-right: 2px; font-size: 14px; }
  /* Wide enough for two chips a line, so the capped set is two lines, not five. */
  .onb-table td.onb-access { min-width: 160px; max-width: 280px; }
}
@media (max-width: 1400px) {
  .onb-table th:nth-child(5), .onb-table td:nth-child(5) { display: none; }
}
/* From 1250px down (the desktop app's 960px minimum window included; a phone keeps only the
   employee, the access and the actions) the register's laptop minimum width goes, so it fits the page. */
@media (max-width: 1250px) {
  .onb-table th:nth-child(7), .onb-table td:nth-child(7) { display: none; }
  .onb-table { min-width: 0; }
}
/* Checklists (onboarding / offboarding): the progress bar in the list and on a run's record. */
.cl-bar {
  height: 8px;
  background: var(--ds-surface-hovered);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-round);
  overflow: hidden;
}
.cl-progress-cell { min-width: 160px; }
.cl-progress-note { margin-top: var(--ds-space-050); }
/* One fill, no gradient: colour is kept for status lozenges (structure.html "Precedence rule"). */
.cl-bar-fill { height: 100%; background: var(--ds-brand); transition: width .2s; }
/* A run's steps, in the record's sections (record-page.css): no cards, no colour bands. Text 14/20,
   the "done by" line 12/18 (compare.html, M), a 4px step between rows and the status chips beside
   the text, 6px apart (the one-control-height rule of the filter bar). */
.cl-steps { display: flex; flex-direction: column; gap: var(--ds-space-050); }
.cl-step { display: flex; align-items: flex-start; gap: var(--ds-space-150); padding: var(--ds-space-050) 0; }
.cl-step-main { flex: 1; min-width: 0; }
.cl-step-text { font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); overflow-wrap: anywhere; padding-top: 6px; }
.cl-step[data-status="done"] .cl-step-text { text-decoration: line-through; color: var(--ds-text-subtle); }
.cl-step[data-status="skipped"] .cl-step-text { color: var(--ds-text-subtle); }
.cl-step-meta { font: 400 12px/18px var(--ds-font-ui); color: var(--ds-text-subtle); }
.cl-step-status { display: flex; flex-shrink: 0; gap: 6px; }
@media (max-width: 640px) {
  .cl-step { flex-direction: column; gap: var(--ds-space-050); }
}
/* The template editor, in the record's page flow (no card): a section title, its steps indented one
   space-200 step (16px), one control height and 6px gaps per row. */
.cl-tpl-sec { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--ds-space-200); }
.cl-tpl-step { display: flex; align-items: center; gap: 6px; }
.cl-tpl-step > input { flex: 1 1 auto; min-width: 0; }
.cl-tpl-sec-input { font-weight: var(--ds-font-weight-semibold); }
.cl-tpl-step-indent { margin-left: var(--ds-space-200); }
.cl-tpl-sec-title { font: var(--ds-font-weight-semibold) 14px/20px var(--ds-font-ui); color: var(--ds-text); }
.cl-tpl-step-ro { margin-left: var(--ds-space-200); font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); }
@media (max-width: 640px) {
  .cl-tpl-step { flex-wrap: wrap; }
  .cl-tpl-step > input { flex-basis: 100%; }
  .cl-tpl-step-indent, .cl-tpl-step-ro { margin-left: 0; }
}
/* OnBoarding — Manage Fields (global schema editor) */
/* The list grows with the page (one page scroll), never a box that scrolls on its own. */
.onb-fld-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 2px;
}
.onb-fld-row { display: grid; grid-template-columns: auto 1fr 130px auto; gap: 10px; align-items: center; }
.onb-fld-row input, .onb-fld-row select { width: 100%; }
.onb-mv:disabled { opacity: 0.35; cursor: default; }
@media (max-width: 640px) {
  .onb-fld-row { grid-template-columns: auto 1fr auto; }
  .onb-fld-row select { grid-column: 2 / 3; }
}
.onb-mv-col { display: flex; flex-direction: row; gap: 0; }
.onb-mv {
  line-height: 1;
  font-size: 9px;
  cursor: pointer;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  border-radius: var(--ds-radius-control);
  background: none;
  color: var(--ds-text-subtle);
}
.onb-mv:not(:disabled):hover {
  border-color: var(--ds-brand);
  background: var(--ds-surface-hovered);
  color: var(--ds-text);
}
.onb-mv .ds-icon { width: 16px; height: 16px; margin: 0; }
.onb-rm {
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
  height: 32px;
  border-radius: var(--ds-radius-control);
  border: 1px solid var(--ds-border);
  background: transparent;
  color: var(--ds-text-subtle);
  font: 500 14px/20px var(--ds-font-ui);
  display: grid;
  place-items: center;
  width: 32px;
  flex-shrink: 0;
}
.onb-rm-spacer { display: inline-block; width: 32px; }
.onb-rm:hover {
  background: var(--ds-surface-hovered);
  color: var(--ds-text);
  border-color: var(--ds-border);
}
.onb-table td.onb-actions { white-space: nowrap; width: 1%; }

/* ── styles/pages/desktop.css ── */
/* pages/desktop.css: Desktop app panel: installers and devices.
   scope: #desk-, #panel-desktop, .desk- */

.desk-note {
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text);
  background: var(--ds-surface-overlay);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-control);
  padding: 8px 12px;
  margin: 0;
  max-width: 900px;
}
.desk-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
  margin: 0;
  max-width: 900px;
}
.desk-card-os { font-size: 16px; font-weight: 600; color: var(--ds-text); }
.desk-card-label { font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); }
.desk-card-meta { font: 400 12px/16px var(--ds-font-ui); color: var(--ds-text-subtle); margin-bottom: 4px; }
/* The button keeps its own inline-flex centring (components/buttons.css): no display override. */
.desk-dl { align-self: flex-start; text-decoration: none; }
.desk-notes {
  grid-column: 1 / -1;
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text);
  border-top: 1px dashed var(--ds-border);
  padding-top: 10px;
}
.desk-notes-h { font-weight: 600; color: var(--ds-text); margin-bottom: 4px; }
.desk-help { max-width: 900px; margin: 0; font: 400 14px/20px var(--ds-font-ui); color: var(--ds-text); }
.desk-help-body { padding: 4px 0 0 4px; }
.desk-help-body ol { margin: 4px 0 12px; padding-left: 20px; }
/* The app's own icon (public/brand/icon-192.png, what the Dock and the taskbar show) beside the intro. */
.desk-hero { display: flex; align-items: center; gap: 16px; max-width: 760px; }
.desk-app-icon { width: 48px; height: 48px; flex-shrink: 0; display: block; }
.desk-intro {
  margin: 0;
  font: 400 14px/20px var(--ds-font-ui);
  color: var(--ds-text);
  max-width: 760px;
}
/* The shared empty state spans the installer grid. */
.desk-grid > .ds-empty { grid-column: 1 / -1; }
.desk-help summary {
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0;
  font: 500 14px/20px var(--ds-font-ui);
  color: var(--ds-link);
  cursor: pointer;
}
.desk-help summary::-webkit-details-marker { display: none; }
.desk-help summary::marker { content: ''; }
.desk-help summary .ds-icon { margin: 0; transform: rotate(-90deg); }
.desk-help[open] summary .ds-icon { transform: none; }
.desk-card {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--ds-surface-raised);
  border: 1px solid var(--ds-border-card);
  border-radius: var(--ds-radius-card);
}

/* ── styles/pages/security.css ── */
/* pages/security.css: Settings › Security log, the event record's "Raw event" block (33-security.js).
   scope: .sec- */

/* The stored event as JSON: the base <pre> look (base/typography.css), wrapped instead of scrolled
   sideways, so the record fits a 640px window and nothing scrolls inside the page (STRUCTURE.md). */
.sec-raw { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/* The client IP in clear (owners, 0059): the code face, so 0/O and 1/l read apart; an IPv6 address
   wraps rather than pushing a 640px window sideways. */
.sec-ip { font-family: var(--ds-font-code); overflow-wrap: anywhere; }

} /* @layer pages */

@layer utilities {

/* ── styles/utilities/motion.css ── */
/* utilities/motion.css: Calm interaction: one quick colour transition on interactive controls, reduced-motion kill switch. */

/* Only on what a person interacts with: on every element (it was `:root *`), each re-render of a
   long list set up a transition on every cell, and a theme switch animated the whole page. */
:where(a, button, input, select, textarea, summary, label, [role="button"], [role="tab"], [role="menuitem"], [role="option"], [role="switch"], [role="checkbox"]) {
  transition-property: background-color, border-color, color, fill, opacity, box-shadow;
  transition-duration: var(--ds-duration-fast);
  transition-timing-function: var(--ds-ease-out);
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
@keyframes ds-fade {from { opacity: 0; } to { opacity: 1; }}

/* ── styles/utilities/focus.css ── */
/* utilities/focus.css: One focus ring (keyboard only); text fields draw their own. */

/* ── Focus: one ring everywhere, 2px focused blue, keyboard only ─────────────
Rows inside menus, lists and the sidebar draw it inset so it is not clipped.
Text fields keep their own border + ring (above), so they take no outline. */
:focus-visible { outline: 2px solid var(--ds-border-focused); }
:is(input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"]), select, textarea, [contenteditable], [tabindex="-1"]):focus-visible {
  outline: none;
}

/* ── styles/utilities/text.css ── */
/* utilities/text.css: One-property text helpers for the app's templates (public/js/app/*.js, index.html), used instead of a repeated style="". In the utilities layer so they win like the inline style they replace. Combine them: class="ds-text-hint ds-fs-12". */

/* Colour */
.ds-text-default { color: var(--ds-text); }
.ds-text-subtle { color: var(--ds-text-subtle); }
.ds-text-hint { color: var(--ds-text-subtlest); }

/* Size */
.ds-fs-11 { font-size: 11px; }
.ds-fs-12 { font-size: 12px; }

/* Line height (a checkbox caption level with its 20px box) */
.ds-lh-20 { line-height: 20px; }

/* Alignment and wrapping */
.ds-nowrap { white-space: nowrap; }

/* ── styles/utilities/spacing.css ── */
/* utilities/spacing.css: Spacing and flex-row helpers for the app's templates (public/js/app/*.js, index.html), used instead of a repeated style="". In the utilities layer so they win like the inline style they replace. Never put ds-m-0 and a ds-mt-/ds-mb- on one element. */

/* Margins */
.ds-m-0 { margin: 0; }
.ds-mt-4 { margin-top: 4px; }
.ds-mt-8 { margin-top: 8px; }
.ds-mt-12 { margin-top: 12px; }

/* A row of items centred on one line, with the gap in px; add ds-wrap to let it wrap. */
.ds-row-6 { display: flex; align-items: center; gap: 6px; }
.ds-row-8 { display: flex; align-items: center; gap: 8px; }
.ds-wrap { flex-wrap: wrap; }
.ds-flex-1 { flex: 1; }
.ds-pointer { cursor: pointer; }

/* ── styles/utilities/inline-overrides.css ── */
/* utilities/inline-overrides.css: Rules that must beat a style="" attribute written by public/js/app/*.js or index.html, each naming its source. Ratcheted in design/css-baseline.json: may only shrink. Empty since 29/10/2026: remove the property from the template and style it in its component instead. */

} /* @layer utilities */

/* Unlayered: overrides of an unlayered CDN stylesheet must stay unlayered to win. */

/* ── styles/vendor/vis.css ── */
/* vendor/vis.css: Overrides of the vis-network library (vis.min.css is an unlayered CDN sheet, so these stay unlayered too). */

/* ── VIS overrides ───────────────────────────────────────────────────────── */
.vis-network { background: transparent; }
/* ── Tooltips: the timeline's tooltip is Atlassian's inverse chip in both themes ── */
div.vis-tooltip {
  background: var(--ds-text);
  color: var(--ds-text-inverse);
  border: none;
  border-radius: var(--ds-radius-control);
  padding: 2px 6px;
  font: 400 12px/16px var(--ds-font-ui);
  box-shadow: none;
}
