/* Auth / dashboard (deep navy) scaffolding. Built for readiness; first
   exercised by authenticated pages in a later phase. */

.auth-shell {
  min-height: calc(100vh - var(--header-h));
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-7) var(--space-5);
}

.card {
  position: relative;
  overflow: hidden;
  width: 100%;
  max-width: 440px;
  background: var(--surface-card);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-7);
  color: var(--on-dark);
}
/* Brand accent bar (primary → aqua) across the top of auth cards */
.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--color-primary), var(--color-accent));
}
.card__title { font-size: var(--fs-xl); margin-bottom: var(--space-2); }
.card__subtitle { color: var(--on-dark-muted); font-size: var(--fs-sm); margin-bottom: var(--space-5); }

/* Dashboard content surface */
.dash-surface {
  padding-block: var(--space-5) var(--space-8);
}
.panel {
  background: var(--surface-card);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}

/* Form fields (dark theme) */
.field { display: grid; gap: var(--space-2); margin-bottom: var(--space-4); }
.field__label { font-size: var(--fs-sm); font-weight: 500; color: var(--on-dark-label); }
.field__input {
  width: 100%;
  padding: 10px 14px;
  background: rgba(0,0,0,0.18);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  color: var(--on-dark);
  font: inherit;
  /* Inputs must not out-size their field labels (first review, Profile §) */
  font-size: var(--fs-sm);
}
.field__input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(30,144,255,0.25);
}

/* Checkbox row (login / dev-login) */
.checkbox {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  margin-bottom: var(--space-5);
  cursor: pointer;
}
.checkbox input { width: 16px; height: 16px; accent-color: var(--color-primary); }
/* Fourth review: in-label links (Usage Agreement) must read as hyperlinks. */
.checkbox a { color: var(--color-primary-300); text-decoration: underline; }
.checkbox a:hover { color: #fff; }

.field__hint { color: var(--on-dark-muted); font-weight: 400; }

.btn--block { width: 100%; justify-content: center; }

.auth-fineprint {
  margin-top: var(--space-5);
  font-size: var(--fs-xs);
  color: var(--on-dark-muted);
  line-height: 1.5;
}
.auth-fineprint a { color: var(--color-primary-300); }
.auth-fineprint a:hover { color: #fff; }

/* Dashboard content */
.dash-intro {
  color: var(--on-dark-muted);
  font-size: var(--fs-md);
  margin-bottom: var(--space-5);
}
/* Guidance demoted below a table (first review: general notes don't deserve
   priority placement above the data). */
.dash-intro--footnote { margin: var(--space-4) 0 0; font-size: var(--fs-sm); }
.dash-intro__link {
  color: var(--color-accent-300);
  text-decoration: underline;
}
.dash-intro__link:hover { color: var(--color-primary-300); }
.panel__title {
  font-size: var(--fs-lg);
  margin-bottom: var(--space-4);
  /* Gold heading accent (first-review directive: headings must contrast with
     links/body — the /dash/docs gold, mirrored in the breadcrumb current item). */
  color: var(--color-warning-300);
}
.data-list { display: grid; gap: 0; }
.data-list__row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--border-dark);
}
.data-list__row:last-child { border-bottom: 0; }
.data-list dt { color: var(--on-dark-muted); font-size: var(--fs-sm); }
/* Fourth review: one value size across a data list — the mono accent values
   (Stradephi/Key IDs) were rendering smaller than adjacent dates. */
.data-list dd { color: var(--on-dark); font-weight: 500; text-align: right; font-size: var(--fs-sm); }
.mono { font-family: var(--font-mono); font-size: var(--fs-sm); }
/* Data accent (spec: mono data gets "special color highlighting").
   The `.data-list dd` selectors above win on specificity, so these utilities
   must repeat that context or the accent color never applies inside data lists. */
.mono--accent, .data-list dd.mono--accent { color: var(--color-accent-300); }
.text-success, .data-list dd.text-success { color: var(--color-success-300); }
.text-warning, .data-list dd.text-warning { color: var(--color-warning-300); }
.data-list dd.muted { color: var(--on-dark-muted); }

/* Profile page: editable card + read-only summary side by side */
.profile-grid { display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
@media (min-width: 820px) {
  .profile-grid { grid-template-columns: 1.5fr 1fr; align-items: start; }
}
/* Right column of the profile grid: Account box + External Integrations
   stacked on the aside (third-blue) surface (second review). */
.profile-grid__side { display: grid; gap: var(--space-5); align-content: start; }
/* Required-field asterisk convention (second review: asterisks, not
   "(optional)" text). */
.field__req { color: var(--color-table-header); font-weight: 700; }
/* Stacked sibling panels get breathing room (second review: board scripts
   content boxes were touching). Grid/flex parents space with gap instead. */
.dash-surface > .panel + .panel,
.dash-surface > .panel--wide + .panel--wide { margin-top: var(--space-5); }
/* Whole-tile link variant for script cards (tiles open the edit page —
   second review; no per-tile action links). */
a.script-card { display: block; color: inherit; text-decoration: none; }
a.script-card:hover .script-card__name,
a.script-card:focus-visible .script-card__name { color: var(--color-warning-300); }

/* Multi-line + dropdown variants of the dark form field */
.field__textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.field__select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-right: 36px;
  background-image: linear-gradient(45deg, transparent 50%, var(--on-dark-muted) 50%),
                    linear-gradient(135deg, var(--on-dark-muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.field__select option { color: #000; }
input[disabled].field__input { opacity: 0.6; cursor: not-allowed; }

/* Inline per-field validation feedback */
.field__error { color: var(--color-error-300); font-size: var(--fs-xs); font-weight: 400; }
/* Label row with an "i" hover-hint icon (first review: move field rules out of
   inline hint text into a tooltip on the right side of the header row). */
.field__labelrow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.field__labelrow .field__label { margin-bottom: 0; }
.field__info {
  flex: none;
  width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-dark);
  border-radius: 50%;
  color: var(--color-accent-300);
  font-size: 10px; font-weight: 700; font-style: normal; line-height: 1;
  cursor: help;
}
.field__info:hover, .field__info:focus-visible { border-color: var(--color-accent-300); }
.field__input--error { border-color: var(--flash-error-border); }
.field__input--error:focus {
  border-color: var(--flash-error-border);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-error) 25%, transparent);
}

/* Full-width panel (membership-level widget sits below the profile grid) */
.panel--wide { margin-top: var(--space-5); }
.panel__intro {
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  margin-bottom: var(--space-5);
}

/* Destructive-action panel (membership-level delete) */
.panel--danger { border-color: var(--flash-error-border); margin-top: var(--space-5); }
.delete-blockers {
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  padding-left: var(--space-5);
  display: grid;
  gap: var(--space-2);
  /* Task 141: the global margin reset left the confirm field's label flush
     under this list. Fourth review: still too tight — give the confirm field
     a full section's worth of air. */
  margin-bottom: var(--space-5);
}

/* Membership-level widget */
.level-widget { display: grid; gap: var(--space-5); }
.level-widget__tiles {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}
@media (min-width: 700px) {
  .level-widget__tiles { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1000px) {
  .level-widget__tiles { grid-template-columns: repeat(3, 1fr); }
}

.level-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border-dark);
  border-top: 3px solid var(--tile-accent, var(--border-dark));
  border-radius: var(--radius-md);
}
/* Per-level color themes (spec: "color theme differentiation for each level").
   Assigned cyclically to paid tiles by the widget macro; free tile stays neutral. */
.level-tile--a1 { --tile-accent: var(--color-primary); --tile-accent-text: var(--color-primary-300); }
.level-tile--a2 { --tile-accent: var(--color-accent); --tile-accent-text: var(--color-accent-300); }
.level-tile--a3 { --tile-accent: var(--color-warning); --tile-accent-text: var(--color-warning-300); }
.level-tile--current {
  border-color: var(--color-primary);
  border-top-color: var(--tile-accent, var(--color-primary));
  box-shadow: 0 0 0 1px var(--color-primary);
}
/* Change-Level chooser: the picked (not yet confirmed) tile */
.level-tile--selected {
  border-color: var(--color-accent);
  border-top-color: var(--tile-accent, var(--color-accent));
  box-shadow: 0 0 0 1px var(--color-accent);
}
.level-tile__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.level-tile__name {
  font-size: var(--fs-lg);
  color: var(--on-dark);
  margin: 0;
}
.level-tile__badges {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
  justify-content: flex-end;
}
.level-tile__badge {
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #fff;
  background: var(--tile-accent, var(--color-primary));
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
/* Aqua/gold badge backgrounds need dark text for contrast */
.level-tile--a2 .level-tile__badge,
.level-tile--a3 .level-tile__badge { color: var(--color-navy-900); }
/* Status badge on a held-but-deactivated level (e.g. "Inactive") */
.level-tile__badge--muted,
.level-tile--a2 .level-tile__badge--muted,
.level-tile--a3 .level-tile__badge--muted {
  color: var(--on-dark-muted);
  background: transparent;
  border: 1px solid var(--border-dark);
}
.level-tile__price {
  font-size: var(--fs-base);
  font-weight: 600;
  font-family: var(--font-mono);
  color: var(--tile-accent-text, var(--color-primary-300));
  margin: 0;
}
.level-tile__desc {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  line-height: 1.5;
  margin: 0;
}
.level-tile__details {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  border-top: 1px solid var(--border-dark);
  padding-top: var(--space-3);
  margin-top: auto;
}
.level-tile__summary {
  cursor: pointer;
  color: var(--on-dark);
  font-weight: 500;
}
.level-tile__group {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--on-dark-muted);
  margin: var(--space-3) 0 var(--space-1);
}
.level-tile__list {
  list-style: none;
  display: grid;
  gap: var(--space-1);
  padding: 0;
  margin: 0;
}
.level-tile__list li {
  position: relative;
  padding-left: var(--space-4);
  color: var(--on-dark);
}
.level-tile__list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--tile-accent-text, var(--color-primary-300));
}
.level-tile__action { margin-top: var(--space-3); }
.btn--block { display: block; width: 100%; text-align: center; }
.btn.is-disabled {
  opacity: 0.5;
  pointer-events: none;
  cursor: not-allowed;
}

/* Free/default level: minimized, full-width strip below the paid tiles */
.level-widget__free .level-tile {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
}
.level-tile--free .level-tile__head { flex: 1 1 auto; }
.level-tile--free .level-tile__price { order: 3; }
/* Third review: the free row's action sat misaligned with the name/price
   line — pin it to the row end, sized to its label, vertically centered. */
.level-tile--free .level-tile__action {
  order: 4;
  margin-top: 0;
  margin-left: auto;
  flex: 0 0 auto;
}
.level-tile--free .level-tile__action .btn--block {
  display: inline-flex;
  width: auto;
}

/* Change-Level actions: .btn--upgrade/.btn--downgrade come from the shared
   canon in components.css (fourth review: page-level duplicates removed).
   "Current" is a quiet non-action pill. */
.btn--current {
  background: rgba(255, 255, 255, 0.10);
  color: var(--on-dark);
  border-color: rgba(255, 255, 255, 0.35);
  cursor: default;
}

/* Change-Level page: single-column (vertical) widget + entry CTA */
.level-widget--vertical .level-widget__tiles { grid-template-columns: 1fr; }
.panel__actions { margin-top: var(--space-5); }

/* Change-Level: confirmation step */
.change-level-confirm {
  max-width: 32rem;
  margin: var(--space-5) auto 0;
  padding: var(--space-6);
  background: var(--surface-card);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-lg);
  color: var(--on-dark);
  text-align: center;
}
.change-level-confirm__title { font-size: var(--fs-lg); margin-bottom: var(--space-2); }
.change-level-confirm__price { font-weight: 600; margin-bottom: var(--space-3); }
.change-level-confirm__note,
.change-level-confirm__devnote {
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  margin-bottom: var(--space-5);
}
.change-level-confirm__actions {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
  flex-wrap: wrap;
}

/* Trading Interface landing: link-box tiles + Recent Transactions widget */
.trading-tiles {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
  margin-bottom: var(--space-5);
}
@media (min-width: 700px) {
  .trading-tiles { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1000px) {
  .trading-tiles { grid-template-columns: repeat(4, 1fr); }
}
.trading-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  color: var(--on-dark);
  transition: border-color .15s ease, background-color .15s ease, transform .05s ease;
}
a.trading-tile:hover {
  border-color: var(--color-primary);
  background: rgba(30, 144, 255, 0.08);
}
a.trading-tile:active { transform: translateY(1px); }
.trading-tile__title { font-size: var(--fs-lg); margin: 0; }
.trading-tile__desc {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  line-height: 1.5;
  margin: 0;
}
.trading-tile__cta {
  margin-top: auto;
  padding-top: var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-primary-300);
}
.trading-tile--pending { opacity: 0.6; }
.trading-tile__cta--pending {
  color: var(--on-dark-muted);
  font-weight: 500;
  font-style: italic;
}

/* Recent Transactions widget (empty / at-a-glance state) */
.recent-tx__head { margin-bottom: var(--space-4); }
.recent-tx__hint {
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  margin: var(--space-1) 0 0;
}
.recent-tx__empty {
  border: 1px dashed var(--border-dark);
  border-radius: var(--radius-md);
  padding: var(--space-7) var(--space-5);
  text-align: center;
}
.recent-tx__empty-title {
  font-weight: 600;
  color: var(--on-dark);
  margin: 0 0 var(--space-2);
}
.recent-tx__empty-desc {
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  line-height: 1.5;
  max-width: 48ch;
  margin: 0 auto;
}

/* Docs surface (§0.1.14) ------------------------------------------------- */
/* Landing: topic cards */
.docs-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
  margin-bottom: var(--space-5);
}
@media (min-width: 760px) {
  .docs-grid { grid-template-columns: repeat(2, 1fr); }
}
.docs-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  color: var(--on-dark);
  transition: border-color .15s ease, background-color .15s ease, transform .05s ease;
}
a.docs-card:hover {
  border-color: var(--color-primary);
  background: rgba(30, 144, 255, 0.08);
}
a.docs-card:active { transform: translateY(1px); }
.docs-card__tag {
  /* Audience-clarity pass (Task 147): member guides carry the primary blue
     tag; Mentor guides keep the gold Stradephi accent (PI Color System). */
  align-self: flex-start;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-primary-300);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.docs-card__tag--mentor { color: var(--color-warning-300); }
.docs-card--mentor {
  border-color: color-mix(in srgb, var(--color-warning) 35%, var(--border-dark));
}
a.docs-card--mentor:hover {
  border-color: var(--color-warning-300);
  background: color-mix(in srgb, var(--color-warning) 8%, transparent);
}
/* Landing: audience groups (Task 147) */
.docs-group { margin-bottom: var(--space-6); }
.docs-group__title {
  font-size: var(--fs-lg);
  color: var(--color-primary-300);
  margin: 0 0 var(--space-1);
}
.docs-group__title--mentor { color: var(--color-warning-300); }
.docs-group__desc {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  margin: 0 0 var(--space-3);
}
/* Detail pages: audience badge under the title (Task 147) */
/* Fourth review (Task 197): the audience pill renders inside the title
   block's subtitle-row controls area, so it carries no block margin there. */
.title-block__controls .doc-audience { margin: 0; }
.doc-audience {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  padding: 4px 12px;
  border: 1px solid color-mix(in srgb, var(--color-primary) 40%, var(--border-dark));
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-primary-300);
  background: rgba(30, 144, 255, 0.08);
}
.doc-audience--mentor {
  color: var(--color-warning-300);
  border-color: color-mix(in srgb, var(--color-warning) 40%, var(--border-dark));
  background: color-mix(in srgb, var(--color-warning) 10%, transparent);
}
.doc-audience__label {
  color: var(--on-dark-muted);
  font-weight: 500;
  text-transform: none;
  letter-spacing: normal;
}
.docs-card__title { font-size: var(--fs-lg); margin: 0; }
.docs-card__summary {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  line-height: 1.5;
  margin: 0;
}
.docs-card__cta {
  margin-top: auto;
  padding-top: var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-primary-300);
}
.docs-empty {
  border: 1px dashed var(--border-dark);
  border-radius: var(--radius-md);
  padding: var(--space-7) var(--space-5);
  text-align: center;
}
.docs-empty__title { font-weight: 600; color: var(--on-dark); margin: 0 0 var(--space-2); }
.docs-empty__desc {
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  line-height: 1.5;
  max-width: 48ch;
  margin: 0 auto;
}

/* Guide article: stacked panels with prose + code + tables */
.doc-article { display: grid; gap: var(--space-5); }
.doc-section { padding: var(--space-6); }
.doc-text { color: var(--on-dark); line-height: 1.6; margin: 0 0 var(--space-3); }
.doc-text:last-child { margin-bottom: 0; }
.doc-subhead {
  font-size: var(--fs-md);
  color: var(--on-dark);
  margin: var(--space-5) 0 var(--space-2);
}
.doc-list, .doc-steps { margin: 0 0 var(--space-3); padding-left: var(--space-5); color: var(--on-dark); }
.doc-list { list-style: disc; }
.doc-steps { list-style: decimal; }
.doc-list li, .doc-steps li { line-height: 1.6; margin-bottom: var(--space-2); }
.doc-link { color: var(--color-primary-300); }
.doc-link:hover { color: #fff; }
.doc-code {
  background: rgba(0, 0, 0, 0.30);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin: 0 0 var(--space-3);
  overflow-x: auto;
  color: var(--on-dark);
  line-height: 1.5;
  white-space: pre;
}
.doc-code code { font: inherit; color: inherit; background: none; }
/* Fourth review (Task 197): callout convention — callouts INSIDE a card/panel
   use the warm gold callout style; blue info-box styling is reserved for
   callouts that sit outside cards (e.g. the title block's info row).
   Every .doc-note sits inside a .panel.doc-section, so it takes the gold
   callout tokens. */
.doc-note {
  padding: 12px 16px;
  background: var(--callout-bg);
  border-left: 3px solid var(--callout-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  color: var(--callout-ink);
  line-height: 1.5;
  margin: var(--space-3) 0 0;
}
.doc-warning {
  padding: 12px 16px;
  background: color-mix(in srgb, var(--color-warning) 12%, transparent);
  border-left: 3px solid var(--color-warning-300);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  color: var(--color-warning-300);
  line-height: 1.5;
  margin: var(--space-3) 0 0;
}
.doc-table-wrap { overflow-x: auto; margin: 0 0 var(--space-3); }
.doc-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.doc-table th, .doc-table td {
  text-align: left;
  padding: var(--space-3);
  border-bottom: 1px solid var(--border-dark);
  vertical-align: top;
}
.doc-table th { color: var(--color-table-header); font-weight: 600; font-size: var(--fs-md); }
.doc-table td { color: var(--on-dark-muted); line-height: 1.5; }
.doc-table tr:last-child td { border-bottom: 0; }

/* Webhook Secrets page (§III.1.4) ---------------------------------------- */
/* Statistics row */
.wh-stats {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, 1fr);
  margin-bottom: var(--space-5);
}
@media (min-width: 760px) {
  .wh-stats { grid-template-columns: repeat(4, 1fr); }
}
.wh-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-5);
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
}
.wh-stat__num { font-family: var(--font-mono); font-size: var(--fs-xl); font-weight: 600; color: var(--color-accent-300); }
.wh-stat__label { font-size: var(--fs-sm); color: var(--on-dark-muted); }
.wh-stat__sub { font-size: var(--fs-xs); color: var(--on-dark-muted); opacity: 0.8; }

/* Main + aside grid */
.wh-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 980px) {
  .wh-grid { grid-template-columns: 2fr 1fr; }
}
.wh-main { display: grid; gap: var(--space-5); }
/* Right-side boxes share the main column's vertical rhythm (first review). */
.wh-aside { display: grid; gap: var(--space-5); align-content: start; }
.wh-aside .panel { margin: 0; }
/* Third blue (second review): RHS narrow content boxes sit one shade lighter
   than the main panels so the page reads in layers. */
.wh-aside .panel,
.dash-cols__side .panel,
.panel--aside { background: var(--surface-aside); }

/* Generic main + aside page grid (first review: wide-left / narrow-right
   layout on editor pages; side boxes share the main column's vertical gap). */
.dash-cols {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 980px) {
  .dash-cols { grid-template-columns: 2fr 1fr; }
}
.dash-cols__main,
.dash-cols__side { display: grid; gap: var(--space-5); }
.dash-cols__side .panel { margin: 0; }

/* Two equal-width columns (Spheres) */
.sphere-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 980px) {
  .sphere-grid { grid-template-columns: 1fr 1fr; }
}
.sphere-grid .panel { margin: 0; }

/* Create-a-secret + How-it-works duo: equal width AND equal height so the
   full-width secrets table below gets the prominence (first review). */
.wh-duo {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  margin-bottom: var(--space-5);
}
@media (min-width: 980px) {
  .wh-duo { grid-template-columns: 1fr 1fr; }
}
.wh-duo .panel { margin: 0; }

/* One-time new-secret card (success border) */
.wh-new {
  background: var(--surface-card);
  border: 1px solid var(--flash-success-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  margin-bottom: var(--space-5);
  color: var(--on-dark);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-success) 35%, transparent),
              0 0 24px color-mix(in srgb, var(--color-success) 18%, transparent);
}
.wh-new__title { font-size: var(--fs-lg); margin: 0 0 var(--space-4); color: var(--color-success-300); }

/* Task 145: two fields on the one-time card — identity (Key ID + label) and
   the secret value; the webhook URL lives in its own permanent section. */
.wh-new__field + .wh-new__field { margin-top: var(--space-4); }
.wh-new__subhead-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.wh-new__subhead {
  font-size: var(--fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--on-dark-muted);
  margin: 0;
}

/* Copy rows */
.wh-copy { display: flex; gap: var(--space-2); align-items: stretch; }
.wh-copy__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 10px 14px;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  color: var(--on-dark);
  font: inherit;
}
.wh-copy__input:focus { outline: none; border-color: var(--color-primary); }
/* Credential inputs: CSS-masked text (not type=password) so browser password
   managers don't offer to suggest/save values (second review). */
.field__input--secret { -webkit-text-security: disc; }

/* Table rows link to the per-secret details page (second review). */
.wh-table__link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted var(--on-dark-muted);
}
.wh-table__link:hover { color: var(--color-primary-300); border-bottom-color: currentColor; }
a.wh-table__link.mono--accent { color: var(--color-accent-300); }

/* Details page: stacked right-hand column inside .wh-duo. */
.wh-stack { display: grid; gap: var(--space-5); align-content: start; }
.wh-stack .panel { margin: 0; }
.wh-result-raw { color: var(--on-dark-muted); font-size: var(--fs-xs); }

/* Create card / empty states */
.wh-cap-note, .wh-empty { color: var(--on-dark-muted); font-size: var(--fs-sm); margin: 0; }

/* Secrets table */
.wh-table-wrap { overflow-x: auto; }
.wh-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.wh-table th, .wh-table td {
  text-align: left;
  padding: var(--space-3);
  border-bottom: 1px solid var(--border-dark);
  vertical-align: middle;
}
.wh-table th { color: var(--color-table-header); font-weight: 600; font-size: var(--fs-md); white-space: nowrap; }
.wh-table td { color: var(--on-dark); }
.wh-table tr:last-child td { border-bottom: 0; }
.wh-fail { color: var(--flash-error-border); }
/* Data accents in the secrets table (contextual selectors so they beat .wh-table td) */
.wh-table td.mono--accent { color: var(--color-accent-300); }
.wh-table td.num { font-family: var(--font-mono); color: var(--color-accent-300); }
.wh-result--ok { color: var(--color-success-300); }
.wh-result--noop { color: var(--on-dark-muted); }
.wh-result--fail { color: var(--color-error-300); }
.wh-result--paused { color: var(--color-warning-300); }

.wh-badge {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
}
/* Task 145: Active follows the app's success/green convention (was blue). */
.wh-badge--active { color: #fff; background: var(--color-success); }
/* Third review: "Paused" reads as deliberately-on-hold — gray field with a
   gold accent — rather than blending into the muted chrome. */
.wh-badge--inactive {
  color: var(--color-warning-300);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid color-mix(in srgb, var(--color-warning-300) 55%, transparent);
}
.wh-badge--revoked { color: #fff; background: var(--flash-error-border); }

/* Fourth review: inline-block so the button aligns and keeps vertical rhythm;
   intro text following an action form gets breathing room above it. */
.wh-inline-form { display: inline-block; }
.wh-inline-form + .panel__intro { margin-top: var(--space-5); }
.panel .panel__intro:last-child { margin-bottom: 0; }

/* Help / aside */
.wh-help {
  margin: 0 0 var(--space-5);
  padding-left: var(--space-5);
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
  display: grid;
  gap: var(--space-2);
}
.wh-aside__note { color: var(--on-dark-muted); font-size: var(--fs-xs); margin: var(--space-3) 0 0; line-height: 1.5; }

/* Button variants used on this page */
.btn--ghost-on-dark { background: transparent; color: var(--on-dark); border-color: var(--border-dark); }
.btn--ghost-on-dark:hover { border-color: var(--color-primary); color: #fff; }
/* Deliberate exception to the semi-transparent standard: delete is permanent,
   so it keeps a strong SOLID red. Anything recoverable uses .btn--revoke. */
.btn--danger { background: var(--action-destructive); color: #fff; border-color: var(--action-destructive); }
.btn--danger:hover { filter: brightness(1.08); }
/* .btn--revoke and .btn--pause come from the shared canon in components.css
   (fourth review: page-level duplicates removed). */
.btn--sm { padding: 6px 12px; font-size: var(--fs-xs); }

/* --- Exchange Connections (§IV.1.1) ----------------------------------- */
.wh-badge--expired { color: #fff; background: var(--flash-error-border); }

.ex-exchange + .ex-exchange { margin-top: 0; }
.ex-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.ex-cap { color: var(--on-dark-muted); font-size: var(--fs-xs); white-space: nowrap; text-align: right; }
/* Task 143: per-card health rollup inside the old cap slot. */
.ex-cap__alert { color: var(--color-error-300); font-weight: 600; }
.ex-cap__ok { color: var(--color-success-300); }
/* Whitelist IP module (Task 143): the address is the headline. */
.ex-ip-addr {
  margin: 0 0 var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--color-accent-300);
}
.ex-note { color: var(--on-dark-muted); font-size: var(--fs-xs); line-height: 1.5; margin: var(--space-2) 0 0; }

.ex-accounts { display: grid; gap: var(--space-4); margin-top: var(--space-4); }
@media (min-width: 720px) { .ex-accounts { grid-template-columns: 1fr 1fr; } }

.ex-account {
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md, 8px);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
}
.ex-account__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.ex-account__title { font-weight: 600; color: var(--on-dark); }
/* Live vs Paper at a glance (first review): gold = real money, aqua = sim */
.ex-account__title--live { color: var(--color-warning-300); }
.ex-account__title--paper { color: var(--color-accent-300); }
.ex-account__free { color: var(--on-dark-muted); font-size: var(--fs-xs); }
/* Connection-status accent on the account box itself */
.ex-account--active { border-left: 3px solid var(--color-success-300); }
.ex-account--attention { border-left: 3px solid var(--color-error-300); }
.ex-account--warning { border-left: 3px solid var(--color-warning-300); }

.ex-meta { margin: 0 0 var(--space-3); display: grid; gap: var(--space-2); }
.ex-meta__row { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--fs-sm); }
.ex-meta__row dt { color: var(--on-dark-muted); margin: 0; }
.ex-meta__row dd { color: var(--on-dark); margin: 0; text-align: right; }
.ex-test--ok { color: var(--color-success-300); }
.ex-test--fail { color: var(--flash-error-border); }
.ex-test--unavailable { color: var(--color-warning-300); }
.ex-key-warning {
  margin: 0 0 var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--color-warning-300);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--color-warning-300) 12%, transparent);
  color: var(--on-dark);
  font-size: var(--fs-xs);
  line-height: 1.45;
}
.ex-key-warning--failed {
  border-left-color: var(--color-error-300);
  background: color-mix(in srgb, var(--color-error-300) 12%, transparent);
}

.ex-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: auto; }

.ex-credtype { border: 0; padding: 0; margin: 0 0 var(--space-3); display: flex; flex-wrap: wrap; gap: var(--space-3); }
.ex-credtype legend { padding: 0; margin-bottom: var(--space-2); }
.ex-radio { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--on-dark); font-size: var(--fs-sm); }

.ex-credgroup { border: 0; padding: 0; margin: 0 0 var(--space-3); }
.ex-credgroup__legend { padding: 0; margin-bottom: var(--space-2); color: var(--on-dark-muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; }
.ex-connect .field { margin-bottom: var(--space-3); }

.ex-health { display: grid; gap: var(--space-2); margin: 0; }
.ex-health__row { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--fs-sm); }
.ex-health__row dt { color: var(--on-dark-muted); margin: 0; }
.ex-health__row dd { color: var(--on-dark); margin: 0; font-weight: 600; }
.ex-health__row dd.num { font-family: var(--font-mono); color: var(--color-accent-300); }
.ex-health__row dd.num--alert { color: var(--color-error-300); }

/* ── Mentor console (Phase 11): hub tiles, tables, pills, sphere cards ─────── */

/* Console hub tiles (Admin Console, Mentor Board, Payment Gateways) */
.console-tiles {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  margin-bottom: var(--space-5);
}
.console-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  color: var(--on-dark);
  transition: border-color .15s ease, background-color .15s ease, transform .05s ease;
}
a.console-tile:hover { border-color: var(--color-primary); background: rgba(30, 144, 255, 0.08); }
a.console-tile:active { transform: translateY(1px); }
.console-tile__title { font-size: var(--fs-lg); margin: 0; }
.console-tile__desc { font-size: var(--fs-sm); color: var(--on-dark-muted); line-height: 1.5; margin: 0; }
.console-tile__cta {
  margin-top: auto;
  padding-top: var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-primary-300);
  display: flex;
  align-items: center;
}
.console-tile--pending { opacity: 0.6; }
.console-tile__cta--pending { color: var(--on-dark-muted); font-weight: 500; font-style: italic; }
/* Version tag chip — bottom row of the tile, pushed to the right edge of the
   CTA line (third review, July 31 2026; previously floated absolute top-right). */
.console-tile__tier {
  margin-left: auto;
  font-size: 0.66rem;
  font-weight: 600;
  font-style: normal;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  color: var(--on-dark-muted);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border-dark);
}
.console-tile__tier--on { color: #fff; background: var(--color-primary); border-color: transparent; }

/* Patrons filter stat boxes — one full-width row on desktop, in a lighter
   blue than the table surface (first review). */
.console-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.console-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 96px;
  flex: 1 1 96px;
  padding: var(--space-3) var(--space-4);
  background: rgba(30, 144, 255, 0.14);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}
@media (min-width: 760px) {
  .console-stats { flex-wrap: nowrap; }
}
a.console-stat:hover { border-color: var(--color-primary); background: rgba(30, 144, 255, 0.22); text-decoration: none; }
.console-stat--on { border-color: var(--color-primary); background: rgba(30, 144, 255, 0.26); }
.console-stat__num { font-family: var(--font-mono); font-size: var(--fs-lg); font-weight: 600; color: var(--color-accent-300); }
.console-stat__label { font-size: var(--fs-xs); color: var(--on-dark-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.console-stat--test .console-stat__num { color: var(--color-warning-300); }
/* Task 143: "Needs attention" stat box — error tint on the count when >0. */
.console-stat--alert .console-stat__num { color: var(--color-error-300); }
.console-stat--alert { border-color: var(--color-error-300); }

/* Second review: stat/filter boxes read darker (mirror the wh-stat surface).
   Used on Exchange Connections and anywhere the light-blue tint is retired. */
.console-stat--dark { background: rgba(0, 0, 0, 0.18); }
a.console-stat--dark:hover { background: rgba(0, 0, 0, 0.30); border-color: var(--color-primary); }
.console-stat--dark.console-stat--on { background: rgba(0, 0, 0, 0.34); border-color: var(--color-primary); }

/* Filter dropdown row (Patrons: Account Type / Role — second review).
   Selects sit on the darker surface; an explicit Apply keeps it JS-free. */
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; margin-bottom: var(--space-4); }
.filter-bar .field { margin-bottom: 0; flex: 0 1 200px; }
.filter-bar .field__select { background: rgba(0, 0, 0, 0.28); }
.filter-bar__submit { flex: 0 0 auto; }

/* Generic data table (Membership Levels, Patrons, sync preview) */
.table-wrap { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.data-table th, .data-table td {
  padding: var(--space-3);
  text-align: left;
  border-bottom: 1px solid var(--border-dark);
  vertical-align: top;
}
.data-table th { color: var(--color-table-header); font-weight: 600; font-size: var(--fs-md); white-space: nowrap; }
.data-table td { color: var(--on-dark); }
.data-table tr:last-child td { border-bottom: 0; }
.data-table tbody tr { transition: background-color .15s ease; }
.data-table tbody tr:hover { background: color-mix(in srgb, var(--color-surface-elevated) 45%, transparent); }
.data-table__actions { text-align: right; white-space: nowrap; }
/* Numeric data cells: mono + aqua data accent */
.data-table .num { font-family: var(--font-mono); color: var(--color-accent-300); }

/* Status / role / default pills */
.pill {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.4;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  color: var(--on-dark-muted);
  border: 1px solid var(--border-dark);
  white-space: nowrap;
}
.pill--status-active { color: #fff; background: var(--color-success); border-color: transparent; }
/* Inactive must read distinctly against the navy surface (first review):
   neutral grey chip, not a blue-on-blue outline. */
.pill--status-inactive { color: var(--on-dark); background: rgba(255, 255, 255, 0.16); border-color: transparent; }
.pill--status-onboarding { color: var(--color-navy-900); background: var(--color-warning); border-color: transparent; }
.pill--status-suspended,
.pill--status-repealing { color: #fff; background: var(--color-error); border-color: transparent; }
/* Sphere connection states (third review): Active / Inactive / Paused / Failed.
   Not-active states follow the grey-and-yellow family — inactive is the grey
   chip above, paused shares onboarding's gold (recoverable, attention-worthy).
   Failed is a fault condition and reads garnet like other failures. */
.pill--status-paused { color: var(--color-navy-900); background: var(--color-warning); border-color: transparent; }
/* Sphere onboarding column (Sept 1 ruling): Requested is the owner's
   worklist state and carries the warning emphasis; Invited is in-flight;
   Connected is done. */
.pill--sphere-requested { color: var(--color-navy-900); background: var(--color-warning); border-color: transparent; }
.pill--sphere-sent { color: var(--on-dark); background: rgba(255, 255, 255, 0.16); border-color: transparent; }
.pill--sphere-connected { color: #fff; background: var(--color-success); border-color: transparent; }
.pill--sphere-needs_attention { color: #fff; background: var(--color-error); border-color: transparent; }
.patrons-table__sphere-email { font-size: var(--fs-xs); margin-top: 4px; word-break: break-all; }
.patrons-table__sphere-action { margin-top: 6px; }
.pill--status-failed { color: #fff; background: var(--color-error); border-color: transparent; }
.pill--default { color: #fff; background: var(--color-primary); border-color: transparent; }
.pill--dev { color: var(--color-navy-900); background: var(--color-dev); border-color: transparent; }
/* Test-user marker (Task 141): test data reads gold/warning everywhere else
   (patrons-table__id--test, console-stat--test); magenta is reserved for
   DEV_ONLY gating, which a test user is not. */
.pill--test { color: var(--color-navy-900); background: var(--color-warning); border-color: transparent; }
.pill--level { color: var(--color-accent-300); border-color: rgba(102, 217, 232, 0.45); }
.pill--atype-member { color: var(--color-accent-300); border-color: rgba(102, 217, 232, 0.45); }
.pill--atype-mentor { color: var(--color-primary-300); border-color: rgba(109, 184, 255, 0.5); }
/* Role pills (third review: role is never blank — 'user' default). */
.pill--role-user { color: var(--on-dark); border-color: rgba(255, 255, 255, 0.35); }
.pill--role-admin { color: var(--color-navy-900); background: var(--color-accent); border-color: transparent; }
.pill--role-manager { color: var(--color-navy-900); background: var(--color-warning); border-color: transparent; }
.pill--role-mentor,
.pill--role-super { color: var(--color-primary-300); border-color: rgba(109, 184, 255, 0.5); }
/* Task 217: TV-sync flag on the Patrons list, mirroring the member-facing
   notice's two honest states — missing username is the actionable fix
   (warning emphasis, matches pill--sphere-requested); a TV-side pending/
   failed retry is quieter (matches pill--sphere-sent). */
.pill--tv-missing_username { color: var(--color-navy-900); background: var(--color-warning); border-color: transparent; }
.pill--tv-retrying { color: var(--on-dark); background: rgba(255, 255, 255, 0.16); border-color: transparent; }

/* Patrons table: Stradephi ID links carry the aqua mono data accent */
.data-table td .patrons-table__id { color: var(--color-accent-300); text-decoration: none; }
.data-table td .patrons-table__id:hover { color: var(--color-accent-300); text-decoration: underline; }
/* Test users: gold ID highlight replaces the retired Test? column */
.data-table td .patrons-table__id--test,
.data-table td .patrons-table__id--test:hover { color: var(--color-warning-300); }

/* Grouped fields (donation rates, bot credentials) */
.field-group { border: 0; padding: 0; margin: 0 0 var(--space-4); }
.field-group__legend {
  /* Match the field-label face (first review: the Donation rates heading
     broke the section-title style used by the rest of the form). */
  padding: 0;
  margin-bottom: var(--space-2);
  color: var(--on-dark-label);
  font-size: var(--fs-sm);
  font-weight: 600;
}
/* Third review: all five period rates share one row on desktop. */
.rate-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
@media (max-width: 720px) {
  .rate-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
}
.rate-grid .field { margin-bottom: 0; }

/* Checkbox field row */
.field--check { margin-bottom: var(--space-4); }
.field__check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--on-dark);
  cursor: pointer;
}
.field__check input { width: 16px; height: 16px; accent-color: var(--color-primary); flex: none; }
.field__check input:disabled { cursor: not-allowed; }

/* Radio row (third review: Membership Level status picks by radio, not dropdown) */
.field__radios { display: flex; flex-wrap: wrap; gap: var(--space-4); padding-top: 2px; }
.field__radio {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  color: var(--on-dark);
  font-size: var(--fs-sm);
}
.field__radio input { width: 16px; height: 16px; accent-color: var(--color-primary); flex: none; }

/* Sphere bot credentials: masked TEXT inputs (never type=password) so browser
   password managers don't offer to save/fill/generate (third review). Firefox
   ignores text-security and shows the keystrokes — acceptable: the field is
   write-only and never echoes a stored value. */
.field__input--secret { -webkit-text-security: disc; }

/* Two-class form so the teal survives .field__input's own color (specificity). */
.field__input.mono--accent { color: var(--color-accent-300); }

/* Sphere cards */
.sphere-card { margin-top: var(--space-5); }
.sphere-card__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.sphere-card__head .panel__title { margin-bottom: 0; }
/* Second review: status pillboxes sit right-aligned on the title row. */
.sphere-card__head .panel__title + .pill { margin-left: auto; }
.sphere-card__row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-dark);
}
.sphere-card__row-actions form { margin: 0; }
.sphere-config-paste {
  min-height: 11rem;
  resize: vertical;
  font-family: var(--font-mono);
  line-height: 1.5;
  white-space: pre;
  overflow-wrap: normal;
  overflow-x: auto;
}
.sphere-current-value {
  max-width: 100%;
  margin: 0;
  overflow-wrap: anywhere;
}
@media (max-width: 560px) {
  .sphere-card__row-actions,
  .sphere-card__row-actions form,
  .sphere-card__row-actions .btn,
  .sphere-card .panel__actions,
  .sphere-card .panel__actions .btn {
    width: 100%;
  }
}

/* DEV dry-run preview panel */
.panel--preview {
  margin-bottom: var(--space-5);
  border-color: var(--color-primary);
  background: rgba(30, 144, 255, 0.06);
}

/* Back-link + small utilities */
.dash-back { margin-top: var(--space-6); }
.dash-back a { color: var(--color-primary-300); font-size: var(--fs-sm); }
.dash-back a:hover { color: #fff; }
.muted { color: var(--on-dark-muted); }
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Notifications feed (dash/notifications.html) ---------------------- */
.notif-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: var(--space-4);
}
.tests-section__title {
  font-size: var(--fs-lg);
  margin: var(--space-6) 0 var(--space-3);
}

.notif-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.notif-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--surface-card);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
}
.notif-item--unread {
  border-color: var(--color-accent);
  background: rgba(0, 188, 212, 0.06);
}
.notif-item__main { min-width: 0; }
.notif-item__subject {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-weight: 600;
  color: var(--on-dark);
}
.notif-item__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
}
.notif-item__link { color: var(--on-dark); }
.notif-item__link:hover { color: #fff; }
.notif-item__body {
  margin: var(--space-2) 0 0;
  color: var(--on-dark-muted);
  font-size: var(--fs-sm);
}
.notif-item__meta {
  margin: var(--space-2) 0 0;
  color: var(--on-dark-muted);
  font-size: var(--fs-xs);
}
.notif-item__action { flex: none; margin: 0; }

/* --- Member Scripts (Phase 8.5) ------------------------------------------ */
.script-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 640px) {
  .script-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .script-cards { grid-template-columns: repeat(3, 1fr); }
}
.script-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-surface-elevated) 45%, transparent);
}
.script-card__name { font-size: var(--fs-md); margin: 0; color: var(--on-dark); }
.script-card__id { margin: 0; font-size: var(--fs-xs); color: var(--color-accent-300); word-break: break-all; }
.script-card__desc { margin: 0; font-size: var(--fs-sm); color: var(--on-dark-muted); }
.script-card__foot {
  margin-top: auto;
  padding-top: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.script-card__meta { font-size: var(--fs-xs); color: var(--on-dark-muted); }
/* Informational callout box (second review: notes like "editing status
   arrives later" and "what the test checks" step out of plain intro text
   into a visually distinct box). */
/* Third review: this box previously sat on --surface-aside (one of the three
   navy content shades) and referenced two tokens that were never defined, so
   the accent bar dropped out entirely and it read as just another blue box.
   Now a warm gold-accented neutral, off the blue ramp by construction. */
.callout {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--callout-border);
  border-radius: var(--radius-sm);
  background: var(--callout-bg);
  color: var(--callout-ink);
  font-size: var(--fs-sm);
}
.callout p { margin: 0; }
.callout p + p { margin-top: var(--space-2); }

/* Task 149: badge marking test modules that exercise dev-only surfaces on the
   System Tests inventory, so a count is never mistaken for a production one. */
.tests-badge {
  display: inline-block;
  margin-left: var(--space-1);
  padding: 0.05rem 0.45rem;
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  font-weight: 600;
  vertical-align: middle;
  white-space: nowrap;
}
.tests-badge--dev {
  border: 1px solid var(--callout-border);
  color: var(--callout-ink);
  background: var(--callout-bg);
}
.tests-badge--prod {
  border: 1px solid var(--flash-success-border);
  color: var(--color-success-300);
  background: var(--flash-success-bg);
}

/* --- Board Scripts + Script-to-Course (Phase 8.6) ------------------------- */
.script-search { display: flex; gap: var(--space-2); align-items: center; }
.script-search__input { max-width: 220px; padding: 6px var(--space-3); font-size: var(--fs-sm); }
.page-nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
.page-nav__status { font-size: var(--fs-sm); color: var(--on-dark-muted); }
.stc-course-list { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: grid; gap: var(--space-3); }
.stc-course {
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-surface-elevated) 45%, transparent);
}
.stc-course__label {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
}
.stc-course__check { margin-top: 4px; accent-color: var(--color-primary); }
.stc-course__body { display: grid; gap: var(--space-1); }
.stc-course__name { color: var(--on-dark); font-weight: 500; display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.stc-course__levels { font-size: var(--fs-sm); color: var(--on-dark-muted); }
.stc-coming { opacity: 0.5; text-decoration: underline dotted; cursor: not-allowed; }

/* --- Registration page (Get Started) -------------------------------------- */
.auth-shell--register { flex-direction: column; align-items: center; gap: var(--space-6); }
.captcha-tiles {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-2) 0;
  min-height: 44px;
}
.captcha-tiles__img { max-height: 52px; width: auto; }
.captcha-tiles__op { color: var(--on-dark-muted); font-size: var(--fs-lg); font-family: var(--font-mono); }
.register-levels { max-width: 560px; width: 100%; }
.register-levels__title { color: var(--on-dark); font-size: var(--fs-lg); margin: 0 0 var(--space-2); }
.register-levels__intro { color: var(--on-dark-muted); font-size: var(--fs-sm); margin: 0 0 var(--space-4); }

/* --- DEV_ONLY display rule (second review, July 26, 2026; recolored Task 112
   follow-up, Aug 28 2026) ---------------------------------------------------
   DEV_ONLY modules render with a card tint in dev config (no labeled
   pillbox) and are absent in stage/prod. The tint sits on the module/card
   itself, per the prototype pattern. Uses the dedicated --color-dev token
   (tokens.css) rather than the gold/warning token, since gold is already
   spoken for elsewhere on the dashboard (headings, Super-status, Live-money)
   — restyle DEV_ONLY everywhere by changing --color-dev/--color-dev-300
   only; nothing below should ever hardcode a color value directly. */
.dev-tint,
.console-tile--dev,
.trading-tile--pending.trading-tile--dev,
.docs-card.docs-card--dev,
.recent-tx.recent-tx--dev,
.console-stat--dev,
.ex-exchange--dev,
.ex-account--dev {
  border: 1px solid color-mix(in srgb, var(--color-dev) 55%, transparent);
  background: color-mix(in srgb, var(--color-dev) 12%, transparent);
}
/* Exchange Connections (Task 112, Aug 27 2026): Live accounts/tab and the
   five non-MVP exchanges (only Bybit/Alpaca have real dispatch adapters) are
   DEV_ONLY — same convention as above. `.ex-account--dev` layers onto
   the existing status border-left accent rather than replacing it. A stray
   connection that survives outside dev config (fail-safe: never silently
   dropped) gets the tint PLUS an explicit out-of-policy note so it reads as
   an anomaly, not a blended-in normal state. */
.ex-account--dev { border-left-color: color-mix(in srgb, var(--color-dev) 70%, transparent); }
.ex-out-of-policy {
  color: var(--color-dev-300);
  font-size: var(--fs-xs);
  font-weight: 600;
}
.dev-tint {
  padding: var(--space-3);
  border-radius: var(--radius-md);
}
.trading-tile--pending.trading-tile--dev { opacity: 0.85; }
.btn--dev {
  border-color: color-mix(in srgb, var(--color-dev) 55%, transparent) !important;
  background: color-mix(in srgb, var(--color-dev) 12%, transparent);
}
.nav__link--dev {
  border: 1px solid color-mix(in srgb, var(--color-dev) 45%, transparent);
  border-radius: var(--radius-pill);
  padding: 2px 10px;
}
.dev-tint__hint {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-dev-300);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
