/* CullyAI Web — shared design system.
   Monochrome, Trade-Republic-esque: black/white, huge confident type,
   generous whitespace, quiet spring-eased motion, borderless glass
   surfaces. Poppins only. Light/dark theme via [data-theme] on <html>,
   same pattern as croploo/website. */

@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap');

/* "System" appearance (no explicit [data-theme] override, see theme.js) —
   dark is the bare :root default below, this is the light-mode fallback
   for whenever the OS itself prefers light and the user hasn't chosen an
   explicit override. Both this and the bare :root sit *before* the
   explicit [data-theme="…"] blocks further down so an explicit choice
   always wins on equal specificity (last one in source order does). */
/* Dark is the bare :root default — covers "system, no override, and the
   OS is dark (or prefers-color-scheme isn't supported at all)". */
:root {
  --bg: #000000;
  --bg-elevated: #18181a;
  --bg-chat: #111111;
  --surface: #131313;
  --surface-hover: #1c1c1d;
  --glass: rgba(18, 18, 19, 0.6);
  --glass-strong: rgba(24, 24, 26, 0.78);
  --text: #ffffff;
  --text-secondary: #9a9a9d;
  --text-tertiary: #656567;
  --hairline: rgba(255, 255, 255, 0.08);
  --danger: #ff6b6b;
  --success: #3ddc84;
  --btn-primary-bg: #ffffff;
  --btn-primary-text: #000000;
  --scrollbar: rgba(255, 255, 255, 0.14);
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg: #ffffff;
    --bg-elevated: #f7f7f7;
    --bg-chat: #f5f5f5;
    --surface: #f2f2f2;
    --surface-hover: #e9e9e9;
    --glass: rgba(255, 255, 255, 0.62);
    --glass-strong: rgba(255, 255, 255, 0.78);
    --text: #0a0a0a;
    --text-secondary: #57575a;
    --text-tertiary: #8c8c8f;
    --hairline: rgba(0, 0, 0, 0.07);
    --danger: #d33d3d;
    --success: #1f9d5c;
    --btn-primary-bg: #000000;
    --btn-primary-text: #ffffff;
    --scrollbar: rgba(0, 0, 0, 0.14);
  }
}

:root[data-theme="dark"] {
  --bg: #000000;
  /* Was #0b0b0c — barely lighter than pure black, so the sidebar/modals
     that lean on this (and on --glass-strong below) read as just as flat
     black as the page behind them. A clearly distinguishable dark gray
     instead of near-true-black is what makes them read as a separate,
     raised surface — same change made in the iOS app. */
  --bg-elevated: #18181a;
  --bg-chat: #111111;
  --surface: #131313;
  --surface-hover: #1c1c1d;
  --glass: rgba(18, 18, 19, 0.6);
  --glass-strong: rgba(24, 24, 26, 0.78);
  --text: #ffffff;
  --text-secondary: #9a9a9d;
  --text-tertiary: #656567;
  --hairline: rgba(255, 255, 255, 0.08);
  --danger: #ff6b6b;
  --success: #3ddc84;
  --btn-primary-bg: #ffffff;
  --btn-primary-text: #000000;
  --scrollbar: rgba(255, 255, 255, 0.14);
}

:root[data-theme="light"] {
  --bg: #ffffff;
  --bg-elevated: #f7f7f7;
  --bg-chat: #f5f5f5;
  --surface: #f2f2f2;
  --surface-hover: #e9e9e9;
  --glass: rgba(255, 255, 255, 0.62);
  --glass-strong: rgba(255, 255, 255, 0.78);
  --text: #0a0a0a;
  --text-secondary: #57575a;
  --text-tertiary: #8c8c8f;
  --hairline: rgba(0, 0, 0, 0.07);
  --danger: #d33d3d;
  --success: #1f9d5c;
  --btn-primary-bg: #000000;
  --btn-primary-text: #ffffff;
  --scrollbar: rgba(0, 0, 0, 0.14);
}

:root {
  --radius-lg: 28px;
  --radius-md: 18px;
  --radius-sm: 12px;
  --radius-pill: 999px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --container: 1120px;
  /* Settings → Text Size (small/medium/large) multiplies message and
     composer text through this — same idea as the iOS app's
     textSizeOption scale, applied via calc() at each font-size below
     instead of a type-scale swap. */
  --text-scale: 1;
}

* { box-sizing: border-box; }
/* Without this, any element whose class sets its own `display` (`.btn`,
   `.card`, etc.) silently ignores the `hidden` attribute — a class
   selector's `display` beats the UA stylesheet's `[hidden]{display:none}`.
   Found via the free-tier Settings modal: `billing-portal-btn` was set
   `hidden` for free users but kept rendering anyway. `!important` here is
   deliberate — `hidden` should always win over whatever else is styling
   the element. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }
html[data-theme="light"] { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background 300ms var(--ease), color 300ms var(--ease);
}

/* The app shell (app.html) is a fixed-to-viewport layout — the page itself
   must never scroll, only .messages and .conv-list internally, or the
   composer and sidebar bottom would drift out of view as a chat grows. */
body.app-shell {
  height: 100vh; height: 100dvh;
  overflow: hidden;
}

img { max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }

.container { max-width: var(--container); margin: 0 auto; padding: 0 24px; }

/* ---------- Typography ---------- */

h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.02em; line-height: 1.04; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 7px 16px;
  background: var(--surface);
  border-radius: var(--radius-pill);
}

.eyebrow .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 8px var(--success);
}

p.lead {
  font-size: clamp(16px, 2vw, 19px);
  color: var(--text-secondary);
  line-height: 1.6;
  font-weight: 400;
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 28px;
  border-radius: var(--radius-pill);
  font-size: 15px;
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: transform 220ms var(--ease), background 220ms var(--ease), opacity 220ms var(--ease);
  white-space: nowrap;
}
.btn:active { transform: scale(0.965); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

.btn-primary { background: var(--btn-primary-bg); color: var(--btn-primary-text); }
.btn-primary:hover { opacity: 0.88; }

.btn-ghost { background: var(--surface); color: var(--text); }
.btn-ghost:hover { background: var(--surface-hover); }

.btn-outline { background: transparent; color: var(--text); box-shadow: inset 0 0 0 1.5px var(--hairline); }
.btn-outline:hover { background: var(--surface); }

.btn-block { width: 100%; }
.btn-sm { padding: 10px 18px; font-size: 13px; }

.btn-google { background: #ffffff; color: #1f1f1f; box-shadow: 0 1px 2px rgba(0,0,0,0.15); }
.btn-google:hover { background: #f7f7f7; }

/* ---------- Theme toggle (same pattern as croploo/website) ---------- */

.theme-toggle { border: none; background: none; padding: 0; display: flex; align-items: center; cursor: pointer; }
.theme-toggle-track {
  width: 44px; height: 24px;
  background: var(--surface);
  border-radius: var(--radius-pill);
  position: relative;
  display: flex;
  align-items: center;
  padding: 2px;
  transition: background 200ms var(--ease);
}
.theme-toggle-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--text);
  color: var(--bg);
  display: flex; align-items: center; justify-content: center;
  transition: transform 250ms cubic-bezier(0.34, 1.56, 0.64, 1);
  transform: translateX(0);
}
:root[data-theme="light"] .theme-toggle-thumb { transform: translateX(20px); }
.theme-toggle .icon-sun, .theme-toggle .icon-moon { position: absolute; }
:root[data-theme="dark"] .theme-toggle .icon-sun { opacity: 0; }
:root[data-theme="light"] .theme-toggle .icon-moon { opacity: 0; }

/* ---------- Nav — modern, solid background ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 24px;
  background: var(--bg);
  transition: background 300ms var(--ease);
}
.nav.scrolled {
  background: var(--bg);
}

.logo { display: flex; align-items: center; gap: 12px; font-weight: 800; font-size: 21px; letter-spacing: -0.01em; }
.logo .mark { height: 56px; width: auto; }

/* Logo light/dark swap — applies to any ".mark" wherever it appears (nav,
   auth cards, footer, sidebar), not just inside .logo: dark mode shows the
   white leaf, light mode shows the black leaf. */
.mark.icon-dark { display: none; }
:root[data-theme="light"] .mark.icon-light { display: none; }
:root[data-theme="light"] .mark.icon-dark { display: block; }

.nav-links { display: flex; align-items: center; gap: 14px; }

/* ---------- Hero ---------- */

.hero { position: relative; padding: 110px 24px 80px; text-align: center; overflow: hidden; }

.hero-glow {
  position: absolute;
  top: -240px; left: 50%;
  transform: translateX(-50%);
  width: 900px; height: 700px;
  background: radial-gradient(circle, var(--hairline) 0%, rgba(0,0,0,0) 65%);
  pointer-events: none;
}

.hero h1 { font-size: clamp(40px, 7.4vw, 92px); max-width: 920px; margin: 28px auto 22px; }
.hero .lead { max-width: 560px; margin: 0 auto 40px; }
.hero-actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.hero-note { margin-top: 18px; font-size: 13px; color: var(--text-tertiary); }

/* ---------- Reveal-on-scroll — text materializes out of a glass blur,
   and blurs away again if you scroll back up past it (same feel as
   croploo/website's scroll reveal). ---------- */

.reveal {
  opacity: 0;
  transform: translateY(28px);
  filter: blur(10px);
  transition: opacity 800ms var(--ease), transform 800ms var(--ease), filter 800ms var(--ease);
}
.reveal.in { opacity: 1; transform: translateY(0); filter: blur(0); }
.reveal.in.leaving {
  opacity: 0;
  transform: translateY(-24px);
  filter: blur(12px);
  transition: opacity 600ms cubic-bezier(0.4, 0, 1, 1), transform 600ms cubic-bezier(0.4, 0, 1, 1), filter 600ms cubic-bezier(0.4, 0, 1, 1);
}
.reveal-delay-1 { transition-delay: 90ms; }
.reveal-delay-2 { transition-delay: 180ms; }
.reveal-delay-3 { transition-delay: 270ms; }

/* Section headings reveal word-by-word (see the JS that wraps each word
   in .word-reveal), each one settling out of blur on its own beat. */
.section-head h2 .word-reveal {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em) scale(0.94);
  filter: blur(8px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease), filter 600ms var(--ease);
}
.section-head.in h2 .word-reveal { opacity: 1; transform: none; filter: blur(0); }

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.in.leaving, .section-head h2 .word-reveal {
    transition-duration: 0.01ms !important;
    transform: none !important;
    filter: none !important;
  }
}

/* ---------- Sections ---------- */

.section { padding: 100px 24px; }
.section-head { text-align: center; max-width: 640px; margin: 0 auto 56px; }
.section-head h2 { font-size: clamp(30px, 4.4vw, 48px); margin-bottom: 16px; }

/* ---------- Feature grid ---------- */

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 860px) { .grid-3 { grid-template-columns: 1fr; } }

.card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 32px;
  transition: transform 260ms var(--ease), background 260ms var(--ease);
}
.card:hover { background: var(--surface-hover); transform: translateY(-4px); }

.card .icon {
  width: 46px; height: 46px; border-radius: 13px;
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 22px;
}
.card h3 { font-size: 19px; margin-bottom: 10px; }
.card p { color: var(--text-secondary); font-size: 14.5px; line-height: 1.6; margin: 0; }

/* ---------- Pricing ---------- */

.grid-pricing { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: stretch; }
@media (max-width: 900px) { .grid-pricing { grid-template-columns: 1fr; max-width: 420px; margin: 0 auto; } }

.plan {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 36px 30px;
  display: flex;
  flex-direction: column;
  position: relative;
}
.plan.featured { background: var(--btn-primary-bg); color: var(--btn-primary-text); transform: scale(1.035); }
@media (max-width: 900px) { .plan.featured { transform: none; } }

.plan .tag {
  position: absolute; top: -13px; left: 30px;
  background: var(--text); color: var(--bg);
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 6px 14px; border-radius: var(--radius-pill);
}
.plan.featured .tag { background: var(--btn-primary-text); color: var(--btn-primary-bg); }
.plan-name { font-size: 15px; font-weight: 600; color: var(--text-secondary); margin-bottom: 18px; }
.plan.featured .plan-name { color: color-mix(in srgb, var(--btn-primary-text) 55%, transparent); }
.plan-price { font-size: 44px; font-weight: 800; letter-spacing: -0.02em; margin-bottom: 4px; }
.plan-price span { font-size: 16px; font-weight: 500; color: var(--text-secondary); }
.plan.featured .plan-price span { color: color-mix(in srgb, var(--btn-primary-text) 55%, transparent); }
.plan-sub { font-size: 13.5px; color: var(--text-tertiary); margin-bottom: 28px; }
.plan.featured .plan-sub { color: color-mix(in srgb, var(--btn-primary-text) 45%, transparent); }
.plan-features { list-style: none; padding: 0; margin: 0 0 32px; flex: 1; }
.plan-features li { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; color: var(--text-secondary); padding: 8px 0; }
.plan.featured .plan-features li { color: color-mix(in srgb, var(--btn-primary-text) 75%, transparent); }
.plan .btn { width: 100%; }
.plan.featured .btn-primary { background: var(--btn-primary-text); color: var(--btn-primary-bg); }

/* ---------- Footer ---------- */

.footer {
  padding: 48px 24px;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 16px;
  color: var(--text-tertiary); font-size: 13px;
}
.footer-links { display: flex; gap: 22px; flex-wrap: wrap; }

/* ---------- Auth pages ---------- */

.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 40px 20px; position: relative; }
.auth-theme-toggle { position: absolute; top: 24px; right: 24px; }
.auth-card { width: 100%; max-width: 400px; background: var(--surface); border-radius: var(--radius-lg); padding: 40px 34px; }
.auth-logo { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 34px; font-weight: 800; font-size: 22px; }
.auth-logo .mark { height: 64px; width: auto; }
.auth-card h1 { font-size: 24px; text-align: center; margin-bottom: 8px; }
.auth-card .sub { text-align: center; color: var(--text-secondary); font-size: 13.5px; margin-bottom: 28px; }

.field { margin-bottom: 16px; }
.field label { display: block; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); margin-bottom: 7px; }
.field input {
  width: 100%;
  padding: 13px 16px;
  border-radius: var(--radius-sm);
  border: none;
  background: var(--bg-elevated);
  color: var(--text);
  font-family: inherit;
  font-size: 14.5px;
  outline: none;
  box-shadow: inset 0 0 0 1.5px transparent;
  transition: box-shadow 200ms var(--ease);
}
.field input:focus { box-shadow: inset 0 0 0 1.5px var(--text); }
.field input.code-input { text-align: center; letter-spacing: 0.5em; font-size: 22px; font-weight: 600; }

.divider { display: flex; align-items: center; gap: 14px; margin: 22px 0; color: var(--text-tertiary); font-size: 12.5px; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }

.auth-foot { text-align: center; margin-top: 22px; font-size: 13.5px; color: var(--text-secondary); }
.auth-foot a { color: var(--text); font-weight: 600; }

.form-error {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger);
  font-size: 13px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  margin-bottom: 16px;
  display: none;
}
.form-error.show { display: block; }
.form-note {
  background: var(--bg-elevated);
  color: var(--text-secondary);
  font-size: 13px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  margin-bottom: 16px;
}

.spinner {
  width: 16px; height: 16px;
  border: 2px solid color-mix(in srgb, var(--btn-primary-text) 25%, transparent);
  border-top-color: var(--btn-primary-text);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Billing success (billing.html) ---------- */
/* Same checkmark-pop-plus-ring-pulse flourish as the iOS app's own
   post-checkout screen — this used to be a plain static icon with no
   entrance at all, which read as unfinished next to everything else that
   animates in this app. CSS @keyframes autoplay the instant this markup is
   inserted, no class-toggle trick needed like a transition would. */
.success-check-wrap { position: relative; width: 56px; height: 56px; margin: 0 auto 22px; }
.success-ring {
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 2px solid var(--btn-primary-bg);
  animation: success-ring-pulse 900ms ease-out 260ms both;
}
.success-check {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
  display: flex; align-items: center; justify-content: center;
  animation: success-check-pop 520ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes success-check-pop {
  0% { transform: scale(0.4); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes success-ring-pulse {
  0% { transform: scale(1); opacity: 0.6; }
  100% { transform: scale(1.6); opacity: 0; }
}
.success-fade-in {
  animation: success-fade-up 500ms var(--ease) 220ms both;
}
@keyframes success-fade-up {
  0% { opacity: 0; transform: translateY(8px); }
  100% { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .success-ring, .success-check, .success-fade-in { animation: none; }
}

/* ---------- App shell ---------- */

.app {
  display: grid; grid-template-columns: 280px 1fr; height: 100vh; height: 100dvh;
  opacity: 0; filter: blur(10px);
  transition: opacity 600ms var(--ease), filter 600ms var(--ease);
}
.app.in { opacity: 1; filter: blur(0); }
@media (max-width: 820px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; width: 280px; z-index: 60;
    transform: translateX(-100%);
    transition: transform 260ms var(--ease);
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-scrim { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 55; }
  .sidebar-scrim.show { display: block; }
}

.sidebar {
  background: var(--bg);
  display: flex; flex-direction: column;
  padding: 18px 14px;
  /* Caps the sidebar to exactly the grid row's height (the screen) instead
     of growing to fit a long conversation list — .conv-list scrolls
     internally instead, top/bottom stay put. */
  height: 100%;
  overflow: hidden;
}
/* Extra top padding — was 6px, read as cramped right under the window's
   own chrome; 18px matches the bottom padding instead of being lopsided. */
.sidebar-top { display: flex; align-items: center; justify-content: space-between; padding: 18px 6px 18px; flex-shrink: 0; }
.sidebar-top-actions { display: flex; align-items: center; gap: 10px; }

.icon-round-btn {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); border: none; color: var(--text);
  cursor: pointer; transition: background 200ms var(--ease);
}
.icon-round-btn:hover { background: var(--surface-hover); }

/* The sort menu — same popover pattern as .account-menu (absolute, toggled
   by a .open class on the wrapper, closed on outside click). */
.sort-menu-wrap { position: relative; }
.sort-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 20;
  min-width: 170px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  padding: 6px;
  display: none;
  flex-direction: column;
  gap: 2px;
}
.sort-menu-wrap.open .sort-menu { display: flex; }
.sort-menu button {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 9px 10px;
  border-radius: var(--radius-sm);
  background: transparent; border: none;
  color: var(--text); font-size: 13px; font-family: inherit;
  cursor: pointer; text-align: left;
  transition: background 160ms var(--ease);
}
.sort-menu button:hover { background: var(--surface); }
.sort-menu button.active { color: var(--text); font-weight: 600; }
.sort-menu button.active::after { content: "✓"; }

/* The Chats/Projects tab row — same visual language as the iOS nav row:
   a pill that slides its "active" fill under whichever label is selected. */
.sidebar-tabs { display: flex; gap: 2px; padding: 2px; margin-bottom: 10px; flex-shrink: 0; }
.sidebar-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  background: transparent; border: none;
  color: var(--text-secondary); font-size: 13.5px; font-weight: 600; font-family: inherit;
  cursor: pointer;
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
.sidebar-tab:hover { color: var(--text); }
.sidebar-tab.active { background: var(--surface); color: var(--text); }

.list-section-label {
  padding: 12px 12px 6px;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.list-section-label:first-child { padding-top: 4px; }

.project-back {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 12px; margin-bottom: 2px;
  border-radius: var(--radius-sm);
  background: transparent; border: none;
  color: var(--text-secondary); font-size: 12.5px; font-weight: 600; font-family: inherit;
  cursor: pointer; width: 100%; text-align: left;
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
.project-back:hover { background: var(--surface); color: var(--text); }

.project-item {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text);
  font-size: 13.5px;
  transition: background 160ms var(--ease);
}
.project-item:hover { background: var(--surface); }
.project-item .project-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-item .project-icon { flex-shrink: 0; color: var(--text-secondary); }
.project-item .project-chevron { flex-shrink: 0; color: var(--text-tertiary); }
.project-item .conv-pin, .project-item .conv-del {
  opacity: 0; width: 22px; height: 22px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 6px; color: var(--text-tertiary);
}
.project-item:hover .conv-pin, .project-item:hover .conv-del { opacity: 1; }
.project-item .conv-pin:hover, .project-item .conv-del:hover { background: var(--surface-hover); color: var(--text); }
.project-item .conv-pin.pinned { opacity: 1; color: var(--text); }

.new-chat-btn {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; margin-bottom: 12px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: none;
  color: var(--text);
  font-size: 14px; font-weight: 600;
  cursor: pointer;
  transition: background 200ms var(--ease);
}
.new-chat-btn:hover { background: var(--surface-hover); }

.conv-list { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }

.group-section { margin-bottom: 4px; }
.group-header {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px 9px 8px;
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 12.5px; font-weight: 600;
  border-radius: var(--radius-sm);
}
.group-header:hover { background: var(--surface); color: var(--text); }
.group-header .chevron { flex-shrink: 0; transition: transform 200ms var(--ease); color: var(--text-tertiary); }
.group-header.collapsed .chevron { transform: rotate(-90deg); }
.group-header .group-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-header .group-del {
  opacity: 0; width: 20px; height: 20px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 6px; color: var(--text-tertiary);
}
.group-header:hover .group-del { opacity: 1; }
.group-header .group-del:hover { background: var(--surface-hover); color: var(--text); }
.group-conv-list { display: flex; flex-direction: column; gap: 2px; padding-left: 14px; }
.group-conv-list.collapsed { display: none; }

.conv-item {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 13.5px;
  position: relative;
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
.conv-item:hover { background: var(--surface); color: var(--text); }
.conv-item.active { background: var(--surface); color: var(--text); }
.conv-item .conv-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-item .conv-pin, .conv-item .conv-move, .conv-item .conv-del {
  opacity: 0; width: 22px; height: 22px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 6px; color: var(--text-tertiary);
  position: relative;
}
.conv-item:hover .conv-pin, .conv-item:hover .conv-move, .conv-item:hover .conv-del { opacity: 1; }
.conv-item .conv-pin:hover, .conv-item .conv-move:hover, .conv-item .conv-del:hover { background: var(--surface-hover); color: var(--text); }
.conv-item .conv-pin.pinned { opacity: 1; color: var(--text); }
.conv-item .conv-move select {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: none;
}

.sidebar-bottom { padding-top: 14px; margin-top: 10px; flex-shrink: 0; display: flex; flex-direction: column; }

.usage-box { padding: 4px 6px 14px; }
.usage-row { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-secondary); margin-bottom: 8px; }
.usage-bar { height: 5px; border-radius: var(--radius-pill); background: var(--surface); overflow: hidden; margin-bottom: 12px; }
.usage-bar-fill { height: 100%; background: var(--text); border-radius: var(--radius-pill); transition: width 400ms var(--ease); }

.account { position: relative; }
.user-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px; border-radius: var(--radius-sm); cursor: pointer; }
.user-row:hover { background: var(--surface); }
.avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; flex-shrink: 0;
}
.user-row .who { flex: 1; min-width: 0; overflow: hidden; }
.user-row .who .name { font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Deliberately not ".plan" — that class already names the big pricing
   cards; reusing it here made this tiny badge inherit their padding/card
   styling (a real bug, not a metaphor). */
.user-row .who .user-plan-badge { font-size: 11.5px; color: var(--text-tertiary); text-transform: capitalize; }
.user-row .chevron { flex-shrink: 0; color: var(--text-tertiary); transition: transform 200ms var(--ease); }
.account.open .user-row .chevron { transform: rotate(180deg); }

.account-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0; right: 0;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  padding: 6px;
  display: none;
  flex-direction: column;
  gap: 2px;
}
.account.open .account-menu { display: flex; }
.account-menu button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: transparent; border: none;
  color: var(--text); font-size: 13.5px; font-family: inherit;
  cursor: pointer; text-align: left;
  transition: background 160ms var(--ease);
}
.account-menu button:hover { background: var(--surface); }
.account-menu button.danger { color: var(--danger); }

/* ---------- Chat main ---------- */

.chat-main { display: flex; flex-direction: column; height: 100%; min-width: 0; position: relative; overflow: hidden; background: var(--bg-chat); }

/* ---------- Drag-and-drop file overlay ---------- */

.dropzone-overlay {
  position: absolute; inset: 0; z-index: 40;
  display: none; align-items: center; justify-content: center;
  background: var(--bg-elevated);
  opacity: 0;
  transition: opacity 200ms var(--ease);
}
.dropzone-overlay.show { display: flex; }
.dropzone-overlay.in { opacity: 1; }
.dropzone-card {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 44px 56px;
  border-radius: var(--radius-lg);
  box-shadow: inset 0 0 0 2px var(--text);
  transform: scale(0.92);
  transition: transform 200ms var(--ease);
}
.dropzone-overlay.in .dropzone-card { transform: scale(1); }
.dropzone-card .dropzone-icon {
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
  display: flex; align-items: center; justify-content: center;
  animation: dropzone-bounce 1.4s ease-in-out infinite;
}
@keyframes dropzone-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
.dropzone-card .dropzone-text { font-size: 16px; font-weight: 600; color: var(--text); }
.dropzone-card .dropzone-sub { font-size: 13px; color: var(--text-secondary); }

.chat-topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 22px;
  background: var(--bg-chat);
  position: sticky; top: 0; z-index: 10;
  flex-shrink: 0;
}
.chat-topbar .menu-btn { display: none; }
@media (max-width: 820px) { .chat-topbar .menu-btn { display: flex; } }
.chat-topbar .conv-title-input {
  flex: 1; background: transparent; border: none; color: var(--text);
  font-size: 15px; font-weight: 600; font-family: inherit; outline: none;
  padding: 6px 8px; border-radius: 8px;
}
.chat-topbar .conv-title-input:focus { background: var(--surface); }

.icon-btn {
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none; color: var(--text-secondary);
  cursor: pointer; transition: background 160ms var(--ease), color 160ms var(--ease);
}
.icon-btn:hover { background: var(--surface); color: var(--text); }

/* min-height: 0 is load-bearing here — without it, a flex child in a
   column layout refuses to shrink below its content's natural height, so
   the whole page (not just this box) grows and scrolls instead of the
   message list scrolling internally with the composer pinned below it. */
.messages { flex: 1; min-height: 0; overflow-y: auto; padding: 32px 22px 12px; display: flex; flex-direction: column; gap: 26px; }
.messages-inner { max-width: 760px; width: 100%; margin: 0 auto; display: flex; flex-direction: column; gap: 26px; }

.msg {
  display: flex; gap: 14px; max-width: 100%;
  opacity: 0; transform: translateY(10px); filter: blur(6px);
  transition: opacity 500ms var(--ease), transform 500ms var(--ease), filter 500ms var(--ease);
}
.msg.in { opacity: 1; transform: translateY(0); filter: blur(0); }
.msg-avatar {
  width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12px;
}
.msg.user { justify-content: flex-end; }
.msg.user .msg-bubble {
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
  border-radius: 20px 20px 4px 20px;
  padding: 13px 18px;
  max-width: 78%;
  font-size: calc(14.5px * var(--text-scale)); line-height: 1.55;
  white-space: pre-wrap;
}
.msg.assistant .msg-avatar { background: var(--btn-primary-bg); color: var(--btn-primary-text); }
/* Avatar background is always the inverse of the page (white in dark mode,
   black in light mode) — the opposite of the normal logo swap — so the
   leaf icon shown inside it is deliberately the other way round. */
.msg-avatar .icon-light { display: none; }
:root[data-theme="light"] .msg-avatar .icon-dark { display: none; }
:root[data-theme="light"] .msg-avatar .icon-light { display: block; }
/* `flex: 1` — a flex item otherwise only shrink-wraps its content by
   default, so a short reply (or the thinking dots) rendered narrower than
   the column instead of using the width actually available next to the
   avatar, the same fix as the iOS app needed for the same reason. */
.msg.assistant .msg-bubble { flex: 1; min-width: 0; padding-top: 4px; font-size: calc(14.5px * var(--text-scale)); line-height: 1.7; color: var(--text); max-width: 100%; }
.msg-bubble p { margin: 0 0 12px; }
.msg-bubble p:last-child { margin-bottom: 0; }
.msg-bubble ul, .msg-bubble ol { margin: 0 0 12px; padding-left: 22px; }
.msg-bubble strong { font-weight: 700; }
.msg-bubble code { background: var(--surface); padding: 2px 6px; border-radius: 5px; font-size: 13px; }
.msg-bubble h1, .msg-bubble h2, .msg-bubble h3 { margin: 18px 0 10px; font-size: 16px; }
.msg-bubble .table-wrap { overflow-x: auto; margin: 0 0 16px; border-radius: var(--radius-sm); background: var(--surface); }
.msg-bubble table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.msg-bubble th, .msg-bubble td { padding: 9px 14px; text-align: left; white-space: nowrap; }
.msg-bubble th { font-weight: 600; color: var(--text); background: var(--surface-hover); }
.msg-bubble td { color: var(--text-secondary); }
.msg-bubble tbody tr:not(:last-child) td { box-shadow: inset 0 -1px 0 var(--hairline); }

.typing-dots { display: inline-flex; gap: 4px; padding: 8px 0; }
.typing-dots span { width: 6px; height: 6px; border-radius: 50%; background: var(--text-tertiary); animation: bounce 1.1s infinite ease-in-out; }
.typing-dots span:nth-child(2) { animation-delay: 0.15s; }
.typing-dots span:nth-child(3) { animation-delay: 0.3s; }
@keyframes bounce { 0%, 60%, 100% { opacity: 0.35; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-4px); } }

.empty-state { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 20px; }
.empty-state h2 { font-size: clamp(24px, 4vw, 34px); margin-bottom: 12px; }
.empty-state p { color: var(--text-secondary); max-width: 420px; margin-bottom: 30px; }
.suggestions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; max-width: 640px; }
.suggestion-chip {
  background: var(--surface); border-radius: var(--radius-pill);
  padding: 10px 18px; font-size: 13px; color: var(--text-secondary);
  cursor: pointer; transition: all 180ms var(--ease);
}
.suggestion-chip:hover { background: var(--surface-hover); color: var(--text); }

.composer-wrap {
  padding: 14px 22px 22px;
  background: var(--bg-chat);
  flex-shrink: 0;
}
.composer {
  max-width: 760px; margin: 0 auto;
  display: flex; align-items: flex-end; gap: 6px;
  background: var(--surface);
  border-radius: 26px;
  padding: 8px 8px 8px 10px;
  box-shadow: inset 0 0 0 1.5px transparent;
  transition: box-shadow 200ms var(--ease);
}
.composer:focus-within { box-shadow: inset 0 0 0 1.5px var(--text); }
.composer textarea {
  flex: 1; resize: none; border: none; outline: none; background: transparent;
  color: var(--text); font-family: inherit; font-size: calc(14.5px * var(--text-scale)); line-height: 1.5;
  max-height: 200px; padding: 10px 0;
}
.composer textarea::placeholder { color: var(--text-tertiary); }
.composer-icon-btn {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  background: transparent; color: var(--text-secondary); border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 180ms var(--ease), color 180ms var(--ease);
}
.composer-icon-btn:hover { background: var(--surface-hover); color: var(--text); }
.composer-icon-btn.recording { background: var(--danger); color: #fff; animation: pulse-rec 1.2s infinite; }
@keyframes pulse-rec { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
.send-btn {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  background: var(--btn-primary-bg); color: var(--btn-primary-text); border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: transform 180ms var(--ease), opacity 180ms var(--ease);
}
.send-btn:disabled { opacity: 0.3; cursor: not-allowed; }
.send-btn:not(:disabled):active { transform: scale(0.9); }
.composer-note { text-align: center; font-size: 11.5px; color: var(--text-tertiary); margin-top: 10px; }

.attachment-preview {
  max-width: 760px; margin: 0 auto 8px;
  display: none; align-items: center; gap: 10px;
  background: var(--surface); border-radius: var(--radius-md);
  padding: 8px 12px;
}
.attachment-preview.show { display: flex; }
.attachment-preview .thumb {
  width: 36px; height: 36px; border-radius: 8px; object-fit: cover; flex-shrink: 0;
  background: var(--bg-elevated);
}
.attachment-preview .file-icon {
  width: 36px; height: 36px; border-radius: 8px; flex-shrink: 0;
  background: var(--bg-elevated); color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center;
}
.attachment-preview .name { flex: 1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attachment-preview .remove-attachment {
  width: 24px; height: 24px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none; color: var(--text-tertiary); cursor: pointer;
}
.attachment-preview .remove-attachment:hover { background: var(--surface-hover); color: var(--text); }

/* ---------- Chart / export blocks inside an assistant reply ---------- */

.chart-block {
  background: var(--surface); border-radius: var(--radius-lg);
  padding: 18px 18px 14px; margin: 14px 0;
  width: 100%;
}
.chart-block .chart-title { font-size: 14px; font-weight: 600; margin-bottom: 12px; color: var(--text); }
/* Chart.js's responsive resize needs its canvas's immediate parent to have
   an explicit height and `position: relative` — without both, it can't
   measure what to resize the canvas to and silently leaves it at the
   browser's built-in 300x150 default instead of filling the card. */
.chart-canvas-wrap { position: relative; height: 220px; width: 100%; }
.chart-block canvas { max-width: 100%; }
.chart-legend { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 12px; }
.chart-legend-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; color: var(--text-secondary); }
.chart-legend-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.export-block {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--surface); border-radius: var(--radius-pill);
  padding: 10px 18px; margin: 8px 0; font-size: 13.5px; font-weight: 600;
  transition: background 180ms var(--ease);
}
.export-block:hover { background: var(--surface-hover); }

.limit-banner {
  max-width: 760px; margin: 0 auto 14px; padding: 14px 18px;
  background: var(--surface);
  border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  font-size: 13.5px;
}

/* ---------- Modal ---------- */

.modal-scrim {
  position: fixed; inset: 0; background: rgba(0,0,0,0.6);
  display: none; align-items: center; justify-content: center; z-index: 100;
  padding: 20px;
}
.modal-scrim.show { display: flex; }
.modal {
  width: 100%; max-width: 920px;
  background: var(--bg-elevated);
  border-radius: var(--radius-lg);
  padding: 40px;
  max-height: 90vh; overflow-y: auto;
}
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 28px; }
.modal-head h2 { font-size: 24px; }

/* ---------- Small dialogs (prompt/confirm) — same glass modal, compact ---------- */

.modal-sm {
  max-width: 400px; padding: 32px;
  transform: scale(0.96); opacity: 0;
  transition: transform 220ms var(--ease), opacity 220ms var(--ease);
}
.modal-sm.in { transform: scale(1); opacity: 1; }
.dialog-title { font-size: 18px; margin-bottom: 6px; }
.dialog-message { font-size: 14px; color: var(--text-secondary); line-height: 1.5; margin: 0 0 4px; }
.dialog-field { margin-top: 18px; margin-bottom: 0; }
.dialog-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 26px; }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { opacity: 0.88; }

/* ---------- Settings modal ----------
   Was a `.modal-sm` full of thin uppercase micro-labels and pill rows —
   its own one-off look, next to nothing else in the app. Restyled to the
   same "card" language the pricing modal's `.plan` cards use (a rounded
   `--radius-lg` surface per section, a plain title, generous padding)
   instead of a bespoke settings-screen pattern. */
.modal-settings { max-width: 920px; }
.settings-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
@media (max-width: 740px) { .settings-grid { grid-template-columns: 1fr; } }
.settings-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 36px 30px;
  display: flex; flex-direction: column;
}
.settings-card-label { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 18px; }
.settings-card-actions { display: flex; flex-direction: column; gap: 10px; }

.settings-account-row {
  display: flex; align-items: center; gap: 14px;
}
.settings-account-row .who { flex: 1; min-width: 0; overflow: hidden; }
.settings-account-row .name { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-account-row .settings-email { font-size: 12.5px; color: var(--text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A 3-way segmented control (Appearance, Text Size) — same shape/role as
   iOS's native segmented Picker, hand-built since the web has no
   equivalent control. */
.segmented {
  display: flex; gap: 2px;
  background: var(--bg-elevated); border-radius: var(--radius-sm);
  padding: 3px;
}
.segmented button {
  flex: 1; padding: 8px 10px;
  border: none; background: transparent; border-radius: 9px;
  color: var(--text-secondary); font-size: 13px; font-weight: 600; font-family: inherit;
  cursor: pointer; transition: background 160ms var(--ease), color 160ms var(--ease);
}
.segmented button:hover { color: var(--text); }
.segmented button.active { background: var(--surface-hover); color: var(--text); }

.settings-link-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 0;
  font-size: 13.5px; font-weight: 500; color: var(--text);
  border-bottom: 1px solid var(--hairline);
}
.settings-link-row:last-child { border-bottom: none; padding-bottom: 0; }
.settings-link-row:first-child { padding-top: 0; }
.settings-link-row svg { color: var(--text-tertiary); flex-shrink: 0; }

.api-key-box {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  overflow-x: auto;
  white-space: nowrap;
}

/* ---------- Toast ---------- */

.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px);
  background: var(--btn-primary-bg); color: var(--btn-primary-text); padding: 13px 22px; border-radius: var(--radius-pill);
  font-size: 13.5px; font-weight: 600; z-index: 200;
  opacity: 0; pointer-events: none; transition: all 260ms var(--ease);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- Utility ---------- */

.center-loader { display: flex; align-items: center; justify-content: center; height: 100%; padding: 60px; }
.dot-loader { display: inline-flex; gap: 5px; }
.dot-loader span { width: 7px; height: 7px; border-radius: 50%; background: var(--text-tertiary); animation: bounce 1.1s infinite ease-in-out; }
.dot-loader span:nth-child(2) { animation-delay: 0.15s; }
.dot-loader span:nth-child(3) { animation-delay: 0.3s; }

::-webkit-scrollbar { width: 0px; height: 0px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: transparent; }
