:root{
  /* Color tokens — ADR-007-3 consolidation (#1257).
     Light and dark values resolve via CSS light-dark() against the
     nearest ancestor's `color-scheme`. The `html[data-theme=light|dark]`
     toggles below pin that scheme; without a toggle, the OS preference
     wins. Values are unchanged from the previous 4-block layout — this
     is a structural cleanup, not a palette migration.
     Reference OP grays (assets/vendor/open-props.min.css) noted in
     comments where the IPAM neutral is close to an OP gray; IPAM keeps
     its slightly cooler tint as brand identity. */
  color-scheme: light dark;
  --bg:                light-dark(#ffffff, #0e1116);                                                                /* OP closest: --gray-0/--gray-10 */
  --fg:                light-dark(#111111, #e7eaf0);                                                                /* OP closest: --gray-12/--gray-2 */
  --muted:             light-dark(#586174, #a8b0bf);                                                                /* OP closest: --gray-7/--gray-5 */
  --border:            light-dark(#d9dde5, #2a2f3a);                                                                /* OP closest: --gray-3/--gray-9 */
  --border-strong:     light-dark(#c5cbd6, #394150);                                                                /* OP closest: --gray-4/--gray-8 */
  --card:              light-dark(#fafbfc, #151a22);                                                                /* OP closest: --gray-0/--gray-10 */
  --card-2:            light-dark(#f3f5f8, #1b2230);                                                                /* OP closest: --gray-1/--gray-9 */
  --link:              light-dark(#0b57d0, #7ab0ff);                                                                /* brand-defined; OP --blue-* sibling */
  --danger:            light-dark(#b00020, #ff5c7a);                                                                /* brand-defined */
  --success:           light-dark(#0f9d58, #22C55E);                                                                /* brand-defined */
  --warn:              light-dark(#b26a00, #ffbf66);                                                                /* brand-defined */
  --btn:               light-dark(#111111, #22C55E);                                                                /* brand-defined (light=black, dark=brand green) */
  --btnfg:             light-dark(#ffffff, #0a1a0d);                                                                /* brand-defined */
  --btn-secondary:     light-dark(#eef1f5, #1b2230);                                                                /* OP closest: --gray-1.5/--gray-9 */
  --btn-secondary-fg:  light-dark(#111111, #e7eaf0);                                                                /* matches --fg */
  --brand:             light-dark(#16a34a, #22C55E);                                                                /* brand-defined */
  --badge-bg:          light-dark(#eef1f5, #1b2230);                                                                /* matches --btn-secondary */
  --input-bg:          light-dark(#ffffff, #0f141c);                                                                /* matches --bg light; subtly darker in dark */
  /* --shadow: 2-stack box-shadow can't live inside light-dark() because the
     function takes exactly 2 comma-separated args; shadow stacks themselves
     contain top-level commas. Split into near/far halves so each half fits. */
  --shadow-near:       light-dark(0 1px 2px rgba(0,0,0,.05), 0 1px 2px rgba(0,0,0,.25));
  --shadow-far:        light-dark(0 6px 16px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.25));
  --shadow:            var(--shadow-near), var(--shadow-far);
  --nav-bg:            light-dark(rgba(255,255,255,.88), rgba(14,17,22,.88));

  /* Spacing scale — ADR-007-2 migration to Open Props.
     Tokens here remain named --space-N for compat with ~300 existing
     references in app.css; values now alias OP's --size-* where the
     scales match exactly (rem-based, identical px at the default 16px
     root font-size). Tokens with no OP equivalent keep their px literal.
     OP source: assets/vendor/open-props.min.css. */
  /* --space-0 (0) removed in #957 — zero references. */
  --space-1:2px;             /* no OP match — smallest OP size is --size-1 (4px) */
  --space-2:var(--size-1);   /* OP: 0.25rem = 4px */
  --space-3:6px;             /* no OP match */
  --space-4:var(--size-2);   /* OP: 0.5rem = 8px */
  --space-5:10px;            /* no OP match */
  --space-6:12px;            /* no OP match */
  --space-7:14px;            /* no OP match */
  --space-8:var(--size-3);   /* OP: 1rem = 16px */
  --space-9:var(--size-4);   /* OP: 1.25rem = 20px */
  --space-10:var(--size-5);  /* OP: 1.5rem = 24px */
  --space-11:40px;           /* no OP match */
  --space-12:var(--size-8);  /* OP: 3rem = 48px */
  --space-13:60px;           /* no OP match */

  /* z-index registry — #957 removed --z-base (0 refs) and --z-drawer-overlay (0 refs). */
  --z-sticky:2;
  --z-topbar:50;
  --z-overlay:100;
  --z-drawer:180;
  --z-nav-overlay:199;
  --z-nav-drawer:200;
  --z-dropdown:300;
  --z-col-vis:1000;
  --z-spinner:1100;
  --z-toast:9000;
  --z-page-overlay:9999;

  /* Radius scale — ADR-007-2 migration to Open Props.
     IPAM's compact UI uses a denser radius scale than OP. Only
     --radius-4xl and --radius-pill align with OP values. The rest
     stay as px literals; closing #1256 does not require value parity. */
  --radius-xs:3px;                /* no OP match (OP --radius-1 = 2px) */
  --radius-sm:4px;                /* no OP match */
  --radius-md:6px;                /* no OP match (OP --radius-2 = 5px, close but not equal) */
  --radius-lg:8px;                /* no OP match */
  --radius-xl:10px;               /* no OP match */
  --radius-2xl:12px;              /* no OP match */
  --radius-3xl:14px;              /* no OP match */
  --radius-4xl:var(--radius-3);   /* OP: 1rem = 16px */
  --radius-pill:var(--radius-round); /* OP: 1e5px — same visual effect (full pill) */

  /* Type scale — C1 / #953.
     6-step scale at 12 / 14 / 16 / 20 / 24 / 32 px (assuming default
     16px root). Five of the six alias OP --font-size-* tokens directly;
     14px (--text-sm, body default) stays as a brand-defined intermediate
     because OP's scale jumps from 12px to 16px without it.
     The legacy 14-step --font-size-N and old 7-step --text-* tokens
     below are kept as deprecation aliases pointing at one of the six
     canonical sizes, so existing ~190 var() callers continue to resolve.
     Net: 14 distinct production sizes (11/12/13/14/14.4/14.72/16/18/...)
     collapse to 6. */
  --text-xs:   var(--font-size-0);   /* 12px - OP */
  --text-sm:   0.875rem;             /* 14px - body default, no OP match */
  --text-base: var(--font-size-1);   /* 16px - OP */
  --text-lg:   var(--font-size-3);   /* 20px - OP */
  --text-xl:   var(--font-size-4);   /* 24px - OP */
  --text-2xl:  var(--font-size-5);   /* 32px - OP */

  /* --text-md retained as deprecation alias (was 1rem in v3.35.0). */
  --text-md:   var(--text-base);     /* 16px */

  /* Legacy --font-size-* deprecation aliases (rounded to nearest 6-step). */
  --font-size-2xs: var(--text-xs);   /* was .65rem (10.4px)  → 12px */
  --font-size-xs:  var(--text-xs);   /* was .75rem (12px)    → 12px */
  --font-size-sm:  var(--text-sm);   /* was .78rem (12.5px)  → 14px */
  --font-size-md:  var(--text-sm);   /* was .82rem (13.1px)  → 14px */
  --font-size-base:var(--text-sm);   /* was .85rem (13.6px)  → 14px */
  --font-size-lg:  var(--text-sm);   /* was .88rem (14.1px)  → 14px */
  --font-size-xl:  var(--text-sm);   /* was .9rem  (14.4px)  → 14px */
  --font-size-2xl: var(--text-sm);   /* was .92rem (14.72px) → 14px */
  --font-size-3xl: var(--text-base); /* was .95rem (15.2px)  → 16px */
  --font-size-4xl: var(--text-base); /* was 1rem   (16px)    → 16px */
  --font-size-5xl: var(--text-base); /* was 1.05rem(16.8px)  → 16px */
  --font-size-6xl: var(--text-lg);   /* was 1.15rem(18.4px)  → 20px */
  --font-size-7xl: var(--text-lg);   /* was 1.35rem(21.6px)  → 20px */
  --font-size-8xl: var(--text-xl);   /* was 1.6rem (25.6px)  → 24px */

  --focus-ring:0 0 0 2px var(--bg), 0 0 0 4px var(--link);
  --font-sans:'Fira Sans',system-ui,-apple-system,sans-serif;
  --font-mono:'Fira Code',ui-monospace,'SFMono-Regular','Consolas',monospace;

  /* Icon size tokens — C10 / #961.
     IPAM uses two standard icon sizes: 16px (the default, used for nav,
     action pills, inline indicators) and 20px (medium-emphasis, used for
     section headings + the empty-state hint icons). The hardcoded values
     in .icon, .icon-lg, and .collapsible-toggle .icon below reference
     these tokens so callers can adopt either via class or via inline
     CSS without re-deriving the value. */
  --icon-sm: 16px;
  --icon-md: 20px;

  /* Section rhythm — C7 / #959.
     One token for the gap between adjacent cards / dashboard widgets
     and for .grid container gaps. Set to --space-8 (16px) to match the
     existing consensus; rebalancing section rhythm globally becomes a
     single-token change. */
  --space-section: var(--space-8);

}

@font-face{font-family:'Fira Sans';src:url('fonts/FiraSans-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Fira Sans';src:url('fonts/FiraSans-Medium.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Fira Sans';src:url('fonts/FiraSans-SemiBold.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Fira Sans';src:url('fonts/FiraSans-Bold.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:'Fira Code';src:url('fonts/fira-code-subset.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}

/* Theme switches — ADR-007-3 (#1257).
   :root above declares `color-scheme: light dark` so light-dark() resolves
   against the OS preference by default. These two rules pin the scheme
   when the user has explicitly toggled, overriding the OS preference. */
html[data-theme="light"]{color-scheme:light;}
html[data-theme="dark"]{color-scheme:dark;}

/* Screen-reader-only utility — C4 / #956.
   Standard a11y pattern: visually hidden, accessible to assistive tech.
   Used to pair color-only signals (util-bar severity, health-dot status)
   with text equivalents for WCAG 1.4.1. Two existing consumers in
   change_password.php were relying on this class without a definition;
   defining it here fixes that latent bug too. */
.sr-only{
  position:absolute;
  width:1px;
  height:1px;
  padding:0;
  margin:-1px;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

/* Dark-mode calendar picker indicator: filter has no light-dark()
   equivalent, so this stays as a separate selector pair. */
html[data-theme="dark"] ::-webkit-calendar-picker-indicator{filter:invert(1);}
@media(prefers-color-scheme:dark){
  html:not([data-theme="light"]) ::-webkit-calendar-picker-indicator{filter:invert(1);}
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}

/* --- SVG icon system (#511, #961) --- */
.icon{display:inline-block;width:var(--icon-sm);height:var(--icon-sm);vertical-align:-0.125em;flex-shrink:0;pointer-events:none;fill:none}
/* .icon-sm previously declared 14px (.875rem); now standardized at 16px
   per C10. Was unused at the prior 14px value, so no caller impact. */
.icon-sm{width:var(--icon-sm);height:var(--icon-sm)}
.icon-md{width:var(--icon-md);height:var(--icon-md)}
/* .icon-lg retained for compat with one in-tree caller; same 20px as .icon-md. */
.icon-lg{width:var(--icon-md);height:var(--icon-md)}
.icon-xl{width:1.5rem;height:1.5rem}
.icon-2xl{width:2rem;height:2rem}

/* --- #504: skip-to-content link --- */
.skip-link{position:absolute;top:-100%;left:var(--space-8);padding:var(--space-4) var(--space-8);background:var(--link);color:#fff;border-radius:var(--radius-sm);z-index:var(--z-page-overlay);font-weight:600;text-decoration:none}
.skip-link:focus{top:var(--space-4)}

/* --- #504: focus-visible rings on all interactive elements --- */
:focus-visible{outline:none;box-shadow:var(--focus-ring)}
input:focus-visible,select:focus-visible,textarea:focus-visible{box-shadow:var(--focus-ring)}
.nav-pill:focus-visible,.action-pill:focus-visible,.badge:focus-visible{box-shadow:var(--focus-ring);border-radius:var(--radius-2xl)}
@media(forced-colors:active){:focus-visible{outline:2px solid CanvasText;outline-offset:2px;box-shadow:none}}
body{
  background:var(--bg);
  color:var(--fg);
  font-family:var(--font-sans);
  /* C1 / #953 — desktop body uses --text-sm (14px). #954's mobile bump
     to 1rem (16px) inside @media (max-width: 768px) overrides this. */
  font-size:var(--text-sm);
  margin:0;
  line-height:1.5;
}
.page{
  max-width:1280px;
  margin:0 auto;
  padding:var(--space-9);
}
a{color:var(--link);text-decoration:none}
a:hover{text-decoration:underline}
hr{border:none;border-top:1px solid var(--border);margin:18px 0}
h1,h2,h3{margin:.2em 0 .55em 0}
h1{font-size:var(--text-xl);font-weight:700;line-height:1.25}
h2{font-size:var(--text-lg);font-weight:600;line-height:1.25}
h3{font-size:var(--text-md);font-weight:600;line-height:1.3}

.topbar{
  position:sticky;
  top:0;
  z-index:var(--z-topbar);
  backdrop-filter:blur(8px);
  background:var(--nav-bg);
  border-bottom:1px solid var(--border);
}
.nav-wrap{
  max-width:1280px;
  margin:0 auto;
  padding:var(--space-6) var(--space-9);
  display:flex;
  gap:18px;
  align-items:center;
  flex-wrap:wrap;
}
.nav-brand{
  display:flex;
  align-items:center;
  font-family:var(--font-mono);
  font-weight:600;
  font-size:var(--font-size-4xl);
  color:var(--fg);
  text-decoration:none;
  white-space:nowrap;
  flex-shrink:0;
  letter-spacing:-.01em;
}
.nav-brand:hover{opacity:.8;text-decoration:none}
.nav-brand-php{color:var(--brand)}
.footer-brand{font-size:var(--font-size-xl);opacity:.85}
.login-wrap{max-width:400px;margin:var(--space-11) auto 0;padding:0 var(--space-8)}
.login-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-2xl);padding:36px var(--space-11);box-shadow:var(--shadow)}
.login-logo{text-align:center;margin-bottom:var(--space-9);display:flex;justify-content:center}
.login-logo img{max-width:200px;height:auto}
.login-wrap h1{text-align:center;margin:0 0 var(--space-10);font-size:var(--font-size-8xl)}
.login-wrap .row{flex-direction:column;gap:var(--space-7)}
.login-wrap label{width:100%}
.login-wrap input[type=text],.login-wrap input[type=password],.login-wrap input:not([type]){width:100%;box-sizing:border-box}
.login-wrap form>p{margin:var(--space-9) 0 0}
.login-wrap form>p>button{width:100%;padding:var(--space-5)}
.nav-links{
  display:flex;
  gap:var(--space-7);
  flex-wrap:wrap;
  align-items:center;
}
.nav-user{
  margin-right:var(--space-3);
}
.nav-pill{
  display:inline-flex;
  align-items:center;
  gap:var(--space-3);
  padding:9px 13px;
  border-radius:var(--radius-2xl);
  line-height:1.2;
  background:transparent;
}
.nav-pill:hover{
  background:var(--card-2);
  text-decoration:none;
}
.nav-right{
  margin-left:auto;
  display:flex;
  gap:var(--space-5);
  align-items:center;
  flex-wrap:wrap;
}
.nav-dropdown{
  position:relative;
}
.nav-dropdown-toggle{
  padding:9px 13px;
  border-radius:var(--radius-2xl);
  background:transparent;
  color:var(--link);
  border:none;
  cursor:pointer;
  font:inherit;
  line-height:1.2;
}
.nav-dropdown-toggle:hover{
  background:var(--card-2);
  filter:none;
}
.nav-dropdown-menu{
  display:none;
  position:absolute;
  top:calc(100% + 4px);
  left:0;
  min-width:160px;
  background:var(--card);
  border:1px solid var(--border);
  border-radius:var(--radius-2xl);
  box-shadow:var(--shadow);
  z-index:var(--z-overlay);
  padding:var(--space-3) 0;
}
.nav-dropdown.open .nav-dropdown-menu{
  display:block;
}
.nav-dropdown-menu--right{
  left:auto;
  right:0;
}
.nav-user-toggle{
  color:var(--fg);
}
.nav-dropdown-item{
  display:block;
  width:100%;
  padding:9px var(--space-8);
  color:var(--fg);
  white-space:nowrap;
  /* reset for <button> */
  background:none;
  border:none;
  border-radius:0;
  text-align:left;
  cursor:pointer;
  font:inherit;
  box-sizing:border-box;
}
.nav-dropdown-item:hover{
  background:var(--card-2);
  text-decoration:none;
  filter:none;
}
.nav-dropdown-divider{
  border:none;
  border-top:1px solid var(--border);
  margin:var(--space-3) 0;
}

.card{
  background:var(--card);
  border:1px solid var(--border);
  border-radius:var(--radius-4xl);
  padding:var(--space-8);
  box-shadow:var(--shadow);
}
.card + .card{margin-top:var(--space-section)}

.table-wrap{
  overflow:auto;
  max-height:65vh;
  -webkit-overflow-scrolling:touch;
}
.diff-table{font-size:var(--font-size-base);border-collapse:collapse;width:auto;min-width:200px}
.diff-table th,.diff-table td{padding:3px var(--space-4);border:1px solid var(--border)}
.diff-table tr.diff-changed{background:var(--warn-bg, rgba(255,193,7,.12))}

tr.highlight{
  background:var(--warn-bg, rgba(255,193,7,.12));
  outline:2px solid var(--warn, #e6a817);
  outline-offset:-2px;
}

.toolbar{
  display:flex;
  gap:var(--space-6);
  flex-wrap:wrap;
  align-items:center;
  margin-bottom:var(--space-6);
}
.toolbar .spacer{margin-left:auto}

.page-actions{
  display:flex;
  gap:var(--space-5);
  flex-wrap:wrap;
  align-items:center;
  margin-top:var(--space-4);
  margin-bottom:var(--space-5);
}
.action-pill{
  display:inline-flex;
  align-items:center;
  gap:var(--space-3);
  padding:var(--space-5) var(--space-6);
  border-radius:var(--radius-2xl);
  background:var(--card-2);
  border:1px solid var(--border);
  color:var(--fg);
}
.action-pill:hover{
  text-decoration:none;
  filter:brightness(1.02);
}
/* Prevent action-pills overflowing card boundaries at narrow widths (#651) */
.card .action-pill{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.breadcrumbs{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-4);
  align-items:center;
  color:var(--muted);
  font-size:var(--text-sm);
  margin-bottom:var(--space-5);
}
.breadcrumbs a{
  color:var(--link);
}
.breadcrumbs .sep{
  color:var(--muted);
}

.grid{
  display:grid;
  gap:var(--space-section);
  align-items:stretch;
}
.grid > .card{
  display:flex;
  flex-direction:column;
  margin-top:0;
}
/* Push CTA links to bottom of equal-height grid cards (#650) */
.grid > .card > .mt-10:last-child{margin-top:auto}
.grid.cols-2{
  grid-template-columns:repeat(auto-fit,minmax(520px,1fr));
}
.grid.cols-3{
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
}
/* Dashboard metric grid — always 3 columns at ≥640px, collapses to 1 at mobile (#649) */
.metric-row{
  display:grid;
  gap:var(--space-section);
  grid-template-columns:repeat(3,1fr);
}
@media(max-width:640px){
  .metric-row{grid-template-columns:1fr}
}

.metric{
  background:var(--card);
  border:1px solid var(--border);
  border-radius:var(--radius-4xl);
  padding:var(--space-7) var(--space-8);
  box-shadow:var(--shadow);
}
.metric .label{color:var(--muted);font-size:var(--font-size-2xl)}
.metric .value{font-size:var(--text-xl);font-weight:700;margin-top:var(--space-3)}

table{
  border-collapse:collapse;
  width:100%;
  background:var(--card);
  border-radius:var(--radius-3xl);
  clip-path:inset(0 round 14px);
}
th,td{
  border:1px solid var(--border);
  padding:var(--space-5) var(--space-6);
  text-align:left;
  vertical-align:top;
}
th{
  background:var(--card-2);
  font-weight:600;
}
th a{color:inherit;text-decoration:none;white-space:nowrap}
th a:hover{text-decoration:underline}
th.sort-active{background:color-mix(in srgb,var(--card-2) 70%,var(--link) 30%)}
tbody tr:nth-child(even) td{
  background:color-mix(in srgb, var(--card) 88%, var(--bg) 12%);
}
tbody tr:hover td{
  background:color-mix(in srgb, var(--card-2) 65%, var(--bg) 35%);
}

.row{
  display:flex;
  gap:var(--space-6);
  flex-wrap:wrap;
  align-items:flex-end;
}
label{
  display:flex;
  flex-direction:column;
  gap:var(--space-3);
  font-size:var(--font-size-3xl);
}
input,select,textarea,button{
  font:inherit;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),select{
  height:40px;
  padding:0 var(--space-6);
  border:1px solid var(--border-strong);
  border-radius:var(--radius-2xl);
  background:var(--input-bg);
  color:var(--fg);
  min-width:0;
  box-sizing:border-box;
}
/* #443: <select multiple> needs the size attribute to control row count
   instead of the default 40px height that single-selects use, otherwise
   the alert recipients picker collapses to a single row with a scrollbar. */
select[multiple]{
  height:auto;
  padding:var(--space-3) var(--space-4);
  line-height:1.4;
}
select[multiple] option{
  padding:var(--space-2) var(--space-3);
  border-radius:var(--radius-sm);
}
.settings-multi-actions{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:0.25rem;
  margin-top:0.5rem;
}
textarea{
  padding:var(--space-5) var(--space-6);
  border:1px solid var(--border-strong);
  border-radius:var(--radius-2xl);
  background:var(--input-bg);
  color:var(--fg);
  min-width:0;
  min-height:100px;
  resize:vertical;
}
input:focus,select:focus,textarea:focus{
  outline:none;
  border-color:var(--link);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--link) 22%, transparent);
}
button{
  padding:var(--space-5) var(--space-7);
  border:none;
  border-radius:var(--radius-2xl);
  background:var(--btn);
  color:var(--btnfg);
  cursor:pointer;
}
button:hover{filter:brightness(1.05)}
button:disabled{opacity:.6;cursor:not-allowed}
.button-secondary{
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
  padding:var(--space-2) var(--space-4);
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  font-size:var(--font-size-sm);
  font-weight:500;
  cursor:pointer;
  text-decoration:none;
  background:var(--btn-secondary);
  color:var(--btn-secondary-fg);
}
.button-secondary:hover{filter:brightness(0.95)}
.button-danger{
  background:var(--danger);
  color:#fff;
}

.recovery-banner{
  background:var(--danger);
  color:#fff;
  text-align:center;
  padding:var(--space-4) var(--space-8);
  font-weight:700;
  font-size:var(--font-size-xl);
  position:sticky;
  top:0;
  z-index:var(--z-spinner);
}
.recovery-banner code{
  background:rgba(255,255,255,.2);
  padding:var(--space-1) var(--space-3);
  border-radius:var(--radius-xs);
}

.muted{color:var(--muted)}
.danger{color:var(--danger)}
.success{color:var(--success)}
.warning{color:var(--warn)}
.badge{
  display:inline-block;
  padding:3px var(--space-5);
  border:1px solid var(--border);
  border-radius:var(--radius-pill);
  font-size:var(--text-xs);
  background:var(--badge-bg);
}
.status-used{color:var(--success);font-weight:600}
.status-reserved{color:var(--warn);font-weight:600}
.status-free{color:var(--muted);font-weight:600}
.badge-network{background:color-mix(in srgb,var(--muted) 15%,var(--badge-bg) 85%);color:var(--muted);font-size:var(--text-xs);padding:2px 6px}
.badge-muted{background:color-mix(in srgb,var(--muted) 10%,var(--badge-bg) 90%);color:var(--muted);border-color:color-mix(in srgb,var(--muted) 30%,var(--border) 70%)}
.badge-success{background:color-mix(in srgb,var(--success) 12%,var(--badge-bg) 88%);color:var(--success);border-color:color-mix(in srgb,var(--success) 35%,var(--border) 65%)}
.badge-broadcast{background:color-mix(in srgb,var(--warn) 15%,var(--badge-bg) 85%);color:var(--warn);font-size:var(--text-xs);padding:2px 6px}
.badge-gateway{background:color-mix(in srgb,var(--link) 15%,var(--badge-bg) 85%);color:var(--link);font-size:var(--text-xs);padding:2px 6px}
.audit-details{display:inline-block;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom;cursor:pointer}
.audit-details.audit-details--expanded{max-width:none;white-space:normal;overflow-wrap:break-word;cursor:pointer}
.badge-role-admin{
  background:color-mix(in srgb,var(--danger) 12%,var(--badge-bg) 88%);
  color:var(--danger);
  border-color:color-mix(in srgb,var(--danger) 40%,var(--border) 60%);
}
.badge-role-netops{
  background:color-mix(in srgb,var(--link) 12%,var(--badge-bg) 88%);
  color:var(--link);
  border-color:color-mix(in srgb,var(--link) 40%,var(--border) 60%);
}
.badge-update{
  background:color-mix(in srgb,var(--warn) 12%,var(--badge-bg) 88%);
  color:var(--warn);
  border-color:color-mix(in srgb,var(--warn) 40%,var(--border) 60%);
}
/* Device type badges (v3.2.0) */
.badge-type-router{background:color-mix(in srgb,var(--link) 15%,var(--badge-bg) 85%);color:var(--link);border-color:color-mix(in srgb,var(--link) 40%,var(--border) 60%)}
.badge-type-switch{background:color-mix(in srgb,var(--success) 15%,var(--badge-bg) 85%);color:var(--success);border-color:color-mix(in srgb,var(--success) 40%,var(--border) 60%)}
.badge-type-server{background:color-mix(in srgb,var(--warn) 15%,var(--badge-bg) 85%);color:var(--warn);border-color:color-mix(in srgb,var(--warn) 40%,var(--border) 60%)}
.badge-type-vm{background:color-mix(in srgb,var(--muted) 25%,var(--badge-bg) 75%);color:var(--fg);border-color:var(--border)}
.badge-type-firewall{background:color-mix(in srgb,var(--danger) 15%,var(--badge-bg) 85%);color:var(--danger);border-color:color-mix(in srgb,var(--danger) 40%,var(--border) 60%)}
.badge-type-other{background:var(--badge-bg);color:var(--muted);border-color:var(--border)}
/* Compact nested table for device interfaces */
.table-compact td,.table-compact th{padding:4px var(--space-8);font-size:var(--text-sm)}
.device-ifaces h4{margin:0 0 var(--space-8);font-size:var(--text-sm);font-weight:600;color:var(--muted)}
.util-bar{
  display:inline-block;
  width:60px;
  height:8px;
  background:var(--border);
  border-radius:var(--radius-xs);
  overflow:hidden;
  vertical-align:middle;
  margin-left:var(--space-2);
}
.util-bar-fill{
  display:block;
  height:100%;
  background:var(--success);
  border-radius:var(--radius-xs);
  transition:width 400ms ease;
}
.util-bar-fill--warn{background:var(--warn)}
.util-bar-fill--crit{background:var(--danger)}

/* Site group collapse/expand */
.site-group-toggle{
  display:flex;
  align-items:center;
  width:100%;
  background:none;
  border:none;
  border-bottom:2px solid var(--border);
  padding:0 0 var(--space-3) 0;
  margin:0 0 var(--space-4) 0;
  cursor:pointer;
  font-size:1.05em;
  font-weight:600;
  color:var(--fg);
  text-align:left;
}
.site-group-toggle:hover{color:var(--link)}
.site-group-caret{
  margin-left:auto;
  font-size:.8em;
  transition:transform .15s ease;
  display:inline-block;
}
.site-group-toggle[aria-expanded="false"] .site-group-caret{transform:rotate(-90deg)}
.site-group-toggle[aria-expanded="false"]+.site-group-body{display:none}
.site-group-body{margin-left:var(--space-8)}

summary{
  cursor:pointer;
  padding:var(--space-2) 0;
}
details > summary{
  list-style:none;
}
details > summary::-webkit-details-marker{display:none}


.empty-state{
  padding:var(--space-9);
  border:1px dashed var(--border-strong);
  border-radius:var(--radius-4xl);
  color:var(--muted);
  background:color-mix(in srgb, var(--card) 80%, var(--bg) 20%);
}

.actions-inline{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-6);
  align-items:center;
}
.actions-inline a{
  display:inline-flex;
  align-items:center;
  padding:var(--space-3) var(--space-5);
  border-radius:var(--radius-xl);
  background:color-mix(in srgb, var(--card-2) 70%, transparent);
}
.actions-inline a:hover{
  background:var(--card-2);
  text-decoration:none;
}

.report-create{color:var(--success);font-weight:600}
.report-update{color:var(--link);font-weight:600}
.report-skip{color:var(--muted);font-weight:600}
.report-invalid{color:var(--danger);font-weight:600}
.report-needs-subnet{color:var(--warn);font-weight:600}

/* Admin notices (config updates, update-available banner) */
.admin-notice{
  display:flex;
  align-items:center;
  gap:var(--space-6);
  flex-wrap:wrap;
  padding:var(--space-5) var(--space-7);
  border-radius:var(--radius-2xl);
  margin-bottom:var(--space-7);
  border:1px solid var(--border);
  font-size:var(--font-size-3xl);
}
.admin-notice--info{
  background:color-mix(in srgb,var(--link) 8%,var(--card));
  border-color:color-mix(in srgb,var(--link) 30%,var(--border));
  color:var(--fg);
}
.admin-notice--update{
  background:color-mix(in srgb,var(--success) 8%,var(--card));
  border-color:color-mix(in srgb,var(--success) 30%,var(--border));
  color:var(--fg);
}
.admin-notice--danger{
  background:color-mix(in srgb,var(--danger) 8%,var(--card));
  border-color:color-mix(in srgb,var(--danger) 30%,var(--border));
  color:var(--fg);
}
.admin-notice--warning{
  background:color-mix(in srgb,var(--warn) 8%,var(--card));
  border-color:color-mix(in srgb,var(--warn) 40%,var(--border));
  color:var(--fg);
}
.admin-notice a{font-weight:600}
.admin-notice-dismiss{
  margin-left:auto;
  background:transparent;
  border:0;
  color:inherit;
  font-size:1.1em;
  cursor:pointer;
  padding:var(--space-1) var(--space-3);
  border-radius:var(--radius-md);
  opacity:.7;
}
.admin-notice-dismiss:hover{opacity:1;background:color-mix(in srgb,var(--fg) 10%,transparent)}

/* Scrollable table wrapper — wrap tables in this on narrow pages */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* Spacing / layout utility classes (replaces inline style="" attributes) */
.mt-6{margin-top:var(--space-3)}.mt-8{margin-top:var(--space-4)}.mt-10{margin-top:var(--space-5)}.mt-12{margin-top:var(--space-6)}
.mt-14{margin-top:var(--space-7)}.mt-16{margin-top:var(--space-8)}.mt-18{margin-top:18px}.mt-24{margin-top:var(--space-10)}
.mb-10{margin-bottom:var(--space-5)}.mb-12{margin-bottom:var(--space-6)}.mb-24{margin-bottom:var(--space-10)}
.ml-4{margin-left:var(--space-2)}.ml-12{margin-left:var(--space-6)}
.pb-6{padding-bottom:var(--space-3)}
.m-0{margin:0}
.label-inline{flex-direction:row;align-items:center;gap:var(--space-3)}
.gap-6{gap:var(--space-3)}.gap-8{gap:var(--space-4)}.gap-10{gap:var(--space-5)}.gap-12{gap:var(--space-6)}
.w-full{width:100%}.w-140{width:140px}.w-160{width:160px}.w-220{width:220px}
.mw-90{min-width:90px}.mw-140{min-width:140px}.mw-160{min-width:160px}.mw-200{min-width:200px}
.mw-220{min-width:220px}.mw-260{min-width:260px}.mw-420{min-width:420px}
.d-flex{display:flex}.d-inline{display:inline}.hidden{display:none}
.flex-1{flex:1}.flex-self-end{align-self:flex-end}
.flex-col{display:flex;flex-direction:column}
.flex-wrap{flex-wrap:wrap}
.align-center{align-items:center}
.text-center{text-align:center}
.fw-600{font-weight:600}
.cursor-pointer{cursor:pointer}
.nowrap{white-space:nowrap}
.opacity-70{opacity:.7}
.font-sm{font-size:.9em}
.font-xs{font-size:.85em;font-weight:400}
.pre-wrap{white-space:pre-wrap;margin:0}
.list-indent{margin:0 0 var(--space-6);padding-left:1.4em}
.key-display{word-break:break-all;font-size:var(--font-size-5xl)}
.link-plain{color:inherit;text-decoration:none}
/* SSO button and local-auth separator on login page */
.btn-sso{display:inline-block;padding:var(--space-5) 18px;border-radius:var(--radius-2xl);background:var(--btn);color:var(--btnfg);text-decoration:none;font-weight:600}
.sso-sep{margin:var(--space-7) 0 var(--space-2)}
/* Small button variant for inline admin-notice actions */
.btn-sm{padding:var(--space-2) var(--space-5);font-size:.85em}
/* New-key success card highlight */
.card--success{border-color:var(--success)}
/* Security warning banner */
.security-banner{display:flex;align-items:center;justify-content:space-between;gap:var(--space-6);flex-wrap:wrap;
  padding:var(--space-5) var(--space-7);margin-bottom:var(--space-8);border-radius:var(--radius-md);border:1px solid color-mix(in srgb,var(--warn) 40%,var(--border) 60%);
  background:color-mix(in srgb,var(--warn) 8%,var(--card) 92%);font-size:.9em}
.security-banner a.dismiss-link{white-space:nowrap;color:var(--muted);text-decoration:none;font-size:.85em}
.security-banner a.dismiss-link:hover{text-decoration:underline}
/* Footer metadata bar */
.footer-meta{display:flex;align-items:center;gap:var(--space-5);flex-wrap:wrap;max-width:1280px;margin:0 auto;padding:var(--space-5) var(--space-9)}
.footer-meta img{height:24px;width:auto;flex-shrink:0}
/* Full-width utilization bar (dashboard top-subnets table) */
.util-bar-block{background:var(--border);border-radius:var(--radius-sm);height:8px;overflow:hidden}
.util-bar-block>.util-bar-fill{border-radius:0;width:0}
/* Dynamic utilization bar fill — width set via data-pct attribute in app.js */
.util-bar-fill[data-pct]{width:0}
/* Subnet hierarchy node (indent is set dynamically via data-indent in app.js) */
.subnet-node{margin-top:var(--space-4)}
/* Demo gate standalone page */
.gate-wrap{max-width:480px;margin:var(--space-13) auto;padding:0 var(--space-8)}

/* Highlight row — used when linking to a specific address row */
.highlight-row{animation:highlight-fade 3s ease-out}
@keyframes highlight-fade{from{background:var(--warn)}to{background:inherit}}

/* Expired address row */
.expired-row td{background:rgba(176,0,32,.06)}
html[data-theme=dark] .expired-row td{background:rgba(255,80,80,.08)}
@media(prefers-color-scheme:dark){html:not([data-theme=light]) .expired-row td{background:rgba(255,80,80,.08)}}

/* DHCP pool inline-edit form */
.dhcp-edit-form{display:flex;gap:var(--space-4);flex-wrap:wrap;align-items:flex-end}
.dhcp-edit-form .ip-label{font-weight:600;align-self:center}
.dhcp-edit-form label{display:flex;flex-direction:column;font-size:var(--font-size-base)}
.dhcp-edit-form .btn-group{align-self:flex-end;display:flex;gap:var(--space-3)}
.dhcp-range-header td{font-size:var(--font-size-md);padding:var(--space-2) var(--space-3);background:var(--card)}
.d-inline-form{display:inline}

/* Mobile — 768px breakpoint */
@media (max-width: 768px){
  /* C2 / #954 — bump base body font-size to 16px on mobile. Two reasons:
     (a) prevents iOS Safari from auto-zooming when focusing a form input
     whose font-size is < 16px; (b) better readability on phones where
     the desktop's 14px default felt cramped. Only affects text that
     inherits from body without an explicit font-size — most components
     define their own --font-size-* token. */
  body{font-size:var(--text-base)}
  .page{padding:var(--space-7)}
  .footer-meta{padding:var(--space-4) var(--space-7)}
  .nav-wrap{
    padding:var(--space-5) var(--space-7);
    gap:var(--space-4);
  }
  .nav-links{gap:var(--space-3)}
  .nav-pill{padding:7px 9px;font-size:var(--font-size-2xl)}
  th,td{padding:var(--space-4) var(--space-5);font-size:var(--font-size-xl)}
  h1{font-size:var(--text-xl)}
  h2{font-size:var(--font-size-6xl)}
  .grid.cols-2,.grid.cols-3{
    grid-template-columns:1fr;
  }
  .metric .value{font-size:var(--font-size-7xl)}
  .row{flex-direction:column;align-items:stretch}
  .row > *{width:100%}
  .toolbar{flex-direction:column;align-items:stretch}
  .toolbar .spacer{display:none}
  .page-actions{flex-direction:column;align-items:stretch}
  table{font-size:var(--font-size-lg)}
  /* Prevent nav-right from jumping to new row; keep it inline */
  .nav-right{margin-left:auto}
  /* Reduce subnet tree indentation on small screens */
  .subnet-node{margin-left:0 !important;padding-left:var(--space-4);border-left:2px solid var(--border)}
}

/* Content padding reduction on narrow viewports */
@media (max-width: 767px){
  .page-content{padding:1rem}
}

/* Mobile — 480px breakpoint (small phones) */
@media (max-width: 480px){
  .page{padding:var(--space-5)}
  .footer-meta{padding:var(--space-3) var(--space-5)}
  .nav-wrap{padding:var(--space-4) var(--space-5)}
  .nav-pill{padding:var(--space-3) var(--space-4);font-size:var(--font-size-lg)}
  h1{font-size:var(--text-lg)}
  .card{padding:var(--space-6)}
  .metric{padding:var(--space-5) var(--space-6)}
  th,td{padding:var(--space-3) var(--space-4);font-size:var(--font-size-base)}
}

/* Import spinner overlay */
.spinner-overlay{
  position:fixed;top:0;left:0;width:100%;height:100%;
  background:rgba(0,0,0,.55);z-index:var(--z-page-overlay);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  color:#fff;font-size:var(--text-lg);gap:var(--space-8);
}
.spinner-overlay .spinner{
  width:48px;height:48px;border:5px solid rgba(255,255,255,.3);
  border-top-color:#fff;border-radius:50%;
  animation:spin .8s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---- Inline checkbox label (used in forms alongside other inputs) ---- */
.row-inline{display:flex;align-items:center;gap:var(--space-3);font-size:var(--font-size-xl);cursor:pointer;padding-bottom:var(--space-3);}
.row-inline input[type=checkbox]{width:16px;height:16px;cursor:pointer;flex-shrink:0;}

/* ---- settings.php row header (v2.7.0) ----
   .setting-head is the title line above an input: label text + source badge
   + key <code>. .setting-head--bool wraps the checkbox on the same line
   as the label so bool settings render inline with the control they toggle
   (see GitHub issue #441). Explicit flex-direction:row overrides the global
   `label { display:flex; flex-direction:column }` rule above, which would
   otherwise stack the checkbox and label on separate rows. */
.setting-head{display:flex;flex-direction:row;align-items:baseline;flex-wrap:wrap;gap:.25rem;margin-bottom:.25rem;}
label.setting-head{font-size:inherit;}
.setting-head--bool{cursor:pointer;align-items:center;}
.setting-head--bool input[type=checkbox]{margin:0 .25rem 0 0;flex-shrink:0;}

/* ---- Sticky table headers (#248, #342, #351, #352) ---- */
/* .table-wrap is the scroll container (overflow:auto; max-height:65vh).
   position:sticky on thead th with top:0 sticks the header to the top of the
   table-wrap scrollport. z-index:2 ensures th cells paint above tbody rows. */
thead th{position:sticky;top:0;z-index:var(--z-sticky);background:var(--card-2)}

/* ---- Mobile hamburger nav (#250) ---- */
.nav-toggle{
  display:none;
  background:none;border:none;cursor:pointer;
  font-size:var(--text-xl);color:var(--fg);padding:var(--space-2) var(--space-4);
  line-height:1;flex-shrink:0;
}
#nav-drawer{
  position:fixed;top:0;right:0;bottom:0;width:280px;max-width:90vw;
  background:var(--card);border-left:1px solid var(--border);
  z-index:var(--z-nav-drawer);overflow-y:auto;
  transform:translateX(100%);transition:transform .22s ease;
  display:flex;flex-direction:column;gap:0;padding:var(--space-8) 0;
  visibility:hidden;pointer-events:none;
}
body.nav-open #nav-drawer{transform:translateX(0);visibility:visible;pointer-events:auto}
.nav-drawer-overlay{
  display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:var(--z-nav-overlay);
}
body.nav-open .nav-drawer-overlay{display:block}
#nav-drawer .drawer-close{
  align-self:flex-end;background:none;border:none;cursor:pointer;
  font-size:var(--text-lg);color:var(--muted);padding:var(--space-2) var(--space-8) var(--space-6);
}
#nav-drawer a,#nav-drawer button.nav-drawer-btn{
  display:block;width:100%;text-align:left;background:none;border:none;cursor:pointer;
  color:var(--fg);padding:var(--space-5) var(--space-9);font-size:var(--font-size-4xl);text-decoration:none;
  border-radius:0;
}
#nav-drawer a:hover,#nav-drawer button.nav-drawer-btn:hover{background:var(--card-2)}
#nav-drawer .nav-drawer-section{padding:var(--space-2) var(--space-9);font-size:var(--font-size-sm);font-weight:700;
  color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:var(--space-4)}
#nav-drawer hr{border:none;border-top:1px solid var(--border);margin:var(--space-3) 0}
@media(max-width:600px){
  .nav-links{display:none}
  .nav-toggle{display:block}
  .card{overflow-x:auto}
}

/* ---- Inline status badge (#252) ---- */
.status-badge{display:inline-block;cursor:default}
.status-badge[data-addr-id]{cursor:pointer;user-select:none}
.status-badge[data-addr-id]:hover{opacity:.8;text-decoration:underline}
.status-badge.status-used{color:var(--success)}
.status-badge.status-reserved{color:var(--warn)}
.status-badge.status-free{color:var(--muted)}

/* Slide-in form-drawer (#247) was retired in v3.34.0 (#1243); all drawer
   styles now live under IpamDrawer's `.drawer` / `#global-drawer` rules. */

/* ---- Tag badges ---- */
/* #869: background fed via the --tag-bg custom property set on the inline
   style so the tag.colour value can never close the declaration or smuggle
   a second property. Falls back to var(--muted) if the variable is absent. */
.tag-badge{
  display:inline-block;padding:var(--space-1) var(--space-4);border-radius:var(--radius-xl);
  font-size:var(--font-size-sm);font-weight:600;color:#fff;white-space:nowrap;
  background:var(--tag-bg, var(--muted));
}
/* Darken text when badge is light-coloured (handled via inline style; default white) */
.tag-picker{display:flex;flex-wrap:wrap;gap:var(--space-3);margin:var(--space-2) 0;}
.tag-picker label{display:flex;align-items:center;gap:var(--space-2);cursor:pointer;font-size:var(--font-size-base);}
.tag-picker input[type=checkbox]{width:14px;height:14px;cursor:pointer;}


/* ---- Contact typeahead suggestions ---- */
.contact-suggestions{
  position:absolute;z-index:var(--z-nav-drawer);top:100%;left:0;right:0;
  background:var(--card);border:1px solid var(--border);border-radius:var(--radius-sm);
  margin:0;padding:0;list-style:none;max-height:200px;overflow-y:auto;
  box-shadow:0 4px 12px rgba(0,0,0,.15);
}
.contact-suggestions li{
  padding:7px var(--space-5);cursor:pointer;font-size:var(--font-size-xl);
  border-bottom:1px solid var(--border);
}
.contact-suggestions li:last-child{border-bottom:none}
.contact-suggestions li:hover{background:var(--btn);color:var(--btnfg);}

/* ---- Command palette ⌘K (#516) ---- */
.cmd-palette-bg {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.5);
    backdrop-filter: blur(4px);
    z-index: 300;
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding-top: 10vh;
}
.cmd-palette-bg.is-open { display: flex; }
.cmd-palette {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-2xl);
    width: min(560px, 90vw);
    box-shadow: 0 24px 64px rgba(0,0,0,.3);
    overflow: hidden;
}
.cmd-input-wrap { display: flex; align-items: center; gap: .5rem; padding: .75rem 1rem; border-bottom: 1px solid var(--border); }
.cmd-input { flex: 1; border: none; background: transparent; font-size: var(--text-md); color: var(--fg); outline: none; }
.cmd-results { max-height: 360px; overflow-y: auto; }
.cmd-group-label { padding: .375rem .75rem; font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.cmd-item { display: flex; align-items: center; gap: .625rem; padding: .5rem .75rem; cursor: pointer; font-size: var(--text-sm); color: var(--fg); }
.cmd-item:hover, .cmd-item.is-active { background: var(--btn); color: var(--btnfg); }
.cmd-empty { padding: .75rem 1rem; color: var(--muted); font-size: var(--text-sm); }
@media (prefers-reduced-motion: reduce) { .cmd-palette-bg { backdrop-filter: none; } }
/* ---- Dashboard widgets (#257) ---- */
.widget-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-3);}
.widget-header h2{margin:0;}
.widget-hide-btn{
  background:none;border:none;cursor:pointer;color:var(--muted);
  font-size:var(--font-size-4xl);padding:var(--space-1) var(--space-3);border-radius:var(--radius-sm);line-height:1;
}
.widget-hide-btn:hover{background:var(--border);color:var(--fg);}

/* ---- Column visibility (#256) ---- */
.col-hidden{display:none;}
.col-vis-wrap{position:relative;display:inline-block;}
.col-vis-gear{font-size:var(--font-size-md);}
.col-vis-drop{
  display:none;position:absolute;right:0;top:100%;z-index:var(--z-dropdown);
  background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:var(--space-4) var(--space-6);min-width:140px;box-shadow:0 4px 12px rgba(0,0,0,.15);
}
.col-vis-drop.visible{display:block;}
.col-vis-drop label{display:flex;align-items:center;gap:var(--space-3);padding:3px 0;cursor:pointer;font-size:var(--font-size-lg);white-space:nowrap;}

/* ---- Subnet map view (#255) ---- */
.subnet-view-btn{margin-left:var(--space-2);}
.subnet-view-btn.active{background:var(--btn);color:var(--btnfg);font-weight:600;}
.map-group{border-left:2px solid var(--border);padding-left:var(--space-5);margin-bottom:var(--space-9);}
.map-group-label{font-weight:600;margin-bottom:var(--space-4);color:var(--muted);}
.map-node{position:relative;}
.map-node-inner{
  display:flex;align-items:center;gap:var(--space-5);flex-wrap:wrap;
  padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);margin-bottom:3px;
  border-left:2px solid var(--border);
}
.map-node-inner:hover{background:rgba(0,0,0,.04);}
html[data-theme=dark] .map-node-inner:hover{background:rgba(255,255,255,.06);}
.map-cidr{font-weight:600;font-family:monospace;}
.map-desc{font-size:var(--font-size-base);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.map-util{display:flex;align-items:center;gap:5px;margin-left:auto;}
.map-util .util-bar{width:60px;}
.map-pct{font-size:var(--text-xs);min-width:30px;}
.map-cap{padding:var(--space-4) var(--space-6);color:var(--muted);font-style:italic;font-size:var(--font-size-xl);}

/* ---- Inline cell editing (#254) ---- */
td[data-editable]:hover{background:var(--btn);color:var(--btnfg);border-radius:var(--radius-xs);}
td[data-editable].cell-saving{opacity:.5;}
.inline-edit-input{
  width:100%;box-sizing:border-box;padding:var(--space-1) var(--space-2);font:inherit;
  background:var(--bg);color:var(--fg);border:1px solid var(--btn);border-radius:var(--radius-xs);
  outline:none;
}

.nav-kbd{
  font-size:var(--font-size-2xs);padding:1px 5px;
  border:1px solid currentColor;border-radius:var(--radius-xs);
  opacity:.55;vertical-align:middle;margin-left:var(--space-2);
  font-family:inherit;pointer-events:none;
}
.nav-search-link:hover .nav-kbd{opacity:.85;}

/* ── Tooltips (#354) ─────────────────────────────────────────────────────── */
/* JS renders a single shared #ipam-tooltip div at position:fixed so it is
   never clipped by overflow:hidden/clip on ancestor containers (.table-wrap). */
[data-tooltip]{ cursor:help; }
#ipam-tooltip{
  display:block;
  position:fixed;
  z-index:var(--z-toast);
  visibility:hidden;
  opacity:0;
  transition:opacity .15s;
  background:var(--fg);
  color:var(--bg);
  font-size:var(--font-size-sm);
  line-height:1.4;
  white-space:normal;
  max-width:240px;
  padding:5px 9px;
  border-radius:var(--radius-sm);
  text-align:center;
  pointer-events:none;
}
#ipam-tooltip.visible{
  visibility:visible;
  opacity:1;
}

/* ── Subnet stats placeholder (#565) ────────────────────────────────────── */
.subnet-stats-placeholder{display:inline-block;min-width:180px;height:1em;border-radius:var(--radius-xs);background:linear-gradient(90deg,var(--card-2) 25%,var(--border) 50%,var(--card-2) 75%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite}
@media(prefers-reduced-motion:reduce){.subnet-stats-placeholder{animation:none}}

/* ── Contact card popover (#561) ─────────────────────────────────────────── */
#contact-card{
  display:none;
  position:fixed;
  z-index:var(--z-dropdown);
  background:var(--card);
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  box-shadow:0 4px 16px rgba(0,0,0,.18);
  padding:var(--space-6) 34px var(--space-6) var(--space-7);
  max-width:320px;
  min-width:200px;
  font-size:var(--font-size-base);
  line-height:1.5;
}
#contact-card.visible{display:block}
.cc-name{font-weight:700;font-size:var(--font-size-xl);margin-bottom:var(--space-2)}
.cc-row{color:var(--muted);margin-top:var(--space-1);overflow-wrap:break-word}
.cc-row a{color:var(--link)}
.cc-label{font-weight:600;color:var(--fg);margin-right:var(--space-2)}
.contact-card-trigger{cursor:pointer}
.cc-close{position:absolute;top:var(--space-2);right:var(--space-2);background:none;border:none;cursor:pointer;font-size:var(--text-base);color:var(--muted);border-radius:var(--radius-sm);width:28px;height:28px;display:flex;align-items:center;justify-content:center;line-height:1;transition:color .15s,background .15s}
.cc-close:hover{color:var(--fg);background:color-mix(in srgb,var(--fg) 8%,transparent)}
.cc-close:focus-visible{outline:2px solid var(--link);outline-offset:2px}

/* ── Contact browse overlay (#562) ──────────────────────────────────────── */
.contact-browse-btn{
  background:var(--card);border:1px solid var(--border);border-radius:var(--radius-sm);
  cursor:pointer;padding:var(--space-1) var(--space-4);font-size:var(--font-size-sm);
  color:var(--link);vertical-align:middle;margin-left:var(--space-2);
}
.contact-browse-btn:hover{background:var(--btn);color:var(--btnfg)}
#contact-browse-overlay{
  display:none;position:fixed;inset:0;z-index:var(--z-col-vis);
  background:rgba(0,0,0,.45);align-items:flex-start;justify-content:center;
  padding-top:12vh;
}
#contact-browse-overlay.visible{display:flex}
.cb-box{
  width:min(480px,94vw);background:var(--card);border:1px solid var(--border);
  border-radius:var(--radius-lg);box-shadow:0 8px 32px rgba(0,0,0,.3);overflow:hidden;
  position:relative;
}
.cb-close{
  position:absolute;right:10px;top:10px;background:none;border:none;
  font-size:var(--text-xl);cursor:pointer;color:var(--muted);line-height:1;z-index:1;
}
#contact-browse-input{
  display:block;width:100%;box-sizing:border-box;
  padding:var(--space-7) var(--space-12) var(--space-7) var(--space-8);font-size:var(--text-base);
  background:var(--card);color:var(--fg);border:none;border-bottom:1px solid var(--border);outline:none;
}
#contact-browse-list{list-style:none;margin:0;padding:0;max-height:360px;overflow-y:auto}
.cb-item{padding:var(--space-5) var(--space-7);cursor:pointer;border-bottom:1px solid var(--border)}
.cb-item:last-child{border-bottom:none}
.cb-item:hover,.cb-item.active{background:var(--btn);color:var(--btnfg)}
.cb-item-name{font-weight:600}
.cb-item-meta{font-size:var(--font-size-sm);color:var(--muted)}
.cb-item:hover .cb-item-meta,.cb-item.active .cb-item-meta{color:inherit;opacity:.8}
.cb-empty{padding:var(--space-7) var(--space-8);color:var(--muted);text-align:center}


/* ---- CSP-safe utility classes (replaces JS inline style assignments) ---- */
.hidden{display:none !important;}
.d-inline{display:inline;}
.badge--success{background:var(--success);color:#0a1a0d;}
.card--warn{border-left:4px solid var(--warn);}
.th-sortable{cursor:pointer;}

/* Contact typeahead: parent needs position:relative for absolute dropdown */
.contact-typeahead-wrap{position:relative;}

/* Utilization bar widths via data-pct attribute (replaces JS el.style.width) */
.util-bar-fill[data-pct="0"]{width:0%}
.util-bar-fill[data-pct="1"]{width:1%}
.util-bar-fill[data-pct="2"]{width:2%}
.util-bar-fill[data-pct="3"]{width:3%}
.util-bar-fill[data-pct="4"]{width:4%}
.util-bar-fill[data-pct="5"]{width:5%}
.util-bar-fill[data-pct="6"]{width:6%}
.util-bar-fill[data-pct="7"]{width:7%}
.util-bar-fill[data-pct="8"]{width:8%}
.util-bar-fill[data-pct="9"]{width:9%}
.util-bar-fill[data-pct="10"]{width:10%}
.util-bar-fill[data-pct="11"]{width:11%}
.util-bar-fill[data-pct="12"]{width:12%}
.util-bar-fill[data-pct="13"]{width:13%}
.util-bar-fill[data-pct="14"]{width:14%}
.util-bar-fill[data-pct="15"]{width:15%}
.util-bar-fill[data-pct="16"]{width:16%}
.util-bar-fill[data-pct="17"]{width:17%}
.util-bar-fill[data-pct="18"]{width:18%}
.util-bar-fill[data-pct="19"]{width:19%}
.util-bar-fill[data-pct="20"]{width:20%}
.util-bar-fill[data-pct="21"]{width:21%}
.util-bar-fill[data-pct="22"]{width:22%}
.util-bar-fill[data-pct="23"]{width:23%}
.util-bar-fill[data-pct="24"]{width:24%}
.util-bar-fill[data-pct="25"]{width:25%}
.util-bar-fill[data-pct="26"]{width:26%}
.util-bar-fill[data-pct="27"]{width:27%}
.util-bar-fill[data-pct="28"]{width:28%}
.util-bar-fill[data-pct="29"]{width:29%}
.util-bar-fill[data-pct="30"]{width:30%}
.util-bar-fill[data-pct="31"]{width:31%}
.util-bar-fill[data-pct="32"]{width:32%}
.util-bar-fill[data-pct="33"]{width:33%}
.util-bar-fill[data-pct="34"]{width:34%}
.util-bar-fill[data-pct="35"]{width:35%}
.util-bar-fill[data-pct="36"]{width:36%}
.util-bar-fill[data-pct="37"]{width:37%}
.util-bar-fill[data-pct="38"]{width:38%}
.util-bar-fill[data-pct="39"]{width:39%}
.util-bar-fill[data-pct="40"]{width:40%}
.util-bar-fill[data-pct="41"]{width:41%}
.util-bar-fill[data-pct="42"]{width:42%}
.util-bar-fill[data-pct="43"]{width:43%}
.util-bar-fill[data-pct="44"]{width:44%}
.util-bar-fill[data-pct="45"]{width:45%}
.util-bar-fill[data-pct="46"]{width:46%}
.util-bar-fill[data-pct="47"]{width:47%}
.util-bar-fill[data-pct="48"]{width:48%}
.util-bar-fill[data-pct="49"]{width:49%}
.util-bar-fill[data-pct="50"]{width:50%}
.util-bar-fill[data-pct="51"]{width:51%}
.util-bar-fill[data-pct="52"]{width:52%}
.util-bar-fill[data-pct="53"]{width:53%}
.util-bar-fill[data-pct="54"]{width:54%}
.util-bar-fill[data-pct="55"]{width:55%}
.util-bar-fill[data-pct="56"]{width:56%}
.util-bar-fill[data-pct="57"]{width:57%}
.util-bar-fill[data-pct="58"]{width:58%}
.util-bar-fill[data-pct="59"]{width:59%}
.util-bar-fill[data-pct="60"]{width:60%}
.util-bar-fill[data-pct="61"]{width:61%}
.util-bar-fill[data-pct="62"]{width:62%}
.util-bar-fill[data-pct="63"]{width:63%}
.util-bar-fill[data-pct="64"]{width:64%}
.util-bar-fill[data-pct="65"]{width:65%}
.util-bar-fill[data-pct="66"]{width:66%}
.util-bar-fill[data-pct="67"]{width:67%}
.util-bar-fill[data-pct="68"]{width:68%}
.util-bar-fill[data-pct="69"]{width:69%}
.util-bar-fill[data-pct="70"]{width:70%}
.util-bar-fill[data-pct="71"]{width:71%}
.util-bar-fill[data-pct="72"]{width:72%}
.util-bar-fill[data-pct="73"]{width:73%}
.util-bar-fill[data-pct="74"]{width:74%}
.util-bar-fill[data-pct="75"]{width:75%}
.util-bar-fill[data-pct="76"]{width:76%}
.util-bar-fill[data-pct="77"]{width:77%}
.util-bar-fill[data-pct="78"]{width:78%}
.util-bar-fill[data-pct="79"]{width:79%}
.util-bar-fill[data-pct="80"]{width:80%}
.util-bar-fill[data-pct="81"]{width:81%}
.util-bar-fill[data-pct="82"]{width:82%}
.util-bar-fill[data-pct="83"]{width:83%}
.util-bar-fill[data-pct="84"]{width:84%}
.util-bar-fill[data-pct="85"]{width:85%}
.util-bar-fill[data-pct="86"]{width:86%}
.util-bar-fill[data-pct="87"]{width:87%}
.util-bar-fill[data-pct="88"]{width:88%}
.util-bar-fill[data-pct="89"]{width:89%}
.util-bar-fill[data-pct="90"]{width:90%}
.util-bar-fill[data-pct="91"]{width:91%}
.util-bar-fill[data-pct="92"]{width:92%}
.util-bar-fill[data-pct="93"]{width:93%}
.util-bar-fill[data-pct="94"]{width:94%}
.util-bar-fill[data-pct="95"]{width:95%}
.util-bar-fill[data-pct="96"]{width:96%}
.util-bar-fill[data-pct="97"]{width:97%}
.util-bar-fill[data-pct="98"]{width:98%}
.util-bar-fill[data-pct="99"]{width:99%}
.util-bar-fill[data-pct="100"]{width:100%}

/* Subnet list-view node indentation via data-indent (step 28px, depth 0–15) */
.subnet-node[data-indent="0"]{margin-left:0}
.subnet-node[data-indent="28"]{margin-left:28px}
.subnet-node[data-indent="56"]{margin-left:56px}
.subnet-node[data-indent="84"]{margin-left:84px}
.subnet-node[data-indent="112"]{margin-left:112px}
.subnet-node[data-indent="140"]{margin-left:140px}
.subnet-node[data-indent="168"]{margin-left:168px}
.subnet-node[data-indent="196"]{margin-left:196px}
.subnet-node[data-indent="224"]{margin-left:224px}
.subnet-node[data-indent="252"]{margin-left:252px}
.subnet-node[data-indent="280"]{margin-left:280px}
.subnet-node[data-indent="308"]{margin-left:308px}
.subnet-node[data-indent="336"]{margin-left:336px}
.subnet-node[data-indent="364"]{margin-left:364px}
.subnet-node[data-indent="392"]{margin-left:392px}
.subnet-node[data-indent="420"]{margin-left:420px}

/* Subnet map-view node indentation via data-indent (step 22px, depth 0–15) */
.map-node-inner[data-indent="0"]{margin-left:0}
.map-node-inner[data-indent="22"]{margin-left:22px}
.map-node-inner[data-indent="44"]{margin-left:44px}
.map-node-inner[data-indent="66"]{margin-left:66px}
.map-node-inner[data-indent="88"]{margin-left:88px}
.map-node-inner[data-indent="110"]{margin-left:110px}
.map-node-inner[data-indent="132"]{margin-left:132px}
.map-node-inner[data-indent="154"]{margin-left:154px}
.map-node-inner[data-indent="176"]{margin-left:176px}
.map-node-inner[data-indent="198"]{margin-left:198px}
.map-node-inner[data-indent="220"]{margin-left:220px}
.map-node-inner[data-indent="242"]{margin-left:242px}
.map-node-inner[data-indent="264"]{margin-left:264px}
.map-node-inner[data-indent="286"]{margin-left:286px}
.map-node-inner[data-indent="308"]{margin-left:308px}

/* --- #449: password show/hide eye-icon button --- */
/* Wraps a sensitive <input> + sibling .pw-toggle button. The button sits
   inside the right edge of the input; the input reserves padding-right so
   the typed value doesn't slide under the icon. The 36px right offset
   leaves room for password manager icons (1Password, Bitwarden) which
   paint at right:0–8px. */
.pw-wrap{position:relative;display:block}
.pw-wrap .pw-input{padding-right:76px}
.pw-toggle{position:absolute;right:36px;top:50%;transform:translateY(-50%);background:transparent;border:0;padding:var(--space-2);margin:0;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-sm)}
.pw-toggle:hover,.pw-toggle:focus{color:var(--fg);outline:none}
.pw-toggle:focus-visible{box-shadow:var(--focus-ring)}
.pw-eye{display:inline-block;vertical-align:middle}
.pw-eye--closed{display:none}
.pw-toggle[aria-pressed="true"] .pw-eye--open{display:none}
.pw-toggle[aria-pressed="true"] .pw-eye--closed{display:inline-block}
body.pw-toggle-hidden .pw-toggle{display:none}
/* CodeRabbit m3 (PR #450): keep right padding when the IPAM eye is hidden so
   the password manager icon at right:0-8px is not crowded against the typed
   value. The eye reservation drops from 76px (eye + PM icon) to 36px (PM
   icon only), not all the way to 8px. */
body.pw-toggle-hidden .pw-wrap .pw-input{padding-right:36px}

/* --- #317: keyboard shortcut hint badge --- */
.kbd-hint{display:inline-block;margin-left:0.4em;padding:0 0.35em;border:1px solid var(--border);border-radius:var(--radius-xs);font:0.78em/1.4 ui-monospace,Menlo,monospace;color:var(--muted);background:transparent;vertical-align:middle}

/* --- #507: loading state on POST form submit --- */
.button-loading{min-width:80px;position:relative;color:transparent !important}
.button-loading::after{content:"";position:absolute;left:50%;top:50%;width:16px;height:16px;margin:-8px 0 0 -8px;border:2px solid currentcolor;border-top-color:transparent;border-radius:50%;animation:spin .6s linear infinite}

/* --- #508: skeleton loaders for slow tables --- */
.skeleton-shell{padding:var(--space-8) 0}
.skeleton-row{height:18px;margin:var(--space-6) 0;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--card-2) 25%,var(--border) 50%,var(--card-2) 75%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite}
.skeleton-row:nth-child(odd){width:90%}
.skeleton-row:nth-child(even){width:70%}
@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
/* v3.25.0 #855: skeleton-toggle container. Ready state hides placeholder
   rows; loading state shows them. Markup: <div data-skeleton="loading">
   .skeleton-row siblings… </div>; JS flips data-skeleton to "ready" when
   the fetch resolves. */
[data-skeleton="ready"] .skeleton-row{display:none}
@media (prefers-reduced-motion:reduce){.skeleton-row{animation:none}}
/* v3.25.0 #847 #848 #851 #857 row badges + protected highlight */
.row-default{background:linear-gradient(90deg,var(--card-2) 0%,var(--card) 100%)}
.row-protected{box-shadow:inset 3px 0 0 var(--success)}
.badge-default{background:var(--badge-bg);color:var(--link);border:1px solid var(--link)}
.badge-protected{background:var(--success);color:#fff}
.badge-warn{background:var(--warn);color:#fff}
.badge-format-logical{background:var(--link);color:#fff}
.badge-format-database{background:var(--muted);color:var(--bg)}
.picker-backup-format,.picker-encryption-mode,.picker-retention{margin-top:var(--space-8)}
.grid-4{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:var(--space-6)}

/* --- #509: monospace font for IP/CIDR/MAC columns --- */
.ip-cell{font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.ip-badge{font-family:var(--font-mono);font-size:var(--font-size-base)}
.monospace{font-family:var(--font-mono)}

/* Contact picker (v3.0.0 #563) */
.contact-badge{background:var(--badge-bg);font-size:.85em;padding:2px 8px;border-radius:4px;white-space:nowrap}
.contact-badges{display:flex;flex-wrap:wrap;gap:4px}
.contact-picker-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.contact-picker-row select{min-width:200px}
.contact-picker-remove{min-width:32px;min-height:32px;padding:0;line-height:1}

/* --- Custom fields (v3.5.0 #313) --- */
.custom-field-group{margin-top:1rem;padding-top:0.75rem;border-top:1px solid var(--border)}
.custom-field-heading{font-size:var(--font-size-1);font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin:0 0 .5rem}
.custom-field-row{margin-bottom:.5rem}
.custom-field-row label{display:block}
.cf-required{color:var(--danger);margin-left:.15em;font-weight:700}

/* --- prefers-reduced-motion: suppress all animations/transitions --- */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:0.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.01ms !important;
    scroll-behavior:auto !important;
  }
}

/* --- Sparklines (v3.1.0 #311) --- */
.sparkline{display:inline-block;vertical-align:middle}
.sparkline polyline{stroke:var(--link);fill:none}

/* ── Dashboard chart empty state (v3.11.0 #644) ─────────────────────── */
.chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:180px;gap:var(--space-3)}
.chart-empty .icon{width:32px;height:32px;color:var(--muted);opacity:.5}
.chart-empty__msg{margin:0;color:var(--muted);font-size:var(--text-sm);text-align:center}
.chart-empty__cta{font-size:var(--text-sm);color:var(--link)}

/* ── Collapsible row toggle (v3.11.0 #632 #633) ─────────────────────── */
.collapsible-toggle{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;background:none;border:none;cursor:pointer;color:var(--muted);padding:0;border-radius:var(--radius-sm);flex-shrink:0}
.collapsible-toggle:hover{color:var(--fg);background:color-mix(in srgb,var(--border) 60%,transparent)}
.collapsible-toggle .icon{width:var(--icon-sm);height:var(--icon-sm);transition:transform 200ms ease}
.collapsible-toggle[aria-expanded="true"] .icon{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.collapsible-toggle .icon{transition:none}}
.collapsible-child--hidden{display:none}

/* ── Health dashboard status indicators (v3.7.0 #425) ───────────────── */
.health-dot{display:inline-block;width:10px;height:10px;border-radius:50%;flex-shrink:0;vertical-align:middle}
.health-dot.ok{background:var(--success)}
.health-dot.warn{background:var(--warn)}
.health-dot.crit{background:var(--danger)}
.health-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:1rem;margin-top:1.25rem}.health-grid>.card{align-self:stretch}
.health-card-header{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-bottom:1px solid var(--border);font-weight:600}
.health-row{display:flex;align-items:baseline;justify-content:space-between;gap:.75rem;padding:.45rem 1rem;border-bottom:1px solid var(--border);font-size:.9em}
.health-row:last-child{border-bottom:none}
.health-val{font-variant-numeric:tabular-nums;text-align:right;flex-shrink:0}
.health-label{color:var(--muted);flex:1}

/* ── TOTP enrollment (v3.6.0 #418) ──────────────────────────────────── */
.totp-qr-container{display:flex;flex-direction:column;align-items:center;gap:16px;padding:24px}
.totp-qr-container canvas{border:4px solid #fff;border-radius:8px}
.totp-secret-box{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--text-sm);background:var(--card);border:1px solid var(--border);border-radius:6px;padding:8px 12px;word-break:break-all;letter-spacing:.05em}
.totp-backup-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px;margin:16px 0}
.totp-backup-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--text-sm);background:var(--card);border:1px solid var(--border);border-radius:6px;padding:8px 12px;text-align:center;letter-spacing:.1em}

/* ===== Sidebar layout (v3.8.0 #512) ===================================== */
.layout-root{display:flex;min-height:100vh}
.layout-root--no-sidebar{display:block}
.layout-root--no-sidebar .layout-main{margin-left:0}
.sidebar{width:var(--sidebar-width,220px);background:var(--card);border-right:1px solid var(--border);display:flex;flex-direction:column;position:fixed;top:0;bottom:0;left:0;z-index:100;overflow-y:auto;transition:transform 200ms ease}
.sidebar-logo{display:flex;align-items:center;gap:.5rem;padding:1rem .75rem;border-bottom:1px solid var(--border);min-height:3.5rem}
.sidebar-logo-link{font-weight:700;font-size:var(--text-lg,1.125rem);color:var(--fg);text-decoration:none;display:flex;align-items:center;gap:.5rem;flex:1}
/* S9 + C6 / #958 — override the global a:hover{text-decoration:underline} and
   default :visited color on the sidebar brand link in both themes. Without
   these the brand link picks up an underline on hover and the OS-default
   visited color, which looks broken (especially in dark mode). */
.sidebar-logo-link:hover,
.sidebar-logo-link:focus{text-decoration:none;color:var(--fg)}
.sidebar-logo-link:visited{color:var(--fg)}
.sidebar-close{display:none;background:none;border:none;cursor:pointer;color:var(--muted);padding:.25rem;line-height:1}
.sidebar-nav{padding:.5rem 0;flex:1;display:flex;flex-direction:column}
.sidebar-group{padding:.25rem 0}
.sidebar-group+.sidebar-group{border-top:1px solid var(--border);margin-top:.25rem;padding-top:.5rem}
.sidebar-group--account{margin-top:auto;border-top:1px solid var(--border);padding-top:.5rem}
.sidebar-group-label{display:block;padding:.25rem .75rem;font-size:var(--text-xs,.6875rem);font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--muted)}
.sidebar-link{display:flex;align-items:center;gap:.5rem;padding:.4rem .75rem;font-size:var(--text-sm,.8125rem);color:var(--fg);text-decoration:none;border-radius:var(--radius-sm);margin:1px .375rem;cursor:pointer;transition:background 150ms ease,color 150ms ease;border:none;background:none;width:calc(100% - .75rem);text-align:left}
.sidebar-link:hover{background:var(--btn);color:var(--btnfg)}
.sidebar-link:focus-visible{outline:2px solid var(--link);outline-offset:2px}
.sidebar-link.is-active{background:var(--link);color:#fff}
.layout-main{flex:1;min-width:0;margin-left:var(--sidebar-width,220px);display:flex;flex-direction:column}
.page-content{flex:1;padding:1.5rem;max-width:1440px;width:100%}
.topbar--mobile{display:none;align-items:center;gap:.75rem;padding:.625rem 1rem;background:var(--card);border-bottom:1px solid var(--border);position:sticky;top:0;z-index:90}
.topbar-title{font-weight:600;font-size:var(--text-md,1rem);color:var(--fg)}
.hamburger{background:none;border:none;cursor:pointer;color:var(--fg);padding:.375rem;border-radius:var(--radius-sm);display:flex;align-items:center}
.hamburger:hover{background:var(--btn);color:var(--btnfg)}
.sidebar-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:99}
@media(max-width:1023px){
  .layout-main{margin-left:0}
  .topbar--mobile{display:flex}
  .sidebar{transform:translateX(-100%)}
  .sidebar.is-open{transform:translateX(0)}
  .sidebar-close{display:flex;align-items:center;justify-content:center}
  .sidebar-overlay.is-visible{display:block}
}

/* ===== KPI cards ===== */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.kpi-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-left: 3px solid transparent;
    border-radius: var(--radius-sm);
    padding: 1rem 1.25rem;
}

.kpi-card--warn { border-left-color: var(--warn); }
.kpi-card--crit { border-left-color: var(--danger); }

.kpi-label {
    font-size: var(--text-xs, .6875rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--muted);
    margin-bottom: .25rem;
}

.kpi-value {
    font-size: var(--text-2xl, 1.5rem);
    font-weight: 700;
    color: var(--fg);
    line-height: 1.1;
}

.kpi-sub {
    font-size: var(--text-xs, .6875rem);
    color: var(--muted);
    margin-top: .25rem;
}

/* ===== Dashboard chart section ===== */
.chart-section {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 1rem 1.25rem;
    margin-bottom: 1.5rem;
    overflow: hidden;
}

.chart-title {
    font-size: var(--text-sm, .8125rem);
    font-weight: 600;
    color: var(--muted);
    margin: 0 0 .75rem;
    text-transform: uppercase;
    letter-spacing: .05em;
}

/* uPlot reset — make it fill the container width */
#growth-chart .uplot,
#growth-chart .u-wrap { width: 100% !important; }
@media(prefers-reduced-motion:reduce){.sidebar{transition:none}}

/* ===== Global drawer (#517) ===== */
.drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(480px, 100vw);
    background: var(--card);
    border-left: 1px solid var(--border);
    z-index: 200;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 220ms ease-out;
    box-shadow: -4px 0 24px rgba(0,0,0,.12);
    outline: none;
}
.drawer.is-open { transform: translateX(0); }
.drawer-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.4);
    z-index: 199;
    display: none;
}
.drawer-overlay.is-visible { display: block; }
.drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.drawer-title { font-size: var(--text-md, 1rem); font-weight: 600; color: var(--fg); }
.drawer-close {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--muted);
    padding: .375rem;
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    line-height: 1;
}
.drawer-close:hover { background: var(--btn); color: var(--btnfg); }
.drawer-body { flex: 1; overflow-y: auto; padding: 1.25rem; }
.drawer-skeleton { display: flex; flex-direction: column; gap: .75rem; }
.drawer-skeleton-line {
    height: 1rem;
    background: var(--border);
    border-radius: var(--radius-sm);
    animation: drawer-pulse 1.4s ease-in-out infinite;
}
.drawer-skeleton-line--wide  { width: 100%; }
.drawer-skeleton-line--mid   { width: 70%; }
.drawer-skeleton-line--short { width: 40%; }
@keyframes drawer-pulse {
    0%, 100% { opacity: 1; }
    50%       { opacity: .4; }
}
@media (prefers-reduced-motion: reduce) {
    .drawer { transition: none; }
    .drawer-skeleton-line { animation: none; }
}

/* Data table */
.data-table-wrap { position: relative; }
.data-table { width: 100%; border-collapse: collapse; }
.data-table thead th {
    position: sticky;
    top: 0;
    background: var(--card);
    border-bottom: 2px solid var(--border);
    z-index: 10;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--muted);
    padding: .5rem .75rem;
    white-space: nowrap;
}
.data-table thead th.is-sorted { color: var(--link); }
.data-table thead th.is-sorted::after { content: ' \2191'; }
.data-table thead th.is-sorted.desc::after { content: ' \2193'; }
.data-table tbody tr { border-bottom: 1px solid var(--border); }
.data-table tbody tr:hover { background: rgba(0,0,0,.04); }
.data-table td { padding: .5rem .75rem; font-size: var(--text-sm); vertical-align: middle; }

/* Bulk action bar */
.bulk-bar {
    position: fixed;
    bottom: 1.5rem;
    left: 50%;
    transform: translateX(-50%);
    background: var(--fg);
    color: var(--bg);
    border-radius: var(--radius-2xl);
    padding: .625rem 1.25rem;
    display: flex;
    align-items: center;
    gap: 1rem;
    box-shadow: 0 8px 24px rgba(0,0,0,.25);
    z-index: 150;
    opacity: 0;
    pointer-events: none;
    transition: opacity 150ms ease;
}
.bulk-bar.is-visible { opacity: 1; pointer-events: all; }
.bulk-bar-count { font-size: var(--text-sm); font-weight: 600; }
@media (prefers-reduced-motion: reduce) { .bulk-bar { transition: none; } }

/* ===== Micro-interaction polish (#519) ===== */
button,.button,.action-pill,.button-danger,.button-secondary,.nav-pill{
    transition:background 150ms ease,color 150ms ease,box-shadow 150ms ease;
}
button:active,.button:active,.action-pill:active{transform:translateY(1px)}

.badge{transition:background 150ms ease,color 150ms ease}

.data-table thead th{transition:color 150ms ease}

/* Global focus ring — outline-based, overrides the earlier box-shadow-only rule */
:focus-visible{
    outline:2px solid var(--link);
    outline-offset:2px;
    border-radius:var(--radius-xs);
}

/* ===== Site filter strip (#629) ===== */
.site-filter-strip{
    display:flex;
    flex-wrap:wrap;
    align-items:center;
    gap:var(--space-2) var(--space-3);
    padding:var(--space-5) 0 var(--space-4);
    border-bottom:1px solid var(--border);
    margin-bottom:var(--space-6);
}
.site-filter-pill{
    display:inline-flex;
    align-items:center;
    gap:var(--space-2);
    padding:var(--space-2) var(--space-5);
    background:var(--btn-secondary);
    color:var(--btn-secondary-fg);
    border:1px solid var(--border);
    border-radius:var(--radius-pill);
    font-size:var(--font-size-sm);
    font-weight:500;
    cursor:pointer;
    white-space:nowrap;
    transition:background 150ms ease,color 150ms ease,border-color 150ms ease,box-shadow 150ms ease;
    line-height:1.4;
}
.site-filter-pill:hover{
    background:var(--btn);
    color:var(--btnfg);
    border-color:var(--btn);
}
.site-filter-pill--active,
.site-filter-pill[aria-pressed="true"]{
    background:var(--btn);
    color:var(--btnfg);
    border-color:var(--btn);
    box-shadow:0 0 0 2px var(--link);
}
.site-filter-pill--region{
    font-weight:600;
}
.site-filter-pill--child{
    font-size:var(--font-size-xs);
    padding:var(--space-1) var(--space-4);
}
.site-filter-region{
    display:flex;
    flex-wrap:wrap;
    align-items:center;
    gap:var(--space-2) var(--space-2);
}
.site-filter-region-children{
    display:flex;
    flex-wrap:wrap;
    gap:var(--space-2);
    transition:opacity 150ms ease;
}
.site-filter-region-children.is-collapsed{
    display:none;
}
.site-filter-caret{
    font-size:.7em;
    margin-left:var(--space-1);
    transition:transform .15s ease;
    display:inline-block;
}
.site-filter-pill[aria-expanded="false"] .site-filter-caret{
    transform:rotate(-90deg);
}
/* Hidden subnet nodes (filtered out) */
.subnet-node--filtered{
    display:none !important;
}
/* Hide site-group when all its subnet nodes are filtered */
.site-group--filter-empty{
    display:none !important;
}
/* uPlot cursor artifact fix (#648): fade cursor elements when chart loses hover */
#growth-chart .u-cursor-pt,
#growth-chart .u-cursor-x,
#growth-chart .u-cursor-y { transition:opacity .1s; }
#growth-chart:not(:hover) .u-cursor-pt,
#growth-chart:not(:hover) .u-cursor-x,
#growth-chart:not(:hover) .u-cursor-y { opacity:0; }
/* Pagination bar (#734) */
.pagination-bar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-3);margin-top:var(--space-5);padding-top:var(--space-4);border-top:1px solid var(--border)}
.pagination-controls{display:flex;align-items:center;gap:var(--space-3)}
.page-indicator{font-size:var(--font-size-sm);color:var(--muted)}

/* ── MFA card on Account page (#745, #755) ────────────────────────────── */
.mfa-card{padding:var(--space-9)}
.mfa-card__header{display:flex;align-items:flex-start;gap:var(--space-6);margin-bottom:var(--space-8);padding-bottom:var(--space-6);border-bottom:1px solid var(--border)}
.mfa-card__icon{width:28px;height:28px;color:var(--link);flex-shrink:0;margin-top:2px}
.mfa-card__lede{margin:var(--space-2) 0 0;font-size:var(--font-size-sm)}
.mfa-card__header h2{margin:0;font-size:var(--font-size-lg, 1.05rem)}
.mfa-method-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:0}
.mfa-method-row{
  display:grid;
  grid-template-columns:1fr auto auto;
  /* "extra" row is only used by the per-method passkey list (.mfa-passkey-list);
     TOTP and Email OTP rows leave it empty by design. (#758) */
  grid-template-areas:"lead pill actions" "hint hint hint" "extra extra extra";
  align-items:center;
  gap:var(--space-5) var(--space-6);
  padding:var(--space-7) 0;
  border-bottom:1px solid var(--border);
}
.mfa-method-row:last-child{border-bottom:none;padding-bottom:0}
.mfa-method-row:first-child{padding-top:0}
.mfa-method-row__lead{grid-area:lead;display:flex;align-items:flex-start;gap:var(--space-5);min-width:0}
.mfa-method-row__icon{width:24px;height:24px;color:var(--muted);flex-shrink:0;margin-top:2px}
.mfa-method-row__text{min-width:0}
.mfa-method-row__title{margin:0;font-size:var(--font-size-base);font-weight:600}
.mfa-method-row__desc{margin:var(--space-1) 0 0;color:var(--muted);font-size:var(--font-size-sm)}
.mfa-method-row__actions{grid-area:actions;display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-4);justify-content:flex-end}
.mfa-method-row__form{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-3);margin:0}
.mfa-method-row__pwlabel,.mfa-method-row__codelabel{
  display:flex;flex-direction:column;font-size:var(--font-size-xs);color:var(--muted);gap:var(--space-1);
}
.mfa-method-row__pwlabel input,.mfa-method-row__codelabel input{width:auto;min-width:160px}
.mfa-method-row__notice{font-size:var(--font-size-sm);color:var(--muted)}
.mfa-method-row__hint{
  grid-area:hint;
  display:flex;align-items:flex-start;gap:var(--space-3);
  margin:var(--space-3) 0 0;
  padding:var(--space-5) var(--space-6);
  background:color-mix(in srgb,var(--link) 6%,var(--card-2) 94%);
  border:1px solid color-mix(in srgb,var(--link) 25%,var(--border) 75%);
  border-radius:var(--radius-lg);
  color:var(--fg);
  font-size:var(--font-size-sm);
}
.mfa-method-row__hint-icon{width:18px;height:18px;color:var(--link);flex-shrink:0;margin-top:2px}

/* Status pills */
.mfa-method-pill{
  grid-area:pill;
  display:inline-flex;align-items:center;justify-content:center;
  padding:var(--space-2) var(--space-5);
  border-radius:var(--radius-2xl);
  border:1px solid var(--border);
  background:var(--badge-bg);
  color:var(--muted);
  font-size:var(--font-size-xs);
  font-weight:600;
  letter-spacing:.02em;
  white-space:nowrap;
}
.mfa-method-pill--enabled{background:color-mix(in srgb,var(--success) 15%,var(--badge-bg) 85%);color:var(--success);border-color:color-mix(in srgb,var(--success) 35%,var(--border) 65%)}
.mfa-method-pill--disabled{background:var(--badge-bg);color:var(--muted);border-color:var(--border)}
.mfa-method-pill--pending{background:color-mix(in srgb,var(--warn) 15%,var(--badge-bg) 85%);color:var(--warn);border-color:color-mix(in srgb,var(--warn) 35%,var(--border) 65%)}
/* Italic on tight-tracked --font-size-xs hurts dark-mode legibility (#758).
   Lean on color + border for the disabled-state cue instead. */
.mfa-method-pill--unavailable{background:color-mix(in srgb,var(--muted) 12%,var(--badge-bg) 88%);color:var(--muted);border-color:var(--border);font-weight:500}

/* Passkey credential list (nested under the passkey row) */
.mfa-passkey-list{grid-area:extra;list-style:none;padding:0;margin:var(--space-5) 0 0;display:flex;flex-direction:column;gap:var(--space-3)}
.mfa-passkey-list__item{display:flex;align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-5);background:var(--card-2);border:1px solid var(--border);border-radius:var(--radius-lg);flex-wrap:wrap}
.mfa-passkey-list__icon{width:18px;height:18px;color:var(--muted);flex-shrink:0}
.mfa-passkey-list__name{flex:1;min-width:0;font-size:var(--font-size-sm)}
.mfa-passkey-list__meta{font-size:var(--font-size-xs);margin-left:var(--space-2)}
.mfa-passkey-list__form{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;margin:0}
.mfa-passkey-list__pw{width:auto;min-width:160px}

/* Mobile: collapse the row to a stacked layout */
@media (max-width:640px){
  .mfa-method-row{
    grid-template-columns:1fr;
    grid-template-areas:"lead" "pill" "actions" "hint" "extra";
    align-items:flex-start;
    gap:var(--space-4);
  }
  .mfa-method-pill{justify-self:start}
  .mfa-method-row__actions{justify-content:flex-start;width:100%}
  .mfa-method-row__form{width:100%}
  .mfa-method-row__pwlabel input,.mfa-method-row__codelabel input,.mfa-passkey-list__pw{width:100%;min-width:0}
}

/* ── Settings page (#749, v3.16.0) — vertical-tab layout ─────────────── */

/* Settings page utility classes (#758) — replaces inline style="margin-…" in views/settings_group_form.php */
.settings-warning{margin-bottom:var(--space-6)}
.settings-row__badge{margin-left:var(--space-3)}
.settings-row__key{margin-left:var(--space-3)}
.settings-row__inline-help{margin-left:var(--space-3);font-size:.85em}
.settings-row__sub{margin-top:var(--space-2)}
.settings-row__actions{margin-top:var(--space-6)}

.settings-shell{
  display:grid;
  /* minmax allows the rail to shrink under the 220px target at narrow desktop widths
     (768–900px) so 'Data & Maintenance' / 'Authentication' labels stop wrapping
     mid-word. Floor of 180px keeps the rail readable. (#758) */
  grid-template-columns:minmax(180px,220px) 1fr;
  gap:var(--space-6,1.5rem);
  align-items:flex-start;
}
.settings-rail{
  position:sticky;
  top:1rem;
  background:var(--card);
  border:1px solid var(--border);
  border-radius:var(--radius-md,8px);
  padding:.5rem 0;
  align-self:flex-start;
}
.settings-rail__list{list-style:none;margin:0;padding:0}
.settings-rail__item{margin:0}
.settings-rail__link{
  display:block;
  padding:.5rem .75rem .5rem calc(.75rem - 3px);
  font-size:var(--text-sm,.875rem);
  color:var(--fg);
  text-decoration:none;
  border-left:3px solid transparent;
  transition:background 150ms ease,color 150ms ease,border-color 150ms ease;
}
.settings-rail__link:hover{background:var(--btn);color:var(--btnfg)}
.settings-rail__link:focus-visible{outline:2px solid var(--link);outline-offset:-2px}
.settings-rail__link.is-active,
.settings-rail__link[aria-current="page"]{
  border-left-color:var(--link);
  background:var(--card-2,var(--card));
  color:var(--fg);
  font-weight:600;
}
.settings-content{min-width:0}
.settings-content__title{margin:0 0 .25rem 0}
.settings-content__desc{margin:0 0 1rem 0}
.settings-group-title{margin-top:0}

.settings-mobile-nav{display:none;margin-bottom:1rem}
.settings-mobile-nav__label{display:block;font-weight:600;margin-bottom:.25rem;font-size:var(--text-sm,.875rem)}

@media (max-width:768px){
  .settings-shell{grid-template-columns:1fr}
  .settings-rail{display:none}
  .settings-mobile-nav{display:block}
}

/* === v3.21 backup_admin Backup tab run-now bar === */
.run-now-bar{
  display:flex;
  flex-wrap:wrap;
  gap:.75rem;
  align-items:flex-end;
  margin-top:.5rem;
}
.run-now-bar label{display:flex;flex-direction:column;gap:.25rem;font-size:var(--text-sm,.875rem);font-weight:600}

/* === v3.21 backup_admin tab bar === */
.tab-bar{
  border-bottom:1px solid var(--border);
  margin:0 0 1rem 0;
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
}
.tab-bar__list{
  list-style:none;
  margin:0;
  padding:0;
  display:flex;
  gap:.25rem;
  flex-wrap:nowrap;
}
.tab-bar__item{margin:0}
.tab-bar__link{
  display:inline-block;
  padding:.5rem .9rem;
  border:1px solid transparent;
  border-bottom:none;
  border-top-left-radius:var(--radius-md,8px);
  border-top-right-radius:var(--radius-md,8px);
  color:var(--fg);
  text-decoration:none;
  font-size:var(--text-sm,.875rem);
  white-space:nowrap;
  transform:translateY(1px);
}
.tab-bar__link:hover{background:var(--card)}
.tab-bar__link:focus-visible{outline:2px solid var(--link);outline-offset:-2px}
.tab-bar__link.is-active,
.tab-bar__link[aria-current="page"]{
  background:var(--card);
  border-color:var(--border);
  font-weight:600;
}

/* === v3.17 destinations + backup history === */
.destination-form, .schedule-form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-9);
    margin-top: var(--space-9);
}
.destination-form label, .schedule-form label {
    display: flex; flex-direction: column; gap: var(--space-4);
    font-weight: 500;
}
/* The display:flex above wins over the UA `[hidden]{display:none}` rule by
   specificity, so the JS frequency-field gating (#781) needs an explicit
   override to keep `el.hidden = true` actually hiding the label. */
.destination-form label[hidden], .schedule-form label[hidden] { display: none; }
.destination-form .checkbox { flex-direction: row; align-items: center; gap: var(--space-6); }
.destination-fields {
    grid-column: 1 / -1;
    border: 1px solid var(--border);
    padding: var(--space-9);
    border-radius: var(--radius-md);
    background: var(--card);
}
.destination-fields legend { font-weight: 600; padding: 0 var(--space-4); }
.badge-type-s3    { background: #fef3c7; color: #92400e; }
.badge-type-sftp  { background: #dbeafe; color: #1e40af; }
.badge-type-local { background: #d1fae5; color: #065f46; }
@media (prefers-color-scheme: dark) {
  .badge-type-s3    { background: #422006; color: #fde68a; }
  .badge-type-sftp  { background: #1e293b; color: #93c5fd; }
  .badge-type-local { background: #052e1f; color: #6ee7b7; }
}

/* v3.17 — destination test/run feedback state */
.button-success { background: color-mix(in srgb, var(--success) 15%, var(--card) 85%); color: var(--success); }

/* v3.17 backup history */
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--space-8); align-items: end; }
.filter-bar label { display: flex; flex-direction: column; gap: var(--space-2); }

/* v3.21.0 #804 — backup history filter chips */
.filter-chips { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-6); }
.filter-chip-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.filter-chip-label { font-size: var(--font-size-xs); color: var(--muted); min-width: 6rem; }
.filter-chip {
    display: inline-block;
    padding: var(--space-2) var(--space-5);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--card);
    color: var(--fg);
    text-decoration: none;
    font-size: var(--font-size-xs);
    line-height: 1.4;
}
.filter-chip:hover { border-color: var(--link); color: var(--link); }
.filter-chip.is-active {
    background: color-mix(in srgb, var(--link) 12%, var(--card));
    border-color: var(--link);
    color: var(--link);
    font-weight: 600;
}
.filter-chip-clear { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, var(--border)); }
.filter-chip-clear:hover { border-color: var(--danger); color: var(--danger); }
.badge-success          { background: color-mix(in srgb, var(--success) 15%, var(--card) 85%); color: var(--success); }
.badge-failed           { background: color-mix(in srgb, var(--danger) 15%, var(--card) 85%);  color: var(--danger); }
.badge-running          { background: color-mix(in srgb, var(--link) 15%, var(--card) 85%);    color: var(--link); }
.badge-retention_pruned { background: var(--card); color: var(--muted); }
.pagination { margin-top: var(--space-9); display: flex; flex-wrap: wrap; gap: var(--space-4); }
.pagination .is-active { font-weight: 700; }
.badge-restore { background: color-mix(in srgb, var(--warn) 15%, var(--card) 85%); color: var(--warn); }
.badge-backup  { background: color-mix(in srgb, var(--link) 15%, var(--card) 85%); color: var(--link); }

/* #803 — drawer body helpers + danger-zone confirm region */
.drawer-meta dl.kv-grid { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-6); margin: 0; }
.drawer-meta dl.kv-grid dt { color: var(--muted); }
.drawer-meta dl.kv-grid dd { margin: 0; }
.drawer-section { margin-top: var(--space-7); }
.drawer-section h4 { margin: 0 0 var(--space-3); font-size: var(--font-size-3xl); }
.drawer-error-text { white-space: pre-wrap; overflow-wrap: anywhere; word-break: normal; background: color-mix(in srgb, var(--danger) 6%, var(--card)); padding: var(--space-4); border-radius: var(--radius-sm); }
.drawer-error { padding: var(--space-6); border: 1px solid var(--danger); border-radius: var(--radius-md); background: color-mix(in srgb, var(--danger) 6%, var(--card)); }
.drawer-actions { margin-top: var(--space-9); display: flex; gap: var(--space-4); justify-content: flex-end; flex-wrap: wrap; }
.drawer-actions .button-danger:not(:disabled) { margin-left: auto; }
.drawer-action-result { margin-top: var(--space-6); padding: var(--space-4); border-radius: var(--radius-sm); }
.drawer-action-result.is-ok    { background: color-mix(in srgb, var(--success) 12%, var(--card)); color: var(--success); }
.drawer-action-result.is-error { background: color-mix(in srgb, var(--danger)  12%, var(--card)); color: var(--danger); }
.drawer-danger { margin-top: var(--space-7); padding: var(--space-6); border: 1px solid var(--danger); border-radius: var(--radius-md); background: color-mix(in srgb, var(--danger) 6%, var(--card)); }
.drawer-danger label { display: block; margin-bottom: var(--space-3); }
.drawer-danger input[type="text"] { width: 100%; }
.history-row { cursor: pointer; }
.history-row:hover { background: color-mix(in srgb, var(--link) 6%, transparent); }
.history-row:focus-visible { outline: 2px solid var(--link); outline-offset: -2px; }
