/* ============================================================
   MemberCairn shared components. Loaded after tokens.css so all
   custom properties resolve. Component primitives only —
   page-specific styles stay in their template.
   ============================================================ */

/* ----- Muted helper text ----- */
/* Captions / hints / "optional" markers. Was relied on by ~50 call sites across
   admin templates but only ever defined page-scoped, so most rendered at full
   text color. Defining it once here makes the intended grey appear everywhere.
   More-specific scoped variants (.stat-tile.muted, .member-line.muted) still win. */
.muted { color: var(--color-text-secondary); }

/* ----- Screen-reader-only utility ----- */
/* Visually hidden but available to assistive tech — for skip links, field
   labels, and aria-live announcement regions. Shared so a11y work doesn't
   re-define it per page (was previously only in page-scoped CSS). */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
}

/* ----- Cards ----- */
.card {
  background: var(--color-bg-primary);
  border: 0.5px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}

/* ----- Buttons ----- */
.btn-primary {
  background: var(--color-accent);
  color: white;
  border: none;
  border-radius: var(--radius-md);
  padding: 8px 16px;
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: background-color 0.12s ease, box-shadow 0.12s ease;
}
.btn-primary:hover {
  background: var(--color-accent-strong);
}
.btn-primary:active {
  background: var(--color-accent-strong);
  transform: translateY(1px);
}
.btn-primary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(31, 75, 59, 0.22);
}
.btn-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.btn-secondary {
  background: transparent;
  color: var(--color-accent);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: 8px 16px;
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: background-color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.btn-secondary:hover {
  background: var(--color-bg-tint);
  border-color: var(--color-accent-strong);
}
.btn-secondary:active {
  background: var(--color-bg-tint);
  transform: translateY(1px);
}
.btn-secondary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(31, 75, 59, 0.22);
}
.btn-secondary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
@media (prefers-reduced-motion: reduce) {
  .btn-primary, .btn-secondary { transition: none; }
  .btn-primary:active, .btn-secondary:active { transform: none; }
}
/* Quiet tertiary button — a hide/state-change or "+ add" action that must not
   out-shout .btn-secondary (e.g. Archive an inbox item, add an FAQ row, add an
   outside address). Neutral border + muted text; warms on hover. */
.btn-ghost {
  background: transparent;
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 8px 14px;
  font: inherit;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
}
.btn-ghost:hover {
  background: var(--color-bg-tint);
  color: var(--color-text-primary);
  border-color: var(--color-cairn-mid);
}
.btn-ghost:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(31, 75, 59, 0.22);
}
.btn-ghost:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ----- Status pills -----
   Status pills carry a semantic color from the tokens below. For a neutral /
   pending / default / "off" state use --color-cold-bg + --color-cold-text (the
   cool grey `.pill-cold`/`.pill-neutral` pair). NEVER build a status pill from
   the muted/parchment pair (--color-bg-tint / --color-cairn-parchment +
   --color-text-muted / --color-cairn-clay) — at pill size that reads as an ugly
   brown on parchment (retired platform-wide 2026-07-22; the Front Door dropped
   its .fd-pill status pills entirely). Those tokens are for fills/hovers/help
   text, not status chips. */
.pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: 20px;
}
.pill-needs-you { background: var(--color-needs-you-bg); color: var(--color-needs-you-text); }
.pill-confirmed { background: var(--color-confirmed-bg); color: var(--color-confirmed-text); }
.pill-reached   { background: var(--color-reached-bg);   color: var(--color-reached-text); }
.pill-cold      { background: var(--color-cold-bg);      color: var(--color-cold-text); }
.pill-new       { background: var(--color-new-bg);       color: var(--color-new-text); }
.pill-attention { background: var(--color-attention-bg); color: var(--color-attention-text); }
.pill-neutral   { background: var(--color-cold-bg);      color: var(--color-cold-text); }

/* Fine print — small muted disclosure/help text (fees, SMS terms, "not sent
   yet" notes). Replaces the repeated inline `font-size:13px; color:muted` pair.
   Element-specific margins stay inline. */
.fine-print { font-size: 13px; color: var(--text-muted); }
/* An inline text link inside prose renders ~18px tall, under the 24px tap
   floor. Use this on links a volunteer is actually meant to follow (not every
   passing mention) to lift the hit area without disturbing the line. */
.link-tap { display: inline-block; padding: 4px 0; }

/* ----- Section labels ----- */
.section-label {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
}

/* ----- Dividers ----- */
.divider {
  height: 0.5px;
  background: var(--color-border);
  border: none;
}

/* ============================================================
   Toggle switch — the MemberCairn design standard for binary
   on/off settings. Built around a real <input type="checkbox">
   so it submits and validates like a normal form control.

   Usage:
     <label class="toggle">
       <input type="checkbox" name="x" value="1">
       <span class="toggle-track"><span class="toggle-thumb"></span></span>
       <span class="toggle-text">
         <span class="toggle-label">Title</span>
         <span class="toggle-help">Optional helper text</span>
       </span>
     </label>

   The minimum form is just .toggle > input + .toggle-track + label
   text — every other slot is optional.
   ============================================================ */
.toggle {
  display: inline-grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  font-weight: 400;
  font-size: 14px;
  color: var(--color-text-primary);
  margin: 8px 0;
  line-height: 1.45;
  -webkit-tap-highlight-color: transparent;
}
/* Hide the real checkbox visually but keep it focusable + form-submittable. */
.toggle > input[type="checkbox"] {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.toggle-track {
  position: relative;
  display: inline-block;
  width: 38px;
  height: 22px;
  flex: 0 0 auto;
  background: var(--color-bg-tint);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  transition: background-color 0.18s ease, border-color 0.18s ease;
}
.toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: var(--color-bg-primary);
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(44, 42, 34, 0.16),
              0 1px 1px rgba(44, 42, 34, 0.10);
  transition: transform 0.18s ease, background-color 0.18s ease;
}
.toggle > input:checked + .toggle-track {
  background: var(--color-accent);
  border-color: var(--color-accent);
}
.toggle > input:checked + .toggle-track .toggle-thumb {
  transform: translateX(16px);
  background: var(--color-cairn-parchment);
}
.toggle > input:focus-visible + .toggle-track {
  outline: none;
  box-shadow: 0 0 0 3px rgba(31, 75, 59, 0.22);
}
.toggle > input:disabled + .toggle-track {
  opacity: 0.55;
  cursor: not-allowed;
}
.toggle:has(> input:disabled) { cursor: not-allowed; color: var(--color-text-muted); }

.toggle-text { min-width: 0; display: block; }
.toggle-label {
  display: block;
  font-weight: 500;
  color: var(--color-text-primary);
}
.toggle-help {
  display: block;
  color: var(--color-text-secondary);
  font-size: 13px;
  margin-top: 2px;
}

/* Danger variant — for destructive toggles like "Pause agent" so they
   don't visually claim the same affordance as a benign setting. */
.toggle.danger > input:checked + .toggle-track {
  background: var(--color-needs-you-text);
  border-color: var(--color-needs-you-text);
}

/* Compact variant — inline with body text, no extra vertical margin. */
.toggle.compact { margin: 0; gap: 8px; font-size: 13px; }
.toggle.compact .toggle-track { width: 32px; height: 18px; }
.toggle.compact .toggle-thumb { width: 12px; height: 12px; }
.toggle.compact > input:checked + .toggle-track .toggle-thumb {
  transform: translateX(14px);
}

/* A grouped block of toggles inside a card or settings section. */
.toggle-stack {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.toggle-stack .toggle { margin: 0; }

/* ============================================================
   Toolbar — page actions row that sits above content
   (e.g. "+ Add lead", filter pills, search). Used to replace
   ad-hoc inline flex containers across templates.
   ============================================================ */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 18px;
}
.toolbar > .toolbar-spacer { flex: 1 1 auto; }
.toolbar .toolbar-group {
  display: inline-flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
}

/* ============================================================
   Section header — used inside cards or below the page hero
   to introduce a block without the heavyweight h2 gold-bar.
   ============================================================ */
.section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 8px 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--color-border);
}
.section-head .section-title {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.05px;
  color: var(--color-text-primary);
  margin: 0;
  display: block;
}
.section-head .section-title::before {
  content: none;
  display: none;
}
.section-head .section-count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.section-head .section-actions { margin-left: auto; display: inline-flex; gap: 8px; }

/* ============================================================
   Help tooltips — two patterns:

     1. <span class="help-tip" data-tip="…" tabindex="0">i</span>
        Tiny "i" glyph that opens a parchment-style tooltip on
        hover/focus. Use when the surrounding element doesn't
        already invite hovering.

     2. <span data-tip="…">…</span>  (or any element)
        Adds a tooltip when the element itself is hovered/focused.
        Use on status badges, stat tiles, chips — surfaces that
        already look interactive.

   Both render the tooltip via the same ::before/::after pair on
   the element with [data-tip]. Pure CSS — no JS — so keyboard
   focus opens the tooltip too. Falls back to the browser-native
   `title=""` attribute on touch devices without :hover.
   ============================================================ */
.help-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-cairn-mid);
  color: var(--color-cairn-dark);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  cursor: help;
  user-select: none;
  vertical-align: middle;
  margin: 0 2px;
  text-decoration: none;
  outline: none;
  transition: background 0.12s, transform 0.08s;
}
.help-tip:hover, .help-tip:focus-visible {
  background: var(--color-accent);
  color: var(--color-cairn-parchment);
}
.help-tip:focus-visible {
  box-shadow: 0 0 0 2px var(--color-cairn-parchment), 0 0 0 4px var(--color-accent);
}
.help-tip::before { content: "?"; }

[data-tip] { position: relative; }
/* When the host is hovered/focused, lift its entire stacking context so
   the tooltip can paint above neighboring elements that have their own
   stacking contexts (e.g. siblings with opacity/transform/filter). The
   pseudo's own z-index is bounded by its host's context, so the lift has
   to happen on the host itself. */
[data-tip]:hover,
[data-tip]:focus-visible,
[data-tip]:focus-within { z-index: 100; }
/* Tooltip pseudos can't escape a parent's overflow:hidden. Several admin
   containers (.trailhead-hero, .action-panel, .card flourishes) clip
   themselves to keep decorative ::before/::after backgrounds inside the
   card. When a tooltip inside is active, temporarily lift the clip so
   the bubble can paint outside the container. Decorations may briefly
   spill during the hover, which is acceptable for the interaction
   window. Scoped to descendants (not html/body) so global scroll
   behavior is unaffected. */
*:not(html):not(body):has(:where(
  [data-tip]:hover,
  [data-tip]:focus-visible,
  [data-tip]:focus-within
)) {
  overflow: visible !important;
}
[data-tip]::after,
[data-tip]::before {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s, transform 0.12s;
  z-index: 50;
}
[data-tip]::after {
  content: attr(data-tip);
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translate(-50%, 4px);
  background: var(--color-cairn-dark);
  color: var(--color-cairn-parchment);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  padding: 7px 11px;
  border-radius: var(--radius-sm);
  white-space: normal;
  width: max-content;
  max-width: 260px;
  text-align: left;
  box-shadow: 0 4px 16px rgba(44, 42, 34, 0.22);
}
[data-tip]::before {
  /* Arrow — a small downward-pointing triangle below the bubble. */
  content: "";
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translate(-50%, 4px);
  border-width: 6px 5px 0 5px;
  border-style: solid;
  border-color: var(--color-cairn-dark) transparent transparent transparent;
  width: 0;
  height: 0;
  padding: 0;
  background: transparent;
}
[data-tip]:hover::after,
[data-tip]:hover::before,
[data-tip]:focus-visible::after,
[data-tip]:focus-visible::before,
[data-tip]:focus-within::after,
[data-tip]:focus-within::before {
  opacity: 1;
  transform: translate(-50%, 0);
}
/* Place the tooltip BELOW the element when there's not enough room
   above. Opt in via data-tip-position="bottom". */
[data-tip][data-tip-position="bottom"]::after {
  bottom: auto;
  top: calc(100% + 10px);
  transform: translate(-50%, -4px);
}
[data-tip][data-tip-position="bottom"]::before {
  bottom: auto;
  top: calc(100% + 4px);
  border-width: 0 5px 6px 5px;
  border-color: transparent transparent var(--color-cairn-dark) transparent;
  transform: translate(-50%, -4px);
}
[data-tip][data-tip-position="bottom"]:hover::after,
[data-tip][data-tip-position="bottom"]:hover::before,
[data-tip][data-tip-position="bottom"]:focus-visible::after,
[data-tip][data-tip-position="bottom"]:focus-visible::before {
  transform: translate(-50%, 0);
}
/* Align left edge of the bubble with the element's left edge —
   used when the trigger sits near a viewport corner. */
[data-tip][data-tip-align="start"]::after {
  left: 0;
  transform: translate(0, 4px);
}
[data-tip][data-tip-align="start"]::before {
  left: 14px;
}
[data-tip][data-tip-align="start"]:hover::after,
[data-tip][data-tip-align="start"]:focus-visible::after {
  transform: translate(0, 0);
}
@media (max-width: 480px) {
  [data-tip]::after { max-width: 220px; font-size: 11px; padding: 6px 9px; }
}
/* Disable the styled tooltip when the user opts in to coarse-pointer
   (touch-only) devices — the browser's native title="" attribute then
   handles long-press. Pages that want both should use `data-tip`
   AND `title` (we encourage this). */
@media (hover: none) {
  [data-tip]::after,
  [data-tip]::before { display: none; }
}

/* ============================================================
   Retention nudge cards (_nudge_card.html). Reused on the admin
   home block, /admin/retention, and as an engagement badge on the
   roster member-edit page. Tokens only — no new color system.
   ============================================================ */
.nudge-list { display: flex; flex-direction: column; gap: 12px; }

.nudge-card {
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 1px 2px rgba(44, 42, 34, 0.04);
  padding: 14px 16px;
}
.nudge-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.nudge-card .family-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  color: var(--color-accent);
}
.nudge-adults { color: var(--color-text-secondary); font-size: 13px; margin-top: 2px; }

.nudge-members { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.member-line { font-size: 14px; }
.member-line.muted { opacity: 0.6; }
/* Standalone .muted used inside nudge cards (the only scoped .muted lives in _base). */
.nudge-card .muted, .member-engagement .muted { color: var(--color-text-muted); }

/* Engagement state pill. Severity escalates silent > lapsing > at_risk. */
.state-chip {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  text-transform: capitalize;
  background: var(--color-cold-bg);
  color: var(--color-cold-text);
  border: 1px solid transparent;
}
.s-silent   { background: var(--color-needs-you-bg); color: var(--color-needs-you-text); }
.s-lapsing  { background: var(--color-cold-bg); color: var(--color-accent); border-color: var(--color-cairn-mid); }
.s-at_risk  { background: #FBF3D6; color: #8A6D1F; }
.s-engaged  { background: var(--color-confirmed-bg); color: var(--color-confirmed-text); }
.s-unknown  { background: var(--color-cold-bg); color: var(--color-cold-text); }

.reason-chip {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  background: var(--color-cold-bg);
  color: var(--color-cold-text);
}
.reason-chip.urgent { background: #FBF3D6; color: #8A6D1F; }

.nudge-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.nudge-act {
  padding: 6px 11px;
  font-size: 13px;
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.nudge-act:hover { background: var(--color-bg-tint); border-color: var(--color-cairn-mid); }

/* The expand panel respects its [hidden] attribute — don't force display. */
.nudge-expand:not([hidden]) {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.nudge-mobile-actions { display: flex; gap: 8px; }
.nudge-desktop-banner {
  font-size: 13px;
  color: var(--color-text-secondary);
  background: var(--color-bg-tint);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
}
.sms-link, .call-link {
  flex: 1;
  text-align: center;
  text-decoration: none;
  padding: 8px 11px;
  font-size: 13px;
  background: var(--color-accent);
  color: #fff;
  border-radius: var(--radius-sm);
}
.nudge-draft .call-points { margin: 4px 0 0; padding-left: 18px; font-size: 13px; color: var(--color-text-secondary); }

.member-engagement { margin: 4px 0 0; }

/* ============================================================
   Page-settings band — the prominent "configure this page" region
   that distinguishes feature-page SETTINGS (Recruiting season, Interest
   form, dens, calendar, onboarding on/off) from the muted gray DATA
   disclosures (Test prospects, Inactive members) elsewhere on the page.
   Pattern B, chosen 2026-06-10. Used via the admin/_page_settings.html
   macro: {% call ps.band("sub") %} <details class="ps-item">…</details> {% endcall %}
   ============================================================ */
.page-settings {
  margin-top: var(--space-8);
  border: 1px solid var(--color-accent);
  border-top: 4px solid var(--color-accent);
  border-radius: var(--radius-lg);
  background: linear-gradient(180deg, rgba(31, 75, 59,0.06), rgba(31, 75, 59,0) 64%);
  padding: var(--space-5) var(--space-5) var(--space-3);
}
.page-settings__head { display: flex; align-items: center; gap: 10px; }
.page-settings__icon {
  width: 30px; height: 30px; border-radius: var(--radius-md); flex: none;
  background: var(--color-accent); color: #fff; display: grid; place-items: center;
}
.page-settings__icon svg { width: 17px; height: 17px; }
.page-settings__title {
  margin: 0; font-family: var(--font-mono, monospace); font-size: 12px;
  letter-spacing: 1.2px; text-transform: uppercase; font-weight: 700;
  color: var(--color-cairn-dark);
}
.page-settings__sub { margin: 5px 0 16px; color: var(--color-text-secondary); font-size: var(--text-sm); }

/* A settings entry inside the band — a brand-accented disclosure row, distinctly
   NOT the gray data-disclosure bar. */
.page-settings details.ps-item {
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-bg-primary); margin-bottom: 10px; overflow: hidden;
}
.page-settings details.ps-item:last-child { margin-bottom: 6px; }
.page-settings details.ps-item > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: baseline; gap: 9px; padding: 13px 15px;
  font-weight: 600; color: var(--color-text-primary);
}
.page-settings details.ps-item > summary::-webkit-details-marker { display: none; }
/* Inset focus ring — .ps-item has overflow:hidden, which would clip an outset
   ring, so use an inset shadow that reads on the white summary. */
.page-settings details.ps-item > summary:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--color-accent);
}
.page-settings details.ps-item > summary::before {
  content: "▸"; color: var(--color-accent); font-size: 11px;
  transition: transform 0.12s; align-self: center;
}
.page-settings details.ps-item[open] > summary::before { transform: rotate(90deg); }
.page-settings details.ps-item[open] > summary { border-bottom: 1px solid var(--color-border); }
.ps-item__hint { font-weight: 400; color: var(--color-text-secondary); font-size: var(--text-sm); }
.ps-item__inner { padding: 16px; }
.ps-item__inner > .card:first-child,
.ps-item__inner > form:first-child { margin-top: 0; }

/* === Field-help text =========================================================
   Muted helper / confirmation note below a form field or field group.
   Used anywhere a secondary note should appear without the mono+uppercase
   weight of .meta (which is a code/data primitive, not prose). */
.field-help {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: 1.5;
  margin-top: var(--space-1, 4px);
  margin-bottom: 0;
}

/* === Auto-save status (shared) ===============================================
   Per-field "Saving… / ✓ Saved / ✕ error" note for [data-autosave] controls
   (agent/static/js/autosave.js). The Profile editor carries a scoped copy in
   its macro; this shared copy serves the Settings hub + page-settings bands. */
.autosave-status { font-size: 12px; min-width: 18px; line-height: 1.2; }
.autosave-status.is-saving { color: var(--color-text-muted); }
.autosave-status.is-ok { color: var(--color-confirmed-text); }
.autosave-status.is-err { color: var(--color-needs-you-text); }
.autosave-status.is-ok::before { content: "\2713 "; }
.autosave-status.is-err::before { content: "\2715 "; }

/* Page-level autosave reassurance ("All changes saved"), used beside the
   page-settings band sub-line and at the top of the Settings Sending tab. */
.autosave-page-status { font-size: 12.5px; }
.autosave-page-status.is-saving { color: var(--color-text-muted); }
.autosave-page-status.is-ok { color: var(--color-confirmed-text); }
.autosave-page-status.is-ok::before { content: "\2713  "; }
.autosave-page-status.is-err { color: var(--color-needs-you-text); }
.autosave-page-status.is-err::before { content: "\2715  "; }

/* === Messages hub (.msg-hub) ===============================================
   The Inbox / Compose / Announce view-switch shared by the org-inbox pages and
   the composer (agent/templates_html/admin/_messages_tabs.html). Drawn as three
   self-describing cards (icon + name + one-line purpose) so the messages home
   reads at a glance; the active face is highlighted. The card per row also lets
   each outgoing surface keep the same hub header. */
.msg-hub { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 4px 0 18px; }
.msg-hub-card {
  flex: 1 1 200px; min-width: 0; display: flex; gap: 11px; align-items: flex-start;
  text-decoration: none; padding: 12px 14px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--card);
  transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}
.msg-hub-card:hover { border-color: var(--brand); box-shadow: var(--shadow-sm, 0 2px 6px rgba(0,0,0,.06)); }
@media (prefers-reduced-motion: reduce) { .msg-hub-card { transition: none; } }
.msg-hub-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.msg-hub-card.is-active { background: var(--brand-deep); border-color: var(--brand-deep); }
.msg-hub-ico {
  width: 32px; height: 32px; border-radius: var(--radius-sm); flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-soft); color: var(--brand-deep);
}
.msg-hub-ico svg { width: 18px; height: 18px; }
.msg-hub-card.is-active .msg-hub-ico { background: rgba(245, 237, 216, 0.18); color: var(--color-cairn-parchment); }
.msg-hub-text { min-width: 0; }
.msg-hub-name {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--brand-deep);
}
.msg-hub-card.is-active .msg-hub-name { color: var(--color-cairn-parchment); }
.msg-hub-desc { display: block; font-size: 12px; color: var(--text-muted); margin-top: 2px; line-height: 1.3; }
.msg-hub-card.is-active .msg-hub-desc { color: var(--color-cairn-parchment); opacity: 0.78; }
.msg-hub-badge {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  background: var(--color-needs-you-text); color: #fff;
  border-radius: 999px; padding: 1px 7px; min-width: 18px; text-align: center;
  font-variant-numeric: slashed-zero tabular-nums;
}
.msg-hub-card.is-active .msg-hub-badge { background: rgba(245, 237, 216, 0.22); color: var(--color-cairn-parchment); }
/* Locked (paid-plan) hub card — the free-tier "Announce" upsell. Reads as
   quietly gated (muted icon, dashed border) but stays a real, clickable link to
   the plan ladder. The "Paid plans" tag carries the meaning in text, not color
   alone. */
.msg-hub-card--locked { border-style: dashed; }
.msg-hub-card--locked .msg-hub-ico {
  background: var(--color-bg-tint); color: var(--text-muted);
}
.msg-hub-card--locked:hover .msg-hub-ico { color: var(--brand-deep); }
.msg-hub-locktag {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--color-cold-bg); color: var(--color-cold-text);
  border-radius: 999px; padding: 1px 7px;
}

/* On a phone the three cards stack. Drop the descriptions for the INACTIVE cards
   so the hub stays compact, but keep the active card's one-line purpose so the
   surface you're on still explains itself. */
@media (max-width: 560px) {
  .msg-hub-card { flex-basis: 100%; padding: 10px 13px; align-items: center; }
  .msg-hub-card:not(.is-active) .msg-hub-desc { display: none; }
}

/* AI-provenance badge — shared across every surface that shows AI-drafted copy
   (agent/templates_html/admin/_provenance.html). Variants reuse the looks the
   old per-surface badges had so nothing regresses on consolidation. */
.provenance-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 1px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 700; white-space: nowrap;
  font-style: normal;
  font-family: var(--font-sans, sans-serif);
}
.provenance-badge:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.provenance-badge[hidden] { display: none; }
/* autonomous / insight — the old .ai-flag "✦ Assistant" look. insight is a
   read-only AI summary written for the leader (nothing was sent), sharing the
   autonomous badge's informational styling. */
.provenance-badge--autonomous,
.provenance-badge--insight { background: var(--brand-soft); color: var(--brand); }
/* draft / edited — the old .msg-ai-flag parchment pill; edited is quieter */
.provenance-badge--draft {
  background: var(--color-cairn-parchment, #F5EDD8);
  border: 1px solid var(--color-cairn-mid, #C4A882);
  color: var(--brand-deep);
}
.provenance-badge--edited {
  background: transparent;
  border: 1px solid var(--color-cairn-mid, #C4A882);
  color: var(--text-muted);
}

/* ===== Setup "what this is powering" rail =====
   Shared trail/rail component used by the pre-activation recruiting interview
   (agent/templates_html/admin/_setup_powering_rail.html) and the onboarding
   preview on the staged setup dashboard
   (admin/_setup_onboarding_rail.html). Layout/positioning of the rail's
   container (the sticky two-column shell on the interview, the centered card
   on the dashboard) stays in each page; only the rail's internal look lives
   here so both render identically. Class names are setup-rail* / setup-trail*
   so nothing bleeds onto other admin surfaces. */
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.setup-rail { padding-left: var(--space-8); border-left: 1px solid var(--color-border); animation: rise 0.5s 0.22s both; }
/* The guard travels with the keyframe: the interview's reduced-motion rule is
   scoped to its own inline <style>, so the dashboard needs its own here. */
@media (prefers-reduced-motion: reduce) { .setup-rail { animation: none; } }
.setup-rail-eyebrow { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-accent); }
.setup-rail-title { font-family: var(--font-display); font-weight: 700; font-size: var(--text-lg); color: var(--color-text-primary); margin: var(--space-1) 0 2px; }
.setup-rail-lead { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: 1.4; margin: 0 0 var(--space-5); }
.setup-trail { position: relative; display: flex; flex-direction: column; gap: var(--space-4); }
.setup-trail::before { content: ""; position: absolute; left: 21px; top: 14px; bottom: 14px; width: 2px; background: repeating-linear-gradient(var(--color-cairn-mid) 0 4px, transparent 4px 10px); }
.setup-trail-node { display: flex; align-items: center; gap: var(--space-3); position: relative; }
.setup-trail-tile { width: 44px; height: 44px; flex: 0 0 44px; border-radius: var(--radius-md); background: var(--color-bg-primary); border: 1px solid var(--color-border); display: grid; place-items: center; box-shadow: var(--shadow-card-sm); z-index: 1; }
.setup-trail-tile-fin { background: var(--color-confirmed-bg); border-color: var(--color-confirmed-bg); }
.setup-trail-tile svg { width: 22px; height: 22px; fill: none; stroke: var(--color-accent); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.setup-trail-cap { font-size: var(--text-sm); font-weight: 600; color: var(--color-text-primary); line-height: 1.2; display: block; }
.setup-trail-sub { font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-text-muted); margin-top: 2px; display: block; }
/* website node mini front-door mock */
.setup-rail-wmock { width: 44px; flex: 0 0 44px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); overflow: hidden; background: var(--color-bg-primary); box-shadow: var(--shadow-card-sm); z-index: 1; }
.setup-rail-wmock-bar { display: flex; gap: 3px; padding: 4px 5px; background: var(--color-bg-tint); border-bottom: 1px solid var(--color-border); }
.setup-rail-wmock-bar i { width: 4px; height: 4px; border-radius: 50%; background: var(--color-cairn-mid); display: block; }
.setup-rail-wmock-hero { display: block; background: var(--color-accent); text-align: center; padding: 7px 3px 8px; }
.setup-rail-wmock-mark { width: 14px; height: 14px; border-radius: 4px; background: rgba(255,255,255,.22); display: inline-flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 7px; overflow: hidden; }
.setup-rail-wmock-mark img { width: 100%; height: 100%; object-fit: contain; }
.setup-rail-wmock-t { display: block; color: #fff; font-weight: 700; font-size: 6.5px; margin-top: 2px; }
.setup-rail-foot { font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-text-muted); margin-top: var(--space-5); padding-top: var(--space-3); border-top: 1px dashed var(--color-cairn-mid); display: flex; align-items: center; gap: var(--space-2); }
.setup-rail-gleam { width: 7px; height: 7px; border-radius: 50%; background: var(--color-accent); box-shadow: 0 0 0 3px rgba(139,111,71,.18); }
/* Segment label within a multi-track rail (e.g. the onboarding rail's
   "New family · the full welcome" / "Continuing family · each year" dividers). */
.setup-rail-seg { font-family: var(--font-mono); font-size: 7.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-accent); font-weight: 600; margin-bottom: var(--space-2); }
.setup-rail-seg--gap { margin-top: var(--space-5); }
/* Small dashed note below the trail (examples are customizable). */
.setup-rail-note { font-size: var(--text-xs); color: var(--color-text-muted); font-style: italic; margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px dashed var(--color-cairn-mid); line-height: 1.4; }

/* ===== Shared AI-action component =====
   Trigger button (.ai-action__trigger) + sparkle glyph (.ai-spark) +
   inline assist panel (.ai-action__panel).  Used by the welcome step editor
   ("Revise with AI") and available to any future AI-assist surface.

   Design rules:
   - Trigger is OUTLINE (not filled); filled treatment is reserved for the
     page's real primary action.  Matches the established house pattern in
     _messaging_composer.html (.msg-ai-spark) and _event_form.html (.ev-ai-cta).
   - Sparkle color = var(--brand) = var(--color-accent) (warm cairn orange).
   - Panel background = var(--color-cairn-parchment); border = var(--color-cairn-mid).
   - Tokens only — no hardcoded hex.
*/

/* Sparkle glyph — shared across all AI-action surfaces */
.ai-spark {
  color: var(--brand);
  font-size: 13px;
  line-height: 1;
}

/* Trigger button — outline style, warm accent color */
.ai-action__trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  color: var(--color-accent);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: 8px 16px;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 120ms ease, box-shadow 120ms ease;
}
.ai-action__trigger:hover {
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}
.ai-action__trigger:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 28%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .ai-action__trigger { transition: none; }
}

/* Inline assist panel — parchment card, revealed on trigger click */
.ai-action__panel {
  background: var(--color-cairn-parchment);
  border: 1px solid var(--color-cairn-mid);
  border-radius: var(--radius-md);
  padding: 12px;
  margin-top: 8px;
}

/* Ghost card — dashed ✦ placeholder where withheld assistant work would be
   (ghost-mode upsell, pattern A). Ambient page furniture: quiet parchment
   tone, never a banner, never a modal. */
.ghost-card { display: flex; gap: 10px; align-items: flex-start;
  border: 1.5px dashed var(--color-cairn-mid); border-radius: var(--radius-md);
  background: var(--color-bg-secondary); padding: 12px 14px; margin: 14px 0; }
.ghost-card .ghost-spark { color: var(--brand); font-size: 15px;
  line-height: 1.4; flex: 0 0 auto; }
.ghost-card .ghost-body { min-width: 0; flex: 1; }
.ghost-card .ghost-headline { margin: 0; font-weight: 600; font-size: 14px; }
.ghost-card .ghost-sub { margin: 2px 0 0; font-size: 13px; color: var(--text-muted); }
.ghost-card .ghost-actions { margin-top: 8px; display: flex; flex-wrap: wrap;
  gap: 8px; align-items: center; }
.ghost-card .ghost-actions form { margin: 0; }
.ghost-card .ghost-upgrade-link { font-size: 13px; font-weight: 600;
  color: var(--brand-deep); text-decoration: none; min-height: 44px;
  display: inline-flex; align-items: center; }
.ghost-card .ghost-upgrade-link:hover { text-decoration: underline; }
/* Stale-lead ghost line inside a pipeline row (leads_list.html). */
.lead-stale-line { font-size: 12.5px; color: var(--text-muted); margin-top: 3px; }
.lead-stale-line .ghost-spark { color: var(--brand); }

/* Setup step rows — the numbered-circle checklist visual. Shared by the
   setup dashboard's first-value checklist and the front-door "Path to live"
   hero, so a step on either surface reads as the same kind of step. */
.fv-row { display: flex; align-items: center; gap: 13px; padding: 13px 0; border-top: 1px solid var(--color-border); }
.fv-row:first-child { border-top: 0; }
.fv-dot { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 11.5px; font-weight: 700; background: var(--color-bg-tint); color: var(--color-text-muted); border: 1px solid var(--color-border); }
.fv-row.is-done .fv-dot { background: var(--color-confirmed-bg); color: var(--color-confirmed-text); border-color: var(--color-confirmed-bg); }
.fv-row.is-done { color: var(--color-text-secondary); }
/* Current step: an outline ring plus weight, never color alone (rubric). */
.fv-row.is-now .fv-dot { background: var(--color-accent); color: #fff; border-color: var(--color-accent); outline: 2px solid var(--color-accent); outline-offset: 2px; }
.fv-row.is-todo { opacity: .55; }
.fv-row-body { flex: 1 1 auto; min-width: 0; }
.fv-row-label { font-weight: 600; font-size: 14px; color: var(--color-text-primary); display: block; }
.fv-row.is-now .fv-row-label { font-family: var(--font-display); font-size: 17px; }
.fv-row-sub { font-size: 13px; color: var(--color-text-secondary); display: block; margin-top: 2px; line-height: 1.4; }
/* Layout only: the button's own look comes from .btn-primary in components.css. */
.fv-row-act { flex: 0 0 auto; white-space: nowrap; min-height: 44px; display: inline-flex; align-items: center; }
@media (max-width: 600px) {
  .fv-row { flex-wrap: wrap; }
  .fv-row-act { width: 100%; justify-content: center; margin-top: 8px; }
}

/* ---- Web-address teaser (shared: front-door hub + setup dashboard) ---------
   The collapsed "Your own web address" disclosure. These lived inline in
   website.html until the setup dashboard needed the same teaser; a second copy
   of the copy is exactly how the two surfaces drifted apart in the first place,
   so the primitive lives here and both pages import the pitch macro from
   admin/_web_address_card.html. */
.cd-lede { margin: 0 0 4px; max-width: 60ch; }
.cd-note { margin: 8px 0 0; font-size: 0.88em; max-width: 60ch; }
.cd-upsell > summary { cursor: pointer; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; list-style: none; padding: 2px 0; }
.cd-upsell > summary::-webkit-details-marker { display: none; }
.cd-upsell > summary:hover .cd-upsell-title { color: var(--color-accent); }
.cd-upsell > summary:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; border-radius: 4px; }
.cd-upsell > summary::before { content: "\25B8"; color: var(--text-muted); font-size: 0.85em; line-height: 1; transition: transform 0.15s ease; }
.cd-upsell[open] > summary::before { transform: rotate(90deg); }
.cd-upsell-title { font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; color: var(--color-text-primary); }
.cd-plan-pill { display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: 0.02em; padding: 3px 10px; border-radius: 999px; background: var(--color-accent-soft); color: var(--color-accent-strong); }
.cd-upsell-body { margin-top: 12px; }
@media (prefers-reduced-motion: reduce) {
  .cd-upsell > summary::before { transition: none; }
}
