/* ============================================================
   Creator Cache™ — one light theme, electric gradients, paper
   ============================================================
   The marketing page and the app used to be two different products to
   look at: the landing redeclared a light palette on #landing while
   :root stayed obsidian, so signing in meant a white page, then a black
   dialog on top of it, then a black app. Three grounds in two clicks.

   Now there is one ground. These are the tokens the landing already
   used — they simply live at :root, so #app, every modal, the toast,
   the sign-in wall and the ten views inherit them like the landing did.

   Contrast: the old dark accents (#8b5cf6, #22d3ee, #34d399) sit at
   roughly 3:1 on white and fail WCAG AA for text, so each is a darker
   sibling that passes at body-text size. Keep that property when
   editing — the number in the comment is the ratio on --bg-card.
   ============================================================ */

:root {
  --bg-primary:   #fbfbfd;
  --bg-secondary: #f3f3f9;
  --bg-card:      #ffffff;
  --border:       #e5e5ef;
  --text-primary: #15151f;
  --text-muted:   #55556b;   /* 7.0:1 on white */

  --accent:       #6d28d9;   /* violet-700  — 6.6:1 on white */
  --accent-2:     #0e7490;   /* cyan-700    — 5.1:1 on white */
  --accent-gradient: linear-gradient(135deg, #7c3aed, #0891b2);
  --success:      #047857;
  --warning:      #b45309;
  --danger:       #b91c1c;
  --shadow:       0 12px 40px rgba(23, 23, 46, 0.10);

  /* Channel triplets for the six hues above — see shared.css for why.
     Every tint in the app (chip fills, active nav, drag targets, the AI
     bubble) is rgba(var(--accent-rgb), a), so restating them here is
     what moves the whole product off the old bright violet. */
  --accent-rgb:   109, 40, 217;
  --accent-2-rgb: 8, 145, 178;
  --success-rgb:  4, 120, 87;
  --warning-rgb:  180, 83, 9;
  --danger-rgb:   185, 28, 28;

  /* The ground-dependent surfaces declared in shared.css. That file is
     shared with the Hub and Womeown, which are still dark, so it keeps
     the dark values and this is where Creator Cache states its own. */
  --input-bg:       #ffffff;
  --surface-sunken: #f3f3f9;
  --track:          rgba(23, 23, 46, 0.10);
  --chrome-bg:      rgba(255, 255, 255, 0.85);
  --scrim:          rgba(23, 23, 46, 0.38);
  --scrim-solid:    rgba(243, 243, 249, 0.96);

  /* Typography: IBM Plex. Sans carries prose and headings, Mono carries the
     UI chrome (labels, counters, tags) so meta-text reads as instrument
     panel rather than copy. Overrides the Outfit/Inter pair in shared.css;
     the Hub and Womeown keep theirs. */
  --font-display: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-body: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Plex Sans stops at 700 and Plex Mono at 600. Anything heavier than the
   face actually ships gets synthesised into a smeared faux-bold, so the two
   blocks below pin every weight to one the font really has. */
.logo, .price-card .plan-price { font-weight: 700; }

/* ---------- Mono chrome ----------
   Labels, counters and tags carry Plex Mono so meta-text reads as an
   instrument panel rather than as copy. Max weight 600. */
.metric .m-label,
.metric .m-value,
.strength-score,
.kanban-col h4,
.pf-case-label,
.popular-tag,
.chip,
.badge {
  font-family: var(--font-mono);
}
.metric .m-value, .strength-score, .pf-case-label,
.popular-tag, .badge, .kanban-col h4 { font-weight: 600; }
.metric .m-value, .strength-score { letter-spacing: -0.02em; }

/* One ground for the whole product. Two soft washes rather than a flat
   fill — a violet bloom top-left and a cyan one top-right — which keeps
   a very light page from reading as a blank sheet. The app is scrolled
   through for hours where the landing is skimmed once, so the app takes
   the same two washes at roughly half strength: same ground, less tint.
   `background-attachment: fixed` keeps the bloom at the top of the
   WINDOW rather than the top of the document, so a long pipeline does
   not scroll out of its own lighting. */
body {
  background:
    radial-gradient(ellipse 70% 55% at 12% -8%, rgba(var(--accent-rgb), 0.10), transparent 60%),
    radial-gradient(ellipse 65% 50% at 92% -2%, rgba(var(--accent-2-rgb), 0.09), transparent 60%),
    var(--bg-primary);
  background-attachment: fixed;
}

body:has(#app:not(.hidden)) {
  background:
    radial-gradient(ellipse 70% 55% at 12% -8%, rgba(var(--accent-rgb), 0.055), transparent 60%),
    radial-gradient(ellipse 65% 50% at 92% -2%, rgba(var(--accent-2-rgb), 0.05), transparent 60%),
    var(--bg-primary);
  background-attachment: fixed;
}
.logo { font-family: var(--font-display); font-size: 1.2rem; display: flex; align-items: center; gap: 8px; }
.logo .mark { background: var(--accent-gradient); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* =================== APP SHELL =================== */
.app-shell { display: flex; min-height: 100vh; min-height: 100dvh; }

.sidebar {
  width: 250px; flex-shrink: 0; padding: 22px 16px;
  background: var(--chrome-bg); border-right: 1px solid var(--border);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  display: flex; flex-direction: column; gap: 6px;
  position: sticky; top: 0; height: 100vh; height: 100dvh; overflow-y: auto; z-index: 100;
}
.sidebar .logo { padding: 0 10px 18px; }
.nav-item {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border-radius: 12px; border: none; background: transparent;
  color: var(--text-muted); font-size: 0.92rem; font-weight: 600; text-align: left;
  transition: background 0.15s, color 0.15s; width: 100%;
}
.nav-item:hover { background: rgba(var(--accent-rgb), 0.07); color: var(--text-primary); }
.nav-item.active { background: linear-gradient(135deg, rgba(var(--accent-rgb),0.2), rgba(var(--accent-2-rgb),0.12)); color: var(--text-primary); box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb),0.35); }
.sidebar-footer { margin-top: auto; display: flex; flex-direction: column; gap: 10px; }

.main { flex: 1; padding: 26px clamp(16px, 3.5vw, 42px) 90px; min-width: 0; }
.view { display: none; animation: fadeIn 0.25s ease; }
.view.active { display: block; }
.view-head { display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 22px; }
.view-head h2 { font-size: 1.5rem; }
.view-head p { color: var(--text-muted); font-size: 0.88rem; margin-top: 4px; }

/* Dashboard metric tiles */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
.metric { padding: 18px; }
.metric .m-value { font-size: 1.9rem; }
.metric .m-label { color: var(--text-muted); font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase; margin-top: 5px; }
.metric .m-icon { font-size: 1.3rem; margin-bottom: 8px; display: block; }

/* Idea cache */
.idea-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; margin-top: 18px; }
.idea-card { position: relative; }
.idea-card.pinned { border-color: var(--warning); }
.idea-card .i-tag { font-size: 0.7rem; }
.idea-card p { margin: 10px 0; font-size: 0.92rem; line-height: 1.5; word-break: break-word; }
.idea-actions { display: flex; gap: 6px; }
.icon-btn { background: transparent; border: 1px solid var(--border); border-radius: 8px; color: var(--text-muted); padding: 5px 9px; font-size: 0.85rem; min-height: 32px; }
.icon-btn:hover { color: var(--text-primary); border-color: var(--accent); }

/* Kanban */
.kanban { display: grid; grid-template-columns: repeat(4, minmax(240px, 1fr)); gap: 14px; overflow-x: auto; padding-bottom: 12px; }
.kanban-col { background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--radius); padding: 13px; min-height: 300px; }
.kanban-col.drag-over { border-color: var(--accent); background: rgba(var(--accent-rgb),0.07); }
.kanban-col h4 { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); display: flex; justify-content: space-between; margin-bottom: 12px; }
.deal-card { margin-bottom: 10px; padding: 14px; cursor: grab; }
.deal-card:active { cursor: grabbing; }
.deal-card .d-name { font-weight: 700; font-size: 0.93rem; }
.deal-card .d-value { color: var(--accent-2); font-weight: 700; font-size: 0.88rem; margin: 5px 0; }
.deal-card .d-notes { color: var(--text-muted); font-size: 0.8rem; line-height: 1.45; }
.deal-move { display: flex; gap: 5px; margin-top: 9px; }

/* Content engine */
.ce-layout { display: grid; grid-template-columns: 1fr 320px; gap: 18px; align-items: start; }
.template-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.chip { padding: 8px 14px; border-radius: 999px; border: 1px solid var(--border); background: transparent; color: var(--text-muted); font-size: 0.76rem; font-weight: 500; letter-spacing: 0.02em; min-height: 36px; }
.chip.active, .chip:hover { border-color: var(--accent); color: var(--text-primary); background: rgba(var(--accent-rgb),0.12); }
.chip.locked { opacity: 0.68; border-style: dashed; }
.sched-item { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 12px 0; border-bottom: 1px solid var(--border); font-size: 0.88rem; }
.sched-item:last-child { border-bottom: none; }
.platform-pill { font-size: 0.7rem; padding: 3px 9px; border-radius: 999px; background: var(--bg-card); border: 1px solid var(--border); }

/* Habits */
.habit-row { display: flex; align-items: center; gap: 12px; padding: 13px 0; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.habit-row:last-child { border-bottom: none; }
.habit-name { flex: 1; font-weight: 600; font-size: 0.92rem; min-width: 130px; }
.habit-days { display: flex; gap: 6px; }
.day-dot {
  width: 32px; height: 32px; border-radius: 9px; border: 1px solid var(--border);
  background: transparent; color: var(--text-muted); font-size: 0.66rem; font-weight: 700;
}
.day-dot.done { background: var(--accent-gradient); color: #fff; border-color: transparent; }
.goal-bar { height: 8px; background: var(--track); border-radius: 99px; overflow: hidden; margin-top: 8px; }
.goal-bar .fill { height: 100%; background: var(--accent-gradient); border-radius: 99px; transition: width 0.4s ease; }

/* AI assistant */
.ai-layout { display: grid; grid-template-columns: 300px 1fr; gap: 18px; align-items: start; }
.ai-actions { display: flex; flex-direction: column; gap: 9px; }
.ai-action { text-align: left; padding: 13px 15px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg-card); color: var(--text-primary); font-size: 0.88rem; font-weight: 600; transition: border-color 0.15s, transform 0.15s; }
.ai-action:hover { border-color: var(--accent); transform: translateX(3px); }
.ai-action small { display: block; color: var(--text-muted); font-weight: 400; margin-top: 3px; font-size: 0.76rem; }
.ai-chat { min-height: 380px; display: flex; flex-direction: column; }
.ai-log { flex: 1; display: flex; flex-direction: column; gap: 12px; overflow-y: auto; max-height: 430px; padding-right: 4px; }
.ai-msg { padding: 13px 16px; border-radius: 14px; font-size: 0.9rem; line-height: 1.6; max-width: 88%; white-space: pre-wrap; word-break: break-word; }
.ai-msg.user { align-self: flex-end; background: rgba(var(--accent-rgb),0.18); border: 1px solid rgba(var(--accent-rgb),0.3); }
.ai-msg.bot { align-self: flex-start; background: var(--bg-card); border: 1px solid var(--border); }
.ai-msg.bot.thinking { color: var(--text-muted); font-style: italic; }
.ai-input-row { display: flex; gap: 9px; margin-top: 14px; }
.ai-input-row input { flex: 1; }
.mode-pill { font-size: 0.72rem; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-muted); }
.mode-pill.live { border-color: var(--success); color: var(--success); }

/* Identity vault */
.socials-grid { display: grid; gap: 0 14px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
/* Dashboard greeting avatar — the user's face, not an initial */
.dash-avatar {
  width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-gradient); color: #fff; font-weight: 700; font-size: 1.1rem;
}
.dash-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.greet-row { display: flex; align-items: center; gap: 13px; }
.links-list { display: flex; flex-direction: column; gap: 9px; margin-top: 12px; }
.link-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 14px; border: 1px solid var(--border); border-radius: 11px; background: var(--bg-card); font-size: 0.88rem; }
.link-row a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.check-item { display: flex; align-items: center; gap: 10px; padding: 9px 0; font-size: 0.9rem; color: var(--text-muted); }
.check-item input { width: 18px; height: 18px; accent-color: var(--accent); }
.check-item.done { text-decoration: line-through; opacity: 0.6; }

/* ============ Profile strength meter ============ */
.strength-card { padding: 18px 20px; }
.strength-bar-wrap { margin-top: 14px; }
.strength-meta { display: flex; align-items: center; gap: 16px; }
.strength-score {
  font-size: 1.7rem; line-height: 1;
  min-width: 74px; text-align: center; padding: 12px 8px; border-radius: 12px;
  background: var(--bg-card); border: 1px solid var(--border);
}
.strength-score.sinvisible { color: var(--danger); }
.strength-score.sthin { color: var(--warning); }
.strength-score.sgettingthere { color: var(--warning); }
.strength-score.sstrong { color: var(--accent-2); }
.strength-score.sclientready { color: var(--success); }
.strength-bar { height: 8px; border-radius: 99px; background: var(--track); overflow: hidden; margin-top: 12px; }
.strength-bar .fill { height: 100%; border-radius: 99px; background: var(--accent-gradient); transition: width 0.5s cubic-bezier(0.4,0,0.2,1); }
.strength-next {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--border);
}

/* ============ Portfolio Studio ============ */
.gap-row { padding: 13px 0; border-bottom: 1px solid var(--border); }
.gap-row:last-child { border-bottom: 0; }
.gap-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.gap-pts { font-size: 0.76rem; font-weight: 700; color: var(--accent-2); }
.upsell-card {
  border: 1px solid rgba(var(--accent-rgb),0.4); border-radius: 12px; padding: 14px;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.13), rgba(var(--accent-2-rgb),0.06));
}
.pf-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.pf-item { position: relative; padding: 16px; }
.pf-item-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pf-price { color: var(--accent-2); font-weight: 700; font-size: 0.95rem; white-space: nowrap; }
.pf-price small { color: var(--text-muted); font-weight: 500; }
.pf-thumb { width: 100%; aspect-ratio: 16/10; object-fit: cover; border-radius: 9px; margin-bottom: 10px; display: block; }
.pf-thumb-empty { display: flex; align-items: center; justify-content: center; font-size: 1.8rem; background: var(--bg-card); border: 1px dashed var(--border); }
.pf-thumb-wrap { position: relative; }
.pf-play {
  position: absolute; top: 8px; left: 8px; padding: 3px 9px; border-radius: 99px;
  background: rgba(0,0,0,0.66); color: #fff; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.02em;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.fm-thumb:not(:empty) { margin-top: 10px; }
.fm-thumb img { width: 100%; max-height: 170px; object-fit: cover; border-radius: 10px; display: block; border: 1px solid var(--border); }
.pf-outcome { color: var(--accent-2); font-size: 0.82rem; font-weight: 600; margin: 4px 0; }
.pf-link { display: inline-block; margin-top: 8px; font-size: 0.83rem; color: var(--accent); font-weight: 600; }
.pf-item .idea-actions { margin-top: 10px; }
.pf-post .platform-pill { font-size: 0.74rem; }
.pf-metric-sm { font-size: 0.76rem; font-weight: 700; color: var(--accent-2); text-align: right; }
.pf-quote p { font-size: 0.9rem; line-height: 1.55; font-style: italic; }
.pf-quote-by { margin-top: 9px; font-size: 0.82rem; }
.pf-case { padding: 18px; margin-bottom: 14px; }
.pf-metric {
  display: inline-block; margin-top: 8px; padding: 4px 12px; border-radius: 99px;
  background: var(--accent-gradient); color: #fff; font-size: 0.8rem; font-weight: 700;
}
.pf-case-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.pf-case-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-weight: 700; }
.pf-case-grid p { font-size: 0.86rem; margin-top: 3px; }
.photo-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.photo-slot {
  width: 84px; height: 84px; border-radius: 50%; overflow: hidden; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 2rem;
  background: var(--bg-card); border: 1px solid var(--border);
}
.photo-slot img { width: 100%; height: 100%; object-fit: cover; }
.skill-tag { display: inline-flex; align-items: center; gap: 6px; }
.skill-x { background: transparent; border: 0; color: inherit; cursor: pointer; opacity: 0.6; font-size: 0.9rem; padding: 0; }
.skill-x:hover { opacity: 1; }

/* ============ AI capability ladder ============ */
.ai-tier { border: 1px solid var(--border); border-radius: 12px; padding: 12px; margin-bottom: 12px; }
.ai-tier.locked { opacity: 0.72; border-style: dashed; }
.ai-tier-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-family: var(--font-display); font-weight: 700; font-size: 0.95rem; }
.ai-tier-blurb { font-size: 0.76rem; color: var(--text-muted); margin: 2px 0 9px; }
.ai-action.locked { cursor: pointer; }
.ai-action.locked:hover { border-color: var(--accent); }

/* Mobile top bar + drawer */
.mobile-bar { display: none; }
@media (max-width: 900px) {
  .app-shell { flex-direction: column; }
  .mobile-bar {
    display: flex; align-items: center; justify-content: space-between;
    padding: 13px 16px; position: sticky; top: 0; z-index: 120;
    background: var(--chrome-bg); border-bottom: 1px solid var(--border);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  }
  .hamburger { background: transparent; border: 1px solid var(--border); color: var(--text-primary); border-radius: 10px; padding: 8px 12px; font-size: 1.05rem; }
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; height: 100dvh;
    transform: translateX(-105%); transition: transform 0.28s ease; width: 270px;
    box-shadow: var(--shadow); z-index: 200;
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 150; }
  .main { padding: 20px 16px 90px; }
  .ce-layout, .ai-layout { grid-template-columns: 1fr; }
  .kanban { display: flex; }
  .kanban-col { min-width: 250px; flex-shrink: 0; }

}

/* ---------------- Post Radar™ ---------------- */
.radar-label {
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 8px;
}
.radar-srcs { display: flex; flex-wrap: wrap; gap: 8px; }
.radar-src {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.82rem; padding: 6px 11px; border-radius: 999px;
  background: var(--bg-card); border: 1px solid var(--border);
  color: var(--text-primary); text-decoration: none;
}
.radar-src:hover { border-color: var(--accent-2); }
/* Dimmed, not hidden: a handle we cannot read is still part of who
   they are, and hiding it would look like we lost it. */
.radar-src.is-dim { opacity: 0.55; border-style: dashed; cursor: default; }

.radar-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.radar-stats .metric { padding: 12px; text-align: center; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); }
.radar-stats .metric .m-value { font-size: 1.35rem; }

.radar-item {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 0.88rem;
}
.radar-item:last-child { border-bottom: none; }
.radar-err { font-size: 0.82rem; color: var(--text-muted); padding: 6px 0; }
.radar-err strong { color: var(--danger); text-transform: capitalize; }

.radar-ideas { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; }
.radar-idea { display: flex; flex-direction: column; }
.radar-idea-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.radar-idea-head h4 { font-size: 0.98rem; margin: 0 0 4px; line-height: 1.35; }
.radar-hook {
  font-size: 0.9rem; font-style: italic; margin: 6px 0 8px; padding-left: 10px;
  border-left: 2px solid var(--accent); color: var(--text-primary);
}
.radar-brief { font-size: 0.86rem; color: var(--text-muted); margin: 0 0 8px; line-height: 1.6; }
.radar-why { font-size: 0.78rem; color: var(--text-muted); margin: 0; }
/* The provenance line is the difference between a suggestion and a
   horoscope, so it is labelled rather than left to be inferred. */
.radar-why span {
  font-family: var(--font-mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-2);
}
.radar-raw {
  white-space: pre-wrap; word-break: break-word; font-family: var(--font-mono);
  font-size: 0.8rem; line-height: 1.6; color: var(--text-muted);
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px; margin: 0;
}

@media (max-width: 720px) {
  .radar-ideas { grid-template-columns: 1fr; }
  .radar-stats { grid-template-columns: repeat(2, 1fr); }

}

.nav-item.is-locked { opacity: 0.62; }

/* Dashboard card + the Rupee Loop view */
.loop-card { border-color: rgba(var(--accent-2-rgb),0.35); }
.loop-big {
  font-family: var(--font-display); font-weight: 700; font-size: clamp(1.9rem, 5vw, 2.6rem);
  letter-spacing: -0.03em; line-height: 1.05; margin-top: 4px;
  background: var(--accent-gradient); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.loop-top, .loop-ask {
  border-top: 1px solid var(--border); padding-top: 12px;
}
.loop-ask { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.loop-row { padding: 11px 0; border-bottom: 1px solid var(--border); }
.loop-row:last-child { border-bottom: none; }
.loop-row-head { display: flex; justify-content: space-between; gap: 12px; font-size: 0.88rem; align-items: baseline; }
.loop-bar { height: 6px; background: var(--track); border-radius: 999px; overflow: hidden; margin: 7px 0 5px; }
.loop-bar .fill { height: 100%; background: var(--accent-gradient); border-radius: 999px; }

/* Attribution picker */
.loop-src-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.loop-src {
  text-align: left; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px; display: flex; flex-direction: column; gap: 3px; min-height: 84px; color: var(--text-primary);
}
.loop-src:hover, .loop-src.active { border-color: var(--accent); background: rgba(var(--accent-rgb),0.1); }
.loop-src .ls-icon { font-size: 1.1rem; }
.loop-src .ls-name { font-weight: 600; font-size: 0.86rem; }
.loop-src .ls-hint { color: var(--text-muted); font-size: 0.74rem; line-height: 1.4; }

/* Deal card additions */
.deal-card .d-src {
  margin-top: 7px; font-size: 0.75rem; color: var(--accent-2);
  border-top: 1px dashed var(--border); padding-top: 6px;
}
.deal-card .d-paid { margin-top: 5px; font-size: 0.75rem; color: var(--success); font-weight: 600; }

/* Deal Radar */
.dr-questions {
  margin-top: 12px; padding: 11px 13px; border-radius: 10px;
  background: rgba(var(--warning-rgb),0.08); border: 1px solid rgba(var(--warning-rgb),0.3);
}
.dr-questions ul { margin: 6px 0 0; padding-left: 18px; }
.dr-questions li { font-size: 0.84rem; line-height: 1.5; margin-bottom: 3px; }

/* Client Link */
.cl-url { border-top: 1px solid var(--border); padding-top: 12px; }
.link-btn {
  background: none; border: none; padding: 0; color: var(--accent-2);
  font: inherit; font-size: 0.76rem; text-decoration: underline; cursor: pointer;
}

/* ---------- Deals & Earnings ----------
   The money strip: four numbers in one row, at the top of the merged
   deals view. Lighter than .metric cards on purpose — this is a
   readout above the working surface, not the point of the screen. */
.money-strip {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--border); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden; margin-bottom: 16px;
}
.ms-item { background: var(--bg-card, #fff); padding: 14px 16px; display: flex; flex-direction: column; gap: 3px; }
.ms-label { color: var(--text-muted); font-size: 0.72rem; letter-spacing: 0.07em; text-transform: uppercase; }
.ms-value { font-size: 1.3rem; font-weight: 700; line-height: 1.15; }
.ms-sub { color: var(--text-muted); font-size: 0.75rem; }
/* The one number no competitor can show gets the accent. */
.ms-hero { background: rgba(var(--accent-2-rgb),0.06); }
.ms-hero .ms-value { color: var(--accent-2); }

.deal-nag {
  border: 1px solid var(--warning, #f59e0b); border-radius: var(--radius);
  background: rgba(245,158,11,0.07); padding: 10px 14px;
  font-size: 0.85rem; margin-bottom: 16px;
}

/* Section headings inside a view that holds more than one thing. */
.view-sub { margin: 26px 0 12px; }
.view-sub h3 { font-size: 1.05rem; }
.view-sub p { font-size: 0.83rem; margin-top: 3px; }

@media (max-width: 720px) {
  .money-strip { grid-template-columns: 1fr 1fr; }
  .ms-value { font-size: 1.1rem; }

}

/* ---------- Connected accounts (OAuth) ---------- */
.conn-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.conn-row { padding: 14px; }
.conn-head { display: flex; gap: 11px; align-items: flex-start; }
.conn-avatar {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  object-fit: cover; border: 1px solid var(--border);
}
.conn-blank {
  display: grid; place-items: center; background: var(--bg-card);
  color: var(--text-muted); font-weight: 700; font-size: 0.95rem;
}
/* What the connection can actually do, stated before the click. */
.conn-note { color: var(--text-muted); font-size: 0.76rem; line-height: 1.45; margin-top: 9px; }

/* ============================================================
   LIGHT-GROUND COMPONENT RULES
   ============================================================
   These used to be scoped to #landing, because the landing was the only
   light surface in the product. It no longer is — :root is light — so
   they are unscoped and every one of them now also fixes the component
   where it appears inside #app and inside a modal.

   They are the rules that a token swap alone cannot express: a glass
   blur that has nothing to blur on an opaque white card, a 1px ring too
   faint to see on white, an outline button that needs a fill because
   "transparent" on paper is invisible.
   ============================================================ */

/* Cards are opaque on light, so the glass blur only costs paint time.
   The elevation that the blur used to imply comes from a two-stop
   shadow instead: a tight contact shadow plus a wide soft one. */
.card,
.loop-step { backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: 0 1px 2px rgba(23,23,46,0.04), 0 8px 24px rgba(23,23,46,0.05); }

.badge {
  background: rgba(var(--accent-rgb), 0.08);
  border-color: rgba(var(--accent-rgb), 0.22);
}

/* On white, a 1px violet ring is too faint to mark the popular plan. */
.price-card.popular {
  box-shadow: 0 0 0 2px var(--accent), 0 16px 44px rgba(var(--accent-rgb), 0.16);
}

/* An outline button on paper needs a fill — "transparent" on a white
   ground reads as no button at all, which is how the app's secondary
   actions disappeared the moment the ground went light. */
.btn-ghost { background: #ffffff; border-color: #d9d9e6; }
.btn-ghost:hover { border-color: var(--accent); background: #faf7ff; }

/* The violet glow under a filled button was tuned to bloom against
   obsidian; at that strength on paper it reads as a smudge. */
.btn-primary { box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.26); }
.btn-primary:hover { box-shadow: 0 12px 32px rgba(var(--accent-rgb), 0.38); }

/* The footer is a sibling of both #landing and #app, so it is themed
   plainly rather than by nesting under either. */
.legal-foot { color: #55556b; border-top: 1px solid #e5e5ef; }
.legal-foot a { color: #55556b; }
.legal-foot a:hover { color: #15151f; }

/* Objection handling. <details> so the answers are in the DOM for
   crawlers on first paint, not injected later by script. */
.faq { max-width: 760px; margin: 26px auto 0; display: flex; flex-direction: column; gap: 10px; }
.faq details {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 15px 18px;
}
.faq summary {
  cursor: pointer; font-weight: 600; font-size: 0.94rem; list-style: none;
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 1.25rem; font-weight: 400; line-height: 1; }
.faq details[open] summary::after { content: "\2212"; }
.faq details p { color: var(--text-muted); font-size: 0.89rem; line-height: 1.62; margin-top: 11px; }

/* Skip link — keyboard users should not have to tab the whole nav. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--accent); color: #fff; padding: 10px 16px; border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; }

/* ---------- cursor spotlight on cards ----------
   landing-fx.js writes --mx/--my as percentages of the card box on
   mousemove; the gradient below is the only thing that reads them, so
   a pointer-less device simply never lights it up. */
#landing .card,
#landing .loop-step {
  position: relative;
  isolation: isolate;
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.28s ease,
              border-color 0.28s ease;
}
#landing .card::before,
#landing .loop-step::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    340px circle at var(--mx, 50%) var(--my, 0%),
    rgba(var(--accent-rgb), 0.10),
    rgba(var(--accent-2-rgb), 0.06) 40%,
    transparent 68%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  z-index: -1;
}
#landing .card:hover::before,
#landing .loop-step:hover::before { opacity: 1; }

#landing .card:hover,
#landing .loop-step:hover {
  transform: translateY(-6px);
  border-color: rgba(var(--accent-rgb), 0.35);
  box-shadow: 0 2px 6px rgba(23, 23, 46, 0.05),
              0 18px 44px rgba(23, 23, 46, 0.11);
}

/* ---------- buttons ---------- */
#landing .btn { position: relative; overflow: hidden; }
/* A light sweep that crosses once per hover. Transform-only, so it
   costs nothing but a composite. */
#landing .btn-primary::after {
  content: "";
  position: absolute; top: 0; left: 0; width: 45%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,0.38), transparent);
  transform: translateX(-180%) skewX(-18deg);
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
#landing .btn-primary:hover::after { transform: translateX(320%) skewX(-18deg); }
#landing .btn-primary:hover { box-shadow: 0 12px 32px rgba(var(--accent-rgb), 0.38); }
@keyframes gradPan {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

#landing .badge { transition: transform 0.25s ease, box-shadow 0.25s ease; }
#landing .badge:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(var(--accent-rgb), 0.18); }

/* ---------- pricing ---------- */
#landing .price-card { transition: transform 0.28s cubic-bezier(0.22,1,0.36,1), box-shadow 0.28s ease; }
#landing .price-card:hover { transform: translateY(-8px); }
#landing .price-card.popular { animation: popFloat 6s ease-in-out infinite; }
#landing .price-card.popular:hover { animation-play-state: paused; }
@keyframes popFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-7px); }
}
#landing .popular-tag { animation: tagGlow 3.4s ease-in-out infinite; }
@keyframes tagGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.35); }
  50%      { box-shadow: 0 0 0 7px rgba(var(--accent-rgb), 0); }
}

/* ---------- FAQ ----------
   Animating height needs a fixed end value; grid-template-rows 0fr -> 1fr
   animates to "whatever this content is", so the answers can change
   length without anyone re-measuring anything. */
#landing .faq details { transition: border-color 0.25s ease, box-shadow 0.25s ease; }
#landing .faq details:hover { border-color: rgba(var(--accent-rgb), 0.32); box-shadow: 0 8px 26px rgba(23,23,46,0.06); }
#landing .faq details[open] { border-color: rgba(var(--accent-rgb), 0.30); }
#landing .faq summary::after { transition: transform 0.25s ease, color 0.25s ease; }
#landing .faq details[open] summary::after { transform: rotate(180deg); }
#landing .faq .faq-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.32s cubic-bezier(0.22,1,0.36,1); }
#landing .faq details[open] .faq-body { grid-template-rows: 1fr; }
#landing .faq .faq-body > div { overflow: hidden; }
@keyframes ctaSpin { to { transform: rotate(360deg); } }

/* ---------- links ---------- */
#landing a:not(.btn) { position: relative; }
#landing .legal-foot a::after,
body:has(#landing:not(.hidden)) .legal-foot a::after {
  content: ""; position: absolute; left: 0; bottom: -2px; width: 100%; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: 100% 50%;
  transition: transform 0.28s cubic-bezier(0.22,1,0.36,1);
}
body:has(#landing:not(.hidden)) .legal-foot a:hover::after { transform: scaleX(1); transform-origin: 0 50%; }
body:has(#landing:not(.hidden)) .legal-foot a:hover { text-decoration: none; }

/* ---------- reduced motion ----------
   Entrances resolve instantly and every ambient loop stops. Hover
   colour feedback is kept: it responds to intent rather than moving on
   its own, which is the distinction the media query is actually about. */
@media (prefers-reduced-motion: reduce) {
  #landing .hero::before,
  #landing .hero h1 .grad,
  #landing .price-card.popular,
  #landing .popular-tag,
  #landing .final-cta::before { animation: none; }
  #landing .card:hover,
  #landing .loop-step:hover,
  #landing .price-card:hover,
  #landing .feature-card:hover,
  #landing .trust-item:hover { transform: none; }
  #landing .btn-primary::after { display: none; }
  #landing .faq .faq-body { transition: none; }

}

/* ---------- shimmer: every button on the landing ----------
   A highlight that crosses the button on a loop, so the primary action
   reads as live rather than as another piece of chrome. Distinct from
   the .btn-primary sweep above, which fires once per hover -- this one
   runs on its own and is what draws the eye before anything is hovered.

   Deliberately a HIGHLIGHT, not an overlay: a positioned pseudo-element
   paints above the button's inline text, so the gradient stays at a low
   alpha and the label reads straight through it. Raising the alpha to
   make it more obvious is what turns it into a smear across the words. */
#landing .btn,
#landing .shimmer { position: relative; overflow: hidden; }

/* The exclusions matter more than the rule itself. A modal's close
   control and a destructive action are not things to draw the eye
   toward, and a disabled button that shimmers is advertising
   something it will refuse to do when clicked. */
#landing .modal-close::before,
#landing .btn-danger::before,
#landing .btn:disabled::before { content: none; }
#landing .btn::before,
#landing .shimmer::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0; width: 55%;
  transform: translateX(-160%) skewX(-18deg);
  animation: btnShimmer 3.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  pointer-events: none;
}
/* Filled button: a white highlight on the violet-to-cyan gradient. */
#landing .btn-primary::before {
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.42), transparent);
}
/* Outline button sits on white, where a white highlight is invisible, so
   this one tints toward the brand violet instead. */
#landing .btn-ghost::before {
  background: linear-gradient(100deg, transparent, rgba(var(--accent-rgb), 0.16), transparent);
}
/* Offset so the two do not sweep in lockstep, which reads as one wide
   band crossing the pair rather than two separate buttons. */
/* Stagger, so a row of buttons does not pulse as one wide band
   crossing the whole page. Outline buttons trail the filled one
   beside them, and each block starts a little after the one above. */
#landing .btn-ghost::before            { animation-delay: 0.55s; }
#landing .price-card .btn::before       { animation-delay: 0.9s; }
#landing .price-card.popular .btn::before { animation-delay: 0.3s; }

@keyframes btnShimmer {
  0%   { transform: translateX(-160%) skewX(-18deg); }
  /* The pause is the point: sweep, then rest. A continuous loop with no
     gap reads as a loading skeleton, which is the opposite of "ready". */
  55%  { transform: translateX(320%)  skewX(-18deg); }
  100% { transform: translateX(320%)  skewX(-18deg); }
}

/* Hovering is intent: stop the ambient loop so the hover sweep already
   defined for .btn-primary is the only thing moving. */
#landing .btn:hover::before,
#landing .shimmer:hover::before { animation-play-state: paused; opacity: 0; }

.nav-auth { display: flex; align-items: center; gap: 8px; }
@media (max-width: 420px) {
  .nav-auth { gap: 6px; }
  #landing .nav-auth .btn-sm { padding: 8px 11px; font-size: 0.8rem; }

}

@media (prefers-reduced-motion: reduce) {
  #landing .btn::before,
  #landing .shimmer::before { animation: none; opacity: 0; }

}

/* The [hidden] attribute works through the UA stylesheet's display:none,
   which ANY author rule with a display beats on specificity -- and .btn
   sets display:inline-flex. So hiding a button with `hidden` silently
   does nothing, which is how "Open App" shipped visible next to Sign up
   while its attribute said otherwise. Restore the guarantee. */
#landing [hidden] { display: none !important; }

/* ============================================================
   AUTH SURFACES
   ============================================================
   The account modal and the sign-in wall are the hinge between the
   marketing page and the app, and they are the two screens a visitor
   judges the product on before they have any of it. They now open with
   the same lockup the landing nav and the sidebar use, so the name does
   not change on the way in — see Auth.brandHead() in shared/auth.js.
   ============================================================ */

.auth-logo {
  font-size: 1.05rem;
  /* Optically aligned with the title below rather than the ✕ beside it:
     the close button carries its own padding, and matching that would
     push the wordmark off the modal's own left margin. */
  margin-bottom: 2px;
}

.auth-title {
  font-size: 1.25rem;
  margin-bottom: 6px;
}

/* The modal sits on --bg-secondary, one step down from the page. On
   paper that is too close to the ground behind it to read as a raised
   panel, so it takes the card white and leans on the shadow instead. */
.modal { background: var(--bg-card); }

/* A white input on a white panel needs its well drawn by something
   other than fill. The inset keeps the field readable as a field
   without adding a second border weight. */
.field input, .field textarea, .field select, .input {
  box-shadow: inset 0 1px 2px rgba(23, 23, 46, 0.05);
}
.field input:focus, .field textarea:focus, .field select:focus, .input:focus {
  box-shadow: inset 0 1px 2px rgba(23, 23, 46, 0.05), 0 0 0 3px rgba(var(--accent-rgb), 0.14);
}

/* ============================================================
   AI ANSWERS, SHOWN WHERE THEY WERE ASKED FOR
   ============================================================
   A rewrite returns five options and used to render them as prose in
   the chat log. As a list of buttons the same answer becomes usable:
   one click puts a line in the field instead of a select-and-paste
   round trip through another screen. See AIBrand.offer().
   ============================================================ */

.ai-lead { font-size: 0.85rem; margin-bottom: 14px; line-height: 1.5; }

.ai-picks { display: flex; flex-direction: column; gap: 8px; }

.ai-pick {
  display: flex; align-items: flex-start; gap: 11px; width: 100%;
  padding: 12px 14px; text-align: left;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 12px; color: var(--text-primary);
  font: inherit; font-size: 0.92rem; line-height: 1.45;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
}
.ai-pick:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.05);
  transform: translateY(-1px);
}
.ai-pick:active { transform: none; }

/* The number is the model's own ordering, kept so "I'd pick #2" in the
   note below still points at something. */
.ai-pick-n {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(var(--accent-rgb), 0.10); color: var(--accent);
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  margin-top: 1px;
}
.ai-pick-t { flex: 1; min-width: 0; }

.ai-pick-note {
  font-size: 0.82rem; line-height: 1.5; margin-top: 12px;
  padding-left: 2px; font-style: italic;
}

/* An answer that is prose rather than a list — kept scrollable so a
   long post cannot push the buttons under the fold. */
.ai-answer {
  white-space: pre-wrap; font-size: 0.9rem; line-height: 1.6;
  max-height: 46vh; overflow-y: auto;
  padding: 14px 16px; border-radius: 12px;
  background: var(--surface-sunken); border: 1px solid var(--border);
}

/* Said plainly, every time: an offline answer that looks like a real
   one is how "the AI wrote this" quietly stops being true. */
.ai-offline {
  font-size: 0.82rem; line-height: 1.5; margin-bottom: 12px;
  padding: 10px 12px; border-radius: 10px;
  background: rgba(var(--warning-rgb), 0.10);
  border: 1px solid rgba(var(--warning-rgb), 0.30);
  color: var(--text-primary);
}
