/* Branding mirrors Levirge Command (assets/css/ui/_ui-theme.css) — "Claude
   Desktop dark" warm clay chrome so Brain reads as one product with Command.

   BASE LAYER ONLY: reset, page grid, header/footer shell, nav, and shared
   primitives. Everything component-specific lives in
   assets/components/<name>/_<name>.css, inlined by the @imports at the end of
   this file (CssBuilder resolves relative @imports at build time).

   Design tokens are NOT defined here — they come from _tokens.css, a copy of
   the canonical design/tokens.css. Do not add a :root block to this file; add
   the token to design/tokens.css and re-copy. See design/STYLE-GUIDE.md. */

/* ─── Levirge canonical design tokens ─────────────────────────────────────────
   Single source of truth for all 5 UIs: app, admin, command, brain, agent-search.
   See design/STYLE-GUIDE.md for the name map, collisions, and adoption steps.

   Derived from app/assets/css/_ui-theme.css (the richest set — only one with a
   light mode, type scale, and dual shadows), with neutrals warmed to hue 48–60
   to match brain / command / agent-search. Values equal brain's hexes where the
   two families already agreed.

   Dark is default. Light via [data-theme="light"] on <html>.
   ponytail: no build step — repos copy this file and @import it. */

:root {
  /* ─── Neutrals — 3 required tiers + sidebar/hover/inset ───────────── */
  --bg-base: hsl(60 2% 12%); /* page canvas */
  --bg-sidebar: hsl(60 3% 10%); /* nav rail — below the canvas */
  --bg-surface: hsl(0 0% 15%); /* cards, panels */
  --bg-raised: hsl(60 3% 17%); /* selected rows, dropdowns */
  --bg-hover: hsl(60 3% 21%); /* one shade above resting */
  --bg-inset: hsl(60 3% 6%); /* tables, inputs, code blocks */

  /* ─── Borders — alpha overlays, so they work on any tier ──────────── */
  --line-1: hsl(0 0% 100% / 0.06); /* hairline, same-tier division */
  --line-2: hsl(0 0% 100% / 0.10); /* default border */
  --line-3: hsl(0 0% 100% / 0.18); /* emphasis / focus ring base */
  --top-highlight: hsl(0 0% 100% / 0.06); /* top edge of raised surfaces */

  /* ─── Foreground — 4 steps ────────────────────────────────────────── */
  --fg-0: hsl(48 12% 92%); /* headings */
  --fg-1: hsl(43 7% 70%); /* body */
  --fg-2: hsl(44 5% 52%); /* secondary / captions */
  --fg-3: hsl(44 4% 36%); /* disabled */

  /* ─── Brand accent — amber ────────────────────────────────────────── */
  --accent: oklch(0.731 0.132 73.9);
  --accent-hi: oklch(0.8 0.132 73.9); /* hover */
  --accent-soft: oklch(0.731 0.132 73.9 / 0.18); /* tinted fill */
  --accent-line: oklch(0.731 0.132 73.9 / 0.42); /* tinted border */
  /* Text/icon ON an accent fill. Tracks the canvas, so it stays readable in both
     modes: near-black on bright amber (dark), white on deep amber (light). */
  --accent-fg: var(--bg-base);
  --link: oklch(0.72 0.13 250);

  /* ─── Semantic status ─────────────────────────────────────────────── */
  --ok: oklch(0.74 0.13 150); /* was brain/command `--accent` */
  --warn: oklch(0.78 0.14 75);
  --error: oklch(0.7 0.18 18);
  --idle: hsl(44 4% 38%);
  --status-online: var(--ok);
  --status-degraded: var(--warn);
  --status-error: var(--error);
  --status-offline: var(--idle);
  --status-unknown: transparent;

  /* ─── Environment palette — 6 assignable hues ─────────────────────── */
  --env-slate: oklch(0.72 0.02 270);
  --env-cyan: oklch(0.72 0.13 220);
  --env-mint: oklch(0.78 0.14 160);
  --env-amber: oklch(0.8 0.14 78);
  --env-rose: oklch(0.7 0.18 18);
  --env-iris: oklch(0.74 0.13 290);

  --env-slate-soft: oklch(0.72 0.02 270 / 0.2);
  --env-cyan-soft: oklch(0.72 0.13 220 / 0.22);
  --env-mint-soft: oklch(0.78 0.14 160 / 0.22);
  --env-amber-soft: oklch(0.8 0.14 78 / 0.22);
  --env-rose-soft: oklch(0.7 0.18 18 / 0.22);
  --env-iris-soft: oklch(0.74 0.13 290 / 0.22);

  --env-slate-line: oklch(0.72 0.02 270 / 0.55);
  --env-cyan-line: oklch(0.72 0.13 220 / 0.6);
  --env-mint-line: oklch(0.78 0.14 160 / 0.6);
  --env-amber-line: oklch(0.8 0.14 78 / 0.6);
  --env-rose-line: oklch(0.7 0.18 18 / 0.6);
  --env-iris-line: oklch(0.74 0.13 290 / 0.6);

  /* ─── Syntax highlighting ─────────────────────────────────────────── */
  --syn-keyword: oklch(0.78 0.13 290);
  --syn-string: oklch(0.78 0.1 145);
  --syn-number: oklch(0.8 0.13 75);
  --syn-ident: var(--fg-0);
  --syn-comment: hsl(44 5% 44%);
  --syn-fn: oklch(0.82 0.1 290);

  /* ─── Shadows — always two layers: contact + ambient ──────────────── */
  --shadow-sm: 0 1px 2px hsl(0 0% 0% / 0.4), 0 4px 12px hsl(0 0% 0% / 0.22);
  --shadow-md: 0 1px 3px hsl(0 0% 0% / 0.45), 0 8px 24px hsl(0 0% 0% / 0.28);
  --shadow-lg: 0 2px 4px hsl(0 0% 0% / 0.5), 0 16px 40px hsl(0 0% 0% / 0.34);
  --shadow-inset: inset 0 2px 4px hsl(0 0% 0% / 0.32), inset 0 -1px 1px hsl(0 0% 100% / 0.04);
  --shadow-selected: inset 0 1px 0 hsl(0 0% 100% / 0.06), inset 0 -1px 0 hsl(0 0% 0% / 0.18);

  /* ─── Typography ──────────────────────────────────────────────────── */
  /* system-ui + "Segoe UI" are load-bearing on Windows — brain and
     agent-search both had them; app's stack did not. Superset of all three. */
  --font-sans:
    ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue",
        Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* Size scale — t-N = Npx / 16 rem */
  --t-11: 0.6875rem;
  --t-12: 0.75rem;
  --t-13: 0.8125rem;
  --t-14: 0.875rem; /* default body */
  --t-16: 1rem;
  --t-20: 1.25rem;
  --t-28: 1.75rem;

  /* ─── Radii ───────────────────────────────────────────────────────── */
  --r-2: 0.125rem;
  --r-4: 0.25rem;
  --r-6: 0.375rem;
  --r-8: 0.5rem;
  --r-12: 0.75rem; /* dialogs and large cards — .ui-dialog, onboarding panels */
  --r-pill: 624.9375rem;

  /* ─── Row heights — dense-UI rhythm ───────────────────────────────── */
  --row-tight: 1.5rem;
  --row: 1.75rem;
  --row-loose: 2rem;
}

/* ─── LIGHT MODE — white canvas, warm grey chrome ──────────────────────── */
[data-theme="light"] {
  --bg-base: hsl(0 0% 100%);
  --bg-sidebar: hsl(36 12% 95%);
  --bg-surface: hsl(36 12% 97%);
  --bg-raised: hsl(0 0% 100%);
  --bg-hover: hsl(36 16% 93%);
  --bg-inset: hsl(36 12% 91%);

  --line-1: hsl(30 18% 16% / 0.07);
  --line-2: hsl(30 18% 16% / 0.13);
  --line-3: hsl(30 18% 16% / 0.22);
  --top-highlight: hsl(0 0% 100% / 0.85);

  --fg-0: hsl(30 18% 10%);
  --fg-1: hsl(30 12% 24%);
  --fg-2: hsl(30 8% 40%);
  --fg-3: hsl(30 6% 56%);

  --accent: oklch(0.56 0.132 73.9);
  --accent-hi: oklch(0.48 0.14 73.9);
  --accent-soft: oklch(0.56 0.132 73.9 / 0.14);
  --accent-line: oklch(0.56 0.132 73.9 / 0.42);
  --link: oklch(0.52 0.15 250);

  --ok: oklch(0.55 0.15 150);
  --warn: oklch(0.62 0.15 68);
  --error: oklch(0.55 0.2 18);
  --idle: hsl(30 6% 60%);

  --env-slate: oklch(0.5 0.02 270);
  --env-cyan: oklch(0.55 0.14 220);
  --env-mint: oklch(0.55 0.15 155);
  --env-amber: oklch(0.62 0.16 72);
  --env-rose: oklch(0.55 0.2 18);
  --env-iris: oklch(0.5 0.16 290);

  --env-slate-soft: oklch(0.5 0.02 270 / 0.14);
  --env-cyan-soft: oklch(0.55 0.14 220 / 0.14);
  --env-mint-soft: oklch(0.55 0.15 155 / 0.14);
  --env-amber-soft: oklch(0.62 0.16 72 / 0.16);
  --env-rose-soft: oklch(0.55 0.2 18 / 0.14);
  --env-iris-soft: oklch(0.5 0.16 290 / 0.14);

  --env-slate-line: oklch(0.5 0.02 270 / 0.55);
  --env-cyan-line: oklch(0.55 0.14 220 / 0.55);
  --env-mint-line: oklch(0.55 0.15 155 / 0.55);
  --env-amber-line: oklch(0.62 0.16 72 / 0.6);
  --env-rose-line: oklch(0.55 0.2 18 / 0.55);
  --env-iris-line: oklch(0.5 0.16 290 / 0.55);

  --syn-keyword: oklch(0.5 0.16 290);
  --syn-string: oklch(0.45 0.13 150);
  --syn-number: oklch(0.55 0.14 60);
  --syn-comment: hsl(30 6% 56%);
  --syn-fn: oklch(0.42 0.18 290);

  --shadow-sm: 0 1px 2px hsl(30 18% 16% / 0.06), 0 6px 18px hsl(30 18% 16% / 0.06);
  --shadow-md: 0 1px 3px hsl(30 18% 16% / 0.08), 0 12px 32px hsl(30 18% 16% / 0.08);
  --shadow-lg: 0 2px 6px hsl(30 18% 16% / 0.1), 0 20px 48px hsl(30 18% 16% / 0.1);
  --shadow-inset: inset 0 2px 4px hsl(30 18% 16% / 0.1), inset 0 -1px 1px hsl(0 0% 100% / 0.5);
  --shadow-selected: inset 0 1px 0 hsl(0 0% 100% / 0.6), inset 0 -1px 0 hsl(30 18% 16% / 0.06);
}

/* ─── Icon filters — theme-aware tint for <img>-based SVG icons ────────── */
:root {
  --icon-filter-0: brightness(0) invert(1);
  --icon-filter-1: brightness(0) invert(1) opacity(0.74);
  --icon-filter-2: brightness(0) invert(1) opacity(0.51);
  --icon-filter-3: brightness(0) invert(1) opacity(0.34);
}
[data-theme="light"] {
  --icon-filter-0: brightness(0);
  --icon-filter-1: brightness(0) opacity(0.7);
  --icon-filter-2: brightness(0) opacity(0.48);
  --icon-filter-3: brightness(0) opacity(0.28);
}

/* ─── LEGACY ALIASES ──────────────────────────────────────────────────────
   Compatibility shims so an existing UI can adopt this file without a
   rewrite. MUST NOT be used in new code. Delete a block once its repo's CSS
   has been sed'd to canonical names.

   Two names could NOT be aliased — they mean different things in the two
   families and must be renamed at the call site on adoption:
     • `--accent`  — amber in app/admin, GREEN in brain/command/agent-search.
                     Green is now `--ok`.
     • `--line-2`  — mid border in app, STRONG border in brain/command/
                     agent-search. Their `--line-2` is now `--line-3`. */
:root {
  /* app */
  --bg-0: var(--bg-base);
  --bg-1: var(--bg-surface);
  --bg-2: var(--bg-raised);
  --bg-3: var(--bg-hover);
  --font-size-xs: var(--t-11);
  --font-size-sm: var(--t-12);
  --font-size-md: var(--t-14);
  --font-size-base: var(--t-16);
  --font-size-lg: var(--t-16);
  --font-size-xl: var(--t-20);
  --font-size-2xl: var(--t-28);
  --radius-xs: var(--r-2);
  --radius-sm: var(--r-4);
  --radius-md: var(--r-6);
  --radius-lg: var(--r-8);
  --radius-pill: var(--r-pill);
  --row-height-tight: var(--row-tight);
  --row-height: var(--row);
  --row-height-loose: var(--row-loose);
  --border-color: var(--line-2);
  --border-width: 0.0625rem;
  --border-radius: var(--r-8);
  --button-border-radius: var(--r-8);
  --icon-filter-primary: var(--icon-filter-0);
  --icon-filter-secondary: var(--icon-filter-1);
  --icon-filter-muted: var(--icon-filter-2);
  --icon-filter-disabled: var(--icon-filter-3);

  /* brain / command / agent-search */
  --bg: var(--bg-base);
  --sidebar: var(--bg-sidebar);
  --panel: var(--bg-surface);
  --panel-2: var(--bg-raised);
  --raised: var(--bg-raised);
  --code-bg: var(--bg-inset);
  --line: var(--line-2);
  --text: var(--fg-0);
  --muted: var(--fg-1);
  --faint: var(--fg-2);
  --brand: var(--accent);
  --clay: var(--accent-hi);
  --clay-soft: var(--accent-soft);
  --stuck: var(--error);
  --question: var(--link);

  /* agent-search — already aliased onto canonical semantics */
  --text-primary: var(--fg-0);
  --text-muted: var(--fg-1);
  --border: var(--line-2);
  --highlight: var(--accent);
}

/* NOT here, deliberately — product-specific semantic palettes stay in their own
   repo, because canonical cannot know how many values must stay mutually
   distinguishable:
     • command `--st-*` (issue statuses) — these render as ADJACENT kanban column
       borders and status buttons, so `planning` and `in_review` must not collapse
       to one hue. Canonical has a single violet (`--env-iris`); command needs two.
     • command `--agent`, brain `--km-*` (knowledge-map hues), admin `--topbar-h` /
       `--nav-w` (layout constants).
   Each lives in its own repo's CSS and may reference canonical tokens. */


*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html {
  font-size: 16px;
}
body {
  font: 1rem ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
  display: grid;
  grid-template-columns: 20rem 1fr;
  grid-template-rows: auto 1fr auto auto;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "drawer  main"
    "footer  footer";
  gap: 0.5rem;
  padding: 0.5rem;
  height: 100vh;
  overflow: hidden;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
.app-header {
  grid-area: header;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  gap: 0.45rem;
  padding: 0.2rem 0.5rem;
  /* Column 1 of the header subgrid (sidebar width): logo left, the Help and
     Settings icons right-aligned at its edge. */
  .brand-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
  }
  .brand-actions {
    display: grid;
    grid-auto-flow: column;
    align-items: center;
    gap: 0.15rem;

    a {
      display: grid;
      place-items: center;
      padding: 0.3rem;
      border-radius: 0.375rem;
      color: var(--muted);
      opacity: 0.5;
      transition: opacity 0.15s, color 0.15s, background 0.15s;

      &:hover {
        opacity: 1;
        color: var(--text);
        background: var(--raised);
      }
      &.active {
        opacity: 1;
        color: var(--text);
      }
    }

    .icon {
      display: block;
      width: 1.2rem;
      height: 1.2rem;
      background: currentColor;
      mask: no-repeat center / contain;
      &.icon-help {
        mask-image: url("/img/help.svg");
      }
      &.icon-settings {
        mask-image: url("/img/settings.svg");
      }
      &.icon-add {
        mask-image: url("/img/add.svg");
      }
    }
  }
  .brand {
    text-decoration: none;
    display: grid;
    grid-template-columns: 2rem 1fr;
    align-items: center;
    gap: 0.5rem;
    & > span {
      display: grid;
      grid-template-columns: auto 1fr;
      & > img {
        margin-top: 0.2rem;
      }
    }
  }
  & > section {
    display: grid;
    grid-template-columns: 1fr auto;
    justify-content: space-between;
    align-items: center;
    gap: 2rem;
  }
}

.app-header .brand-mark {
  height: 2rem;
  width: auto;
}
.app-header .brand-wordmark {
  display: grid;
  grid-template-columns: auto auto;
  height: 1.6rem;
  width: auto;
  font-size: 1.5rem;
  img {
    margin-top: 0.2rem;
    height: 1.6rem;
  }
}
.app-header .brand-sub {
  color: var(--muted);
  font-weight: 500;
  font-size: 1.4rem;
  line-height: 1.2;
  opacity: 0.5;
}
.app-footer {
  grid-area: footer;
  /* auto columns + space-between: children stay content-sized (a 1fr track
     would stretch ui-conn-status and spread its dot from its label). */
  display: grid;
  grid-auto-flow: column;
  justify-content: space-between;
  align-items: center;
  padding: 0.1rem 0.75rem;
  font-size: 0.72rem;
  color: var(--faint);
  .footer-link {
    color: var(--faint);
    text-decoration: none;
    &:hover {
      color: var(--clay);
    }
  }
}
::-webkit-scrollbar {
  width: 6px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--line-3);
  border-radius: 3px;
}
#sidebar {
  grid-area: sidebar;
  min-width: 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  /* bottom is closed by the flush ui-account-drawer below it */
  border-bottom: none;
  border-radius: 0.5rem 0.5rem 0 0;
  overflow: hidden;
  /* Stacked rows; the LAST child fills so its list scrolls internally. Sidebars
     hold 1–3 children (a component, or header + nav + component), hence the
     ladder — grid can't say "last row gets 1fr" without knowing the count. */
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  &:has(> :nth-child(2)) {
    grid-template-rows: auto minmax(0, 1fr);
  }
  &:has(> :nth-child(3)) {
    grid-template-rows: auto auto minmax(0, 1fr);
  }
}
/* Primary nav — lives in the header (Skills · Entities · Docs · Metrics). */
#page-nav {
  display: grid;
  grid-auto-flow: column;
  justify-content: end;
  align-items: center;
  gap: 0.15rem;
  a {
    padding: 0.4rem 0.8rem;
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--faint);
    text-decoration: none;
    border-radius: 0.375rem;
    border-bottom: 2px solid transparent;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
    &:hover {
      color: var(--text);
      background: var(--raised);
    }
    &.active {
      color: var(--text);
      border-bottom-color: var(--brand);
    }
    /* Icon-only nav entries (Help, Settings). The SVG is applied as a CSS mask
       so the glyph inherits the link's currentColor for hover/active states
       (Material Symbols, vendored in assets/img/ — no icon fonts). */
    &.nav-icon {
      padding: 0.4rem 0.5rem;
    }
    .icon {
      display: block;
      width: 1.2rem;
      height: 1.2rem;
      background: currentColor;
      mask: no-repeat center / contain;
      &.icon-settings {
        mask-image: url("/img/settings.svg");
      }
      &.icon-help {
        mask-image: url("/img/help.svg");
      }
      &.icon-hub {
        mask-image: url("/img/hub.svg");
      }
      &.icon-cached {
        mask-image: url("/img/cached.svg");
      }
    }
  }
}
#main {
  grid-area: main;
  overflow-y: auto;
  padding: 1.5rem 2rem;
}
/* Shared primitives — any component may render these states. */
.loading {
  color: var(--faint);
  font-size: 0.85rem;
  padding: 2rem 0;
}
.error {
  color: var(--stuck);
  font-size: 0.85rem;
  padding: 1rem 0;
}
/* Sidebar placeholder for pages with no list (Metrics, Ask) — page templates
   render this directly; no component owns it. */
.sidebar-empty {
  padding: 1rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--faint);
}
/* Settings page wrapper — lives on <main> in the _page-settings-* templates.
   Left-aligned (not centred) and wider than before, but still capped: long
   measure hurts the link-card and metrics grids more than the extra room
   helps. */
.settings-page {
  max-width: 84rem;
  margin: 0;
  padding: 1.5rem;
  display: grid;
  gap: 1.5rem;
}
/* Sign-in page — standalone SSR template (templates/login.eta), no app chrome.
   The .brand styles above are scoped to .app-header, so the card carries its
   own sizing for the same marks. */
#login-page {
  min-height: 100vh;
  display: grid;
  /* The base `body` rule is the app-shell grid (20rem sidebar + named areas);
     this page has no chrome, so reset all three template axes or the card
     lands in the sidebar column. */
  grid-template-columns: 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas: none;
  place-items: center;
  background: var(--bg);

  .login-card {
    display: grid;
    justify-items: center;
    gap: 0.75rem;
    width: 24rem;
    max-width: 92vw;
    padding: 2.5rem 2rem 2rem;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 0.75rem;
  }
  .login-logo {
    height: 3rem;
    width: auto;
    margin-bottom: 0.35rem;
  }

  h1 {
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--text);
  }
  .login-providers {
    display: grid;
    gap: 0.6rem;
    width: 100%;
  }
  .login-provider {
    display: grid;
    grid-auto-flow: column;
    justify-content: center;
    align-items: center;
    gap: 0.6rem;
    padding: 0.65rem 1rem;
    border: 1px solid var(--line-2);
    border-radius: 0.45rem;
    background: var(--raised);
    color: var(--text);
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color 0.15s ease, background 0.15s ease;

    &:hover {
      border-color: var(--brand);
      background: var(--panel);
    }
    .provider-logo {
      height: 1.15rem;
      width: 1.15rem;
    }
  }

  .login-foot {
    font-size: 0.85rem;
    color: var(--muted);
    a {
      color: var(--brand);
      text-decoration: underline dotted;
      &:hover {
        text-decoration: underline;
      }
    }
  }

  /* Mirrors the Levirge Search sign-in footer: product + version left, © right. */
  .login-footer {
    justify-self: stretch;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    padding: 0.5rem 1rem;
    font-size: 0.8rem;
    color: var(--muted);
    a {
      color: var(--muted);
      text-decoration: none;
      &:hover {
        color: var(--brand);
      }
    }
  }
}

/* Section sidebar navs — SSR partials (_settings-nav.eta, _profile-nav.eta, _help-nav.eta),
   mirroring the main sidebar list look. */
#settings-nav-header,
#profile-nav-header,
#help-nav-header {
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 1rem 1rem 0.5rem;
  color: var(--faint);
}
#settings-nav,
#profile-nav,
#help-nav {
  display: grid;
  align-content: start;
  padding: 0.25rem 0;
  a {
    padding: 0.45rem 1rem;
    border-left: 3px solid transparent;
    font-size: 0.875rem;
    color: var(--muted);
    text-decoration: none;
    transition: all 0.15s ease;
    &:hover {
      background: var(--raised);
      color: var(--text);
    }
    &.active {
      background: var(--raised);
      border-left-color: var(--brand);
      color: var(--text);
    }
    /* Nested nav entries (e.g. per-agent MCP pages under "MCP Setup"). */
    &.sub {
      padding-left: 2rem;
      font-size: 0.82rem;
      color: var(--faint);
      &:hover,
      &.active {
        color: var(--text);
      }
    }
  }
}
/* Help page body — static SSR content. */
#help-body {
  max-width: 720px;
  a {
    color: var(--link);
  }
  /* Agent picker cards on the MCP Setup landing. */
  .help-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 0.75rem;
    margin: 0.5rem 0 1rem;
    a {
      display: grid;
      gap: 0.25rem;
      padding: 0.9rem 1rem;
      background: var(--panel);
      border: 1px solid var(--line);
      border-radius: 0.5rem;
      text-decoration: none;
      transition: background 0.15s, border-color 0.15s;
      &:hover {
        background: var(--raised);
        border-color: var(--line-3);
      }
      strong {
        color: var(--text);
        font-size: 0.95rem;
      }
      span {
        color: var(--muted);
        font-size: 0.8rem;
      }
    }
  }
  h3 {
    font-size: 1rem;
    font-weight: 600;
    margin: 1rem 0 0.5rem;
    color: var(--text);
  }
  p,
  li {
    color: var(--muted);
  }
  ul,
  ol {
    margin: 0 0 0.75rem 1.25rem;
  }
  li {
    margin-bottom: 0.35rem;
  }
  .first-steps {
    display: grid;
    gap: 0.45rem;
    margin-left: 0;
    list-style-position: inside;
    li {
      border: 1px solid var(--line);
      border-radius: 0.4rem;
      background: var(--panel);
      padding: 0.55rem 0.7rem;
    }
  }
  strong {
    color: var(--text);
  }
  table {
    width: 100%;
    border-collapse: collapse;
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    th {
      text-align: left;
      color: var(--text);
      font-weight: 600;
    }
    th,
    td {
      padding: 0.4rem 0.6rem;
      border: 1px solid var(--line);
      color: var(--muted);
      vertical-align: top;
    }
  }
  code {
    background: var(--raised);
    padding: 0.1em 0.35em;
    border-radius: 3px;
    font-size: 0.85em;
    font-family: "SF Mono", "Fira Code", monospace;
    color: var(--clay);
  }
  pre {
    background: var(--code-bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 0.75rem 1rem;
    overflow-x: auto;
    margin: 0 0 0.75rem;
    font-size: 0.82rem;
    line-height: 1.5;
    code {
      background: none;
      padding: 0;
      color: var(--text);
    }
  }
}
@media (max-width: 640px) {
  body {
    grid-template-columns: 180px 1fr;
  }
  #sidebar {
    width: auto;
    min-width: 0;
  }
  #main {
    padding: 1rem;
  }
}

/* Shared primitive: YAML frontmatter block emitted by renderMarkdown()
   (assets/js/lib/_markdown.ts) — appears wherever markdown renders (docs,
   skills, entities, ask answers), so it lives in the base layer. Inset like
   code blocks: bg-base tier + inset shadow, no outer elevation. */
.md-frontmatter {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.125rem 0.75rem;
  margin: 0 0 1rem;
  padding: 0.6rem 0.8rem;
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: 0.375rem;
  box-shadow: inset 0 1px 3px hsl(0 0% 0% / 0.25);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.78rem;
  line-height: 1.5;
}
.md-frontmatter .fm-key {
  color: var(--brand);
  white-space: nowrap;
}
.md-frontmatter .fm-val {
  color: var(--muted);
  overflow-wrap: anywhere;
}
.md-frontmatter .fm-raw {
  grid-column: 1 / -1;
  color: var(--muted);
  white-space: pre-wrap;
}

/* Home landing hero (placeholder main; sidebar is the vault-nav rail). */
.home-hero {
  max-width: 48rem;
  margin: 0 auto;
  padding-top: 2rem;
}
.home-hero h1 {
  font-size: 1.6rem;
  font-weight: 650;
}
.home-hero p {
  color: var(--muted);
  font-size: 0.95rem;
  margin-top: 0.5rem;
  line-height: 1.6;
}

/* ── Components (inlined by CssBuilder at build time) ─────────────────── */

/* ui-table — shared results-table pattern, ported from the app repo's
   ui-table component (app/assets/components/ui-table). CSS-only: consumers
   put class="ui-table" on a container, declare grid-template-columns ONCE on
   it, and use this structure:

     <div class="ui-table">
       <header class="ui-table-header"><div class="row"><span class="cell">…</span></div></header>
       <main class="ui-table-body [rows-zebra]"> …<div class="row"><span class="cell">…</span></div> </main>
       <footer class="ui-table-footer">…</footer>   (optional)
     </div>

   Columns flow to every row via subgrid, so header and body can never drift.
   The table is a rows grid (auto 1fr auto): it fills its container and ONLY
   the body scrolls. */

.ui-table {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    min-height: 0;
    overflow: hidden;

    .ui-table-header,
    .ui-table-body,
    .ui-table-footer,
    .row {
        display: grid;
        grid-column: 1 / -1;
        grid-template-columns: subgrid;
    }

    .ui-table-header {
        color: var(--faint);
        font-weight: 500;
        border-bottom: 1px solid var(--line);
    }

    .ui-table-body {
        align-content: start;
        overflow-y: auto;
        min-height: 0;

        .row {
            border-bottom: 1px solid var(--line);
        }
        &.rows-zebra .row:nth-child(even) {
            background: hsl(0 0% 100% / 0.03);
        }
    }

    .row {
        align-items: center;

        .cell {
            padding: 0.4rem 0.5rem;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;

            &.num {
                text-align: right;
                font-variant-numeric: tabular-nums;
            }
            &.actions {
                text-align: right;
            }
        }
    }
}



/* Header query bar. Customized built-in (<form is="ui-search-bar">) — scoped
   under form[is=…] per the component convention. The form IS the single bordered
   element: [mode | input | vault | submit] read as one control, divided by
   internal hairlines rather than four separate outlines. */

form[is="ui-search-bar"] {
    display: grid;
    /* mode | input | ⌘K hint | vault | submit */
    grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    align-items: stretch;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 0.375rem;
    overflow: hidden; /* clips child corners to the shared radius */

    &:focus-within {
        border-color: var(--brand);
    }

    /* Segments: no own border/radius/background — the form owns those. */
    input[type="text"],
    select {
        min-width: 0;
        background: transparent;
        color: var(--text);
        border: none;
        border-radius: 0;
        font-family: inherit;

        &:focus {
            outline: none;
        }
    }

    input[type="text"] {
        padding: 0.5rem 0.9rem;
        font-size: 1rem;
        border-left: 1px solid var(--line); /* divider: mode | input */
    }

    select {
        padding: 0.5rem 0.6rem;
        font-size: 0.85rem;
        cursor: pointer;
    }

    /* ⌘K affordance. Hidden once the bar has focus — you are already here, and
       it would sit under the caret on a long query. */
    .query-hint {
        align-self: center;
        margin-right: 0.4rem;
        padding: 0.1rem 0.35rem;
        border: 1px solid var(--line);
        border-radius: 0.25rem;
        color: var(--faint);
        background: var(--bg);
        font-family: inherit;
        font-size: 0.68rem;
        white-space: nowrap;
        pointer-events: none;
    }

    &:focus-within .query-hint {
        visibility: hidden;
    }

    /* Mode picker — customizable <select> (Chromium `appearance: base-select`,
       verified in Chrome 148; Brain is a Chromium internal tool). Options carry
       an icon + label; the closed button clones only the icon via
       <selectedcontent>, so it reads icon-only shut, icon + label open. */
    .query-mode {
        padding: 0;

        /* Label is for the open list only — the closed button shows the icon. */
        selectedcontent .mode-label { display: none; }

        option {
            display: grid;
            grid-template-columns: auto minmax(0, 1fr);
            align-items: center;
            gap: 0.5rem;
            padding: 0.4rem 0.5rem;
            border-radius: 0.3rem;
            color: var(--muted);
            font-size: 0.85rem;

            &:hover, &:checked { background: var(--raised); color: var(--text); }

            /* Native checkmark column — the icon is the affordance here. */
            &::checkmark { display: none; }
        }

        .icon {
            display: block; /* inline spans ignore width/height */
            width: 1.1rem;
            height: 1.1rem;
            background: currentColor;
            mask: no-repeat center / contain;

            &.icon-chat { mask-image: url("/img/chat-bubble.svg"); }
            &.icon-search { mask-image: url("/img/search.svg"); }
        }
    }

    /* Long vault names truncate rather than widen the bar. */
    .query-vault {
        max-width: 10rem;
        padding: 0;
        border-left: 1px solid var(--line); /* divider: input | vault */

        selectedcontent {
            display: block;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        option {
            padding: 0.4rem 0.5rem;
            border-radius: 0.3rem;
            color: var(--muted);
            font-size: 0.85rem;

            &:hover, &:checked { background: var(--raised); color: var(--text); }
            &::checkmark { display: none; }
        }
    }

    /* ── Chevrons ─────────────────────────────────────────────────────────
       One glyph for every dropdown in the bar: both selects run
       `appearance: base-select` so the UA arrow becomes a styleable
       ::picker-icon, which we replace with the same masked expand_more used by
       the account drawer caret. Muted at half opacity, full on hover. */
    .query-mode,
    .query-vault {
        appearance: base-select;
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: center;

        &::picker(select) {
            appearance: base-select;
            margin-top: 0.25rem;
            padding: 0.25rem;
            border: 1px solid var(--line-2);
            border-radius: 0.45rem;
            background: var(--panel);
        }

        &::picker-icon {
            content: "";
            align-self: center;
            width: 1rem;
            height: 1rem;
            margin-right: 0.5rem;
            background: var(--muted);
            mask: url("/img/expand-more.svg") no-repeat center / contain;
            opacity: 0.5;
            transition: opacity 0.15s, background 0.15s;
        }

        &:hover::picker-icon { opacity: 1; background: var(--text); }

        & > button {
            display: grid;
            grid-auto-flow: column;
            justify-content: start;
            align-items: center;
            min-width: 0;
            padding: 0.5rem 0.35rem 0.5rem 0.7rem;
            border: none;
            background: transparent;
            color: var(--muted);
            font-size: 0.85rem;
            font-family: inherit;
            cursor: pointer;

            &:hover { color: var(--text); }
        }
    }

    /* Right cap: brand fill is its own visual divider — no hairline needed. */
    button[type="submit"] {
        background: var(--brand);
        color: var(--bg-base);
        border: none;
        border-radius: 0;
        padding: 0.4rem 1.1rem;
        font-size: 0.85rem;
        font-weight: 600;
        cursor: pointer;
        transition: opacity 0.15s;

        &:hover {
            opacity: 0.9;
        }

        &:disabled {
            opacity: 0.5;
            cursor: default;
        }
    }
}



ui-vault-nav {
    display: grid;
    align-content: start;
    overflow-y: auto;

    header {
        padding: 1rem 1rem 0.5rem;

        h2 {
            font-size: 0.8rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.08em;
            color: var(--faint);
        }

        span {
            display: block;
            color: var(--faint);
            font-size: 0.76rem;
            text-transform: none;
            letter-spacing: normal;
        }
    }

    ul {
        display: grid;
        align-content: start;
        padding: 0.25rem 0;
    }

    a {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        gap: 0.5rem;
        padding: 0.45rem 1rem;
        border-left: 3px solid transparent;
        font-size: 0.875rem;
        color: var(--muted);
        text-decoration: none;
        transition: all 0.15s ease;

        span {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        &:hover {
            background: var(--raised);
            color: var(--text);
        }
    }

    .vault-nav-avatar,
    .vault-nav-ph {
        width: 1.2rem;
        height: 1.2rem;
        border-radius: 0.25rem;
        flex-shrink: 0;
    }

    .vault-nav-avatar { object-fit: cover; }

    .vault-nav-ph {
        display: grid;
        place-items: center;
        background: var(--raised);
        color: var(--faint);
        font-size: 0.6rem;
        font-weight: 650;
    }

    /* class display: grid beats the UA [hidden] rule — restore it so the
       placeholder never shows alongside a real avatar. */
    .vault-nav-avatar[hidden],
    .vault-nav-ph[hidden] { display: none; }

    .vault-nav-label {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .vault-nav-count {
        flex-shrink: 0;
        color: var(--faint);
        font-size: 0.68rem;
        font-variant-numeric: tabular-nums;
    }

    .vault-nav-empty {
        padding: 0.45rem 1rem;
        color: var(--faint);
        font-size: 0.8rem;
    }
}



ui-home {
    display: grid;
    gap: 1rem;
    max-width: 72rem;
    margin: 0 auto;

    .panel {
        border: 1px solid var(--line);
        background: var(--panel);
        border-radius: 0.45rem;
        padding: 0.9rem;
    }

    .home-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: baseline;
        margin-bottom: 0.7rem;

        h2 { font-size: 0.9rem; font-weight: 650; }
        span { color: var(--faint); font-size: 0.78rem; font-variant-numeric: tabular-nums; }
    }

    .home-heatmap {
        display: grid;
        grid-auto-flow: column;
        grid-template-rows: repeat(7, 1fr);
        grid-auto-columns: 1fr;
        gap: 0.1875rem;
        width: 100%;
        height: 7rem;
    }

    .heat-cell {
        border-radius: 0.125rem;
        background: var(--raised);

        &[data-level="1"] { background: color-mix(in srgb, var(--brand) 30%, var(--raised)); }
        &[data-level="2"] { background: color-mix(in srgb, var(--brand) 55%, var(--raised)); }
        &[data-level="3"] { background: color-mix(in srgb, var(--brand) 78%, var(--raised)); }
        &[data-level="4"] { background: var(--brand); }
    }

    .home-empty { color: var(--faint); font-size: 0.85rem; }

    .home-metrics {
        display: grid;
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 0.75rem;

        article {
            border: 1px solid var(--line);
            background: var(--panel);
            border-radius: 0.45rem;
            padding: 0.7rem 0.85rem;
            display: grid;
            gap: 0.1rem;
        }

        span {
            font-size: 1.5rem;
            font-weight: 650;
            font-variant-numeric: tabular-nums;
        }

        label {
            color: var(--faint);
            font-size: 0.68rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }
    }

    .home-cols {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 1rem;
        align-items: start;
    }

    @media (max-width: 760px) {
        .home-metrics { grid-template-columns: repeat(2, 1fr); }
        .home-cols { grid-template-columns: 1fr; }
    }

    .home-list {
        list-style: none;
        display: grid;
        gap: 0.4rem;

        li {
            display: grid;
            grid-template-columns: auto minmax(0, 1fr) auto;
            gap: 0.5rem;
            align-items: baseline;
            font-size: 0.82rem;
            color: var(--muted);
        }

        .home-item-text {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .home-item-meta {
            color: var(--faint);
            font-size: 0.68rem;
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
    }

    /* Two-line todo row: [status] [title …… priority] / (under title) [vault …… due] */
    .home-list li.todo-row {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        gap: 0.5rem;
        align-items: start;
    }

    .todo-body {
        display: grid;
        gap: 0.15rem;
        min-width: 0;
    }

    .todo-l1,
    .todo-l2 {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: baseline;
        gap: 0.6rem;
        min-width: 0;
    }

    .todo-title {
        color: var(--text);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        /* flex items default to min-width:auto — without this the nowrap
           title refuses to shrink and overflows instead of ellipsing. */
        min-width: 0;
    }

    .todo-pri {
        flex-shrink: 0;
        font-size: 0.62rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--faint);

        &[data-pri="high"] { color: var(--stuck); }
        &[data-pri="normal"] { color: var(--clay, var(--brand)); }
    }

    .todo-vault {
        color: var(--link);
        font-size: 0.74rem;
        text-decoration: none;

        &:hover { text-decoration: underline; }
    }

    .todo-due {
        flex-shrink: 0;
        color: var(--faint);
        font-size: 0.72rem;
    }

    .home-badge {
        font-size: 0.62rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--faint);
        background: var(--raised);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.05rem 0.35rem;
        white-space: nowrap;
    }

    @media (max-width: 760px) {
        .home-cols { grid-template-columns: 1fr; }
    }
}



ui-todos {
    display: grid;
    gap: 1rem;
    max-width: 60rem;
    margin: 0 auto;

    .todos-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: end;
        gap: 1rem;
        border-bottom: 1px solid var(--line);
        padding-bottom: 0.9rem;

        h1 { font-size: 1.45rem; font-weight: 650; }
        .back-link { color: var(--link); font-size: 0.78rem; text-decoration: none; display: block; }
    }

    .todos-tabs {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        gap: 0.25rem;

        button {
            border: 1px solid var(--line);
            background: var(--bg);
            color: var(--muted);
            font-size: 0.78rem;
            padding: 0.3rem 0.7rem;
            cursor: pointer;

            &:first-child { border-radius: 0.35rem 0 0 0.35rem; }
            &:last-child { border-radius: 0 0.35rem 0.35rem 0; }
            &.active { background: var(--raised); color: var(--text); border-color: var(--line-3); }
        }
    }

    .loading { color: var(--faint); font-size: 0.86rem; }
    .todos-empty { color: var(--faint); font-size: 0.86rem; }

    &[data-state="loading"] .todos-empty,
    &[data-state="loading"] .todos-list { display: none; }
    &[data-state="ready"] .loading { display: none; }

    .todos-list {
        list-style: none;
        display: grid;
        gap: 0.5rem;
    }

    .todos-list li {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 0.7rem;
        align-items: center;
        border: 1px solid var(--line);
        background: var(--panel);
        border-radius: 0.4rem;
        padding: 0.55rem 0.8rem;
    }

    .todo-body {
        display: grid;
        gap: 0.15rem;
        min-width: 0;
    }

    .todo-l1 {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        gap: 0.5rem;
    }

    .todo-title {
        min-width: 0;
        color: var(--text);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .todo-l2 {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: baseline;
        gap: 0.5rem;
    }

    .todo-vault {
        color: var(--link);
        font-size: 0.74rem;
        text-decoration: none;

        &:hover { text-decoration: underline; }
    }

    .todo-due {
        color: var(--faint);
        font-size: 0.72rem;
    }

    .todo-pri-sel {
        background: var(--bg);
        color: var(--muted);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        font-size: 0.72rem;
        padding: 0.2rem 0.3rem;
        cursor: pointer;

        &[data-pri="high"] { color: var(--stuck); }
        &[data-pri="normal"] { color: var(--clay, var(--brand)); }
    }

    /* Done control: empty circle → faint tick on hover → filled green tick done. */
    .todo-toggle {
        width: 1.35rem;
        height: 1.35rem;
        padding: 0;
        border: 1.5px solid var(--line-2);
        border-radius: 50%;
        background: transparent;
        color: transparent;
        display: grid;
        place-items: center;
        cursor: pointer;
        transition: color 0.12s, background 0.12s, border-color 0.12s;

        &::after {
            content: "✓";
            font-size: 0.8rem;
            line-height: 1;
        }

        &:hover {
            border-color: var(--accent);
            color: var(--faint);
        }

        &[data-done="true"] {
            background: var(--accent);
            border-color: var(--accent);
            color: var(--bg);
        }
    }

}



/* Footer live connection indicator — rules moved from assets/css/ui.css
   (#conn-status), re-scoped under the component element. The dot is a
   ::before on the component root; colour is driven by [data-state]. */

ui-conn-status {
    display: grid;
    grid-auto-flow: column;
    align-items: center;
    gap: 0.4rem;
    color: var(--muted);

    &::before {
        content: "";
        width: 0.7em;
        height: 0.7em;
        border-radius: 50%;
        background: currentColor;
    }

    &[data-state="online"] {
        color: var(--ok);
    }

    &[data-state="offline"] {
        color: var(--stuck);
    }
}



/* Account drawer — the bottom of the left sidebar panel (shell owns one instance;
   grid-area "drawer" in ui.css places it flush under #sidebar so the two read as
   one panel). The menu is a native [popover]: zero-JS toggle + light-dismiss,
   CSS-anchored above the trigger. Mirrors the admin ui-account-drawer. */

ui-account-drawer {
  grid-area: drawer;
  display: block;
  margin-top: -0.5rem; /* eat the grid row-gap so it merges with #sidebar */
  padding: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-top: none;
  border-radius: 0 0 0.5rem 0.5rem;
}

.account-avatar {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 0.4rem;
  border: 1px solid var(--line-3);
  background: var(--raised);
  display: grid;
  place-items: center;
  overflow: hidden;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* Placeholder when no avatar is set. */
  .icon-person {
    width: 1.4rem;
    height: 1.4rem;
    background: var(--faint);
    mask: url("/img/person.svg") no-repeat center / contain;
  }

  /* `display: grid` would otherwise beat the UA [hidden] rule. */
  [hidden] { display: none; }
}

.account-trigger {
  anchor-name: --account-trigger;
  width: 100%;
  display: grid;
  /* [avatar] [name ......] [caret] — avatar and caret span both rows, the
     email sits under the name in row 2. */
  grid-template-columns: 2.2rem minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: 0.6rem;
  align-items: center;
  padding: 0.4rem;
  border: none;
  border-radius: 0.4rem;
  background: transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;

  /* Explicit placement: with 3 columns, auto-flow would drop the email into
     column 3 row 1 instead of under the name. */
  .account-avatar { grid-column: 1; grid-row: span 2; }
  .account-caret { grid-column: 3; grid-row: span 2; }
  strong { grid-column: 2; grid-row: 1; font-size: 0.85rem; font-weight: 600; }
  small { grid-column: 2; grid-row: 2; color: var(--faint); font-size: 0.72rem; }
  strong, small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  &:hover { background: var(--raised); }
}

/* Caret affordance — same expand_more glyph and half-opacity treatment as the
   search-bar select chevrons, so every dropdown on the page reads alike. */
.account-caret {
  width: 1rem;
  height: 1rem;
  background: var(--muted);
  mask: url("/img/expand-more.svg") no-repeat center / contain;
  opacity: 0.5;
  transition: opacity 0.15s, background 0.15s;
}

.account-trigger:hover .account-caret { opacity: 1; background: var(--text); }

/* ── Popover menu ──────────────────────────────────────────────────────
   Grows upward from the trigger: the menu's bottom edge sits on the anchor's
   bottom edge, left/right flush with it (native CSS anchor positioning).
   ponytail: no fallback — Brain is a Chromium internal tool. */
.account-menu {
  position: fixed;
  position-anchor: --account-trigger;
  margin: 0;
  inset: auto;
  bottom: anchor(bottom);
  left: anchor(left);
  right: anchor(right);
  width: auto; /* beat the UA [popover] { width: fit-content } so it stretches */
  padding: 0.4rem;
  border: 1px solid var(--line-3);
  border-radius: 0.6rem;
  background: var(--panel);
  color: var(--text);
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.45);
}

.account-menu-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.4rem 0.6rem;
  border-bottom: 1px solid var(--line);

  strong { display: block; font-size: 0.85rem; }
  small { display: block; color: var(--faint); font-size: 0.72rem; }
  .account-menu-id { overflow: hidden; }
  strong, small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

.account-menu-items {
  display: grid;
  padding-top: 0.3rem;
}

.account-item {
  /* [icon] [label / description] — icon spans both rows. Logout has no
     description, so its single child just sits in row 1. */
  display: grid;
  grid-template-columns: 1.1rem minmax(0, 1fr);
  align-items: center;
  column-gap: 0.6rem;
  width: 100%;
  padding: 0.5rem 0.5rem;
  border: none;
  border-radius: 0.4rem;
  background: transparent;
  color: var(--text);
  font-size: 0.85rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;

  &:hover { background: var(--raised); }
  &:disabled { color: var(--faint); cursor: not-allowed; background: transparent; }
  &.account-item--danger { color: var(--stuck); }

  strong { grid-column: 2; font-size: 0.85rem; font-weight: 600; }
  small {
    grid-column: 2;
    color: var(--faint);
    font-size: 0.72rem;
    line-height: 1.3;
  }
  strong, small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Icons inherit the row's colour (incl. the danger + disabled states). */
  .icon {
    grid-column: 1;
    grid-row: 1 / -1;
    width: 1.1rem;
    height: 1.1rem;
    background: currentColor;
    mask: no-repeat center / contain;

    &.icon-person { mask-image: url("/img/person.svg"); }
    &.icon-settings { mask-image: url("/img/settings.svg"); }
    &.icon-help { mask-image: url("/img/help.svg"); }
    &.icon-swap { mask-image: url("/img/swap-horiz.svg"); }
    &.icon-logout { mask-image: url("/img/logout.svg"); }
  }
}



/* README pane — rules copied from assets/css/ui.css (#default-view,
   .skill-header, .loading, .error, and the #readme-body markdown typography
   block), re-scoped under the component. Visibility of the WHOLE pane is
   controlled from outside by each page's detail component ([data-view] CSS);
   only the header/error/body swap is state-driven here via [data-state]. */

ui-readme-pane {
    display: block;

    #default-view {
        max-width: 720px;
    }

    /* Header hidden until the README loads (was style.display toggling in ui.js). */
    .skill-header {
        display: none;
        margin-bottom: 1.5rem;
        padding-bottom: 1rem;
        border-bottom: 1px solid var(--line);
    }

    &[data-state="loaded"] .skill-header {
        display: block;
    }

    .skill-header h2 {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--text);
    }

    .skill-header .description {
        font-size: 0.9rem;
        color: var(--muted);
        margin-top: 0.5rem;
        line-height: 1.6;
    }

    .error {
        display: none;
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }

    &[data-state="error"] .error {
        display: block;
    }

    &[data-state="error"] #readme-body {
        display: none;
    }

    .loading {
        color: var(--faint);
        font-size: 0.85rem;
        padding: 2rem 0;
    }

    /* ── Markdown typography (from the shared #readme-body block in ui.css) ── */

    #readme-body {
        max-width: 720px;

        h1:first-child {
            font-size: 1.6rem;
            margin-top: 0;
        }

        h1 {
            font-size: 1.3rem;
            font-weight: 600;
            margin: 1.5rem 0 0.75rem;
            color: var(--text);
        }

        h2 {
            font-size: 1.1rem;
            font-weight: 600;
            margin: 1.25rem 0 0.5rem;
            color: var(--text);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin: 1rem 0 0.5rem;
            color: var(--text);
        }

        p {
            margin: 0 0 0.75rem;
            color: var(--text);
        }

        ul,
        ol {
            margin: 0 0 0.75rem 1.25rem;
        }

        li {
            margin-bottom: 0.25rem;
            color: var(--text);
        }

        code {
            background: var(--raised);
            padding: 0.1em 0.35em;
            border-radius: 0.1875rem;
            font-size: 0.85em;
            font-family: "SF Mono", "Fira Code", "Fira Mono", monospace;
            color: var(--clay);
        }

        pre {
            background: var(--code-bg);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.75rem 1rem;
            overflow-x: auto;
            margin: 0 0 0.75rem;
            font-size: 0.82rem;
            line-height: 1.5;
        }

        pre code {
            background: none;
            padding: 0;
            color: var(--text);
        }

        table {
            border-collapse: collapse;
            margin: 0 0 0.75rem;
            width: 100%;
            font-size: 0.85rem;
        }

        th,
        td {
            border: 1px solid var(--line);
            padding: 0.4rem 0.6rem;
            text-align: left;
        }

        th {
            background: var(--panel);
            color: var(--text);
            font-weight: 600;
        }

        td {
            color: var(--muted);
        }

        a {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }

        hr {
            border: none;
            border-top: 1px solid var(--line);
            margin: 1rem 0;
        }

        blockquote {
            border-left: 0.1875rem solid var(--line-3);
            padding-left: 0.75rem;
            margin: 0 0 0.75rem;
            color: var(--muted);
        }
    }
}



/* Skills sidebar — rules copied from assets/css/ui.css (#skills-header,
   #skill-list, .add-btn, .error), re-scoped under the component. The
   surrounding <aside id="sidebar"> flex column stays in ui.css; the component
   fills it and owns the header/list split. */

ui-skill-sidebar {
    min-height: 0;
    display: grid;
    grid-template-rows: auto 1fr;
    overflow: hidden;

    #skills-header {
        font-size: 0.8rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        padding: 1rem 1rem 0.5rem;
        color: var(--faint);
        cursor: pointer;
        transition: color 0.15s;
        user-select: none;
        display: grid;
        grid-template-columns: 1fr auto;
        align-items: center;

        &:hover {
            color: var(--muted);
        }
    }

    .add-btn {
        background: var(--clay-soft);
        color: var(--clay);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.2rem 0.5rem;
        font-size: 0.68rem;
        font-weight: 600;
        text-transform: none;
        letter-spacing: normal;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;

        &:hover {
            background: var(--brand);
            color: var(--bg);
        }
    }

    #skill-list {
        list-style: none;
        overflow-y: auto;
        min-height: 0;
        padding: 0.25rem 0;

        li {
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            gap: 0.5rem;
            align-items: center;
            padding: 0.45rem 1rem;
            cursor: pointer;
            border-left: 3px solid transparent;
            font-size: 0.875rem;
            color: var(--muted);
            transition: all 0.15s ease;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;

            [data-field="name"] {
                overflow: hidden;
                text-overflow: ellipsis;
            }

            .status {
                display: none;
                color: var(--faint);
                font-size: 0.65rem;
                font-weight: 600;
            }

            &.disabled {
                color: var(--faint);
            }

            &.disabled .status {
                display: inline;
            }

            &:hover {
                background: var(--raised);
                color: var(--text);
            }

            &.active {
                background: var(--raised);
                border-left-color: var(--brand);
                color: var(--text);
            }

            &.error {
                color: var(--stuck);
                font-size: 0.85rem;
                cursor: default;
                white-space: normal;
            }

            &.group {
                display: block;
                cursor: default;
                padding: 0.8rem 1rem 0.25rem;
                border-left-color: transparent;
                color: var(--faint);
                font-size: 0.68rem;
                font-weight: 700;
                text-transform: uppercase;
                letter-spacing: 0.08em;
            }

            &.group:hover {
                background: transparent;
                color: var(--faint);
            }
        }
    }
}



/* Skill detail pane — rules copied from assets/css/ui.css (.skill-header,
   #skill-body typography, #bundled-files, .file-list, #file-preview, .loading,
   .error), re-scoped under the component. Pane switching (readme ↔ skill),
   bundled-files presence, file-preview visibility, and loading/error states
   are all CSS-driven off data-* attributes on the component root — no
   style.display or classList toggling in JS. */

ui-skill-detail {
    display: block;

    /* ── Pane switching: readme view vs skill view ─────────────────────────── */

    &[data-view="skill"] > ui-readme-pane {
        display: none;
    }

    &[data-view="readme"] #skill-detail {
        display: none;
    }

    /* ── Loading / error states (replace the old innerHTML swaps) ──────────── */

    #skill-detail .loading {
        display: none;
        color: var(--faint);
        font-size: 0.85rem;
        padding: 2rem 0;
    }

    &[data-state="loading"] #skill-detail .loading {
        display: block;
    }

    #skill-detail .skill-error {
        display: none;
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }

    &[data-state="error"] #skill-detail .skill-error {
        display: block;
    }

    &[data-state="loading"] #skill-body,
    &[data-state="error"] #skill-body {
        display: none;
    }

    /* ── Header ────────────────────────────────────────────────────────────── */

    .skill-header {
        margin-bottom: 1.5rem;
        padding-bottom: 1rem;
        border-bottom: 1px solid var(--line);

        .skill-title-row {
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            align-items: center;
            gap: 1rem;
        }

        .skill-actions {
            display: grid;
            grid-auto-flow: column;
            justify-content: start;
            align-items: center;
            gap: 0.75rem;
        }

        .enable-toggle {
            display: inline-grid;
            grid-auto-flow: column;
            align-items: center;
            gap: 0.35rem;
            color: var(--muted);
            font-size: 0.75rem;
            font-weight: 500;
            cursor: pointer;
        }

        .enable-toggle input {
            width: 0.9rem;
            height: 0.9rem;
            accent-color: var(--brand);
        }

        h2 {
            font-size: 1.4rem;
            font-weight: 600;
            color: var(--text);
        }

        .danger-btn {
            border: 1px solid color-mix(in srgb, var(--stuck) 45%, transparent);
            background: transparent;
            color: var(--stuck);
            border-radius: 0.25rem;
            padding: 0.25rem 0.55rem;
            font-size: 0.75rem;
            cursor: pointer;
        }

        .danger-btn:hover {
            background: color-mix(in srgb, var(--stuck) 10%, transparent);
        }

        .danger-btn:disabled {
            opacity: 0.55;
            cursor: wait;
        }

        .version {
            font-size: 0.75rem;
            font-weight: 500;
            color: var(--faint);
            background: var(--raised);
            padding: 0.15rem 0.5rem;
            border-radius: 0.25rem;
            display: inline-block;
            margin-top: 0.25rem;
        }

        .description {
            font-size: 0.9rem;
            color: var(--muted);
            margin-top: 0.5rem;
            line-height: 1.6;
        }
    }

    /* ── Markdown body typography (from the shared #skill-body block) ──────── */

    #skill-body {
        max-width: 720px;

        h1 {
            font-size: 1.3rem;
            font-weight: 600;
            margin: 1.5rem 0 0.75rem;
            color: var(--text);
        }

        h2 {
            font-size: 1.1rem;
            font-weight: 600;
            margin: 1.25rem 0 0.5rem;
            color: var(--text);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin: 1rem 0 0.5rem;
            color: var(--text);
        }

        p {
            margin: 0 0 0.75rem;
            color: var(--text);
        }

        ul,
        ol {
            margin: 0 0 0.75rem 1.25rem;
        }

        li {
            margin-bottom: 0.25rem;
            color: var(--text);
        }

        code {
            background: var(--raised);
            padding: 0.1em 0.35em;
            border-radius: 0.1875rem;
            font-size: 0.85em;
            font-family: "SF Mono", "Fira Code", "Fira Mono", monospace;
            color: var(--clay);
        }

        pre {
            background: var(--code-bg);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.75rem 1rem;
            overflow-x: auto;
            margin: 0 0 0.75rem;
            font-size: 0.82rem;
            line-height: 1.5;
        }

        pre code {
            background: none;
            padding: 0;
            color: var(--text);
        }

        table {
            border-collapse: collapse;
            margin: 0 0 0.75rem;
            width: 100%;
            font-size: 0.85rem;
        }

        th,
        td {
            border: 1px solid var(--line);
            padding: 0.4rem 0.6rem;
            text-align: left;
        }

        th {
            background: var(--panel);
            color: var(--text);
            font-weight: 600;
        }

        td {
            color: var(--muted);
        }

        a {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }

        hr {
            border: none;
            border-top: 1px solid var(--line);
            margin: 1rem 0;
        }

        blockquote {
            border-left: 0.1875rem solid var(--line-3);
            padding-left: 0.75rem;
            margin: 0 0 0.75rem;
            color: var(--muted);
        }
    }

    /* ── Bundled files (hidden until a skill with files loads) ─────────────── */

    #bundled-files {
        margin-top: 2rem;
        padding-top: 1rem;
        border-top: 1px solid var(--line);
    }

    &:not([data-has-files]) #bundled-files {
        display: none;
    }

    #bundled-files h3 {
        font-size: 0.85rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--faint);
        margin-bottom: 0.5rem;
    }

    .file-list {
        list-style: none;

        li {
            padding: 0.3rem 0;
        }

        a {
            font-size: 0.85rem;
            font-family: "SF Mono", "Fira Code", monospace;
            color: var(--link);
            cursor: pointer;
            transition: color 0.15s;

            &:hover {
                text-decoration: underline;
            }
        }
    }

    /* ── File preview (was #file-preview.visible class toggling) ───────────── */

    #file-preview {
        margin-top: 1rem;
        display: none;
    }

    &[data-preview] #file-preview {
        display: block;
    }

    #file-preview .file-header {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: center;
        gap: 0.5rem;
        margin-bottom: 0.5rem;

        h4 {
            font-size: 0.8rem;
            font-weight: 500;
            color: var(--muted);
            font-family: "SF Mono", monospace;
        }
    }

    #file-preview .close-btn {
        background: none;
        border: 1px solid var(--line-3);
        color: var(--muted);
        border-radius: 0.25rem;
        padding: 0.1rem 0.4rem;
        font-size: 0.7rem;
        cursor: pointer;
        transition: all 0.15s;

        &:hover {
            background: var(--raised);
            border-color: var(--line-3);
        }
    }

    #file-preview pre {
        background: var(--code-bg);
        border: 1px solid var(--line);
        border-radius: 0.375rem;
        padding: 0.75rem 1rem;
        overflow-x: auto;
        font-size: 0.8rem;
        line-height: 1.5;
        color: var(--text);
    }
}



/* Add Skill modal — rules copied from assets/css/ui.css (.modal-overlay,
   .modal, .modal-header, #skill-form, .modal-actions, .error), re-scoped
   under the component. Open/close is CSS-driven off [data-open] on the
   component root; the error box off [data-error] — no style.display in JS. */

/* The component sits as a direct body child (the overlay is position:fixed);
   display:contents keeps it from becoming a body-grid item. */
ui-skill-form {
    display: contents;

    .modal-overlay {
        position: fixed;
        inset: 0;
        background: hsl(0deg 0% 0% / 0.55);
        display: none;
        align-items: center;
        justify-content: center;
        z-index: 100;
    }

    &[data-open] .modal-overlay {
        display: grid;
        place-items: center;
    }

    .modal {
        background: var(--panel);
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        width: 34rem;
        max-width: 92vw;
        max-height: 85vh;
        overflow-y: auto;
        box-shadow: 0 0.5rem 1.5rem hsl(0deg 0% 0% / 0.4), 0 0.1rem 0.3rem hsl(0deg 0% 0% / 0.3);
    }

    .modal-header {
        display: grid;
        grid-template-columns: auto 1fr auto;
        align-items: stretch;
        gap: 1.1rem;
        padding: 0 1.1rem;
        min-height: 2.8rem;
        border-bottom: 1px solid var(--line);

        h3 {
            font-size: 1rem;
            font-weight: 600;
            align-self: center;
        }

        .close-btn {
            align-self: center;
        }
    }

    .close-btn {
        background: none;
        border: 1px solid var(--line-3);
        color: var(--muted);
        border-radius: 0.25rem;
        padding: 0.1rem 0.4rem;
        font-size: 0.7rem;
        cursor: pointer;
        transition: all 0.15s;

        &:hover {
            background: var(--raised);
            border-color: var(--line-3);
        }
    }

    /* Tab strip lives in the modal header; panes toggle off the checked
       radio via :has() on the component root (labels aren't siblings of the
       bodies, so app's adjacent-sibling variant doesn't apply). No JS. */
    .ui-tabpanel {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;

        > .ui-tabpanel-label {
            display: inline-grid;
            grid-auto-flow: column;
            align-items: center;
            padding: 0 0.75rem;
            cursor: pointer;
            user-select: none;
            color: var(--muted);
            font-size: 0.8rem;
            font-weight: 600;
            white-space: nowrap;
            border-bottom: 0.125rem solid transparent;

            > input[type="radio"] {
                position: absolute;
                opacity: 0;
                pointer-events: none;
                width: 0;
                height: 0;
            }

            &:hover {
                color: var(--text);
            }

            &:has(input:checked) {
                color: var(--text);
                border-bottom-color: var(--brand);
            }
        }

    }

    .ui-tabpanel-body {
        display: none;
    }

    &:has([name="skill-form-tab"][value="manual"]:checked) #skill-form,
    &:has([name="skill-form-tab"][value="import"]:checked) #skill-import-form {
        display: grid;
    }

    /* display comes from .ui-tabpanel-body (an id rule would out-rank the
       tab switcher's display:none) */
    #skill-form {
        gap: 0.85rem;
        padding: 1.1rem;

        label {
            display: grid;
            gap: 0.3rem;
            font-size: 0.8rem;
            font-weight: 600;
            color: var(--muted);
        }

        input,
        textarea {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.3rem;
            padding: 0.45rem 0.6rem;
            font-family: inherit;
            font-size: 0.85rem;
            resize: vertical;
        }

        textarea#skill-form-body {
            font-family: "SF Mono", monospace;
            font-size: 0.8rem;
        }

        input:focus,
        textarea:focus {
            outline: none;
            border-color: var(--brand);
        }
    }

    #skill-import-form {
        gap: 0.85rem;
        padding: 1.1rem;
        align-content: start;

        label {
            display: grid;
            gap: 0.3rem;
            font-size: 0.8rem;
            font-weight: 600;
            color: var(--muted);
        }

        input {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.3rem;
            padding: 0.45rem 0.6rem;
            font-family: inherit;
            font-size: 0.85rem;
        }

        input:focus {
            outline: none;
            border-color: var(--brand);
        }
    }

    .hint {
        font-weight: 400;
        color: var(--faint);
        text-transform: none;
        letter-spacing: normal;
    }

    .error {
        display: none;
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }

    &[data-error] [data-field="error"],
    &[data-import-error] [data-field="import-error"] {
        display: block;
    }

    .modal-actions {
        display: grid;
        justify-content: end;

        button {
            background: var(--brand);
            color: var(--bg);
            border: none;
            border-radius: 0.3rem;
            padding: 0.5rem 1.1rem;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;

            &:disabled {
                opacity: 0.6;
                cursor: default;
            }
        }
    }
}



/* ui-entity-sidebar — vault filter + search/sort + entity list.
   Rules moved from assets/css/ui.css, re-scoped under the element. */

/* The component fills the #sidebar grid (ui.css owns #sidebar):
   header auto, list takes the rest and scrolls. */
ui-entity-sidebar {
    display: grid;
    grid-template-rows: auto 1fr;
    min-height: 0;
    overflow: hidden;

    .vault-picker {
        padding: 0.5rem 1rem 0.5rem;
        display: grid;
        gap: 0.4rem;

        select {
            width: 100%;
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 4px;
            padding: 0.3rem 0.4rem;
            font-size: 0.8rem;
            font-family: inherit;

            &:focus { outline: 1px solid var(--brand); }
        }
    }

    .ent-controls {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 0.3rem;
        padding: 0 1rem 0.5rem;

        input[type="text"] {
            min-width: 0;
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 4px;
            padding: 0.3rem 0.4rem;
            font-family: inherit;
            font-size: 0.8rem;

            &:focus { outline: 1px solid var(--brand); }
        }

        button {
            background: var(--bg);
            color: var(--muted);
            border: 1px solid var(--line);
            border-radius: 4px;
            padding: 0.3rem 0.5rem;
            font-size: 0.8rem;
            cursor: pointer;
            font-variant-numeric: tabular-nums;

            &:hover { color: var(--brand); border-color: var(--line-3); }
        }
    }

    .count {
        font-size: 0.7rem;
        color: var(--faint);
        padding: 0 1rem 0.5rem;
        border-bottom: 1px solid var(--line);
    }

    #entity-list {
        list-style: none;
        overflow-y: auto;
        padding: 0.25rem 0;
        min-height: 3.75rem;

        /* Entity row — icon spans both rows, then two text rows:
             [icon] [name] ............ [mentions]
             [icon] [kind] ............ [domain]   */
        li {
            padding: 0.4rem 1rem;
            cursor: pointer;
            border-left: 3px solid transparent;
            color: var(--muted);
            transition: all 0.15s ease;
            display: grid;
            /* col2 = minmax(0,1fr) so the name shrinks+ellipsises instead of overflowing;
               col3 capped so a long right-hand value (mentions/vaults) can't steal the
               name's width (multi-vault rows were collapsing "nats" → "n."). */
            grid-template-columns: auto minmax(0, 1fr) minmax(0, 6rem);
            align-items: baseline;
            column-gap: 0.5rem;
            row-gap: 0.1rem;

            &:hover {
                background: var(--raised);
                color: var(--text);
            }

            &[data-active] {
                background: var(--raised);
                border-left-color: var(--brand);
                color: var(--text);
            }

            > span {
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                min-width: 0;
            }

            .ent-icon {
                grid-column: 1;
                grid-row: 1 / span 2;
                align-self: center;
                width: 1.7rem;
                height: 1.7rem;
                border-radius: 0.35rem;
                background: var(--raised);
                color: var(--faint);
                display: grid;
                place-items: center;
                font-size: 0.75rem;
                font-weight: 600;
                text-transform: uppercase;
            }

            &:hover .ent-icon { color: var(--brand); }

            /* pending-consolidation glyph sits in the slot as a status icon, not a letter badge */
            &[data-pending] .ent-icon {
                background: transparent;
                font-size: 0.95rem;
                text-transform: none;
            }

            .ent-name {
                grid-column: 2;
                grid-row: 1;
                font-size: 0.82rem;
            }

            .ent-mentions {
                grid-column: 3;
                grid-row: 1;
                justify-self: end;
                font-size: 0.68rem;
                color: var(--faint);
                font-variant-numeric: tabular-nums;
            }

            .ent-kind {
                grid-column: 2;
                grid-row: 2;
                justify-self: start;
                font-size: 0.6rem;
                color: var(--faint);
                text-transform: uppercase;
                letter-spacing: 0.04em;
            }

            .ent-domain {
                grid-column: 3;
                grid-row: 2;
                justify-self: end;
                font-size: 0.6rem;
                color: var(--faint);
                font-family: "SF Mono", monospace;
                max-width: 9rem;
            }
        }
    }

    .entity-stub {
        color: var(--faint);
        font-style: italic;
        font-size: 0.85rem;
        padding: 0.5rem 0;
    }

    .error {
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }
}



/* ui-entity-detail — two-column entity pane + readme view switch.
   Rules moved from assets/css/ui.css, re-scoped under the element.
   Visibility is CSS-driven off data-view / data-state / data-summary attrs. */

ui-entity-detail {
    display: block;
    /* Query container so the two-column ↔ stacked switch keys off the CONTENT
       width (inside #main, minus the 20rem sidebar), not the viewport. */
    container-type: inline-size;

    /* View switch: readme ↔ entity (ui-readme-pane owns its own content). */
    ui-readme-pane { display: none; }
    &[data-view="readme"] ui-readme-pane { display: block; }

    /* Entity detail: content left (same 720px cap as other panes), header/chips right. */
    #entity-detail { display: none; }
    &[data-view="entity"] #entity-detail {
        display: grid;
        /* side column capped at 20rem so wide viewports don't stretch the chips */
        grid-template-columns: minmax(0, 720px) minmax(0, 20rem);
        gap: 2rem;
        align-items: start;
    }
    .entity-main { min-width: 0; }
    .entity-side .skill-header {
        border-bottom: none;
        padding-bottom: 0;
        margin-bottom: 0;
    }
    @container (max-width: 1000px) {
        &[data-view="entity"] #entity-detail { grid-template-columns: 1fr; }
        .entity-side { order: -1; }
        .entity-side .skill-header {
            border-bottom: 1px solid var(--line);
            padding-bottom: 1rem;
        }
    }

    /* Load / error state (shown instead of JS-injected placeholder markup). */
    .loading {
        display: none;
        color: var(--faint);
        font-size: 0.85rem;
        padding: 2rem 0;
    }
    &[data-state="loading"] .loading { display: block; }
    .error {
        display: none;
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }
    &[data-state="error"] .error { display: block; }

    /* No-summary stub — visible only when the loaded entity has no summary. */
    .no-summary { display: none; }
    &[data-state="ready"][data-summary="stub"] .no-summary { display: block; }
    .entity-stub {
        color: var(--faint);
        font-style: italic;
        font-size: 0.85rem;
        padding: 0.5rem 0;
    }
    /* Old stub rendered inside #entity-body and inherited its code-chip style;
       the SSR stub sits beside it, so carry the rule over. */
    .no-summary code {
        background: var(--raised);
        padding: 0.1em 0.35em;
        border-radius: 3px;
        font-size: 0.85em;
        font-family: "SF Mono", "Fira Code", "Fira Mono", monospace;
        color: var(--clay);
    }

    /* Right-hand header (name / kind badge / meta + chips). */
    .skill-header {
        margin-bottom: 1.5rem;
        padding-bottom: 1rem;
        border-bottom: 1px solid var(--line);

        h2 {
            font-size: 1.4rem;
            font-weight: 600;
            color: var(--text);
        }

        .version {
            font-size: 0.75rem;
            font-weight: 500;
            color: var(--faint);
            background: var(--raised);
            padding: 0.15rem 0.5rem;
            border-radius: 4px;
            display: inline-block;
            margin-top: 0.25rem;
        }

        .description {
            font-size: 0.9rem;
            color: var(--muted);
            margin-top: 0.5rem;
            line-height: 1.6;
        }
    }
    .ent-chips {
        display: flex;
        flex-wrap: wrap;
        gap: 0.3rem;
        margin-top: 0.5rem;

        &:empty { display: none; }
    }
    .ent-chip {
        font-size: 0.7rem;
        padding: 0.1rem 0.45rem;
        border-radius: 3px;
        background: var(--raised);
        color: var(--muted);
        font-family: "SF Mono", monospace;

        &.vault { background: var(--clay-soft); color: var(--clay); }
    }
    .context-link {
        display: inline-grid;
        grid-auto-flow: column;
        align-items: center;
        min-height: 1.75rem;
        margin-top: 0.75rem;
        border: 1px solid var(--line);
        border-radius: 4px;
        padding: 0.25rem 0.55rem;
        color: var(--muted);
        font-size: 0.78rem;
        text-decoration: none;

        &:hover {
            border-color: var(--link);
            color: var(--link);
        }
    }

    /* Mentioned-in list. */
    #bundled-files {
        margin-top: 2rem;
        padding-top: 1rem;
        border-top: 1px solid var(--line);

        h3 {
            font-size: 0.85rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.06em;
            color: var(--faint);
            margin-bottom: 0.5rem;
        }
    }
    /* Mentioned-In tabs — radio-driven .ui-tabpanel (same pattern as the
       skill form): CSS :has() switches panes; the atom pane's rows are built
       lazily by JS on first activation. */
    #bundled-files .ui-tabpanel {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        border-bottom: 1px solid var(--line);
        margin-bottom: 0.5rem;

        > .ui-tabpanel-label {
            display: inline-grid;
            grid-auto-flow: column;
            align-items: center;
            padding: 0.25rem 0.65rem;
            cursor: pointer;
            user-select: none;
            color: var(--muted);
            font-size: 0.78rem;
            font-weight: 600;
            white-space: nowrap;
            border-bottom: 0.125rem solid transparent;

            > input[type="radio"] {
                position: absolute;
                opacity: 0;
                pointer-events: none;
                width: 0;
                height: 0;
            }

            &:hover { color: var(--text); }

            &:has(input:checked) {
                color: var(--text);
                border-bottom-color: var(--brand);
            }
        }
    }

    #bundled-files .ui-tabpanel-body { display: none; }
    &:has([name="entity-mention-tab"][value="docs"]:checked) #entity-doc-list {
        display: block;
    }
    &:has([name="entity-mention-tab"][value="atoms"]:checked) #entity-atom-list {
        display: block;
    }

    #entity-doc-list,
    #entity-atom-list {
        list-style: none;

        li {
            padding: 0.3rem 0;
            font-size: 0.85rem;
        }

        a {
            color: var(--link);
            cursor: pointer;
            font-family: "SF Mono", "Fira Code", monospace;
            text-decoration: none;

            &:hover { text-decoration: underline; }
        }
    }

    /* Atom titles are long distilled sentences — one line each, ellipsised,
       so the list scans as rows instead of a wall of wrapped text. */
    #entity-atom-list li {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Markdown-rendered summary — mirrors the shared body typography from ui.css. */
    #entity-body {
        max-width: 720px;

        h1 {
            font-size: 1.3rem;
            font-weight: 600;
            margin: 1.5rem 0 0.75rem;
            color: var(--text);
        }

        h2 {
            font-size: 1.1rem;
            font-weight: 600;
            margin: 1.25rem 0 0.5rem;
            color: var(--text);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin: 1rem 0 0.5rem;
            color: var(--text);
        }

        p { margin: 0 0 0.75rem; color: var(--text); }

        ul,
        ol { margin: 0 0 0.75rem 1.25rem; }

        li { margin-bottom: 0.25rem; color: var(--text); }

        code {
            background: var(--raised);
            padding: 0.1em 0.35em;
            border-radius: 3px;
            font-size: 0.85em;
            font-family: "SF Mono", "Fira Code", "Fira Mono", monospace;
            color: var(--clay);
        }

        pre {
            background: var(--code-bg);
            border: 1px solid var(--line);
            border-radius: 6px;
            padding: 0.75rem 1rem;
            overflow-x: auto;
            margin: 0 0 0.75rem;
            font-size: 0.82rem;
            line-height: 1.5;

            code {
                background: none;
                padding: 0;
                color: var(--text);
            }
        }

        table {
            border-collapse: collapse;
            margin: 0 0 0.75rem;
            width: 100%;
            font-size: 0.85rem;
        }

        th,
        td {
            border: 1px solid var(--line);
            padding: 0.4rem 0.6rem;
            text-align: left;
        }

        th {
            background: var(--panel);
            color: var(--text);
            font-weight: 600;
        }

        td { color: var(--muted); }

        a {
            color: var(--link);
            text-decoration: none;

            &:hover { text-decoration: underline; }
        }

        hr {
            border: none;
            border-top: 1px solid var(--line);
            margin: 1rem 0;
        }

        blockquote {
            border-left: 3px solid var(--line-3);
            padding-left: 0.75rem;
            margin: 0 0 0.75rem;
            color: var(--muted);
        }
    }

    /* On-demand summary rebuild — lives in the side header, always available. */
    .consolidate-btn {
        display: block;
        margin-top: 0.5rem;
        padding: 0.2rem 0.6rem;
        border: 1px solid var(--brand);
        border-radius: 0.3rem;
        background: transparent;
        color: var(--brand);
        font: inherit;
        font-size: 0.78rem;
        cursor: pointer;

        &:hover:not(:disabled) {
            background: var(--clay-soft);
        }

        &:disabled {
            opacity: 0.6;
            cursor: progress;
        }
    }

    /* ── Relations panel ("how do you know?") ───────────────────────────── */
    .ent-relations {
        margin-top: 1.25rem;

        h3 {
            font-size: 0.82rem;
            font-weight: 650;
            color: var(--muted);
            text-transform: uppercase;
            letter-spacing: 0.06em;
            margin-bottom: 0.5rem;
        }

        ul { list-style: none; }
    }

    /* Empty state: hide the panel entirely rather than show a bare heading */
    &[data-relations="none"] .ent-relations { display: none; }

    .rel-row {
        summary {
            display: grid;
            grid-auto-flow: column;
            justify-content: start;
            align-items: center;
            gap: 0.5rem;
            padding: 0.3rem 0.4rem;
            border-radius: 0.3rem;
            cursor: pointer;
            list-style: none;

            &:hover { background: var(--raised); }
            &::-webkit-details-marker { display: none; }
        }

        .rel-type {
            font-size: 0.62rem;
            padding: 0.0625rem 0.375rem;
            border-radius: 0.125rem;
            letter-spacing: 0.05em;
            background: var(--bg);
            border: 1px solid var(--line-3);
            color: var(--muted);
            white-space: nowrap;

            /* Type colours mirror the knowledge-map edge palette */
            &[data-rel="part_of"] { color: var(--stuck); border-color: var(--stuck); }
            &[data-rel="depends_on"] { color: var(--link); border-color: var(--link); }
            &[data-rel="integrates_with"] { color: var(--ok); border-color: var(--ok); }
            &[data-rel="supersedes"] { color: var(--brand); border-color: var(--brand); }
        }

        .rel-arrow { color: var(--faint); }

        .rel-other {
            color: var(--link);
            text-decoration: none;
            font-size: 0.82rem;

            &:hover { text-decoration: underline; }
        }

        .rel-meta {
            color: var(--faint);
            font-size: 0.68rem;
            margin-left: auto;
        }
    }

    .rel-evidence {
        margin: 0.25rem 0 0.5rem 1.5rem;
        display: grid;
        gap: 0.25rem;

        li {
            font-size: 0.74rem;
            color: var(--muted);

            q { font-style: italic; }

            a {
                color: var(--link);
                font-size: 0.68rem;
                margin-left: 0.375rem;
                text-decoration: none;

                &:hover { text-decoration: underline; }
            }
        }
    }
}



/* Docs sidebar — rules copied from assets/css/ui.css (.vault-picker,
   .ent-controls, .count, #docs-list + .doc-title/.doc-vault, .loading,
   .error), re-scoped under the component. Do not edit ui.css — a central
   cleanup strips the old copies afterward. */

ui-docs-sidebar {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    min-height: 0; /* #sidebar's grid gives this the filling row */
    overflow: hidden;

    .vault-picker {
        padding: 0.5rem 1rem 0.5rem;
        display: grid;
        gap: 0.4rem;

        select {
            width: 100%;
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 4px;
            padding: 0.3rem 0.4rem;
            font-size: 0.8rem;
            font-family: inherit;

            &:focus {
                outline: 1px solid var(--brand);
            }
        }
    }

    .ent-controls {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 0.3rem;
        padding: 0 1rem 0.5rem;

        input[type="text"] {
            min-width: 0;
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 4px;
            padding: 0.3rem 0.4rem;
            font-family: inherit;
            font-size: 0.8rem;

            &:focus {
                outline: 1px solid var(--brand);
            }
        }

        button {
            background: var(--bg);
            color: var(--muted);
            border: 1px solid var(--line);
            border-radius: 4px;
            padding: 0.3rem 0.5rem;
            font-size: 0.8rem;
            cursor: pointer;
            font-variant-numeric: tabular-nums;

            &:hover {
                color: var(--brand);
                border-color: var(--line-3);
            }
        }
    }

    .count {
        font-size: 0.7rem;
        color: var(--faint);
        padding: 0 1rem 0.5rem;
        border-bottom: 1px solid var(--line);
    }

    #docs-list {
        list-style: none;
        overflow-y: auto;
        padding: 0.25rem 0;

        li {
            padding: 0.45rem 1rem;
            cursor: pointer;
            border-left: 3px solid transparent;
            color: var(--muted);
            transition: all 0.15s ease;
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            align-items: baseline;
            column-gap: 0.5rem;

            &:hover {
                background: var(--raised);
                color: var(--text);
            }

            &.active {
                background: var(--raised);
                border-left-color: var(--brand);
                color: var(--text);
            }
        }

        .doc-title {
            font-size: 0.82rem;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .doc-vault {
            font-size: 0.65rem;
            color: var(--faint);
            font-family: "SF Mono", monospace;
            justify-self: end;
        }

        /* Placeholder rows (removed / replaced by the first render). */
        li.loading,
        li.error {
            cursor: default;
            display: block;
        }
    }

    .loading {
        color: var(--faint);
        font-size: 0.85rem;
    }

    .error {
        color: var(--stuck);
        font-size: 0.85rem;
    }
}



/* Doc detail pane — rules copied from assets/css/ui.css (.skill-header block,
   select#doc-vault, .ent-chips/.ent-chip, #doc-body markdown typography,
   .loading, .error), re-scoped under the component. Everything is scoped
   under #doc-detail so nothing bleeds into the included ui-readme-pane.
   Do not edit ui.css — a central cleanup strips the old copies afterward. */

ui-doc-detail {
    display: block;

    /* readme ↔ doc view switch, driven by [data-view] on the component root.
       The included ui-readme-pane is visible in the default readme view. */
    > #doc-detail {
        display: none;
    }

    &[data-view="doc"] {
        > #doc-detail {
            display: block;
        }

        > ui-readme-pane {
            display: none;
        }
    }

    #doc-detail {
        .skill-header {
            margin-bottom: 1.5rem;
            padding-bottom: 1rem;
            border-bottom: 1px solid var(--line);

            h2 {
                font-size: 1.4rem;
                font-weight: 600;
                color: var(--text);
            }

            .version {
                font-size: 0.75rem;
                font-weight: 500;
                color: var(--faint);
                background: var(--raised);
                padding: 0.15rem 0.5rem;
                border-radius: 4px;
                display: inline-block;
                margin-top: 0.25rem;
            }
        }

        select#doc-vault {
            border: 1px solid var(--line);
            font-family: inherit;
            cursor: pointer;

            &:focus {
                outline: 1px solid var(--brand);
            }
        }

        .skill-header .description {
            font-size: 0.9rem;
            color: var(--muted);
            margin-top: 0.5rem;
            line-height: 1.6;
        }

        .raw-toggle {
            font-size: 0.7rem;
            font-family: "SF Mono", monospace;
            color: var(--faint);
            background: var(--raised);
            border: 1px solid var(--line);
            border-radius: 3px;
            padding: 0.1rem 0.45rem;
            margin-left: 0.5rem;
            cursor: pointer;

            &:hover {
                color: var(--text);
                border-color: var(--line-3);
            }
        }

        .context-link {
            color: var(--link);
            font-size: 0.75rem;
            margin-left: 0.5rem;
        }

        .delete-btn:hover {
            color: var(--stuck);
            border-color: var(--stuck);
        }

        /* Single-axis chip row — flex permitted here. */
        .ent-chips {
            display: flex;
            flex-wrap: wrap;
            gap: 0.3rem;
            margin-top: 0.5rem;

            &:empty {
                display: none;
                margin-top: 0;
            }
        }

        .ent-chip {
            font-size: 0.7rem;
            padding: 0.1rem 0.45rem;
            border-radius: 3px;
            background: var(--raised);
            color: var(--muted);
            font-family: "SF Mono", monospace;
        }

        /* Load/error state, driven by [data-state] on the component root. Errors are
           :empty-collapsed so the vault-reassign error only shows when filled. */
        .loading {
            display: none;
            color: var(--faint);
            font-size: 0.85rem;
            padding: 2rem 0;
        }
    }

    &[data-state="loading"] #doc-detail .loading {
        display: block;
    }

    #doc-detail {
        .error {
            color: var(--stuck);
            font-size: 0.85rem;
            padding: 1rem 0;

            &:empty {
                display: none;
            }
        }

        .vault-error {
            padding: 0.5rem 0 0;
        }

        .doc-error {
            padding: 1rem 0;
        }

        .doc-lineage {
            max-width: 720px;
            border: 1px solid var(--line);
            border-radius: 0.45rem;
            background: var(--panel);
            padding: 0.8rem;
            margin: 0 0 1rem;

            h3 {
                font-size: 0.88rem;
                font-weight: 650;
                margin-bottom: 0.6rem;
            }
        }

        .lineage-grid {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 0.75rem;

            section {
                min-width: 0;
            }

            h4 {
                color: var(--faint);
                font-size: 0.66rem;
                font-weight: 650;
                letter-spacing: 0.05em;
                margin-bottom: 0.35rem;
                text-transform: uppercase;
            }

            ul {
                list-style: none;
                display: grid;
                gap: 0.25rem;
            }

            li {
                display: grid;
                grid-template-columns: auto minmax(0, 1fr);
                gap: 0.45rem;
                align-items: baseline;
                color: var(--muted);
                font-size: 0.78rem;
                min-width: 0;
            }

            li.lineage-empty {
                display: block;
                color: var(--faint);
                font-style: italic;
            }

            span {
                color: var(--clay);
                font-family: "SF Mono", monospace;
                font-size: 0.68rem;
            }

            a {
                color: var(--link);
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
        }
    }

    /* Raw ingested text — visible only in [data-mode=raw] (rendered is the
       default; #load resets the mode on every doc). */
    #doc-raw {
        display: none;
        max-width: 720px;
        background: var(--code-bg);
        border: 1px solid var(--line);
        border-radius: 6px;
        padding: 0.75rem 1rem;
        font-size: 0.82rem;
        line-height: 1.5;
        font-family: "SF Mono", "Fira Code", "Fira Mono", monospace;
        color: var(--text);
        white-space: pre-wrap;
        word-break: break-word;
    }

    &[data-mode="raw"] {
        #doc-raw {
            display: block;
        }

        #doc-body {
            display: none;
        }
    }

    /* Markdown body typography (copied from the ui.css #doc-body variants). */
    #doc-body {
        max-width: 720px;

        h1 {
            font-size: 1.3rem;
            font-weight: 600;
            margin: 1.5rem 0 0.75rem;
            color: var(--text);
        }

        h2 {
            font-size: 1.1rem;
            font-weight: 600;
            margin: 1.25rem 0 0.5rem;
            color: var(--text);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin: 1rem 0 0.5rem;
            color: var(--text);
        }

        p {
            margin: 0 0 0.75rem;
            color: var(--text);
        }

        ul,
        ol {
            margin: 0 0 0.75rem 1.25rem;
        }

        li {
            margin-bottom: 0.25rem;
            color: var(--text);
        }

        code {
            background: var(--raised);
            padding: 0.1em 0.35em;
            border-radius: 3px;
            font-size: 0.85em;
            font-family: "SF Mono", "Fira Code", "Fira Mono", monospace;
            color: var(--clay);
        }

        pre {
            background: var(--code-bg);
            border: 1px solid var(--line);
            border-radius: 6px;
            padding: 0.75rem 1rem;
            overflow-x: auto;
            margin: 0 0 0.75rem;
            font-size: 0.82rem;
            line-height: 1.5;

            code {
                background: none;
                padding: 0;
                color: var(--text);
            }
        }

        table {
            border-collapse: collapse;
            margin: 0 0 0.75rem;
            width: 100%;
            font-size: 0.85rem;
        }

        th,
        td {
            border: 1px solid var(--line);
            padding: 0.4rem 0.6rem;
            text-align: left;
        }

        th {
            background: var(--panel);
            color: var(--text);
            font-weight: 600;
        }

        td {
            color: var(--muted);
        }

        a {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }

        hr {
            border: none;
            border-top: 1px solid var(--line);
            margin: 1rem 0;
        }

        blockquote {
            border-left: 3px solid var(--line-3);
            padding-left: 0.75rem;
            margin: 0 0 0.75rem;
            color: var(--muted);
        }
    }

    @media (max-width: 760px) {
        #doc-detail .lineage-grid {
            grid-template-columns: 1fr;
        }
    }

    /* Confirmation dialogs (vault reassign + delete) — native <dialog>
       (top layer via showModal). Delete's confirm button flips to the
       danger color below. */
    dialog.vault-confirm,
    dialog.delete-confirm {
        /* the global `* { margin: 0 }` reset kills the UA's margin:auto dialog
           centering — restore it. */
        margin: auto;
        background: var(--panel);
        color: var(--text);
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        padding: 1.1rem 1.25rem;
        width: 26rem;
        max-width: 92vw;
        box-shadow: 0 0.5rem 1.5rem hsl(0 0% 0% / 0.4), 0 0.1rem 0.3rem hsl(0 0% 0% / 0.3);

        &::backdrop {
            background: hsl(0 0% 0% / 0.55);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin-bottom: 0.6rem;
        }

        p {
            font-size: 0.9rem;
            color: var(--muted);
            line-height: 1.6;

            strong {
                color: var(--clay);
                font-family: "SF Mono", monospace;
                font-weight: 600;
            }
        }

        menu {
            list-style: none;
            display: grid;
            grid-auto-flow: column;
            justify-content: end;
            gap: 0.5rem;
            margin-top: 1rem;

            button {
                border: 1px solid var(--line-3);
                border-radius: 0.3rem;
                background: none;
                color: var(--muted);
                padding: 0.4rem 1rem;
                font-size: 0.85rem;
                font-weight: 600;
                cursor: pointer;

                &[value="confirm"] {
                    background: var(--brand);
                    border-color: var(--brand);
                    color: var(--bg);
                }

                &:hover {
                    color: var(--text);

                    &[value="confirm"] {
                        opacity: 0.9;
                        color: var(--bg);
                    }
                }
            }
        }
    }

    dialog.delete-confirm menu button[value="confirm"] {
        background: var(--stuck);
        border-color: var(--stuck);
    }
}



ui-add-knowledge {
    display: grid;
    /* Fill #main vertically: header is auto, the form takes the rest, and the
       editor row inside it absorbs the slack. minmax(0,1fr) (not 1fr) so the
       textarea's own min-height cannot push the grid past the panel. */
    min-height: 100%;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 1.25rem;
    color: var(--text);

    .add-header {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 1rem;
        align-items: start;

        .description {
            max-width: 46rem;
            margin: 0.45rem 0 0;
            color: var(--muted);
            font-size: 0.9rem;
            line-height: 1.55;
        }
    }

    .eyebrow,
    .header-actions label > span {
        margin: 0;
        color: var(--faint);
        font-size: 0.7rem;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
    }

    /* Vault picker beside the format badge. Single-axis row → flex. */
    .header-actions {
        display: flex;
        align-items: center;
        gap: 0.75rem;

        label {
            display: flex;
            align-items: center;
            gap: 0.45rem;
        }

        select { width: auto; min-width: 11rem; }
    }

    .format-badge {
        padding: 0.3rem 0.55rem;
        border: 0.0625rem solid var(--line-3);
        border-radius: 999rem;
        color: var(--muted);
        background: var(--raised);
        font-family: "SF Mono", "Fira Code", monospace;
        font-size: 0.7rem;
    }

    #add-knowledge-form {
        display: grid;
        /* tabs, editor (absorbs slack), then feedback + footer as auto rows. */
        grid-template-rows: auto minmax(0, 1fr);
        min-height: 0;
        gap: 1rem;
    }

    /* Write / Preview tabs — same radio-driven pattern as the entity page.
       Single-axis row, so flex: it lets the format badge sit hard right
       (margin-left:auto) while the tabs stay packed left. */
    .ui-tabpanel {
        display: flex;
        align-items: center;
        border-bottom: 0.0625rem solid var(--line);

        > .format-badge {
            margin-left: auto;
        }

        > .ui-tabpanel-label {
            display: inline-grid;
            padding: 0.3rem 0.75rem;
            cursor: pointer;
            user-select: none;
            color: var(--muted);
            font-size: 0.78rem;
            font-weight: 600;
            border-bottom: 0.125rem solid transparent;

            > input[type="radio"] {
                position: absolute;
                opacity: 0;
                pointer-events: none;
                width: 0;
                height: 0;
            }

            &:hover { color: var(--text); }

            &:has(input:checked) {
                color: var(--text);
                border-bottom-color: var(--brand);
            }

            /* Keyboard focus has to be visible — the real radio is hidden. */
            &:has(input:focus-visible) {
                outline: 0.125rem solid var(--brand);
                outline-offset: -0.125rem;
            }
        }
    }

    select,
    textarea {
        width: 100%;
        color: var(--text);
        background: var(--bg);
        border: 0.0625rem solid var(--line);
        border-radius: 0.4rem;
        font: inherit;
        box-shadow: inset 0 0.1rem 0.25rem hsl(0deg 0% 0% / 0.22);

        &:focus-visible {
            outline: 0.125rem solid var(--brand);
            outline-offset: 0.125rem;
            border-color: var(--brand);
        }
    }

    select {
        padding: 0.55rem 0.7rem;
        font-size: 0.85rem;
    }

    /* One pane at a time (tabs), so whichever is active spans the full panel.
       No frame of its own — the textarea already carries a border + inset
       shadow, and a panel around it just boxed a box. */
    .editor-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        min-height: 18rem;
    }

    .editor-grid > .ui-tabpanel-body { display: none; }
    &:has([name="add-editor-tab"][value="write"]:checked) .editor-pane { display: grid; }
    &:has([name="add-editor-tab"][value="preview"]:checked) .preview-pane { display: grid; }

    .editor-pane,
    .preview-pane {
        grid-template-rows: minmax(0, 1fr) auto;
        min-width: 0;
    }

    .editor-pane {
        gap: 0.65rem;
    }

    textarea {
        height: 100%;
        min-height: 12rem;
        padding: 0.9rem;
        resize: none;
        /* One thin outline only: the shared inset shadow read as a second
           line inside the border at this size. */
        box-shadow: none;

        /* Focus ring flush with the border, so it thickens the existing line
           instead of drawing a second one outside it. */
        &:focus-visible {
            outline-offset: 0;
        }
        font-family: "SF Mono", "Fira Code", monospace;
        font-size: 0.84rem;
        line-height: 1.6;
    }

    /* Capture note and character count share the strip under the editor. */
    .editor-foot {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
    }

    .capture-note,
    .character-count {
        color: var(--faint);
        font-size: 0.7rem;
    }

    .character-count {
        font-variant-numeric: tabular-nums;
    }

    .preview-pane {
        grid-template-rows: minmax(0, 1fr);
        gap: 0.65rem;
        overflow: auto;
    }

    .preview-empty {
        align-self: center;
        justify-self: center;
        color: var(--faint);
        font-size: 0.85rem;
    }

    .preview-content {
        min-width: 0;
        font-size: 0.9rem;
        line-height: 1.65;

        h1,
        h2,
        h3 {
            margin: 1.1rem 0 0.5rem;
            color: var(--text);
            font-weight: 650;
        }

        h1:first-child,
        h2:first-child,
        h3:first-child {
            margin-top: 0;
        }

        h1 { font-size: 1.45rem; }
        h2 { font-size: 1.2rem; }
        h3 { font-size: 1rem; }

        p,
        ul,
        ol,
        pre,
        blockquote {
            margin: 0 0 0.8rem;
        }

        ul,
        ol {
            padding-left: 1.3rem;
        }

        code {
            padding: 0.1rem 0.3rem;
            border-radius: 0.25rem;
            color: var(--clay);
            background: var(--code-bg);
            font-family: "SF Mono", "Fira Code", monospace;
            font-size: 0.86em;
        }

        pre {
            overflow-x: auto;
            padding: 0.8rem;
            border: 0.0625rem solid var(--line);
            border-radius: 0.4rem;
            background: var(--code-bg);

            code {
                padding: 0;
                color: var(--text);
                background: transparent;
            }
        }

        blockquote {
            padding-left: 0.8rem;
            border-left: 0.2rem solid var(--brand);
            color: var(--muted);
        }

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

    .feedback {
        display: none;
        padding: 0.8rem 1rem;
        border-radius: 0.4rem;
        font-size: 0.85rem;
    }

    &[data-state="error"] .error {
        display: block;
        color: var(--stuck);
        border: 0.0625rem solid color-mix(in srgb, var(--stuck) 45%, transparent);
        background: color-mix(in srgb, var(--stuck) 10%, transparent);
    }

    &[data-state="success"] .success {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        gap: 0.45rem;
        color: var(--ok);
        border: 0.0625rem solid color-mix(in srgb, var(--ok) 45%, transparent);
        background: color-mix(in srgb, var(--ok) 10%, transparent);
    }

    /* Submit lives in the header row now, so the primary-button styling
       travels with it. */
    .header-actions {
        button {
            padding: 0.65rem 1.1rem;
            border: 0;
            border-radius: 0.4rem;
            color: var(--bg);
            background: var(--brand);
            font: inherit;
            font-size: 0.85rem;
            font-weight: 700;
            cursor: pointer;
            box-shadow: 0 0.45rem 1rem hsl(0deg 0% 0% / 0.2),
                0 0.1rem 0.25rem hsl(0deg 0% 0% / 0.2);

            &:hover:not(:disabled) {
                filter: brightness(1.08);
            }

            &:disabled {
                opacity: 0.6;
                cursor: wait;
            }
        }
    }

    /* No 58rem split-collapse rule any more — tabs show one pane at any width. */
    @media (max-width: 38rem) {
        .add-header {
            grid-template-columns: 1fr;
        }

        .header-actions {
            flex-wrap: wrap;
        }

        &[data-state="success"] .success {
            grid-template-columns: 1fr;
        }
    }
}



ui-vault-profile {
    display: grid;
    gap: 1rem;
    max-width: 72rem;
    margin: 0 auto;

    .vault-desc {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        align-items: start;
        gap: 0.75rem;

        .vault-desc-text {
            color: var(--muted);
            font-size: 0.92rem;
            line-height: 1.55;
        }

        &[data-state="generating"] .vault-desc-text { color: var(--faint); font-style: italic; }
        &[data-state="error"] .vault-desc-text { color: var(--stuck); }
    }

    /* Icon-only nav actions (Context/hub, Regenerate/cached, Settings). Same
       currentColor mask treatment as the header #page-nav icons. */
    .vault-profile-head nav {
        .nav-icon {
            display: grid;
            place-items: center;
            padding: 0.25rem;
            background: none;
            border: none;
            cursor: pointer;
            color: var(--muted);
            opacity: 0.5;
            transition: opacity 0.15s, color 0.15s;

            &:hover { opacity: 1; color: var(--brand); }
            &:disabled { opacity: 0.35; cursor: default; }
        }

        .icon {
            display: block;
            width: 1.2rem;
            height: 1.2rem;
            background: currentColor;
            mask: no-repeat center / contain;

            &.icon-hub { mask-image: url("/img/hub.svg"); }
            &.icon-cached { mask-image: url("/img/cached.svg"); }
            &.icon-settings { mask-image: url("/img/settings.svg"); }
        }
    }

    .activity-head {
        display: grid;
        grid-auto-flow: column;
        justify-content: space-between;
        align-items: baseline;
        margin-bottom: 0.7rem;

        h2 { font-size: 0.9rem; font-weight: 650; }
        span { color: var(--faint); font-size: 0.78rem; font-variant-numeric: tabular-nums; }
    }

    .activity-scroll {
        overflow-x: auto;
        padding-bottom: 0.25rem;
    }

    .activity-heatmap {
        display: grid;
        grid-auto-flow: column;
        grid-template-rows: repeat(7, 1fr);
        grid-auto-columns: 1fr;
        gap: 3px;
        width: 100%;
        height: 7rem; /* fill the panel; the grid stretches the 7 rows to fit */
    }

    .heat-cell {
        border-radius: 2px;
        background: var(--raised);

        &[data-level="1"] { background: color-mix(in srgb, var(--brand) 30%, var(--raised)); }
        &[data-level="2"] { background: color-mix(in srgb, var(--brand) 55%, var(--raised)); }
        &[data-level="3"] { background: color-mix(in srgb, var(--brand) 78%, var(--raised)); }
        &[data-level="4"] { background: var(--brand); }
    }

    .activity-empty { color: var(--faint); font-size: 0.85rem; }

    /* Stat tiles between the heatmap and the panels, matching the home page. */
    .profile-metrics {
        display: grid;
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 0.75rem;

        /* Each tile deep-links to its filtered view. */
        a {
            border: 1px solid var(--line);
            background: var(--panel);
            border-radius: 0.45rem;
            padding: 0.7rem 0.85rem;
            display: grid;
            gap: 0.1rem;
            color: var(--text);
            text-decoration: none;
            transition: border-color 0.15s, background 0.15s;

            &:hover {
                border-color: var(--brand);
                background: var(--raised);
            }
        }

        span {
            font-size: 1.5rem;
            font-weight: 650;
            font-variant-numeric: tabular-nums;
        }

        label {
            color: var(--faint);
            font-size: 0.68rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
            cursor: pointer;
        }
    }

    /* Hero: avatar in column 1 alongside the stacked title (row 1) + auto-curated
       description (row 2). */
    .vault-hero {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        gap: 1rem;
        align-items: start;
    }

    .vault-hero-body {
        display: grid;
        gap: 0.5rem;
        min-width: 0;
    }

    .vault-avatar {
        width: 4rem;
        height: 4rem;
        border-radius: 0.6rem;
        object-fit: cover;

        /* The hero grid top-aligns the avatar with the back-link row; push it
           down by that row's height (0.78rem × 1.4 line-height, pinned on
           .back-link below) so it tops out level with the vault name. */
        margin-top: calc(0.78rem * 1.4);
    }

    /* Fallback when the vault has no custom avatar: a muted brain glyph filling
       the avatar footprint, no tile background or border. */
    .vault-avatar-ph {
        display: grid;
        place-items: center;
        background: none;

        /* `display: grid` would otherwise beat the UA [hidden] rule. */
        &[hidden] { display: none; }

        .icon {
            width: 100%;
            height: 100%;
            background: var(--muted);
            mask: url("/img/brain-icon.svg") no-repeat center / contain;
        }
    }

    .vault-profile-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: end;
        gap: 1rem;

        h1 {
            font-size: 1.6rem;
            font-weight: 650;
            line-height: 1.2;
        }

        nav {
            display: grid;
            grid-auto-flow: column;
            gap: 0.65rem;
        }
    }

    /* Block + pinned line-height so the row's height is the link's own
       (0.78rem × 1.4), not the parent's 1rem strut — .vault-avatar's
       margin-top mirrors it to top-align the avatar with the vault name. */
    .back-link {
        display: block;
        line-height: 1.4;
    }

    .back-link,
    .settings-link {
        color: var(--text);
        font-size: 0.78rem;
        text-decoration: underline dotted;
        text-underline-offset: 0.15em;
        text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);

        &:hover { color: var(--brand); text-decoration-style: solid; }
    }

    &[data-state="ready"] .loading,
    &[data-state="error"] .loading,
    &:not([data-state="error"]) .error {
        display: none;
    }

    .summary-grid {
        display: grid;
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 0.6rem;

        article {
            border: 1px solid var(--line);
            background: var(--panel);
            border-radius: 0.45rem;
            padding: 0.8rem 0.9rem;
            display: grid;
            gap: 0.1rem;
        }

        span {
            font-size: 1.35rem;
            font-weight: 650;
            font-variant-numeric: tabular-nums;
        }

        label {
            color: var(--faint);
            font-size: 0.72rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }
    }

    .profile-grid {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.8rem;
        align-items: start;
    }

    .panel {
        border: 1px solid var(--line);
        background: var(--panel);
        border-radius: 0.45rem;
        padding: 0.9rem;
        min-width: 0;

        h2 {
            font-size: 0.88rem;
            font-weight: 650;
            margin-bottom: 0.65rem;
        }

        ul {
            list-style: none;
            display: grid;
            gap: 0.45rem;
        }

        li {
            color: var(--muted);
            font-size: 0.82rem;
            min-width: 0;
        }

        a {
            color: var(--text);
            text-decoration: underline dotted;
            text-underline-offset: 0.15em;
            text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);

            &:hover { color: var(--brand); text-decoration-style: solid; }
        }
    }

    .coverage-meter {
        height: 0.55rem;
        background: var(--bg);
        border: 1px solid var(--line);
        border-radius: 99rem;
        overflow: hidden;
        margin-bottom: 0.55rem;

        span {
            display: block;
            height: 100%;
            width: 0;
            background: color-mix(in srgb, var(--brand) 50%, transparent);
        }
    }

    .coverage-panel p {
        color: var(--muted);
        font-size: 0.82rem;
        margin-bottom: 0.7rem;
    }

    .entity-list li {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto auto;
        gap: 0.5rem;
        align-items: baseline;

        a {
            color: var(--text);
            text-decoration: underline dotted;
            text-underline-offset: 0.15em;
            text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;

            &:hover { color: var(--brand); text-decoration-style: solid; }
        }

        a[data-stale="true"]::after {
            content: " stale";
            color: var(--stuck);
            font-size: 0.68rem;
        }

        span {
            color: var(--faint);
            font-size: 0.66rem;
            text-transform: uppercase;
        }

        strong {
            color: var(--text);
            font-size: 0.75rem;
            font-variant-numeric: tabular-nums;
        }
    }

    .bar-list li {
        display: grid;
        gap: 0.25rem;

        div {
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            gap: 0.7rem;
        }

        span {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        /* Tag label is a link into the filtered Entities page. */
        a {
            color: var(--text);
            text-decoration: underline dotted;
            text-underline-offset: 0.15em;
            text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
            cursor: pointer;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;

            &:hover { color: var(--brand); text-decoration-style: solid; }
        }

        strong {
            color: var(--text);
            font-variant-numeric: tabular-nums;
        }

        /* Same treatment as the Atom-coverage bar: a rounded green pill. */
        meter {
            width: 100%;
            height: 0.55rem;
            border: 1px solid var(--line);
            border-radius: 99rem;
            overflow: hidden;
            background: var(--bg);

            &::-webkit-meter-bar {
                background: var(--bg);
                border: none;
                border-radius: 99rem;
            }

            &::-webkit-meter-optimum-value { background: color-mix(in srgb, var(--brand) 50%, transparent); }
            &::-moz-meter-bar { background: color-mix(in srgb, var(--brand) 50%, transparent); }
        }
    }

    @media (max-width: 760px) {
        .summary-grid,
        .profile-grid {
            grid-template-columns: 1fr;
        }
        .profile-metrics { grid-template-columns: repeat(2, 1fr); }
    }
}



ui-vault-metrics {
    display: grid;
    align-content: start;
    gap: 0.75rem;
    padding: 1rem;
    overflow-y: auto;

    header {
        display: grid;
        gap: 0.1rem;

        h2 {
            font-size: 0.95rem;
            font-weight: 650;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
    }

    .vm-titlerow {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        gap: 0.5rem;
    }

    /* Right-aligned cog to this vault's settings. */
    .vm-settings {
        display: grid;
        place-items: center;
        color: var(--muted);
        opacity: 0.5;
        transition: opacity 0.15s, color 0.15s;

        &:hover { opacity: 1; color: var(--brand); }

        .icon {
            width: 1.1rem;
            height: 1.1rem;
            background: currentColor;
            mask: url("/img/settings.svg") no-repeat center / contain;
        }
    }

    .vm-avatar {
        width: 1.5rem;
        height: 1.5rem;
        border-radius: 0.3rem;
        object-fit: cover;
        border: 1px solid var(--line);
    }

    /* Fallback avatar: a muted brain glyph filling the footprint, no tile. */
    .vm-avatar-ph {
        display: grid;
        place-items: center;
        border: none;

        /* `display: grid` would otherwise beat the UA [hidden] rule. */
        &[hidden] { display: none; }

        .icon {
            width: 100%;
            height: 100%;
            background: var(--muted);
            mask: url("/img/brain-icon.svg") no-repeat center / contain;
        }
    }

    /* Match the main sidebar list rows: muted, full-width hover, brand rail.
       Full-bleed against the 1rem root padding. */
    .vm-nav {
        display: grid;
        margin: 0 -1rem;
        padding: 0.25rem 0;
        border-top: 1px solid var(--line);

        a {
            display: grid;
            grid-template-columns: auto minmax(0, 1fr);
            align-items: center;
            gap: 0.6rem;
            padding: 0.45rem 1rem;
            border-left: 3px solid transparent;
            color: var(--muted);
            font-size: 0.82rem;
            text-decoration: none;
            transition: all 0.15s ease;

            &:hover {
                background: var(--raised);
                border-left-color: var(--brand);
                color: var(--text);
            }
        }

        .icon {
            width: 1.1rem;
            height: 1.1rem;
            flex-shrink: 0;
            background: currentColor;
            mask: no-repeat center / contain;

            &.icon-entities { mask-image: url("/img/entities.svg"); }
            &.icon-docs { mask-image: url("/img/docs.svg"); }
            &.icon-map { mask-image: url("/img/map.svg"); }
            &.icon-todos { mask-image: url("/img/todos.svg"); }
        }
    }

    .vm-error {
        color: var(--stuck);
        font-size: 0.8rem;
    }
}



ui-search-results {
    display: grid;
    gap: 1rem;
    max-width: 72rem;
    margin: 0 auto;

    .search-head {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: baseline;
        gap: 0.75rem;
        border-bottom: 1px solid var(--line);
        padding-bottom: 0.9rem;

        h1 {
            font-size: 1.45rem;
            font-weight: 650;
        }

        span {
            color: var(--faint);
            font-size: 0.82rem;
            font-variant-numeric: tabular-nums;
        }
    }

    .empty,
    .loading,
    .error,
    ol {
        display: none;
    }

    &[data-state="idle"] .empty,
    &[data-state="loading"] .loading,
    &[data-state="error"] .error {
        display: block;
    }

    &[data-state="ready"] ol {
        display: grid;
    }

    .empty,
    .loading {
        color: var(--faint);
        font-size: 0.86rem;
    }

    .error {
        color: var(--error);
        font-size: 0.86rem;
    }

    ol {
        list-style-position: inside;
        gap: 0.75rem;
    }

    li {
        border-top: 1px solid var(--line);
        padding-top: 0.75rem;
        display: grid;
        gap: 0.4rem;

        header {
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            gap: 0.75rem;
            align-items: baseline;
        }

        a {
            color: var(--link);
            text-decoration: none;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;

            &:hover {
                text-decoration: underline;
            }
        }

        strong {
            color: var(--text);
            font-variant-numeric: tabular-nums;
            font-size: 0.78rem;
        }

        .meta {
            color: var(--faint);
            font-size: 0.74rem;
        }

        p {
            color: var(--muted);
            font-size: 0.85rem;
            line-height: 1.55;
        }
    }
}



ui-inbox-board {
    display: grid;
    gap: 1rem;

    .inbox-filters {
        display: flex;
        flex-wrap: wrap;
        align-items: end;
        gap: 0.75rem;

        label {
            display: grid;
            gap: 0.25rem;
            color: var(--muted);
            font-size: 0.75rem;
        }

        input,
        select {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.3rem;
            padding: 0.35rem 0.45rem;
            font: inherit;
            font-size: 0.82rem;
        }

        input { width: 6rem; }

        button {
            border: 1px solid var(--brand);
            border-radius: 0.35rem;
            background: var(--brand);
            color: var(--bg);
            cursor: pointer;
            font-weight: 650;
            font-size: 0.82rem;
            padding: 0.45rem 0.7rem;

            &:disabled {
                border-color: var(--line);
                background: none;
                color: var(--faint);
                cursor: default;
            }
        }

        button.retry-all {
            border-color: var(--line);
            background: none;
            color: var(--text);

            &:hover:not(:disabled) {
                background: var(--stuck);
                border-color: var(--stuck);
                color: var(--bg);
            }
        }
    }

    .inbox-head {
        border-bottom: 1px solid var(--line);
        padding-bottom: 0.9rem;
        h1 { font-size: 1.45rem; font-weight: 650; }
        p { color: var(--muted); font-size: 0.88rem; margin-top: 0.25rem; }
    }

    .loading,
    .error,
    .inbox-summary,
    .inbox-table {
        display: none;
    }

    &[data-state="loading"] .loading,
    &[data-state="error"] .error {
        display: block;
    }

    &[data-state="ready"] {
        .inbox-summary { display: block; }
        .inbox-table { display: grid; }
    }

    .inbox-summary {
        color: var(--muted);
        font-size: 0.82rem;
    }

    .inbox-table {
        border: 1px solid var(--line);
        border-radius: 0.45rem;
        background: var(--panel);
        overflow: hidden;
    }

    .row {
        display: grid;
        grid-template-columns: 6rem 8rem 5rem 5rem minmax(0, 1fr) 5rem;
        gap: 0.7rem;
        padding: 0.55rem 0.75rem;
        border-top: 1px solid var(--line);
        align-items: start;
        font-size: 0.8rem;

        &.head {
            border-top: 0;
            color: var(--faint);
            text-transform: uppercase;
            letter-spacing: 0.05em;
            font-size: 0.68rem;
            font-weight: 650;
        }

        &[data-status="errored"],
        &[data-status="failed"] {
            border-left: 3px solid var(--stuck);
        }

        &[data-status="pending"],
        &[data-status="review"] {
            border-left: 3px solid var(--brand);
        }

        .row-action {
            display: flex;
            align-items: start;
        }

        button.retry {
            padding: 0.2rem 0.6rem;
            border: 1px solid var(--line);
            border-radius: 0.3rem;
            background: none;
            color: var(--text);
            font-size: 0.75rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s, color 0.15s;

            &:hover:not(:disabled) {
                background: var(--brand);
                color: var(--bg);
            }

            &:disabled {
                color: var(--faint);
                cursor: default;
            }
        }

        span {
            min-width: 0;
        }

        strong {
            display: block;
            color: var(--text);
            font-family: "SF Mono", monospace;
            font-size: 0.74rem;
        }

        em {
            display: block;
            color: var(--faint);
            font-style: normal;
            overflow-wrap: anywhere;
        }

        p {
            color: var(--muted);
            margin-top: 0.2rem;
            overflow-wrap: anywhere;
        }
    }

    @media (max-width: 760px) {
        .row {
            grid-template-columns: 1fr;
        }
    }
}



/* ui-ask-panel — RAG ask pane (/ui/ask main pane).
   Rules moved from assets/css/ui.css (#ask-detail / .ask-* / #ask-answer
   typography), re-scoped under the component element. */

ui-ask-panel {
    display: block;
    max-width: 47.5rem; /* 760px in old #ask-detail */

    /* ── State panes — visibility driven by data-state on the component root ── */
    .ask-empty,
    .loading,
    .error,
    #ask-answer {
        display: none;
    }
    &[data-state="idle"] .ask-empty {
        display: block;
    }
    &[data-state="loading"] .loading {
        display: block;
    }
    &[data-state="error"] .error {
        display: block;
    }
    &[data-state="answer"] #ask-answer {
        display: block;
    }

    /* ── Header ── */
    .skill-header {
        margin-bottom: 1.5rem;
        padding-bottom: 1rem;
        border-bottom: 1px solid var(--line);

        h2 {
            font-size: 1.4rem;
            font-weight: 600;
            color: var(--text);
        }
        .description {
            font-size: 0.9rem;
            color: var(--muted);
            margin-top: 0.5rem;
            line-height: 1.6;
        }
    }

    /* ── Answer body ── */
    .ask-body {
        font-size: 0.9rem;
        line-height: 1.65;
    }
    .ask-empty {
        color: var(--faint);
        font-size: 0.85rem;
    }
    .loading {
        color: var(--faint);
        font-size: 0.85rem;
        padding: 2rem 0;
    }
    .error {
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }

    /* ── Sources box — shown only once sources arrive (data-has-sources) ── */
    #ask-sources {
        display: none;
    }
    &[data-has-sources="true"] #ask-sources {
        display: block;
        margin-top: 1.5rem;
        padding-top: 1rem;
        border-top: 1px solid var(--line);
    }
    #ask-sources h3 {
        font-size: 0.85rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--faint);
        margin-bottom: 0.5rem;
    }
    .file-list {
        list-style: none;

        li {
            padding: 0.3rem 0;
        }
        a {
            font-size: 0.85rem;
            font-family: "SF Mono", "Fira Code", monospace;
            color: var(--link);
            cursor: pointer;
            transition: color 0.15s;

            &:hover {
                text-decoration: underline;
            }
        }
    }
    .ask-score {
        font-size: 0.7rem;
        color: var(--faint);
        font-variant-numeric: tabular-nums;
        margin-left: 0.4rem;
    }

    /* ── Answer markdown — mirrors the shared body typography ── */
    #ask-answer {
        h1,
        h2,
        h3 {
            font-weight: 600;
            margin: 1rem 0 0.5rem;
            color: var(--text);
        }
        h1 {
            font-size: 1.2rem;
        }
        h2 {
            font-size: 1.05rem;
        }
        h3 {
            font-size: 0.95rem;
        }
        p,
        li {
            color: var(--text);
        }
        p {
            margin: 0 0 0.75rem;
        }
        ul,
        ol {
            margin: 0 0 0.75rem 1.25rem;
        }
        li {
            margin-bottom: 0.25rem;
        }
        a {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }
        code {
            background: var(--raised);
            padding: 0.1em 0.35em;
            border-radius: 0.1875rem;
            font-size: 0.85em;
            font-family: "SF Mono", "Fira Code", monospace;
            color: var(--clay);
        }
        pre {
            background: var(--code-bg);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.75rem 1rem;
            overflow-x: auto;
            margin: 0 0 0.75rem;
            font-size: 0.82rem;

            code {
                background: none;
                padding: 0;
                color: var(--text);
            }
        }
    }
}



/* ui-metrics-panel — /healthz dashboard (/ui/metrics main pane).
   Rules moved from assets/css/ui.css (#metrics-detail / .metrics-* /
   .metric-*), re-scoped under the component element. */

ui-metrics-panel {
    display: block;
    /* No max-width of its own — it was 900px from the old dedicated /metrics
       page, which made this panel narrower than the Processing and link-card
       sections beside it. The page wrapper (.settings-page) owns the cap. */

    /* ── State panes — visibility driven by data-state on the component root ── */
    .loading,
    .error,
    .metrics-grid {
        display: none;
    }
    &[data-state="loading"] .loading {
        display: block;
    }
    &[data-state="error"] .error {
        display: block;
    }
    &[data-state="ready"] .metrics-grid {
        display: grid;
    }

    .loading {
        color: var(--faint);
        font-size: 0.85rem;
        padding: 2rem 0;
    }
    .error {
        color: var(--stuck);
        font-size: 0.85rem;
        padding: 1rem 0;
    }

    /* ── Metric cards ── */
    /* Six fixed columns — auto-fill packed 8 narrow cards in at this width and
       wrapped the longer values. No top margin: the panel is the first thing
       under the page title, and the parent grid's gap already spaces it. */
    .metrics-grid {
        grid-template-columns: repeat(6, minmax(0, 1fr));
        gap: 0.75rem;
        margin: 0 0 1rem;
    }

    @media (max-width: 64rem) {
        .metrics-grid {
            grid-template-columns: repeat(3, minmax(0, 1fr));
        }
    }

    @media (max-width: 36rem) {
        .metrics-grid {
            grid-template-columns: repeat(2, minmax(0, 1fr));
        }
    }
    .metric-card {
        background: var(--panel);
        border: 1px solid var(--line);
        border-radius: 0.5rem;
        padding: 0.9rem 1rem;
    }
    .metric-value {
        font-size: 1.6rem;
        font-weight: 600;
        color: var(--text);
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }

    /* The unit rides with the number but at label weight — "221.7 MB" stays on
       one line and the eye lands on the figure, not the suffix. */
    .metric-unit {
        margin-left: 0.2rem;
        font-size: 0.85rem;
        font-weight: 500;
        color: var(--muted);

        &:empty {
            display: none;
        }
    }
    .metric-label {
        font-size: 0.7rem;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--faint);
        margin-top: 0.25rem;
    }
}



/* ui-shortcuts — the `?` help overlay. The host renders nothing itself; only
   the dialog is visible, and only while open. */

ui-shortcuts {
    display: contents;
}

.shortcuts-dialog {
    max-width: 26rem;
    /* The global reset zeroes margins, which is what centres a native modal —
       restore it or the dialog pins to the top-left. */
    margin: auto;
    padding: 1.25rem;
    border: 1px solid var(--line);
    border-radius: 0.6rem;
    background: var(--panel);
    color: var(--text);

    &::backdrop {
        background: hsl(0deg 0% 0% / 0.55);
    }

    header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        margin-bottom: 0.9rem;

        h3 {
            margin: 0;
            font-size: 1rem;
            font-weight: 650;
        }
    }

    .shortcuts-close {
        border: 0;
        background: none;
        color: var(--faint);
        font: inherit;
        font-size: 0.9rem;
        cursor: pointer;

        &:hover { color: var(--text); }
    }

    /* Keys left, meaning right — a two-column <dl> so the pairing is semantic
       rather than positional. */
    .shortcuts-list {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        align-items: baseline;
        gap: 0.55rem 1rem;
        margin: 0;

        dt {
            display: flex;
            gap: 0.2rem;
            white-space: nowrap;
        }

        dd {
            margin: 0;
            color: var(--muted);
            font-size: 0.85rem;
        }

        kbd {
            padding: 0.1rem 0.35rem;
            border: 1px solid var(--line);
            border-radius: 0.25rem;
            background: var(--bg);
            color: var(--text);
            font-family: inherit;
            font-size: 0.72rem;
        }
    }
}



/* ui-profile — the caller's own page. Master/detail via CSS Grid; the master is
   a fixed column, the detail takes the rest and scrolls independently. */
ui-profile {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 1rem;
    min-height: 0;

    .profile-title-row {
        display: grid;
        grid-template-columns: auto 1fr;
        align-items: baseline;
        gap: 0.75rem;
    }
    .profile-meta {
        display: inline-grid;
        grid-auto-flow: column;
        gap: 0.75rem;
        color: var(--muted);
        font-size: 0.85rem;
    }

    .profile-detail {
        display: grid;
        grid-template-rows: auto auto auto minmax(0, 1fr);
        gap: 0.75rem;
        min-height: 0;
    }
    .profile-detail-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: start;
        gap: 1rem;
    }
    .profile-hint {
        color: var(--muted);
        font-size: 0.85rem;
        margin: 0;
        max-width: 44rem;
    }

    /* Radio-driven tabs — the house .ui-tabpanel pattern (entity detail, skill
       form). :has() switches panes, so there is no JS toggling class names and
       no state to keep in sync. Its styles are declared per consumer, not
       globally, so they are repeated here deliberately. */
    .ui-tabpanel {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        border-bottom: 1px solid var(--line);
        margin-bottom: 0.5rem;

        > .ui-tabpanel-label {
            display: inline-grid;
            grid-auto-flow: column;
            align-items: center;
            padding: 0.25rem 0.65rem;
            cursor: pointer;
            user-select: none;
            color: var(--muted);
            font-size: 0.78rem;
            font-weight: 600;
            white-space: nowrap;
            border-bottom: 0.125rem solid transparent;

            > input[type="radio"] {
                position: absolute;
                opacity: 0;
                pointer-events: none;
                width: 0;
                height: 0;
            }

            &:hover { color: var(--text); }

            &:has(input:checked) {
                color: var(--text);
                border-bottom-color: var(--brand);
            }
        }
    }

    .ui-tabpanel-body { display: none; }
    &:has([name="profile-detail-tab"][value="tokens"]:checked) [data-pane="tokens"] {
        display: grid;
        grid-template-rows: auto auto minmax(0, 1fr);
        gap: 0.75rem;
        min-height: 0;
    }

    .add-btn {
        background: var(--clay-soft);
        color: var(--clay);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.2rem 0.5rem;
        font-size: 0.68rem;
        font-weight: 600;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;
        white-space: nowrap;

        &:hover {
            background: var(--brand);
            color: var(--bg);
        }
    }

    /* .ui-table is a shared skeleton (subgrid rows, fixed header, scrolling
       zebra body); each consumer declares its OWN column widths. Without this
       every cell stacked vertically — the markup was right and the grid had no
       tracks to place it into. */
    .ui-table {
        grid-template-columns: minmax(8rem, 1fr) minmax(8rem, 1.2fr) 9rem 6rem;
        font-size: 0.85rem;
    }

    /* An unscoped token reaches everything its owner does (ADR-0028 §4). Say so
       in the row rather than leaving the cell blank — blank reads as "fine". */
    .scope-unscoped {
        color: var(--warn);
    }

    .link-btn {
        background: none;
        border: none;
        color: var(--brand);
        font-size: 0.85rem;
        cursor: pointer;
        padding: 0;

        &:hover { text-decoration: underline; }
    }

    /* Dialogs. Native <dialog> carries no app styling of its own and the rules
       are declared per component, not globally — reusing the element without
       these gives a white box in the top-left corner with UA buttons. Matched
       to the settings dialogs so the page belongs to the same product. */
    dialog {
        /* The global `* { margin: 0 }` reset kills the UA's margin:auto dialog
           centering — restore it, or showModal() renders top-left. */
        margin: auto;
        background: var(--panel);
        color: var(--text);
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        padding: 1.1rem 1.25rem;
        width: 26rem;
        max-width: 92vw;
        box-shadow: 0 0.5rem 1.5rem hsl(0 0% 0% / 0.4), 0 0.1rem 0.3rem hsl(0 0% 0% / 0.3);

        &::backdrop { background: hsl(0 0% 0% / 0.55); }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin-bottom: 0.6rem;
        }

        label {
            display: grid;
            gap: 0.25rem;
            font-size: 0.8rem;
            color: var(--muted);
            margin-bottom: 0.75rem;
        }
        /* Scope picker: a checkbox per Vault. Sunken + scrolling, so a long Vault
           list cannot push the dialog buttons off-screen. */
        fieldset.vault-picker {
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.5rem 0.6rem 0.6rem;
            margin-bottom: 0.75rem;
            display: grid;
            gap: 0.35rem;
            background: var(--bg);
            box-shadow: inset 0 1px 2px hsl(0 0% 0% / 0.25);

            legend {
                font-size: 0.8rem;
                color: var(--muted);
                padding: 0 0.3rem;
            }
        }

        .vault-list {
            display: grid;
            gap: 0.3rem;
            max-height: 9rem;
            overflow-y: auto;

            /* The rows are label.inline, which the rule below lays out; they carry
               no margin of their own so the grid gap is the only spacing. */
            label.inline { margin-bottom: 0; }
        }

        input[type="text"] {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.35rem 0.6rem;
            font-size: 0.9rem;

            &:focus {
                outline: none;
                border-color: var(--brand);
            }
        }

        /* Scope hint under the Vaults picker. */
        small {
            color: var(--muted);
            font-size: 0.75rem;
        }

        /* A checkbox reads as a control with its text beside it, not above it —
           the grid `label` above would stack them. */
        label.inline {
            grid-auto-flow: column;
            grid-template-columns: auto 1fr;
            align-items: center;
            gap: 0.45rem;
            justify-content: start;
        }

        .error {
            color: var(--clay);
            font-size: 0.8rem;
            min-height: 1rem;
        }

        menu {
            list-style: none;
            display: grid;
            grid-auto-flow: column;
            justify-content: end;
            gap: 0.5rem;
            margin-top: 1rem;

            button {
                border: 1px solid var(--line-2);
                border-radius: 0.3rem;
                background: none;
                color: var(--muted);
                padding: 0.4rem 1rem;
                font-size: 0.85rem;
                font-weight: 600;
                cursor: pointer;

                &.danger-confirm {
                    background: var(--stuck);
                    border-color: var(--stuck);
                    color: var(--bg);
                }

                &[type="submit"], &[value="done"] {
                    background: var(--brand);
                    border-color: var(--brand);
                    color: var(--bg);
                }
            }
        }
    }

    /* The one-time reveal. Monospace and wrapping, because it will be copied by
       hand and a truncated token is worse than an ugly one. */
    .token-value {
        background: var(--bg);
        border: 1px solid var(--line);
        border-radius: 0.375rem;
        padding: 0.6rem;
        font-family: ui-monospace, monospace;
        font-size: 0.85rem;
        overflow-wrap: anywhere;
        /* Inset: this is a value to read out of, not a raised control. */
        box-shadow: inset 0 1px 2px hsl(0 0% 0% / 0.25);
    }

    &[data-state="loading"] .profile-detail { opacity: 0.5; }
}



/* ui-settings-home — Settings landing (/ui/settings): metrics panel, the
   processing-lane toggle, and link-cards to the subsections. The users/vaults
   summary moved into the metrics panel.
   Token bar / status rules carried over from ui-settings-admin; link-cards
   styled like its .settings-section panels. */

ui-settings-home {
    display: grid;
    gap: 1.5rem;
    align-content: start;

    /* Title left, health icons hard right. */
    .settings-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
    }

    .settings-title {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
    }

    /* The plan is context, not the heading — lighter so "Overview" still reads
       as the title. Empty until the settings call returns. */
    .settings-plan {
        color: var(--muted);
        font-weight: 500;
    }

    .settings-health {
        display: flex;
        align-items: center;
        gap: 0.6rem;
    }

    /* Masked glyph tinted by state — colour IS the signal, the tooltip carries
       the words. Focusable so keyboard users can reach the tooltip too. */
    .health-dot {
        width: 1.15rem;
        height: 1.15rem;
        background: currentColor;
        mask: no-repeat center / contain;
        cursor: help;

        &.health-docs { mask-image: url("/img/docs.svg"); }
        &.health-hub { mask-image: url("/img/hub.svg"); }
        &.health-search { mask-image: url("/img/search.svg"); }

        &[data-state="ok"] { color: var(--ok); }
        &[data-state="bad"] { color: var(--stuck); }
        &[data-state="unknown"] { color: var(--faint); }

        &:focus-visible {
            outline: 0.125rem solid var(--brand);
            outline-offset: 0.125rem;
        }
    }

    .settings-status {
        color: var(--ok);
        font-size: 0.85rem;

        /* Empty most of the time — don't let it hold a grid row open. */
        &:empty {
            display: none;
        }

        &[data-error="true"] {
            color: var(--stuck);
        }
    }
    .add-btn {
        background: var(--clay-soft);
        color: var(--clay);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.2rem 0.5rem;
        font-size: 0.68rem;
        font-weight: 600;
        text-transform: none;
        letter-spacing: normal;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;

        &:hover {
            background: var(--brand);
            color: var(--bg);
        }
    }

    /* ── Processing lane toggle (hidden until loaded) ────────────────────── */
    .settings-llm {
        display: none;
        background: var(--panel);
        border: 1px solid var(--line);
        border-radius: 0.5rem;
        padding: 0.75rem 1rem;
        gap: 0.5rem;

        h2 {
            font-size: 1rem;
            font-weight: 600;
            margin: 0;
        }
    }
    &[data-state="loaded"] .settings-llm {
        display: grid;
    }
    .settings-llm-hint {
        margin: 0;
        font-size: 0.85rem;
        color: var(--muted);
    }

    .settings-llm-options {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
        gap: 0.75rem;
        margin-top: 0.25rem;
    }

    /* Card is the label; the radio stays a real radio for keyboard/AT. */
    .settings-llm-option {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        gap: 0.25rem 0.5rem;
        align-items: start;
        /* Cards stretch to equal height; pack rows to the top so the shorter
           card's text doesn't drift down to meet the taller one's. */
        align-content: start;
        padding: 0.75rem 0.9rem;
        border: 1px solid var(--line);
        border-radius: 0.5rem;
        background: var(--bg);
        font-size: 0.9rem;
        color: var(--text);
        cursor: pointer;
        transition: border-color 0.15s, background 0.15s;

        input {
            margin: 0;
            grid-row: 1;
        }

        .option-title {
            grid-row: 1;
            font-weight: 650;
        }

        /* Description and note sit under the title, clear of the radio. */
        .option-desc,
        .option-note {
            grid-column: 2;
            font-size: 0.8rem;
            color: var(--muted);
        }

        .option-note {
            font-style: normal;
            color: var(--faint);

            &:empty { display: none; }
        }

        /* Only while this lane is the active one. */
        .option-warn {
            grid-column: 2;
            display: none;
            padding: 0.35rem 0.5rem;
            border-radius: 0.3rem;
            border: 1px solid var(--stuck);
            background: color-mix(in srgb, var(--stuck) 12%, transparent);
            color: var(--stuck);
            font-size: 0.75rem;
            font-weight: 600;
            line-height: 1.4;
        }

        &:has(input:checked) .option-warn {
            display: block;
        }

        &:hover:not(:has(input:disabled)) {
            border-color: var(--line-3);
        }

        &:has(input:checked) {
            border-color: var(--brand);
            background: var(--raised);
        }

        /* Keyboard focus must show on the card — the radio itself is small. */
        &:has(input:focus-visible) {
            outline: 0.125rem solid var(--brand);
            outline-offset: 0.125rem;
        }

        /* Either option can be unavailable (fast unconfigured, private by plan). */
        &:has(input:disabled) {
            color: var(--muted);
            background: var(--panel);
            cursor: not-allowed;
            opacity: 0.65;
        }
    }

    /* Off-network confirmation. Native <dialog>, so ::backdrop, Esc and the
       focus trap are the platform's job, not ours. */
    .llm-confirm {
        max-width: 30rem;
        /* The global reset zeroes margins, which is what centres a native
           modal — restore it or the dialog pins to the top-left. */
        margin: auto;
        padding: 1.25rem;
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        background: var(--panel);
        color: var(--text);

        &::backdrop {
            background: hsl(0deg 0% 0% / 0.55);
        }

        h3 {
            margin: 0 0 0.6rem;
            font-size: 1rem;
            font-weight: 650;
        }

        p {
            margin: 0 0 0.6rem;
            font-size: 0.85rem;
            line-height: 1.5;
            color: var(--muted);
        }

        .llm-confirm-note {
            color: var(--faint);
            font-size: 0.8rem;
        }
    }

    .llm-confirm-actions {
        display: flex;
        justify-content: flex-end;
        gap: 0.5rem;
        margin-top: 1rem;

        button {
            padding: 0.45rem 0.85rem;
            border: 1px solid var(--line);
            border-radius: 0.4rem;
            background: var(--bg);
            color: var(--text);
            font: inherit;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;

            &:hover { border-color: var(--line-3); }

            /* The consequential one is the off-network switch, not the cancel. */
            &.danger {
                border-color: var(--stuck);
                background: var(--stuck);
                color: var(--bg);

                &:hover { filter: brightness(1.08); }
            }
        }
    }

    .settings-llm-status {
        font-size: 0.85rem;
        color: var(--ok);

        &[data-error="true"] {
            color: var(--stuck);
        }
    }

    /* ── Link-cards to the subsections ───────────────────────────────────── */
    .settings-links {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
        gap: 1rem;
    }
    .settings-link-card {
        display: grid;
        gap: 0.25rem;
        align-content: start;
        background: var(--panel);
        border: 1px solid var(--line);
        border-radius: 0.5rem;
        padding: 1rem 1.25rem;
        color: var(--text);
        text-decoration: none;
        transition: background 0.15s, border-color 0.15s;

        h2 {
            font-size: 1rem;
            font-weight: 600;
            margin: 0;
        }
        p {
            margin: 0;
            font-size: 0.85rem;
            color: var(--muted);
        }
        &:hover {
            background: var(--raised);
            border-color: var(--line-3);
        }
    }
}



/* ui-settings-users — Settings/Users subsection (/ui/settings/users):
   full-width user table (shared .ui-table) with per-row token issue, an
   add-user <dialog> opened from the title row, and the one-time token-reveal
   <dialog> (margin:auto centering fix from ui-doc-detail). */

ui-settings-users {
    /* Fill #main so the user table's BODY is the scroller (shared ui-table
       pattern): title row + table section, section takes the rest. */
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 1rem;
    height: 100%;

    .users-title-row {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: center;
        gap: 0.75rem;
    }
    .settings-title {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
    }
    .count {
        font-size: 0.75rem;
        color: var(--faint);
    }
    .users-title-row .add-btn {
        margin-left: auto;
    }

    /* ── Token gate + body reveal: CSS-driven via data-state on the root ── */
    #users-body {
        display: none;
    }
    &[data-state="ready"] #users-body {
        /* status line + the table, which takes the remaining height */
        display: grid;
        grid-template-rows: auto minmax(0, 1fr);
        min-height: 0;
    }

    .settings-status {
        color: var(--ok);
        font-size: 0.85rem;

        &:empty {
            display: none;
        }
        &[data-error="true"] {
            color: var(--stuck);
        }
    }

    .add-btn {
        background: var(--clay-soft);
        color: var(--clay);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.2rem 0.5rem;
        font-size: 0.68rem;
        font-weight: 600;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;

        &:hover {
            background: var(--brand);
            color: var(--bg);
        }
    }

    /* ── User results — shared .ui-table consumer (components/ui-table) ────
       Only this table's column tracks + local text styles live here; the
       skeleton (subgrid rows, fixed header, scrolling zebra body) is shared. */
    .ui-table {
        grid-template-columns: minmax(10rem, 1fr) minmax(14rem, 1.2fr) 5rem 7rem;
        font-size: 0.85rem;

        .name-link {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }
    }
    .link-btn {
        background: none;
        border: none;
        color: var(--link);
        cursor: pointer;
        font-size: 0.8rem;
        padding: 0;

        &:hover {
            text-decoration: underline;
        }
    }

    /* ── Add/edit-user dialogs — shared chrome (mirrors ui-settings-vaults) ── */
    dialog.user-add,
    dialog.user-edit {
        /* the global `* { margin: 0 }` reset kills the UA's margin:auto dialog
           centering — restore it. */
        margin: auto;
        background: var(--panel);
        color: var(--text);
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        padding: 1.1rem 1.25rem;
        width: 26rem;
        max-width: 92vw;
        box-shadow: 0 0.5rem 1.5rem hsl(0 0% 0% / 0.4), 0 0.1rem 0.3rem hsl(0 0% 0% / 0.3);

        &::backdrop {
            background: hsl(0 0% 0% / 0.55);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin-bottom: 0.6rem;
        }

        .edit-who {
            font-size: 0.85rem;
            color: var(--muted);
            margin-bottom: 0.6rem;

            strong {
                color: var(--clay);
                font-family: "SF Mono", monospace;
                font-weight: 600;
            }
        }

        label {
            display: grid;
            gap: 0.25rem;
            font-size: 0.8rem;
            color: var(--muted);
            margin-bottom: 0.75rem;
        }
        .settings-check {
            display: inline-grid;
            grid-auto-flow: column;
            align-items: center;
            gap: 0.3rem;
            font-size: 0.85rem;
        }
        input[type="text"],
        input[type="email"] {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.35rem 0.6rem;
            font-size: 0.9rem;

            &:focus {
                outline: none;
                border-color: var(--brand);
            }
        }

        .error {
            color: var(--stuck);
            font-size: 0.85rem;

            &:empty {
                display: none;
            }
        }

        menu {
            list-style: none;
            display: grid;
            grid-auto-flow: column;
            justify-content: end;
            gap: 0.5rem;
            margin-top: 1rem;

            button {
                border: 1px solid var(--line-3);
                border-radius: 0.3rem;
                background: none;
                color: var(--muted);
                padding: 0.4rem 1rem;
                font-size: 0.85rem;
                font-weight: 600;
                cursor: pointer;

                &[type="submit"] {
                    background: var(--brand);
                    border-color: var(--brand);
                    color: var(--bg);
                }

                &:hover {
                    color: var(--text);

                    &[type="submit"] {
                        opacity: 0.9;
                        color: var(--bg);
                    }
                }
            }
        }
    }

    /* ── One-time token reveal — native <dialog> (top layer via showModal) ── */
    dialog.token-reveal {
        margin: auto;
        background: var(--panel);
        color: var(--text);
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        padding: 0;
        width: 34rem;
        max-width: 92vw;
        max-height: 85vh;
        overflow-y: auto;
        box-shadow: 0 0.5rem 1.5rem hsl(0deg 0% 0% / 0.4), 0 0.1rem 0.3rem hsl(0deg 0% 0% / 0.3);

        &::backdrop {
            background: hsl(0deg 0% 0% / 0.55);
        }

        .modal-header {
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            align-items: center;
            padding: 0.9rem 1.1rem;
            border-bottom: 1px solid var(--line);

            h3 {
                font-size: 1rem;
                font-weight: 600;
                margin: 0;
            }
        }
        .close-btn {
            background: none;
            border: 1px solid var(--line-3);
            color: var(--muted);
            border-radius: 0.25rem;
            padding: 0.1rem 0.4rem;
            font-size: 0.7rem;
            cursor: pointer;
            transition: all 0.15s;

            &:hover {
                background: var(--raised);
                border-color: var(--line-3);
            }
        }
        .settings-warn {
            color: var(--clay);
            font-size: 0.85rem;
            margin: 0.75rem 1.1rem 0.5rem;
        }
        .settings-token {
            background: var(--code-bg);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.75rem;
            margin: 0 1.1rem 1.1rem;
            font-family: ui-monospace, monospace;
            word-break: break-all;
            color: var(--ok);
        }
    }
}



/* ui-settings-user — single-user detail page (/ui/settings/users/<id>):
   back link + title header, name/role edit form, and the "Grant Options"
   sub-tab — every vault with an access toggle + role select in a shared
   .ui-table. Token gate + data-state reveal mirror ui-settings-users. */

ui-settings-user {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 1rem;
    height: 100%;

    .user-title-row {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: baseline;
        gap: 0.75rem;
    }
    .back-link {
        color: var(--link);
        font-size: 0.8rem;
        text-decoration: none;

        &:hover {
            text-decoration: underline;
        }
    }
    .settings-title {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
    }
    .user-meta {
        font-size: 0.75rem;
        color: var(--faint);

        .mono {
            font-family: ui-monospace, monospace;
        }
    }

    /* ── Token gate + body reveal: CSS-driven via data-state on the root ── */
    #user-body {
        display: none;
    }
    &[data-state="ready"],
    &[data-state="ready-empty"] {
        #user-body {
            /* status + form + tabs, then the vault table takes the rest */
            display: grid;
            grid-template-rows: auto auto auto minmax(0, 1fr) auto;
            gap: 0.75rem;
            min-height: 0;
            align-content: start;
        }
    }
    .grants-empty {
        display: none;
        color: var(--muted);
        font-size: 0.85rem;
        margin: 0;
    }
    &[data-state="ready-empty"] {
        .ui-table {
            display: none;
        }
        .grants-empty {
            display: block;
        }
    }
    /* Load errors arrive before "ready" — reveal only the status line. */
    &[data-state="error"] #user-body {
        display: block;

        > :not(.settings-status) {
            display: none;
        }
    }

    .settings-status {
        color: var(--ok);
        font-size: 0.85rem;

        &:empty {
            display: none;
        }
        &[data-error="true"] {
            color: var(--stuck);
        }
    }

    /* ── Header edit form — name + role, PATCH on Save ─────────────────── */
    #user-detail-form {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: end;
        gap: 0.75rem;

        label {
            display: grid;
            gap: 0.25rem;
            font-size: 0.8rem;
            color: var(--muted);
        }
        input[type="text"],
        select {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.35rem 0.6rem;
            font-size: 0.9rem;

            &:focus {
                outline: none;
                border-color: var(--brand);
            }
        }
        input[type="text"] {
            width: 16rem;
        }
        button[type="submit"] {
            background: var(--brand);
            border: 1px solid var(--brand);
            border-radius: 0.3rem;
            color: var(--bg);
            padding: 0.4rem 1rem;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;

            &:hover {
                opacity: 0.9;
            }
        }
    }

    /* ── Sub tabs ──────────────────────────────────────────────────────── */
    .sub-tabs {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        gap: 0.25rem;
        border-bottom: 1px solid var(--line);

        .sub-tab {
            background: none;
            border: none;
            border-bottom: 2px solid transparent;
            color: var(--muted);
            padding: 0.35rem 0.75rem;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;

            &.active {
                color: var(--text);
                border-bottom-color: var(--brand);
            }
        }
    }

    /* ── Grant options table — Access (fixed) | Vault name ─────────────── */
    .ui-table {
        grid-template-columns: 13rem minmax(12rem, 1fr);
        font-size: 0.85rem;
    }

    /* Access — none|viewer|member button group (segmented control). */
    .btn-group {
        display: inline-grid;
        grid-auto-flow: column;
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        overflow: hidden;
        vertical-align: middle;

        button {
            background: none;
            border: none;
            color: var(--muted);
            padding: 0.2rem 0.6rem;
            font-size: 0.75rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s, color 0.15s;

            &:not(:first-child) {
                border-left: 1px solid var(--line);
            }
            &[aria-pressed="true"] {
                background: var(--brand);
                color: var(--bg);
            }
            &:hover:not([aria-pressed="true"]) {
                color: var(--text);
            }
        }
    }
}



/* ui-settings-vaults — Vaults subsection (/ui/settings/vaults): full-width
   vault table (shared .ui-table) with per-row delete + content counts, an
   add-vault <dialog> (display name + slug) opened from the title row, and a
   native <dialog> delete confirmation (margin:auto centering fix from
   ui-doc-detail). */

ui-settings-vaults {
    /* Fill #main so the vault table's BODY is the scroller (shared ui-table
       pattern): title row + table section, section takes the rest. */
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 1rem;
    height: 100%;

    .vaults-title-row {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: center;
        gap: 0.75rem;
    }
    .settings-title {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
    }
    .count {
        font-size: 0.75rem;
        color: var(--faint);
    }
    .vaults-title-row .add-btn {
        margin-left: auto;
    }

    /* ── No-token gate: CSS-driven via data-state on the root ────────────── */
    /* ── Body: status block + the table, which takes the remaining height ── */
    #vaults-body {
        display: grid;
        grid-template-rows: auto minmax(0, 1fr);
        min-height: 0;
    }

    .add-btn {
        background: var(--clay-soft);
        color: var(--clay);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.2rem 0.5rem;
        font-size: 0.68rem;
        font-weight: 600;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;

        &:hover {
            background: var(--brand);
            color: var(--bg);
        }
    }

    /* ── Error + status lines (:empty-collapsed) ─────────────────────────── */
    .error {
        color: var(--stuck);
        font-size: 0.85rem;
        margin-bottom: 0.75rem;

        &:empty {
            display: none;
        }
    }
    .settings-status {
        color: var(--ok);
        font-size: 0.85rem;
        margin-bottom: 0.75rem;

        &:empty {
            display: none;
        }
    }

    /* ── Vault results — shared .ui-table consumer (components/ui-table) ────
       Only this table's column tracks + local text styles live here; the
       skeleton (subgrid rows, fixed header, scrolling zebra body) is shared. */
    .ui-table {
        /* Vault slug fixed | Display name flexes | counts | actions */
        grid-template-columns: 12rem minmax(8rem, 1fr) 9rem 9rem 6rem 5rem 5rem;
        font-size: 0.85rem;

        .mono {
            font-family: ui-monospace, monospace;
            color: var(--muted);
        }
        .muted {
            color: var(--faint);
        }
        .name-link {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }
        .actions a {
            color: var(--link);
            text-decoration: none;

            &:hover {
                text-decoration: underline;
            }
        }
    }
    .link-btn {
        background: none;
        border: none;
        color: var(--link);
        cursor: pointer;
        font-size: 0.8rem;
        padding: 0;

        &:hover {
            text-decoration: underline;
        }
        &.danger {
            color: var(--stuck);
        }
        &:disabled {
            color: var(--faint);
            cursor: not-allowed;

            &:hover {
                text-decoration: none;
            }
        }
    }

    /* ── Dialogs — shared chrome (add + delete confirmation) ─────────────── */
    dialog {
        /* the global `* { margin: 0 }` reset kills the UA's margin:auto dialog
           centering — restore it. */
        margin: auto;
        background: var(--panel);
        color: var(--text);
        border: 1px solid var(--line);
        border-radius: 0.6rem;
        padding: 1.1rem 1.25rem;
        width: 26rem;
        max-width: 92vw;
        box-shadow: 0 0.5rem 1.5rem hsl(0 0% 0% / 0.4), 0 0.1rem 0.3rem hsl(0 0% 0% / 0.3);

        &::backdrop {
            background: hsl(0 0% 0% / 0.55);
        }

        h3 {
            font-size: 1rem;
            font-weight: 600;
            margin-bottom: 0.6rem;
        }

        p {
            font-size: 0.9rem;
            color: var(--muted);
            line-height: 1.6;

            strong {
                color: var(--clay);
                font-family: "SF Mono", monospace;
                font-weight: 600;
            }
        }

        /* Add-vault form fields. */
        label {
            display: grid;
            gap: 0.25rem;
            font-size: 0.8rem;
            color: var(--muted);
            margin-bottom: 0.75rem;
        }
        input[type="text"] {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.35rem 0.6rem;
            font-size: 0.9rem;

            &:focus {
                outline: none;
                border-color: var(--brand);
            }
        }

        menu {
            list-style: none;
            display: grid;
            grid-auto-flow: column;
            justify-content: end;
            gap: 0.5rem;
            margin-top: 1rem;

            button {
                border: 1px solid var(--line-3);
                border-radius: 0.3rem;
                background: none;
                color: var(--muted);
                padding: 0.4rem 1rem;
                font-size: 0.85rem;
                font-weight: 600;
                cursor: pointer;

                &[type="submit"] {
                    background: var(--brand);
                    border-color: var(--brand);
                    color: var(--bg);
                }
                &.danger-confirm {
                    background: var(--stuck);
                    border-color: var(--stuck);
                    color: var(--bg);
                }

                &:hover {
                    color: var(--text);

                    &[type="submit"],
                    &.danger-confirm {
                        opacity: 0.9;
                        color: var(--bg);
                    }
                }
            }
        }
    }
}



/* ui-settings-vault — single-vault detail page (/ui/settings/vaults/<vault>):
   back link + title header, display-name edit form, and the "User Grant
   Options" sub-tab — every user with a none|viewer|member button group in a
   shared .ui-table. Mirrors ui-settings-user. */

/* The avatar is one control — a label wrapping the hidden file input, so the
   whole tile is the click target for upload/replace. Both children occupy the
   same grid cell; exactly one is unhidden by #refreshAvatar. */
.avatar-field {
    display: grid;
    width: 3.5rem;
    height: 3.5rem;
    cursor: pointer;
    position: relative;

    .avatar-preview,
    .avatar-none {
        grid-area: 1 / 1;
        width: 3.5rem;
        height: 3.5rem;
        border-radius: 0.5rem;
    }
    .avatar-preview {
        object-fit: cover;
        border: 1px solid var(--line);
        background: var(--bg);
    }
    .avatar-none {
        border: 1px dashed var(--line);
        display: grid;
        place-items: center;
        text-align: center;
        color: var(--faint);
        font-size: 0.62rem;
    }
    /* Hover affordance — the tile is the button, so it must say so. */
    &::after {
        content: "";
        grid-area: 1 / 1;
        border-radius: 0.5rem;
        background: hsl(0 0% 0% / 0.45);
        opacity: 0;
        transition: opacity 0.15s;
    }
    &:hover::after,
    &:focus-within::after {
        opacity: 1;
    }
    &:focus-within {
        outline: 2px solid var(--brand);
        outline-offset: 2px;
        border-radius: 0.5rem;
    }
    &[data-busy="true"] {
        cursor: progress;
        opacity: 0.6;
    }
}

ui-settings-vault {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 1rem;
    height: 100%;

    .vault-title-row {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: baseline;
        gap: 0.75rem;
    }
    .back-link {
        color: var(--link);
        font-size: 0.8rem;
        text-decoration: none;

        &:hover {
            text-decoration: underline;
        }
    }
    .settings-title {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
    }
    .vault-meta {
        font-size: 0.75rem;
        color: var(--faint);

        .mono {
            font-family: ui-monospace, monospace;
        }
    }

    /* ── Token gate + body reveal: CSS-driven via data-state on the root ── */
    #vault-body {
        display: none;
    }
    &[data-state="ready"],
    &[data-state="ready-empty"] {
        #vault-body {
            /* Stack compactly, top-aligned — no row stretches (a fixed 1fr row
               left a big gap once the avatar row was added). Page scrolls if the
               grants table gets long. */
            display: grid;
            grid-auto-rows: auto;
            gap: 0.75rem;
            min-height: 0;
            align-content: start;
        }
    }
    .grants-empty {
        display: none;
        color: var(--muted);
        font-size: 0.85rem;
        margin: 0;
    }
    &[data-state="ready-empty"] {
        .ui-table {
            display: none;
        }
        .grants-empty {
            display: block;
        }
    }
    /* Load errors arrive before "ready" — reveal only the status line. */
    &[data-state="error"] #vault-body {
        display: block;

        > :not(.settings-status) {
            display: none;
        }
    }

    .settings-status {
        color: var(--ok);
        font-size: 0.85rem;

        &:empty {
            display: none;
        }
        &[data-error="true"] {
            color: var(--stuck);
        }
    }

    /* ── Identity form — [avatar][name][save] over [description] ────────── */
    #vault-detail-form {
        display: grid;
        grid-template-columns: auto minmax(12rem, 20rem) auto;
        justify-content: start;
        align-items: end;
        gap: 0.75rem;

        .description-field {
            grid-column: 1 / -1;
            display: grid;
            grid-template-columns: 1fr auto;
            align-items: start;
            gap: 0.5rem 0.75rem;
            max-width: 46rem;

            .field-label {
                grid-column: 1 / -1;
                font-size: 0.8rem;
                color: var(--muted);
            }
            .vault-description {
                margin: 0;
                font-size: 0.85rem;
                line-height: 1.45;
                color: var(--text);

                /* No description yet — the placeholder must not read as content. */
                &:empty::before {
                    content: "No description yet.";
                    color: var(--faint);
                }
            }
            button {
                background: none;
                border: 1px solid var(--line);
                border-radius: 0.3rem;
                color: var(--muted);
                padding: 0.3rem 0.7rem;
                font-size: 0.78rem;
                font-weight: 600;
                cursor: pointer;
                white-space: nowrap;

                &:hover:not(:disabled) {
                    color: var(--text);
                    border-color: var(--line-3);
                }
                &:disabled {
                    cursor: progress;
                    opacity: 0.6;
                }
            }
        }

        label:not(.avatar-field) {
            display: grid;
            gap: 0.25rem;
            font-size: 0.8rem;
            color: var(--muted);
        }
        button[type="submit"] {
            align-self: end;
        }
    }

    /* ── Priorities panel — the vault's LLM guidance, its own PATCH ─────── */
    #vault-priorities-form {
        display: grid;
        gap: 0.75rem;
        max-width: 46rem;

        /* Must live here: the id selector outranks .tab-panel[hidden], so the
           generic hide rule alone leaves this panel visible. */
        &[hidden] {
            display: none;
        }

        label {
            display: grid;
            gap: 0.25rem;
            font-size: 0.8rem;
            color: var(--muted);
        }
        small {
            color: var(--faint);
            font-size: 0.72rem;
            line-height: 1.35;
        }
        button[type="submit"] {
            justify-self: start;
        }
    }

    /* Shared field + submit chrome across both forms. */
    input[type="text"],
    textarea {
        background: var(--bg);
        box-shadow: inset 0 1px 3px hsl(0 0% 0% / 0.25);
        color: var(--text);
        border: 1px solid var(--line);
        border-radius: 0.375rem;
        padding: 0.35rem 0.6rem;
        font-size: 0.9rem;
        width: 100%;
        box-sizing: border-box;

        &:focus {
            outline: none;
            border-color: var(--brand);
        }
    }
    textarea {
        font: inherit;
        line-height: 1.4;
        min-height: 6rem;
        resize: vertical;
    }
    button[type="submit"] {
        background: var(--brand);
        border: 1px solid var(--brand);
        border-radius: 0.3rem;
        color: var(--bg);
        padding: 0.4rem 1rem;
        font-size: 0.85rem;
        font-weight: 600;
        cursor: pointer;

        &:hover {
            opacity: 0.9;
        }
    }

    /* Tab panels — one visible at a time; `hidden` must beat the grid display. */
    .tab-panel[hidden] {
        display: none;
    }

    /* ── Sub tabs ──────────────────────────────────────────────────────── */
    .sub-tabs {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        gap: 0.25rem;
        border-bottom: 1px solid var(--line);

        .sub-tab {
            background: none;
            border: none;
            border-bottom: 2px solid transparent;
            color: var(--muted);
            padding: 0.35rem 0.75rem;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;

            &.active {
                color: var(--text);
                border-bottom-color: var(--brand);
            }
        }
    }

    /* ── User grant table — shared .ui-table consumer ──────────────────── */
    .ui-table {
        grid-template-columns: minmax(10rem, 0.8fr) minmax(12rem, 1fr) 13rem;
        font-size: 0.85rem;
    }

    /* Access — none|viewer|member button group (segmented control). */
    .btn-group {
        display: inline-grid;
        grid-auto-flow: column;
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        overflow: hidden;
        vertical-align: middle;

        button {
            background: none;
            border: none;
            color: var(--muted);
            padding: 0.2rem 0.6rem;
            font-size: 0.75rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s, color 0.15s;

            &:not(:first-child) {
                border-left: 1px solid var(--line);
            }
            &[aria-pressed="true"] {
                background: var(--brand);
                color: var(--bg);
            }
            &:hover:not([aria-pressed="true"]) {
                color: var(--text);
            }
        }
    }
}



/* ui-settings-grants — Settings/Grants subsection (/ui/settings/grants).
   Rules carried over from ui-settings-admin (grants section), re-scoped
   under the component element. */

ui-settings-grants {
    display: grid;
    gap: 1.5rem;
    align-content: start;

    .settings-title {
        font-size: 1.25rem;
        font-weight: 600;
        margin: 0;
    }

    /* ── Token gate + body reveal: CSS-driven via data-state on the root ── */
    #grants-body {
        display: none;
    }
    &[data-state="ready"] #grants-body {
        display: block;
    }

    .settings-status {
        color: var(--ok);
        font-size: 0.85rem;

        &:empty {
            display: none;
        }
        &[data-error="true"] {
            color: var(--stuck);
        }
    }

    /* ── Section ─────────────────────────────────────────────────────────── */
    .settings-section {
        background: var(--panel);
        border: 1px solid var(--line);
        border-radius: 0.5rem;
        padding: 1rem 1.25rem;
    }
    .settings-section-head {
        display: grid;
        grid-auto-flow: column;
        justify-content: start;
        align-items: baseline;
        gap: 0.5rem;
        margin-bottom: 0.75rem;

        h2 {
            font-size: 1rem;
            font-weight: 600;
            margin: 0;
        }
    }

    /* ── Form ────────────────────────────────────────────────────────────── */
    .settings-form {
        display: flex;
        gap: 0.5rem;
        flex-wrap: wrap;
        align-items: center;
        margin-bottom: 1rem;

        select {
            background: var(--bg);
            color: var(--text);
            border: 1px solid var(--line);
            border-radius: 0.375rem;
            padding: 0.35rem 0.6rem;
        }
        select:focus {
            outline: none;
            border-color: var(--brand);
        }
    }
    .add-btn {
        background: var(--clay-soft);
        color: var(--clay);
        border: 1px solid var(--line);
        border-radius: 0.3rem;
        padding: 0.2rem 0.5rem;
        font-size: 0.68rem;
        font-weight: 600;
        text-transform: none;
        letter-spacing: normal;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;

        &:hover {
            background: var(--brand);
            color: var(--bg);
        }
    }

    /* ── Table ───────────────────────────────────────────────────────────── */
    .settings-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 0.85rem;

        th {
            text-align: left;
            color: var(--faint);
            font-weight: 500;
            border-bottom: 1px solid var(--line);
            padding: 0.4rem 0.5rem;
        }
        td {
            border-bottom: 1px solid var(--line);
            padding: 0.4rem 0.5rem;
        }
        .mono {
            font-family: ui-monospace, monospace;
            color: var(--muted);
        }
    }
    .link-btn {
        background: none;
        border: none;
        color: var(--link);
        cursor: pointer;
        font-size: 0.8rem;
        padding: 0;

        &:hover {
            text-decoration: underline;
        }
        &.danger {
            color: var(--stuck);
        }
    }
}


