/* AUTO-EXTRACTED from dashboard/index.html by S2-4 (one design system).
   MOVE, NOT REWRITE (C-9): every rule below is byte-identical to its
   source except (a) hard-coded hex -> tokens (SPRINT2_DESIGN §4.2) and
   (b) the .status-pill -> .angle-pill/.listing-pill rename (§4.3's three-step
   handoff: L3 aliased, L2 flipped the JS strings, and SERIAL-LAST has now
   DELETED the alias — it lived in components.css). Load order: see §4.1. */

/* shell.css — the app shell: .glass, .topbar, brand mark, status
   cluster, fb/scrape/debug pills, account menu. Styles exactly the markup
   js/shell.mjs emits (S2-6 §8.3). Loaded on EVERY page. */
/* ─────────────────────────────────────────────────────────────────────────
   3. App shell + glass primitives
   ───────────────────────────────────────────────────────────────────────── */
.app {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.glass {
  background: var(--glass-bg);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow);
}
.glass-strong {
  background: var(--glass-bg-2);
  backdrop-filter: blur(60px) saturate(200%);
  -webkit-backdrop-filter: blur(60px) saturate(200%);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow);
}
/* ─────────────────────────────────────────────────────────────────────────
   4. Header bar
   ───────────────────────────────────────────────────────────────────────── */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 24px;
  border-radius: 0;
  border-top: 0;
  border-left: 0;
  border-right: 0;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--accent);
  display: grid; place-items: center;
  color: white; font-weight: 700; font-size: 14px;
  letter-spacing: .04em;
  box-shadow: 0 2px 8px rgba(45,79,160,.25), 0 1px 0 rgba(255,255,255,.2) inset;
  overflow: hidden;
}
/* When the account has a logo, show it instead of initials (white tile, contained) */
.brand-mark.has-logo { background: var(--white); padding: 3px; }
.brand-mark.has-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.brand-name { font-weight: 600; letter-spacing: -0.01em; }
.brand-name .dim { color: var(--ink-soft); font-weight: 400; margin-left: 6px; }
.spacer { flex: 1; }
.icon-btn {
  width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center;
  color: var(--ink-soft);
  transition: background var(--t-fast), color var(--t-fast), transform var(--t-fast);
}
.icon-btn:hover { background: var(--glass-edge); color: var(--ink); }
.icon-btn:active { transform: scale(.94); }
.icon-btn svg { width: 18px; height: 18px; }
.theme-toggle .icon { transition: transform var(--t-base); }
[data-theme="dark"] .theme-toggle .icon { transform: rotate(180deg); }
.agent-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px 6px 6px;
  border-radius: 999px;
  background: var(--glass-edge);
  font-size: 13px; color: var(--ink-soft); font-weight: 500;
}
/* Top-bar zones: status cluster + account menu */
.status-cluster { display: flex; align-items: center; gap: 8px; padding: 0 4px; }
.fb-pill.compact .fb-pill-label {
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account-menu { position: relative; }
.account-menu .agent-pill { cursor: pointer; gap: 8px; border: 0; }
.account-menu .agent-pill .chev { width: 14px; height: 14px; opacity: .6; transition: transform var(--t-fast); }
.account-menu .agent-pill[aria-expanded="true"] .chev { transform: rotate(180deg); }
.account-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0;
  min-width: 190px; padding: 6px;
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: 0 8px 28px rgba(0,0,0,.14);
  display: flex; flex-direction: column; gap: 2px;
  z-index: 60;
}
.account-dropdown[hidden] { display: none; }
.account-item {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; border-radius: 9px;
  font-size: 13px; font-weight: 600; color: var(--ink);
  text-decoration: none; cursor: pointer; background: transparent; border: 0;
  text-align: left; width: 100%;
}
.account-item:hover { background: var(--glass-edge); }
.account-item.danger { color: var(--bad); }
.account-sep { height: 1px; background: var(--rule); margin: 4px 6px; }
/* FB connection pill */
.fb-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--glass-edge);
  font-size: 12px; font-weight: 600;
  color: var(--ink-soft);
  transition: background var(--t-fast), color var(--t-fast);
  cursor: pointer;
}
.fb-pill:hover { background: color-mix(in oklab, var(--ink) 8%, transparent); color: var(--ink); }
.fb-pill .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-faint);
}
.fb-pill .dot.dot-pending { background: var(--warn); animation: dotPulse 1.2s infinite; }
.fb-pill .dot.dot-ok      { background: var(--good); }
.fb-pill .dot.dot-bad     { background: var(--bad); }
.fb-pill.connected        { color: var(--good); background: var(--good-soft); }
.fb-pill.error            { color: var(--bad);  background: var(--bad-soft); }
@keyframes dotPulse {
  0%, 100% { box-shadow: 0 0 0 0 currentColor; opacity: 1; }
  50% { box-shadow: 0 0 0 4px transparent; opacity: .55; }
}
/* Topbar Scrape pill — same shape language as the FB + Debug pills */
.scrape-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px;
  border-radius: 999px;
  background: var(--glass-edge);
  font-size: 12px; font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), transform var(--t-fast);
}
.scrape-pill:hover {
  background: color-mix(in oklab, var(--accent) 14%, transparent);
  color: var(--accent);
}
.scrape-pill:active { transform: scale(.97); }
.scrape-pill svg { width: 13px; height: 13px; }
/* Debug pill — sits next to the FB pill */
.debug-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px;
  border-radius: 999px;
  background: var(--glass-edge);
  font-size: 12px; font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.debug-pill:hover { background: color-mix(in oklab, var(--ink) 8%, transparent); color: var(--ink); }
.debug-pill svg { width: 13px; height: 13px; }
.debug-pill .badge {
  display: none;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--bad); color: white;
  font-size: 10px; font-weight: 700;
  align-items: center; justify-content: center;
}
.debug-pill.has-error {
  color: var(--bad); background: var(--bad-soft);
  animation: debugPulse 2s ease-in-out infinite;
}
.debug-pill.has-error .badge { display: inline-flex; }
@keyframes debugPulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--bad-soft); }
  50% { box-shadow: 0 0 0 6px transparent; }
}
.agent-pill .avatar {
  width: 24px; height: 24px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: white; display: grid; place-items: center;
  font-size: 10px; font-weight: 700;
}

/* Top-bar responsive collapse: dots-only status, hide account name on narrow widths */
@media (max-width: 720px) {
  .fb-pill.compact .fb-pill-label { display: none; }
  .account-menu #userName { display: none; }
}

/* ── SERIAL-LAST reconciliation (Sprint 2 lane merge) ──────────────────────
   MOVED VERBATIM from css/dashboard.css's @media 820px / 480px blocks. These
   are topbar rules, but dashboard.css is loaded by index.html ALONE, so the
   seven pages that mount the very same topbar from js/shell.mjs never got
   them — the bar did not wrap, the brand did not shrink and the account label
   never collapsed on a phone. Not one declaration changed: this is the S2-4
   partition finishing its job. Kept in their original breakpoint order, and
   after the 720px block exactly as they were after it in index.html's
   original single stylesheet, so index.html's cascade is unchanged.          */
@media (max-width: 820px) {
  .topbar { padding: 12px 16px; gap: 8px; flex-wrap: wrap; }
  .topbar .brand-name { font-size: 14px; }
  .topbar .agent-pill .avatar { font-size: 11px; }
}
@media (max-width: 480px) {
  .brand-name .dim { display: none; }
  .topbar .agent-pill span:not(.avatar) { display: none; }
  .topbar { gap: 6px; padding: 10px 12px; }
  .fb-pill, .debug-pill { padding: 5px 9px; font-size: 11px; }
}
/* ── Wave 1: listing website · QR codes · market reports ──────────────────
   Everything below reuses the existing tokens (--accent, --glass-edge,
   --ink-soft, --good/--warn/--bad, DM Serif + Inter) and the existing
   primitives (.glass, .btn-primary, .btn-secondary, .section-header).
   The ONE new thing is `.site-pill`: publication state is a different
   vocabulary from campaign state, and C-6 says a third overload of
   .status-pill is worse than one honest new class.                        */
/* .badge is scoped to .debug-pill, so the Leads pill needs its own. */
.scrape-pill .badge {
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px;
  background: var(--accent); color: var(--white);
  font-size: 10px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}

/* ═════════════════════════════════════════════════════════════════════════
   S2-6 ADDITIONS — the mount point js/shell.mjs renders into.

   Everything above is a verbatim move of index.html's topbar rules. The five
   rules below are new, and exist only to make ONE copy of that topbar work on
   every page. They do not change index.html's rendering: index already has a
   sticky ~61px .topbar and already sets text-decoration on its own anchors.
   ═════════════════════════════════════════════════════════════════════════ */

/* Reserved height. shell.mjs mounts AFTER /api/me resolves (the avatar, the
   name and the Admin item are per-user), so for one frame the bar is empty.
   A fixed min-height means no layout shift and no flash of a wrong account
   name — see SPRINT2_DESIGN §8.2. */
#apexShell { min-height: var(--topbar-h); }

/* The brand lockup is an <a> back to the dashboard on every page. */
.topbar a.brand { text-decoration: none; color: inherit; }

/* The nav pills shell.mjs emits carry BOTH `scrape-pill` (for the existing
   look, unchanged) and `topbar-pill` (the §8.3 markup contract name), so the
   contract selector is real without duplicating a single declaration. */
.topbar-pill { font-family: inherit; }

/* Current page in the account dropdown. */
.account-item.active { background: var(--accent-soft); color: var(--accent-dark); }

/* The status cluster collapses to dots on narrow widths; when a page passes
   status:false it is simply absent, so no rule is needed for that case. */
.status-cluster:empty { display: none; }
