/* CullyAI Web — shared design system.
   Monochrome, Trade-Republic-esque: black/white, huge confident type,
   generous whitespace, quiet spring-eased motion. Poppins only.
   Light is the base palette below; dark swaps every token via
   [data-theme="dark"] on <html> (see js/app.js applyTheme — toggled from
   Settings → Preferences, default "system"). Every surface that relies on
   the "glass" look also gets a visible --border for contrast in both
   modes. */

@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');

:root {
  --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);
  --border: rgba(0, 0, 0, 0.14);
  --danger: #d33d3d;
  --success: #1f9d5c;
  --btn-primary-bg: #000000;
  --btn-primary-text: #ffffff;
  --scrollbar: rgba(0, 0, 0, 0.14);
}

:root[data-theme="dark"] {
  --bg: #0b0b0b;
  --bg-elevated: #171717;
  --bg-chat: #131313;
  --surface: #1c1c1c;
  --surface-hover: #282828;
  --glass: rgba(20, 20, 20, 0.62);
  --glass-strong: rgba(20, 20, 20, 0.82);
  --text: #f2f2f2;
  --text-secondary: #a9a9a9;
  --text-tertiary: #7a7a7a;
  --hairline: rgba(255, 255, 255, 0.08);
  --border: rgba(255, 255, 255, 0.14);
  --danger: #f0685f;
  --success: #35c17e;
  --btn-primary-bg: #ffffff;
  --btn-primary-text: #0b0b0b;
  --scrollbar: rgba(255, 255, 255, 0.18);
}

: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 { 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); border: 1px solid var(--hairline); 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; }

/* ---------- 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; }

/* Two logo variants (see assets/leaf-dark.png + leaf-white.png): the dark
   (black) mark shows by default, the white one only under [data-theme="dark"]
   — wherever both <img> tags are present (nav, auth cards, footer, sidebar). */
.mark.icon-light { display: none; }
.mark.icon-dark { display: block; }
:root[data-theme="dark"] .mark.icon-light { display: block; }
:root[data-theme="dark"] .mark.icon-dark { display: none; }

.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; }

/* ---------- Legal pages (privacy.html, terms.html) ---------- */

.legal-page {
  min-height: 100vh;
  padding: 40px 20px 100px;
}
.legal-inner {
  max-width: 740px;
  margin: 0 auto;
}
.legal-header {
  padding: 60px 0 48px;
  border-bottom: 1px solid var(--hairline);
  margin-bottom: 56px;
}
.legal-category {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin: 0 0 16px;
}
.legal-header h1 {
  font-size: clamp(32px, 5vw, 48px);
  margin-bottom: 16px;
}
.legal-meta {
  font-size: 13.5px;
  color: var(--text-tertiary);
  margin: 0;
}
.legal-body section {
  margin-bottom: 48px;
}
.legal-body h2 {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 16px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--hairline);
}
.legal-body h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin: 24px 0 10px;
}
.legal-body p {
  font-size: 14.5px;
  line-height: 1.75;
  color: var(--text-secondary);
  margin: 0 0 14px;
}
.legal-body p:last-child { margin-bottom: 0; }
.legal-body ul {
  margin: 0 0 14px;
  padding-left: 22px;
}
.legal-body li {
  font-size: 14.5px;
  line-height: 1.75;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.legal-body a { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.legal-body a:hover { opacity: 0.7; }
.legal-body table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 20px;
  font-size: 14px;
}
.legal-body th {
  text-align: left;
  font-weight: 600;
  color: var(--text);
  padding: 10px 14px;
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
}
.legal-body td {
  padding: 10px 14px;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
  line-height: 1.6;
}
.legal-body tr:last-child td { border-bottom: none; }
.legal-callout {
  background: var(--surface);
  border-left: 3px solid var(--btn-primary-bg);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 14px 18px;
  margin-bottom: 18px;
  font-size: 14.5px;
  color: var(--text);
  line-height: 1.6;
}
.legal-footer {
  display: flex;
  gap: 24px;
  padding-top: 48px;
  border-top: 1px solid var(--hairline);
  margin-top: 64px;
}
.legal-footer a {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-secondary);
  text-decoration: none;
}
.legal-footer a:hover { color: var(--text); }

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

.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 40px 20px; position: relative; }
.auth-card { width: 100%; max-width: 400px; background: var(--surface); border: 1px solid var(--border); 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: 1px solid var(--border);
  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/Charts/Delivery nav — stacked vertically as a plain
   nav list (not a horizontal pill row, which got cramped once a 4th tab
   was added) — each item full-width, icon + label left-aligned, active
   one filled in like a standard sidebar nav item. */
.sidebar-tabs { display: flex; flex-direction: column; gap: 2px; padding: 2px; margin-bottom: 10px; flex-shrink: 0; }
.sidebar-tab {
  display: flex; align-items: center; justify-content: flex-start; gap: 10px;
  width: 100%; min-width: 0; 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; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
.sidebar-tab svg { flex-shrink: 0; }
.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; }

.list-empty-hint {
  padding: 14px 12px;
  font-size: 12.5px; line-height: 1.45;
  color: var(--text-tertiary);
}

.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-files-list { padding: 0 4px; margin-bottom: 4px; }
.project-files-empty { padding: 8px 8px 12px; font-size: 12px; line-height: 1.5; color: var(--text-tertiary); }
.project-file-row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 8px; border-radius: var(--radius-sm);
}
.project-file-row:hover { background: var(--surface); }
.project-file-row:hover .project-file-delete { opacity: 1; }
.project-file-icon { flex-shrink: 0; color: var(--text-secondary); display: flex; }
.project-file-name { flex: 1; min-width: 0; font-size: 12.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.project-file-size { flex-shrink: 0; font-size: 11px; color: var(--text-tertiary); }
.project-file-error { flex-shrink: 0; font-size: 11px; color: var(--danger); }
.project-file-delete {
  flex-shrink: 0; opacity: 0; background: none; border: none; cursor: pointer;
  color: var(--text-tertiary); padding: 3px; display: flex; border-radius: 4px;
  transition: opacity 140ms var(--ease), color 140ms var(--ease);
}
.project-file-delete:hover { color: var(--danger); }
.project-files-add {
  display: flex; align-items: center; width: 100%; text-align: left;
  padding: 8px 12px; margin-bottom: 6px;
  border-radius: var(--radius-sm); border: none; background: transparent;
  color: var(--text-secondary); font-size: 12.5px; font-weight: 600; font-family: inherit;
  cursor: pointer; transition: background 160ms var(--ease), color 160ms var(--ease);
}
.project-files-add: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); }

.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); }

.credits-section { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--hairline); }
.credits-section .usage-row { font-weight: 600; color: var(--text); font-size: 13px; }
.credits-topup-options { display: flex; gap: 8px; flex-wrap: wrap; }
.credit-txn-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; padding: 7px 0; border-bottom: 1px solid var(--hairline); color: var(--text-secondary); }
.credit-txn-row:last-child { border-bottom: none; }
.credit-txn-amount.positive { color: var(--success); }
.credit-txn-amount.negative { color: var(--text-secondary); }

.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: 1px solid var(--border);
  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); }

/* Model picker (Swift 1.0 / Pro 1.0 / Ultra 1.0) — same popover pattern as
   .sort-menu-wrap, sitting in the chat topbar next to the title. */
.model-picker-wrap { position: relative; flex-shrink: 0; }
.model-btn {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--surface); border: none; color: var(--text);
  font-size: 12.5px; font-weight: 600; font-family: inherit;
  cursor: pointer; white-space: nowrap;
  transition: background 160ms var(--ease);
}
.model-btn:hover { background: var(--surface-hover); }
.model-btn svg { color: var(--text-secondary); flex-shrink: 0; }
.model-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 20;
  width: 280px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 6px;
  display: none;
  flex-direction: column;
  gap: 2px;
}
.model-picker-wrap.open .model-menu { display: flex; }
.model-option {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%; padding: 10px 11px;
  border-radius: var(--radius-sm);
  background: transparent; border: none;
  cursor: pointer; text-align: left; font-family: inherit;
  transition: background 160ms var(--ease);
}
.model-option:hover { background: var(--surface); }
.model-option.active { background: var(--surface); }
.model-option.locked { cursor: pointer; opacity: 0.68; }
.model-option-body { flex: 1; min-width: 0; }
.model-option-name { display: flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 600; color: var(--text); }
.model-option-name .thinking-badge {
  font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 999px;
  background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success);
}
.model-option-tagline { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.model-option-desc { font-size: 11.5px; color: var(--text-tertiary); margin-top: 4px; line-height: 1.45; }
.model-option-check { flex-shrink: 0; color: var(--text); margin-top: 2px; }
.model-option-lock { flex-shrink: 0; color: var(--text-tertiary); margin-top: 2px; }

/* Custom select widget: see css/ui.css (.ui-select) and js/ui.js. */
/* .conv-move is opacity:0 except on row hover — force it visible while
   its menu is open, or moving the cursor down into the menu (outside
   the row's own bounds) would fade the trigger out from under it. */
.conv-item .conv-move.open { opacity: 1; }

/* Ultra's extended-thinking trace — collapsible, shown above the final
   answer text and auto-collapsed once real answer text starts streaming. */
.msg-reasoning {
  border-radius: var(--radius-sm);
  background: var(--surface);
  margin-bottom: 10px;
  overflow: hidden;
}
.msg-reasoning summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 7px;
  padding: 9px 12px;
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
}
.msg-reasoning summary::-webkit-details-marker { display: none; }
.msg-reasoning summary::before { content: "🧠"; font-size: 12px; }
.msg-reasoning[open] summary::after { content: "reasoning…"; font-weight: 500; color: var(--text-tertiary); }
.msg-reasoning:not([open]) summary::after { content: "reasoning (tap to expand)"; font-weight: 500; color: var(--text-tertiary); }
.msg-reasoning .reasoning-text {
  padding: 0 12px 12px; font-size: 12.5px; line-height: 1.6;
  color: var(--text-tertiary); white-space: pre-wrap;
}

/* 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); }
/* `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, .msg-bubble h4, .msg-bubble h5, .msg-bubble h6 { font-weight: 700; line-height: 1.3; }
.msg-bubble h1 { margin: 22px 0 12px; font-size: 20px; }
.msg-bubble h1:first-child { margin-top: 0; }
.msg-bubble h2 { margin: 20px 0 10px; font-size: 18px; }
.msg-bubble h2:first-child { margin-top: 0; }
.msg-bubble h3 { margin: 18px 0 8px; font-size: 16px; }
.msg-bubble h3:first-child { margin-top: 0; }
.msg-bubble h4, .msg-bubble h5, .msg-bubble h6 { margin: 16px 0 8px; font-size: 14.5px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.03em; }
.msg-bubble h4:first-child, .msg-bubble h5:first-child, .msg-bubble h6:first-child { margin-top: 0; }
.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(calc(24px * var(--text-scale)), 4vw, calc(34px * var(--text-scale))); margin-bottom: 12px; }
.empty-state p { color: var(--text-secondary); max-width: 420px; margin-bottom: 30px; font-size: calc(14.5px * var(--text-scale)); }
.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: calc(13px * var(--text-scale)); color: var(--text-secondary);
  cursor: pointer; transition: all 180ms var(--ease);
}
.suggestion-chip:hover { background: var(--surface-hover); color: var(--text); }

/* Floating "scroll to latest" button — sits just above the composer,
   only shown (see scrollBottomBtn logic in app.js) once the user has
   scrolled up away from the newest message. `bottom` is set from JS to
   track the composer's actual height, which isn't fixed (attachment
   preview, the daily-limit banner, and the textarea's own auto-grow all
   change it). */
.scroll-bottom-btn {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 96px; z-index: 15;
  width: 38px; height: 38px; border-radius: var(--radius-pill);
  background: var(--bg-elevated); border: 1px solid var(--border);
  color: var(--text); display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: 0 6px 18px rgba(0,0,0,0.18);
  transition: background 160ms var(--ease), opacity 160ms var(--ease);
}
.scroll-bottom-btn:hover { background: var(--surface-hover); }

.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: calc(11.5px * var(--text-scale)); 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; }

/* ---------- Charts dashboard (sidebar "Charts" tab) ---------- */

.charts-view {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 22px 22px 40px;
  display: flex; flex-direction: column; gap: 18px;
}
.charts-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.charts-header h2 { font-size: 20px; font-weight: 700; margin: 0; }
.charts-header-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.category-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.category-pill {
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--surface); border: none;
  color: var(--text-secondary); font-size: 13px; font-weight: 600; font-family: inherit;
  cursor: pointer; transition: background 160ms var(--ease), color 160ms var(--ease);
}
.category-pill:hover { background: var(--surface-hover); color: var(--text); }
.category-pill.active { background: var(--btn-primary-bg); color: var(--btn-primary-text); }

.commodity-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
}
.commodity-card {
  background: var(--surface);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  cursor: pointer;
  text-align: left;
  border: 1px solid var(--border); font-family: inherit;
  display: flex; flex-direction: column; gap: 10px;
  transition: background 160ms var(--ease), transform 160ms var(--ease);
}
.commodity-card:hover { background: var(--surface-hover); transform: translateY(-1px); }
.commodity-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.commodity-card-name { font-size: 13.5px; font-weight: 600; color: var(--text); line-height: 1.3; }
.commodity-card-symbol { font-size: 11px; color: var(--text-tertiary); font-weight: 600; letter-spacing: 0.02em; }
.commodity-card-change {
  font-size: 12px; font-weight: 700; padding: 3px 8px; border-radius: 999px; flex-shrink: 0; white-space: nowrap;
}
.commodity-card-change.up { color: var(--success); background: color-mix(in srgb, var(--success) 14%, transparent); }
.commodity-card-change.down { color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, transparent); }
.commodity-card-price { font-size: 19px; font-weight: 700; color: var(--text); }
.commodity-card-unit { font-size: 11px; color: var(--text-tertiary); font-weight: 500; margin-top: -6px; }
.commodity-card-sparkline { height: 44px; width: 100%; position: relative; }
.commodity-card-empty { color: var(--text-secondary); font-size: 13.5px; padding: 30px 4px; text-align: center; grid-column: 1 / -1; }

.modal-chart-detail { max-width: 640px; }
.chart-detail-stats { display: flex; gap: 24px; margin-bottom: 4px; }
.chart-detail-stat-label { font-size: 11.5px; color: var(--text-tertiary); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 4px; }
.chart-detail-stat-value { font-size: 17px; font-weight: 700; color: var(--text); }
.chart-detail-stat-value.up { color: var(--success); }
.chart-detail-stat-value.down { color: var(--danger); }

/* ---------- Correlation matrix + storage/carry modals ---------- */

.modal-analysis { max-width: 620px; max-height: 82vh; overflow-y: auto; }

.symbol-picker { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; max-height: 180px; overflow-y: auto; padding: 2px; }
.symbol-chip {
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--surface); border: none;
  color: var(--text-secondary); font-size: 12px; font-weight: 600; font-family: inherit;
  cursor: pointer; transition: background 160ms var(--ease), color 160ms var(--ease);
}
.symbol-chip:hover { background: var(--surface-hover); color: var(--text); }
.symbol-chip.selected { background: var(--btn-primary-bg); color: var(--btn-primary-text); }

.corr-matrix-wrap { overflow-x: auto; margin-top: 18px; }
.corr-matrix { border-collapse: separate; border-spacing: 3px; font-size: 11.5px; }
.corr-matrix th { font-weight: 600; color: var(--text-secondary); padding: 4px 6px; text-align: center; }
.corr-matrix th.row-label { text-align: right; padding-right: 10px; }
.corr-cell {
  width: 46px; height: 32px; text-align: center; border-radius: 6px;
  font-weight: 700; color: #fff;
}
.corr-legend { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 11.5px; color: var(--text-tertiary); }
.corr-relationships { margin-top: 16px; display: flex; flex-direction: column; gap: 6px; }
.corr-relationship-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; padding: 6px 0; border-bottom: 1px solid var(--hairline); }
.corr-relationship-row:last-child { border-bottom: none; }
.corr-relationship-pair { font-weight: 600; color: var(--text); }
.corr-relationship-note { color: var(--text-secondary); }

.carry-form { display: flex; flex-direction: column; gap: 14px; margin-top: 14px; }
.carry-form label { font-size: 12.5px; font-weight: 600; color: var(--text-secondary); display: flex; flex-direction: column; gap: 6px; }
.carry-form .field-hint { font-weight: 400; color: var(--text-tertiary); }
.carry-form input {
  background: var(--surface); border: none; border-radius: var(--radius-sm);
  padding: 10px 12px; color: var(--text); font-size: 13.5px; font-family: inherit;
}
.carry-result-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 18px; }
.carry-stat { background: var(--surface); border-radius: var(--radius-sm); padding: 12px 14px; }
.carry-stat-label { font-size: 11px; color: var(--text-tertiary); font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 5px; }
.carry-stat-value { font-size: 16px; font-weight: 700; color: var(--text); }
.carry-note { font-size: 12.5px; color: var(--text-secondary); line-height: 1.6; margin-top: 14px; }

/* ---------- Price Alerts (Settings) + Marketing Plan (Farm Tools) forms ---------- */

/* Single column, not a 2-up grid — this card sits alongside others in
   .settings-compact-grid and is rarely wider than ~260px, nowhere near
   enough room for two selects side by side without truncating their
   labels down to 3-4 characters. */
.alert-form {
  display: flex; flex-direction: column; gap: 8px;
  margin: 14px 0;
}
.alert-form input {
  background: var(--bg-elevated); border: none; border-radius: var(--radius-sm);
  padding: 9px 11px; color: var(--text); font-size: 13px; font-family: inherit;
}
.alert-form .ui-select-trigger { background: var(--bg-elevated); padding: 9px 11px; font-size: 13px; }

.alert-list, .marketing-plan-list { display: flex; flex-direction: column; gap: 10px; }
.alert-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px;
}
.alert-row-text { font-size: 12.5px; color: var(--text); }
.alert-row-text .name { font-weight: 600; }
.alert-row-status {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  padding: 2px 8px; border-radius: 999px; flex-shrink: 0;
}
.alert-row-status.active { color: var(--text-secondary); background: var(--surface); }
.alert-row-status.triggered { color: var(--success); background: color-mix(in srgb, var(--success) 16%, transparent); }
.alert-row-cancel { flex-shrink: 0; background: none; border: none; color: var(--text-tertiary); cursor: pointer; padding: 4px; }
.alert-row-cancel:hover { color: var(--danger); }

.plan-card { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px; }
.plan-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.plan-card-title { font-size: 13.5px; font-weight: 600; color: var(--text); }
.plan-card-delete { background: none; border: none; color: var(--text-tertiary); cursor: pointer; padding: 4px; }
.plan-card-delete:hover { color: var(--danger); }
.plan-progress-bar { height: 8px; border-radius: 999px; background: var(--surface); overflow: hidden; margin-bottom: 10px; }
.plan-progress-fill { height: 100%; background: var(--success); border-radius: 999px; }
.plan-card-stats { display: flex; flex-wrap: wrap; gap: 14px; font-size: 11.5px; color: var(--text-secondary); margin-bottom: 10px; }
.plan-card-stats strong { color: var(--text); }
.plan-sale-form { display: grid; grid-template-columns: 1fr 1fr auto; gap: 6px; }
.plan-sale-form input {
  background: var(--surface); border: none; border-radius: var(--radius-sm);
  padding: 7px 9px; color: var(--text); font-size: 12px; font-family: inherit;
}

/* ---------- Delivery / order tracker settings card ---------- */

.delivery-list { display: flex; flex-direction: column; gap: 10px; }
.delivery-card { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px; }
.delivery-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.delivery-card-title { font-size: 13.5px; font-weight: 600; color: var(--text); }
.delivery-card-sub { font-size: 11.5px; color: var(--text-tertiary); margin-top: 2px; }
.delivery-status-badge {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  padding: 3px 9px; border-radius: 999px; flex-shrink: 0; white-space: nowrap;
}
.delivery-status-badge.pending { color: var(--text-secondary); background: var(--surface); }
.delivery-status-badge.in_transit { color: #f5b942; background: rgba(245,185,66,0.16); }
.delivery-status-badge.delivered { color: var(--success); background: color-mix(in srgb, var(--success) 16%, transparent); }
.delivery-status-badge.cancelled { color: var(--text-tertiary); background: var(--surface); }
.delivery-card-detail { font-size: 12px; color: var(--text-secondary); line-height: 1.6; margin-bottom: 10px; }
.delivery-card-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.delivery-confirm-form { display: flex; gap: 8px; margin-top: 8px; align-items: center; }
.delivery-confirm-form input {
  background: var(--surface); border: none; border-radius: var(--radius-sm);
  padding: 7px 9px; color: var(--text); font-size: 12px; font-family: inherit; width: 120px;
}

/* ---------- Farm Tools dashboard (sidebar "Farm Tools" tab) ---------- */
/* Marketing Plan + Basis Bid Sheet — moved out of Settings into their own
   full-panel view (same reasoning as Deliveries: an ongoing worklist, not
   a one-time account setting). */
.farmtools-section {
  background: var(--surface); border-radius: var(--radius-lg);
  padding: 20px 22px;
}
.farmtools-section-label { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 4px; }
.farmtools-section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.farmtools-section-head .farmtools-section-label { margin-bottom: 4px; }
.farmtools-section-head .dialog-message { margin: 0; }
.farmtools-section-head .btn { flex-shrink: 0; }

/* ---------- Basis bid sheet ---------- */


.bid-list { display: flex; flex-direction: column; gap: 14px; }
.bid-group-label { font-size: 12px; font-weight: 700; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.03em; }
.bid-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px; margin-top: 6px;
}
.bid-row.best { border: 1px solid color-mix(in srgb, var(--success) 40%, transparent); }
.bid-row-text { font-size: 12.5px; color: var(--text); }
.bid-row-text .elevator { font-weight: 600; }
.bid-row-basis { font-size: 11px; color: var(--text-tertiary); margin-top: 2px; }
.bid-best-tag {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  padding: 2px 8px; border-radius: 999px; color: var(--success);
  background: color-mix(in srgb, var(--success) 16%, transparent); flex-shrink: 0;
}
.bid-row-cash { font-size: 14px; font-weight: 700; color: var(--text); flex-shrink: 0; }
.bid-row-delete { flex-shrink: 0; background: none; border: none; color: var(--text-tertiary); cursor: pointer; padding: 4px; }
.bid-row-delete:hover { color: var(--danger); }
.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-chat);
  border: 1px solid var(--border);
  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;
  border: 1px solid var(--border);
  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. */
/* Settings modal: a left-hand category nav + independently-scrolling
   panel area, instead of one long flat list of 12+ cards a user had to
   scroll all the way through to find e.g. "Log out". Overrides the base
   .modal's own overflow-y:auto (which would otherwise fight the panel's
   own scroll) with a fixed-height flex column instead. */
.modal-settings {
  max-width: 920px;
  display: flex; flex-direction: column;
  max-height: 85vh; overflow: hidden;
}
.modal-settings .modal-head { flex-shrink: 0; }
.settings-layout { display: flex; gap: 28px; flex: 1; min-height: 0; }
.settings-nav { display: flex; flex-direction: column; gap: 2px; width: 190px; flex-shrink: 0; }
.settings-nav-item {
  position: relative;
  text-align: left; padding: 10px 14px;
  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);
}
.settings-nav-item:hover { color: var(--text); background: var(--surface); }
.settings-nav-item.active { background: var(--surface); color: var(--text); }
/* Left accent bar on the active item — a clearer "you are here" than a
   background tint alone, especially once the row wraps onto its own
   line among several others. */
.settings-nav-item.active::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 16px; border-radius: var(--radius-pill); background: var(--text);
}
/* Own scroll container, independent from .settings-panels — a tall nav
   list (mobile's wrapped rows) must never push the panel content down
   or fight it for the same scrollbar. */
.settings-panels { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding-right: 4px; }
@media (max-width: 740px) {
  .modal-settings { padding: 26px 20px; max-height: 90vh; }
  .settings-layout { flex-direction: column; gap: 16px; }
  /* Wraps to as many rows as needed instead of scrolling sideways — at
     390px wide, a horizontal-scroll nav hid 2 of the 5 items off-screen
     with no visual hint they existed. */
  .settings-nav { flex-direction: row; flex-wrap: wrap; width: 100%; gap: 6px; }
  .settings-nav-item { flex-shrink: 0; white-space: nowrap; }
  .settings-nav-item.active::before { display: none; }
}

/* Each panel is one ordered list of sections, stacked top to bottom — not
   a grid of cards that reflows into an uneven 1/2-column jumble depending
   on the modal's width. No inner max-height/scroll here: .settings-panels
   above is the single scroll container, so a list longer than the modal
   just scrolls the whole panel instead of double-scrolling inside a fixed
   box. */
.settings-compact-grid {
  display: flex;
  flex-direction: column;
}
.settings-compact-card {
  padding: 22px 2px;
  border-bottom: 1px solid var(--hairline);
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.settings-compact-card:first-child { padding-top: 2px; }
.settings-compact-card:last-child { border-bottom: none; padding-bottom: 2px; }
.settings-compact-label {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  margin-bottom: 14px;
}
.settings-compact-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.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;
}

/* One row per model (Swift 1.0 / Pro 1.0 / Ultra 1.0) in the API Access
   settings card — nests one shade lighter than .settings-card's own
   --surface background so each model's key is visually its own unit. */
.api-key-list { display: flex; flex-direction: column; gap: 12px; }
.api-key-row {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
}
.api-key-row-label { font-size: 13.5px; font-weight: 600; color: var(--text); margin-bottom: 10px; }
.api-key-row.locked { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.api-key-row.locked .api-key-row-label { margin-bottom: 0; }
.api-key-row .api-key-box { background: var(--surface); }

/* ---------- Auth tabs (login QR / email switcher) ---------- */

.auth-tabs {
  display: flex;
  gap: 4px;
  background: var(--surface-hover);
  border-radius: var(--radius-pill);
  padding: 4px;
  margin-bottom: 28px;
}
.auth-tab {
  flex: 1;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 13.5px;
  font-weight: 600;
  padding: 8px 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background 200ms, color 200ms;
}
.auth-tab.active { background: var(--surface); color: var(--text); }

/* ---------- QR code display (login + add-device in settings) ---------- */

.qr-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 220px;
  height: 220px;
  background: var(--bg);
  border-radius: var(--radius-md);
  margin: 0 auto 12px;
  border: 1px solid var(--hairline);
  position: relative;
}
.qr-wrap-sm { width: 176px; height: 176px; }

/* qrcodejs generates an <img>; make sure it fills the container cleanly */
.qr-wrap img { display: block; border-radius: 6px; }

.qr-spinner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  border-radius: inherit;
}
.qr-expiry {
  text-align: center;
  font-size: 12.5px;
  color: var(--text-tertiary);
  margin-bottom: 4px;
}

/* ---------- Invoice rows (billing history) ---------- */

.invoice-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--hairline);
}
.invoice-row:last-child { border-bottom: none; }
.invoice-meta { display: flex; flex-direction: column; gap: 2px; }
.invoice-amount { font-size: 14.5px; font-weight: 600; color: var(--text); }
.invoice-date { font-size: 12px; color: var(--text-tertiary); }
.invoice-actions { display: flex; align-items: center; gap: 8px; }
.invoice-status {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  background: var(--surface-hover);
  color: var(--text-secondary);
  text-transform: capitalize;
}
.invoice-status.paid { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.btn-xs { padding: 5px 10px; font-size: 11px; }

/* ---------- Device rows + secondary-email rows ---------- */

.device-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--hairline);
}
.device-row:last-child { border-bottom: none; }
.device-icon { color: var(--text-secondary); flex-shrink: 0; }
.device-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.device-name { font-size: 13.5px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.device-last-seen { font-size: 11.5px; color: var(--text-tertiary); }
.icon-btn-sm {
  width: 28px; height: 28px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text-tertiary);
  transition: color 160ms, background 160ms;
}
.icon-btn-sm:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }

/* ---------- 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; }
