/* design-system: tokens reset layout sidebar cards buttons forms inputs info-list auth-layout selects tables badges edge-panel modals toggle-switch */
/* Copied from design-system/css by tooling/design-system/copy.sh. Edit those files, never this block. */
/* ── Nodge design tokens ─────────────────────────────────────────────────
   The single source of truth for colours, typography, radii, spacing and
   shadow. Dark mode is the default; light mode applies when the browser
   prefers it (and the user has not forced dark) or when the user forces it.

   Derived values, written out:
   - --color-primary-hover is the primary colour mixed with 12% black;
   - --color-error-bg is the error colour at 10% opacity;
   - --color-*-20 are the primary, secondary, accent, muted text and surface
     colours at 20% opacity.
   The light blocks set colours only. Their selectors outrank :root, so any
   other token repeated there would undo a service's own :root override in
   light mode (Central sets --font-ui).
   ────────────────────────────────────────────────────────────────────── */

/* Dark mode (default) */
:root {
  --color-text: #ddd4c5;
  --color-text-muted: #9e9283;
  --color-bg: #161412;
  --color-surface: #1e1b18;
  --color-border: #3a3530;
  --color-control-border: #71675e;
  --color-primary: #cf5e3f;
  --color-secondary: #a885b9;
  --color-accent: #8aa26d;
  --color-error: #e05252;
  --color-warning: #d4a24e;
  --color-on-primary: #ffffff;
  --color-primary-hover: rgb(71.4352941176%, 32.4392156863%, 21.7411764706%);
  --color-error-bg: rgba(224, 82, 82, 0.1);
  --color-primary-20: rgba(207, 94, 63, 0.2);
  --color-secondary-20: rgba(168, 133, 185, 0.2);
  --color-accent-20: rgba(138, 162, 109, 0.2);
  --color-muted-20: rgba(158, 146, 131, 0.2);
  --color-surface-20: rgba(30, 27, 24, 0.2);
  --color-overlay: rgba(0, 0, 0, 0.6);
  --color-hover: rgba(255, 255, 255, 0.06);
  --color-active: #161412;
  --font-ui: 'Satoshi', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-code: 'JetBrains Mono', 'Fira Code', monospace;
  --radius: 10px;
  --radius-sm: 6px;
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

/* Light mode (browser preference — applies when theme = system) */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --color-text: #3a3122;
    --color-text-muted: #7a6f62;
    --color-bg: #fbfbfe;
    --color-surface: #ffffff;
    --color-border: #d3ccc3;
    --color-control-border: #9a9086;
    --color-primary: #c04f30;
    --color-secondary: #9271a2;
    --color-accent: #7a925d;
    --color-error: #c0392b;
    --color-warning: #b07d1a;
    --color-on-primary: #ffffff;
    --color-primary-hover: rgb(66.2588235294%, 27.262745098%, 16.5647058824%);
    --color-error-bg: rgba(192, 57, 43, 0.1);
    --color-primary-20: rgba(192, 79, 48, 0.2);
    --color-secondary-20: rgba(146, 113, 162, 0.2);
    --color-accent-20: rgba(122, 146, 93, 0.2);
    --color-muted-20: rgba(122, 111, 98, 0.2);
    --color-surface-20: rgba(255, 255, 255, 0.2);
    --color-hover: rgba(0, 0, 0, 0.04);
    --color-active: #ffffff;
    --color-overlay: rgba(0, 0, 0, 0.5);
  }
}

/* Light mode (forced via user preference) */
:root[data-theme="light"] {
  --color-text: #3a3122;
  --color-text-muted: #7a6f62;
  --color-bg: #fbfbfe;
  --color-surface: #ffffff;
  --color-border: #d3ccc3;
  --color-control-border: #9a9086;
  --color-primary: #c04f30;
  --color-secondary: #9271a2;
  --color-accent: #7a925d;
  --color-error: #c0392b;
  --color-warning: #b07d1a;
  --color-on-primary: #ffffff;
  --color-primary-hover: rgb(66.2588235294%, 27.262745098%, 16.5647058824%);
  --color-error-bg: rgba(192, 57, 43, 0.1);
  --color-primary-20: rgba(192, 79, 48, 0.2);
  --color-secondary-20: rgba(146, 113, 162, 0.2);
  --color-accent-20: rgba(122, 146, 93, 0.2);
  --color-muted-20: rgba(122, 111, 98, 0.2);
  --color-surface-20: rgba(255, 255, 255, 0.2);
  --color-hover: rgba(0, 0, 0, 0.04);
  --color-active: #ffffff;
  --color-overlay: rgba(0, 0, 0, 0.5);
}
/* -- Fonts -- */
@font-face {
  font-family: 'Satoshi';
  src: url('/theme/fonts/Satoshi-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

/* -- Reset -- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
}

/* The hidden attribute always hides, also on an element whose class sets
   display, so no component needs its own [hidden] rule. */
[hidden] {
  display: none !important;
}

/* Focus is one orange ring around whatever has keyboard focus; a text field
   has it however it was focused. A control keeps its own border on focus,
   so no rule sets outline: none on a control or recolours its border then
   (Leon, 19 Oct). */
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* -- Scrollbars -- the browser's own, as Fabric's: a thin dark thumb on the
   dark page was too hard to see (Leon, 18 Oct). color-scheme follows the
   theme switch, so the browser draws it to match the page. */
:root { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) { color-scheme: light; }
}

body {
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.5;
  background: var(--color-bg);
  color: var(--color-text);
  -webkit-font-smoothing: antialiased;
}

/* -- Links --
   Platform-wide hover convention: links turn secondary (purple) on hover.
   Specificity is (0,1,1), so anchors styled as buttons must re-assert their
   text color in their own :hover rule (see buttons.css / badges.css). */
a:hover {
  color: var(--color-secondary);
}

/* Inline prose link: primary at rest, global purple on hover.
   Kept at (0,1,0) so a:hover above wins — do not raise specificity. */
.text-link {
  color: var(--color-primary);
}
/* -- App Shell -- */
.app-shell {
  display: flex;
  min-height: 100vh;
  /* Guard against a wide child (an ECharts canvas holding its last-rendered
     width, a long unwrapped line) pushing the page wider than the viewport. */
  overflow-x: hidden;
}

/* -- Content Area -- */
.content-area {
  margin-left: 60px;
  flex: 1;
  /* A flex child defaults to min-width:auto, so it refuses to shrink below its
     content's intrinsic width — that's what kept the dashboard wide on zoom and
     produced the horizontal scrollbar. min-width:0 lets it shrink to fit; the
     charts then reflow via their resize handler. */
  min-width: 0;
  /* Half the gap beside the left rail (Leon, 18 Oct). */
  padding: 32px 40px 32px 20px;
  min-height: 100vh;
}

/* 24px, as Central's .project-heading: a page with tabs and one without
   start their content at the same height (Leon, 19 Oct). */
.content-header {
  margin-bottom: 24px;
}

/* Title block + primary actions inline on one row — no wasted band. */
.content-header--row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.content-header-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}
.back-link {
  display: inline-block;
  font-size: 13px;
  color: var(--color-text-muted);
  text-decoration: none;
  margin-bottom: 8px;
}

.back-link:hover {
  color: var(--color-secondary);
}

.content-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.typewriter-cursor {
  font-weight: 300;
  color: var(--color-text-muted);
  animation: blink 1s step-end infinite;
  margin-left: 1px;
}
@keyframes blink {
  50% { opacity: 0; }
}

.content-subtitle {
  font-size: 14px;
  color: var(--color-text-muted);
  margin-top: 4px;
}

/* -- Mobile -- */
@media (max-width: 768px) {
  .content-area {
    margin-left: 0;
    padding: 24px 16px;
    padding-top: 56px;
  }
}
/* -- Sidebar (icon-only) -- */
.sidebar {
  width: 60px;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 50;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 0 16px;
}

.sidebar-logo {
  width: 28px;
  height: 28px;
  /* Force white in dark mode (default) — overrides SVG's prefers-color-scheme */
  filter: brightness(0) invert(1);
}

:root[data-theme="light"] .sidebar-logo {
  /* Force purple in light mode — drop to black then tint to #9271a2 */
  filter: brightness(0) saturate(100%) invert(49%) sepia(10%) saturate(1400%) hue-rotate(240deg) brightness(88%) contrast(88%);
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .sidebar-logo {
    filter: brightness(0) saturate(100%) invert(49%) sepia(10%) saturate(1400%) hue-rotate(240deg) brightness(88%) contrast(88%);
  }
}

.sidebar-wordmark {
  display: none;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0;
  flex: 1;
  width: 100%;
}

.sidebar-nav a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  color: var(--color-text-muted);
  text-decoration: none;
  font-size: 0;
  border-radius: 10px;
  transition: background 0.15s, color 0.15s;
  position: relative;
}

.sidebar-nav a:hover {
  background: var(--color-primary-20);
  color: var(--color-text);
}

.sidebar-nav a.active {
  color: var(--color-text);
  background: var(--color-primary-20);
}

.sidebar-nav a .nav-label {
  display: none;
}

/* A rail entry that performs an action posts a form rather than following a
   link. The form carries no appearance of its own so the button it wraps sits
   in the rail exactly like the neighbouring icons. */
.sidebar-nav form {
  display: flex;
  justify-content: center;
  width: 100%;
  margin: 0;
}

.sidebar-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  color: var(--color-text-muted);
  background: none;
  border: none;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  position: relative;
  padding: 0;
}

.sidebar-nav-btn:hover {
  background: var(--color-primary-20);
  color: var(--color-text);
}

.sidebar-nav-btn:disabled {
  opacity: 0.5;
  cursor: wait;
}

/* Tooltip on hover */
.sidebar-nav-btn[data-tooltip]:hover::after,
.sidebar-nav a[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text);
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  z-index: 100;
  pointer-events: none;
}

.sidebar-nav .nav-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.sidebar-badge {
  position: absolute;
  top: 4px;
  right: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--color-primary);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  line-height: 16px;
  text-align: center;
  box-sizing: border-box;
  pointer-events: none;
}

.sidebar-section-label {
  display: none;
}

.sidebar-divider {
  width: 24px;
  height: 1px;
  background: var(--color-border);
  margin: 8px 0;
}

.sidebar-user {
  margin-top: auto;
  padding: 12px 0 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  position: relative;
}

.sidebar-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-secondary-20);
  color: var(--color-secondary);
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  cursor: pointer;
  transition: opacity 0.15s;
}

.sidebar-avatar:hover {
  opacity: 0.8;
}

.sidebar-avatar-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

/* -- User Popup -- */
.sidebar-popup {
  display: none;
  position: absolute;
  bottom: calc(100% + 8px);
  left: 8px;
  width: 220px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 8px 0;
  z-index: 200;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
}

.sidebar-popup.open {
  display: block;
}

.sidebar-popup-header {
  padding: 10px 16px;
}

.sidebar-popup-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-text);
}

.sidebar-popup-email {
  font-size: 12px;
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-popup-divider {
  height: 1px;
  background: var(--color-border);
  margin: 4px 0;
}

a.sidebar-popup-item {
  text-decoration: none;
}

.sidebar-popup-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  color: var(--color-text-muted);
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s, color 0.1s;
}

.sidebar-popup-item:hover {
  background: var(--color-hover);
  color: var(--color-text);
}

/* -- Mobile Sidebar -- */
.mobile-menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 60;
}

.sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  z-index: 40;
}

@media (max-width: 768px) {
  .sidebar {
    transform: translateX(-100%);
    transition: transform 0.2s ease;
  }

  .sidebar.open {
    transform: translateX(0);
    padding-top: 56px;
  }

  .sidebar-overlay.open {
    display: block;
  }

  .mobile-menu-btn {
    display: flex;
  }
}
/* -- Project Cards -- */
.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

.project-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 24px;
  transition: border-color 0.15s;
}

.project-card:hover {
  /* Clickable-card hover affordance is the primary border (matches
     .admin-tools-card); text stays put — the global a:hover purple
     (reset.css link convention) is for inline links, not cards. */
  border-color: var(--color-primary);
  color: var(--color-text);
}

.project-card-name {
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 4px;
}

.project-card-slug {
  font-family: var(--font-code);
  font-size: 13px;
  color: var(--color-text-muted);
  margin-bottom: 16px;
}

.project-card-meta {
  font-size: 13px;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}

.project-card-meta .meta-icon {
  width: 14px;
  height: 14px;
}

/* -- Info Card (description box above tables) -- */
.info-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 20px;
}

/* The old platform drew the title as a div at the text size; V1 pages use an
   h2, so it inherits instead of taking the browser's heading size. */
.info-card-title {
  font-size: inherit;
  font-weight: 600;
  margin-bottom: 8px;
}

.info-card-text {
  font-size: 13px;
  color: var(--color-text-muted);
  margin: 0;
}

/* -- Empty State -- */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--color-text-muted);
}

.empty-state-icon {
  width: 48px;
  height: 48px;
  margin: 0 auto 16px;
  opacity: 0.4;
}

.empty-state-title {
  font-size: 16px;
  font-weight: 500;
  margin-bottom: 4px;
  color: var(--color-text);
}

.empty-state-text {
  font-size: 14px;
}

/* Clickable create variant (dashboard zero-projects state) — the whole tile
   opens the create modal, with an explicit button inside for the affordance. */
.empty-state--create {
  cursor: pointer;
  border: 1px dashed var(--color-border);
  border-radius: 12px;
  transition: border-color 0.15s;
}

.empty-state--create:hover {
  border-color: var(--color-text-muted);
}

.empty-state--create .btn-primary {
  margin-top: 16px;
}

/* -- Loading -- */
.loading-text {
  color: var(--color-text-muted);
  font-size: 14px;
}

/* -- Clickable Card Link -- */
a.project-card {
  text-decoration: none;
  color: inherit;
  display: block;
}

/* -- Mobile -- */
@media (max-width: 768px) {
  .project-grid {
    grid-template-columns: 1fr;
  }
}
/* -- Buttons (app context) -- */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 20px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-on-primary);
  background: var(--color-primary);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  text-decoration: none; /* anchors styled as buttons must not underline */
  transition: background 0.15s;
}

.btn-primary:hover {
  color: var(--color-on-primary); /* outranks the global a:hover for anchor usage */
  background: var(--color-primary-hover);
}

.btn-primary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 9px 20px;
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  color: var(--color-text);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  cursor: pointer;
  text-decoration: none; /* anchors styled as buttons must not underline */
  transition: border-color 0.15s;
}

.btn-secondary:hover {
  color: var(--color-text); /* outranks the global a:hover for anchor usage */
  border-color: var(--color-secondary);
}

/* Full-size destructive action (panel footers). Same outline-danger
   vocabulary as .btn-sm--danger; the filled .btn-primary.btn-danger
   stays reserved for the confirm modal's final "yes, do it" button. */
.btn-secondary.btn-danger {
  color: var(--color-error);
  border-color: var(--color-error);
}

/* :not(:disabled) outranks the generic .btn-secondary:hover:not(:disabled)
   (auth layout), which would otherwise mix its border and text colour into
   the red hover. */
.btn-secondary.btn-danger:hover:not(:disabled) {
  color: var(--color-error);
  background: var(--color-error-bg);
  border-color: var(--color-error);
}

.btn-secondary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Icon-only action button (refresh, export, …). Square, transparent, hover
   ring. Pair with aria-label + title so the visual is the only thing missing
   for sighted users. Same border + radius vocabulary as .btn-secondary so
   adjacent icon + text buttons line up. */
.btn-icon {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}
.btn-icon:hover {
  color: var(--color-text);
  border-color: var(--color-secondary);
}
.btn-icon:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
}
/* While a refresh is in flight, spin the icon in place (uses the shared
   @keyframes spin below) instead of swapping the button's label. */
.btn-icon.is-spinning svg {
  animation: spin 0.6s linear infinite;
}

/* -- Template Picker -- */
.template-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 8px;
}

.template-grid__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.template-grid__row--blank {
  grid-template-columns: 1fr;
}

.template-grid__divider {
  height: 1px;
  background: var(--color-border);
  margin: 4px 0;
}

.template-option {
  padding: 14px 16px;
  background: var(--color-bg);
  border: 2px solid var(--color-border);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color 0.15s;
}

.template-option:hover {
  border-color: var(--color-text-muted);
}

.template-option.selected {
  border-color: var(--color-primary);
}

.template-option-name {
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 2px;
}

.template-option-desc {
  font-size: 12px;
  color: var(--color-text-muted);
}

/* Agent-access flavor cards (create-app wizard, Access step) — single-column
   stack of the same option cards the template picker uses. */
.flavor-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}

/* -- Inline helper classes -- */
.deploy-date {
  margin-left: 6px;
  font-size: 12px;
  color: var(--color-text-muted);
}

.activity-sha {
  margin-left: 6px;
  font-family: var(--font-code);
  font-size: 12px;
  color: var(--color-text-muted);
}

.invite-chips-wrapper {
  max-width: 500px;
}

.invite-btn {
  margin-top: 8px;
}

.invite-feedback {
  font-size: 13px;
  padding: 8px 12px;
  border-radius: 6px;
  margin-top: 8px;
  max-width: 500px;
  display: none;
  color: var(--color-error);
  background: var(--color-error-bg);
}

/* -- Spinner -- */
/* Small inline spinner for buttons. */
.btn-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: var(--color-on-primary);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
/* -- Form Fields (app context) -- */
.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-bottom: 16px;
}

.field label {
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-muted);
}

.field input,
.field textarea,
.field select {
  font-family: var(--font-ui);
  font-size: 14px;
  padding: 9px 12px;
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  color: var(--color-text);
}

.field .field-hint {
  font-size: 12px;
  color: var(--color-text-muted);
}

/* Inline error under a single input. Terracotta = action-needed. */
.field-error {
  font-size: 12px;
  color: var(--color-primary);
  margin-top: 6px;
}

.form-group {
  margin-bottom: 16px;
}

.form-group .form-label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-muted);
  margin-bottom: 5px;
}

.form-group .form-input {
  display: block;
  width: 100%;
  padding: 9px 12px;
  font-size: 14px;
  font-family: var(--font-ui);
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  color: var(--color-text);
}

/* A field's help text, under the field or beside it. */
.form-hint {
  display: block;
  font-size: 12px;
  color: var(--color-text-muted);
  margin-top: 4px;
}

/* A settings card's row (with .detail-section): the setting's .detail-label
   and field on the left, its .form-hint on the right. */
.settings-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 8px 32px;
}

.settings-row > .form-hint {
  margin-top: 0;
}

@media (max-width: 720px) {
  .settings-row {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Toggle switch */
.nodge-toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  font-size: 14px;
  color: var(--color-text);
}

.nodge-toggle input {
  display: none;
}

.nodge-toggle-track {
  width: 36px;
  height: 20px;
  background: var(--color-control-border);
  border-radius: 10px;
  position: relative;
  transition: background 0.2s;
}

.nodge-toggle input:checked + .nodge-toggle-track {
  background: var(--color-primary);
}

.nodge-toggle--gate .nodge-toggle-track {
  background: var(--color-error);
}

.nodge-toggle--gate input:checked + .nodge-toggle-track {
  background: var(--color-accent);
}

.nodge-toggle-track::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: white;
  border-radius: 50%;
  transition: transform 0.2s;
}

.nodge-toggle input:checked + .nodge-toggle-track::after {
  transform: translateX(16px);
}

/* App-wide checkbox style: empty bordered box when off, solid terracotta
   (--color-primary) fill when on. No checkmark glyph — the fill is the signal.
   Applies to every checkbox; .nodge-checkbox below only adds label layout. */
input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  min-width: 18px;
  border: 1px solid var(--color-control-border);
  border-radius: 4px;
  background: var(--color-surface);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  vertical-align: middle;
  margin: 0;
}

input[type="checkbox"]:hover {
  border-color: var(--color-primary);
}

input[type="checkbox"]:checked {
  background: var(--color-primary);
  border-color: var(--color-primary);
}

/* App-wide radio style: same tick-box language as the checkbox above, but round.
   Empty bordered circle when off; terracotta ring with a centered dot when on
   (surface-coloured inset gap over a --color-primary fill). Kills the native
   OS-blue radio everywhere. */
input[type="radio"] {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  min-width: 18px;
  border: 1px solid var(--color-control-border);
  border-radius: 50%;
  background: var(--color-surface);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
  vertical-align: middle;
  margin: 0;
}

input[type="radio"]:hover {
  border-color: var(--color-primary);
}

input[type="radio"]:checked {
  background: var(--color-primary);
  border-color: var(--color-primary);
  box-shadow: inset 0 0 0 3px var(--color-surface);
}

/* Label wrapper for a checkbox + its text. Use this class for ALL checkboxes. */
.nodge-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 14px;
  color: var(--color-text);
  user-select: none;
}

/* Custom form select dropdown */
.form-select {
  position: relative;
}

.form-select__trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 9px 12px;
  font-family: var(--font-ui);
  font-size: 14px;
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  color: var(--color-text);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s;
}

/* An open list rings its trigger like focus does, also after a click. */
.form-select.open .form-select__trigger {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.form-select__label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.form-select__placeholder {
  color: var(--color-text-muted);
}

.form-select__chevron {
  flex-shrink: 0;
  width: 12px;
  height: 7px;
  color: var(--color-text-muted);
  transition: transform 0.15s;
}

.form-select.open .form-select__chevron {
  transform: rotate(180deg);
}

.form-select__menu {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 212px;
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 4px;
  z-index: 50;
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}

.form-select.open .form-select__menu {
  display: block;
}

/* Searchable mode: a filter input pinned to the top of the scrolling menu. */
.form-select__search {
  position: sticky;
  top: 0;
  z-index: 1;
  box-sizing: border-box;
  width: 100%;
  margin-bottom: 4px;
  padding: 8px;
  font-size: 14px;
  font-family: var(--font-ui);
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-control-border);
  border-radius: 4px;
}

/* The search sits at the menu's scrolling top edge: ring it inside. */
.form-select__search:focus-visible {
  outline-offset: -2px;
}

.form-select__empty {
  padding: 8px;
  font-size: 13px;
  color: var(--color-text-muted);
}

.form-select__option {
  display: block;
  width: 100%;
  padding: 8px 8px;
  font-size: 14px;
  font-family: var(--font-ui);
  color: var(--color-text);
  background: none;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s, color 0.1s;
}

.form-select__option:hover {
  background: var(--color-hover);
}

.form-select__option.active {
  color: var(--color-primary);
  font-weight: 600;
}
/* -- Browser autofill -- keep autofilled fields on the dark theme instead of
   the browser's white/blue chrome (Chrome paints an inset white box + dark text
   on -webkit-autofill). The huge inset shadow repaints the background; the long
   transition stops the brief white flash on submit. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--color-text);
  caret-color: var(--color-text);
  -webkit-box-shadow: 0 0 0 1000px var(--color-bg) inset;
  box-shadow: 0 0 0 1000px var(--color-bg) inset;
  transition: background-color 9999s ease-out 0s;
}

/* -- Invite Chip Input -- */
.invite-chips-input {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  cursor: text;
  transition: border-color 0.15s;
}

/* The ring goes around the whole chip field, not its inner input. */
.invite-chips-input:focus-within {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.field .invite-chips-input input {
  flex: 1;
  min-width: 140px;
  border: none;
  border-radius: 0;
  outline: none;
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-ui);
  font-size: 14px;
  padding: 4px 0;
}

.field .invite-chips-input input:focus {
  border-color: transparent;
  outline: none;
}

.invite-chips {
  display: contents;
}

.invite-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  white-space: nowrap;
}

.invite-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  font-size: 14px;
  line-height: 1;
  color: var(--color-text-muted);
  background: none;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

.invite-chip-remove:hover {
  color: var(--color-error);
}

/* -- Theme Toggle -- */
.theme-toggle {
  display: inline-flex;
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  overflow: hidden;
}

.theme-option {
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  color: var(--color-text-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.theme-option:not(:last-child) {
  border-right: 1px solid var(--color-border);
}

.theme-option:hover {
  color: var(--color-text);
  background: var(--color-hover);
}

.theme-option.active {
  color: var(--color-text);
  background: var(--color-active);
}

/* -- File Upload (legacy) -- */
.file-upload {
  display: flex;
  align-items: center;
  gap: 12px;
}

.file-upload-name {
  font-size: 13px;
  color: var(--color-text-muted);
}

/* -- File Dropzone -- */
.file-dropzone {
  border: 2px dashed var(--color-control-border);
  border-radius: 8px;
  padding: 24px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
  text-align: center;
}

.file-dropzone:hover {
  border-color: var(--color-text-muted);
}

.file-dropzone.dragover {
  border-color: var(--color-primary);
  background: rgba(192, 79, 48, 0.06);
}

.file-dropzone-prompt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--color-text-muted);
  font-size: 14px;
  pointer-events: none;
}

.file-dropzone-icon {
  width: 32px;
  height: 32px;
  color: var(--color-text-muted);
}

.file-dropzone-hint {
  font-size: 12px;
  opacity: 0.7;
}

.file-dropzone-selected {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

.file-dropzone-name {
  font-size: 14px;
  color: var(--color-text);
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-dropzone-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  font-size: 18px;
  line-height: 1;
  color: var(--color-text-muted);
  background: none;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  padding: 0;
  transition: color 0.15s;
}

.file-dropzone-remove:hover {
  color: var(--color-error);
}

/* -- Search Dropdown -- */
.search-wrapper {
  position: relative;
}

.search-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  margin-top: 4px;
  max-height: 200px;
  overflow-y: auto;
  z-index: 10;
  display: none;
}

.search-dropdown.open {
  display: block;
}

.search-dropdown-item {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.1s;
}

.search-dropdown-item:hover {
  background: var(--color-primary-20);
}

.search-dropdown-item .search-item-name {
  font-weight: 500;
}

.search-dropdown-item .search-item-email {
  font-size: 12px;
  color: var(--color-text-muted);
}

/* -- Centered Content -- */
.content-centered {
  max-width: 480px;
  margin: 0 auto;
}
/* -- Info List -- */
/* Label-above-value rows. Used for read-only summaries of an entity
   (profile, project general, admin org). */

.info-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin-bottom: 32px;
  font-size: 14px;
  padding-left: 10px;
}

.info-list-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.info-list-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.info-list-value {
  color: var(--color-text);
}

/* A value that is itself the problem — a credential saved here but not applied
   where it is actually read, a setting that has not taken effect. Terracotta is
   the action-needed signal, so this is for state an operator must do something
   about, never for merely secondary or dimmed text (that is --color-text-muted). */
.info-list-value--alert {
  color: var(--color-primary);
}

.info-list-value a {
  color: var(--color-text);
  text-decoration: none;
}

.info-list-value a:hover {
  color: var(--color-secondary);
  text-decoration: underline;
}

.info-list-value .col-mono {
  font-family: var(--font-code);
  font-size: 13px;
}
/* -- Auth layout (login, pending, password reset) -- */
.auth-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  position: relative;
  overflow: hidden;
}

/* -- Network background -- */
.network-bg {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 30%;
  pointer-events: none;
  color: var(--color-text);
  opacity: 0.4;
}

.network-bg--left  { left: 0; }
.network-bg--right { right: 0; }

.network-bg-svg {
  width: 100%;
  height: 100%;
}

.network-bg-svg circle,
.network-bg-svg line {
  opacity: 0;
  transition: opacity 0.4s;
}

@media (max-width: 767px) {
  .network-bg { display: none; }
}

/* -- Card -- */
.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 40px 36px;
}

.auth-card--centered { text-align: center; }
.auth-card--wide     { max-width: 480px; }

.auth-card--primary {
  background: var(--color-secondary-20);
  border-color: transparent;
  color: #ffffff;
}

.auth-card--primary .auth-wordmark,
.auth-card--primary .auth-title {
  color: #ffffff;
}

.auth-card--primary .auth-subtitle  { color: rgba(255, 255, 255, 0.7); }
.auth-card--primary .pending-icon   { color: rgba(255, 255, 255, 0.8); }
.auth-card--primary .auth-footer a  { color: rgba(255, 255, 255, 0.8); }
.auth-card--primary .auth-logo      { filter: brightness(0) invert(1); }

/* -- Brand -- */
.auth-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 32px;
}

.auth-logo {
  width: 32px;
  height: 32px;
}

.auth-wordmark {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text);
}

/* -- Headings -- */
.auth-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 6px;
}

.auth-subtitle {
  font-size: 14px;
  color: var(--color-text-muted);
  margin-bottom: 28px;
}

/* -- Form (auth scale: larger, full-width) -- */
.auth-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 24px;
}

.auth-page .field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Honeypot: off-screen, not display:none — some bots skip display-none fields
   but still fill visually-hidden ones. Humans never see or tab into it
   (aria-hidden + tabindex=-1 in the markup). */
.hp-field {
  position: absolute;
  left: -9999px;
  top: -9999px;
}

.auth-page .field label {
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-muted);
}

.auth-page .field input,
.auth-page .field textarea,
.auth-page .field select {
  width: 100%;
  padding: 10px 13px;
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-sm);
}

.auth-page .field input::placeholder,
.auth-page .field textarea::placeholder {
  color: var(--color-text-muted);
  opacity: 0.5;
}

.auth-page .field textarea {
  resize: vertical;
  min-height: 80px;
}

.auth-page .field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%237a6f62' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

/* -- Buttons (auth scale: larger; full width only in the sign-in card) -- */
.auth-page .btn-primary {
  padding: 11px 16px;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  background: var(--color-primary);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s, opacity 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
}

.auth-page .btn-primary:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.auth-page .btn-primary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.auth-page .btn-secondary {
  padding: 11px 16px;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  color: var(--color-text-muted);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.15s;
  /* Matches .btn-primary: centres a .btn-spinner while the label is hidden. */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.auth-page .btn-secondary:hover:not(:disabled) {
  border-color: var(--color-secondary);
  color: var(--color-text);
}

.auth-page .btn-secondary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* This file is copied into Central's whole stylesheet, so every rule that
   reuses an app class (.field, .btn-*, .chip) holds only inside .auth-page:
   the old platform compiled these into the sign-in pages' own auth.css. Global,
   they set every app button and field to the sign-in scale (17 and 18 Oct
   dry run). Only the sign-in card's buttons fill their width. */
.auth-card .btn-primary,
.auth-card .btn-secondary {
  width: 100%;
}

.auth-page .btn-row {
  display: flex;
  gap: 12px;
  margin-top: 4px;
}

/* In a row every button keeps its own width; only the sign-in card's
   primary fills the row beside its secondary. */
.auth-page .btn-row .btn-primary,
.auth-page .btn-row .btn-secondary {
  flex: 0 0 auto;
  width: auto;
  padding: 11px 20px;
  margin-top: 0;
}

.auth-card .btn-row .btn-primary {
  flex: 1;
}

/* -- Spinner -- */
.auth-page .btn-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255,255,255,0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

/* The white spinner above is for the filled primary. On the outlined
   secondary it would be invisible, so track the button's own text colour. */
.auth-page .btn-secondary .btn-spinner {
  border-color: var(--color-border);
  border-top-color: var(--color-text-muted);
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* -- Error -- */
.auth-error {
  font-size: 13px;
  color: var(--color-error);
  background: var(--color-error-bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}

/* -- Footer -- */
.auth-footer {
  margin-top: 24px;
  font-size: 13px;
  color: var(--color-text-muted);
  text-align: center;
}

.auth-footer a {
  color: var(--color-secondary);
  text-decoration: none;
  font-weight: 500;
}

.auth-footer a:hover {
  text-decoration: underline;
}

/* -- Pending icon -- */
.pending-icon {
  width: 48px;
  height: 48px;
  margin: 0 auto 20px;
  color: var(--color-secondary);
}

.pending-icon svg {
  width: 100%;
  height: 100%;
}

/* -- Steps -- */
.auth-step--centered { text-align: center; }

/* -- Check email -- */
.check-email-icon {
  width: 48px;
  height: 48px;
  margin: 0 auto 20px;
  color: var(--color-text);
}

.check-email-icon svg {
  width: 100%;
  height: 100%;
}

/* -- Social login -- */
.social-buttons {
  margin-top: 20px;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  color: var(--color-text-muted);
  font-size: 13px;
}

.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  border-top: 1px solid var(--color-border);
}

.social-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 11px 16px;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.15s;
  margin-bottom: 8px;
}

.social-btn:hover {
  border-color: var(--color-secondary);
}

.social-icon {
  width: 20px;
  height: 20px;
}

/* -- Onboarding multi-step -- */
.step-indicator {
  font-size: 13px;
  color: var(--color-text-muted);
  margin-left: auto;
}

/* -- Chip Picker -- */
.chip-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.auth-page .chip {
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 500;
  font-family: var(--font-ui);
  color: var(--color-text-muted);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 20px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}

.auth-page .chip:hover {
  border-color: var(--color-text-muted);
  color: var(--color-text);
}

.auth-page .chip.selected {
  border-color: var(--color-primary);
  color: var(--color-primary);
  background: var(--color-primary-20);
}

/* -- Footnote -- */
.auth-footnote {
  max-width: 400px;
  margin-top: 24px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--color-text-muted);
  text-align: center;
  opacity: 0.6;
}

.auth-footnote a {
  color: var(--color-secondary);
  text-decoration: none;
  font-weight: 500;
}

.auth-footnote a:hover {
  text-decoration: underline;
}
/* -- Selects, dropdowns, and pickers -- */

.nodge-select,
.nodge-picker {
  position: relative;
  min-width: 12rem;
}

.nodge-select__trigger,
.nodge-picker__trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 12px;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.nodge-select__trigger:focus-visible,
.nodge-picker__trigger:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.nodge-select__menu,
.nodge-picker__menu {
  position: absolute;
  z-index: 30;
  inset: calc(100% + 4px) 0 auto;
  display: none;
  max-height: 18rem;
  overflow: auto;
  padding: 6px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  box-shadow: 0 12px 30px var(--color-overlay);
}

.nodge-select.is-open .nodge-select__menu,
.nodge-picker.is-open .nodge-picker__menu {
  display: grid;
  gap: 2px;
}

.nodge-select__option,
.nodge-picker__option {
  padding: 8px 10px;
  color: var(--color-text);
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.nodge-select__option:hover,
.nodge-select__option[aria-selected='true'],
.nodge-picker__option:hover,
.nodge-picker__option[aria-selected='true'] {
  background: var(--color-hover);
}

/* A native select's open list follows the theme where the browser has the
   customizable select (Chrome, Edge): the option under the pointer and the
   chosen one get the light primary tint instead of the system blue. Other
   browsers keep their own list. */
@supports (appearance: base-select) {
  select:not([multiple]):not([size]),
  ::picker(select) {
    appearance: base-select;
  }

  /* A base-select box lays its label out like text, so a narrow row would
     wrap "All components" onto two lines and make the select taller than
     the search beside it; a classic select never wraps (Leon, 19 Oct). */
  select:not([multiple]):not([size]) {
    gap: 10px;
    white-space: nowrap;
  }

  select:not([multiple]):not([size])::picker-icon {
    content: '';
    width: 6px;
    height: 6px;
    border-right: 1.5px solid var(--color-text-muted);
    border-bottom: 1.5px solid var(--color-text-muted);
    align-self: center;
    translate: 0 -2px;
    rotate: 45deg;
    transition: rotate 0.15s, translate 0.15s;
  }

  select:not([multiple]):not([size]):open::picker-icon {
    translate: 0 2px;
    rotate: 225deg;
  }

  ::picker(select) {
    margin-block: 4px;
    padding: 4px;
    color: var(--color-text);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    box-shadow: 0 12px 30px var(--color-overlay);
  }

  select:not([multiple]):not([size]) option {
    padding: 6px 8px;
    border-radius: var(--radius-sm);
  }

  select:not([multiple]):not([size]) option::checkmark {
    display: none;
  }

  select:not([multiple]):not([size]) option:not(:disabled):hover,
  select:not([multiple]):not([size]) option:focus-visible {
    background: var(--color-primary-20);
    outline: none;
  }

  /* The pointer wins over the keyboard focus: one option is tinted at a time. */
  select:not([multiple]):not([size]):has(option:hover) option:focus-visible:not(:hover) {
    background: none;
  }

  select:not([multiple]):not([size]) option:disabled {
    color: var(--color-text-muted);
  }
}

.nodge-action-rail {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 140px;
  min-width: 140px;
  flex-shrink: 0;
}
/* -- Data Table -- */
.data-table {
  width: 100%;
  border-collapse: collapse;
}

.data-table th {
  text-align: left;
  padding: 8px 16px;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--color-border);
}

/* A server-sorted, paged list's header link looks exactly like the sort
   button table-sort.js drives (ui-patterns.md, "Copying a page"). */
.data-table thead th > button,
.data-table thead th > a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-decoration: none;
  cursor: pointer;
}

.data-table thead th > button:hover,
.data-table thead th > a:hover {
  color: var(--color-text);
}

.data-table thead th > button > [aria-hidden="true"] {
  display: none;
}

.data-table thead th[aria-sort="ascending"] > button::after,
.data-table thead th[aria-sort="ascending"] > a::after {
  content: '\2191';
}

.data-table thead th[aria-sort="descending"] > button::after,
.data-table thead th[aria-sort="descending"] > a::after {
  content: '\2193';
}

.data-table td {
  padding: 12px 16px;
  font-size: 14px;
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}

/* A date in a grid stays on one line. */
.data-table td time {
  white-space: nowrap;
}

.data-table tr:last-child td {
  border-bottom: none;
}

.data-table td a {
  color: var(--color-text);
  text-decoration: none;
}

.data-table td a:hover {
  color: var(--color-secondary);
  text-decoration: underline;
}

.data-table .col-mono {
  font-family: var(--font-code);
  font-size: 13px;
}

/* -- Action cells: right-align buttons in the actions column -- */
.data-table td.cell-actions,
.data-table th.cell-actions {
  text-align: right;
  padding-right: 0;
}

/* -- Empty-state cell: the "No X yet." row spanning the table -- */
.data-table td.cell-empty {
  padding: 16px;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 13px;
}

.data-table td .btn-row-sm {
  justify-content: flex-end;
}

/* -- Aligned tables: stacked tables on one page share fixed column widths, so columns line up across tables -- */
.data-table--aligned {
  table-layout: fixed;
}

.data-table--aligned th:first-child {
  width: 32%;
}

.data-table--aligned th,
.data-table--aligned td {
  overflow-wrap: break-word;
}

/* -- Filterable Table Headers -- */
.data-table th[data-filterable] {
  cursor: pointer;
  user-select: none;
}

.data-table th[data-filterable]:hover {
  color: var(--color-text);
}

.data-table th .th-filter {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.data-table th .th-filter-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}

.data-table th .th-filter-input {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 400;
  padding: 4px 6px;
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: 4px;
  color: var(--color-text);
  width: 100%;
  text-transform: none;
  letter-spacing: normal;
}

/* -- Table Toolbar -- */
.table-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.table-toolbar .table-search {
  flex: 1;
  margin-bottom: 0;
}

/* A toolbar's Search is a square icon button as tall as the field beside it;
   the field keeps the rest of the row. */
.table-toolbar .btn-icon {
  flex: none;
  align-self: stretch;
  width: auto;
  height: auto;
  aspect-ratio: 1;
}

/* -- Table Search Bar -- */
.table-search {
  margin-bottom: 16px;
}

.table-search-input {
  width: 100%;
  padding: 10px 13px;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-sm);
}

.table-search-input::placeholder {
  color: var(--color-text-muted);
  opacity: 0.5;
}

/* -- Mobile: Data Table to Card Gallery -- */
@media (max-width: 768px) {
  .data-table thead {
    display: none;
  }

  .data-table tbody {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .data-table tr {
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 16px;
    gap: 8px;
  }

  .data-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0;
    border-bottom: none;
    font-size: 14px;
  }

  .data-table td::before {
    content: attr(data-label);
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex-shrink: 0;
    margin-right: 12px;
  }

  .data-table td:empty,
  .data-table td[data-hide-mobile] {
    display: none;
  }

  .data-table td[data-hide-mobile="true"] {
    display: none;
  }
}
/* -- Badges -- */
/* A badge without a colour variant is the neutral one: grey fill and border.
   The coloured variants keep a transparent border, so every badge is the same
   size. */
.badge {
  display: inline-block;
  padding: 1px 7px;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-muted-20);
  color: var(--color-text-muted);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

.badge--sm {
  font-size: 11px;
}

.badge--active,
.badge--error,
.badge--pending,
.badge--org,
.badge--unverified,
.badge--admin,
.badge--api,
.badge--org-admin,
.badge--test {
  border-color: transparent;
}

.badge--active {
  background: var(--color-accent-20);
  color: var(--color-accent);
}

.badge--error {
  background: var(--color-error-bg);
  color: var(--color-error);
}

.badge--pending {
  background: var(--color-primary-20);
  color: var(--color-primary);
}

.badge--org {
  background: var(--color-secondary-20);
  color: var(--color-secondary);
}

.badge--unverified {
  background: var(--color-muted-20);
  color: var(--color-text-muted);
}

.badge--admin {
  background: var(--color-secondary-20);
  color: var(--color-secondary);
}

.badge--api {
  background: var(--color-secondary-20);
  color: var(--color-secondary);
}

.badge--org-admin {
  background: var(--color-accent-20, rgba(122, 146, 93, 0.15));
  color: var(--color-accent);
}

/* Test / dummy org marker (E2E provisioning wizard). Purple = informational,
   matching the --secondary semantic in tokens.css. */
.badge--test {
  background: var(--color-secondary-20);
  color: var(--color-secondary);
}

/* -- Buttons (small, for tables) -- */
.btn-sm {
  display: inline-block;
  padding: 5px 12px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  border-radius: 6px;
  border: 1px solid var(--color-border);
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  text-decoration: none; /* anchors styled as buttons must not underline */
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

/* In-app action (button element): hovers with the primary border.
   Anchors — browser interactions — hover as links instead; see a.btn-sm below. */
.btn-sm:hover {
  background: var(--color-primary-20);
  border-color: var(--color-primary);
}

.btn-sm:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-sm--approve {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

.btn-sm--approve:hover {
  background: var(--color-accent-20);
}

.btn-sm--primary {
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.btn-sm--primary:hover {
  background: var(--color-primary-20);
  border-color: var(--color-primary);
}

.btn-sm--primary-fill {
  color: var(--color-on-primary);
  background: var(--color-primary);
  border-color: var(--color-primary);
}

.btn-sm--primary-fill:hover {
  color: var(--color-on-primary); /* outranks the global a:hover for anchor usage */
  background: var(--color-primary-hover);
  border-color: var(--color-primary-hover);
}

.btn-sm--danger {
  color: var(--color-error);
  border-color: var(--color-error);
}

.btn-sm--danger:hover {
  color: var(--color-error); /* outranks the global a:hover for anchor usage */
  background: var(--color-error-bg);
}

/* Anchor = browser interaction (download / open link / new tab): hovers as a
   link — purple text + underline, no action-button border/tint. Specificity
   (0,2,1) deliberately outranks .btn-sm:hover and the variant hovers above. */
a.btn-sm:hover {
  color: var(--color-secondary);
  text-decoration: underline;
  background: none;
  border-color: var(--color-border);
}

.btn-link {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
  text-decoration: underline;
  color: var(--color-primary);
}
.btn-link:hover { color: var(--color-primary); opacity: 0.8; }
.btn-link:disabled { opacity: 0.5; cursor: not-allowed; text-decoration: none; }

.btn-row {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 20px;
}

.btn-row-sm {
  display: flex;
  gap: 8px;
}
/* -- Edge Side Panel -- */
.edge-panel-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  z-index: 200;
}

.edge-panel-overlay.open {
  display: block;
}

.edge-panel {
  position: fixed;
  top: 0;
  right: 0;
  /* Wider than the typical side drawer so action schemas (JSON/TOON) fit
     without horizontal scroll. Phones collapse to 100% via the media query below. */
  width: 640px;
  max-width: 100vw;
  height: 100vh;
  background: var(--color-surface);
  border-left: 1px solid var(--color-border);
  z-index: 201;
  transform: translateX(100%);
  transition: transform 0.25s ease;
  display: flex;
  flex-direction: column;
}

.edge-panel.open {
  transform: translateX(0);
}

/* CI monitoring primary — raised above the stacked Finding detail (202) so the
   detail's slide is masked by the primary until it clears the left edge.
   See #ci-report-detail-panel.edge-panel--stacked below. */
#edge-panel {
  z-index: 203;
}

/* Secondary panel that opens to the LEFT of an already-open .edge-panel.
   Anchored 640px from the right (one primary-panel width), and slid
   off-screen via translateX that clears past the primary panel. The
   .open rule below overrides translateX back to 0.

   z-index 202 — ABOVE both the overlay (200) and the primary panel (201).
   When the stacked panel is injected EARLIER in the DOM than the shared
   overlay (e.g. the project CI detail panel in core.js vs. the monitoring
   overlay in node.html), an equal z-index would let the later-in-source
   overlay paint over it — the "detail behind the dim" bug. 202 breaks that
   source-order tie regardless of DOM position, so the focused stacked panel
   always sits on top of its dim. */
.edge-panel--stacked {
  right: 640px;
  width: 480px;
  z-index: 202;
  transform: translateX(calc(100% + 640px));
}

.edge-panel--stacked.open {
  transform: translateX(0);
}

/* CI Finding detail — "emerge from behind, leftward". Unlike the org-nodes
   member panel (which keeps the shared .edge-panel--stacked z 202 ABOVE its
   primary), this detail sits BELOW its raised primary (#edge-panel, z 203).
   The inherited closed transform keeps it fully off-screen right; .open slides
   it to its left anchor, and because z 202 < 203 the slide travels *behind*
   the primary the whole way — so it emerges from behind the list panel instead
   of sweeping across its front. Id-scoped so the member panel is untouched.
   (Do NOT override the transform here — a "tuck under the primary" value leaks
   the panel into view whenever no primary is open to mask it.) */
#ci-report-detail-panel.edge-panel--stacked {
  z-index: 202;
}

@media (max-width: 1120px) {
  /* Not enough room for two full-width panels side-by-side; let the
     stacked panel cover part of the primary. The primary's header peek
     on the right edge still cues that it's there. */
  .edge-panel--stacked {
    right: 480px;
    transform: translateX(calc(100% + 480px));
  }
}

.edge-panel-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px 24px 16px;
  flex-shrink: 0;
}

.edge-panel-close {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.edge-panel-close:hover {
  color: var(--color-text);
  background: var(--color-border);
}

.edge-panel-search {
  padding: 12px 24px;
  flex-shrink: 0;
}

/* Search row with a trailing action (e.g. the CSV export button on the
   Security Findings panel). The input flexes to fill; the .btn-icon sits
   beside it, matching the platform-admin filter row. */
.edge-panel-search--with-action {
  display: flex;
  align-items: center;
  gap: 8px;
}

.edge-panel-search--with-action input {
  flex: 1;
}

.edge-panel-search input {
  width: 100%;
  padding: 8px 12px;
  font-size: 13px;
  background: var(--color-background);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  color: var(--color-text);
  font-family: var(--font-ui);
  box-sizing: border-box;
}

/* Kind filter <select> beside the search input (Security Findings panel).
   Mirrors the input's look; capped width so the input keeps the row. */
.edge-panel-search select {
  padding: 8px 12px;
  font-size: 13px;
  background: var(--color-background);
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  color: var(--color-text);
  font-family: var(--font-ui);
  max-width: 180px;
}

.edge-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 0 24px 24px;
}

/* Label / value rows inside an edge-panel body. Uppercase muted label
   above the value, soft divider between rows. Used by Deployment Details,
   Build Details, Environments, Agent Settings. */
.detail-section {
  padding: 12px 0;
  border-bottom: 1px solid var(--color-border);
}

.detail-section:last-child {
  border-bottom: none;
}

.detail-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-text-muted);
  margin-bottom: 6px;
}

/* Label row with a trailing action (e.g. "Edit" / "Disable") sitting to the
   right of the uppercase field label. Replaces the plain .detail-label line
   when the attribute needs an inline action. */
.detail-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

.detail-label-row .detail-label {
  margin-bottom: 0;
}

.detail-label-row .btn-sm {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
}

/* Big white section header used INSIDE an edge-panel body to introduce
   a group of fields/rows. Same visual weight as .edge-panel-header so
   the panel reads as Header → fields → Section → fields. */
.panel-section-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--color-text);
  margin: 24px 0 12px;
}

.edge-panel-body > .panel-section-title:first-child {
  margin-top: 0;
}

.panel-section-title--with-action {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* The panel's actions, below the scrolling body: standard-size buttons on
   the right, Cancel then the primary action. An existing item's Delete
   takes .edge-panel-footer-start and sits on the left (D83). */
.edge-panel-footer {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 24px;
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
}

/* A footer button keeps its own width, also where a page's button style is
   full width (Central's auth layout). */
.edge-panel-footer .btn-primary,
.edge-panel-footer .btn-secondary {
  flex: 0 0 auto;
  width: auto;
  margin-top: 0;
}

.edge-panel-footer-start {
  margin-right: auto;
}

/* Collapsible groups */
.edge-group {
  margin-bottom: 4px;
}

.edge-group-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 0;
  cursor: pointer;
  user-select: none;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-text-muted);
}

.edge-group-header:hover {
  color: var(--color-text);
}

/* Buttons in the group header (e.g. "Add follower") opt out of the header's
   uppercase letter-spacing so they match normal button typography. */
.edge-group-header .btn-sm,
.edge-group-header a.btn-sm {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
}

.edge-group-toggle {
  font-size: 10px;
  width: 12px;
  text-align: center;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}

.edge-group.collapsed .edge-group-toggle {
  transform: rotate(-90deg);
}

.edge-group-items {
  padding-left: 18px;
}

.edge-group.collapsed .edge-group-items {
  display: none;
}

.edge-group-item {
  font-size: 13px;
  padding: 4px 0;
  border-bottom: 1px solid var(--color-border);
}

.edge-group-item:last-child {
  border-bottom: none;
}

.edge-group-item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.edge-group-item-name-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
}

.edge-group-item-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.edge-group-item-badges {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.edge-group-item-badges .badge {
  font-size: 10px;
}

.edge-group-item-info {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  background: transparent;
  color: var(--color-text-muted);
  font-size: 10px;
  font-family: var(--font-ui);
  font-style: italic;
  font-weight: 600;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: help;
  padding: 0;
  position: relative;
  flex-shrink: 0;
}

.edge-group-item-info:hover {
  color: var(--color-text);
  border-color: var(--color-text-muted);
}

.edge-group-item-info[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text);
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 400;
  font-style: normal;
  line-height: 1.4;
  white-space: normal;
  width: max-content;
  max-width: 280px;
  z-index: 1000;
  pointer-events: none;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.edge-group-item-desc {
  color: var(--color-text-muted);
  font-size: 12px;
}

.edge-group-item.hidden {
  display: none;
}

.edge-group.hidden {
  display: none;
}

.edge-group-empty {
  font-size: 12px;
  color: var(--color-text-muted);
  padding: 4px 0;
  opacity: 0.6;
}

/* Empty groups dim the toggle + label spans, but leave any header action
   button (e.g. "Add follower" when there are 0 followers) at full
   saturation. Applying opacity to the parent .edge-group-header would
   create a stacking context that washes out the CTA too. */
.edge-group--empty .edge-group-header > span {
  opacity: 0.5;
}

/* Action row with clickable schema reveal */
.edge-group-item--expandable {
  cursor: pointer;
}

.edge-group-item--expandable:hover {
  color: var(--color-primary);
}

.edge-group-item-schema {
  display: none;
  margin: 8px 0 4px;
  padding: 10px 12px;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.5;
  color: var(--color-text);
  white-space: pre;
  overflow-x: auto;
}

.edge-group-item--open .edge-group-item-schema {
  display: block;
}

.edge-group-item-schema--empty {
  font-family: var(--font-ui);
  color: var(--color-text-muted);
  font-style: italic;
}

@media (max-width: 720px) {
  .edge-panel {
    width: 100%;
  }
}
/* -- Modal -- */
.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  z-index: 100;
  align-items: center;
  justify-content: center;
}

.modal-overlay.open {
  display: flex;
}

.modal-overlay--bare {
  background: transparent;
  z-index: 250;
  pointer-events: none;
}

.modal-overlay--bare .modal-card {
  pointer-events: auto;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.modal-card {
  position: relative;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  overflow-y: auto;
  padding: 28px 32px;
  margin: 16px;
  transition: max-width 0.25s ease;
}

/* Optional top-right close button (NodgeApp.modal({ closeButton: true })). */
.modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 3;
  display: flex;
  padding: 4px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}

.modal-close:hover {
  color: var(--color-text);
  background: var(--color-border);
}

.modal-card.wide {
  max-width: 740px;
}

.modal-header,
.modal-card > .modal-title:first-child,
.modal-card > form > .modal-title:first-child {
  position: sticky;
  top: -28px;
  z-index: 2;
  background: var(--color-surface);
  margin: -28px -32px 16px;
  padding: 28px 32px 12px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.modal-header .modal-title {
  margin-bottom: 0;
}

.modal-title {
  font-size: 18px;
  font-weight: 600;
}

/* "Step N of M" hint inside a wizard modal's title line */
.modal-step-hint {
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text-muted);
}

/* User action dropdown (modal header) */
.user-action-dropdown {
  position: relative;
  display: inline-grid;
}

.user-action-dropdown .btn-primary {
  border-radius: 8px;
  font-size: 13px;
  padding: 6px 14px;
  white-space: nowrap;
  width: 100%;
}

.user-action-dropdown .btn-primary.open {
  border-radius: 8px 8px 0 0;
}

.user-action-menu {
  position: absolute;
  top: 100%;
  right: 0;
  width: 200%;
  display: none;
  flex-direction: column;
  border-radius: 0 0 8px 8px;
  z-index: 10;
  background: var(--color-surface);
}

.user-action-menu.open {
  display: flex;
  border: 1px solid var(--color-primary);
  border-top: none;
}

.user-action-item {
  display: block;
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-primary);
  background: transparent;
  border: none;
  text-align: center;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
  transition: background 0.15s;
}

.user-action-item:hover {
  background: var(--color-primary);
  color: var(--color-on-primary);
}

.user-action-item--danger {
  color: var(--color-error, #c04f30);
}

.user-action-item--danger:hover {
  background: var(--color-error, #c04f30);
  color: #fff;
}

.user-action-item--approve {
  color: var(--color-accent);
}

.user-action-item--approve:hover {
  background: var(--color-accent);
  color: #fff;
}

.modal-error {
  font-size: 13px;
  color: var(--color-error);
  background: var(--color-error-bg);
  padding: 8px 12px;
  border-radius: 6px;
  margin-bottom: 16px;
  display: none;
}

.modal-footer {
  position: sticky;
  bottom: -28px;
  z-index: 2;
  background: var(--color-surface);
  margin: 24px -32px -28px;
  padding: 16px 32px 28px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  border-top: 1px solid var(--color-border);
}

.modal-footer--quiet {
  border-top: 0;
}
/* -- Toggle Switch (reusable) -- */
.toggle-switch {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.toggle-switch input {
  display: none;
}
.toggle-switch-slider {
  position: relative;
  width: 36px;
  height: 20px;
  background: var(--color-bg);
  border: 1px solid var(--color-control-border);
  border-radius: 10px;
  transition: background 0.2s, border-color 0.2s;
}
.toggle-switch-slider::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: var(--color-text-muted);
  border-radius: 50%;
  transition: transform 0.2s, background 0.2s;
}
input:checked + .toggle-switch-slider {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
input:checked + .toggle-switch-slider::before {
  transform: translateX(16px);
  background: #fff;
}
input:disabled + .toggle-switch-slider {
  opacity: 0.5;
  cursor: default;
}
.toggle-switch-label {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--color-text-muted);
  white-space: nowrap;
  user-select: none;
}
/* end design-system */
/* Central page rules. The shared tokens and controls above are copied from
   design-system/css; everything below this line is Central's own source. */

/* A side panel's toggle rows (a member's access, a project's labels), copied from the old platform's Team tab
   (public/js/project/team.js): its inline styles as classes, values unchanged,
   because Central's CSP allows no inline style. */
.perm-panel-email {
  font-size: 13px;
  color: var(--color-text-muted);
  padding: 12px 0 4px;
}
.perm-group-title {
  font-weight: 600;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-primary);
  padding: 16px 0 8px;
  border-bottom: 1px solid var(--color-border);
}
.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border);
}
.toggle-row-label {
  font-size: 14px;
}
.toggle-row-desc {
  font-size: 12px;
  color: var(--color-text-muted);
}

/* The project MCP grid, copied from the old platform's Agent access
   (scss/pages/_agent-access.scss): a row per tool, its badge, and the orange
   tickbox; a row is a label, so all of it ticks the box. */
.agent-access-tool-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border);
}
.agent-access-tool-row:last-child { border-bottom: none; }
label.agent-access-tool-row { cursor: pointer; }
.agent-access-tool-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-family: var(--font-code);
}
.agent-access-tool-desc {
  font-size: 12px;
  color: var(--color-text-muted);
  line-height: 1.4;
  margin-top: 2px;
}
.agent-access-risky-badge {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-primary);
  border: 1px solid var(--color-primary);
  border-radius: 8px;
  padding: 1px 6px;
}
.tickbox {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-surface);
  cursor: pointer;
  position: relative;
  transition: background 0.12s, border-color 0.12s;
}
.tickbox:hover:not(:disabled) { border-color: var(--color-primary); }
.tickbox:checked {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.tickbox:checked::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid var(--color-on-primary);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.tickbox:disabled { opacity: 0.5; cursor: not-allowed; }

/* Git Settings' Secret/Variable switch in the add dialog, the old
   git-settings.js modal's inline styles as classes. */
.config-type-group { display: flex; gap: 8px; }
.config-type-option { flex: 1; justify-content: center; text-align: center; cursor: pointer; }
.config-type-option.is-selected { background: var(--color-primary-20); border-color: var(--color-primary); color: var(--color-primary); }
.config-type-hint { font-size: 12px; color: var(--color-text-muted); margin: 8px 0 0; }
@font-face {
  font-family: 'Satoshi Central';
  src: url('/assets/Satoshi-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

:root { --font-ui: 'Satoshi Central', -apple-system, BlinkMacSystemFont, sans-serif; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  left: 72px;
  top: -60px;
  z-index: 100;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  color: var(--color-on-primary);
  background: var(--color-primary);
  text-decoration: none;
}
.skip-link:focus { top: 12px; }

.sidebar-nav svg { width: 20px; height: 20px; }
.sidebar-popup-item svg { width: 16px; height: 16px; flex: 0 0 auto; }
.sidebar-popup-form { margin: 0; }
.sidebar-avatar.active { box-shadow: 0 0 0 2px var(--color-secondary); }
/* The account menu and the Hosting "not set up yet" card are native popovers.
   A popover sits in the top layer, so it is placed against the viewport: the
   menu beside the rail's avatar, the card in the middle over a dimmed page. */
.sidebar-popup[popover] { position: fixed; inset: auto auto 68px 8px; margin: 0; color: var(--color-text); }
.sidebar-popup:popover-open { display: block; }
.modal-card[popover] { position: fixed; inset: 0; height: fit-content; max-width: min(520px, calc(100% - 32px)); margin: auto; color: var(--color-text); }
.modal-card[popover]::backdrop { background: var(--color-overlay); }

.auth-page { background: var(--color-bg); }
.auth-brand { justify-content: flex-start; }
.auth-logo { filter: brightness(0) invert(1); }
.auth-card { box-shadow: 0 18px 60px rgba(0, 0, 0, 0.18); }
.auth-form + .auth-form { margin-top: 0; }
.auth-separator {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 24px 0 0;
  color: var(--color-text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.auth-separator::before,
.auth-separator::after { content: ''; flex: 1; height: 1px; background: var(--color-border); }
.auth-actions { margin-top: 24px; }
.auth-actions .btn-primary { width: 100%; }

.content-area { max-width: 1680px; }
.content-header-actions .btn-primary { white-space: nowrap; }
/* A header of just a title and its actions keeps them on one line. */
.content-header--row:has(> .content-title) { align-items: center; }
.project-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
a.project-card { min-height: 168px; display: flex; flex-direction: column; }
.project-card-date {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: auto;
  padding-top: 20px;
  color: var(--color-text-muted);
  font-size: 13px;
}
.project-card-date svg { width: 17px; height: 17px; }
/* The type badge (and Published) sits at the right of the By line. */
.project-card-badges { display: flex; gap: 6px; margin-left: auto; }

.project-modal-page { overflow: hidden; }
.create-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: var(--color-overlay);
}
.create-modal {
  position: relative;
  width: 100%;
  max-width: 740px;
  max-height: 90vh;
  overflow-y: auto;
  padding: 28px 32px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-surface);
  box-shadow: 0 20px 70px rgba(0, 0, 0, 0.35);
}
.create-modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  display: flex;
  width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  color: var(--color-text-muted);
}
.create-modal-close:hover { color: var(--color-text); background: var(--color-hover); }
.create-modal-close svg { width: 20px; height: 20px; }
.create-form { display: block; }
.wizard-step[hidden] { display: none; }
.create-modal-header { padding-right: 36px; margin-bottom: 22px; }
.create-modal-header > div { display: flex; align-items: baseline; gap: 10px; }
.create-modal-title { font-size: 18px; font-weight: 600; }
.create-modal-step { color: var(--color-text-muted); font-size: 12px; font-weight: 500; }
.create-modal-copy { margin-top: 5px; color: var(--color-text-muted); font-size: 13px; }
.modal-copy { margin: 0 0 18px; color: var(--color-text-muted); font-size: 13px; line-height: 1.55; }
.project-detail-list {
  display: grid;
  gap: 24px;
  margin: 34px 28px 0;
}
.project-detail-list div { display: grid; gap: 7px; }
.project-detail-list dt {
  color: var(--color-text-muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.project-detail-list dd { margin: 0; color: var(--color-text); font-size: 15px; }
.create-modal .field { margin-bottom: 22px; }
.create-modal .field:last-of-type { margin-bottom: 0; }
.field-label { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 600; }
.choice-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.choice-grid--palette,
.choice-grid--flavor { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.choice-card {
  display: block;
  min-width: 0;
  padding: 14px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-bg);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.choice-card:hover { border-color: var(--color-text-muted); }
.choice-card:has(input:checked) { border-color: var(--color-primary); background: var(--color-primary-20); }
.choice-card:has(input:focus-visible) { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.choice-card input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.choice-card-body { min-width: 0; }
.choice-card-name { display: block; font-size: 14px; font-weight: 600; }
.choice-card-copy { display: block; margin-top: 2px; color: var(--color-text-muted); font-size: 12px; }
.design-palette-field { margin-bottom: 18px; }
.design-palette-field label { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 600; }
.palette-select {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  color: var(--color-text);
  background: var(--color-bg);
  font-family: var(--font-ui);
  font-size: 13px;
  cursor: pointer;
}
.color-step-layout { display: grid; grid-template-columns: 210px 1fr; gap: 28px; }
.color-pickers { display: flex; flex-direction: column; gap: 8px; }
.mode-toggle {
  display: flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  background: var(--color-bg);
}
.mode-toggle-btn {
  flex: 1;
  padding: 6px 16px;
  border: 0;
  border-radius: 6px;
  color: var(--color-text-muted);
  background: transparent;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.mode-toggle-btn.active { color: var(--color-text); background: var(--color-surface); }
.color-swatch-row { display: flex; align-items: center; gap: 8px; }
.color-swatch {
  flex: 1;
  min-width: 108px;
  padding: 10px 14px;
  border: 0;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  text-transform: capitalize;
  cursor: pointer;
  transition: filter 0.15s;
}
.color-swatch:hover { filter: brightness(1.1); }
.color-swatch-hidden { position: absolute; width: 0; height: 0; opacity: 0; pointer-events: none; }
.hex-input {
  width: 80px;
  padding: 6px 8px;
  border: 1px solid var(--color-control-border);
  border-radius: 6px;
  color: var(--color-text);
  background: var(--color-bg);
  font-family: var(--font-code);
  font-size: 12px;
}
.color-preview {
  display: grid;
  grid-template-columns: 1fr 2fr 1.2fr 1.5fr;
  grid-template-rows: 40px 90px 56px 56px 32px;
  grid-template-areas: "a . e e" "b c c d" "b c c d" ". f g h" ". . i j";
  gap: 5px;
  min-height: 300px;
  padding: 8px;
  border-radius: 10px;
  transition: background-color 0.2s;
}
.cp-cell { border-radius: 7px; transition: background-color 0.15s; }
.cp-a { grid-area: a; } .cp-b { grid-area: b; } .cp-c { grid-area: c; } .cp-d { grid-area: d; } .cp-e { grid-area: e; }
.cp-f { grid-area: f; } .cp-g { grid-area: g; } .cp-h { grid-area: h; } .cp-i { grid-area: i; } .cp-j { grid-area: j; }
.palette-strip { display: flex; height: 6px; margin-bottom: 10px; overflow: hidden; border-radius: 999px; }
.palette-strip span { flex: 1; }
.palette-ocean span:nth-child(1) { background:#3b82f6; } .palette-ocean span:nth-child(2) { background:#06b6d4; } .palette-ocean span:nth-child(3) { background:#22d3ee; }
.palette-forest span:nth-child(1) { background:#4d7c0f; } .palette-forest span:nth-child(2) { background:#a3763d; } .palette-forest span:nth-child(3) { background:#65a30d; }
.palette-sunset span:nth-child(1) { background:#ea580c; } .palette-sunset span:nth-child(2) { background:#e11d48; } .palette-sunset span:nth-child(3) { background:#eab308; }
.palette-arctic span:nth-child(1) { background:#6366f1; } .palette-arctic span:nth-child(2) { background:#818cf8; } .palette-arctic span:nth-child(3) { background:#38bdf8; }
.palette-lavender span:nth-child(1) { background:#a855f7; } .palette-lavender span:nth-child(2) { background:#c084fc; } .palette-lavender span:nth-child(3) { background:#e879f9; }
.palette-ember span:nth-child(1) { background:#dc2626; } .palette-ember span:nth-child(2) { background:#f97316; } .palette-ember span:nth-child(3) { background:#fbbf24; }
.palette-moss span:nth-child(1) { background:#6b8f71; } .palette-moss span:nth-child(2) { background:#8b9e7e; } .palette-moss span:nth-child(3) { background:#b5c4a8; }
.palette-slate span:nth-child(1) { background:#3b82f6; } .palette-slate span:nth-child(2) { background:#64748b; } .palette-slate span:nth-child(3) { background:#22c55e; }
.palette-sand span:nth-child(1) { background:#c2956a; } .palette-sand span:nth-child(2) { background:#a08070; } .palette-sand span:nth-child(3) { background:#d4a574; }
.palette-midnight span:nth-child(1) { background:#22c55e; } .palette-midnight span:nth-child(2) { background:#a78bfa; } .palette-midnight span:nth-child(3) { background:#06b6d4; }
.palette-coral span:nth-child(1) { background:#f97171; } .palette-coral span:nth-child(2) { background:#2dd4bf; } .palette-coral span:nth-child(3) { background:#fb923c; }
.create-modal-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  margin: 26px -32px -28px;
  padding: 18px 32px;
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
}
.form-error { padding: 10px 12px; border-radius: var(--radius-sm); color: var(--color-error); background: var(--color-error-bg); font-size: 13px; }

.project-page { max-width: none; }
.project-heading { display: flex; align-items: center; gap: 14px; margin-bottom: 24px; }
.project-context-switch { display: inline-flex; align-items: center; gap: 2px; padding: 2px; border: 1px solid var(--color-border); border-radius: 7px; background: var(--color-surface); }
.project-context-option { padding: 3px 9px; border-radius: 5px; color: var(--color-text-muted); font-size: 11px; font-weight: 600; text-decoration: none; }
.project-context-option:hover { color: var(--color-text); background: var(--color-hover); }
.project-context-option.active { color: var(--color-text); background: var(--color-hover); }
.project-context-option.disabled { color: var(--color-text-muted); opacity: 0.42; cursor: not-allowed; }
.project-context-option.disabled:hover { color: var(--color-text-muted); background: transparent; }
.project-tab-notice { margin: 0 0 20px; color: var(--color-text-muted); font-size: 13px; }
.project-layout { display: flex; gap: 32px; min-height: 400px; }
.project-tabs { width: 160px; flex-shrink: 0; display: flex; flex-direction: column; padding: 0; }
.project-tab-category { padding: 20px 20px 4px; color: var(--color-accent); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
.project-tab-category:first-child { padding-top: 0; }
.project-tab { padding: 10px 20px; border-radius: 8px; color: var(--color-text-muted); background: transparent; font-size: 14px; font-weight: 500; text-decoration: none; }
.project-tab.active { color: var(--color-text); background: var(--color-hover); font-weight: 600; }
/* The Commerce handoff page submits itself, so it is normally a flash. It is
   still styled: on a slow network it is what the administrator looks at. */
.handoff-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
.handoff-card { text-align: center; }
.handoff-message { color: var(--color-text-muted); font-size: 14px; }

.project-tab-stage { flex: 1; min-width: 0; }
.project-tab-panel { min-width: 0; display: flex; gap: 32px; }
.project-tab-content { flex: 1; min-width: 0; max-width: 1200px; }
.project-tab-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 4px;
}
.project-action-btn { width: 100%; white-space: nowrap; }
/* A rail action longer than the rail wraps rather than overflowing it, at
   the same line height whether it is a link or a button. */
.nodge-action-rail .project-action-btn { white-space: normal; text-align: center; line-height: 1.2; }
.nodge-action-rail form { display: flex; margin: 0; }
.info-card-title-row { display: flex; align-items: center; gap: 16px; margin-bottom: 8px; }
.info-card-title-row .info-card-title { margin-bottom: 0; }
.general-open-link { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; padding: 0; color: var(--color-secondary); background: none; border: 0; font: inherit; font-size: 13px; font-weight: 500; cursor: pointer; text-decoration: none; }
.general-open-link:hover { color: var(--color-secondary); text-decoration: underline; }
.general-open-link svg { width: 15px; height: 15px; flex-shrink: 0; }
.project-general-fields code { overflow-wrap: anywhere; font-family: var(--font-code); font-size: 13px; }
/* The old General's "Open in" dropdown (general.js): its arrow turns up while
   it is open; details[data-dismiss] closes it on a click outside. */
.project-open-menu { position: relative; width: 100%; }
.project-open-menu-trigger { border-radius: 8px; list-style: none; }
.project-open-menu-trigger::-webkit-details-marker { display: none; }
.project-open-menu-trigger::after { content: " \2193"; white-space: pre; }
.project-open-menu[open] .project-open-menu-trigger { border-radius: 8px 8px 0 0; }
.project-open-menu[open] .project-open-menu-trigger::after { content: " \2191"; }
.project-open-menu-list { position: absolute; top: 100%; left: 0; z-index: 30; width: 100%; overflow: hidden; background: var(--color-surface); border: 1px solid var(--color-border); border-top: 0; border-radius: 0 0 8px 8px; }
/* The Git URL's copy icon beside its label (old _project-general.scss). */
.info-label-link { display: inline-flex; align-items: center; margin-left: 6px; padding: 0; color: var(--color-text-muted); background: none; border: none; cursor: pointer; vertical-align: middle; }
.info-label-link:hover { color: var(--color-secondary); }
.info-label-link svg { width: 13px; height: 13px; }
.project-open-menu-item { display: flex; width: 100%; align-items: center; justify-content: center; padding: 8px 12px; color: var(--color-text); background: transparent; border: 0; border-top: 1px solid var(--color-border); font: inherit; font-size: 13px; font-weight: 500; text-align: center; text-decoration: none; cursor: pointer; }
.project-open-menu-item:first-child { border-top: 0; }
.project-open-menu-item:hover { color: var(--color-text); background: var(--color-primary-20); text-decoration: none; }
.table-sort,
.table-sort-button {
  padding: 0;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}
.table-sort:hover,
.table-sort-button:hover { color: var(--color-text); }
.text-muted { color: var(--color-text-muted); }
.admin-card-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 24px; }
.admin-nav-card { display: flex; min-height: 132px; flex-direction: column; justify-content: center; gap: 8px; padding: 24px; border: 1px solid var(--color-border); border-radius: var(--radius); color: var(--color-text); background: var(--color-surface); text-decoration: none; }
.admin-nav-card:hover { color: var(--color-text); border-color: var(--color-secondary); background: var(--color-hover); }
.admin-nav-card.is-disabled { cursor: not-allowed; opacity: .62; }
.admin-nav-card.is-disabled:hover { border-color: var(--color-border); background: var(--color-surface); }
.admin-nav-card strong { font-size: 16px; }
.admin-nav-card span { color: var(--color-text-muted); font-size: 13px; }
.admin-form, .admin-integration-list { margin-top: 24px; }
.admin-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 24px; }
.admin-form label, .admin-section label { display: flex; flex-direction: column; gap: 7px; color: var(--color-text-muted); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.admin-form input, .admin-form select, .admin-form textarea, .admin-section input, .admin-section select, .admin-section textarea, .admin-command-modal input, .admin-command-modal select, .admin-command-modal textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--color-control-border); border-radius: var(--radius-sm); color: var(--color-text); background: var(--color-bg); font: 14px var(--font-ui); text-transform: none; letter-spacing: normal; }
.admin-command-modal label { display: flex; flex-direction: column; gap: 7px; color: var(--color-text-muted); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.admin-form-span { grid-column: 1 / -1; }
.admin-command-modal textarea { resize: vertical; font-family: var(--font-code); }
.panel-command-list { display: flex; flex-direction: column; align-items: stretch; gap: 12px; margin-top: 24px; }
.panel-command-form { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
.panel-command-form label { display: flex; flex-direction: column; gap: 6px; color: var(--color-text-muted); font-size: 12px; }
.panel-command-form input[type='text'], .panel-command-form input:not([type]) { width: 100%; padding: 9px 12px; border: 1px solid var(--color-control-border); border-radius: var(--radius-sm); color: var(--color-text); background: var(--color-bg); font: 14px var(--font-ui); }
.panel-command-form .nodge-checkbox { flex-direction: row; align-items: center; color: var(--color-text); font-size: 13px; }
.admin-inline-actions { display: flex; align-items: center; gap: 8px; margin-top: 20px; }
.admin-section { padding: 22px 0; }
.admin-section + .admin-section { margin-top: 6px; }
.admin-section h2 { margin-bottom: 6px; font-size: 16px; font-weight: 600; }
.admin-section p { margin-bottom: 14px; color: var(--color-text-muted); font-size: 13px; }
/* Platform administration card forms share one row: the fields take the
   width and the actions keep their natural size at the right end of the same
   row, primary first. A card's other actions (Unpublish) are their own forms,
   so .admin-form-row holds a card's forms in one row. An explanation inside a
   form takes a line of its own, and the row wraps instead of scrolling.
   A dialog rendered inside a section (a row's Release) keeps its own stacked
   layout: fields full width, actions in its footer. */
.admin-section form:not(.admin-command-modal) { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-top: 10px; }
.admin-section form:not(.admin-command-modal) > label, .admin-section form:not(.admin-command-modal) > .admin-form-grid, .admin-section form:not(.admin-command-modal) > input[type='file'] { flex: 1 1 200px; min-width: 0; }
.admin-section form:not(.admin-command-modal) > p { flex: 1 1 100%; margin-bottom: 0; }
.admin-section form:not(.admin-command-modal) > button, .admin-form-row .btn-primary, .admin-form-row .btn-secondary { flex: none; width: auto; white-space: nowrap; }
.admin-form-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-top: 10px; }
.admin-form-row > form { margin-top: 0; }
.admin-form-row > form:first-child { flex: 1 1 320px; }
.admin-section code { overflow-wrap: anywhere; }
/* Status, provenance and caveats sit under the table or grid they describe. */
.admin-footnote { margin-top: 10px; color: var(--color-text-muted); font-size: 13px; }
/* The red line under a grid whose owner refused or failed (D90). */
.admin-footnote.is-error { color: var(--color-error); }
.admin-footnote + .admin-footnote { margin-top: 4px; }
/* A field's input with one action on the same row (Company settings Login:
   Issuer URL and Discover). */
.field-with-action { display: flex; gap: 8px; }
.field-with-action > input { flex: 1; min-width: 0; }
/* A checkbox is not a text field: it keeps the app-wide box (18px, its own
   radius) beside its text, and the field rule's control border. A border: 0
   here left a dark square on a dark panel (19 Oct). */
.admin-form input[type='checkbox'], .admin-section input[type='checkbox'], .admin-command-modal input[type='checkbox'] { width: 18px; height: 18px; padding: 0; border-radius: 4px; flex: none; }
.admin-form label:has(> input[type='checkbox']), .admin-section label:has(> input[type='checkbox']), .admin-command-modal label:has(> input[type='checkbox']) { flex-direction: row; align-items: center; gap: 8px; color: var(--color-text); font-size: 13px; font-weight: 500; text-transform: none; letter-spacing: normal; }
/* A digest or identifier in an administration table wraps instead of
   pushing the table under the action rail. */
.project-tab-content .data-table code { overflow-wrap: anywhere; }
/* A configuration list: one row per item, its pip saying whether it works. */
.admin-integration-table td:first-child { white-space: nowrap; }
.admin-pip { display: inline-block; width: 8px; height: 8px; margin-right: 10px; border-radius: 50%; background: var(--color-text-muted); vertical-align: middle; }
.admin-pip--ok { background: var(--color-accent); }
.admin-pip--attention { background: var(--color-warning); }
.admin-pip--error { background: var(--color-error); }
/* A side panel the server renders open (data-panel, nodge-ui.js): its
   close control is a link, its fields stack one per row and its buttons sit
   in the footer (D83). */
a.edge-panel-close { text-decoration: none; }
/* A field labelled by .detail-label (a side panel's or a settings card's
   row) spaces as the design system does: by the label's own margin. */
.admin-form label:has(> .detail-label) { gap: 0; }
.edge-panel-body .form-error, .edge-panel-body .project-tab-notice { margin-bottom: 16px; }
.edge-panel-body .panel-section-title { margin-top: 24px; }
.admin-section h3 { margin-bottom: 12px; font-size: 14px; font-weight: 600; }
/* A hint inside a field's label reads as text, not as the label. */
.admin-form .field-hint, .admin-section .field-hint { color: var(--color-text-muted); font-size: 12px; font-weight: 400; text-transform: none; letter-spacing: normal; }
.admin-panel-advanced { margin-top: 18px; }
.admin-panel-advanced summary { color: var(--color-text-muted); font-size: 13px; font-weight: 600; cursor: pointer; }
/* Text to copy exactly (a bootstrap key, an address list): read-only, in
   the code face, with Copy (data-copy) beside it. */
.admin-copy-text { width: 100%; padding: 10px 12px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-text); background: var(--color-bg); font: 12px var(--font-code); resize: none; overflow-wrap: anywhere; }
/* Releasing the free-tier captain ends the cluster: a red block says so. */
.hosting-release-warning { margin-bottom: 16px; padding: 12px 14px; border: 1px solid var(--color-error); border-radius: var(--radius-sm); color: var(--color-error); background: var(--color-error-bg); font-size: 13px; }
.hosting-release-warning p + p { margin-top: 6px; }
.hosting-key-fingerprint { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin: 10px 0 14px; }
.hosting-key-fingerprint code { overflow-wrap: anywhere; font-size: 12px; }
.hosting-key-fingerprint .btn-secondary { width: auto; }
/* Two blocks side by side. */
.admin-columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 32px; }
.admin-columns > .admin-section + .admin-section { margin-top: 0; }
.modal-error:not([hidden]) { display: block; }
/* A sort or filter <select> on a table's toolbar row looks like the search
   field beside it and keeps its own width; the field takes the rest. */
.table-toolbar select { flex: none; padding: 10px 13px; font: 14px var(--font-ui); color: var(--color-text); background: var(--color-bg); border: 1px solid var(--color-control-border); border-radius: var(--radius-sm); }
/* The old platform's collapsible groupbox (scss/components/_fold-section.scss)
   for Gateway's sections, as <details>: it opens without a script. */
.fold-section { border: 1px solid var(--color-border); border-radius: 8px; margin-bottom: 12px; overflow: hidden; }
.fold-section-header { display: flex; align-items: center; padding: 12px 16px; cursor: pointer; user-select: none; background: var(--color-surface); list-style: none; }
.fold-section-header::-webkit-details-marker { display: none; }
.fold-section-header:hover { filter: brightness(0.97); }
.fold-section-hint { font-size: 12px; color: var(--color-text-muted); margin-left: 8px; }
.fold-section-body { padding: 0 16px 16px; }
.fold-section-body .data-table { margin-top: 0; }
.gateway-row-description { display: block; margin-top: 2px; color: var(--color-text-muted); font-size: 12px; }
.gateway-schema { overflow: auto; padding: 14px; border-radius: 8px; color: var(--color-text); background: var(--color-bg); font: 12px/1.55 var(--font-code); white-space: pre-wrap; overflow-wrap: anywhere; }

/* A doc reads as a page (D95, Leon 18 Oct): one sheet filling the column a
   project tab uses, in the middle of the screen, like a document in a word
   processor or a PDF reader, with
   Docs above its left edge in the download links' colour. The title, summary
   and byline sit above a line, then the text, then the downloads as a quiet
   list of links. The type is a manual's, not a landing page's: 14px text,
   headings clearly larger and bolder with room above them. A copy box is the
   old platform's copy line (scss/components/_dev-setup.scss
   .setup-copy-line), set on the page background so it stands out from the
   sheet. */
.doc-page { padding: 48px 64px 56px; border: 1px solid var(--color-border); border-radius: 4px; background: var(--color-surface); box-shadow: var(--shadow); }
.project-tab-content.doc-column { margin: 0 auto; }
/* The sheet sits in the middle of the screen (Leon, 19 Oct): an empty spacer
   as wide as the action rail mirrors it on the left, so a guide's empty rail
   or a doc's Edit and Delete do not push the sheet aside. */
.project-tab-panel.doc-panel::before { content: ""; flex: 0 0 140px; }
.back-link.doc-back-link { margin-bottom: 14px; color: var(--color-primary); font-size: 15px; }
.back-link.doc-back-link:hover { color: var(--color-secondary); }
.doc-page-header { margin-bottom: 28px; padding-bottom: 20px; border-bottom: 1px solid var(--color-border); }
.doc-page-title { margin: 0 0 8px; font-size: 28px; font-weight: 700; line-height: 1.25; letter-spacing: -0.02em; }
.doc-page-subtitle { margin: 0 0 10px; color: var(--color-text-muted); font-size: 15px; line-height: 1.5; }
.doc-page-byline { margin: 0; color: var(--color-text-muted); font-size: 12px; }
.doc-body { font-size: 14px; line-height: 1.65; color: var(--color-text); }
.doc-body h2, .doc-body h3 { font-weight: 700; line-height: 1.3; letter-spacing: -0.01em; }
.doc-body h2 { margin: 36px 0 10px; font-size: 20px; }
.doc-body h3 { margin: 24px 0 6px; font-size: 16px; }
.doc-body > .doc-section:first-child > h2:first-child { margin-top: 0; }
.doc-body p, .doc-body ul, .doc-body ol { margin: 0 0 10px; }
.doc-body ul, .doc-body ol { padding-left: 24px; }
.doc-body li { margin-bottom: 4px; }
.doc-body code { padding: 1px 4px; border: 1px solid var(--color-border); border-radius: 4px; background: var(--color-bg); font-family: var(--font-code); font-size: 13px; }
.doc-body p a, .doc-body li a { color: var(--color-primary); text-decoration: none; }
.doc-body p a:hover, .doc-body li a:hover { color: var(--color-secondary); text-decoration: underline; }
.doc-copy { display: flex; align-items: center; gap: 8px; margin: 0 0 14px; padding: 8px 8px 8px 12px; border: 1px solid var(--color-border); border-radius: 6px; background: var(--color-bg); }
.doc-copy pre { flex: 1; min-width: 0; margin: 0; overflow-x: auto; }
.doc-copy code { padding: 0; border: 0; background: none; color: var(--color-text); }
.doc-downloads { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--color-border); }
.doc-downloads h2 { margin: 0 0 8px; color: var(--color-text-muted); font-size: 13px; font-weight: 600; }
.doc-download-list { margin: 0; padding: 0; list-style: none; }
.doc-download-list li { padding: 4px 0; }
.doc-download { display: inline-flex; align-items: center; gap: 10px; max-width: 100%; color: var(--color-primary); font-size: 14px; text-decoration: none; }
.doc-download:hover .doc-download-name { color: var(--color-secondary); text-decoration: underline; }
.doc-download-thumb, .doc-download-type { flex: none; width: 32px; height: 32px; border-radius: 4px; }
.doc-download-thumb { object-fit: cover; }
.doc-download-type { display: flex; align-items: center; justify-content: center; border: 1px solid var(--color-border); background: var(--color-bg); color: var(--color-text-muted); font-size: 10px; font-weight: 600; }
.doc-download-name { min-width: 0; overflow-wrap: anywhere; }
.doc-download-meta { flex: none; color: var(--color-text-muted); font-size: 12px; }

/* Profile */
.profile-details { display: grid; gap: 24px; margin: 30px 0 44px; padding: 0 16px; }
.profile-detail { display: grid; gap: 5px; }
.profile-detail dt { color: var(--color-text-muted); font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.profile-detail dd { margin: 0; overflow-wrap: anywhere; }
.profile-danger { margin-top: 48px; padding: 0 16px; }
.profile-danger > h2 { margin-bottom: 20px; color: var(--color-error); font-size: 13px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.profile-danger-action { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; }
.profile-danger-action h3 { margin: 0 0 4px; font-size: 14px; font-weight: 600; }
.profile-danger-action p,
.profile-modal-copy { margin: 0; color: var(--color-text-muted); font-size: 13px; }
.profile-danger-action p + p { margin-top: 8px; }
.profile-modal-copy { margin-bottom: 18px; }
.profile-surface .table-toolbar { margin-top: 24px; }
.profile-surface code { font-family: var(--font-code); font-size: 13px; }
/* Delete stays dimmed until the typed confirmation matches its pattern. */
.profile-delete-form:has(:invalid) .btn-danger { opacity: .5; }

/* The Runs tab's phase chips, copied from the old platform's pipeline page
   (scss/pages/_pipeline.scss) with its values. D93 changes two: advisory is
   amber (the old inverse-neutral chip in --color-warning), and a running chip
   carries the old running dot's pulse; reduced motion keeps it still. */
.pipeline-phase-chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.pipeline-phase-chip--success   { background: var(--color-accent-20);    color: var(--color-accent); }
.pipeline-phase-chip--advisory  { background: var(--color-warning);      color: var(--color-bg); }
.pipeline-phase-chip--failure   { background: var(--color-error-bg);     color: var(--color-error); }
.pipeline-phase-chip--running   { background: var(--color-secondary-20); color: var(--color-secondary); animation: pulse 1.5s ease-in-out infinite; }
.pipeline-phase-chip--skipped   { background: var(--color-muted-20);     color: var(--color-text-muted); }
.pipeline-phase-chip--waiting   { background: var(--color-muted-20);     color: var(--color-text-muted); opacity: 0.65; }
.pipeline-phase-chip--clickable {
  cursor: pointer;
  transition: filter 0.15s ease;
}
.pipeline-phase-chip--clickable:hover {
  filter: brightness(1.2);
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}
@media (prefers-reduced-motion: reduce) {
  .pipeline-phase-chip--running { animation: none; }
}

@media (max-width: 1100px) {
  .admin-columns { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .choice-grid--palette,
  .choice-grid--flavor { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .sidebar {
    top: auto;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 56px;
    transform: none;
    flex-direction: row;
    border-right: 0;
    border-top: 1px solid var(--color-border);
  }
  .sidebar-brand { padding: 0 12px; }
  .sidebar-logo { width: 24px; height: 24px; }
  .sidebar-nav { width: auto; flex: 1; flex-direction: row; justify-content: flex-start; }
  .sidebar-popup[popover] { inset: auto 8px 64px auto; }
  .sidebar-form { margin: 0 8px 0 auto; }
  .sidebar-logout { margin: 0; }
  .content-area { padding-bottom: 80px; }
  .content-header--row { flex-direction: column; }
  .content-header-actions,
  .content-header-actions .btn-primary { width: 100%; }
  .choice-grid,
  .choice-grid--palette,
  .choice-grid--flavor { grid-template-columns: 1fr; }
  .color-step-layout { grid-template-columns: 1fr; }
  .color-preview { min-height: 250px; }
  .create-modal { max-height: calc(100vh - 32px); padding: 24px 20px; }
  .create-modal-footer { margin: 24px -20px -24px; padding: 16px 20px; }
  .project-layout { flex-direction: column; gap: 16px; }
  .project-tabs { flex-direction: row; }
  .project-tab-category { display: none; }
  .project-tab-panel { flex-direction: column; gap: 16px; }
  .doc-page { padding: 28px 20px 32px; }
  .project-tab-panel.doc-panel::before { display: none; }
  .project-tab-actions { width: 100%; min-width: 0; padding-top: 0; }
  .profile-danger-action { flex-direction: column; }
  .admin-card-grid, .admin-form-grid { grid-template-columns: 1fr; }
}
