/* ============ Clutter dashboard — glassmorphism theme (self-contained) ============ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: 'Outfit', 'Inter', system-ui, -apple-system, sans-serif;
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}
/* the vivid, fixed mesh backdrop every glass surface blurs/refracts against —
   glassmorphism needs actual color behind it or the blur has nothing to show */
body.dash-body {
  background-color: #eef0fb;
  background-image:
    radial-gradient(1100px 700px at 8% -10%, rgba(79,70,229,.35), transparent 55%),
    radial-gradient(900px 650px at 100% 0%, rgba(124,58,237,.30), transparent 55%),
    radial-gradient(1000px 800px at 90% 100%, rgba(20,184,166,.22), transparent 55%),
    radial-gradient(700px 600px at 0% 100%, rgba(236,72,153,.15), transparent 50%);
  background-attachment: fixed;
}
:root[data-theme="dark"] body.dash-body {
  background-color: #0e0c1a;
  background-image:
    radial-gradient(1100px 700px at 8% -10%, rgba(129,140,248,.30), transparent 55%),
    radial-gradient(900px 650px at 100% 0%, rgba(167,139,250,.26), transparent 55%),
    radial-gradient(1000px 800px at 90% 100%, rgba(45,212,191,.16), transparent 55%),
    radial-gradient(700px 600px at 0% 100%, rgba(236,72,153,.12), transparent 50%);
  background-attachment: fixed;
}
/* auth pages (login/register/forgot/onboarding) deliberately do NOT use the
   glassmorphism mesh -- these are the visitor's very first impression and a
   plain, clean, white form (matching the reference the user asked to match)
   reads as more trustworthy than a busy gradient backdrop */
.auth-shell { background: #fff; }
:root[data-theme="dark"] .auth-shell { background: #121022; }
/* themed scrollbars — the default OS scrollbar looks out of place on glass panels */
.thread-body, .conv-list, .sidebar-nav, .page-content {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) transparent;
}
.thread-body::-webkit-scrollbar, .conv-list::-webkit-scrollbar,
.sidebar-nav::-webkit-scrollbar, .page-content::-webkit-scrollbar { width: 8px; height: 8px; }
.thread-body::-webkit-scrollbar-track, .conv-list::-webkit-scrollbar-track,
.sidebar-nav::-webkit-scrollbar-track, .page-content::-webkit-scrollbar-track { background: transparent; }
.thread-body::-webkit-scrollbar-thumb, .conv-list::-webkit-scrollbar-thumb,
.sidebar-nav::-webkit-scrollbar-thumb, .page-content::-webkit-scrollbar-thumb {
  background-color: var(--scrollbar-thumb); border-radius: 999px;
  border: 2px solid transparent; background-clip: padding-box;
}
.thread-body::-webkit-scrollbar-thumb:hover, .conv-list::-webkit-scrollbar-thumb:hover,
.sidebar-nav::-webkit-scrollbar-thumb:hover, .page-content::-webkit-scrollbar-thumb:hover {
  background-color: var(--scrollbar-thumb-hover); background-clip: padding-box;
}
.thread-body::-webkit-scrollbar-button, .conv-list::-webkit-scrollbar-button,
.sidebar-nav::-webkit-scrollbar-button, .page-content::-webkit-scrollbar-button {
  display: none !important; width: 0; height: 0;
}

h1,h2,h3,h4 { font-family: 'Outfit','Inter',sans-serif; margin: 0; font-weight: 700; letter-spacing: -0.01em; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
input, select, textarea { font: inherit; }
svg { display: block; }

:root {
  --bg: #f8f7fb;
  --panel: #ffffff;
  --panel-2: #f2f1f8;
  --border: #e7e4f0;
  --text: #16152b;
  --dim: #64607d;
  --faint: #9895ae;
  --primary: #4f46e5;
  --primary-dark: #4338ca;
  --primary-soft: #eef0ff;
  --green: #16a34a;
  --green-soft: #e8f7ee;
  --amber: #d97706;
  --amber-soft: #fdf3e3;
  --violet: #7c3aed;
  --violet-soft: #f3edff;
  --danger: #dc2626;
  --danger-soft: #fdecec;
  --radius: 14px;
  --shadow: 0 1px 2px rgba(30,20,70,.06);
  --shadow-lg: 0 16px 40px -10px rgba(30,20,70,.16);
  --ease: cubic-bezier(.22,.9,.32,1.1);

  /* aliases for templates written against the old dark-theme token names */
  --surface: var(--panel);
  --surface-2: var(--panel-2);
  --text-dim: var(--dim);
  --text-faint: var(--faint);
  --accent: var(--primary);
  --accent-2: #0e9f8a;
  --accent-3: var(--danger);
  --gold: var(--amber);
  --grad: linear-gradient(135deg, #4f46e5, #14b8a6);
  --grad-2: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);

  /* glass surfaces — used on the chrome (sidebar/cards/modals), not on data-dense
     inner elements like table cells/inputs, which stay opaque for legibility.
     Applied directly on each component's own rule below (not as one shared
     selector list) so source order in this file can't silently override it. */
  --glass-bg: rgba(255,255,255,.5);
  --glass-bg-soft: rgba(255,255,255,.3);
  --glass-bg-strong: rgba(255,255,255,.75);
  --glass-border: rgba(255,255,255,.7);
  --glass-blur: blur(24px) saturate(200%);

  --scrollbar-thumb: rgba(79,70,229,.28);
  --scrollbar-thumb-hover: rgba(79,70,229,.5);
}

/* dark theme — toggled via <html data-theme="dark">, set by /app/theme/{light|dark}
   (persisted per-user, see users.theme) and the topbar toggle button in base.html */
:root[data-theme="dark"] {
  --bg: #100e1c;
  --panel: #1a1830;
  --panel-2: #211e3a;
  --border: #322d51;
  --text: #f1f0f7;
  --dim: #a9a5c4;
  --faint: #766f96;
  --primary: #818cf8;
  --primary-dark: #6366f1;
  --primary-soft: #2a2652;
  --green: #34d399;
  --green-soft: #123324;
  --amber: #fbbf24;
  --amber-soft: #3a2c0d;
  --violet: #a78bfa;
  --violet-soft: #2e2758;
  --danger: #f87171;
  --danger-soft: #3a1a1e;
  --shadow: 0 1px 2px rgba(0,0,0,.35);
  --shadow-lg: 0 16px 40px -10px rgba(0,0,0,.55);
  --grad: linear-gradient(135deg, #818cf8, #2dd4bf);
  --grad-2: linear-gradient(135deg, #818cf8 0%, #a78bfa 100%);
  --accent-2: #2dd4bf;
  --glass-bg: rgba(26,24,48,.45);
  --glass-bg-soft: rgba(26,24,48,.25);
  --glass-bg-strong: rgba(20,18,38,.75);
  --glass-border: rgba(255,255,255,.15);
  --scrollbar-thumb: rgba(129,140,248,.35);
  --scrollbar-thumb-hover: rgba(129,140,248,.6);
}
body.dash-body { display: flex; min-height: 100vh; }

/* ---------- native cross-page transitions (progressive enhancement) ----------
   Paired with <meta name="view-transition" content="same-origin"> in base.html.
   Sidebar/topbar are tagged so they hold still across navigations (the actual
   "app shell" feel) while the page content cross-fades — browsers without
   support (Firefox/Safari) just navigate normally, no JS, no fallback needed. */
@media (prefers-reduced-motion: no-preference) {
  .sidebar { view-transition-name: app-sidebar; }
  .topbar { view-transition-name: app-topbar; }

  ::view-transition-old(app-sidebar), ::view-transition-new(app-sidebar),
  ::view-transition-old(app-topbar), ::view-transition-new(app-topbar) {
    animation: none;
  }
  ::view-transition-old(root) { animation: page-fade-out .12s ease both; }
  ::view-transition-new(root) { animation: page-fade-in .22s var(--ease) both; }
}
@keyframes page-fade-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
@keyframes page-fade-out { to { opacity: 0; } }

/* ---------- entrance motion for content that just landed ---------- */
@media (prefers-reduced-motion: no-preference) {
  .page-content > * { animation: content-in .38s var(--ease) both; }
  .card, .stat-card, .pricing-mini-card { animation: content-in .4s var(--ease) both; }
  .data-table tbody tr, .conv-item { animation: content-in .3s var(--ease) both; }
  .grid-2 > *, .grid-3 > *, .grid-4 > * { animation: content-in .4s var(--ease) both; }
  .grid-2 > *:nth-child(1), .grid-3 > *:nth-child(1), .grid-4 > *:nth-child(1) { animation-delay: .02s; }
  .grid-2 > *:nth-child(2), .grid-3 > *:nth-child(2), .grid-4 > *:nth-child(2) { animation-delay: .06s; }
  .grid-2 > *:nth-child(3), .grid-3 > *:nth-child(3), .grid-4 > *:nth-child(3) { animation-delay: .1s; }
  .grid-3 > *:nth-child(4), .grid-4 > *:nth-child(4) { animation-delay: .14s; }
  .conv-item:nth-child(1) { animation-delay: .01s; }
  .conv-item:nth-child(2) { animation-delay: .03s; }
  .conv-item:nth-child(3) { animation-delay: .05s; }
  .conv-item:nth-child(4) { animation-delay: .07s; }
  .conv-item:nth-child(5) { animation-delay: .09s; }
  .conv-item:nth-child(n+6) { animation-delay: .1s; }
}
@keyframes content-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- tactile feedback ---------- */
.btn:active, .icon-btn:active, .pay-provider-btn:active, .conv-tab:active { transform: scale(.97); }
.card, .stat-card, .pricing-mini-card, .conv-item {
  transition: box-shadow .3s ease, transform .3s var(--ease), border-color .3s ease;
}
.card:hover, .stat-card:hover, .pricing-mini-card:hover { 
  box-shadow: 0 16px 40px -10px rgba(79,70,229,.2); transform: translateY(-4px); border-color: rgba(79,70,229,.35); 
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px; border-radius: 10px; border: 1px solid transparent;
  font-weight: 600; font-size: 14px; white-space: nowrap;
  transition: background .2s ease, border-color .2s ease, transform .2s var(--ease), box-shadow .2s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary {
  background: var(--grad-2); color: #fff; box-shadow: 0 4px 14px -4px rgba(79,70,229,.5);
  background-size: 160% 160%; background-position: 0% 50%;
  transition: background-position .35s ease, transform .2s var(--ease), box-shadow .2s ease;
}
.btn-primary:hover { background-position: 100% 50%; box-shadow: 0 6px 18px -4px rgba(79,70,229,.6); }
.btn-ghost { background: var(--panel-2); color: var(--text); }
.btn-ghost:hover { background: #e8ebf1; }
.btn-danger { background: #e5484d; color: #fff; box-shadow: 0 4px 14px -4px rgba(229,72,77,.5); }
.btn-danger:hover { background: #d43d42; box-shadow: 0 6px 18px -4px rgba(229,72,77,.6); }
.btn-outline { background: var(--panel); color: var(--text); border-color: var(--border); }
.btn-outline:hover { border-color: var(--primary); color: var(--primary); }
.btn-block { width: 100%; }
.btn-lg { padding: 13px 24px; font-size: 15px; }
.btn-sm { padding: 7px 14px; font-size: 13px; }

/* ---------- sidebar ---------- */
.sidebar {
  width: 248px; flex-shrink: 0; background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  display: flex; flex-direction: column; padding: 14px 12px; position: sticky; top: 16px; max-height: calc(100vh - 32px); height: calc(100vh - 32px); z-index: 20;
  margin-left: 16px; border-radius: 24px; border: 1px solid var(--glass-border); box-shadow: var(--shadow-lg);
  overflow-x: hidden; overflow-y: auto; transition: width .28s var(--ease), padding .28s var(--ease), opacity .2s ease, margin .28s var(--ease);
}
html.sidebar-collapsed .sidebar { width: 0; padding-left: 0; padding-right: 0; opacity: 0; pointer-events: none; margin-left: 0; border: none; }
.sidebar > * { min-width: 220px; }

/* the sole sidebar-collapse control -- a persistent edge tab that tracks the
   sidebar's current width so it always sits right on its edge, both expanded
   and collapsed (an earlier topbar icon duplicated this and was removed --
   one clear, always-visible control beat two competing ones) */
.sidebar-edge-toggle {
  position: fixed; top: 50%; left: calc(248px + 16px); transform: translate(-50%, -50%);
  width: 28px; height: 64px; border-radius: 0 12px 12px 0;
  background: var(--grad-2); border: none;
  color: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 2px 0 14px -2px rgba(79,70,229,.55); z-index: 25;
  transition: left .28s var(--ease), transform .2s ease, box-shadow .2s ease;
}
.sidebar-edge-toggle:hover { transform: translate(-50%, -50%) scale(1.08); box-shadow: 3px 0 18px -2px rgba(79,70,229,.7); }
.sidebar-edge-toggle svg { transition: transform .28s var(--ease); }
html.sidebar-collapsed .sidebar-edge-toggle { left: 0; }
html.sidebar-collapsed .sidebar-edge-toggle svg { transform: rotate(180deg); }
.company-switch-wrap { position: relative; margin-bottom: 14px; }
.company-switch {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px;
  border: none; background: none; width: 100%; text-align: left;
}
.company-switch:hover { background: var(--panel-2); }
.company-avatar {
  width: 32px; height: 32px; border-radius: 9px; background: var(--grad-2); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 14px; flex-shrink: 0;
  box-shadow: 0 3px 8px -2px rgba(79,70,229,.5);
}
.company-name { font-weight: 700; font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }

.company-menu {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border); border-radius: 14px; padding: 6px; box-shadow: var(--shadow-lg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  display: none; flex-direction: column; z-index: 60; max-height: 320px; overflow-y: auto;
}
.company-menu.is-open { display: flex; }
.company-menu-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 9px; border-radius: 9px;
  color: var(--text); font-size: 13.5px; background: none; border: none; width: 100%; text-align: left;
}
.company-menu-item:hover { background: var(--panel-2); }
.company-menu-item.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.company-menu hr { border: none; border-top: 1px solid var(--border); margin: 5px 0; }
.company-add-form { display: flex; gap: 6px; padding: 6px; }
.company-add-form input {
  flex: 1; min-width: 0; background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 7px 10px; font-size: 12.5px; color: var(--text); outline: none;
}
.company-add-form input:focus { border-color: var(--primary); }

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; overflow-x: hidden; }
.sidebar-nav a {
  display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 12px; position: relative;
  color: var(--text); font-size: 14px; font-weight: 500; transition: background .15s ease, color .15s ease, transform .25s var(--ease), box-shadow .2s ease;
}
.sidebar-nav a svg { color: var(--dim); flex-shrink: 0; transition: color .15s ease, transform .2s var(--ease); }
.sidebar-nav a:hover { background: var(--panel-2); transform: translateX(4px); }
.sidebar-nav a:hover svg { transform: translateX(1px) scale(1.06); }
.sidebar-nav a.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; box-shadow: 0 4px 14px -4px rgba(79,70,229,.15); }
.sidebar-nav a.is-active svg { color: var(--primary); }
.sidebar-nav a.is-active::before {
  content: ''; position: absolute; left: 0px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 3px; background: var(--primary);
}
.nav-section-label { font-size: 11.5px; color: var(--faint); margin: 16px 12px 6px; font-weight: 500; }

.sidebar-credits { display: block; background: var(--panel-2); border-radius: 12px; padding: 10px 12px; margin-top: 10px; color: var(--text); }
.sidebar-credits:hover { background: var(--border); }
.sidebar-credits-head { display: flex; align-items: center; justify-content: space-between; font-size: 11.5px; color: var(--dim); font-weight: 600; }
.sidebar-credits-pct { font-size: 15px; font-weight: 800; margin-top: 2px; }
.sidebar-credits-bar { height: 5px; background: var(--border); border-radius: 999px; overflow: hidden; margin-top: 6px; }
.sidebar-credits-bar i { display: block; height: 100%; border-radius: 999px; transition: width .5s var(--ease); }

.account-box { position: relative; border-top: 1px solid var(--border); padding-top: 10px; margin-top: 10px; }
.account-box-btn {
  display: flex; align-items: center; gap: 10px; width: 100%; background: none; border: none; padding: 8px 10px;
  border-radius: 10px; text-align: left; color: var(--text);
}
.account-box-btn:hover { background: var(--panel-2); }
.account-avatar {
  width: 34px; height: 34px; border-radius: 9px; background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #78350f;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 14px; flex-shrink: 0;
  box-shadow: 0 3px 8px -2px rgba(245,158,11,.4);
}
.account-name-block { min-width: 0; }
.account-name-block strong { display: block; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-name-block span { display: block; font-size: 12px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-menu {
  position: absolute; bottom: calc(100% + 8px); left: 0; right: 0;
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 14px; padding: 6px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  display: none; flex-direction: column; z-index: 999999 !important;
  opacity: 1 !important;
}
.account-menu.is-open { display: flex; }
.account-menu a, .account-menu button, .account-menu-item-row {
  display: flex; align-items: center; justify-content: flex-start; gap: 10px; padding: 9px 12px;
  border-radius: 8px; color: var(--text); font-size: 13.5px; background: none; border: none; width: 100%; text-align: left;
}
.account-menu a:hover, .account-menu button:hover, .account-menu-item-row:hover { background: var(--panel-2); }
.account-menu hr { border: none; border-top: 1px solid var(--border); margin: 5px 0; }
.account-menu-icon { display: flex; align-items: center; justify-content: center; width: 20px; flex-shrink: 0; color: var(--dim); }
.account-menu-label { flex: 1; min-width: 0; }
.lang-select-inline {
  appearance: none; -webkit-appearance: none; border: none; background: none; outline: none;
  color: var(--faint); font-size: 13px; text-align: right; cursor: pointer; padding: 0;
}
.account-menu-chevron { color: var(--faint); flex-shrink: 0; }

.nav-pro-badge {
  background: linear-gradient(135deg, #a855f7, #6366f1);
  color: #ffffff;
  font-size: 10px;
  font-weight: 800;
  padding: 2px 6px;
  border-radius: 6px;
  margin-left: auto;
  letter-spacing: 0.5px;
  box-shadow: 0 2px 8px rgba(168, 85, 247, 0.4);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.sidebar-nav a:hover .nav-pro-badge {
  transform: scale(1.08);
  box-shadow: 0 4px 12px rgba(168, 85, 247, 0.6);
}

/* ---------- custom themed dropdown (replaces ugly native <select> lists) ---------- */
.cd-wrap { position: relative; }
select.cd-native { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; margin: 0; }
.cd-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
  background: var(--panel-2); border: 1px solid transparent; border-radius: 12px; padding: 11px 14px;
  font-size: 14px; color: var(--text); text-align: left; cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.cd-trigger:hover { border-color: var(--border); }
.cd-wrap.is-open .cd-trigger { border-color: var(--primary); }
.cd-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cd-chevron { color: var(--faint); flex-shrink: 0; transition: transform .2s ease; }
.cd-wrap.is-open .cd-chevron { transform: rotate(180deg); }
.cd-menu {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 9005; max-height: 264px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 6px;
  box-shadow: var(--shadow-lg); display: none; -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.cd-wrap.is-open .cd-menu { display: block; animation: cd-in .16s var(--ease); }
@keyframes cd-in { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
.cd-item {
  display: block; width: 100%; text-align: left; padding: 9px 12px; border: none; background: none;
  border-radius: 8px; font-size: 14px; color: var(--text); cursor: pointer; white-space: nowrap;
}
.cd-search-wrap { padding: 4px; margin-bottom: 4px; border-bottom: 1px solid var(--border); position: sticky; top: -6px; background: inherit; z-index: 10; }
.cd-search-input { width: 100%; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 14px; background: var(--panel-2); color: var(--text); outline: none; }
.cd-search-input:focus { border-color: var(--primary); }
.cd-item:hover { background: var(--panel-2); }
.cd-item.is-active { background: var(--primary); color: #fff; }
/* country-code picker in the phone row: keep it compact, don't stretch */
.cd-wrap:has(select[name="country_code"]) { flex: 0 0 auto; width: 118px; }
.cd-wrap:has(select[name="country_code"]) .cd-menu { min-width: 150px; }
/* Phone field = compact country picker + number input that takes the rest.
   min-width:0 on the input is what actually lets it shrink inside the flex row
   -- without it an input's default intrinsic width keeps the row wider than
   its container and pushes the whole card past the screen edge on a phone. */
.phone-row { display: flex; gap: 8px; align-items: stretch; min-width: 0; }
.phone-row > input[data-phone-input] { flex: 1 1 auto; min-width: 0; letter-spacing: .02em; }
/* language picker (auth top-right + account menu): compact, right-aligned menu */
.auth-lang .cd-wrap .cd-trigger, .lang-row .cd-wrap .cd-trigger { background: none; padding: 4px 6px; font-size: 13px; color: var(--dim); }
.auth-lang .cd-menu, .lang-row .cd-menu { left: auto; right: 0; min-width: 150px; }

/* ---------- main area ---------- */
.main-area { flex: 1; min-width: 0; display: flex; flex-direction: column; position: relative; }
.topbar { display: flex; align-items: center; justify-content: space-between; padding: 18px 28px 0; position: relative; z-index: 1; }
.topbar h1 { font-size: 23px; font-weight: 800; letter-spacing: -.02em; }
.page-content { padding: 20px 28px 90px; flex: 1; position: relative; z-index: 1; }
.engine-status { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--faint); }
.theme-toggle-btn {
  display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%;
  color: var(--dim); border: 1px solid var(--glass-border); background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  transition: color .2s ease, transform .2s var(--ease), border-color .2s ease;
}
.theme-toggle-btn:hover { color: var(--primary); border-color: var(--primary); transform: rotate(14deg); }
.engine-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); position: relative; }
.engine-dot::after {
  content: ''; position: absolute; inset: -4px; border-radius: 50%; background: var(--green);
  opacity: .35; animation: dot-pulse 2.2s ease-out infinite;
}
.engine-dot.is-off { background: var(--danger); }
.engine-dot.is-off::after { background: var(--danger); animation: none; opacity: 0; }
@media (prefers-reduced-motion: reduce) { .engine-dot::after { animation: none; } }
@keyframes dot-pulse {
  0% { transform: scale(.6); opacity: .45; }
  70% { transform: scale(1.9); opacity: 0; }
  100% { opacity: 0; }
}

/* floating call button (bottom-right, like gramir) */
.call-fab {
  position: fixed; right: 26px; bottom: 26px; width: 58px; height: 58px; border-radius: 50%;
  background: #22c55e; color: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 24px -6px rgba(34,197,94,.55); z-index: 80;
  transition: transform .25s var(--ease), box-shadow .25s ease, opacity .22s ease;
}
.call-fab:hover { transform: scale(1.08); box-shadow: 0 14px 30px -6px rgba(34,197,94,.65); }
/* The call button used to sit on top of the content permanently and got in the
   way of real actions (owner's report: "мешает при действие в любом
   устройстве"). It now gets out of the way on its own -- while scrolling down
   through content, while a modal/drawer is open, and while a field is focused
   (i.e. the on-screen keyboard is up) -- and comes back as soon as the user
   stops or scrolls up. dashboard.js toggles these classes. pointer-events:none
   matters as much as the fade: a fully transparent button would otherwise
   still swallow the tap meant for whatever is underneath it. */
.call-fab { opacity: 1; pointer-events: auto; }
.call-fab.fab-hidden {
  opacity: 0; pointer-events: none; transform: translateY(14px) scale(.9);
}
@media (prefers-reduced-motion: reduce) { .call-fab.fab-hidden { transform: none; } }
.call-fab::before {
  content: ''; position: absolute; inset: -6px; border-radius: 50%; border: 2px solid #22c55e;
  opacity: 0; animation: fab-ring 2.8s ease-out infinite;
}
@media (prefers-reduced-motion: reduce) { .call-fab::before { animation: none; } }
@keyframes fab-ring {
  0% { transform: scale(.85); opacity: .55; }
  100% { transform: scale(1.35); opacity: 0; }
}

/* ---------- cards / tables / forms ---------- */
.card {
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius);
  padding: 20px; box-shadow: var(--shadow); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.card + .card { margin-top: 16px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }

.stat-card {
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius);
  padding: 18px 20px; box-shadow: var(--shadow); position: relative; overflow: hidden;
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.stat-card::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--grad-2); opacity: 0; transition: opacity .25s ease;
}
.stat-card:hover::before { opacity: 1; }
.stat-card .lbl { font-size: 13px; color: var(--dim); display: flex; align-items: center; gap: 8px; }
.stat-card .lbl svg { color: var(--faint); }
.stat-card .val {
  font-family: 'Outfit',sans-serif; font-size: 32px; font-weight: 800; margin-top: 8px;
  background: var(--grad-2); -webkit-background-clip: text; background-clip: text; color: transparent;
}

.data-table { width: 100%; border-collapse: collapse; }
.data-table th { text-align: left; font-size: 12px; font-weight: 600; color: var(--faint); padding: 10px 14px; border-bottom: 1px solid var(--border); }
.sort-link:hover { color: var(--text); }
.data-table td { padding: 13px 14px; border-bottom: 1px solid var(--border); font-size: 14px; color: var(--text); vertical-align: middle; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tr:hover td { background: var(--panel-2); }

.icon-btn { background: none; border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; color: var(--dim); font-size: 13px; }
.icon-btn:hover { color: var(--danger); border-color: var(--danger); }

.search-input {
  display: flex; align-items: center; gap: 8px; background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 9px 14px; width: 280px; max-width: 100%;
}
/* min-width:0 -- without it the inner <input>'s intrinsic width (~180px) plus
   this row's padding kept the whole search box from shrinking, so .search-input
   stayed 280px wide despite its own max-width:100% and pushed the page sideways
   on a 240px screen (Galaxy Fold folded). Same root cause as .phone-row. */
.search-input input { border: none; outline: none; background: none; flex: 1; min-width: 0; font-size: 14px; color: var(--text); }
.search-input svg { color: var(--faint); flex-shrink: 0; }

.form-field { margin-bottom: 15px; }
.form-field label { display: block; font-size: 13px; color: var(--dim); margin-bottom: 6px; font-weight: 600; }
.form-field input, .form-field textarea, .form-field select {
  width: 100%; background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 14px; color: var(--text); outline: none; transition: border-color .2s ease, box-shadow .2s ease;
}
.form-field input[type="checkbox"], .form-field input[type="radio"] {
  width: 16px; height: 16px; padding: 0; border: none; background: none; flex-shrink: 0; accent-color: var(--primary);
}
.form-field input:focus, .form-field textarea:focus, .form-field select:focus {
  border-color: var(--primary); box-shadow: 0 0 0 3px rgba(37,99,235,.12);
}
.form-field textarea { resize: vertical; min-height: 90px; }
.form-row { display: flex; gap: 14px; }
.form-row .form-field { flex: 1; }

.badge-status { display: inline-flex; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge-status.open, .badge-status.active, .badge-status.succeeded, .badge-status.sent { background: var(--green-soft); color: var(--green); }
.badge-status.unassigned, .badge-status.draft, .badge-status.trialing, .badge-status.pending { background: var(--amber-soft); color: var(--amber); }
.badge-status.resolved { background: var(--violet-soft); color: var(--violet); }

.page-head-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; flex-wrap: wrap; gap: 12px; }
.page-head-row h2 { font-size: 19px; font-weight: 800; }
.page-head-row p { color: var(--dim); font-size: 13.5px; margin-top: 4px; }

.empty-state { text-align: center; padding: 70px 20px; color: var(--dim); }
.empty-icon {
  font-size: 44px; margin: 0 auto 14px; width: 84px; height: 84px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle, var(--primary-soft) 0%, transparent 72%);
}
.empty-state h3 { color: var(--text); font-size: 20px; font-weight: 800; margin-bottom: 10px; }
.empty-state p { max-width: 480px; margin: 0 auto 22px; line-height: 1.6; font-size: 14.5px; }
.empty-icons { display: flex; justify-content: center; gap: 14px; margin-bottom: 26px; }
.chan {
  width: 54px; height: 54px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff;
  box-shadow: 0 8px 18px -6px rgba(16,24,40,.25); flex-shrink: 0;
}
.chan.tg { background: #34aadf; }
.chan.ig { background: radial-gradient(circle at 30% 110%, #fdf497 0%, #fd5949 45%, #d6249f 60%, #285AEB 90%); }
.chan.ms { background: linear-gradient(45deg, #0695ff, #a334fa, #ff6968); }
.chan.fb { background: #1877f2; }
.chan.vk { background: #0077ff; }

/* connected-accounts list: proper clickable row cards instead of a bare table */
.account-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 24px; }
.account-row {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px; color: inherit;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius);
  box-shadow: var(--shadow); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  transition: transform .15s var(--ease), border-color .15s var(--ease);
}
.account-row:hover { border-color: var(--primary); transform: translateY(-1px); }
.account-row:active { transform: translateY(0); }
.account-row-avatar { width: 44px; height: 44px; font-size: 17px; flex-shrink: 0; }
.account-row-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.account-row-info strong { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-row-meta { font-size: 12.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-row .badge-status { flex-shrink: 0; }
.account-row-chevron { color: var(--faint); flex-shrink: 0; }

/* channel-connect cards: was pure inline-style duplication per card, now one shared look */
.connect-solo { max-width: 340px; }
.connect-card { text-align: center; padding: 28px 24px; transition: transform .15s var(--ease), box-shadow .15s var(--ease); }
.connect-card:hover { transform: translateY(-2px); box-shadow: 0 14px 30px -14px rgba(16,24,40,.22); }
.connect-card .chan { margin: 0 auto 14px; }
.connect-card h3 { font-size: 17px; }
.connect-card p { font-size: 13.5px; color: var(--dim); margin: 8px 0 18px; }

.toast {
  position: fixed; top: 18px; right: 18px; background: var(--panel); border: 1px solid var(--green);
  box-shadow: var(--shadow-lg); border-radius: 12px; padding: 13px 20px; font-size: 14px; z-index: 300;
  animation: toast-in .4s var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }

/* ---------- chat bubbles (Native Theme) ---------- */
.msg {
  position: relative;
  padding: 8px 12px 6px; border-radius: 14px; font-size: 14px; line-height: 1.45; max-width: min(78%, 520px);
  display: flex; flex-direction: column; word-break: break-word;
  transition: transform .12s ease;
  box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
.msg-delete-btn {
  position: absolute; top: -8px; right: -8px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--panel); border: 1px solid var(--border); color: var(--dim); font-size: 13px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0;
  opacity: 0; transform: scale(.7); transition: opacity .15s, transform .15s; box-shadow: 0 2px 8px rgba(0,0,0,.2);
  z-index: 5;
}
.msg:hover .msg-delete-btn { opacity: 1; transform: scale(1); }
.msg-delete-btn:hover { background: #ef4444; color: #fff; border-color: #ef4444; }
.msg-out .msg-delete-btn { right: auto; left: -8px; }

.msg-text { white-space: pre-wrap; font-size: 14px; }
.msg-time { align-self: flex-end; font-size: 11px; margin-top: 3px; opacity: 0.75; white-space: nowrap; display: inline-flex; align-items: center; gap: 3px; }
.msg-check { letter-spacing: -2px; color: #6ab3f3; font-weight: 800; font-size: 12px; }

/* Inbound / Outbound Colors */
.msg-in {
  background: var(--panel-2); color: var(--text); align-self: flex-start; border-bottom-left-radius: 3px;
  border: 1px solid var(--border); box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.msg-out {
  background: var(--primary); color: #ffffff; align-self: flex-end; border-bottom-right-radius: 3px;
  border: 1px solid rgba(255,255,255,0.08); box-shadow: 0 1px 4px rgba(0,0,0,0.15);
}
.msg-out .msg-check { color: #ffffff; opacity: 0.8; }
.msg-out.msg-ai {
  background: linear-gradient(135deg, var(--primary) 0%, #8b5cf6 100%); color: #ffffff;
}

:root[data-theme="dark"] .msg-in {
  background: var(--panel-2); color: var(--text); border-color: rgba(255,255,255,0.05);
}
:root[data-theme="dark"] .msg-out {
  background: var(--primary); color: #ffffff; border-color: rgba(255,255,255,0.1);
}
:root[data-theme="dark"] .msg-out.msg-ai {
  background: linear-gradient(135deg, var(--primary) 0%, #8b5cf6 100%); color: #ffffff;
}

/* Make chat seamless with the app theme */
.inbox-shell { border: none !important; box-shadow: none !important; }
.conv-thread { border: none !important; }


/* media messages */
.msg:has(.voice-player), .msg:has(.video-note), .msg:has(.msg-video), .msg:has(.msg-photo) { max-width: 320px; }
.msg-video { max-width: 100%; border-radius: 8px; display: block; }
.msg-photo { max-width: 100%; border-radius: 8px; display: block; cursor: zoom-in; }
.msg-file { font-weight: 600; text-decoration: underline; word-break: break-all; }
.msg-in .msg-file { color: var(--primary); }
.msg-transcript { font-size: 13px; color: var(--dim); margin-top: 6px; white-space: pre-wrap; padding: 4px 0 0; border-top: 1px solid rgba(127,145,164,0.2); }

/* Telegram-style voice message player */
.voice-player { display: flex; align-items: center; gap: 10px; min-width: 160px; padding: 2px; }
.voice-play-btn {
  width: 36px; height: 36px; border-radius: 50%; background: #3b82f6; color: #fff; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; border: none; cursor: pointer; transition: background 0.15s;
}
:root[data-theme="dark"] .msg-out .voice-play-btn { background: #5288c1; }
:root[data-theme="dark"] .msg-in .voice-play-btn { background: #2b5278; }
.voice-play-btn:hover { filter: brightness(1.1); }
.voice-play-btn .icon-play { margin-left: 2px; width: 14px; height: 14px; }
.voice-play-btn .icon-pause { display: none; width: 14px; height: 14px; }
.voice-play-btn.is-playing .icon-play { display: none; }
.voice-play-btn.is-playing .icon-pause { display: block; }

.voice-wave { position: relative; flex: 1; height: 22px; min-width: 90px; display: flex; align-items: center; }
.voice-wave-bg, .voice-wave-fg-inner { display: flex; align-items: center; gap: 2px; height: 100%; width: 100%; }
.voice-wave-bg span, .voice-wave-fg-inner span { width: 2.5px; border-radius: 2px; flex-shrink: 0; }
.voice-wave-bg span { background: rgba(127,145,164,0.4); }
.voice-wave-fg-inner span { background: #5288c1; }
:root[data-theme="dark"] .msg-out .voice-wave-fg-inner span { background: #ffffff; }
.voice-wave-fg { position: absolute; left: 0; top: 0; height: 100%; width: 0%; overflow: hidden; transition: width 0.1s linear; }
.voice-duration { font-size: 11px; font-weight: 500; color: var(--faint); flex-shrink: 0; min-width: 28px; text-align: right; }

/* Telegram-style circular Video Note */
.video-note {
  position: relative; width: 210px; height: 210px; border-radius: 50%; overflow: hidden;
  background: #000; display: flex; align-items: center; justify-content: center; cursor: pointer;
  box-shadow: 0 8px 30px rgba(0,0,0,0.45); border: 3px solid rgba(139,92,246,0.6);
  transition: transform .2s ease, border-color .2s ease;
}
.video-note:hover { transform: scale(1.03); border-color: #8b5cf6; }
.video-note video { width: 100%; height: 100%; object-fit: cover; }
.video-note-play {
  position: absolute; inset: 0; margin: auto; width: 52px; height: 52px; border-radius: 50%;
  background: rgba(0,0,0,.5); border: 1.5px solid rgba(255,255,255,0.4); color: #fff; display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: opacity .15s ease, transform .15s ease; backdrop-filter: blur(8px);
}
.video-note-play:hover { transform: scale(1.1); }
.video-note-play .icon-pause { display: none; }
.video-note-play.is-playing { opacity: 0; }
.video-note-play.is-playing:hover { opacity: 1; }
.video-note-play.is-playing .icon-play { display: none; }
.video-note-play.is-playing .icon-pause { display: block; }
.video-note-duration {
  position: absolute; bottom: 12px; background: rgba(0,0,0,.65); color: #fff; font-size: 11px;
  font-weight: 700; padding: 3px 10px; border-radius: 999px; backdrop-filter: blur(6px);
}

.contact-notes-form { display: flex; flex-direction: column; gap: 8px; }
.contact-notes-form textarea {
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
  font-size: 13.5px; color: var(--text); resize: vertical; font-family: inherit;
}
.contact-notes-form .btn { align-self: flex-end; }
/* date separator pill, centered between message groups */
.msg-date { align-self: center; margin: 12px 0 4px; }
.msg-date span {
  font-size: 11.5px; font-weight: 600; color: var(--dim); background: var(--panel-2);
  padding: 3px 12px; border-radius: 999px;
}
.msg-meta { align-self: flex-end; font-size: 11px; color: var(--faint); padding: 0 4px; }

/* conversation-list search + add row (Telegram-style header) */
.conv-search-row { display: flex; gap: 8px; align-items: center; padding: 12px 14px 6px; }
.conv-search {
  flex: 1; display: flex; align-items: center; gap: 8px; background: var(--panel-2);
  border-radius: 999px; padding: 8px 14px; color: var(--faint);
}
.conv-search input { flex: 1; min-width: 0; border: none; background: none; outline: none; font-size: 13.5px; color: var(--text); }

/* ---------- contact info panel (3rd inbox column, gramir-style) ---------- */
.contact-panel { overflow-y: auto; padding: 20px 18px; min-width: 0; }
.contact-panel-head { font-size: 15px; font-weight: 700; margin-bottom: 18px; }
.contact-hero { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding-bottom: 20px; }
.contact-hero-avatar {
  width: 84px; height: 84px; border-radius: 50%; color: #fff; font-weight: 700; font-size: 32px;
  display: flex; align-items: center; justify-content: center; margin-bottom: 6px; object-fit: cover;
}
.contact-hero-name { font-size: 16px; font-weight: 700; word-break: break-word; }
.contact-hero-sub { font-size: 12.5px; color: var(--dim); display: flex; align-items: center; gap: 5px; }
.contact-section-title { font-size: 13px; font-weight: 700; color: var(--dim); margin: 8px 0 12px; }
.contact-field { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
.contact-field > svg { color: var(--faint); flex-shrink: 0; }
.contact-field .lbl { display: block; font-size: 11.5px; color: var(--faint); }
.contact-field .val { display: block; font-size: 14px; color: var(--text); word-break: break-word; }

.msg-new { animation: msg-in .3s var(--ease) both; }
@media (prefers-reduced-motion: reduce) { .msg-new { animation: none; } }
@keyframes msg-in { from { opacity: 0; transform: translateY(10px) scale(.97); } to { opacity: 1; transform: none; } }

/* ---------- inbox ---------- */
/* height (not min-height) + overflow:hidden bounds the panel to the viewport, so
   .thread-body scrolls internally and the input bar stays put instead of drifting
   down the page as messages accumulate */
.inbox-shell {
  display: grid; grid-template-columns: 320px minmax(0, 1fr) 300px; height: calc(100vh - 70px); overflow: hidden;
  transition: grid-template-columns .18s var(--ease);
}
/* manual close of the contact panel (top-right toggle button), independent of
   the auto-hide-on-narrow-viewport media query below */
/* bleeds the inbox out to the page-content padding edges (was an inline style;
   made a class so the mobile media query can actually override it -- inline
   styles win over stylesheets) */
.inbox-bleed { margin: -20px -28px -90px; }
.inbox-shell.contact-panel-hidden { grid-template-columns: 320px minmax(0, 1fr) 0; }
.inbox-shell.contact-panel-hidden .contact-panel { display: none; }
#contactPanelToggle { padding: 7px; line-height: 0; }
#contactPanelToggle:hover { color: var(--primary); border-color: var(--primary); }
/* drop the contact panel first when space gets tight, before the full mobile stack */
@media (max-width: 1150px) {
  .inbox-shell { grid-template-columns: 300px minmax(0, 1fr); }
  .contact-panel { display: none; }
  /* deliberately no background/backdrop-filter here: a distinct translucent panel
     over the page mesh created visible tonal "frame" lines at its top/bottom edges
     (repeatedly flagged) — the inbox now blends seamlessly into the page. */
}
.conv-list { overflow-y: auto; display: flex; flex-direction: column; min-height: 0; background: var(--panel); border-right: 1px solid var(--border); }
.conv-search-row { padding: 12px 14px 4px; }
.conv-search { display: flex; align-items: center; background: var(--panel-2); border-radius: 20px; padding: 0 12px; height: 36px; border: 1px solid transparent; transition: border-color .2s, background .2s; }
.conv-search:focus-within { border-color: var(--primary); background: transparent; }
.conv-search svg { color: var(--faint); margin-right: 8px; flex-shrink: 0; }
.conv-search input { flex: 1; min-width: 0; background: transparent; border: none; color: var(--text); font-size: 13.5px; outline: none; }
.conv-tabs { display: flex; gap: 6px; padding: 10px 14px 14px; flex-wrap: wrap; }
.conv-tab { padding: 6px 14px; border-radius: 20px; font-size: 13px; font-weight: 600; color: var(--dim); background: transparent; transition: background .15s, color .15s; }
.conv-tab:hover { background: rgba(127,145,164,0.1); color: var(--text); }
.conv-tab.is-active { background: var(--primary); color: #fff; }
.conv-item { display: flex; flex-direction: column; gap: 4px; padding: 13px 16px; color: inherit; }
.conv-avatar {
  width: 38px; height: 38px; border-radius: 50%; color: #fff; font-weight: 700; font-size: 15px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; object-fit: cover;
}
.msg-ai { background: linear-gradient(135deg, #2563eb, #7c3aed); }
.msg-operator { background: #0e9f8a; }
.msg-meta-left { align-self: flex-start; font-size: 11px; color: var(--faint); padding: 0 4px; }
.conv-item:hover, .conv-item.is-active { background: var(--primary-soft); }
.conv-item-flash { animation: conv-flash 1.6s var(--ease) both; }
@media (prefers-reduced-motion: reduce) { .conv-item-flash { animation: none; } }
@keyframes conv-flash {
  0% { background: var(--primary-soft); }
  100% { background: transparent; }
}
.conv-item-top { display: flex; justify-content: space-between; font-size: 13.5px; font-weight: 700; }
.conv-item-top time { font-weight: 500; color: var(--faint); font-size: 11.5px; }
.conv-item-preview { font-size: 12.5px; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-thread { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.thread-head { padding: 14px 22px; display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.thread-body { flex: 1; overflow-y: auto; padding: 22px; display: flex; flex-direction: column; gap: 10px; }
.thread-input { padding: 12px 22px; display: flex; gap: 10px; flex-wrap: wrap; }
.thread-input input { flex: 1; min-width: 160px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 10px 18px; color: var(--text); outline: none; }
.thread-input input:focus { border-color: var(--primary); }
.ai-toggle-label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--dim); }
/* The round send icon is mobile-only chrome — desktop keeps the text button. */
.thread-send .send-icon { display: none; }

/* Telegram-style chat list rows: fixed avatar, name left / time right on one
   tidy line, single-line preview underneath — nothing wraps or jitters. */
.conv-item { flex-direction: row; align-items: center; gap: 0; padding: 11px 14px; border-radius: 12px; margin: 2px 6px; }
.conv-item-top time { flex-shrink: 0; margin-left: 8px; }
.conv-item-top span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- broadcasts (compose + live preview, gramir-style) ---------- */
.bc-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.bc-file-drop {
  width: 96px; height: 96px; border: 2px dashed var(--border); border-radius: 14px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: border-color .2s ease, color .2s ease;
}
.bc-file-drop:hover { border-color: var(--primary); }
.bc-file-plus { font-size: 26px; color: var(--faint); font-weight: 400; }
.bc-file-drop:hover .bc-file-plus { color: var(--primary); }
.bc-preview { min-height: 120px; }
.bc-bubble {
  background: linear-gradient(135deg, #2563eb, #7c3aed); color: #fff; padding: 11px 15px; border-radius: 16px;
  border-bottom-right-radius: 5px; font-size: 14px; line-height: 1.5; max-width: 90%; margin-left: auto; word-break: break-word;
}
@media (max-width: 900px) { .bc-grid { grid-template-columns: 1fr; } }

/* ---------- broadcast recipient picker (accounts -> individual contacts) ---------- */
.bc-recipients { position: relative; }
.bc-recipients-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px; padding: 11px 14px;
  font-size: 14px; color: var(--text); cursor: pointer; text-align: left;
}
.bc-recipients.is-open .bc-recipients-trigger { border-color: var(--primary); }
.bc-recipients-panel {
  display: none; position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 60;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-lg);
  padding: 10px; max-height: 380px; overflow-y: auto;
}
.bc-recipients.is-open .bc-recipients-panel { display: block; }
.bc-account-row { display: flex; align-items: center; gap: 8px; padding: 8px 6px; border-radius: 10px; }
.bc-account-row:hover { background: var(--panel-2); }
.bc-row-info { display: flex; flex-direction: column; min-width: 0; }
.bc-row-info strong { font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bc-row-info small { font-size: 12px; color: var(--faint); }
.bc-drill-btn { background: none; border: none; color: var(--faint); cursor: pointer; padding: 6px; flex-shrink: 0; }
.bc-drill-btn:hover { color: var(--primary); }
.bc-back-btn {
  display: flex; align-items: center; gap: 6px; background: none; border: none; color: var(--dim);
  font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 2px;
}
.bc-back-btn:hover { color: var(--primary); }
.bc-level2-head { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; color: var(--dim); padding: 4px 6px 8px; }
.bc-deselect-link { background: none; border: none; color: var(--primary); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.bc-contact-list { display: flex; flex-direction: column; gap: 2px; max-height: 260px; overflow-y: auto; }
.bc-contact-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px; border-radius: 10px; cursor: pointer; }
.bc-contact-row:hover { background: var(--panel-2); }

/* ---------- broadcast preview: phone mockup ---------- */
.bc-phone-mock {
  width: 260px; margin: 0 auto; border-radius: 30px; overflow: hidden; border: 7px solid #1c1c1e;
  background: #111; box-shadow: 0 20px 40px -14px rgba(16,24,40,.35);
}
.bc-phone-statusbar {
  display: flex; align-items: center; justify-content: space-between; padding: 8px 16px 4px;
  font-size: 12px; font-weight: 700; color: #fff; background: #1a4f6e;
}
.bc-phone-icons { display: flex; align-items: center; gap: 5px; }
.bc-phone-chatheader { display: flex; align-items: center; gap: 8px; padding: 6px 12px 10px; background: #1a4f6e; color: #fff; }
.bc-phone-back { font-size: 20px; font-weight: 300; position: relative; padding-right: 6px; }
.bc-phone-badge {
  position: absolute; top: -4px; right: -6px; background: #ff453a; color: #fff; font-size: 10px; font-weight: 700;
  border-radius: 999px; min-width: 15px; height: 15px; display: flex; align-items: center; justify-content: center; padding: 0 3px;
}
.bc-phone-namewrap { display: flex; flex-direction: column; min-width: 0; }
.bc-phone-name { font-size: 14px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bc-phone-status { font-size: 11px; opacity: .75; }
.bc-phone-body {
  min-height: 320px; padding: 18px 12px; display: flex; flex-direction: column; justify-content: flex-end;
  background-color: #b7d9b9;
  background-image: radial-gradient(rgba(255,255,255,.35) 1.5px, transparent 1.5px);
  background-size: 18px 18px;
}
.bc-phone-body .bc-bubble { max-width: 85%; }

/* Every on/off switch site-wide reads as red = off, green = on — one
consistent color language for every toggle (permissions, auto-assign,
status, AI on/off in the inbox, etc.) instead of mixing a blue/grey style
in some places and green/red in others. */
.switch { width: 42px; height: 24px; border-radius: 999px; background: #ef4444; border: none; position: relative; transition: background .25s ease; flex-shrink: 0; }
.switch.is-on, .switch[aria-checked="true"] { background: #22c55e; }
.switch-knob { position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: transform .25s var(--ease); box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.switch.is-on .switch-knob, .switch[aria-checked="true"] .switch-knob { transform: translateX(18px); }
.perm-locked { cursor: default; }
.perm-row { display: flex; align-items: center; justify-content: space-between; padding: 7px 0; font-size: 13.5px; }
.perm-grid { padding-right: 4px; max-height: 220px; overflow-y: auto; }

/* ---------- responsive visibility ----------
   Some views genuinely need a DIFFERENT component on a phone, not the same
   one reflowed (a 7x24 heatmap, a 140px donut, a 4-column stat grid). These
   two classes let a template ship both and let CSS pick -- the mobile
   counterpart is authored for touch first, it is not the desktop one resized. */
/* The swap happens at 700px, NOT at the 900px drawer/tab-bar breakpoint: a
   tablet (iPad portrait is 768px) has plenty of room for the richer desktop
   widgets -- the donut, the full 7x24 heatmap -- and downgrading those to the
   phone versions there would throw away detail for no reason. Below 700px the
   phone-native components take over. */
.mobile-only { display: none !important; }
@media (max-width: 700px) {
  .desktop-only { display: none !important; }
  .mobile-only { display: revert !important; }
  .mobile-only.stat-strip, .mobile-only.hour-bars { display: flex !important; }
  .mobile-only.channel-bar-list { display: flex !important; }
}


/* ---------- analytics ---------- */
.analytics-row { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); gap: 16px; }
.analytics-head { gap: 10px; }
.range-switch { display: inline-flex; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 3px; gap: 2px; }
.range-opt {
  padding: 6px 14px; border-radius: 999px; font-size: 13px; font-weight: 600;
  color: var(--dim); transition: background .18s var(--ease), color .18s var(--ease); white-space: nowrap;
}
.range-opt.is-active { background: var(--primary); color: #fff; }

.stat-card .trend { font-size: 12px; font-weight: 700; margin-top: 6px; }
.stat-card .trend.up { color: var(--green); }
.stat-card .trend.down { color: var(--danger); }

.chart-row { display: flex; gap: 8px; }
.chart-y-labels { position: relative; width: 26px; flex-shrink: 0; height: 180px; }
.chart-y-labels span { position: absolute; right: 4px; transform: translateY(-50%); font-size: 10.5px; color: var(--faint); }
.chart-plot { flex: 1; min-width: 0; position: relative; }
.line-chart { width: 100%; height: 180px; display: block; overflow: visible; }
.chart-x-labels { position: relative; height: 16px; margin-top: 4px; }
.chart-x-labels span { position: absolute; transform: translateX(-50%); font-size: 10.5px; color: var(--faint); white-space: nowrap; }
.chart-tooltip {
  position: absolute; transform: translate(-50%, -125%); background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 12px; font-size: 12.5px; box-shadow: var(--shadow-lg); pointer-events: none;
  white-space: nowrap; z-index: 5;
}
.chart-tooltip b { display: block; font-size: 12px; color: var(--dim); font-weight: 700; margin-bottom: 2px; }
.chart-tooltip span { color: var(--primary); font-weight: 700; }

.donut-row { display: flex; align-items: center; gap: 24px; }
.donut-wrap { position: relative; width: 140px; height: 140px; flex-shrink: 0; }
.donut-chart { width: 100%; height: 100%; }
.donut-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.donut-center strong { font-size: 22px; font-weight: 800; }
.donut-center span { font-size: 11.5px; color: var(--dim); }
.channel-legend { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.channel-legend-row { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.channel-legend-row .dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.channel-legend-row .lbl { flex: 1; font-weight: 600; }
.channel-legend-row .pct { color: var(--dim); }

.heatmap { display: grid; grid-template-columns: 34px repeat(24, 1fr); gap: 3px; align-items: center; }
.heatmap .hm-day { font-size: 11px; color: var(--faint); }
.heatmap .hm-hour { font-size: 9.5px; color: var(--faint); text-align: center; margin-bottom: 2px; }
.heatmap .hm-cell {
  aspect-ratio: 1;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  cursor: default;
  transition: transform .2s ease, box-shadow .2s ease, background .2s ease;
  width: 14px;
  height: 14px;
  margin: auto;
}
.heatmap .hm-cell:hover {
  transform: scale(1.4);
  z-index: 5;
}
.heatmap .hm-cell[data-l="1"] {
  background: rgba(139, 92, 246, 0.45);
  box-shadow: 0 0 4px rgba(139, 92, 246, 0.3);
}
.heatmap .hm-cell[data-l="2"] {
  background: rgba(99, 102, 241, 0.85);
  box-shadow: 0 0 8px rgba(99, 102, 241, 0.6);
}
.heatmap .hm-cell[data-l="3"] {
  background: #38bdf8;
  box-shadow: 0 0 12px rgba(56, 189, 248, 0.9);
  animation: dotPulse 2s ease-in-out infinite alternate;
}

@keyframes dotPulse {
  0% { transform: scale(1); box-shadow: 0 0 8px rgba(56, 189, 248, 0.7); }
  100% { transform: scale(1.2); box-shadow: 0 0 16px rgba(56, 189, 248, 1); }
}

/* ---------- analytics chart entrance animation ---------- */
/* Intentionally NOT gated behind prefers-reduced-motion: the product owner
   explicitly wants these charts to animate on their own dashboard, and the OS
   setting here is a Windows default rather than a real accessibility need.
   Longer, more pronounced durations so the motion is unmistakable on load. */
.line-chart polyline {
  stroke-dasharray: 2000; stroke-dashoffset: 2000;
  animation: draw-line 1.6s var(--ease) .15s forwards;
}
.line-chart path { opacity: 0; animation: fade-in 1s ease .7s forwards; }
.line-chart line { opacity: 0; animation: fade-in .5s ease 1.1s forwards; }
.donut-chart {
  opacity: 0; transform: scale(.6) rotate(-25deg); transform-origin: center;
  animation: donut-in .8s var(--ease) .2s forwards;
}
.channel-legend-row { opacity: 0; animation: content-in .45s var(--ease) both; }
.channel-legend-row:nth-child(1) { animation-delay: .5s; }
.channel-legend-row:nth-child(2) { animation-delay: .62s; }
.channel-legend-row:nth-child(3) { animation-delay: .74s; }
.channel-legend-row:nth-child(n+4) { animation-delay: .86s; }
.stat-card .val { animation: pop-in .5s var(--ease) both; }
.stat-card:nth-child(1) .val { animation-delay: .05s; }
.stat-card:nth-child(2) .val { animation-delay: .12s; }
.stat-card:nth-child(3) .val { animation-delay: .19s; }
.stat-card:nth-child(4) .val { animation-delay: .26s; }
.heatmap .hm-cell { opacity: 0; transform: scale(.4); animation: cell-in .4s var(--ease) forwards; }
.heatmap .hm-cell:nth-child(8n+1) { animation-delay: .1s; }
.heatmap .hm-cell:nth-child(8n+2) { animation-delay: .16s; }
.heatmap .hm-cell:nth-child(8n+3) { animation-delay: .22s; }
.heatmap .hm-cell:nth-child(8n+4) { animation-delay: .28s; }
.heatmap .hm-cell:nth-child(8n+5) { animation-delay: .34s; }
.heatmap .hm-cell:nth-child(8n+6) { animation-delay: .4s; }
.heatmap .hm-cell:nth-child(8n+7) { animation-delay: .46s; }
.heatmap .hm-cell:nth-child(8n+8) { animation-delay: .52s; }
@keyframes draw-line { to { stroke-dashoffset: 0; } }
@keyframes donut-in { to { opacity: 1; transform: scale(1) rotate(0deg); } }
@keyframes fade-in { to { opacity: 1; } }
@keyframes pop-in { from { opacity: 0; transform: translateY(10px) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes cell-in { to { opacity: 1; transform: scale(1); } }
/* mobile: chat pane fades in when a conversation is opened. Deliberately
   opacity-ONLY, no transform: a translateX/Y entrance gets stuck at its
   from-state when the tab isn't compositing (backgrounded tab, slow device) --
   measured live: a translateX(13%) slide froze the whole thread 49px to the
   right, pushing the ⋮ button off-screen. Opacity stuck at 0.6 is at worst
   slightly dim for a frame; it never breaks layout or hides a control. */
@keyframes thread-slide-in { from { opacity: .4; } to { opacity: 1; } }
.heatmap-footer { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.heatmap-legend { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--faint); }
.heatmap-legend i { width: 12px; height: 12px; border-radius: 3px; background: var(--panel-2); }
.heatmap-legend i[data-l="1"] { background: #bfdbfe; }
.heatmap-legend i[data-l="2"] { background: #60a5fa; }
.heatmap-legend i[data-l="3"] { background: #2563eb; }
.heatmap-peak { font-size: 12.5px; color: var(--dim); }
.heatmap-peak strong { color: var(--text); }

/* ---------- billing / checkout ---------- */
.price-amount { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.price-amount .amount { font-family: 'Manrope',sans-serif; font-size: 34px; font-weight: 800; }
.price-amount .currency { font-size: 17px; font-weight: 700; color: var(--dim); }
.price-amount .per { font-size: 13px; color: var(--faint); }
.price-old { font-size: 17px; color: var(--faint); text-decoration: line-through; text-decoration-color: var(--danger); }
.amount-custom { font-size: 22px; }
.promo-badge { background: linear-gradient(135deg, #f59e0b, #ef4444); color: #fff; font-size: 11.5px; font-weight: 800; padding: 4px 10px; border-radius: 999px; }
/* minmax(0, ...), not a bare 1fr: a plain 1fr track's automatic minimum is its
   content's min-content width, so a card with a long untruncated line (a
   plan description) forced the whole grid ~23px past the viewport on
   desktop -- pre-existing, unrelated to today's mobile work, found while
   fixing the identical pattern on /app/analytics. */
.pricing-mini-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.pricing-mini-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); align-items: stretch; }
.pricing-mini-card {
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius);
  padding: 20px; box-shadow: var(--shadow); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  position: relative; display: flex; flex-direction: column;
}
.pricing-mini-card.is-current { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.pricing-mini-card.is-highlighted {
  border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary), var(--shadow-lg);
  transform: scale(1.03); z-index: 1;
}
.pricing-mini-card.is-highlighted.is-current { box-shadow: 0 0 0 2px var(--green), var(--shadow-lg); border-color: var(--green); }
.popular-badge {
  position: absolute; top: -13px; left: 50%; transform: translateX(-50%);
  background: var(--grad-2); color: #fff; font-size: 11px; font-weight: 800;
  padding: 4px 14px; border-radius: 999px; white-space: nowrap; box-shadow: 0 4px 10px -3px rgba(79,70,229,.5);
}
.plan-tokens { font-size: 12.5px; color: var(--dim); margin-top: 10px; }
.plan-desc { font-size: 13px; color: var(--dim); margin-top: 6px; min-height: 36px; }
.trial-note { font-size: 12px; color: var(--green); font-weight: 600; margin-top: 8px; }
.plan-features { margin-top: 18px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.plan-features li { font-size: 13px; color: var(--dim); padding-left: 24px; position: relative; }
.plan-features li::before {
  content: ''; position: absolute; left: 0; top: 2px; width: 15px; height: 15px; border-radius: 50%;
  background: var(--green-soft);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M5 13l4 4L19 7' stroke='%2322c55e' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center; background-size: 9px;
}
.plan-cta { margin-top: auto; padding-top: 16px; }
/* ---------- Telegram Native Sidebar ---------- */
.tg-sidebar { width: 320px; background: var(--panel); border-left: 1px solid var(--border); display: flex; flex-direction: column; overflow-y: auto; }
.tg-sidebar-header { padding: 16px 24px 10px; }
.tg-sidebar-title { font-size: 15px; font-weight: 600; color: var(--text); }
.tg-profile-hero { display: flex; flex-direction: column; align-items: center; padding: 20px 24px 12px; }
.tg-profile-avatar, .tg-profile-avatar-placeholder { width: 120px; height: 120px; border-radius: 50%; object-fit: cover; margin-bottom: 16px; }
.tg-profile-avatar-placeholder { display: flex; align-items: center; justify-content: center; color: #fff; font-size: 48px; font-weight: 600; }
.tg-profile-name { font-size: 18px; font-weight: 600; color: var(--text); text-align: center; margin-bottom: 4px; word-break: break-word; line-height: 1.2; }
.tg-profile-status { font-size: 14px; color: var(--dim); }
.tg-info-section { display: flex; flex-direction: column; padding: 8px 0; }
.tg-info-row { padding: 8px 24px; cursor: pointer; transition: background 0.1s; }
.tg-info-row:hover { background: rgba(127,145,164,0.08); }
.tg-info-val { font-size: 15px; color: var(--text); margin-bottom: 2px; word-break: break-all; }
.tg-info-lbl { font-size: 13.5px; color: var(--dim); }
.tg-notes-form { display: flex; flex-direction: column; gap: 12px; padding: 12px 24px 24px; }
.tg-notes-form textarea { background: transparent; border: 1px solid var(--border); border-radius: 12px; padding: 12px; font-family: inherit; font-size: 14px; color: var(--text); resize: none; }
.tg-notes-form textarea:focus { border-color: var(--primary); outline: none; }

@media (max-width: 900px) {
  .tg-sidebar { position: fixed; inset: auto 0 0 0; width: 100%; height: 75vh; border-left: none; border-top: 1px solid var(--border); border-radius: 20px 20px 0 0; z-index: 99; transform: translateY(100%); transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); }
  body.mobile-contact-open .tg-sidebar { transform: translateY(0); }
}
.pay-provider-btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; padding: 13px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel); font-weight: 700; font-size: 15px; margin-top: 10px; transition: border-color .2s ease, transform .2s var(--ease); }
.pay-provider-btn:hover { border-color: var(--primary); transform: translateY(-1px); }

/* ---------- auth pages ---------- */
/* deliberately plain and flat -- no glass, no card chrome, matches the clean
   reference design the user asked to follow rather than the dashboard's mesh look */
.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px; position: relative; }
.auth-card {
  width: 100%; max-width: 420px; padding: 8px 4px;
  /* NOT animation:content-in -- that keyframe moves through a transform
     (translateY), and a `transform` value (even mid-animation, even
     "stuck" at a from-state if the animation never finishes compositing)
     makes this element the CONTAINING BLOCK for any position:absolute
     descendant, no matter what `position` .auth-card itself computes to.
     That silently broke .auth-lang below: it's positioned absolute against
     "the page corner", but while auth-card had a lingering transform it was
     actually positioned against auth-card's OWN box instead, landing right
     on top of the card's title/fields (measured live: auth-lang at
     x=714,y=135 sitting inside the card's x=430-850,y=109-627 -- exactly
     the "переключатель языка стоит не на своём месте" report). Confirmed by
     forcing transform:none: the switcher snapped back to the correct
     viewport corner (x=1144,y=26). Simplest permanent fix is to never let
     this element carry a transform-based animation at all. */
  animation: auth-card-in .3s var(--ease);
}
@keyframes auth-card-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .auth-card { animation: none; } }
.auth-card .auth-logo {
  display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 19px;
  font-family: 'Manrope',sans-serif; margin-bottom: 20px;
  background: var(--grad-2); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.auth-card h1 { font-size: 24px; font-weight: 800; text-align: center; }
.auth-card p.sub { color: var(--dim); font-size: 14px; margin: 8px 0 28px; text-align: center; }
.auth-footer { text-align: center; margin-top: 20px; font-size: 13.5px; color: var(--dim); }
.auth-footer a { color: var(--primary); font-weight: 600; }
/* Where the Telegram code actually lands. Telegram delivers it as a message
   inside its own app, not as an SMS -- people watched their SMS inbox, saw
   nothing and assumed registration was broken, so this line is deliberately
   prominent rather than fine print. */
.verify-where {
  background: var(--primary-soft); color: var(--primary);
  border-radius: 10px; padding: 10px 13px; font-size: 13px; line-height: 1.5;
  margin: 0 0 16px;
}
.auth-error { background: var(--danger-soft); color: var(--danger); border: 1px solid #f5c2c2; border-radius: 10px; padding: 10px 14px; font-size: 13.5px; margin-bottom: 16px; }
.auth-notice { background: var(--green-soft); color: var(--green); border: 1px solid var(--green); border-radius: 10px; padding: 10px 14px; font-size: 13.5px; margin-bottom: 16px; }

/* "Отправить код ещё раз" -- a plain inline link/button under the main
   submit button, not a second competing CTA */
/* "Send the code again" was a bare text link and people did not see it while
   staring at an empty SMS inbox. It is the single most likely next action on
   this screen, so it now looks like a real button with a full-width tap target
   -- still secondary to "Verify", but impossible to miss. */
.resend-form { margin-top: 12px; }
.resend-form .link-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 46px; padding: 12px 16px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel-2); color: var(--text);
  font-size: 14.5px; font-weight: 600; text-decoration: none;
  transition: border-color .2s ease, background .2s ease;
}
.resend-form .link-btn:hover { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); }
.resend-form .link-btn:disabled { opacity: .55; cursor: default; }
.link-btn {
  background: none; border: none; padding: 0; color: var(--primary); font-size: 13.5px;
  font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.link-btn:hover { color: var(--primary-dark); }

/* plain text+globe dropdown, pinned to the shell's top-right corner --
   replaces the old RU/UZ/EN pill tabs */
.auth-lang { position: absolute; top: 26px; right: 26px; }
.auth-lang select {
  border: none; background: none; outline: none; font-size: 13.5px; font-weight: 600;
  color: var(--dim); cursor: pointer;
}
/* On a narrow screen 26px from the SHELL's corner sits almost on top of the
   card's own edge (the card has no room to breathe under it) -- give the
   switcher its own row above the card content instead of pinning it
   absolutely, which is the actual "не положено стоит" the owner meant. */
@media (max-width: 480px) {
  .auth-lang { position: static; display: flex; justify-content: flex-end; margin-bottom: 14px; }
}

/* "<- back to login" nudge on the forgot-password step */
.auth-back {
  display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--dim);
  font-weight: 500; margin-bottom: 22px;
}
.auth-back:hover { color: var(--text); }

.terms-note { font-size: 12px; color: var(--faint); text-align: center; margin-top: 14px; line-height: 1.5; }
.dev-code-box { background: var(--amber-soft); border: 1px dashed var(--amber); color: var(--amber); border-radius: 10px; padding: 12px 14px; font-size: 13.5px; margin-bottom: 16px; text-align: center; }
.dev-code-box b { font-size: 20px; letter-spacing: 4px; display: block; margin-top: 4px; }
.code-input { text-align: center; font-size: 24px !important; letter-spacing: 10px; font-weight: 700; }

.field-error { color: var(--danger); font-size: 12.5px; margin-top: 6px; }

/* flat, borderless, rounded inputs + pill buttons -- scoped to .auth-card so
   the rest of the dashboard's own form/button styling is untouched */
.auth-card .form-field input, .auth-card .form-field select, .auth-card .form-field textarea {
  background: var(--panel-2); border: 1px solid transparent; border-radius: 13px; padding: 13px 16px; font-size: 14.5px;
}
.auth-card .form-field input:focus, .auth-card .form-field select:focus, .auth-card .form-field textarea:focus {
  border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft);
}
.auth-card .btn-primary, .auth-card .btn-outline { border-radius: 999px; }
.auth-card .btn-primary { background: #1e6fe3; box-shadow: 0 4px 14px -4px rgba(30,111,227,.5); }
.auth-card .btn-primary:hover { background: #1a63cc; box-shadow: 0 6px 18px -4px rgba(30,111,227,.6); }
.auth-card .btn-lg { padding: 15px 24px; font-size: 15.5px; }

/* password show/hide toggle */
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 46px !important; }
.pw-toggle {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  color: var(--faint); border-radius: 8px; background: none; border: none;
}
.pw-toggle:hover { color: var(--dim); }
.pw-toggle .icon-eye-off { display: none; }
.pw-toggle.is-active .icon-eye { display: none; }
.pw-toggle.is-active .icon-eye-off { display: block; }

/* onboarding: 3-step progress + logo upload (per the org-creation design) */
.progress-steps { display: flex; gap: 8px; margin: 4px 0 24px; }
.progress-steps i { flex: 1; height: 5px; border-radius: 3px; background: var(--primary); }
.progress-steps i.is-pending { background: var(--border); }
.logo-upload { display: flex; align-items: center; gap: 16px; cursor: pointer; }
.logo-drop {
  width: 78px; height: 78px; flex-shrink: 0; border: 2px dashed var(--border); border-radius: 16px;
  display: flex; align-items: center; justify-content: center; color: var(--faint); overflow: hidden;
  transition: border-color .2s ease, color .2s ease;
}
.logo-upload:hover .logo-drop { border-color: var(--primary); color: var(--primary); }
.logo-drop img { width: 100%; height: 100%; object-fit: cover; }

/* auth divider + google button */
.auth-divider { display: flex; align-items: center; gap: 12px; margin: 18px 0 14px; color: var(--faint); font-size: 12.5px; }
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.google-btn {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
  padding: 11px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel);
  font-weight: 600; font-size: 14.5px; color: var(--text);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.google-btn:hover { border-color: #c6cbd4; box-shadow: var(--shadow); }

/* ---------- modal ---------- */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(16,24,40,.45); z-index: 200;
  display: none; padding: 40px 20px; overflow-y: auto;
}
.modal-backdrop.is-open { display: flex; align-items: flex-start; justify-content: center; }
.modal-card {
  background: var(--glass-bg-strong); border: 1px solid var(--glass-border); border-radius: 16px; box-shadow: var(--shadow-lg);
  padding: 26px; width: 100%; max-width: 440px; animation: modal-in .25s var(--ease);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  overflow: visible; margin: auto;
}
.modal-card h3 { font-size: 17px; margin-bottom: 18px; }
@keyframes modal-in { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }

/* Custom confirm()/alert() replacement (built by ClutterDialog in dashboard.js
   and duplicated inline in admin_layout.html) -- reuses .modal-backdrop/.modal-card
   so it looks identical to every other modal in the app instead of the browser's
   own unstyled "localhost says" box. */
.dlg-card { max-width: 380px; text-align: center; }
.dlg-card p { font-size: 14.5px; color: var(--text); line-height: 1.5; margin: 0 0 22px; white-space: pre-line; }
.dlg-card .dlg-input { margin-bottom: 18px; text-align: left; }
.dlg-actions { display: flex; gap: 10px; justify-content: center; }
.dlg-actions .btn { flex: 1; }

/* ---------- responsive ---------- */
/* ============================================================================
   MOBILE (≤900px) — a real phone layout, not a squeezed desktop one.
   Desktop rules above are untouched on purpose; everything here is additive.

   What this replaces (all measured broken at 375x812 before this existed):
     - the message input sat at y=838 on an 812px-tall screen, i.e. literally
       off-screen — you could not send a message at all;
     - the conversation list and the open chat were stacked 371px each, leaving
       the message area ~115px tall (1-2 messages visible);
     - the desktop sidebar became a 103px horizontally-scrolling strip at the
       top, which is undiscoverable and unreachable one-handed;
     - the contact card (phone number, notes) was display:none with no way in.

   The model here is the one every real phone messaging app uses: a bottom tab
   bar for the thumb, a drawer for secondary navigation, one full-height screen
   at a time (list OR chat), and a chat pane that never scrolls the page.
   ============================================================================ */

/* Both are mobile-only chrome — off entirely on desktop. */
.mobile-tabbar, .mobile-drawer-backdrop, .thread-back { display: none; }

@media (max-width: 900px) {
  :root { --tabbar-h: 58px; }

  /* ========================================================================
     FLAT MOBILE THEME — no glassmorphism.
     Measured root cause of three real complaints (2026-07-28):
       • "лагает / не быстрая": backdrop-filter: blur(20px) saturate(180%) was
         live on 9 surfaces (sidebar, cards, both menus, modals, drawer, tab
         bar, engine pill) AND the body ran a 4-layer radial mesh at
         background-attachment: fixed — every scroll frame re-blurred the whole
         mesh. That combination is the textbook mobile-jank recipe.
       • "фон светлее чем на ПК": the conversation list had a fully transparent
         background (measured rgba(0,0,0,0)), so the bright mesh showed straight
         through, and every "glass" surface sat at .55–.82 opacity letting the
         same vivid gradient bleed up — the app read washed-out and lighter than
         the desktop it's supposed to match.
       • "слишком ярко": that vivid 4-colour mesh itself.
     Fix: on phones, drop glass entirely for solid opaque surfaces on a calm
     solid background — exactly what Telegram/native apps do. Faster (zero blur
     compositing), consistent (no bleed-through), calmer. Desktop keeps its
     glass look untouched — this is all inside the mobile media query.
     Implemented by re-pointing the --glass-* tokens to solid values, so every
     component that reads them flips automatically, plus a blanket
     backdrop-filter:none. ======================================================= */
  :root {
    --glass-bg: #ffffff; --glass-bg-soft: #ffffff; --glass-bg-strong: #ffffff;
    --glass-border: var(--border);
    --app-bg: #f3f3fa;   /* calm solid page background (light) */
    --surface-solid: #ffffff;
  }
  :root[data-theme="dark"] {
    --glass-bg: #17152a; --glass-bg-soft: #17152a; --glass-bg-strong: #141221;
    --glass-border: #2a2647;
    --app-bg: #0c0a15;   /* deep, calm, solid (dark) */
    --surface-solid: #17152a;
    --panel-2: #201d38;
  }

  /* one calm solid background instead of the fixed vivid mesh */
  body.dash-body,
  :root[data-theme="dark"] body.dash-body {
    background-image: none;
    background-attachment: scroll;
    background-color: var(--app-bg);
  }

  /* kill every blur composite — the single biggest perf win on a phone */
  .sidebar, .company-menu, .account-menu, .engine-status, .card, .stat-card,
  .pricing-mini-card, .modal-card, .modal-backdrop, .mobile-tabbar,
  .conv-thread, .contact-panel, .kb-card, .agent-card, .note-card,
  .cd-menu, .theme-toggle-btn, [class*="menu"], [class*="dropdown"] {
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }

  /* solid surfaces so nothing bleeds through the (now removed) mesh */
  .inbox-shell, .conv-list { background: var(--app-bg); }
  .conv-thread { background: var(--surface-solid); }
  /* snappier: the per-row entrance animation stuttered across ~27 list rows on
     load; a chat list should just appear, like a native app's does */
  .conv-item, .page-content > *, .data-table tbody tr { animation: none !important; }

  /* ---- shell ---- */
  /* 100dvh (dynamic viewport height), not 100vh: on mobile browsers 100vh
     includes the space under the collapsing URL bar, which is exactly how the
     message input ended up rendered below the visible screen. */
  body.dash-body { display: block; min-height: 100dvh; }
  .main-area { min-height: 100dvh; }
  .page-content { padding: 14px 15px calc(var(--tabbar-h) + 22px); }
  .topbar { padding: 12px 15px 0; }
  .topbar h1 { font-size: 19px; }
  /* the engine-status pill's text is desktop detail; the dot alone carries it */
  .engine-status span, .engine-status { font-size: 0; gap: 0; }
  .engine-status .engine-dot { font-size: 12px; }
  .sidebar-edge-toggle { display: none; }  /* desktop-only affordance */
  .call-fab { bottom: calc(var(--tabbar-h) + 14px); right: 14px; }

  /* ---- sidebar becomes an off-canvas drawer ---- */
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 90;
    width: min(84vw, 320px); height: 100dvh; max-height: 100dvh;
    flex-direction: column; overflow-y: auto; padding: 16px 14px;
    background: var(--glass-bg-strong); box-shadow: 6px 0 28px -6px rgba(16,24,40,.28);
    transform: translateX(-102%); transition: transform .26s var(--ease);
  }
  body.mobile-drawer-open .sidebar { transform: translateX(0); }
  /* the desktop collapse state must never hide the drawer on mobile */
  html.sidebar-collapsed .sidebar {
    width: min(84vw, 320px); padding: 16px 14px; opacity: 1; pointer-events: auto;
  }
  .mobile-drawer-backdrop {
    display: block; position: fixed; inset: 0; z-index: 85;
    background: rgba(16,24,40,.5); opacity: 0; pointer-events: none;
    transition: opacity .26s ease;
  }
  body.mobile-drawer-open .mobile-drawer-backdrop { opacity: 1; pointer-events: auto; }
  body.mobile-drawer-open { overflow: hidden; }
  .sidebar-nav { flex-direction: column; }
  .sidebar-nav a { padding: 13px 12px; font-size: 15px; min-height: 46px; }  /* ≥44px touch target (was 42) */
  .account-box { display: block; }

  /* ---- bottom tab bar ---- */
  .mobile-tabbar {
    display: flex; position: fixed; bottom: 0; left: 0; right: 0; z-index: 80;
    height: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);  /* iPhone home-bar gap */
    background: var(--glass-bg-strong); border-top: 1px solid var(--glass-border);
    -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  }
  .mobile-tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; border: none; background: none; color: var(--dim);
    font-size: 10.5px; font-weight: 600; text-decoration: none; cursor: pointer;
    padding: 0 2px; min-width: 0;
  }
  .mobile-tab span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
  .mobile-tab svg { flex-shrink: 0; }
  .mobile-tab.is-active { color: var(--primary); }

  /* ---- inbox: ONE full-height screen at a time ----
     Sized by a flex chain (viewport → main-area → page-content → shell) rather
     than a calc() subtracting guessed chrome heights: the topbar's real height
     changes with the page title's font/wrapping and the safe-area inset varies
     by device, and any such guess being a few px off is what puts the composer
     under the tab bar or leaves a dead gap. */
  body.is-chat-page { height: 100dvh; overflow: hidden; }
  body.is-chat-page .main-area {
    height: 100dvh; display: flex; flex-direction: column;
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  }
  body.is-chat-page .page-content {
    flex: 1; min-height: 0; display: flex; flex-direction: column;
    padding: 12px 15px 0; overflow: hidden;
  }
  body.is-chat-page .inbox-bleed { margin: 0 -15px; flex: 1; min-height: 0; }
  /* The generic .page-content > * entrance animation slides content up from
     translateY(8px). On a fixed-height chat shell that 8px is not decoration --
     it pushes the composer under the tab bar, and it stays pushed for as long
     as the animation is paused or interrupted (a background tab pauses
     animations, so this was reproducibly stuck at 8px). An app shell shouldn't
     slide on every navigation anyway. */
  body.is-chat-page .page-content > * { animation: none; }
  .inbox-shell {
    display: flex; flex-direction: column; height: auto; overflow: hidden;
  }
  /* list view (default): list fills the screen, thread is not rendered */
  .conv-list { flex: 1; min-height: 0; }
  .conv-thread { display: none; }
  /* thread view (a conversation is named in the URL): the reverse.
     The chat slides in from the right (Telegram feel). Ends at translateX(0)
     with no fill, so if ever interrupted it just rests in the correct place --
     and it's horizontal, so unlike the old vertical entrance it can't push the
     composer off-screen. */
  .inbox-shell.mobile-thread-open .conv-list { display: none; }
  .inbox-shell.mobile-thread-open .conv-thread {
    display: flex; flex: 1; min-height: 0; animation: thread-slide-in .24s var(--ease);
  }
  @media (prefers-reduced-motion: reduce) {
    .inbox-shell.mobile-thread-open .conv-thread { animation: none; }
  }

  .thread-back {
    display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; margin-left: -6px; flex-shrink: 0;
    border-radius: 10px; color: var(--text);
  }
  /* Two rows, not one. The owner asked for the SAME controls the desktop has
     ("кнопки должны быть схожими как на пк версии") — an earlier attempt hid
     the status and contact controls behind a ⋮ menu and the reaction was that
     close/open could not be found at all. Everything is visible again; the
     room comes from a second row instead of from squeezing (one row at 375px
     crushed the contact name to ~60px). */
  .thread-head { padding: 8px 10px; gap: 6px; flex-wrap: wrap; }
  .thread-head > div:first-child { flex: 1 1 100%; min-width: 0; gap: 9px !important; }
  .thread-head-actions {
    flex: 1 1 100%; justify-content: flex-start;
    gap: 10px !important; flex-wrap: nowrap !important;
  }
  /* every control a thumb has to hit gets the 44px minimum (they were 34/38/24) */
  .thread-back { width: 44px !important; height: 44px !important; margin-left: -8px !important; }
  .thread-contact-btn { width: 46px; height: 46px; display: flex !important;
    align-items: center; justify-content: center; flex-shrink: 0; }
  .thread-status-form { display: block !important; flex: 1 1 auto; min-width: 0; }
  .thread-status-form select { width: 100%; min-height: 46px; }
  /* The switch stays visually 42x24 (that's the control's design) but the
     ACTUAL tap target has to be ≥44px or a thumb misses it — measured 42x24
     before. A transparent ::before stretches the hit area vertically without
     changing how the switch looks. */
  .thread-head .ai-toggle-label { min-height: 46px; padding: 0 2px; }
  .thread-head .ai-toggle-label .switch { position: relative; }
  .thread-head .ai-toggle-label .switch::before {
    content: ""; position: absolute; left: -4px; right: -4px; top: 50%;
    height: 46px; transform: translateY(-50%);
  }
  /* composer input was 41px tall */
  .thread-input input { min-height: 46px; }
  /* only the name block shrinks; back arrow and avatar keep their size */
  .thread-back, .thread-head .conv-avatar { flex-shrink: 0; }
  .thread-head > div:first-child > div { min-width: 0; flex: 1 1 auto; }
  .thread-head strong,
  .thread-head > div:first-child > div > div {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
  }
  .thread-head strong { font-size: 15.5px; }
  .thread-head .conv-avatar { width: 38px; height: 38px; font-size: 15px; }
  /* the "ИИ отвечает" label stays visible, same as desktop — the second row
     has room for it, and an unlabelled switch is guesswork */
  .thread-head .ai-toggle-label span { display: inline; font-size: 13px; }
  .thread-body { padding: 14px 12px; }
  .msg { max-width: 86%; }
  /* the safe-area gap is already reserved by .main-area's padding-bottom on a
     chat page, so the composer itself must not add it again */
  .thread-input { padding: 9px 10px; gap: 8px; flex-wrap: nowrap; align-items: center; }
  .thread-input > select { display: none; }   /* templates picker: desktop nicety */
  /* round icon send button (Telegram), not a wide "Отправить" text button */
  .thread-send {
    flex-shrink: 0; width: 44px; height: 44px; min-height: 44px; padding: 0;
    border-radius: 50%; display: flex; align-items: center; justify-content: center;
  }
  .thread-send .send-text { display: none; }
  .thread-send .send-icon { display: block; }
  /* contact info as a bottom sheet, opened from the ⋮ menu (the desktop side
     panel has nowhere to live on a phone) */
  .contact-panel {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
    max-height: 82dvh; overflow-y: auto; border-radius: 18px 18px 0 0;
    background: var(--surface-solid); border-top: 1px solid var(--border);
    box-shadow: 0 -8px 30px -8px rgba(0,0,0,.5);
    transform: translateY(101%); transition: transform .28s var(--ease);
    padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  }
  /* The desktop "I collapsed the contact panel" state is remembered in
     localStorage and re-applies .contact-panel-hidden on EVERY page load,
     including on a phone -- and that rule is `display:none`, which silently
     killed the mobile bottom sheet: the button toggled the class, but the
     panel never appeared. Reproduced exactly (flag=1 → sheet open → computed
     display:none). The collapse state is a desktop-only concept, so it must
     not reach the sheet. */
  .inbox-shell.contact-panel-hidden .contact-panel { display: block; }
  body.mobile-contact-open .contact-panel { transform: translateY(0); }
  /* reuse the drawer backdrop for the sheet too */
  body.mobile-contact-open .mobile-drawer-backdrop { display: block; opacity: 1; pointer-events: auto; }
  .conv-search-row { padding: 10px 12px 4px; }
  .conv-tabs { padding: 8px 12px; }
  /* the Открытые/Закрытые/Все filter chips are the most-tapped control on the
     list screen and were only 32px tall */
  .conv-tab { padding: 12px 16px; font-size: 13.5px; min-height: 44px;
    display: inline-flex; align-items: center; }
  /* Telegram-style full-width list rows: edge-to-edge, a hairline divider
     between them, no card margins/rounding. In list view a row must NOT carry
     the desktop split-view "active" tint (there's no thread beside it here --
     tapping opens a separate screen), so the auto-selected first row doesn't
     sit permanently highlighted; the tint is reserved for the actual press. */
  .conv-item { padding: 11px 15px; margin: 0; border-radius: 0; gap: 11px;
    border-bottom: 1px solid var(--border); }
  .conv-list .conv-item.is-active { background: transparent; }
  .conv-list .conv-item:active { background: var(--panel-2); }
  .conv-item-top { font-size: 15px; }
  /* the name+platform-icon span needs min-width:0 to actually shrink inside
     the flex row — without it a long contact name pushed the ✈ icon ~90px off
     the right edge instead of ellipsising */
  .conv-item-top > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .conv-item-preview { font-size: 13px; }
  .conv-avatar { width: 46px; height: 46px; font-size: 17px; }
  /* the hover-reveal × can't be hovered on a touchscreen — always show it,
     just muted, so deleting a message is actually reachable by thumb */
  .msg-delete-btn { opacity: .55; transform: scale(1); width: 24px; height: 24px; }

  /* ---- forms: 16px minimum stops iOS Safari auto-zooming the page on focus,
     which on this app zoomed in and clipped the layout every time you tapped
     the message field ---- */
  input, select, textarea, .thread-input input { font-size: 16px !important; }
  .btn { min-height: 44px; }
  .btn-sm { min-height: 44px; }   /* was 38 — still a finger target, not a mouse one */

  /* ---- generic page content ---- */
  .grid-2, .grid-3, .grid-4, .pricing-mini-grid, .pricing-mini-grid-4, .bc-grid { grid-template-columns: 1fr; }
  /* Safety net: several pages (analytics.html's chart/donut rows, and likely
     others not yet audited one-by-one) use a raw inline
     style="display:grid; grid-template-columns:..." instead of a .grid-N
     class, so the rule above can't reach them -- confirmed these forced the
     page 18px+ wider than the viewport. An inline style only loses to a
     stylesheet rule with !important, so this blanket catch stacks ANY
     multi-column grid in the page content to one column, whatever markup
     produced it. Worst case something that could have fit side-by-side
     stacks instead -- always fine visually; the alternative (missing one) is
     a real horizontal-scroll bug like the two just found. */
  /* minmax(0, 1fr), NOT a bare 1fr: a plain 1fr track's automatic minimum size
     is the content's min-content width, so a wide non-shrinking child (the
     line-chart SVG here) still forced the column open to its full desktop
     width even with a single column -- confirmed this by testing the naive
     version first (it made analytics 2160px wide, worse than before). The
     explicit 0 minimum is what actually lets grid children shrink below their
     content size. */
  .page-content [style*="grid-template-columns"] { grid-template-columns: minmax(0, 1fr) !important; }
  .page-content [style*="grid-template-columns"] > * { min-width: 0; }
  .card { padding: 16px 14px; }

  /* ---- analytics: a genuinely separate phone design, not the desktop one
     shrunk. Desktop widgets (4-col stat grid, 140px donut, 7x24 heatmap) are
     hidden via .desktop-only; each has a touch-native counterpart below. ---- */
  .analytics-row { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .analytics-head { flex-direction: column; align-items: stretch; }
  /* full-width segmented control -- one thumb-sized target per range */
  .range-switch { width: 100%; }
  .range-opt { flex: 1; text-align: center; padding: 11px 8px; font-size: 13.5px; min-height: 44px;
    display: flex; align-items: center; justify-content: center; }

  /* swipeable stat tiles: 4 numbers stay on ONE screen row instead of
     becoming 4 stacked full-width cards you have to scroll past every visit */
  .stat-strip {
    gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
    margin: 0 -14px 14px; padding: 2px 14px 6px;
  }
  .stat-strip::-webkit-scrollbar { display: none; }
  .stat-pill {
    flex: 0 0 auto; min-width: 132px; scroll-snap-align: start;
    display: flex; flex-direction: column; gap: 3px; padding: 14px 16px;
    background: var(--glass-bg); border: 1px solid var(--glass-border);
    border-radius: 16px; box-shadow: var(--shadow);
  }
  .stat-pill-val { font-family: 'Manrope', sans-serif; font-size: 25px; font-weight: 800; line-height: 1.1;
    background: var(--grad-2); -webkit-background-clip: text; background-clip: text; color: transparent; }
  .stat-pill-lbl { font-size: 11.5px; color: var(--dim); line-height: 1.25; }
  .stat-pill-trend { font-size: 11.5px; font-weight: 700; margin-top: 2px; }
  .stat-pill-trend.up { color: var(--green); }
  .stat-pill-trend.down { color: var(--danger); }

  /* channels: readable labelled bars instead of a tiny donut + cramped legend */
  .channel-bar-list { flex-direction: column; gap: 13px; }
  .channel-bar-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; align-items: center; }
  .channel-bar-lbl { display: flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 600; min-width: 0; }
  .channel-bar-lbl .dot { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }
  .channel-bar-pct { font-size: 13px; color: var(--dim); font-weight: 700; }
  .channel-bar-track { grid-column: 1 / -1; height: 8px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
  .channel-bar-fill { height: 100%; border-radius: 999px; }

  /* busy hours: 8 fat 3-hour columns you can actually see, not 168 slivers */
  .hour-bars { align-items: flex-end; gap: 6px; height: 132px; }
  .hour-bar-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; height: 100%; }
  .hour-bar-track { flex: 1; width: 100%; display: flex; align-items: flex-end;
    background: var(--panel-2); border-radius: 8px; overflow: hidden; }
  .hour-bar-fill { width: 100%; min-height: 3px; border-radius: 8px; background: var(--primary); }
  .hour-bar-lbl { font-size: 10.5px; color: var(--faint); }
  .heatmap-footer { margin-top: 12px; }

  /* the line chart's fixed 180px height is fine, but its y-label gutter and
     x labels crowd on a narrow screen */
  .chart-y-labels { width: 22px; height: 150px; }
  .line-chart { height: 150px; }
  .chart-x-labels span { font-size: 9.5px; }

  /* Data tables become CARDS on a phone — one stacked card per row, each cell
     showing "Заголовок ..... значение". A 5-7 column table (Контакты has 7,
     Команда 7) can only be read by dragging it sideways otherwise, which is
     what made these sections feel unusable on mobile. The per-cell headings
     come from the data-label attributes filled in by dashboard.js, so this
     works for every table in the app without touching the templates. */
  .card:has(> .data-table) { overflow-x: visible; }
  .data-table, .data-table tbody, .data-table tr, .data-table td { display: block; width: 100%; }
  .data-table { min-width: 0; border-collapse: separate; border-spacing: 0; }
  .data-table thead { display: none; }
  .data-table tbody tr {
    background: var(--panel-2); border: 1px solid var(--border);
    border-radius: 12px; margin-bottom: 10px; overflow: hidden;
  }
  .data-table tbody tr:hover td { background: transparent; }
  .data-table td {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    padding: 10px 13px; border-bottom: 1px solid var(--border);
    font-size: 14px; text-align: right; min-height: 0;
  }
  .data-table td::before {
    content: attr(data-label); color: var(--faint); font-size: 12px; font-weight: 600;
    text-align: left; flex-shrink: 0; white-space: nowrap;
  }
  /* cells with no heading (row checkbox, action buttons) sit full-width */
  .data-table td:not([data-label]) { justify-content: flex-end; }
  .data-table tbody tr td:last-child { border-bottom: none; }
  /* A long unbroken value (a Telegram @username like
     "@qalanuz_mentor_support") has no space to wrap at and pushed the cell
     21px past the screen. Everything after the label gets a hard bound plus
     ellipsis; the value is still selectable/copyable in full. */
  .data-table td > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .data-table td > *, .data-table td { overflow-wrap: anywhere; }

  /* Page-header action rows: several 150px+ buttons sat on one nowrap line and
     ran off-screen (Аналитика 614px, Команда 423px). Only display/gap are set
     inline on these, so plain flex-wrap here wins. */
  .page-head-row div { flex-wrap: wrap; }
  .page-head-row { align-items: flex-start; }

  /* charts/donuts sized for a desktop column */
  .donut-row { flex-wrap: wrap; gap: 14px; }
  svg { max-width: 100%; }

  .heatmap { grid-template-columns: 26px repeat(24, 1fr); }
  .modal-card { width: calc(100vw - 24px); max-height: 88dvh; overflow-y: auto; }
}

/* ---------- tablet tier (701-900px) ----------
   Deliberately LAST in this file so it beats the 900px phone block above by
   source order (both are single-class selectors, so specificity ties).
   A tablet is still a touch device -- it keeps the drawer, the bottom tab bar
   and the 44px hit targets from that block -- but it is roughly twice a
   phone's width, so card grids stay 2-across instead of collapsing into one
   long single-file column, which is what made an iPad feel like a stretched
   phone rather than its own layout. */
@media (min-width: 701px) and (max-width: 900px) {
  .grid-3, .grid-4, .pricing-mini-grid, .pricing-mini-grid-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* the chart row stays stacked: a line chart and a donut side by side at
     ~750px each get too narrow to read comfortably */
  .analytics-row { grid-template-columns: minmax(0, 1fr); }
  /* the full 24-hour heatmap has room again at this width */
  .heatmap { grid-template-columns: 30px repeat(24, 1fr); }
  .account-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}

/* ---------- ultra-narrow phones (<=380px) ----------
   Covers the folded Galaxy Fold / Z Fold cover screen (240-344px) and the
   oldest small Androids still in use. These are not "one more device" -- they
   are the floor the layout has to hold at, so the page can never scroll
   sideways on ANY screen rather than only on the ones that happened to be
   tested. Everything here targets the two things that actually cause it:
   a flex child that refuses to shrink, and an unbreakable string. */
@media (max-width: 380px) {
  /* a flex item will not shrink below its intrinsic size without this, which
     is what made search boxes, phone rows and toolbars overflow */
  .search-input, .search-input input,
  .phone-row, .phone-row input,
  .page-head-row, .admin-toolbar, .conv-item, .account-row { min-width: 0; }

  /* long unbroken tokens (emails, URLs, long numbers) can otherwise set a
     min-content width wider than the screen and nothing can shrink past it */
  body, .card, .stat-card, .pricing-mini-card, .admin-card { overflow-wrap: anywhere; }

  .page-content { padding-left: 12px; padding-right: 12px; }
  .card, .stat-card, .pricing-mini-card { padding: 14px 12px; }
  .btn, .btn-sm, .btn-lg { white-space: normal; max-width: 100%; }
  .page-head-row { flex-wrap: wrap; gap: 8px; }

  /* The swipeable stat strip deliberately bleeds past the page padding so the
     tiles run edge-to-edge. That bleed is hard-coded to the 14px padding used
     at wider sizes -- once .page-content drops to 12px here, a -14px margin
     overhangs by exactly the 2px measured. Keep the two in step. */
  .stat-strip { margin-left: -12px; margin-right: -12px; padding-left: 12px; padding-right: 12px; }
}


/* Toasts */
.toast { position: fixed; top: 20px; right: 20px; z-index: 9999; padding: 14px 20px; border-radius: 12px; font-weight: 500; font-size: 14px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); color: #fff; animation: toastIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); display: flex; align-items: center; gap: 10px; }
.toast-success { background: rgba(46, 213, 115, 0.2); border: 1px solid rgba(46, 213, 115, 0.4); }
.toast-error { background: rgba(255, 71, 87, 0.2); border: 1px solid rgba(255, 71, 87, 0.4); }
.toast-out { animation: toastOut 0.3s ease forwards; }
@keyframes toastIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes toastOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } }

/* Page Transitions & Glassmorphism */
.admin-card { animation: fadeUp 0.4s ease-out forwards; }
.admin-card:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(0,0,0,0.4); }
@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* Real-Time Font Scaling Engine */
html[data-font-size="14px"] { font-size: 13px !important; }
html[data-font-size="14px"] body, 
html[data-font-size="14px"] .card, 
html[data-font-size="14px"] .account-card,
html[data-font-size="14px"] .stat-card-real,
html[data-font-size="14px"] .msg-bubble,
html[data-font-size="14px"] .account-menu-label,
html[data-font-size="14px"] .nav-link,
html[data-font-size="14px"] input,
html[data-font-size="14px"] button { font-size: 13px !important; }

html[data-font-size="15px"] { font-size: 14.5px !important; }

html[data-font-size="16px"] { font-size: 16px !important; }
html[data-font-size="16px"] body, 
html[data-font-size="16px"] .card, 
html[data-font-size="16px"] .account-card,
html[data-font-size="16px"] .stat-card-real,
html[data-font-size="16px"] .msg-bubble,
html[data-font-size="16px"] .account-menu-label,
html[data-font-size="16px"] .nav-link,
html[data-font-size="16px"] input,
html[data-font-size="16px"] button { font-size: 16px !important; }

/* Compact UI Mode Rules */
html.compact-ui .card, 
html.compact-ui .account-card, 
html.compact-ui .stat-card-real {
  padding: 12px 16px !important;
}
html.compact-ui .chat-item,
html.compact-ui .conv-item {
  padding: 8px 12px !important;
}
html.compact-ui .msg-bubble {
  padding: 6px 12px !important;
  margin-bottom: 5px !important;
}
html.compact-ui .form-field {
  margin-bottom: 8px !important;
}
html.compact-ui table th, 
html.compact-ui table td {
  padding: 6px 10px !important;
}

/* Floating Real-Time In-App Message Notification Toast */
.inapp-msg-toast {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 10000;
  display: flex;
  align-items: center;
  gap: 14px;
  background: rgba(18, 16, 34, 0.92);
  border: 1px solid var(--accent);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5), 0 0 15px rgba(108, 92, 231, 0.3);
  backdrop-filter: blur(16px);
  padding: 14px 18px;
  border-radius: 16px;
  color: #ffffff;
  cursor: pointer;
  max-width: 360px;
  animation: msgToastSlideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1);
  transition: transform 0.2s, box-shadow 0.2s;
}
.inapp-msg-toast:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.6), 0 0 22px rgba(108, 92, 231, 0.5);
}
.inapp-toast-avatar {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 16px;
  color: #fff;
  flex-shrink: 0;
}
.inapp-toast-content {
  flex: 1;
  min-width: 0;
}
.inapp-toast-title {
  font-size: 13.5px;
  font-weight: 700;
  color: #ffffff;
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.inapp-toast-body {
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.75);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@keyframes msgToastSlideIn {
  from { opacity: 0; transform: translateY(30px) scale(0.95); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}


/* ============================================================
   BUSINESS SPHERES + RESTAURANT SECTIONS
   ============================================================
   Uses the dashboard's own variables (--panel, --text, --dim, --border,
   --accent) rather than literal colours, unlike tour.css: these pages render
   only INSIDE the dashboard, which defines all of them and flips them for
   dark mode on its own. tour.css had to avoid variables because it also
   renders over the landing page, which is a different design system.
   ============================================================ */

/* ---- sphere picker ---- */
/* A grid rather than a <select>: the sphere decides which sections the company
   gets and cannot be changed afterwards, so the whole choice has to be visible
   at once instead of hidden behind a dropdown. */
.sphere-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 10px;
}
.sphere-tile {
  position: relative;
  display: flex; flex-direction: column; gap: 3px;
  padding: 14px 12px 12px;
  /* Отдельными свойствами, а не сокращением `border: 1.5px solid var(--border)`:
     сокращение с var() внутри подставляется на этапе вычисления значения, и в
     Chrome оно перебивало border-color выбранной плитки - фон и подсветка
     применялись, а рамка оставалась серой. Проверено в браузере. */
  border-width: 1.5px; border-style: solid; border-color: var(--border);
  border-radius: 14px;
  cursor: pointer; background: var(--panel);
  transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
.sphere-grid .sphere-tile:hover { border-color: var(--accent); transform: translateY(-1px); }
.sphere-tile input { position: absolute; opacity: 0; pointer-events: none; }
/* Выше специфичностью, чем правило рамки самой плитки: сокращённое
   `border: ... var(--border)` подставляется на этапе вычисления значения, и
   при равной специфичности оно перебивало цвет выбранной плитки - фон и
   подсветка применялись, а рамка оставалась серой. */
.sphere-grid .sphere-tile:has(input:checked) {
  /* outline, а не border-color: у рамки плитки сокращённая запись с var()
     внутри, и переопределить только цвет не удавалось - фон и подсветка
     применялись, рамка оставалась серой (проверено в браузере). outline
     рисуется поверх и ни с чем не конкурирует, а отрицательный offset кладёт
     его точно на место рамки, так что плитка не прыгает. */
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  background: color-mix(in srgb, var(--accent) 8%, var(--panel));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.sphere-emoji { font-size: 24px; line-height: 1.1; }
.sphere-name { font-weight: 700; font-size: 14px; color: var(--text); }
.sphere-hint { font-size: 12px; color: var(--dim); line-height: 1.35; }
.sphere-soon {
  align-self: flex-start; margin-top: 4px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--dim); background: var(--bg-soft, rgba(127,127,127,.12));
  border-radius: 999px; padding: 2px 7px;
}
.sphere-warn { font-size: 13px; color: var(--dim); line-height: 1.5; margin: 2px 0 0; }

/* ---- shared bits for sphere pages ---- */
.page-sub { font-size: 13.5px; color: var(--dim); margin: 4px 0 0; line-height: 1.5; }
.empty-note { color: var(--dim); font-size: 14px; line-height: 1.6; margin: 6px 0; }
.alert-warn {
  padding: 11px 14px; border-radius: 10px; margin-bottom: 14px; font-size: 14px;
  background: rgba(240, 170, 40, .13); border: 1px solid rgba(240, 170, 40, .35);
  color: var(--text);
}
.cell-sub { font-size: 12.5px; color: var(--dim); margin-top: 2px; }
.nowrap { white-space: nowrap; }
.inline-form { display: inline; }
/* wide tables must scroll inside their own box, never widen the page */
.table-wrap { overflow-x: auto; }
.data-table tr.is-past td { opacity: .5; }
.btn-danger-ghost {
  background: none; border: 1px solid transparent; color: #d9534f;
  padding: 5px 9px; border-radius: 8px; cursor: pointer; font-family: inherit; font-size: 13px;
}
.btn-danger-ghost:hover { background: rgba(217, 83, 79, .12); border-color: rgba(217, 83, 79, .3); }

.badge {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 600; background: var(--bg-soft, rgba(127,127,127,.12)); color: var(--dim);
}
/* A booking the agent made must be identifiable at a glance -- the owner has
   to be able to find and undo the machine's work. */
.badge-ai { background: rgba(108, 92, 231, .15); color: #6c5ce7; }

.status-select {
  font-family: inherit; font-size: 13px; padding: 5px 8px;
  border-radius: 8px; border: 1px solid var(--border); background: var(--panel); color: var(--text);
}
.status-select.st-cancelled { color: #d9534f; }
.status-select.st-done { color: var(--dim); }

@media (max-width: 560px) {
  .sphere-grid { grid-template-columns: repeat(auto-fill, minmax(min(132px, 100%), 1fr)); }
  .table-grid  { grid-template-columns: 1fr; }
}



/* ============================================================
   РАЗДЕЛЫ СФЕРЫ: каталог и заявки
   ============================================================
   Один набор стилей на все сферы -- как и разметка (см. spheres.py). Меню
   ресторана и товары магазина выглядят одинаково, потому что это одно и то
   же: список того, что предлагает бизнес.

   Использует ТЕ ЖЕ переменные и тот же язык, что и остальное приложение
   (--glass-bg, --shadow, --radius, --grad-2, content-in) -- первая версия
   этого раздела рисовала свои плоские карточки поверх системы вместо того,
   чтобы быть её частью, из-за чего выглядела чужеродно и безжизненно рядом
   с остальными разделами.
   ============================================================ */

/* Кнопки в подвале модалки -- общий класс, а не инлайн-стиль на каждой
   странице: используется здесь в трёх местах. */
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; }

/* ---- загрузка фото списка ----
   Стоит первой и крупно намеренно: у владельца список уже есть на бумаге, и
   сфотографировать его быстрее, чем вбить руками. */
.scan-card {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 20px 22px; margin-bottom: 16px;
  border-radius: var(--radius);
  border: 1.5px dashed color-mix(in srgb, var(--primary) 40%, transparent);
  background: linear-gradient(135deg, color-mix(in srgb, var(--primary) 9%, var(--glass-bg)),
                                        color-mix(in srgb, var(--violet) 7%, var(--glass-bg)));
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow);
  transition: border-color .25s ease, box-shadow .25s ease, transform .25s var(--ease);
}
.scan-card:hover {
  border-color: color-mix(in srgb, var(--primary) 65%, transparent);
  box-shadow: var(--shadow-lg);
}
.scan-card.is-busy { opacity: .65; pointer-events: none; }
.scan-icon {
  width: 50px; height: 50px; flex-shrink: 0; border-radius: 15px;
  display: flex; align-items: center; justify-content: center;
  background: var(--grad-2); color: #fff;
  box-shadow: 0 6px 16px -4px rgba(79,70,229,.5);
  animation: scan-icon-breathe 2.8s ease-in-out infinite;
}
@keyframes scan-icon-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}
@media (prefers-reduced-motion: reduce) { .scan-icon { animation: none; } }
.scan-text { flex: 1 1 220px; min-width: 0; font-size: 14.5px; line-height: 1.5; color: var(--text); }
.scan-btn { flex-shrink: 0; cursor: pointer; }
.scan-review-head { font-size: 15px; margin-bottom: 12px; color: var(--text); }
.scan-review input {
  width: 100%; min-width: 0; padding: 7px 9px; font-size: 13.5px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.scan-review input:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}
@media (prefers-reduced-motion: no-preference) {
  .scan-review { animation: content-in .3s var(--ease) both; }
}

/* ---- каталог: карточки с фото ---- */
.item-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: 16px;
}
.item-card {
  display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  border-radius: var(--radius);
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  box-shadow: var(--shadow);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s ease;
}
.item-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: color-mix(in srgb, var(--primary) 35%, var(--glass-border));
}
.item-card.is-off { opacity: .5; }
.item-photo { aspect-ratio: 16 / 10; background: var(--panel-2); overflow: hidden; }
.item-photo img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .4s ease;
}
.item-card:hover .item-photo img { transform: scale(1.05); }
.item-photo-empty {
  display: flex; align-items: center; justify-content: center; color: var(--faint);
  background: linear-gradient(135deg, var(--panel-2), var(--primary-soft));
}
.item-body { padding: 13px 14px 12px; display: flex; flex-direction: column; gap: 4px; flex: 1; }
.item-cat {
  align-self: flex-start; font-size: 10.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--primary);
  background: var(--primary-soft); padding: 2px 8px; border-radius: 999px;
}
.item-name { font-size: 15px; font-weight: 700; color: var(--text); line-height: 1.3; margin-top: 2px; }
.item-desc { font-size: 12.5px; color: var(--dim); line-height: 1.45; }
.item-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: auto; padding-top: 10px;
}
.item-price { font-size: 16px; font-weight: 800; color: var(--text); white-space: nowrap; }
.item-actions { display: flex; gap: 6px; }

.chip {
  border: 1px solid var(--border); background: var(--panel); color: var(--dim);
  font-family: inherit; font-size: 11.5px; font-weight: 600;
  padding: 5px 10px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: background .18s ease, border-color .18s ease, color .18s ease, transform .15s ease;
}
.chip:hover { transform: translateY(-1px); }
.chip:active { transform: scale(.95); }
.chip-on { color: var(--green); border-color: color-mix(in srgb, var(--green) 40%, transparent); background: var(--green-soft); }
.chip-off { color: var(--dim); }
.chip-danger { color: var(--danger); border-color: transparent; padding: 5px 9px; }
.chip-danger:hover { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }

/* ---- занятость ресурсов, полосой над списком заявок ---- */
.res-strip { display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 16px; }
.res-chip {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 8px 14px; border-radius: 999px; font-size: 13px;
  border: 1.5px solid var(--border); background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow);
  transition: transform .18s var(--ease), box-shadow .18s ease;
}
.res-chip:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.res-chip.is-free { border-color: color-mix(in srgb, var(--green) 45%, transparent); }
.res-chip.is-busy {
  border-color: color-mix(in srgb, var(--amber) 50%, transparent);
  background: var(--amber-soft);
}
.res-name { font-weight: 800; color: var(--text); }
.res-cap  { font-size: 12px; color: var(--dim); }
.res-note { font-size: 12px; color: var(--dim); }
.res-manage { margin-bottom: 16px; display: flex; flex-direction: column; gap: 8px; }
.res-manage-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 13.5px; padding: 9px 12px; border-radius: 10px;
  background: var(--panel-2); border: 1px solid var(--border);
}

/* ---- заявки: карточки, а не таблица ----
   У заявки переменный состав полей (время, гости, что заказано, адрес,
   заметка агента), и в таблице половина колонок стояла бы пустой у каждой
   сферы по-своему. */
.rec-list { display: flex; flex-direction: column; gap: 11px; }
.rec-row {
  display: flex; gap: 16px; align-items: flex-start; justify-content: space-between;
  padding: 15px 17px; border-radius: var(--radius);
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  box-shadow: var(--shadow);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  transition: transform .2s var(--ease), box-shadow .2s ease, border-color .2s ease;
}
.rec-row:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
  border-color: color-mix(in srgb, var(--primary) 30%, var(--glass-border));
}
.rec-row.is-past { opacity: .55; }
.rec-row.st-cancelled .rec-who { text-decoration: line-through; }
.rec-main { min-width: 0; flex: 1; }
.rec-top { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.rec-who { font-size: 15.5px; font-weight: 700; color: var(--text); }
.rec-meta { display: flex; flex-wrap: wrap; gap: 5px 16px; margin-top: 6px; font-size: 13px; color: var(--dim); }
.rec-note { margin-top: 8px; font-size: 13px; color: var(--dim); }
.rec-link {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 9px;
  font-size: 13px; font-weight: 600; color: var(--primary); text-decoration: none;
  transition: gap .15s ease;
}
.rec-link:hover { gap: 7px; text-decoration: underline; }
.rec-side { flex-shrink: 0; }

/* то, что записал агент со слов клиента -- визуально отделено от заметок
   владельца, потому что это пересказ разговора, а не установленный факт */
.rec-ai {
  margin-top: 9px; padding: 9px 12px; border-radius: 0 10px 10px 0;
  border-left: 3px solid var(--primary);
  background: linear-gradient(90deg, var(--primary-soft), transparent);
  font-size: 13px; line-height: 1.5; color: var(--text);
}
.rec-ai-label {
  display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--primary); margin-bottom: 3px;
}

/* ---- пустые состояния ---- */
.empty-note {
  text-align: center; padding: 34px 20px; color: var(--dim); font-size: 14px; line-height: 1.6;
}

@media (prefers-reduced-motion: no-preference) {
  .item-card, .rec-row, .res-chip { animation: content-in .38s var(--ease) both; }
  .item-grid > *:nth-child(1), .rec-list > *:nth-child(1) { animation-delay: .02s; }
  .item-grid > *:nth-child(2), .rec-list > *:nth-child(2) { animation-delay: .06s; }
  .item-grid > *:nth-child(3), .rec-list > *:nth-child(3) { animation-delay: .1s; }
  .item-grid > *:nth-child(4), .rec-list > *:nth-child(4) { animation-delay: .14s; }
  .item-grid > *:nth-child(n+5), .rec-list > *:nth-child(n+5) { animation-delay: .16s; }
}

@media (max-width: 620px) {
  .item-grid { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); }
  .rec-row { flex-direction: column; gap: 11px; }
  .rec-side { width: 100%; }
  .rec-side .status-select { width: 100%; }
  .scan-card { flex-direction: column; align-items: flex-start; }
  .scan-btn { width: 100%; text-align: center; }
}

/* Hide number input arrows */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type=number] {
  -moz-appearance: textfield;
}

/* Custom Scrollbars */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.15);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.25);
}
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}

::-webkit-scrollbar-button {
  display: none;
}

::-webkit-scrollbar-corner {
  background: transparent;
}
