/* =========================================================================
   COMPONENTS — reusable, token-driven UI primitives
   ========================================================================= */

/* ---------- Button ---------------------------------------------------- */
/* ---------- Surface button (toolbar: Filter, Sort, Customize Widget…) */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  height: var(--btn-height);
  padding: 0 var(--btn-pad-x);
  border-radius: var(--btn-radius);
  font-size: var(--text-md);
  font-weight: var(--fw-medium);
  color: var(--btn-fg);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--btn-shadow);
  white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), color var(--dur) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.btn svg { width: var(--btn-icon-size); height: var(--btn-icon-size); color: var(--btn-fg); transition: color var(--dur) var(--ease); }
/* hover only on real pointers — on touch :hover latches after a tap (stuck highlight) */
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--gray-50); border-color: var(--border-strong); }
}
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }
@media (hover: hover) and (pointer: fine) {
  .btn:disabled:hover { background: var(--surface); border-color: var(--border); }
}

/* Ghost / low-emphasis — flat, no shadow */
.btn-ghost { background: transparent; border-color: transparent; box-shadow: none; }
@media (hover: hover) and (pointer: fine) {
  .btn-ghost:hover { background: var(--gray-100); border-color: transparent; }
}

/* Primary CTA — the ink pill (tokens: --btn-primary-*; NOT the accent) */
.btn-primary {
  background: var(--btn-primary-bg);
  border-color: var(--btn-primary-border);
  color: var(--btn-primary-fg);
  box-shadow: var(--btn-primary-shadow);
}
.btn-primary svg { color: var(--btn-primary-fg); }
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { background: var(--btn-primary-hover); border-color: var(--btn-primary-border); }
}
.btn-primary:focus-visible { box-shadow: var(--btn-primary-shadow), 0 0 0 3px var(--primary-200); }

/* Hint tip — a small "?" after a label; its data-hint shows under it on hover / focus */
.hint-tip { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; margin-left: var(--space-1-5); border-radius: var(--radius-full); border: 1px solid var(--border-strong); background: transparent; color: var(--text-soft); font: inherit; font-size: 10px; font-weight: var(--fw-semibold); line-height: 1; vertical-align: 1px; cursor: default; transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.hint-tip::after { content: attr(data-hint); position: absolute; top: calc(100% + 6px); left: 0; width: max-content; max-width: 240px; padding: var(--space-1-5) var(--space-2-5); border-radius: var(--radius-sm); background: var(--text-strong); color: var(--surface); font-size: var(--text-xs); font-weight: var(--fw-regular); line-height: 1.4; text-align: left; white-space: normal; opacity: 0; pointer-events: none; transition: opacity var(--dur-fast) var(--ease); z-index: var(--z-popover); box-shadow: var(--shadow-md); }
.hint-tip:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.hint-tip:focus-visible::after { opacity: 1; }
@media (hover: hover) and (pointer: fine) {
  .hint-tip:hover { color: var(--text); border-color: var(--text-soft); }
  .hint-tip:hover::after { opacity: 1; }
}

/* Meta-blue call to action ("Connect Meta") — the one button that wears a
   brand colour: the dashboard's Meta bar, the connect popover and the
   Integrations card all use it. Doubled selectors so .btn:hover can't wash it out. */
.btn-meta, .btn-meta:hover, .btn-meta:focus, .btn-meta:active { border-color: var(--brand-meta); background: var(--brand-meta); color: var(--on-primary-static); font-weight: var(--fw-semibold); box-shadow: 0 1px 2px color-mix(in srgb, var(--brand-meta) 35%, transparent); transition: background var(--dur) var(--ease), transform var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) { .btn-meta:hover { background: var(--brand-meta-deep); border-color: var(--brand-meta-deep); } }
.btn-meta:active { transform: translateY(1px); }
.btn-meta:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-meta) 30%, transparent); }
.btn-meta svg { color: var(--on-primary-static); }
.btn-meta img { width: 16px; height: 16px; filter: brightness(0) invert(1); }

/* Solid destructive button — red fill, white text */
.btn-danger {
  background: var(--danger-600);
  border-color: var(--danger-600);
  color: var(--text-invert);
  box-shadow: 0 1px 2px rgba(180, 35, 40, 0.28), inset 0 1px 0 rgba(255,255,255,0.14);
}
.btn-danger svg { color: rgba(255,255,255,0.92); }
@media (hover: hover) and (pointer: fine) {
  .btn-danger:hover { background: #d23b40; border-color: #d23b40; }
}
.btn-danger:focus-visible { box-shadow: 0 0 0 3px var(--danger-bg); }
.btn-danger:disabled, .btn-danger.is-loading { opacity: 0.6; cursor: default; }

/* Ghost destructive — text-capable; add .btn-icon for the square icon form */
.btn-ghost-danger { color: var(--danger-600); background: transparent; border-color: transparent; box-shadow: none; }
@media (hover: hover) and (pointer: fine) {
  .btn-ghost-danger:hover { background: var(--danger-bg); }
}

/* generic in-flight state for any .btn — spinner replaces the label */
.btn.is-loading { position: relative; color: transparent; pointer-events: none; }
.btn.is-loading svg { visibility: hidden; }
.btn.is-loading::after {
  content: ""; position: absolute; left: 50%; top: 50%; margin: -8px 0 0 -8px;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--border-strong); border-top-color: var(--primary-600);
  animation: spin 0.7s linear infinite;
}
.btn-danger.is-loading::after {
  border-color: rgba(255, 255, 255, 0.35); border-top-color: #fff;
}
/* the ink pill's spinner follows its own fg so the dark-theme white pill
   gets an ink spinner instead of white-on-white */
.btn-primary.is-loading::after {
  border-color: color-mix(in srgb, var(--btn-primary-fg) 35%, transparent);
  border-top-color: var(--btn-primary-fg);
}
/* the moment after: the action landed. The button turns the success tone and its tick pops in (pair with
   is-loading: loading → success → the view moves on). The label is whatever the caller sets ("Published"). */
.btn.is-success, .btn.is-success:hover, .btn.is-success:disabled { opacity: 1; border-color: transparent; background: var(--success-600); color: #fff; box-shadow: none; pointer-events: none; transition: background var(--dur) var(--ease-enter); }
.btn.is-success svg { animation: tick-pop 340ms var(--ease-bounce); }
@media (prefers-reduced-motion: reduce) { .btn.is-success svg { animation: none; } .btn.is-success { transition: none; } }

.btn-sm { height: 34px; padding: 0 var(--space-3); font-size: var(--text-sm); }
.btn-icon { width: var(--btn-height); height: var(--btn-height); padding: 0; }
.btn-icon.btn-sm { width: 34px; height: 34px; }
/* Responsive label swap: .btn-label-ext shows on desktop, .btn-label-sm is its
   compact mobile stand-in (flipped in responsive.css ≤640). */
.btn-label-sm { display: none; }

/* Split surface button: one shared shell shadow, short centred divider */
.btn-split {
  display: inline-flex; align-items: stretch;
  border-radius: var(--btn-radius);
  box-shadow: var(--btn-shadow);
}
.btn-split > .btn { box-shadow: none; }
.btn-split > .btn:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; border-right: none; }
.btn-split > .btn-caret {
  position: relative;
  border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none;
  padding: 0 var(--space-2); width: 32px;
}
.btn-split > .btn-caret::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 1px; height: var(--split-divider-h); background: var(--split-divider);
}
.btn-split > .btn-caret.btn-primary::before { background: color-mix(in srgb, var(--btn-primary-fg) 30%, transparent); }

/* (the old standalone .icon-btn — a near-duplicate of `.btn.btn-icon` that
   differed only in word order — is gone; icon-only buttons use `btn btn-icon`) */

/* ---------- App toast (shared/lib/toast.js — the app-wide ephemeral toast) */
.app-toast { position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 12px); z-index: var(--z-toast); padding: 10px 16px; border-radius: var(--radius-lg); background: var(--overlay-dark); color: #fff; border: 1px solid var(--border); font-size: var(--text-sm); font-weight: var(--fw-medium); box-shadow: var(--shadow-lg); opacity: 0; pointer-events: none; transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
.app-toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- Card-action button (inside cards: On Google Meet, View more) */
.btn-card {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 32px; padding: 0 12px;
  border-radius: var(--radius-md);
  font-size: var(--text-sm); font-weight: var(--fw-medium);
  color: var(--btn-card-fg);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--btn-shadow-card);
  white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn-card svg { width: 14px; height: 14px; color: var(--btn-card-fg); }
@media (hover: hover) and (pointer: fine) {
  .btn-card:hover { background: var(--gray-50); border-color: var(--border-strong); }
}

/* shared disabled state (no app button is disabled today; additive only) */
.btn:disabled, .btn-card:disabled, .kebab:disabled {
  opacity: 0.45; cursor: not-allowed; box-shadow: none; transform: none;
}
@media (hover: hover) and (pointer: fine) {
  .btn:disabled:hover, .btn-card:disabled:hover, .kebab:disabled:hover {
    background: var(--surface); border-color: var(--border);
  }
  .btn-primary:disabled:hover { background: var(--primary-600); border-color: var(--primary-600); }
  .btn-ghost:disabled:hover { background: transparent; }
}

/* ---------- Badge / pill --------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 8px;
  border-radius: var(--radius-xs);
  font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  line-height: 1; white-space: nowrap; letter-spacing: 0.01em;
}
.badge-priority-high   { color: var(--pri-high-fg); background: var(--pri-high-bg); }
.badge-priority-medium { color: var(--pri-medium-fg); background: var(--pri-medium-bg); }
.badge-priority-low    { color: var(--pri-low-fg); background: var(--pri-low-bg); }
.badge-cat-dashboard   { color: var(--primary-tint-fg); background: var(--primary-50); }
.badge-cat-landing     { color: var(--info-600); background: var(--info-bg); }
.badge-cat-mobile      { color: var(--cat-mobile-fg); background: var(--cat-mobile-bg); }
.badge-neutral         { color: var(--text-muted); background: var(--gray-100); }
.badge-success         { color: var(--metric-up-fg); background: var(--metric-up-bg); }
.badge-danger          { color: var(--danger-600); background: var(--metric-down-bg); }
.badge-warning         { color: var(--warning-700); background: var(--warning-bg); }
.badge-info            { color: var(--info-600); background: var(--info-bg); }
.badge-primary         { color: var(--primary-tint-fg); background: var(--primary-50); }
/* "In progress" — the DEFAULT client state, on ~2/3 of cards. The class was
   referenced by projectCard/trainerApp but DEFINED NOWHERE, so it rendered as
   bare text carrying .badge's 8px pad (a visible optical indent, no pill).
   Defining it loud would stamp a coloured chip on the dominant state and
   manufacture exactly the repetition the cards are already criticised for —
   so it is deliberately quiet: the pill treatment stays reserved for states
   that actually want attention (Overdue, Unassigned, Completed). */
.badge-cat-deals       { color: var(--text-soft); background: none; padding: 0; font-weight: var(--fw-medium); }
.badge svg { width: 13px; height: 13px; }

/* Publish-status tone pill — ONE recipe for the schedule/approval chips
   (admin Content Schedule .csched-chip, portal week grid .clsched-chip,
   post-detail .pdet-note-badge). JS adds .tone-pill + is-ok|is-warn|is-bad|
   is-idle; the per-view class keeps only sizing/placement. */
.tone-pill { display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px; border-radius: var(--radius-full); font-size: var(--text-2xs); font-weight: var(--fw-semibold); white-space: nowrap; }
.tone-pill.is-ok   { background: color-mix(in srgb, var(--success-600) 12%, var(--surface)); color: var(--success-700); }
.tone-pill.is-warn { background: color-mix(in srgb, var(--warning-600) 12%, var(--surface)); color: var(--warning-700); }
.tone-pill.is-bad  { background: color-mix(in srgb, var(--danger-600) 10%, var(--surface)); color: var(--danger-600); }
.tone-pill.is-idle { background: var(--surface-2); color: var(--text-muted); }

/* count chip used in sidebar / kanban headers */
.chip-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  font-size: var(--text-xs); font-weight: var(--fw-semibold); line-height: 1;
  color: var(--text-muted); background: var(--gray-100);
  border-radius: var(--radius-xs);
}

/* ---------- Stage indicator ------------------------------------------ */
.stage { display: inline-flex; align-items: center; gap: var(--space-2); font-weight: var(--fw-medium); color: var(--text); white-space: nowrap; }
.stage .dot { width: 7px; height: 7px; border-radius: 50%; }
.stage[data-stage="Leads"]     .dot { background: var(--stage-leads); }
.stage[data-stage="Discovery"] .dot { background: var(--stage-discovery); }
.stage[data-stage="Demo"]      .dot { background: var(--stage-demo); }
.stage[data-stage="Won"]       .dot { background: var(--stage-won); }
.stage[data-stage="Lead"]      .dot { background: var(--stage-leads); }
.stage[data-stage="Follow Up"] .dot { background: var(--stage-discovery); }
.stage[data-stage="Consult"]   .dot { background: var(--stage-demo); }
.stage[data-stage="Closed"]    .dot { background: var(--stage-won); }
.stage[data-stage="Dead"]      .dot { background: var(--danger-600); }

/* ---------- Avatar / logo monogram ----------------------------------- */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  font-size: var(--text-xs); font-weight: var(--fw-bold); color: #fff;
  flex-shrink: 0; overflow: hidden; letter-spacing: 0;
}
.avatar-sm { width: 26px; height: 26px; font-size: var(--text-3xs); }
/* A client's logo as the account avatar (the portal chip): the whole mark on a well,
   marked by shared/lib/logoTone like .proj-logo--photo — "opaque" fills as before,
   "light" (a white mark) gets the dark well. */
.avatar--logo { position: relative; background: var(--logo-well); box-shadow: inset 0 0 0 1px var(--border-faint); }
.avatar--logo::after { content: ""; position: absolute; inset: 14%; background: var(--logo) center / contain no-repeat; }
.avatar--logo[data-tone="light"] { background: var(--logo-well-dark); box-shadow: none; }
.avatar--logo[data-tone="opaque"] { background: none; box-shadow: none; }
.avatar--logo[data-tone="opaque"]::after { inset: 0; background-size: cover; }
.avatar--logo[data-tone="opaque-wide"] { background: var(--logo-well-auto, var(--logo-well)); box-shadow: none; }
.avatar--logo[data-tone="opaque-wide"]::after { inset: 8%; }

/* ---- skeleton loading blocks (reusable across views) ----
   A grey placeholder with a sweeping shimmer. Size it with inline width/height;
   .skel-circle rounds it fully. Pairs with per-view skeleton markup that mirrors
   the real layout so content swaps in without a jump. */
.skel { position: relative; overflow: hidden; display: inline-block; vertical-align: middle; background: var(--gray-200); border-radius: 4px; }
.skel::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  animation: skel-shimmer 1.5s ease-in-out infinite;
}
html[data-theme="dark"] .skel::after { background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.06), transparent); }
.skel-circle { border-radius: 50%; }
.skel--pill { border-radius: var(--radius-full); }
.skel--check { width: 18px; height: 18px; border-radius: 5px; }
@keyframes skel-shimmer { 100% { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .skel::after { animation: none; } }

/* company square logo */
.logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: var(--fw-bold); color: #fff;
  flex-shrink: 0;
}
.logo-round { border-radius: 50%; }

/* ---------- Input / select / textarea -------------------------------- */
.input {
  width: 100%; height: 40px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text);
  font-size: var(--text-md); font-family: inherit;
  /* inputs sit a tier BELOW buttons: the faintest 1px drop, so a field reads
     as a well to type into rather than a raised control (Attio reference) */
  box-shadow: var(--shadow-xs);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.input::placeholder { color: var(--text-soft); }
.input:focus { outline: none; border-color: var(--primary-400); box-shadow: var(--ring-primary); }
select.input {
  cursor: pointer; appearance: none; -webkit-appearance: none; padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23848b9b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
}
textarea.input { height: auto; min-height: 76px; padding: 10px 12px; resize: vertical; line-height: var(--leading-snug); }
.input-sm { height: 34px; font-size: var(--text-sm); }
.input:disabled, select.input:disabled, textarea.input:disabled {
  opacity: 0.55; background: var(--gray-50); cursor: not-allowed; box-shadow: none;
}
.input.is-error { border-color: var(--danger-600); box-shadow: 0 0 0 2px var(--danger-bg); }
/* WebKit autofill paints its own pale-yellow fill — repaint it with the
   theme's surface/text so dark mode stays dark (Login especially) */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  box-shadow: 0 0 0 1000px var(--surface) inset;
  caret-color: var(--text);
  transition: background-color 9999s ease-out;
}

/* Checkbox — the NATIVE input restyled (appearance:none), not a span+JS
   stand-in, so label clicks, Space/Tab, :checked and form semantics all keep
   working for free. 16px box with a 4px radius (--radius-xs at 6px reads too
   round at this size) and the lucide check baked in as a mask-free data URI,
   matching the select.input chevron convention above. */
.checkbox {
  appearance: none; -webkit-appearance: none;
  flex-shrink: 0; width: 16px; height: 16px; margin: 0;
  border: 1px solid var(--border); border-radius: 4px;
  background: var(--surface); cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}
.checkbox:hover:not(:disabled):not(:checked) { border-color: var(--border-strong); }
.checkbox:active:not(:disabled) { transform: scale(0.9); }
.checkbox:checked {
  background-color: var(--primary-600); border-color: var(--primary-600);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center; background-size: 14px;
}
.checkbox:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.checkbox:disabled { opacity: .5; cursor: default; }
/* popCheck() (tasksHelpers) adds this on a REAL check only — a plain :checked
   keyframe would replay every time a re-render inserts an already-checked box.
   Overshoot bounce + an expanding halo ring. */
.checkbox--pop { animation: checkbox-pop 360ms var(--ease-bounce); }
@keyframes checkbox-pop {
  0%   { transform: scale(0.8);  box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary-600) 45%, transparent); }
  45%  { transform: scale(1.18); }
  100% { transform: scale(1);    box-shadow: 0 0 0 12px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .checkbox { transition-duration: 0.01ms; }
  .checkbox--pop { animation: none; }
}

/* inline editable field — borderless until hover/focus (for edit-in-place) */
.input-inline {
  width: 100%; height: 40px; padding: 0 12px;
  border: 0; border-radius: var(--radius-md); outline: 0;
  background: transparent; color: var(--text);
  font: inherit; font-size: var(--text-md);
  box-shadow: inset 0 0 0 1px transparent;
  transition: background-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; appearance: none;
}
.input-inline::placeholder { color: var(--text-soft); opacity: 1; }
@media (hover: hover) and (pointer: fine) {
  .input-inline:hover:not(:disabled):not([readonly]) { background: var(--surface-hover); }
}
.input-inline:focus { background: transparent; box-shadow: 0 0 0 1px var(--primary-400), var(--ring-primary); }
.input-inline:disabled { color: var(--text-soft); cursor: default; }
/* inline editable text area variant */
textarea.input-inline { height: auto; min-height: 56px; padding: 8px 12px; white-space: pre-wrap; overflow: auto; resize: vertical; line-height: var(--leading-snug); }
/* forced states (for the design-system reference) */
.input-inline.is-hovered { background: var(--surface-hover); }
.input-inline.is-focused { background: transparent; box-shadow: 0 0 0 1px var(--primary-400), var(--ring-primary); }

/* ---------- Filter dropdown ------------------------------------------ */
.filter-dd { position: relative; }
.filter-dd #filterTrigger svg:last-child { width: 15px; height: 15px; }
.filter-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: var(--z-popover);
  min-width: 210px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; gap: 2px;
  animation: popIn var(--dur) var(--ease);
}
.filter-menu[hidden] { display: none; }
.filter-opt {
  display: flex; align-items: center; gap: var(--space-2);
  height: 36px; padding: 0 10px; border-radius: var(--radius-sm);
  font-size: var(--text-md); font-weight: var(--fw-medium); color: var(--text);
  transition: background var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .filter-opt:hover { background: var(--nav-hover-bg); }
}
.filter-opt > span:first-child { color: var(--text); }
/* selected option: a quiet primary wash so the current choice reads at a
   glance (the trailing ✓ alone is easy to miss on a full sheet) */
/* the selected option ALWAYS carries a slight fill (owner rule 4 Sep) — whether
   a menu marks it with .active, aria-checked (radio menus) or .sel */
.filter-opt.active,
.filter-opt.sel,
.filter-opt.is-selected,
.filter-opt[aria-checked="true"],
.filter-opt[aria-selected="true"] { background: color-mix(in srgb, var(--primary-500) 7%, var(--surface)); }
.filter-opt svg { width: 16px; height: 16px; margin-left: auto; color: var(--primary-600); }
/* separates the special "Dead" status (hidden by default) from the live stages */
.filter-opt-sep { height: 1px; margin: 4px 8px; background: var(--border-faint); flex-shrink: 0; }

/* ---------- Date-picker grid ------------------------------------------
   Base layout for the shared month grid — used by shared/lib/datePicker.js
   (drawers, schedule sheets, every shell), the dashboard mini-cal widget,
   and the sort-dd calendar below. Was stranded in views/dashboard.css,
   which the Trainer shell doesn't link. */
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.cal-head .cal-nav { width: 28px; height: 28px; flex: none; border-radius: var(--radius-sm); display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); border: none; background: none; box-shadow: none; padding: 0; transition: background var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .cal-head .cal-nav:hover { background: var(--nav-hover-bg); }
}
.cal-head .cal-nav svg { width: 18px; height: 18px; }
.cal-head .month { flex: 1; font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--text-strong); text-align: center; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; }
.cal-grid .dow { font-size: var(--text-xs); color: var(--text-soft); font-weight: var(--fw-medium); padding: 6px 0; }
.cal-grid .day { height: 38px; display: inline-flex; align-items: center; justify-content: center; font-size: var(--text-md); font-weight: var(--fw-bold); color: var(--text-strong); border-radius: 50%; cursor: pointer; transition: background var(--dur) var(--ease), color var(--dur) var(--ease); margin: 0 auto; width: 38px; }
@media (hover: hover) and (pointer: fine) {
  .cal-grid .day:hover { background: var(--gray-100); }
}
.cal-grid .day.active { background: var(--primary-600); color: var(--on-primary); font-weight: var(--fw-bold); }

/* ---------- Date (sort) dropdown ------------------------------------- */
.sort-dd { position: relative; }
.sort-dd #sortTrigger svg:last-child { width: 15px; height: 15px; }
.sort-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: var(--z-popover);
  width: 300px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  animation: popIn var(--dur) var(--ease);
}
.sort-menu[hidden] { display: none; }

/* ---------- Shared popover-menu surface ------------------------------
   ONE surface recipe for every anchored menu/popover (the .filter-menu
   look): card surface, hairline border, pop shadow, popIn entrance. The
   per-view rules keep ONLY positioning/sizing/padding. Menus whose markup
   already carries .filter-menu (account/note/rt/cfile menus) need nothing
   here. Two radius tiers exist: md (compact menus) and lg (larger
   popovers). New menus: prefer .filter-menu in markup; else add the class
   to the matching tier below. */
.nc-dd-menu, .td-due-menu, .td-pri-menu,
.compose-fmt-pop, .compose-thumb-pop, .imed-shape-menu, .ne-fmt,
.emoji-pop, .compose-when-pop, .compose-save-pop, .plan-ico-menu,
.plan-datepop, .mpage-menu {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  animation: popIn var(--dur) var(--ease);
}
.slash-menu, .ne-ai-menu, .ne-style-menu, .cal-evt-pop, .cal-filt-pop,
.rchart-metric-menu {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  animation: popIn var(--dur) var(--ease);
}

/* Searchable-dropdown internals — shared by the New-Client field picker
   (.nc-dd-*) and the assignee picker (.assign-*); option rows and menu
   widths stay per-view. */
.nc-dd-search, .assign-search { display: flex; align-items: center; gap: 7px; padding: 0 9px; margin-bottom: 4px; border-bottom: 1px solid var(--border-faint); }
.nc-dd-search svg, .assign-search svg { width: 15px; height: 15px; color: var(--text-soft); flex-shrink: 0; }
.nc-dd-search input, .assign-search input { flex: 1; min-width: 0; height: 36px; border: 0; outline: 0; background: transparent; font-family: var(--font-sans); font-size: var(--text-sm); color: var(--text); }
.nc-dd-search input:focus, .nc-dd-search input:focus-visible,
.assign-search input:focus, .assign-search input:focus-visible { outline: none; box-shadow: none; border: 0; }
.nc-dd-search input::placeholder, .assign-search input::placeholder { color: var(--text-soft); }
.nc-dd-list, .assign-list { display: flex; flex-direction: column; gap: 1px; max-height: 264px; overflow-y: auto; }
/* one-line empty row inside menus / dropdowns */
.menu-empty, .nc-dd-empty, .assign-empty, .mpage-empty { padding: 14px 10px; text-align: center; font-size: var(--text-sm); color: var(--text-soft); }
/* Two-column date picker (owner call 30 Aug, macOS-style): presets in a
   quiet left rail with Clear pinned at the bottom, calendar on the right.
   On phones (sheet) the rail folds back to a 2-up grid above the calendar. */
.sort-menu:has(.sort-body) { width: 470px; }
.sort-body { display: flex; align-items: stretch; gap: var(--space-2-5); }
.sort-presets { flex: 0 0 150px; display: flex; flex-direction: column; gap: 2px; padding: var(--space-1-5); background: var(--surface-sunk); border-radius: var(--radius-sm); }
.sort-presets .filter-opt { height: 34px; }
/* the presets sit on the SUNK track, where the global --nav-hover-bg wash is
   invisible (≈ the same grey) — hover lifts to a white pill instead */
@media (hover: hover) and (pointer: fine) {
  .sort-presets .filter-opt:not(:disabled):hover { background: var(--surface); box-shadow: var(--shadow-xs); }
}
.sort-clear { color: var(--danger-600); margin-top: auto; }
.sort-clear:disabled { opacity: 0.45; cursor: default; }
.sort-cal-wrap { flex: 1 1 auto; min-width: 0; padding-top: 2px; }
@media (max-width: 640px) {
  .sort-body { flex-direction: column; }
  .sort-presets { flex: none; display: grid; grid-template-columns: 1fr 1fr; background: transparent; padding: 0; }
  .sort-clear { grid-column: 1 / -1; margin-top: 0; }
  .sort-cal-wrap { border-top: 1px solid var(--border); padding-top: 10px; }
}
.sort-cal-head { margin-bottom: 6px; }
.sort-cal-head .month { font-size: var(--text-sm); }
.sort-cal { gap: 2px; }
.sort-cal .dow { font-size: 10px; padding: 2px 0; }
.sort-cal .day {
  width: 100%; height: auto; margin: 0; aspect-ratio: 1 / 1;
  border-radius: var(--radius-sm); background: transparent;
  color: var(--text); font-weight: var(--fw-medium); font-size: var(--text-sm); position: relative;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .sort-cal .day:hover { background: var(--gray-100); }
}
.sort-cal .day.other { background: transparent; color: var(--text-soft); opacity: 0.4; pointer-events: none; }
.sort-cal .day.has-lead::after { content: ""; position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%; background: var(--primary-500); }
.sort-cal .day.active { background: var(--primary-600); color: var(--on-primary); }
.sort-cal .day.in-range { background: var(--primary-50); color: var(--primary-700); }
.sort-cal .day.in-range.has-lead::after { background: var(--primary-500); }
.sort-cal .day.active.has-lead::after { background: var(--on-primary); }
.sort-cal-hint { font-size: var(--text-xs); color: var(--text-soft); text-align: center; margin-bottom: 8px; }

/* ---------- Empty / error states --------------------------------------
   The app-universal emptyState()/errorState() (shared/lib/ui.js) plus the
   illustration it renders. Formerly stranded across views/meta-picker.css +
   views/content.css, which forced shells to link view files they didn't use. */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; flex: 1 1 auto; min-height: 56vh;
  padding: var(--space-6) var(--space-4);
}
.empty-state--compact { min-height: 260px; }
/* Error twin of the empty state (errorState()) — a distinct alert disc so a
   failed load never masquerades as "nothing here yet". Danger tokens are
   dark-remapped, so the disc flips with the theme. */
.empty-state-ico {
  display: grid; place-items: center;
  width: 52px; height: 52px; margin-bottom: var(--space-4);
  border-radius: var(--radius-full);
  background: var(--danger-bg); color: var(--danger-600);
}
.empty-state-ico svg { width: 26px; height: 26px; }
/* the illustration + copy emptyState() renders */
.lead-empty-body { display: flex; flex-direction: column; align-items: center; text-align: center; padding: var(--space-5) var(--space-4) var(--space-6); }
.lead-empty-art { position: relative; width: 320px; max-width: 100%; height: 184px; display: flex; align-items: center; justify-content: center; margin-bottom: var(--space-2); }
.lead-empty-grid { position: absolute; inset: 0; width: 100%; height: 100%; }
.lead-empty-card { position: relative; width: 150px; height: 150px; }
.lead-empty-title { font-size: var(--text-lg); font-weight: var(--fw-bold); color: var(--text-strong); letter-spacing: -0.01em; }
.lead-empty-desc { margin-top: var(--space-1-5); max-width: 34ch; font-size: var(--text-sm); color: var(--text-soft); line-height: var(--leading-relaxed); text-wrap: pretty; }
.lead-empty-cta { margin-top: var(--space-4); }
/* Shared load-failure banner (errorBanner()) — a slim inline alert + Retry for
   views that still render content around a failed source (dashboard, calendar). */
.load-error-banner {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-4); padding: var(--space-3) var(--space-4);
  border: 1px solid var(--danger-600); border-radius: var(--radius-md);
  background: var(--danger-bg); color: var(--text-strong);
}
.load-error-ico { display: inline-flex; color: var(--danger-600); }
.load-error-ico svg { width: 20px; height: 20px; }
.load-error-msg { flex: 1 1 auto; font-size: var(--text-sm); }
.load-error-banner .btn { flex: 0 0 auto; }
/* Icon-tile empty state (Files / Notes grids) — one tile + heading + copy;
   per-view classes keep only grid placement (e.g. grid-column: 1 / -1). */
.empty-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-1-5); min-height: 56vh; padding: var(--space-6); text-align: center; }
.empty-tile .tile { width: 52px; height: 52px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-lg); background: var(--gray-100); color: var(--text-soft); margin-bottom: var(--space-0-5); }
.empty-tile .tile svg { width: 25px; height: 25px; }
.empty-tile h3 { font-size: var(--text-lg); font-weight: var(--fw-semibold); color: var(--text-strong); }
.empty-tile p { font-size: var(--text-sm); color: var(--text-muted); max-width: 320px; }

/* ---------- Search field --------------------------------------------- */
.search {
  display: inline-flex; align-items: center; gap: var(--space-2);
  height: 38px; padding: 0 var(--space-3);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface); color: var(--text-soft);
  min-width: 232px;
  box-shadow: var(--btn-shadow);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.search:focus-within { border-color: var(--primary-400); box-shadow: var(--ring-primary); }
.search svg { width: 19px; height: 19px; color: var(--primary-500); }
.search input {
  border: none; outline: none; background: none;
  font-size: var(--text-md); color: var(--text); width: 100%;
}
.search input::placeholder { color: var(--text-soft); }
.search input:focus, .search input:focus-visible { outline: none; box-shadow: none; border: none; }
/* read by screen readers, not shown (a search's "6 results", a status line) */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
/* × clears the box: it takes the ⌘K hint's place once something's typed */
.search .search-clear { display: inline-grid; place-items: center; flex: 0 0 auto; width: 22px; height: 22px; margin-right: calc(var(--space-1) * -1); padding: 0; border: 0; border-radius: var(--radius-full); background: transparent; color: var(--text-soft); cursor: pointer; }
.search .search-clear svg { width: 14px; height: 14px; color: inherit; }
@media (hover: hover) and (pointer: fine) { .search .search-clear:hover { background: var(--surface-hover); color: var(--text-strong); } }
.search .search-clear:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.search input:placeholder-shown ~ .search-clear { display: none; }
.search input:not(:placeholder-shown) ~ .search-kbd { display: none; }

/* ---------- Segmented control ---------------------------------------- */
.segmented {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px; background: var(--seg-track);
  border-radius: var(--radius-md);
}
.segmented button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1-5);
  height: 31px; padding: 0 14px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: var(--fw-medium);
  color: var(--text-soft);
  white-space: nowrap; flex-shrink: 0;   /* a segment never wraps its label */
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .segmented button:hover { color: var(--text); }
}
.segmented button.active {
  background: var(--seg-active); color: var(--text-strong);
  box-shadow: var(--seg-active-shadow);
  border: 1px solid var(--seg-active-border);
}
/* full-width segmented control (e.g. dashboard widget tabs) */
.seg-full { display: flex; width: 100%; }
.seg-full button { flex: 1; }

/* tabs — text tabs where the active one sits on a soft grey pill (reference
   "Upcoming / Unconfirmed / Past" pattern; replaced the underline 4 Sep) */
.tabs { display: inline-flex; gap: var(--space-1); }
.tabs button {
  position: relative; padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: var(--fw-medium);
  color: var(--text-muted);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .tabs button:hover { color: var(--text-strong); background: var(--gray-50); }
}
.tabs button.active { color: var(--text-strong); background: var(--gray-100); }

/* ---------- Card ------------------------------------------------------ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}
.card-pad { padding: var(--space-5); }

/* ---------- Kebab / square icon button (small surface variant) ------- */
.kebab {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--btn-shadow);
  color: var(--btn-fg);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .kebab:hover { background: var(--gray-50); border-color: var(--border-strong); }
}
.kebab svg { width: 16px; height: 16px; }

/* ---------- Small ghost icon button -----------------------------------
   The borderless row/card affordance (delete, copy, close, format…) that
   ~18 views used to hand-roll. Default 30px; --sm 24px; --danger for
   destructive hovers. */
.icon-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border: 0;
  border-radius: var(--radius-sm);
  background: transparent; color: var(--text-soft);
  cursor: pointer; flex-shrink: 0;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.icon-ghost svg { width: 16px; height: 16px; }
.icon-ghost--sm { width: 24px; height: 24px; }
.icon-ghost--sm svg { width: 14px; height: 14px; }
@media (hover: hover) and (pointer: fine) {
  .icon-ghost:hover { background: var(--gray-100); color: var(--text); }
  .icon-ghost--danger:hover { background: var(--danger-bg); color: var(--danger-600); }
}
.icon-ghost:focus-visible { box-shadow: var(--ring-primary); }

/* ---------- Loading spinner -------------------------------------------
   One border-ring spinner (base.css `spin` keyframes). --inverse for dark
   media overlays; size overrides inline or via --lg. */
.spinner {
  width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid var(--border); border-top-color: var(--primary-600);
  animation: spin 0.7s linear infinite;
}
.spinner--lg { width: 26px; height: 26px; border-width: 2.5px; }
.spinner--inverse { border-color: rgba(255, 255, 255, 0.3); border-top-color: #fff; }

/* ---------- Keyboard-hint chip ---------------------------------------- */
.kbd {
  display: inline-flex; align-items: center; height: 22px; padding: 0 7px;
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: var(--gray-50); color: var(--text-muted);
  font-family: inherit; font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
}

/* ---------- Toggle switch ---------------------------------------------
   Canonical: input-based (native :checked + focus ring). Markup:
   <label class="switch"><input type="checkbox"><span class="switch-track"></span></label> */
.switch { position: relative; display: inline-flex; flex-shrink: 0; cursor: pointer; }
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch .switch-track { width: 36px; height: 21px; border-radius: var(--radius-full); background: var(--gray-200); position: relative; transition: background var(--dur-fast) var(--ease); }
.switch .switch-track::after { content: ""; position: absolute; top: 2.5px; left: 2.5px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(27, 27, 35, 0.25); transition: transform var(--dur-fast) var(--ease); }
.switch input:checked + .switch-track { background: var(--primary-600); }
.switch input:checked + .switch-track::after { transform: translateX(15px); }
.switch input:focus-visible + .switch-track { box-shadow: var(--ring-primary); }
.switch input:disabled + .switch-track { opacity: 0.5; cursor: not-allowed; }

/* ---------- Integration status pill -----------------------------------
   Shared by the lead drawer + Settings integrations (was defined in
   lead-drawer.css with the --warn variant patched in from settings.css). */
.intg-status { display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0; white-space: nowrap; font-size: var(--text-xs); font-weight: var(--fw-semibold); padding: 2px 9px 2px 7px; border-radius: var(--radius-full); }
.intg-dot { width: 7px; height: 7px; border-radius: 50%; }
.intg-status--on { color: var(--success-600); background: var(--success-bg); }
.intg-status--on .intg-dot { background: var(--success-600); }
.intg-status--off { color: var(--text-soft); background: var(--gray-100); }
.intg-status--off .intg-dot { background: var(--gray-400); }
.intg-status--warn { color: var(--warning-600); background: var(--warning-bg); }
.intg-status--warn .intg-dot { background: var(--warning-600); }

/* shared "tick pops in" overshoot — replaces the four per-view clones
   (nc-tick-pop / pinTickPop / onbTickPop / paprSentPop) */
@keyframes tick-pop {
  0%   { transform: scale(0.45); opacity: 0; }
  60%  { transform: scale(1.12); opacity: 1; }
  100% { transform: scale(1); }
}

/* ---------- Template micro-utilities ----------------------------------
   For JS-rendered markup: hint-text spacing, self-alignment, media fit.
   JS may write geometry/transforms/custom props inline — never these. */
.form-hint { margin: 10px 2px 0; }
.u-ml-auto { margin-left: auto; }
.img-cover { width: 100%; height: 100%; object-fit: cover; }

/* ---- Toolbar load-error chip -------------------------------------------
   The quiet in-toolbar replacement for the old full-width .load-error-banner:
   a <button> styled as a status chip (alert icon + short message) in danger
   red. Carries the surface's retry attribute (data-data-retry on Dashboard,
   data-cal-retry on Calendar) — the shells' delegated handlers re-run the
   right loader; is-loading is set by those handlers while a retry is in
   flight. [hidden] needs the explicit rule: display:flex would beat the UA
   [hidden]{display:none} at equal specificity. */
.load-error-chip { display: flex; align-items: center; gap: var(--space-2); color: var(--danger-600); font-family: inherit; font-size: var(--text-md); font-weight: var(--fw-medium); background: none; border: 0; padding: 0; cursor: pointer; }
.load-error-chip svg { width: 18px; height: 18px; flex: 0 0 auto; }
.load-error-chip.is-loading { opacity: 0.6; cursor: default; }
.load-error-chip[hidden] { display: none; }
/* On phones the chips are relocated into the crowded topbar
   (applyMobileLeadTools) — collapse them to icon-only (the title/aria-label
   keep the message reachable). */
@media (max-width: 640px) { .load-error-chip span { display: none; } }

/* =========================================================================
   Cross-cutting state + platform rules (kept last on purpose)
   ========================================================================= */

/* Keyboard focus ring for focusable cards/rows — components that set their
   own box-shadow (cards, KPIs) eat base.css's ring at equal specificity;
   the attribute selector outranks a single class. */
[role="button"]:focus-visible {
  outline: none;
  box-shadow: var(--ring-primary), var(--shadow-sm);
}

/* Touch floor — primitives get comfortable hit targets on coarse pointers
   (the WKWebView app + mobile web) instead of per-surface bumps. */
@media (pointer: coarse) {
  .btn { height: 44px; }
  .btn-sm { height: 40px; }
  .btn-icon { width: 44px; }
  .btn-icon.btn-sm { width: 40px; height: 40px; }
  .btn-card { height: 38px; }
  .kebab { width: 38px; height: 38px; }
  .icon-ghost { width: 38px; height: 38px; }
  .icon-ghost--sm { width: 34px; height: 34px; }
  .checkbox { width: 18px; height: 18px; }
}

/* Menus/popovers skip the popIn entrance under reduced motion */
@media (prefers-reduced-motion: reduce) {
  .filter-menu, .sort-menu, .nc-dd-menu, .td-due-menu, .td-pri-menu,
  .compose-fmt-pop, .compose-thumb-pop, .imed-shape-menu, .ne-fmt,
  .emoji-pop, .compose-when-pop, .compose-save-pop, .plan-ico-menu,
  .plan-datepop, .mpage-menu, .slash-menu, .ne-ai-menu, .ne-style-menu,
  .cal-evt-pop, .cal-filt-pop, .rchart-metric-menu { animation: none; }
}

/* =========================================================================
   Setup checklist ("Finish setting up") — what a client still needs to fill
   in for their packages. One primitive, three homes: the portal Dashboard
   card, the Settings → Business banner, and the admin client record
   (features/onboarding/setupCard, features/clients/clientSetup).
   ========================================================================= */
.setup-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4) var(--space-5); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow-xs); }
.setup-head { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.setup-ico { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 32px; height: 32px; border-radius: var(--radius-md); background: var(--brand-gold-soft); color: var(--brand-gold-deep); }
.setup-ico svg { width: 16px; height: 16px; }
.setup-title { display: grid; gap: 1px; min-width: 0; }
.setup-title b { font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--text-strong); }
.setup-title small { font-size: var(--text-xs); color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.setup-bar { flex: 1; min-width: 48px; max-width: 160px; height: 4px; margin-left: auto; border-radius: var(--radius-full); background: var(--gray-200); overflow: hidden; }
.setup-bar i { display: block; height: 100%; width: var(--w, 0%); border-radius: var(--radius-full); background: var(--success-600); transition: width var(--dur-slow) var(--ease); }
/* progress as segments, one per step (Attio) */
.setup-segs { flex: 1; min-width: 48px; max-width: 200px; display: flex; gap: 3px; margin-left: auto; }
.setup-segs i { flex: 1; height: 4px; border-radius: var(--radius-full); background: var(--gray-200); transition: background var(--dur) var(--ease); }
.setup-segs i.is-on { background: var(--primary-600); }
.setup-later { flex-shrink: 0; }
.setup-list { display: flex; flex-direction: column; }
.setup-row { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; padding: var(--space-1-5) 0; border-top: 1px solid var(--border-faint); }
.setup-row:first-child { border-top: 0; }
.setup-tick { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 20px; height: 20px; border-radius: var(--radius-full); border: 1.5px solid var(--border-strong); color: transparent; }
.setup-tick svg { width: 12px; height: 12px; stroke-width: 2.5; }
.setup-row.is-done .setup-tick { border-color: transparent; background: var(--success-bg); color: var(--success-600); }
.setup-row.is-pending .setup-tick { border-color: transparent; background: var(--warning-bg); color: var(--warning-700); }
.setup-row > span { flex: 1; min-width: 0; display: grid; gap: 1px; }
.setup-row b { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-strong); }
.setup-row.is-done b { font-weight: var(--fw-regular); color: var(--text-muted); }
.setup-row small { font-size: var(--text-xs); color: var(--text-soft); overflow: hidden; text-overflow: ellipsis; }
.setup-row .btn { flex-shrink: 0; }
.setup-row .btn svg { width: 14px; height: 14px; }
.setup-note { flex-shrink: 0; font-size: var(--text-xs); color: var(--text-soft); text-align: right; }
/* the portal card lists only what's left, as tiles that wrap to the width */
.setup-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-2); }
.setup-tile { display: flex; align-items: center; gap: var(--space-3); min-height: 56px; padding: var(--space-2-5) var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-sunk); }
.setup-tile > span { flex: 1; min-width: 0; display: grid; gap: 1px; }
.setup-tile b { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-strong); }
.setup-tile small { font-size: var(--text-xs); color: var(--text-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.setup-tile .btn { flex-shrink: 0; }
.setup-tile .btn svg { width: 14px; height: 14px; }
.setup-tile.is-pending { background: transparent; border-style: dashed; }
.setup-tile.is-pending .setup-tick { border-color: transparent; background: var(--warning-bg); color: var(--warning-700); }
/* the Settings banner: tighter, no shadow — it sits above the profile card */
.setup-card--compact { padding: var(--space-3) var(--space-4); box-shadow: none; background: var(--surface-sunk); }
.setup-card--compact .setup-row { min-height: 40px; }
.setup-card--compact .setup-tile { background: var(--surface); }
/* on the admin record it lives inside the sunk packages block */
.setup-card--admin { padding: var(--space-3) var(--space-3-5); box-shadow: none; }
.setup-card--admin .setup-title b { font-size: var(--text-sm); }
.setup-card--admin .setup-bar { max-width: 90px; }
@media (max-width: 640px) {
  .setup-bar { display: none; }
  .setup-row { flex-wrap: wrap; }
}

/* Getting started — the portal sidebar's bottom-left panel (Attio): steps left,
   collapsible. Lives in .sidebar-footer above My Plan / Settings. */
/* between the nav and the footer; contents sit on its bottom edge (which never moves)
   so the open/close morph has a fixed anchor; the pill is centred */
.gs-host { position: relative; display: flex; flex-direction: column; justify-content: flex-end; align-items: stretch; padding: 0 var(--space-4) var(--space-3); box-sizing: border-box; }
.gs-host .gs-pill { align-self: center; }
.gs-host[hidden] { display: none; }
.gs-panel { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; padding: var(--space-3) var(--space-3) var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow-md); }
.gs-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); }
.gs-title { display: grid; gap: 1px; min-width: 0; }
.gs-title b { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }
.gs-title small { font-size: var(--text-xs); color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gs-actions { display: flex; gap: 2px; flex-shrink: 0; margin: -4px -4px 0 0; }
.gs-actions .icon-ghost { width: 24px; height: 24px; }
.gs-actions .icon-ghost svg { width: 13px; height: 13px; }
.gs-panel .setup-segs { max-width: none; margin: 0; }
.gs-panel .setup-segs i { height: 3px; }
.gs-min { flex-shrink: 0; width: 24px; height: 24px; margin: -4px -4px 0 0; }
.gs-min svg { width: 13px; height: 13px; }
/* minimised: a pill — the progress is the accent line running round its edge (--p = percent done) */
/* the ring is an ink segment that travels round the pill (a registered angle so the gradient animates) */
@property --gs-a { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.gs-pill { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 32px; padding: 0 12px; margin: 0; border: 1.5px solid transparent; border-radius: var(--radius-full); font: inherit; font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-strong); box-shadow: var(--shadow-md);
  background: linear-gradient(var(--surface), var(--surface)) padding-box, conic-gradient(from var(--gs-a), var(--primary-600) 0 22%, var(--border) 22% 100%) border-box;
  animation: gsOrbit 2.8s linear infinite; transition: box-shadow var(--dur) var(--ease); }
@keyframes gsOrbit { to { --gs-a: 360deg; } }
/* panel ↔ pill: the container morph (setupCard.swap, Web Animations) — one box
   animates between the two states while their contents cross-fade inside it */
.gs-morph { position: absolute; z-index: 2; overflow: hidden; box-sizing: border-box; pointer-events: none; background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-md); }
.gs-morph-content { position: absolute; left: 0; bottom: 0; margin: 0; }
.gs-morph .gs-panel, .gs-morph .gs-pill { border-color: transparent; box-shadow: none; animation: none; }
.gs-morph .gs-pill { background: var(--surface); }
@media (prefers-reduced-motion: reduce) { .gs-pill { animation: none; } }
.gs-pill small { font-size: var(--text-xs); font-weight: var(--fw-regular); color: var(--text-soft); }
@media (hover: hover) and (pointer: fine) { .gs-pill:hover { box-shadow: var(--shadow-sm); } }
.gs-pill:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.gs-list { display: flex; flex-direction: column; margin-top: var(--space-1); }
.gs-step { display: flex; align-items: center; gap: var(--space-2-5); width: 100%; min-height: 34px; padding: 0 var(--space-1); border-radius: var(--radius-sm); font: inherit; text-align: left; color: var(--text); transition: background var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) { button.gs-step:hover { background: var(--nav-hover-bg); } }
button.gs-step:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.gs-step-ico { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 24px; height: 24px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--text-muted); }
.gs-step-ico svg, .gs-step-ico img { width: 13px; height: 13px; }
.gs-step-text { flex: 1; min-width: 0; display: grid; gap: 0; }
.gs-step-text b { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gs-step-text small { font-size: var(--text-2xs, 11px); color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gs-step > svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-soft); }
.gs-step.is-pending { cursor: default; }
.gs-step.is-pending .gs-step-ico { border-color: transparent; background: var(--warning-bg); color: var(--warning-700); }
/* collapsed sidebar: only the count shows (same orbiting ring); clicking it opens the nav and the panel */
.gs-collapsed { display: none; align-self: center; height: 30px; min-width: 40px; padding: 0 9px; border: 1.5px solid transparent; border-radius: var(--radius-full); font: inherit; font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--text-strong); box-shadow: var(--shadow-xs);
  background: linear-gradient(var(--surface), var(--surface)) padding-box, conic-gradient(from var(--gs-a), var(--primary-600) 0 22%, var(--border) 22% 100%) border-box; animation: gsOrbit 2.8s linear infinite; }
.app.collapsed .gs-host { padding-left: var(--space-2); padding-right: var(--space-2); }
.app.collapsed .gs-panel, .app.collapsed .gs-pill { display: none; }
.app.collapsed .gs-collapsed { display: inline-flex; align-items: center; justify-content: center; }
@media (prefers-reduced-motion: reduce) { .gs-collapsed { animation: none; } }

/* Connect Facebook & Instagram — the in-portal account picker (features/onboarding/metaConnect) */
.mc-pick { display: flex; flex-direction: column; gap: var(--space-1); }
.mc-lead { margin: 0 0 var(--space-3); font-size: var(--text-sm); color: var(--text-muted); }
.mc-group { margin: var(--space-2) 0 var(--space-1); font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--text-soft); text-transform: uppercase; letter-spacing: .04em; }
.mc-row { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; padding: var(--space-1-5) var(--space-2); border-radius: var(--radius-md); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .mc-row:hover { background: var(--surface-sunk); } }
.mc-row > span { display: grid; gap: 1px; min-width: 0; }
.mc-row b { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-strong); }
.mc-row small { font-size: var(--text-xs); color: var(--text-soft); }
.mc-av { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.mc-none { margin: 0; font-size: var(--text-sm); color: var(--text-muted); }
.mc-foot { display: flex; justify-content: flex-end; gap: var(--space-2); }

/* the intro popover beside the Getting started panel (Attio): an accent ring, the active step lit */
.mc-pop { position: fixed; z-index: var(--z-popover); width: 380px; padding: var(--space-3); border-radius: var(--radius-xl); background: var(--surface); box-shadow: 0 0 0 1px var(--border), var(--shadow-lg); animation: popIn var(--dur) var(--ease); }
.gs-step.is-active { background: var(--nav-hover-bg); }   /* the tint alone marks the open step — no outline on its icon */
/* the Connect-Meta intro card: the Content-page mock as the picture, copy, two buttons */
.mc-intro { display: flex; flex-direction: column; gap: var(--space-4); }
.mc-intro-art { position: relative; height: 230px; border-radius: var(--radius-lg); overflow: hidden; background: var(--surface-sunk); border: 1px solid var(--border); }
.mc-intro-mock { position: absolute; left: 7%; top: 9%; right: -14%; bottom: -30%; pointer-events: none; font-size: var(--text-xs); }
.mc-intro-mock .onb-mock { box-shadow: var(--shadow-md); }
.mc-intro-mock .onb-approve { left: 8%; right: 10%; bottom: 42%; padding: var(--space-2-5) var(--space-3); gap: var(--space-1-5) var(--space-2-5); animation-delay: 900ms; }   /* the approval card, sized for the small picture; slides in a beat after the card opens */
.mc-intro-mock .onb-approve-body b { font-size: var(--text-xs); }
.mc-intro-mock .onb-approve-body small { font-size: var(--text-2xs, 11px); }
.mc-intro-mock .onb-approve-actions i { height: 24px; padding: 0 9px; font-size: var(--text-2xs, 11px); }
.mc-intro-copy { margin: 0; font-size: var(--text-sm); line-height: var(--leading-relaxed); color: var(--text-muted); }
.mc-intro-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.mc-intro-actions .btn img { width: 16px; height: 16px; }

.gs-list { max-height: min(48vh, 390px); overflow-y:auto; }

/* Setup previews: a quiet row highlight and a benefit card beside the sidebar. */
.gs-step.is-previewing { background:var(--primary-50); box-shadow:inset 0 0 0 1px var(--primary-100); }
.gs-step.is-previewing .gs-step-ico { color:var(--primary-600); border-color:var(--primary-100); }
.gs-step > svg { transition:transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.gs-step.is-previewing > svg { transform:translateX(2px); color:var(--primary-600); }
.gs-benefit { position:fixed; z-index:var(--z-popover); width:340px; max-width:calc(100vw - 24px); max-height:calc(100vh - 24px); overflow:auto; padding:var(--space-2); border:1px solid var(--primary-100); border-radius:var(--radius-xl); background:var(--surface); box-shadow:var(--shadow-lg); animation:gsBenefitIn var(--dur-fast) var(--ease-enter) both; }
.gs-benefit-art { position:relative; isolation:isolate; min-height:154px; display:flex; flex-direction:column; align-items:flex-start; justify-content:center; gap:var(--space-2); overflow:hidden; padding:var(--space-5); border-radius:var(--radius-lg); background:var(--text-strong); color:var(--surface); }
.gs-benefit-art::before { content:""; position:absolute; inset:0; z-index:-1; opacity:.07; background-image:linear-gradient(currentColor 1px, transparent 1px),linear-gradient(90deg,currentColor 1px,transparent 1px); background-size:24px 24px; mask-image:linear-gradient(90deg,transparent,black); }
.gs-benefit-kicker { font-size:var(--text-2xs); letter-spacing:.06em; opacity:.65; }
.gs-benefit-art h3 { position:relative; max-width:190px; margin:0; font-size:var(--text-lg); font-weight:var(--fw-semibold); line-height:1.2; color:inherit; }
.gs-benefit-art > svg { position:absolute; z-index:-1; width:230px; height:160px; right:-68px; bottom:0; stroke:currentColor; stroke-width:1; opacity:.23; }
.gs-benefit-brand { margin-top:var(--space-3); font-size:var(--text-2xs); font-weight:var(--fw-semibold); letter-spacing:.13em; opacity:.7; }
.gs-benefit-body { padding:var(--space-3) var(--space-1) var(--space-1); }
.gs-benefit-stat { display:grid; gap:var(--space-0-5); }
.gs-benefit-stat b { font-size:var(--text-xl); font-weight:var(--fw-semibold); letter-spacing:-.03em; line-height:1.2; color:var(--text-strong); }
.gs-benefit-stat span { font-size:var(--text-xs); color:var(--text-muted); }
.gs-benefit-body p { margin:var(--space-3) 0; font-size:var(--text-sm); line-height:1.5; color:var(--text-muted); }
.gs-benefit-body .btn { gap:var(--space-2); }
@keyframes gsBenefitIn { from { opacity:0; transform:translateX(-4px); } to { opacity:1; transform:translateX(0); } }
@media(prefers-reduced-motion:reduce) { .gs-benefit { animation:none; } .gs-step > svg { transition:none; } }

/* Two content milestones: recommended first action, then real customer proof. */
.website-activation { display:grid; gap:var(--space-4); }
.activation-head { display:flex; align-items:center; gap:var(--space-4); }
.activation-head h2 { margin:0; font-size:var(--text-lg); font-weight:var(--fw-semibold); letter-spacing:-.025em; }
.activation-head p { margin:var(--space-1) 0 0; color:var(--text-muted); font-size:var(--text-sm); }
.activation-head > .icon-ghost { flex-shrink:0; align-self:flex-start; }
.activation-progress { margin-left:auto; min-width:100px; display:grid; gap:var(--space-2); color:var(--text-muted); font-size:var(--text-xs); white-space:nowrap; }
.activation-progress-track { display:flex; gap:var(--space-1); }
.activation-progress-track i { height:4px; flex:1; border-radius:var(--radius-full); background:var(--border); }
.activation-progress-track .is-done { background:var(--success-600); }
.activation-cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr)); gap:var(--space-4); }
.activation-card { position:relative; isolation:isolate; display:flex; overflow:hidden; padding:var(--space-5); border:1px solid var(--border); border-radius:var(--radius-xl); background:var(--surface); box-shadow:var(--shadow-xs); transition:box-shadow var(--dur) var(--ease),border-color var(--dur) var(--ease); }
.activation-card--photos { background:linear-gradient(115deg,var(--surface) 45%,var(--info-bg)); }
.activation-card--reviews { background:linear-gradient(115deg,var(--surface) 45%,var(--warning-50)); }
.activation-copy { z-index:1; flex:1; min-width:0; padding-right:var(--space-3); }
.activation-eyebrow { display:flex; align-items:center; gap:var(--space-3); color:var(--text-muted); font-size:var(--text-2xs); font-weight:var(--fw-medium); letter-spacing:.04em; }
.activation-eyebrow > span { color:var(--text-soft); }
.activation-copy h3 { margin:var(--space-3) 0 var(--space-2); color:var(--text-strong); font-size:var(--text-xl); line-height:1.2; font-weight:var(--fw-semibold); letter-spacing:-.03em; }
.activation-copy p { max-width:360px; margin:0 0 var(--space-4); color:var(--text-muted); font-size:var(--text-sm); line-height:1.5; }
.activation-copy small { display:block; margin-top:var(--space-2); color:var(--text-soft); font-size:var(--text-2xs); }
.activation-photo-art,.activation-review-art { position:relative; align-self:center; flex:0 0 148px; height:166px; pointer-events:none; }
.activation-photo { position:absolute; display:grid; grid-template-rows:1fr auto; width:102px; height:126px; padding:var(--space-1-5); border:1px solid var(--border); border-radius:var(--radius-md); background:var(--surface); box-shadow:var(--shadow-md); }
.activation-photo--back { right:0; top:5px; transform:rotate(10deg); }
.activation-photo--front { left:0; bottom:0; transform:rotate(-8deg); }
.activation-photo svg { width:100%; height:88px; border-radius:var(--radius-sm); background:var(--info-bg); stroke:var(--info-600); stroke-width:1.5; }
.activation-photo--front svg { background:var(--success-bg); stroke:var(--success-700); }
.activation-photo > span { padding-top:var(--space-1); text-align:center; font-size:var(--text-2xs); color:var(--text-muted); }
.activation-plus,.activation-proof { position:absolute; display:grid; place-items:center; width:30px; height:30px; border-radius:var(--radius-full); background:var(--surface); border:1px solid var(--border); box-shadow:var(--shadow-sm); right:-4px; bottom:0; }
.activation-plus svg,.activation-proof svg { width:14px; height:14px; }
.activation-review-sheet { position:absolute; inset:16px 0 14px; display:flex; flex-wrap:wrap; align-content:flex-start; gap:var(--space-2); padding:var(--space-3); background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); box-shadow:var(--shadow-md); transform:rotate(6deg); }
.activation-avatar { display:grid; place-items:center; width:26px; height:26px; border-radius:var(--radius-full); background:var(--warning-bg); color:var(--warning-700); }
.activation-avatar svg { width:14px; height:14px; }
.activation-review-lines { flex:1; display:grid; align-content:center; gap:5px; }
.activation-review-lines i,.activation-review-copy i { display:block; height:4px; border-radius:var(--radius-full); background:var(--border); }
.activation-review-lines i:last-child { width:65%; }
.activation-review-stars { width:100%; font-size:var(--text-md); letter-spacing:2px; color:var(--warning-600); }
.activation-review-copy { width:100%; display:grid; gap:5px; }
.activation-review-copy i:last-child { width:70%; }
.activation-review-sheet > img { position:absolute; bottom:-8px; right:12px; }
.activation-proof { color:var(--success-700); bottom:0; right:118px; }
.activation-complete { display:flex; align-items:center; gap:var(--space-2); color:var(--success-700); font-size:var(--text-sm); }
.activation-complete svg { width:16px; height:16px; }
@media(hover:hover) and (pointer:fine) { .activation-card:hover { border-color:var(--primary-100); box-shadow:var(--shadow-md); } }
@media(max-width:720px) { .activation-head { flex-wrap:wrap; gap:var(--space-2); } .activation-head > div:first-child { flex:1; } .activation-progress { order:3; margin-left:0; width:100%; } .activation-progress-track { max-width:110px; } .activation-cards { grid-template-columns:1fr; } .activation-card { padding:var(--space-4); } .activation-photo-art,.activation-review-art { flex-basis:100px; transform:scale(.78); transform-origin:right center; margin-left:-22px; } }
@media(prefers-reduced-motion:reduce) { .activation-card { transition:none; } }

/* ---- tooltip: a small dark label under an icon button (shared/lib/tooltip.js wireTooltips; Google-style) ---- */
.tip { position: fixed; z-index: var(--z-toast); max-width: 240px; padding: var(--space-1) var(--space-2); border-radius: var(--radius-xs); background: var(--gray-800); color: var(--gray-0); font-size: var(--text-xs); font-weight: var(--fw-medium); line-height: 1.35; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity 0.12s var(--ease); }
.tip.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .tip { transition: none; } }

