/* ==========================================================================
   Performator app shell — Apple-services register.
   White sidebar, light-gray canvas, white cards. One view at a time (routed),
   never a single long scroll of every section stacked together.
   Tokens come from /css/main.css — do not redefine colours here.
   ========================================================================== */

body { font-size: var(--text-sm); background: var(--surface-canvas); }

/* Hidden until the session check AND the first data load resolve — the user
   never sees an empty shell with "—" in place of numbers. boot() in app.js
   drives the overlay: .is-ready completes the logo ring, then body loses
   .auth-pending (app renders underneath) and .is-leaving fades the overlay. */
body.auth-pending .app { display: none; }
.auth-loading {
  position: fixed; inset: 0; z-index: 1000; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: var(--sp-5);
  background: var(--surface-canvas); color: var(--faint); font-size: var(--text-sm);
  transition: opacity 320ms var(--ease-out-expo);
}
.auth-loading.is-leaving { opacity: 0; pointer-events: none; }
.auth-loading.is-leaving .boot-mark { transform: scale(1.06); }
.boot-mark {
  width: 76px; height: 76px; overflow: visible;
  transition: transform 420ms var(--ease-out-expo);
}
.boot-mark circle, .boot-mark line { fill: none; stroke-width: 11; }
.boot-track { stroke: var(--line-soft); }
.boot-ink { stroke: var(--ink); }
.boot-blue { stroke: var(--primary); }
/* Stem draws once top → bottom, crossing the black/blue seam like the logo. */
.boot-stem {
  stroke-dasharray: 100; stroke-dashoffset: 100;
  animation: boot-draw 560ms var(--ease-out-expo) 60ms forwards;
}
/* Spinner arc: variable length + rotation; the two clip groups recolour it
   black above the seam and blue below, so it "changes ink" as it passes. */
.boot-arc {
  transform-box: view-box; transform-origin: 42px 35px;
  animation: boot-spin 1.5s linear infinite, boot-dash 1.5s ease-in-out infinite;
  transition: opacity 220ms ease;
}
/* Full ring — hidden until data is ready, then drawn from the stem junction. */
.boot-ring {
  transform-box: view-box; transform-origin: 42px 35px; transform: rotate(180deg);
  stroke-dasharray: 100; stroke-dashoffset: 100;
  transition: stroke-dashoffset 420ms var(--ease-out-expo);
}
.auth-loading.is-ready .boot-arc { opacity: 0; }
.auth-loading.is-ready .boot-ring { stroke-dashoffset: 0; }
/* Caption stays invisible on a fast load and fades in only if it drags on. */
.boot-label { opacity: 0; animation: boot-fade 400ms ease 1.6s forwards; min-height: 1.4em; }
.auth-loading.is-ready .boot-label { animation: none; opacity: 0; transition: opacity 160ms ease; }
@keyframes boot-draw { to { stroke-dashoffset: 0; } }
@keyframes boot-spin { to { transform: rotate(360deg); } }
@keyframes boot-dash {
  0% { stroke-dasharray: 2 98; stroke-dashoffset: 0; }
  50% { stroke-dasharray: 58 42; stroke-dashoffset: -18; }
  100% { stroke-dasharray: 2 98; stroke-dashoffset: -98; }
}
@keyframes boot-fade { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .boot-stem { animation: none; stroke-dashoffset: 0; }
  .boot-arc { animation: boot-fade 900ms ease-in-out infinite alternate; stroke-dasharray: 40 60; }
  .boot-ring, .boot-mark, .auth-loading { transition: none; }
}

.app { display: grid; grid-template-columns: 212px 1fr; min-height: 100vh; }
.main { min-width: 0; display: flex; flex-direction: column; }

/* --- sidebar --- */
.sidebar {
  background: var(--bg); border-right: 1px solid var(--line-soft);
  display: flex; flex-direction: column; padding: 0 14px 16px; gap: 2px;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
/* Same 56px as .topbar — the brand row and the topbar content sit on the
   same horizontal line instead of the sidebar starting lower than the
   topbar, which was wasting vertical space at the top of the canvas. */
.sidebar-brand {
  display: flex; align-items: center; height: 56px; padding: 0 10px;
  border-bottom: 1px solid var(--line-soft); margin-bottom: 14px; flex: none;
  text-decoration: none;
}
.sidebar-brand img { height: 25px; width: auto; display: block; }

/* AI-агент — the product's main feature, not a utility action, so it's
   pulled out of the plain nav list and given its own filled treatment (same
   footprint the old "Подключить аккаунт" button had). Two-tone diagonal
   gradient (blue -> violet) + one soft corner glow for depth. ::before is a
   second, wider multi-hue gradient sliding via background-position — a flat
   colour drift across the surface, not a rotating conic wheel (which pools
   into a visible blob spinning inside a box this small). z-index: -1 keeps
   it strictly behind the icon/text, painted on the button's own background
   layer, never over the label. Dormant until hover/active — permanently
   animated at rest read as busy/distracting. */
.ai-agent-btn {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; align-items: center; justify-content: center; gap: 7px; width: 100%;
  height: 40px; border-radius: 12px; color: var(--primary-ink);
  background:
    radial-gradient(130% 160% at 12% -30%, oklch(0.7 0.14 228 / 0.6) 0%, transparent 60%),
    linear-gradient(135deg, oklch(0.58 0.21 262) 0%, oklch(0.46 0.23 288) 100%);
  font-size: 0.875rem; font-weight: 600; line-height: 1; border: none; cursor: pointer; margin-bottom: 20px;
  box-shadow: 0 3px 12px -3px oklch(0.5 0.2 270 / 0.55), 0 0 0 1px oklch(1 0 0 / 0.1) inset;
  transition: transform 200ms var(--ease-out-expo), box-shadow 200ms var(--ease-out-expo);
}
/* The sparkles glyph's own ink sits slightly above its viewBox's vertical
   middle (two overlapping star shapes, not a symmetric mark) — geometrically
   centered via flexbox still reads as a hair high next to the text baseline;
   this nudges it down to where it looks centered, not just measures centered.
   The breathing scale on top is the "agent is alive" cue up close, same idea
   as the typing-indicator dots in the chat log. */
.ai-agent-btn svg {
  flex: none; display: block; transform-origin: center;
  animation: ai-agent-icon-breathe 2.6s ease-in-out infinite;
}
@keyframes ai-agent-icon-breathe {
  0%, 100% { transform: translateY(1px) scale(1); }
  50% { transform: translateY(1px) scale(1.16); }
}
.ai-agent-btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: linear-gradient(100deg,
    oklch(0.6 0.22 258), oklch(0.56 0.24 292), oklch(0.66 0.2 330), oklch(0.6 0.22 258));
  background-size: 260% 100%; background-position: 0% 50%;
  opacity: 0;
  animation: ai-agent-flow 7s ease-in-out infinite;
  transition: opacity 280ms var(--ease-out-expo);
}
.ai-agent-btn:hover::before, .ai-agent-btn.active::before { opacity: 1; }
@keyframes ai-agent-flow {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}
.ai-agent-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 18px -5px oklch(0.5 0.19 262 / 0.6); }
.ai-agent-btn:active { transform: translateY(0) scale(0.98); }
.ai-agent-btn.active { box-shadow: 0 0 0 1.5px oklch(1 0 0 / 0.3) inset, 0 2px 8px -3px oklch(0.5 0.19 262 / 0.5); }
@media (prefers-reduced-motion: reduce) {
  .ai-agent-btn::before { animation: none; }
  .ai-agent-btn svg { animation: none; }
}

.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-group + .nav-group { margin-top: 20px; }
.nav-group-label {
  font-size: 0.6875rem; color: var(--faint); text-transform: uppercase;
  letter-spacing: 0.06em; padding: 0 10px 8px; font-weight: 600;
}
.nav-item {
  display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 10px;
  border-radius: 9px; color: var(--muted); font-size: 0.875rem; text-decoration: none;
  cursor: pointer; border: none; background: none; font: inherit; text-align: left; width: 100%;
  transition: background 140ms var(--ease-out-expo), color 140ms var(--ease-out-expo);
}
.nav-item svg { flex: none; opacity: 0.75; }
.nav-item:hover { background: var(--bg-alt); color: var(--ink); }
.nav-item.active { background: var(--primary-dim); color: var(--primary); font-weight: 600; }
.nav-item.active svg { opacity: 1; }
.nav-item .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.nav-item .count { margin-left: auto; font-family: var(--font-mono); font-size: 0.75rem; color: var(--faint); }
.nav-item.empty { color: var(--faint); cursor: default; font-size: 0.8125rem; }
.nav-item.empty:hover { background: none; color: var(--faint); }
.nav-item .disconnect-btn {
  margin-left: auto; width: 20px; height: 20px; border-radius: 6px; border: none; background: none;
  color: var(--faint); display: none; align-items: center; justify-content: center; cursor: pointer;
}
.nav-item:hover .disconnect-btn { display: flex; }
.nav-item .disconnect-btn:hover { color: var(--danger); background: var(--danger-dim); }

.sidebar-foot { margin-top: auto; padding-top: 14px; }

/* --- mobile nav (replaces the sidebar below the breakpoint) --- */
.mobile-nav { display: none; }
@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .sidebar { display: none; }
  .mobile-nav {
    display: flex; gap: 6px; overflow-x: auto; padding: 10px clamp(16px, 4vw, 24px);
    background: var(--bg); border-bottom: 1px solid var(--line-soft);
    position: sticky; top: 56px; z-index: calc(var(--z-sticky) - 1);
    scrollbar-width: none;
  }
  .mobile-nav::-webkit-scrollbar { display: none; }
  .mobile-nav button {
    flex: none; height: 32px; padding-inline: 14px; border-radius: 999px; border: 1px solid var(--line);
    background: var(--bg); color: var(--muted); font: inherit; font-size: 0.8125rem; font-weight: 550; cursor: pointer;
  }
  .mobile-nav button.active { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); }
  .mobile-nav button[data-view="agent"] {
    border-color: transparent; color: var(--primary-ink); font-weight: 620;
    background: linear-gradient(135deg, oklch(.58 .21 262), oklch(.46 .23 288));
    box-shadow: 0 3px 10px -4px oklch(.5 .2 270 / .7), 0 0 0 1px oklch(1 0 0 / .12) inset;
  }
  .mobile-nav button[data-view="agent"].active { background: linear-gradient(135deg, oklch(.54 .22 262), oklch(.43 .24 288)); border-color: oklch(1 0 0 / .22); }
}

/* --- topbar --- */
.topbar {
  height: 56px; flex: none; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 0 clamp(16px, 3vw, 40px);
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: oklch(1 0 0 / 0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
}
.topbar-left { display: flex; align-items: center; gap: 16px; min-width: 0; flex: 1 1 auto; overflow: hidden; }
/* topbar-right is only ever a plan-tag pill — wide viewports leave the
   middle of the bar empty while workspace-switcher/sync/badge stay bunched
   at the left edge. Let the switcher actually use that slack instead of
   capping at an arbitrary 340px regardless of how much room the bar has. */
.workspace-switcher { display: inline-flex; align-items: center; gap: 5px; min-width: 0; width: fit-content; flex: 0 1 auto; max-width: min(420px, 100%); padding: 5px 7px; margin-left: -7px; border: none; border-radius: 9px; background: none; color: var(--ink); cursor: pointer; }
.workspace-switcher:hover, .workspace-switcher[aria-expanded="true"] { background: var(--bg-alt); }
.workspace-switcher:focus-visible { outline: 2px solid var(--primary-line); outline-offset: 1px; }
.workspace-switcher .dropdown-caret { flex: none; }
.workspace-name { font-size: 0.875rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.workspace-badge {
  font-family: var(--font-mono); font-size: 0.6875rem; color: var(--muted);
  background: var(--bg-alt); padding: 4px 9px; border-radius: 6px; white-space: nowrap;
}
.workspace-badge.is-warning { color: var(--warning); background: var(--warning-dim); }
@media (max-width: 620px) { .workspace-badge { display: none; } }
/* topbar-left now also carries the sync button (moved here from
   topbar-right so it sits next to the freshness label) — on a narrow phone
   there isn't room for the workspace name too once the plan-tag pill on the
   right claims its natural width, so it collapses to an invisible 0px box
   instead of truncating. Hide it outright below this width — the mobile
   nav bar already labels the current section. */
@media (max-width: 480px) { .topbar { gap: 8px; padding-inline: 12px; } .topbar-left { gap: 8px; } .workspace-switcher { min-width: 0; } .workspace-name { text-overflow: ellipsis; } .plan-tag { padding-inline: 8px; } .plan-tag #plan-days, .plan-tag .plan-sep { display: none; } }
@media (max-width: 360px) { .topbar-right { display: none; } }
.topbar-right { display: flex; align-items: center; gap: 10px; flex: none; }
.period-select {
  font: inherit; font-size: 0.8125rem; color: var(--ink); background: var(--bg-alt);
  border: 1px solid transparent; border-radius: 9px; padding: 7px 11px; cursor: pointer;
}
.period-select:hover { border-color: var(--line); }
.plan-tag {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;
  border-radius: 999px; background: var(--primary-dim); color: var(--primary); border: none;
  font: inherit; font-size: 0.8125rem; font-weight: 620; white-space: nowrap; flex: none;
  cursor: pointer; transition: background 140ms var(--ease-out-expo);
}
.plan-tag:hover, .plan-tag:focus-visible { background: var(--primary-line); }
.plan-tag:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.plan-tag .plan-sep { color: var(--primary-line); }
.plan-tag #plan-days { color: var(--muted); font-weight: 500; }

.billing-plan-control { display: inline-flex; align-items: center; gap: 10px; }
.billing-plan-gift {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; color: var(--primary); background: var(--primary-dim);
  border: 1px solid var(--primary-line); border-radius: 9px; cursor: help; outline: none;
}
.billing-plan-gift:focus-visible { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--primary); }
.billing-plan-gift::after {
  content: attr(data-tooltip); position: absolute; z-index: 4; right: 0; bottom: calc(100% + 8px);
  width: max-content; max-width: 230px; padding: 7px 9px; border-radius: 7px;
  background: var(--ink); color: var(--surface); font-size: 0.75rem; font-weight: 560;
  line-height: 1.3; opacity: 0; pointer-events: none; transform: translateY(3px);
  transition: opacity 120ms ease, transform 120ms ease;
}
.billing-plan-gift:hover::after, .billing-plan-gift:focus-visible::after { opacity: 1; transform: translateY(0); }

/* --- views: exactly one is rendered at a time --- */
.canvas { flex: 1; padding: clamp(22px, 3vw, 38px) clamp(16px, 3vw, 40px) 72px; }
/* 1080px capped every view to a narrow centered column, leaving huge empty
   margins on anything wider than a laptop — the canvas's own horizontal
   padding already lines up with the topbar (same clamp() on both), so the
   working area should use that full width, not re-narrow inside it. Capped
   at 1600px only so table rows and prose don't stretch absurdly on a 4K/
   ultrawide monitor — well past this app's realistic breakpoints otherwise. */
.view { display: none; max-width: 1600px; margin-inline: auto; }
.view.active { display: block; }
@media (prefers-reduced-motion: no-preference) {
  .view.active { animation: view-in 320ms var(--ease-out-expo) backwards; }
  @keyframes view-in { from { opacity: 0; transform: translateY(6px); } }
}

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 26px; flex-wrap: wrap; }
.page-head h1 { font-size: clamp(1.5rem, 1.4vw + 1.1rem, 1.875rem); letter-spacing: -0.025em; }
.page-head p { color: var(--muted); font-size: 0.9375rem; margin-top: 6px; max-width: 62ch; }
.page-head .sub-note { font-size: 0.8125rem; color: var(--faint); margin-top: 4px; }
.page-head .sub-note[hidden] { display: none; }
.page-head-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* --- card --- */
.card {
  background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.card + .card { margin-top: 18px; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-4) var(--space-5); flex-wrap: wrap; }
.card-head + * { border-top: 1px solid var(--border-subtle); }
.card-head h2 { font-size: 0.9375rem; font-weight: 620; letter-spacing: -0.01em; }
.card-head .sub { font-size: 0.8125rem; color: var(--faint); margin-top: 3px; }
.card-head .hint { font-size: 0.8125rem; color: var(--faint); }
.card-body { padding: var(--space-5); }
.card-empty { padding: var(--space-8) var(--space-5); text-align: center; color: var(--text-tertiary); font-size: var(--text-sm); }
.history-load-error { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); padding: var(--space-5); color: var(--danger); background: color-mix(in oklab, var(--danger), transparent 94%); border-top: 1px solid color-mix(in oklab, var(--danger), transparent 76%); font-size: var(--text-sm); }
.history-load-error[hidden] { display: none; }
@media (max-width: 560px) { .history-load-error { align-items: flex-start; flex-direction: column; } }

/* Shared pager for server-backed long lists. It stays quiet when there is no
   second page, but gives a clear result count and large touch targets when a
   dataset needs navigation. */
.pagination { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 22px 14px; border-top: 1px solid var(--line-soft); }
.pagination[hidden] { display: none; }
.pagination-info { min-width: 0; color: var(--faint); font-size: .75rem; }
.pagination-actions { display: flex; align-items: center; gap: 6px; flex: none; }
.pagination-btn { min-width: 32px; height: 30px; padding-inline: 9px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--muted); font: inherit; font-size: .75rem; font-weight: 600; cursor: pointer; }
.pagination-btn:hover:not(:disabled) { border-color: var(--primary-line); color: var(--primary); background: var(--primary-dim); }
.pagination-btn:disabled { opacity: .45; cursor: default; }

/* --- stat cards --- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-4); }
.overview-stat-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.overview-stat-grid--health { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.overview-stat-grid .stat { min-width: 0; padding: 16px; }
.overview-stat-grid .stat .value { font-size: 1.25rem; }
@media (max-width: 1180px) { .overview-stat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px) { .overview-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stat {
  background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-card); padding: var(--space-4) var(--space-5);
  box-shadow: var(--shadow-card);
}
.stat .label { font-size: 0.75rem; color: var(--faint); margin-bottom: 10px; }
.stat .value { font-family: var(--font-mono); font-size: 1.5rem; font-weight: 500; letter-spacing: -0.02em; }
.stat .delta { font-size: 0.75rem; margin-top: 6px; color: var(--faint); }
.stat .delta.up { color: var(--success); }
.stat .delta.down { color: var(--danger); }
.stat--link { text-decoration: none; color: inherit; display: block; cursor: pointer; transition: border-color 140ms var(--ease-out-expo), transform 140ms var(--ease-out-expo); }
.stat--link:hover { border-color: var(--primary-line); transform: translateY(-1px); }
.stat--link .delta { color: var(--primary); font-weight: 550; }

/* --- segmented control (iOS-style) --- */
.segmented { display: inline-flex; background: var(--bg-alt); border-radius: 999px; padding: 3px; gap: 2px; flex-wrap: wrap; }
.segmented button {
  height: 30px; padding-inline: 14px; border-radius: 999px; border: none; background: none;
  color: var(--muted); font: inherit; font-size: 0.8125rem; font-weight: 550; cursor: pointer; white-space: nowrap;
  transition: background 180ms var(--ease-out-expo), color 180ms var(--ease-out-expo);
}
.segmented button:hover { color: var(--ink); }
.segmented button.active { background: var(--bg); color: var(--ink); font-weight: 600; box-shadow: 0 1px 3px oklch(0 0 0 / 0.09); }
.view[data-view="campaigns"] #group-by {
  display: flex; flex-wrap: nowrap; width: max-content; max-width: 100%; overflow-x: auto;
  scrollbar-width: none;
}
.view[data-view="campaigns"] #group-by::-webkit-scrollbar { display: none; }
.view[data-view="campaigns"] #group-by button { flex: 0 0 auto; }

.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 14px 22px; flex-wrap: wrap; }
.toolbar + * { border-top: 1px solid var(--line-soft); }
.toolbar-label { font-size: 0.8125rem; color: var(--faint); }
.filter-chip { height: 32px; padding: 0 10px; border: 1px solid var(--primary-line); border-radius: 999px; color: var(--primary); background: color-mix(in oklab, var(--primary), transparent 92%); font: inherit; font-size: .75rem; font-weight: 600; cursor: pointer; }

/* --- segment breakdown --- */
.seg-bar { display: flex; height: 12px; border-radius: 999px; overflow: hidden; gap: 2px; margin-bottom: 20px; box-shadow: inset 0 0 0 1px var(--line-soft); }
.seg-bar span { height: 100%; transition: width 460ms var(--ease-out-expo); }
.seg-list { display: flex; flex-direction: column; }
.seg-list-row { display: flex; align-items: center; gap: 11px; font-size: 0.875rem; padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.seg-list-row:last-child { border-bottom: none; }
.seg-list-row .swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.seg-list-row .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; }
.seg-list-row .val { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.seg-list-row .share { color: var(--faint); font-family: var(--font-mono); font-size: 0.75rem; width: 40px; text-align: right; }
.seg-list-row.seg-list-empty { color: var(--faint); justify-content: center; }

/* --- Обзор: динамика расхода (SVG multi-line overlay) --- */
.trend-chart-wrap { position: relative; }
.trend-chart-wrap[hidden] { display: none; }
.trend-chart { width: 100%; height: 200px; display: block; cursor: crosshair; }
/* position:fixed with left/top computed per-frame in positionTooltip()
   (app.js) — anchored to the actual cursor, flipped to stay on-screen, so
   no CSS transform is involved in placement. */
.trend-tooltip {
  position: fixed; z-index: var(--z-tooltip);
  background: var(--tooltip-bg); color: var(--tooltip-fg); padding: 9px 12px; border-radius: var(--r-sm);
  font-size: 0.75rem; line-height: 1.6; pointer-events: none; white-space: nowrap;
  box-shadow: 0 12px 28px -10px oklch(0 0 0 / 0.35);
}
.trend-tooltip[hidden] { display: none; }
.trend-tooltip-date { color: oklch(1 0 0 / 0.6); font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px; }
.trend-tooltip-row { display: flex; align-items: center; gap: 7px; }
.trend-tooltip-row + .trend-tooltip-row { margin-top: 2px; }
.trend-tooltip-label { color: oklch(1 0 0 / 0.75); }
.trend-tooltip-row b { font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; margin-left: auto; padding-left: 14px; }
.trend-tooltip-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }

/* Legend doubles as the series toggle — each chip is a real <button>. */
.chart-legend { display: flex; flex-wrap: wrap; gap: 8px; padding: 16px 22px 20px; border-top: 1px solid var(--line-soft); }
.chart-legend-item {
  display: flex; align-items: center; gap: 7px; height: 32px; padding: 0 12px 0 10px; border-radius: 999px;
  border: 1px solid var(--line-soft); background: var(--bg); cursor: pointer; font: inherit; font-size: 0.8125rem;
  color: var(--faint); transition: opacity 140ms var(--ease-out-expo), border-color 140ms var(--ease-out-expo);
  opacity: 0.55;
}
.chart-legend-item:hover { opacity: 0.85; }
.chart-legend-item.active { color: var(--ink); border-color: var(--line); opacity: 1; }
.chart-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.chart-legend-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--muted); }
.chart-legend-item.active .chart-legend-value { color: var(--ink); }

.client-delta { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.client-delta.up { color: var(--success); }
.client-delta.down { color: var(--danger); }
.client-delta.flat { color: var(--faint); }

/* --- Обзор: статусы кампаний (счётчики) --- */
.status-chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line-soft); }

/* --- Overview: agency action triage --- */
.overview-two-col { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(320px, 0.75fr); gap: 18px; margin-top: 18px; }
.overview-two-col .card + .card { margin-top: 0; }
.overview-niche-table table.data, table.data.data--compact { min-width: 0; }
.overview-niche-table table.data th, .overview-niche-table table.data td, table.data.data--compact th, table.data.data--compact td { padding-inline: 16px; }
.overview-niche-table table.data td.num { font-size: .8125rem; }
/* Left-aligned (not right-aligned like plain .num columns elsewhere) — a
   right-aligned stack of varying-width numbers reads as a ragged, jumpy
   column; left-aligning keeps every row's value flush under the header. */
.overview-niche-table th.num, .overview-niche-table td.num { text-align: left; }
.niche-metric { display: grid; gap: 2px; justify-items: start; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.niche-metric small { color: var(--faint); font-size: .6875rem; }
.attention-list { display: grid; gap: 4px; }
.attention-item { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--line-soft); color: inherit; text-decoration: none; min-width: 0; }
.attention-item:last-child { border-bottom: 0; }
.attention-item .attention-icon { display: grid; place-items: center; width: 25px; height: 25px; flex: none; border-radius: 8px; background: var(--bg-alt); color: var(--primary); font-size: .75rem; font-weight: 700; }
.attention-item.is-danger .attention-icon { background: color-mix(in oklab, var(--danger), transparent 87%); color: var(--danger); }
.attention-item .attention-copy { min-width: 0; flex: 1; }
/* Wrap long titles/notes onto a second line instead of truncating — a grid
   item's default min-width:auto otherwise keeps this whole row from
   shrinking below its unwrapped text width, so the row (and its ellipsis)
   silently overflowed the card to the right instead of ever kicking in. */
.attention-item b, .attention-item span { display: block; overflow-wrap: break-word; }
.attention-item b { font-size: .8125rem; font-weight: 620; }
.attention-item span { margin-top: 2px; color: var(--faint); font-size: .75rem; }
.attention-empty { padding: 8px 0 2px; }
/* Лучшая/худшая динамика — a mirrored pair of cards, so unlike the
   asymmetric niche/attention row above, both columns get equal width. */
.overview-two-col--even { grid-template-columns: 1fr 1fr; }
.mover-list { display: grid; gap: 4px; }
.mover-item { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--line-soft); min-width: 0; }
.mover-item:last-child { border-bottom: 0; }
.mover-copy { min-width: 0; flex: 1; }
.mover-copy b, .mover-copy span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mover-copy b { font-size: .8125rem; font-weight: 620; }
.mover-copy span { margin-top: 2px; color: var(--faint); font-size: .75rem; }
.mover-cpa { flex: none; text-align: right; font-variant-numeric: tabular-nums; }
.mover-cpa-value { font-family: var(--font-mono); font-size: .8125rem; font-weight: 620; }
.mover-cpa .client-delta { display: block; margin-top: 2px; font-size: .75rem; }
@media (max-width: 950px) { .overview-two-col { grid-template-columns: 1fr; } }

/* --- table ---
   13 columns (Статистика: клиент + 9 метрик + бюджет/формат/статус) at
   width:100% + table-layout:auto was squeezing every column below its
   content's natural width on anything but a very wide screen — client
   names wrapped to 2-3 lines, "Расход с НДС"/"Бюджет и стратегия" wrapped
   too, rows ended up uneven heights. min-width forces natural sizing;
   .table-scroll (overflow-x:auto) already handles narrower viewports with
   a horizontal scroll instead of cramming everything. */
.table-scroll { overflow-x: auto; }
table.data { width: 100%; min-width: 1180px; border-collapse: collapse; }
table.data th {
  text-align: left; font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--faint); font-weight: 620; padding: 12px 22px; border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}
table.data td { padding: 14px 22px; border-bottom: 1px solid var(--line-soft); font-size: 0.875rem; vertical-align: middle; white-space: nowrap; }
table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr:hover td { background: var(--bg-alt); }
td.num, th.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
table.data th:first-child, table.data td:first-child { width: 260px; }
.view[data-view="campaigns"] table.data { min-width: 1090px; }
.view[data-view="campaigns"] table.data th, .view[data-view="campaigns"] table.data td { border-bottom: none; }
.view[data-view="campaigns"] table.data tbody tr:hover td { background: var(--primary-dim); }
.view[data-view="campaigns"] table.data th:nth-child(2), .view[data-view="campaigns"] table.data td:nth-child(2), .view[data-view="campaigns"] table.data th:nth-child(8), .view[data-view="campaigns"] table.data td:nth-child(8) { min-width: 112px; }
.view[data-view="campaigns"] table.data th:nth-child(3), .view[data-view="campaigns"] table.data td:nth-child(3), .view[data-view="campaigns"] table.data th:nth-child(7), .view[data-view="campaigns"] table.data td:nth-child(7) { min-width: 104px; }
/* CPL/CPQL columns (account settings popup) — only meaningful once at least
   one visible row has the metric configured; setupCampaignTable's render()
   toggles these two classes on the table itself rather than rebuilding
   every row's markup just to add/remove a cell. */
table.data.hide-cpl .col-cpl, table.data.hide-cpql .col-cpql { display: none; }
.tree-cell-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Статистика drill-down tree: Клиент → Кампания → Группа → Объявление ---
   No default fill on any row — a plain table by default reads calmer, and
   the previous unconditional light overlay on every campaign/ad-group/ad
   row made the whole body look shaded regardless of state. Only a row that
   is itself currently expanded (see tree-row--open, set from JS render() in
   setupCampaignTable) gets the same --bg-alt tone group headers always used
   — a closed row and a leaf (ad) row, which never expands, both stay plain. */
.tree-row { cursor: pointer; }
.tree-row--leaf { cursor: default; }
.tree-row--message { cursor: default; }
.tree-row--open td { background: var(--bg-alt); }
.tree-cell { display: flex; align-items: center; gap: 11px; padding-left: calc(var(--tree-indent, 0) * 20px); }
.tree-cell .p-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.tree-cell .meta { color: var(--faint); font-size: 0.75rem; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Flex children default to min-width:auto (content-based), which blocks
   ellipsis truncation from ever kicking in — this is the one declaration
   that actually lets a long client/campaign name shrink and truncate
   instead of forcing the row (and the whole table) wider. */
.tree-cell > div:not(.p-dot) { min-width: 0; flex: 1; }
.tree-cell--message { color: var(--faint); font-size: 0.8125rem; }
.tree-chevron { flex: none; color: var(--faint); transition: transform 160ms var(--ease-out-expo); }
.tree-chevron--open { transform: rotate(90deg); }
.tree-chevron-spacer { display: inline-block; width: 10px; flex: none; }
.group-header-row td { padding: 9px 22px; border-bottom: 1px solid var(--line-soft); }
.group-header-row .group-header-cell { gap: 9px; }
.group-header-row .group-name { font-size: 0.8125rem; font-weight: 620; }
.group-header-row .pill { font-size: 0.6875rem; padding: 2px 8px; margin-right: 4px; }

/* --- generic row (queue / log / hypotheses) --- */
.row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 15px 22px; border-bottom: 1px solid var(--line-soft);
}
.row:last-child { border-bottom: none; }
.row .row-main { min-width: 0; }
.row .row-title { font-size: 0.875rem; }
.row .row-sub { font-size: 0.8125rem; color: var(--faint); margin-top: 3px; }
.row .row-actions { display: flex; gap: 8px; flex: none; align-items: center; }
.row-delete-btn {
  width: 28px; height: 28px; border-radius: 8px; border: none; cursor: pointer; flex: none;
  background: none; color: var(--faint);
  display: flex; align-items: center; justify-content: center;
  transition: color 140ms var(--ease-out-expo), background 140ms var(--ease-out-expo);
}
.row-delete-btn:hover { color: var(--danger); background: var(--danger-dim); }
.row.resolved {
  animation: row-out 260ms var(--ease-out-expo) forwards;
}
@keyframes row-out { to { opacity: 0; transform: translateX(10px); max-height: 0; padding-top: 0; padding-bottom: 0; border-bottom-width: 0; } }
@media (prefers-reduced-motion: reduce) { .row.resolved { display: none; } }

.icon-btn {
  width: 32px; height: 32px; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: var(--bg); color: var(--muted); cursor: pointer;
  transition: background 140ms, color 140ms, border-color 140ms;
}
.icon-btn:hover { background: var(--bg-alt); color: var(--ink); }
.icon-btn.approve:hover { color: var(--success); border-color: var(--success); background: var(--success-dim); }
.icon-btn.reject:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-dim); }

/* --- log (История) ---
   .log-body now stacks two lines (tags row, then summary) instead of one
   inline strong+span pair, so .log-row switched from baseline to
   flex-start alignment — a multi-line body against a single-line time
   column reads oddly on a shared text baseline. .log-detail-btn sits as a
   third flex child (margin-left:auto pins it to the right), not appended
   inside .log-body's own markup like the old impact button was. */
/* Day header → rows: [icon] [title+status / summary / account+campaigns] [time+details]. */
.log-day {
  padding: 14px 22px 6px; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--faint); border-bottom: 1px solid var(--line-soft);
}
.log-row { display: flex; gap: 14px; padding: 13px 22px; border-bottom: 1px solid var(--line-soft); font-size: 0.8438rem; align-items: flex-start; }
.log-row:last-child { border-bottom: none; }
.log-icon {
  width: 30px; height: 30px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; background: var(--bg-alt); color: var(--muted);
}
.log-icon img { width: 18px; height: 18px; object-fit: contain; }
.log-icon--agent { background: var(--primary-dim); color: var(--primary); }
.log-body { min-width: 0; flex: 1; display: grid; gap: 4px; }
.log-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.log-title { font-weight: 600; color: var(--ink); }
.log-summary { color: var(--muted); font-size: 0.8125rem; overflow-wrap: anywhere; }
.log-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.log-account { font-size: 0.75rem; font-weight: 550; color: var(--ink); white-space: nowrap; max-width: 280px; overflow: hidden; text-overflow: ellipsis; }
.log-id { font-family: var(--font-mono); font-weight: 400; color: var(--faint); }
.log-tag.log-campaign { display: inline-flex; align-items: baseline; gap: 6px; max-width: 340px; }
.log-campaign-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.log-campaign .log-id { flex: none; }
.log-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.log-time { font-family: var(--font-mono); color: var(--faint); font-size: 0.75rem; padding-top: 2px; }
.log-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 4px; }
/* Flat chip, not a .pill — .pill already carries the dot+colour meaning
   "type of event" (see HISTORY_BADGE_CLASS); client/campaign are plain
   identifying labels, a second dotted pill next to the first would read as
   two competing statuses instead of one status + two names. */
.log-tag {
  font-size: 0.75rem; color: var(--muted); background: var(--bg-alt);
  border-radius: var(--r-sm); padding: 2px 7px; white-space: nowrap;
  max-width: 220px; overflow: hidden; text-overflow: ellipsis;
}
.log-detail-btn {
  flex: none; font: inherit; font-size: 0.75rem; font-weight: 600; color: var(--primary);
  background: none; border: none; padding: 0; cursor: pointer; white-space: nowrap;
}
.log-detail-btn:hover { text-decoration: underline; }
.log-detail-panel { padding: 4px 22px 18px 66px; border-bottom: 1px solid var(--line-soft); display: grid; gap: 16px; }
.detail-section-title { margin: 0 0 8px; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--faint); }
.log-detail-panel .detail-note { margin: 0 0 10px; color: var(--faint); font-size: 0.75rem; line-height: 1.45; }
/* Effect windows: one card per window; comparison only when both sides
   cover the same number of closed days, otherwise a progress bar. */
.effect-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 10px; }
.effect-card { display: grid; gap: 6px; align-content: start; padding: 11px 12px; border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: var(--bg); }
.effect-card.is-complete { border-color: var(--line); }
.effect-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 0.8125rem; white-space: nowrap; }
.effect-chip { font-size: 0.6875rem; color: var(--faint); background: var(--bg-alt); border-radius: var(--r-pill); padding: 2px 8px; white-space: nowrap; }
.effect-card.is-complete .effect-chip { color: var(--success); background: var(--success-dim); }
.effect-card.is-insufficient .effect-chip { color: var(--warning); background: var(--warning-dim); }
.effect-metric { display: grid; grid-template-columns: 1fr auto; align-items: baseline; column-gap: 8px; row-gap: 1px; font-size: 0.75rem; }
.effect-metric-label { color: var(--faint); }
.effect-metric-values { grid-column: 1 / -1; font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.effect-metric-values b { color: var(--ink); font-weight: 550; }
.effect-metric-delta { grid-column: 2; grid-row: 1; font-size: 0.6875rem; }
.effect-progress { height: 4px; border-radius: var(--r-pill); background: var(--bg-alt); overflow: hidden; margin-top: 4px; }
.effect-progress i { display: block; height: 100%; background: var(--primary); border-radius: inherit; }
.effect-card-note { color: var(--faint); font-size: 0.6875rem; line-height: 1.4; }
.log-detail-panel .hyp-diff { margin-bottom: 12px; }
.log-detail-panel .hyp-diff:last-child { margin-bottom: 0; }
.execution-history-inline { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.execution-history-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 9px; color: var(--muted); font-size: 0.75rem; }
.execution-history-head strong { color: var(--text-primary); font-weight: 650; }
.execution-history-list { display: grid; gap: 7px; }
.execution-history-attempts { display: grid; gap: 7px; margin-top: 10px; }
.execution-history-subhead { color: var(--muted); font-size: 0.75rem; }
.execution-history-row { display: flex; justify-content: space-between; gap: 12px; padding: 8px 10px; border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: var(--bg-alt); font-size: 0.8125rem; }
.execution-history-status { color: var(--muted); white-space: nowrap; }
.execution-history-events { display: grid; gap: 5px; margin-top: 10px; color: var(--faint); font-size: 0.75rem; }
.execution-history-event { display: flex; justify-content: space-between; gap: 12px; }
.execution-history-note, .execution-history-loading { margin-top: 8px; color: var(--muted); font-size: 0.75rem; }
.effect-history { margin-top: 15px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.effect-history-toggle { display: inline-block; }
.effect-history-content[hidden] { display: none; }
.effect-history-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 9px; color: var(--muted); font-size: 0.75rem; }
.effect-history-head strong { color: var(--text-primary); font-weight: 650; }
.effect-history-list { display: grid; gap: 8px; }
.effect-history-row { padding: 9px 10px; border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: var(--bg-alt); }
.effect-history-row-head { display: flex; justify-content: space-between; gap: 12px; color: var(--muted); font-size: 0.75rem; }
.effect-history-row-head strong { color: var(--text-primary); font-weight: 600; }
.effect-history-row-head span, .effect-history-meta, .effect-history-note { color: var(--faint); font-size: 0.6875rem; }
.effect-history-metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 8px; }
.effect-history-metric { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 0.75rem; }
.effect-history-metric > span:first-child { color: var(--faint); }
.effect-history-metric > span:last-child { overflow-wrap: anywhere; }
.effect-history-meta { margin-top: 8px; }
.effect-history-note { margin-top: 5px; color: var(--muted); }
.effect-history-empty, .effect-history-error { color: var(--faint); font-size: 0.75rem; }
.effect-history-pager { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 10px; }
.effect-history-content > .pagination-btn { margin-top: 10px; }

@media (max-width: 680px) {
  .effect-history-metrics { grid-template-columns: 1fr; gap: 5px; }
  .effect-history-row-head { flex-direction: column; gap: 2px; }
  .effect-history-pager { align-items: flex-start; flex-direction: column; }
}

/* --- audits --- */
.audit-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 328px); gap: 18px; align-items: start; }
.audit-layout > .card + .card { margin-top: 0; }
.audit-side-card { display: flex; flex-direction: column; position: sticky; top: 74px; max-height: calc(100vh - 96px); overflow: hidden; }
.audit-side-tabs { display: flex; gap: 2px; width: fit-content; margin: 12px 14px 0; padding: 3px; background: var(--bg-alt); border-radius: 999px; flex: none; }
.audit-side-tab { font: inherit; font-size: 0.75rem; font-weight: 550; color: var(--muted); background: none; border: none; border-radius: 999px; height: 30px; padding-inline: 10px; cursor: pointer; display: flex; align-items: center; gap: 5px; }
.audit-side-tab:hover { color: var(--ink); }
.audit-side-tab.active { color: var(--ink); font-weight: 600; background: var(--bg); box-shadow: 0 1px 3px oklch(0 0 0 / 0.09); }
.audit-side-count { font-family: var(--font-mono); font-size: 0.6875rem; background: var(--primary); color: var(--primary-ink); border-radius: 999px; min-width: 16px; height: 16px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center; }
.audit-side-tab:not(.active) .audit-side-count { background: var(--faint); }
.audit-side-panel { flex: 1; overflow-y: auto; padding: 12px 14px 16px; }
.audit-side-panel[hidden] { display: none; }
.audit-history-row { align-items: flex-start; gap: 9px; }
.audit-history-row.active { background: var(--primary-dim); }
.audit-history-row .row-title { line-height: 1.35; }
.audit-history-row .row-sub { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.audit-history-row .row-delete-btn { position: relative; flex: none; margin-top: 1px; width: 28px; height: 28px; padding: 0; border-radius: 8px; font-size: 0; color: var(--faint); }
.audit-history-row .row-delete-btn::before, .audit-history-row .row-delete-btn::after { content: ""; position: absolute; width: 12px; height: 1.5px; background: currentColor; border-radius: 1px; }
.audit-history-row .row-delete-btn::before { transform: rotate(45deg); }
.audit-history-row .row-delete-btn::after { transform: rotate(-45deg); }
.audit-history-row .row-delete-btn:hover { color: var(--danger); background: var(--danger-dim); }
.audit-findings-context { margin-bottom: 10px; font-size: 0.75rem; color: var(--muted); line-height: 1.4; }
.audit-side-finding { padding: 11px 0; border-bottom: 1px solid var(--line-soft); }
.audit-side-finding:last-child { border-bottom: none; }
.audit-side-finding .audit-title { margin-top: 8px; font-size: 0.8125rem; }
.audit-side-finding .audit-verdict { font-size: 0.75rem; line-height: 1.5; }
.audit-side-finding .audit-suggestion { font-size: 0.6875rem; line-height: 1.4; }
.audit-side-finding .hyp-actions { margin-top: 9px; gap: 6px; }
.audit-side-finding .btn-sm { height: 29px; padding-inline: 9px; font-size: 0.6875rem; }
@media (max-width: 1180px) { .audit-layout { grid-template-columns: 1fr; } .audit-side-card { position: static; max-height: none; min-height: 300px; } }
.audit-progress { padding: 26px 22px; }
.audit-progress[hidden] { display: none; }
.audit-progress .step-text { font-size: 0.875rem; color: var(--muted); margin-bottom: 14px; }
.audit-progress .bar-track { height: 5px; border-radius: 5px; background: var(--bg-alt); overflow: hidden; }
.audit-progress .bar-fill { height: 100%; width: 0; background: var(--primary); border-radius: 5px; transition: width 440ms var(--ease-out-expo); }
.audit-progress .bar-fill.indeterminate { width: 40%; animation: bar-indet 1.7s ease-in-out infinite; }
@keyframes bar-indet { 0% { margin-left: -40%; } 100% { margin-left: 100%; } }
@media (prefers-reduced-motion: reduce) {
  .audit-progress .bar-fill.indeterminate { animation: none; margin-left: 0; width: 60%; }
}
.audit-results[hidden] { display: none; }

/* Methodology intro — period/coverage, printed once per completed run. */
.audit-intro { padding-bottom: 6px; }
.audit-methodology { padding: 0 22px 18px; }
.audit-coverage-note { font-size: 0.8125rem; color: var(--muted); line-height: 1.55; margin: 0 0 8px; max-width: 78ch; }
.audit-coverage-line { font-size: 0.8438rem; color: var(--ink); font-weight: 600; margin: 0; }
/* Global account-wide anomalies (e.g. zero conversions across all spend) —
   surfaced right in the methodology intro, not buried in a per-item row. */
.audit-flag { font-size: 0.8125rem; color: var(--warning); background: var(--warning-dim); border-radius: var(--r-md); padding: 8px 12px; margin: 0 0 8px; line-height: 1.5; max-width: 78ch; }

/* Blocks — one section per checklist category, numbered "block.item". */
.audit-block { border-top: 1px solid var(--line-soft); }
.audit-block:first-child { border-top: none; }
.audit-block-header { display: flex; align-items: center; gap: 10px; padding: 16px 22px 6px; }
.audit-block-header h3 { font-size: 0.9375rem; font-weight: 650; letter-spacing: -0.008em; margin: 0; }
.audit-block-items { display: flex; flex-direction: column; }

/* Fixed number/pill columns so every title starts on the same x regardless
   of "4.10" vs "4.2" width or pill label length. */
.audit-item { display: grid; grid-template-columns: 30px 1fr auto; gap: 14px; padding: 13px 22px; border-top: 1px solid var(--line-soft); align-items: start; }
.audit-block-items .audit-item:first-child { border-top: none; }
.audit-item-num { font-size: 0.75rem; color: var(--faint); padding-top: 2px; }
.audit-item-pill { margin-top: 1px; justify-self: end; white-space: nowrap; }
@media (max-width: 640px) {
  .audit-item { grid-template-columns: 20px 1fr; }
  .audit-item-pill { grid-column: 2; justify-self: start; margin-top: 4px; }
}
.audit-item-head { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.audit-title { font-size: 0.9062rem; font-weight: 600; letter-spacing: -0.005em; }
.audit-verdict { font-size: 0.8438rem; color: var(--muted); line-height: 1.6; max-width: 68ch; }
.audit-suggestion { font-size: 0.8125rem; color: var(--faint); margin-top: 6px; }

/* Per-block AI narrative — grounded problems/positives/hypotheses, only
   rendered when the model actually produced content for that block. */
.audit-narrative { margin: 6px 22px 16px; padding: 14px 16px; background: var(--bg-alt); border-radius: var(--r-md); display: flex; flex-direction: column; gap: 10px; }
.audit-narrative-head { font-size: 0.75rem; font-weight: 650; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.audit-narrative-group ul { margin: 4px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.audit-narrative-group li { font-size: 0.8281rem; line-height: 1.55; color: var(--ink); }
.audit-narrative-label { font-size: 0.75rem; font-weight: 600; }
.audit-narrative-problems .audit-narrative-label { color: var(--danger); }
.audit-narrative-positives .audit-narrative-label { color: var(--success); }
.audit-narrative-hypotheses .audit-narrative-label { color: var(--primary); }

/* Overall conclusion — Критично/Важно/Желательно, the last thing on the page. */
.audit-conclusion { border-top: 1px solid var(--line); padding: 20px 22px 22px; background: var(--bg-alt); }
.audit-conclusion[hidden] { display: none; }
.audit-conclusion-head h3 { font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.012em; margin: 0 0 12px; }
.audit-conclusion-tier { padding: 12px 14px; border-radius: var(--r-md); background: var(--bg); border: 1px solid var(--line-soft); margin-bottom: 10px; }
.audit-conclusion-tier:last-child { margin-bottom: 0; }
.audit-conclusion-label { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
.audit-conclusion-critical .audit-conclusion-label { color: var(--danger); }
.audit-conclusion-important .audit-conclusion-label { color: var(--warning); }
.audit-conclusion-nice .audit-conclusion-label { color: var(--muted); }
.audit-conclusion-tier ul { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 5px; }
.audit-conclusion-tier li { font-size: 0.8438rem; line-height: 1.55; color: var(--ink); }

/* --- agent hypotheses: two-step confirm --- */
.hyp-detail { padding: 0 22px 18px; border-bottom: 1px solid var(--line-soft); }
.hyp-detail[hidden] { display: none; }
.hyp-diff { background: var(--bg-alt); border-radius: 12px; padding: 14px 16px; margin-bottom: 14px; }
.hyp-diff-line { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; font-size: 0.8438rem; padding: 5px 0; }
.hyp-diff-line > span:not(.field) { min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; word-break: break-word; }
.hyp-diff-line .field { flex: 0 0 min(200px, 34%); min-width: 0; color: var(--muted); white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
.hyp-diff .d-old { color: var(--danger); text-decoration: line-through; opacity: 0.75; font-family: var(--font-mono); overflow-wrap: anywhere; word-break: break-word; white-space: pre-line; }
.hyp-diff .d-new { color: var(--success); font-weight: 600; font-family: var(--font-mono); overflow-wrap: anywhere; word-break: break-word; white-space: pre-line; }
.hyp-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.hyp-note { font-size: 0.75rem; color: var(--faint); }
.hyp-tree { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.hyp-tree-grid { display: flex; flex-direction: column; gap: 1px; }
.hyp-tree-row { display: flex; align-items: flex-start; gap: 14px; padding: 5px 0; font-size: 0.8438rem; }
.hyp-tree-row .field { flex: 0 0 min(180px, 34%); min-width: 0; color: var(--muted); white-space: nowrap; }
.hyp-tree-value { min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; word-break: break-word; }
.hyp-tree-section-title, .hyp-tree-subtitle { color: var(--muted); font-size: 0.75rem; font-weight: 650; }
.hyp-tree-section-title { padding-top: 4px; border-top: 1px solid var(--line-soft); }
.hyp-tree-subtitle { margin-top: 8px; }
.hyp-tree-groups { display: flex; flex-direction: column; gap: 8px; }
.hyp-tree-group { border: 1px solid var(--line-soft); border-radius: 10px; background: var(--bg); min-width: 0; }
.hyp-tree-group summary, .hyp-tree-list-details summary { cursor: pointer; padding: 9px 11px; color: var(--ink); font-size: 0.8125rem; font-weight: 600; overflow-wrap: anywhere; }
.hyp-tree-group-body { padding: 0 11px 11px; font-size: 0.8125rem; line-height: 1.5; overflow-wrap: anywhere; word-break: break-word; }
.hyp-tree-meta { color: var(--faint); font-size: 0.75rem; font-weight: 400; }
.hyp-tree-list { margin: 4px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; overflow-wrap: anywhere; word-break: break-word; }
.hyp-tree-muted { color: var(--faint); font-size: 0.8125rem; }
.hyp-tree-warning { margin-top: 8px; padding: 8px 10px; border-radius: 8px; color: var(--muted); background: var(--bg-alt); font-size: 0.75rem; line-height: 1.45; overflow-wrap: anywhere; }
.hyp-tree-ads { display: flex; flex-direction: column; gap: 7px; margin-top: 4px; }
.hyp-tree-ad { padding: 8px 10px; border-radius: 8px; background: var(--bg-alt); overflow-wrap: anywhere; word-break: break-word; }
.hyp-tree-ad-title { font-weight: 600; margin-bottom: 2px; }
.hyp-tree-url { color: var(--primary); font-family: var(--font-mono); font-size: 0.75rem; margin-top: 3px; }
.hyp-tree-provider-json { margin-top: 4px; padding: 7px 9px; border-radius: 7px; background: var(--bg-alt); color: var(--muted); font: .72rem/1.45 var(--font-mono); overflow-wrap: anywhere; word-break: break-word; white-space: pre-wrap; }
.hyp-tree-list-details { border-top: 1px solid var(--line-soft); padding-top: 3px; }
.hyp-tree-volume .hyp-tree-list { max-height: 220px; overflow: auto; }
.hyp-tree-group .hyp-tree-list-details .hyp-tree-list { max-height: 220px; overflow: auto; }
/* kind badge (2026-08-10) — sits inline before the title text on both the
   Гипотезы row and the chat confirm card (renderHypothesis/
   appendChatActionCard, both build this markup via renderDiffSummary's
   sibling helpers in app.js). Plain margin, no new tokens — .pill already
   carries its own colour per category (pill-success/-primary/-neutral, see
   KIND_BADGE_CLASS in app.js, same map История's badges use). */
.row-title .pill, .chat-action-title .pill { margin-right: 8px; vertical-align: middle; }
/* proposedPlan multi-step confirm card (Вариант D+, 2026-08-10) — a plan's
   diffSummary is {type:'plan', steps:[...]}, each step rendered via the
   same renderDiffSummary recursively, just wrapped with a numbered label so
   "3 шага: выдать доступ → создать кампанию → перенести ключи" (the shape
   CAMPAIGN_FLOW_ROADMAP.md envisioned) reads as a sequence, not a jumble. */
.plan-steps { display: flex; flex-direction: column; gap: 4px; }
.plan-step-label { font-size: 0.8125rem; font-weight: 600; color: var(--muted); margin-bottom: 4px; }
@media (max-width: 640px) {
  .hyp-diff-line, .hyp-tree-row { flex-direction: column; gap: 3px; }
  .hyp-diff-line .field, .hyp-tree-row .field { flex-basis: auto; white-space: normal; }
}

/* --- settings --- */
.setting-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; padding: 17px 22px; border-bottom: 1px solid var(--line-soft); }
.setting-row[hidden] { display: none; }
.setting-row:last-child { border-bottom: none; }
.setting-row .k { font-size: 0.875rem; font-weight: 550; }
.setting-row .d { font-size: 0.8125rem; color: var(--muted); margin-top: 3px; max-width: 54ch; }
.setting-row .v { font-size: 0.8438rem; color: var(--muted); text-align: right; flex: none; }
@media (max-width: 640px) { .setting-row { flex-direction: column; gap: 6px; } .setting-row .v { text-align: left; } }
.link-row { display: flex; gap: 20px; padding: 16px 22px; flex-wrap: wrap; }
.link-row a { font-size: 0.8438rem; color: var(--primary); text-decoration: none; }
.link-row a:hover { text-decoration: underline; }
.workspace-name-form, .workspace-member-form { display: flex; align-items: center; gap: 8px; flex: none; }
.btn-danger { color: var(--danger); border-color: var(--danger-dim); }
.btn-danger:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-dim); }
.workspace-name-form .field-input { width: min(250px, 30vw); }
.workspace-member-form .field-input { width: min(230px, 28vw); }
.workspace-members { padding: 0 22px; }
.workspace-member { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 0; border-top: 1px solid var(--line-soft); color: var(--muted); font-size: 0.8125rem; }
.workspace-member:first-child { border-top: none; }
@media (max-width: 640px) { .workspace-name-form, .workspace-member-form { width: 100%; } .workspace-name-form .field-input, .workspace-member-form .field-input { width: 100%; } }
.workspace-currency-select, .workspace-vat-select { width: 240px; max-width: min(240px, 100%); min-width: 0; flex: none; }
.view[data-view="settings"] .field-input,
.view[data-view="settings"] .btn { min-height: 36px; border-radius: 10px; }
.view[data-view="settings"] .field-input { background: var(--bg); border: 1px solid var(--line-soft); padding: 0 12px; }
.view[data-view="settings"] select.field-input { padding-right: 30px; }
.view[data-view="settings"] .btn { padding-inline: 14px; font-size: .8125rem; }
.inline-action { display: inline-flex; align-items: center; margin-left: 5px; color: var(--primary); font-weight: 650; text-decoration: none; }
.inline-action:hover { text-decoration: underline; }

/* --- integrations (Настройки → Интеграции) --- */
.integration-group + .integration-group { border-top: 1px solid var(--line-soft); }
.integration-group-label {
  font-size: 0.6875rem; color: var(--faint); text-transform: uppercase; letter-spacing: 0.06em;
  font-weight: 620; padding: 14px 22px 4px;
}
.integration-row { align-items: center; }
.integration-row .k { display: flex; align-items: center; justify-content: flex-start; gap: 14px; min-width: 0; text-align: left; }
.integration-row .k-name { font-size: 0.875rem; font-weight: 600; color: var(--ink); }
.integration-row .d { font-size: 0.8125rem; color: var(--muted); margin-top: 2px; max-width: 46ch; }
.service-logo {
  width: 40px; height: 40px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 10px; overflow: hidden;
}
.service-logo img { display: block; width: 100%; height: 100%; object-fit: contain; padding: 3px; }
.integration-row.is-soon .service-logo { opacity: 0.6; }

/* Account goal multi-select */
.field-hint { display: block; margin: 4px 0 7px; color: var(--faint); font-size: .75rem; font-weight: 400; line-height: 1.4; }
.goal-search { margin-top: 2px; }
.goal-picker { display: grid; gap: 5px; max-height: 190px; margin-top: 7px; overflow: auto; padding: 3px; border: 1px solid var(--line-soft); border-radius: 11px; background: var(--bg-alt); }
.goal-option { display: flex; align-items: center; gap: 9px; padding: 8px 9px; border-radius: 8px; cursor: pointer; transition: background 140ms var(--ease-out-expo); }
.goal-option:hover { background: var(--surface); }
.goal-option input { width: 16px; height: 16px; accent-color: var(--primary); flex: none; }
.goal-option span { display: grid; gap: 1px; min-width: 0; }
.goal-option b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .8125rem; font-weight: 600; }
.goal-option small { color: var(--faint); font: .6875rem var(--font-mono); }
.goal-picker-empty, .goal-picker-loading { padding: 13px 10px; color: var(--faint); font-size: .75rem; }

/* First-entry guidance */
.onboarding-layer { position: fixed; inset: 0; z-index: calc(var(--z-modal) - 2); pointer-events: none; background: oklch(0.18 0 0 / .08); }
.onboarding-card { position: fixed; width: min(350px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); overflow: auto; padding: 18px 18px 15px; border: 1px solid var(--primary-line); border-radius: 16px; background: var(--surface); box-shadow: 0 18px 50px oklch(0.16 0.02 260 / .18), 0 0 0 6px var(--primary-dim); pointer-events: auto; animation: onboarding-in 280ms var(--ease-out-expo) both; }
.onboarding-card h2 { margin: 0 0 6px; font-size: 1rem; letter-spacing: -.015em; }
.onboarding-card p { margin: 0; color: var(--muted); font-size: .8125rem; line-height: 1.5; }
.onboarding-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 15px; }
.onboarding-skip { padding: 5px 0; border: none; background: none; color: var(--faint); font: inherit; font-size: .75rem; cursor: pointer; }
.onboarding-skip:hover { color: var(--muted); }
.onboarding-focus { position: relative; z-index: calc(var(--z-modal) - 1); box-shadow: 0 0 0 4px var(--surface), 0 0 0 7px var(--primary-line) !important; border-radius: 10px; }
@keyframes onboarding-in { from { opacity: 0; transform: translateY(7px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .onboarding-card { animation: none; } }

/* --- iOS-style toggle switch (Автоправила, Уведомления) --- */
.switch { position: relative; display: inline-flex; align-items: center; width: 38px; height: 22px; flex: none; cursor: pointer; }
.switch input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.switch-track {
  position: absolute; inset: 0; border-radius: 999px; background: var(--line);
  transition: background 160ms var(--ease-out-expo);
}
.switch-track::before {
  content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--bg); box-shadow: 0 1px 3px oklch(0 0 0 / 0.25);
  transition: transform 160ms var(--ease-out-expo);
}
.switch input:checked + .switch-track { background: var(--primary); }
.switch input:checked + .switch-track::before { transform: translateX(16px); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--primary); outline-offset: 2px; }

/* --- Мониторинг --- */
.monitoring-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-bottom: 16px; }
.monitoring-summary-card { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding: 14px 16px; border: 1px solid var(--line-soft); border-radius: 13px; background: var(--bg); color: var(--ink); text-align: left; cursor: pointer; }
.monitoring-summary-card:hover { border-color: var(--faint); box-shadow: var(--sh-1); }
.monitoring-summary-card b { font: 620 1.35rem/1 var(--font-mono); }
.monitoring-summary-card span { color: var(--muted); font-size: .75rem; }
.monitoring-summary-card.critical { border-color: oklch(.67 .19 25 / .38); }.monitoring-summary-card.important { border-color: oklch(.72 .15 72 / .42); }.monitoring-summary-card.attention { border-color: var(--primary-line); }
.monitoring-head { gap: 16px; }.monitoring-filters { display: flex; gap: 8px; flex-wrap: wrap; }
.monitoring-issue-list { display: flex; flex-direction: column; }
.monitoring-issue { padding: 17px 22px; border-top: 1px solid var(--line-soft); border-left: 3px solid var(--line); }
.monitoring-issue.critical { border-left-color: oklch(.62 .2 25); }.monitoring-issue.important { border-left-color: oklch(.72 .15 72); }.monitoring-issue.attention { border-left-color: var(--primary); }.monitoring-issue.insight { border-left-color: oklch(.58 .11 190); }
.monitoring-issue-top { display: flex; align-items: center; gap: 8px; min-width: 0; }.monitoring-severity, .monitoring-category { border-radius: 999px; padding: 3px 7px; font-size: .68rem; font-weight: 650; white-space: nowrap; }.monitoring-severity.critical { color: oklch(.45 .18 25); background: oklch(.93 .04 25); }.monitoring-severity.important { color: oklch(.48 .11 72); background: oklch(.94 .04 72); }.monitoring-severity.attention { color: var(--primary); background: var(--primary-dim); }.monitoring-severity.insight { color: oklch(.42 .1 190); background: oklch(.93 .025 190); }.monitoring-category { color: var(--muted); background: var(--bg-alt); font-weight: 500; }.monitoring-time { margin-left: auto; color: var(--faint); font: .7rem var(--font-mono); white-space: nowrap; }
.monitoring-issue h3 { margin: 10px 0 4px; font-size: .92rem; font-weight: 620; }.monitoring-issue p { margin: 0; max-width: 82ch; color: var(--muted); font-size: .8125rem; line-height: 1.5; }.monitoring-issue-context { margin-top: 9px; color: var(--faint); font-size: .75rem; }.monitoring-issue-bottom { display: flex; justify-content: flex-end; margin-top: 10px; }.monitoring-issue-actions { display: flex; gap: 7px; flex-wrap: wrap; }.monitoring-status-note { color: var(--faint); font-size: .75rem; }
.rule-config { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }.rule-config-field { min-width: 0; }
.rule-period-custom { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.rule-period-custom[hidden] { display: none; }
.monitoring-rule-preview { padding: 10px 12px; border: 1px solid var(--primary-line); border-radius: var(--radius-control); background: var(--primary-dim); color: var(--text-secondary); font-size: var(--text-xs); line-height: 1.45; }
.rule-after-sync { margin-top: 2px; }

/* Email/Telegram toggle buttons — create/edit rule dialog. Plain buttons
   (not checkboxes): the ask was literally "two buttons with icons", and
   state is read straight off aria-pressed in the submit handler, same as
   any other toggle button in this app. */
.channel-toggle-row { display: flex; gap: 8px; margin: -4px 0 2px; }
.channel-toggle {
  display: flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg); color: var(--faint); font: inherit; font-size: 0.8125rem; cursor: pointer;
  transition: background 140ms var(--ease-out-expo), border-color 140ms var(--ease-out-expo), color 140ms var(--ease-out-expo);
}
.channel-toggle:hover { border-color: var(--muted); color: var(--muted); }
.channel-toggle[aria-pressed="true"] { background: var(--primary-dim); border-color: var(--primary-line); color: var(--primary); }

.rule-row {
  display: flex; align-items: center; gap: 16px; padding: 15px 22px; border-bottom: 1px solid var(--line-soft);
}
.rule-row:last-child { border-bottom: none; }
.rule-main { flex: 1; min-width: 0; }
.rule-title { font-size: 0.875rem; }
.rule-sub { font-size: 0.8125rem; color: var(--faint); margin-top: 3px; }
.rule-schedule { flex: none; color: var(--muted); font-size: 0.8125rem; }
.rule-queue-link { flex: none; font-size: 0.8125rem; color: var(--primary); text-decoration: none; }
.rule-queue-link:hover { text-decoration: underline; }
.rule-edit-btn { flex: none; }

/* Rule card, two rows: switch + name/summary + schedule + edit on top,
   enabled channels as small pills underneath — only rendered when the rule
   has at least one channel on, so a rule with notifications off keeps the
   compact single-row look. */
.rule-card { border-bottom: 1px solid var(--line-soft); }
.rule-card:last-child { border-bottom: none; }
.rule-card .rule-row { border-bottom: none; padding-bottom: 10px; }
.rule-channel-summary { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 0 22px 15px calc(38px + 16px + 22px); }
.rule-channel-badge {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 10px; border-radius: 999px;
  background: var(--primary-dim); color: var(--primary); font-size: 0.75rem; font-weight: 550;
}
.rule-channel-badge svg { flex: none; }
@media (max-width: 760px) {
  .monitoring-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }.monitoring-head { align-items: flex-start; flex-direction: column; }.monitoring-issue { padding: 15px; }.monitoring-issue-top { flex-wrap: wrap; }.monitoring-time { margin-left: 0; }.rule-config, .rule-period-custom { grid-template-columns: 1fr; }
  .rule-row { flex-wrap: wrap; }
  .rule-main { flex-basis: 100%; order: 1; }
  .rule-schedule, .rule-queue-link, .rule-edit-btn { order: 2; }
  .rule-channel-summary { padding-left: 22px; }
}

/* --- Ежемесячные отчеты --- */
.reports-schedule {
  display: flex; align-items: center; gap: 9px; min-height: 44px; margin-bottom: 18px;
  padding: 10px 14px; border: 1px solid var(--primary-line); border-radius: 12px;
  background: var(--primary-dim); color: var(--muted); font-size: 0.8125rem;
}
.reports-schedule::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--primary); box-shadow: 0 0 0 4px oklch(0.52 0.19 258 / 0.14); flex: none; }
.reports-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 14px; }
.report-card {
  display: flex; flex-direction: column; min-height: 206px; padding: 18px; border: 1px solid var(--line-soft);
  border-radius: 16px; color: inherit; text-decoration: none; background: var(--bg); box-shadow: var(--sh-1);
  transition: transform 160ms var(--ease-out-expo), box-shadow 160ms var(--ease-out-expo), border-color 160ms var(--ease-out-expo);
}
.report-card:hover { transform: translateY(-2px); border-color: var(--primary-line); box-shadow: var(--sh-2); }
.report-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.report-card-month { font-family: var(--font-mono); font-size: 0.75rem; color: var(--primary); }
.report-card-arrow { color: var(--faint); font-size: 1.15rem; line-height: 1; }
.report-card-client { margin-top: 10px; font-size: 1rem; font-weight: 630; letter-spacing: -0.015em; }
.report-card-platform { margin-top: 3px; color: var(--faint); font-size: 0.75rem; }
.report-card-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: auto; padding-top: 18px; }
.report-card-stat { min-width: 0; color: var(--faint); font-size: 0.6875rem; line-height: 1.3; }
.report-card-stat b { display: block; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-family: var(--font-mono); font-size: 0.8125rem; font-weight: 550; }
.report-card-stat small { display: block; margin-top: 2px; font-size: 0.6875rem; }
.report-account-option .chat-scope-option-label { flex: 1; }
.report-account-option { cursor: pointer; }
.reports-empty { margin-top: 0; border: 1px dashed var(--line); border-radius: 16px; background: var(--bg); }

/* --- modal (native <dialog>) --- */
/* z-index explicit (not relying only on the browser's native top-layer for
   <dialog>) — defensive, so a modal always renders above the rest of the
   interface regardless of what else on the page claims a high z-index. */
.modal { border: none; border-radius: var(--radius-lg); padding: 0; width: min(420px, calc(100vw - 40px)); box-shadow: 0 30px 60px -20px oklch(0 0 0 / 0.35); z-index: var(--z-modal); }
#select-accounts-dialog { width: min(600px, calc(100vw - 40px)); }
.modal::backdrop { background: oklch(0.19 0 0 / 0.45); }
.modal-body { padding: 24px 24px 20px; display: flex; flex-direction: column; gap: 14px; }
#rule-dialog { width: min(720px, calc(100vw - 32px)); max-height: min(860px, calc(100dvh - 32px)); }
#rule-dialog .modal-body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; max-height: min(860px, calc(100dvh - 32px)); overflow-y: auto; overscroll-behavior: contain; padding: 26px 28px 22px; }
#rule-dialog .modal-title,
#rule-dialog .monitoring-field--accounts,
#rule-dialog #monitoring-account-list,
#rule-dialog .monitoring-modal-note,
#rule-dialog .monitoring-rule-preview,
#rule-dialog .monitoring-modal-actions { grid-column: 1 / -1; }
#rule-dialog .monitoring-field--name,
#rule-dialog .monitoring-field--check,
#rule-dialog .monitoring-field--period,
#rule-dialog .monitoring-field--timezone,
#rule-dialog .monitoring-field--schedule { min-width: 0; }
#rule-dialog #monitoring-rule-config { grid-column: 1 / -1; }
#rule-dialog #monitoring-custom-period { grid-column: 1 / -1; }
#rule-dialog .monitoring-field--notifications { grid-column: 1 / -1; margin-bottom: -8px; }
#rule-dialog #monitoring-channel-toggles,
#rule-dialog .rule-after-sync { grid-column: 1 / -1; }
#rule-dialog .checkbox-list { max-height: 190px; }
.modal-title { font-size: 1.0625rem; font-weight: 620; letter-spacing: -0.01em; }
.modal-sub { font-size: 0.8438rem; color: var(--muted); margin-top: -8px; }
.field-label { display: flex; flex-direction: column; gap: 6px; font-size: 0.8125rem; color: var(--muted); font-weight: 550; }
.field-input {
  font: inherit; font-size: 0.875rem; color: var(--ink); background: var(--bg-alt);
  border: 1px solid transparent; border-radius: var(--radius-sm); padding: 9px 12px; width: 100%;
}
.field-input:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; border-color: transparent; }
.field-checkbox { display: flex; align-items: center; gap: 9px; font-size: 0.8438rem; color: var(--ink); }
.checkbox-list { display: flex; flex-direction: column; gap: 2px; max-height: 320px; overflow-y: auto; border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 6px; }
.checkbox-list .field-checkbox { padding: 6px 6px; border-radius: var(--radius-sm); }
.checkbox-list .field-checkbox:hover { background: var(--bg-alt); }
.field-note { font-size: 0.75rem; color: var(--faint); line-height: 1.5; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }

/* --- toast --- */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: var(--z-toast);
  padding: 12px 18px; border-radius: 12px; font-size: 0.8438rem; font-weight: 550;
  background: var(--ink); color: var(--bg); box-shadow: 0 16px 36px -12px oklch(0 0 0 / 0.35);
  max-width: calc(100vw - 32px);
}
.toast.success::before { content: "✓ "; color: oklch(0.75 0.16 150); }
.toast.error::before { content: "✕ "; color: oklch(0.72 0.17 25); }
@media (prefers-reduced-motion: no-preference) {
  .toast { animation: toast-in 260ms var(--ease-out-expo); }
  @keyframes toast-in { from { opacity: 0; transform: translate(-50%, 10px); } to { opacity: 1; transform: translate(-50%, 0); } }
}

/* --- agent page: chat column + sessions/hypotheses sidebar --- */
.page-head--compact { margin-bottom: 18px; }
.page-head--compact p { font-size: 0.8438rem; max-width: 54ch; }
/* Unlike .period-select (a lightweight scope filter tucked into a card
   head), this sits in the page head as the one config control on the whole
   page — a border that only appears on hover made it invisible at rest
   (same fill as the canvas behind it), so it got read as broken rather than
   minimal. Permanent border + white fill so it reads as a real control. */
.model-select {
  font: inherit; font-size: 0.8125rem; color: var(--ink); background: var(--bg);
  border: 1px solid var(--line); border-radius: 9px; padding: 7px 11px; cursor: pointer; max-width: 220px;
  transition: border-color 160ms var(--ease-out-expo), box-shadow 160ms var(--ease-out-expo);
}
.model-select:hover { border-color: var(--faint); }
.model-select:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-dim); }

/* height: max(floor, viewport-driven) — grows to fill the screen on a tall
   viewport (no page-level scroll, only .chat-log scrolls internally) and
   never collapses below a usable minimum on a short one. No upper cap on
   purpose — a fixed max (980px, removed 2026-08-08) left a dead strip of
   canvas below the card on any viewport taller than ~1280px, which read as
   "chat doesn't fill the screen". 300px measured live (.agent-layout's
   offsetTop + canvas bottom padding, 1440x1080) — topbar + canvas top
   padding + page-head + its margin-bottom + canvas bottom padding, the
   fixed chrome above/below this card on the agent view. */
.agent-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 328px); gap: 18px; align-items: stretch; }
/* .card + .card's 18px stacking margin (for vertically-stacked cards
   elsewhere) leaked into this grid's second column — chat-card and
   side-card both carry .card, so the side card silently sat 18px lower
   than the chat card even though they're side by side, not stacked. The
   grid's own `gap` already spaces them; this only needs to zero the
   vertical offset. */
.agent-layout > .card + .card { margin-top: 0; }
.agent-chat-card { display: flex; flex-direction: column; height: max(560px, calc(100vh - 300px)); }
.agent-chat-card .card-head { flex: none; }
.agent-side-card { display: flex; flex-direction: column; height: max(560px, calc(100vh - 300px)); overflow: hidden; }
@media (max-width: 1180px) {
  .agent-layout { grid-template-columns: 1fr; }
  .agent-chat-card { height: max(420px, min(720px, calc(100dvh - 270px))); min-height: 0; max-height: calc(100dvh - 220px); overflow: hidden; }
  .agent-side-card { height: auto; min-height: 420px; }
}

/* Same iOS-style segmented-control look as .segmented elsewhere (period
   pickers etc) — this used to be a bespoke "folder tab" (flat-bottomed,
   rounded top only), the one place in the app with its own one-off tab
   style instead of the shared pill pattern. */
.agent-side-tabs { display: flex; gap: 2px; width: fit-content; margin: 12px 14px 0; padding: 3px; background: var(--bg-alt); border-radius: 999px; flex: none; }
.agent-side-tab {
  font: inherit; font-size: 0.8125rem; font-weight: 550; color: var(--muted);
  background: none; border: none; border-radius: 999px; height: 30px; padding-inline: 13px; cursor: pointer;
  display: flex; align-items: center; gap: 6px;
  transition: color 180ms var(--ease-out-expo), background 180ms var(--ease-out-expo);
}
.agent-side-tab:hover { color: var(--ink); }
.agent-side-tab.active { color: var(--ink); font-weight: 600; background: var(--bg); box-shadow: 0 1px 3px oklch(0 0 0 / 0.09); }
.agent-side-count {
  font-family: var(--font-mono); font-size: 0.6875rem; background: var(--primary); color: var(--primary-ink);
  border-radius: 999px; min-width: 16px; height: 16px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center;
}
.agent-side-tab:not(.active) .agent-side-count { background: var(--faint); }
.agent-side-panel { flex: 1; overflow-y: auto; padding: 12px 14px 16px; }
.agent-side-panel[hidden] { display: none; }
.agent-side-panel-head { margin-bottom: 10px; }

/* Mobile drawer primitives are hidden on desktop; the side cards remain
   ordinary sticky columns there. The open control is intentionally a compact
   secondary action so it does not compete with the agent/audit primary CTA. */
.mobile-drawer-trigger, .mobile-drawer-backdrop, .mobile-drawer-head, .mobile-drawer-close { display: none; }

/* The chat scope uses a popover because native <option> elements cannot
   display provider logos consistently. Its hidden select remains the
   session/API value source. */
.chat-scope-picker { min-width: 0; max-width: min(360px, 48vw); }
.chat-scope-trigger {
  height: 34px; max-width: 100%; padding: 6px 9px 6px 8px;
  display: flex; align-items: center; gap: 7px;
  color: var(--ink); background: var(--bg); border: 1px solid var(--line);
  border-radius: 9px; box-shadow: 0 1px 2px oklch(0 0 0 / .03);
  font: inherit; font-size: .8125rem; cursor: pointer;
  transition: border-color 150ms var(--ease-out-expo), box-shadow 150ms var(--ease-out-expo);
}
.chat-scope-trigger:hover { border-color: var(--primary-line); }
.chat-scope-trigger:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-dim); }
.chat-scope-trigger-icon, .chat-scope-option-icon {
  width: 20px; height: 20px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 5px; background: var(--bg-alt);
}
.chat-scope-trigger-icon[hidden] { display: none; }
.chat-scope-trigger-icon img, .chat-scope-option-icon img { width: 15px; height: 15px; object-fit: contain; }
.chat-scope-trigger-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-scope-caret { flex: none; margin-left: 1px; color: var(--faint); }
.chat-scope-menu { width: max-content; min-width: 260px; max-width: min(390px, calc(100vw - 24px)); }
.chat-scope-menu-item { display: flex; align-items: center; gap: 9px; width: 100%; }
.chat-scope-option-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-scope-option-icon--all { gap: 2px; background: var(--primary-dim); }
.chat-scope-option-icon--all span { width: 5px; height: 5px; border-radius: 50%; background: var(--primary); }

/* Full-width, tinted like a real primary action instead of a stray
   right-aligned ghost link — this is the one thing you actually go to this
   panel to do, so it gets the same weight a "new chat" button gets
   elsewhere (ChatGPT/Claude sidebars), not an afterthought over the list. */
.agent-new-session-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  height: 36px; border-radius: 10px; font: inherit; font-size: 0.8125rem; font-weight: 560;
  color: var(--primary); background: var(--primary-dim); border: none; cursor: pointer;
  transition: background 160ms var(--ease-out-expo);
}
.agent-new-session-btn:hover { background: var(--primary-line); }
.agent-new-session-btn:active { transform: scale(0.98); }
.agent-new-session-btn svg { flex: none; }

/* Sessions list — the shared .row/.row-title (app.css "generic row") has no
   length limit, meant for short single-line labels (account names etc).
   Session titles are raw user messages and can run long, which used to wrap
   to 3-4 ragged lines per row ("сокращением названий и текста сессий").
   Clamped to 2 lines + ellipsis here, scoped to this list only — other .row
   usages elsewhere are untouched. align-items: flex-start (overriding the
   shared .row's center) keeps the delete button pinned to the title's first
   line instead of drifting to the middle of a two-line block. */
[data-session-list] .row { align-items: flex-start; padding: 12px 14px; gap: 10px; }
[data-session-list] .row-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.4;
}
[data-session-list] .row-delete-btn { margin-top: 1px; }

.agent-pending-row { padding: 14px 4px; border-bottom: 1px solid var(--line-soft); }
.agent-pending-row:last-child { border-bottom: none; }
.agent-pending-title {
  min-width: 0; font-size: 0.8125rem; font-weight: 600; line-height: 1.4;
  overflow-wrap: anywhere;
}
.agent-pending-status { display: flex; min-width: 0; margin-top: 10px; }
.agent-pending-status .pill { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.agent-pending-row > .row-sub { overflow-wrap: anywhere; }
.agent-pending-actions {
  display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(120px, 0.85fr);
  gap: 8px; margin-top: 12px; min-width: 0;
}
.agent-pending-actions:empty { display: none; }
.agent-pending-actions .btn-sm {
  width: 100%; min-width: 0; height: 30px; padding-inline: 12px; font-size: 0.75rem;
  overflow: hidden; text-overflow: ellipsis;
}

/* --- chat with the agent --- */
.agent-chat-card .chat-log, .agent-chat-card .chat-form { padding-left: 18px; padding-right: 18px; }
.chat-log {
  display: flex; flex-direction: column; gap: 10px; padding: 4px 2px;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch; touch-action: pan-y;
}
.chat-form { flex: none; }
/* Empty conversation (just the greeting): a normal top-aligned agent turn,
   same as any other message — dead-centering it in a tall card used to read
   as "the message is floating randomly in the middle of the screen", not as
   an intentional empty state. Toggled by JS (chat-log--empty) whenever the
   log holds nothing but the greeting; removed the moment a real conversation
   starts. Kept as a hook for the little extra top breathing room only. */
.chat-log--empty { padding-top: 8px; }
/* Column, not row: the bubble and its timestamp stack, both pinned to the
   same side (right for the user, left for the agent) via align-items. */
.chat-row { display: flex; flex-direction: column; gap: 3px; }
.chat-row--user { align-items: flex-end; }
.chat-row--agent { align-items: flex-start; }
.chat-bubble {
  max-width: min(78%, 560px); padding: 9px 13px; border-radius: 14px;
  font-size: 0.8125rem; line-height: 1.5; word-break: break-word;
  background: var(--bg-alt); color: var(--ink);
}
/* font-size/color: inherit — .card p (main.css, "card description" text
   elsewhere in the app) matches this element with the exact same
   specificity but sets its own 15px/--muted, and beats .chat-bubble p on
   whichever property THAT rule leaves undeclared. Every rendered reply
   (wrapped in <p> by renderChatMarkdown) was quietly bumped to 15px grey
   text while the bare-text greeting (no <p>) stayed at the bubble's real
   13px/--ink — the "разный шрифт" the greeting looked smaller next to. */
.chat-bubble p { margin: 0 0 6px; font-size: inherit; color: inherit; }
.chat-bubble p:last-child { margin-bottom: 0; }
.chat-bubble ul, .chat-bubble ol { margin: 0 0 6px; padding-left: 18px; }
.chat-bubble ul:last-child, .chat-bubble ol:last-child { margin-bottom: 0; }
.chat-bubble li { margin: 2px 0; }
.chat-bubble code { font-family: var(--font-mono); font-size: 0.9em; background: oklch(0 0 0 / 0.06); padding: 1px 5px; border-radius: 4px; }
/* The model marks a line as a title with "# "/"## " — one bigger size on
   top of the normal body text, not a full h1..h6 ladder (it only ever needs
   to say "this line is the title", see renderChatMarkdown in app.js). */
/* .chat-bubble .chat-heading (not just .chat-heading) so its specificity
   safely beats .card p's font-size/color leak above, regardless of source
   order — a bare .chat-heading class selector alone would tie and lose. */
.chat-bubble .chat-heading { font-size: 0.9375rem; font-weight: 650; letter-spacing: -0.005em; margin: 0 0 6px; color: inherit; }
.chat-bubble .chat-heading:first-child { margin-top: 0; }
.chat-bubble a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.chat-bubble a:hover { text-decoration-color: currentColor; }
/* GFM tables — the model already writes them unprompted for spend/CTR/CPA
   breakdowns; without this they rendered as literal "| a | b |" text rows.
   Scrolls horizontally inside its own wrapper instead of stretching the
   whole bubble wide, so a plain one-line reply next to it stays compact —
   same reasoning as .chat-bubble's own max-width. */
.chat-table-wrap { overflow-x: auto; margin: 2px 0 6px; border-radius: 8px; border: 1px solid var(--line-soft); }
.chat-table-wrap:last-child { margin-bottom: 0; }
.chat-bubble table { border-collapse: collapse; width: 100%; font-size: 0.8125em; white-space: nowrap; }
.chat-bubble th, .chat-bubble td { padding: 6px 10px; text-align: left; border-bottom: 1px solid var(--line-soft); }
.chat-bubble thead th { font-weight: 620; background: oklch(0 0 0 / 0.03); border-bottom: 1px solid var(--line); }
.chat-bubble tbody tr:last-child td { border-bottom: none; }
.chat-row--user .chat-table-wrap { border-color: oklch(1 0 0 / 0.3); }
.chat-row--user .chat-bubble thead th { background: oklch(1 0 0 / 0.25); border-bottom-color: oklch(1 0 0 / 0.35); }
.chat-row--user .chat-bubble th, .chat-row--user .chat-bubble td { border-bottom-color: oklch(1 0 0 / 0.2); }
.chat-time { font-size: 0.6875rem; color: var(--faint); padding: 0 4px; }
/* --primary-ink is white — meant for text on the solid --primary fill, not
   on --primary-dim (a ~10%-opacity tint over the page background). White on
   near-white read as barely-there ("полупрозрачный"); --primary (the same
   dark blue the tint is derived from) is what actually contrasts on it. */
.chat-row--user .chat-bubble { background: var(--primary-dim); color: var(--primary); border-bottom-right-radius: 4px; }
.chat-row--user .chat-bubble code { background: oklch(1 0 0 / 0.4); }
.chat-row--agent .chat-bubble { border-bottom-left-radius: 4px; }
/* Wider than a prose bubble — this holds a diff table + two buttons, not
   text, so the 78%/560px prose cap reads as cramped. .hyp-diff below
   already supplies its own background, so the outer bubble goes flat. */
.chat-bubble.chat-action-card {
  width: min(100%, 680px); max-width: 100%; box-sizing: border-box;
  padding: 16px; border: 1px solid var(--line-soft); border-radius: 16px;
  background: var(--surface-card); box-shadow: var(--sh-1);
}
.chat-action-title {
  display: flex; align-items: flex-start; gap: 12px; min-width: 0;
  font-weight: 600; font-size: 0.9375rem; line-height: 1.4; margin-bottom: 0;
}
.chat-action-title .pill { flex: none; margin-right: 0; }
.chat-action-title-text { min-width: 0; flex: 1; overflow-wrap: anywhere; }
.chat-queue-note { margin-top: 8px; overflow-wrap: anywhere; }
.chat-action-reasoning { font-size: 0.8125rem; color: var(--faint); margin-top: 8px; line-height: 1.5; overflow-wrap: anywhere; }
.chat-action-status { display: flex; min-width: 0; margin: 14px 0 0; }
.chat-action-status .pill { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.chat-bubble.chat-action-card .hyp-diff { margin-top: 14px; }
.chat-bubble.chat-action-card .hyp-actions {
  display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(150px, 0.85fr);
  gap: 10px; margin-top: 14px; min-width: 0;
}
.chat-bubble.chat-action-card .hyp-actions .btn { width: 100%; min-width: 0; }
.chat-bubble.chat-action-card .hyp-actions .hyp-note { grid-column: 1 / -1; }
.chat-sources-card .chat-source-list { margin: 12px 0 0; padding: 0; list-style: none; }
.chat-sources-card .chat-source-list li { display: flex; align-items: baseline; gap: 8px; margin: 6px 0; min-width: 0; }
.chat-sources-card .chat-source-list a { min-width: 0; overflow-wrap: anywhere; }
.chat-source-kind { flex: none; color: var(--faint); font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em; }
@media (max-width: 640px) {
  .chat-bubble.chat-action-card { width: 100%; padding: 14px; }
  .chat-action-title { gap: 8px; font-size: 0.875rem; }
  .chat-action-title--with-kind { flex-direction: column; }
  .chat-bubble.chat-action-card .hyp-actions { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
  .agent-pending-actions { grid-template-columns: 1fr; }
}

/* Typing indicator — a real bubble in the log (Claude/GPT convention),
   not just a busy button, so "the agent is working" reads at a glance
   even if you've scrolled the button out of view. */
.chat-typing { display: flex; align-items: center; gap: 4px; padding: 12px 13px; }
.chat-typing span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--faint);
  animation: chat-typing-bounce 1.1s ease-in-out infinite;
}
.chat-typing span:nth-child(2) { animation-delay: 0.15s; }
.chat-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-typing-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; } 30% { transform: translateY(-3px); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .chat-typing span { animation: none; opacity: 0.8; } }

/* Live "what the agent is doing right now" caption under the typing dots
   (jobs.progress, polled during a multi-round tool-loop) — without this a
   read-tool round trip (read tree, pull 6 months of stats, ...) is just the
   same 3 dots for 5-10+ seconds, indistinguishable from stuck. Empty/no
   progress yet: stays blank, dots alone are enough for a fast reply. */
.chat-typing-status { font-size: 0.75rem; color: var(--muted); margin: 4px 0 0 2px; min-height: 1em; }

/* Busy state for an apply/reject button mid-request (agent-hypotheses
   apply now runs off the jobs queue — a multi-second campaign_clone/plan
   apply with the button just sitting there disabled read as frozen, not
   working). Text swaps to a live progress label (see setButtonBusy in
   app.js); the ring reuses chat-send-spin rather than a second keyframe. */
.btn.is-busy { pointer-events: none; opacity: 0.75; position: relative; padding-right: 30px; }
.btn.is-busy::after {
  content: ''; position: absolute; right: 10px; top: 50%; width: 13px; height: 13px;
  margin-top: -6.5px; border-radius: 50%;
  border: 1.8px solid currentColor; border-right-color: transparent; opacity: 0.6;
  animation: chat-send-spin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .btn.is-busy::after { animation: none; } }

.chat-form { display: flex; gap: 8px; margin-top: 0; padding-top: 12px; padding-bottom: 16px; flex: none; border-top: 1px solid var(--line-soft); }
.chat-input {
  flex: 1; min-width: 0; padding: 9px 13px; border-radius: 10px;
  border: 1px solid var(--line-soft); background: var(--bg); color: var(--text);
  font: inherit; font-size: 0.8125rem;
}
.chat-input:focus { outline: none; border-color: var(--primary); }
.chat-input::placeholder { color: var(--faint); }

/* Fixed width so swapping "Отправить"<->"Остановить" never reshuffles the
   layout ("кнопка не дёргалась") — narrower than the default btn-sm padding
   too. While thinking the button stays enabled with a spinner alongside the
   relabeled text (not disabled+spinner-only, as it used to be): clicking it
   cancels the in-flight turn (see setupChat's submit handler in app.js)
   instead of just sitting there unusable until the turn finishes or times
   out (real complaint 2026-08-26). */
.chat-send-btn { width: 128px; height: 38px; padding-inline: 0; flex: none; }
.chat-send-spinner { display: none; animation: chat-send-spin 0.8s linear infinite; }
.chat-send-btn.is-thinking .chat-send-spinner { display: block; }
@keyframes chat-send-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .chat-send-spinner { animation: none; } }

/* --- account selection modal (MCC/agency picker) --- */
.modal-head { display: flex; flex-direction: column; gap: 3px; margin-bottom: 16px; }
.account-settings-head { flex-direction: row; align-items: center; gap: 12px; }
.account-settings-logo {
  width: 40px; height: 40px; border-radius: 10px; flex: none; object-fit: contain;
  background: var(--bg-alt); padding: 6px;
}
.modal-eyebrow {
  font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 600;
  color: var(--primary); letter-spacing: 0.02em; text-transform: uppercase;
}
.modal-title { margin: 0; font-size: 1.1875rem; font-weight: 650; letter-spacing: -0.02em; color: var(--ink); }
.modal-sub { margin: 0; font-size: var(--text-sm); color: var(--muted); line-height: 1.5; max-width: 420px; }
.account-settings-sync {
  margin-top: 3px; color: var(--muted); font-size: var(--text-xs); line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 280px;
}
.account-settings-sync.is-error { color: var(--danger); }

.account-tabs { margin-bottom: 14px; width: fit-content; }
.account-tab-count {
  font-family: var(--font-mono); font-size: var(--text-xs);
  opacity: 0.75; margin-left: 4px; font-variant-numeric: tabular-nums;
}

.account-list {
  display: flex; flex-direction: column; gap: 2px; max-height: 340px; overflow-y: auto;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm); padding: 6px;
}
.account-row { display: flex; align-items: center; gap: 12px; padding: 7px 8px; border-radius: var(--r-sm); }
.account-row:hover { background: var(--bg-alt); }
.account-main { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.account-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-sm); color: var(--ink); }
.account-status-pill {
  font-family: var(--font-mono); font-size: var(--text-xs); color: var(--faint);
  background: var(--bg-alt); padding: 2px 8px; border-radius: var(--r-pill); flex: none;
}
.account-status-pill--archived { color: var(--muted); }
.account-status-pill--paused { color: var(--warning); background: var(--warning-dim); }

/* Apple-style checkbox: rounded square, blue fill, white check */
.acc-check {
  appearance: none; -webkit-appearance: none; margin: 0; flex: none;
  width: var(--control-size); height: var(--control-size); border-radius: 6.5px;
  border: 1.5px solid var(--line); background: var(--bg); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 150ms var(--ease-out-expo), border-color 150ms var(--ease-out-expo), transform 100ms var(--ease-out-expo);
}
.acc-check:hover { border-color: var(--primary-line); }
.acc-check:active { transform: scale(0.92); }
.acc-check:checked { background: var(--primary); border-color: var(--primary); }
.acc-check:checked::after {
  content: ""; width: 11px; height: 11px; flex: none;
  background: var(--tooltip-fg);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M3 7.5L5.8 10.3L11 4' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 11px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M3 7.5L5.8 10.3L11 4' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 11px no-repeat;
}
.acc-check:focus-visible { outline: 2px solid var(--primary-line); outline-offset: 2px; }

/* Per-account category block — caption on top, input below, sits on the same
   line as the account name. Space is always reserved (visibility, not
   display), so toggling the checkbox never shifts the list. */
.account-niche {
  width: 230px; flex: none;
  visibility: hidden; opacity: 0; transform: translateY(3px);
  transition: opacity 160ms var(--ease-out-expo), transform 160ms var(--ease-out-expo);
}
.account-row.niche-open .account-niche { visibility: visible; opacity: 1; transform: none; }
.niche-caption { display: flex; align-items: center; gap: 4px; margin-bottom: 3px; }
.niche-caption-label { font-size: 0.6875rem; font-weight: 600; color: var(--muted); letter-spacing: 0.01em; }
.account-niche-input {
  width: 100%; font: inherit; font-size: var(--text-sm);
  padding: 5px 9px; border-radius: var(--r-sm); border: 1px solid var(--line-soft);
  background: var(--bg); color: var(--ink);
}
.account-niche-input:focus-visible { outline: none; border-color: var(--primary); }
.account-niche-input::placeholder { color: var(--faint); }
@media (prefers-reduced-motion: reduce) { .account-niche { transition: none; } }

/* Apple-style tooltip — dark popover above the trigger */
.tip {
  position: relative; display: inline-flex; flex: none;
  width: 16px; height: 16px; border-radius: 50%; cursor: help;
  color: var(--faint); background: none; border: none; padding: 0;
  align-items: center; justify-content: center;
}
.tip:hover, .tip:focus-visible { color: var(--primary); outline: none; }


/* --- uniform connect buttons (Интеграции) --- */
.btn-connect {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 34px; padding: 0 16px; border-radius: 999px;
  background: var(--primary); color: var(--primary-ink);
  font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.01em;
  border: none; cursor: pointer; text-decoration: none;
  transition: background 160ms var(--ease-out-expo), transform 100ms var(--ease-out-expo);
}
.btn-connect:hover { background: var(--primary-hover); }
.btn-connect:active { transform: scale(0.97); }
.btn-connect:focus-visible { outline: 2px solid var(--primary-line); outline-offset: 2px; }
.btn-connect--ghost {
  background: var(--bg); color: var(--primary);
  border: 1px solid var(--primary-line);
}
.btn-connect--ghost:hover { background: var(--primary-dim); }

/* --- clients block (Интеграции) --- */
.clients-list { display: flex; flex-direction: column; }
.client-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 18px; border-bottom: 1px solid var(--line-soft);
  transition: background 140ms var(--ease-out-expo);
}
.client-row:last-child { border-bottom: none; }
.client-row:hover { background: var(--bg-alt); }
.client-icon {
  width: 34px; height: 34px; border-radius: 9px; flex: none;
  background: var(--bg-alt); display: flex; align-items: center; justify-content: center;
}
.client-icon img { width: 24px; height: 24px; object-fit: contain; }
.client-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.client-name-wrap { display: flex; align-items: center; gap: 6px; }
.client-disconnect-note { color: var(--muted); font-size: 0.75rem; margin-top: 3px; }
.client-name-text {
  font-size: 0.875rem; font-weight: 600; color: var(--ink); cursor: text;
  border-radius: 5px; padding: 1px 4px; margin: -1px -4px;
  transition: background 140ms var(--ease-out-expo), box-shadow 140ms var(--ease-out-expo);
}
.client-name-text:hover { background: var(--bg-alt); }
.client-name-text[contenteditable="true"] { outline: none; background: var(--bg); box-shadow: 0 0 0 2px var(--primary-dim); cursor: text; }
.client-name-edit-icon { color: var(--faint); flex: none; opacity: 0; transition: opacity 140ms var(--ease-out-expo); }
.client-name-wrap:hover .client-name-edit-icon, .client-name-wrap:focus-within .client-name-edit-icon { opacity: 1; }
.client-platform { font-size: 0.75rem; color: var(--faint); flex: none; }
.client-remove {
  width: 28px; height: 28px; border-radius: 8px; border: none; cursor: pointer; flex: none;
  background: none; color: var(--faint);
  display: flex; align-items: center; justify-content: center;
  transition: color 140ms var(--ease-out-expo), background 140ms var(--ease-out-expo);
}
.client-remove:hover { color: var(--danger); background: var(--danger-dim); }
.client-cancel-disconnect {
  border: 1px solid var(--line); border-radius: 7px; cursor: pointer; flex: none;
  padding: 5px 8px; background: var(--bg-alt); color: var(--ink); font-size: 0.72rem;
  white-space: nowrap; transition: color 140ms var(--ease-out-expo), background 140ms var(--ease-out-expo);
}
.client-cancel-disconnect:hover { color: var(--primary); background: var(--primary-dim); }
.client-settings {
  width: 28px; height: 28px; border-radius: 8px; border: none; cursor: pointer; flex: none;
  background: none; color: var(--faint);
  display: flex; align-items: center; justify-content: center;
  transition: color 140ms var(--ease-out-expo), background 140ms var(--ease-out-expo);
}
.client-settings:hover { color: var(--ink); background: var(--bg-alt); }

/* --- usage bar (Тариф в Настройках) --- */
.usage-bar { position: relative; width: min(260px, 30vw); height: 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-alt); overflow: hidden; flex: none; }
.usage-bar::before, .usage-bar::after { content: ''; position: absolute; z-index: 1; top: 2px; width: 1px; height: 4px; background: color-mix(in oklab, var(--faint) 38%, transparent); }
.usage-bar::before { left: 50%; }
.usage-bar::after { right: 2px; }
.usage-bar-fill { position: relative; z-index: 0; height: 100%; width: 0; background: linear-gradient(90deg, var(--primary), color-mix(in oklab, var(--primary) 72%, white)); border-radius: inherit; transition: width 440ms var(--ease-out-expo); }
.billing-account-usage { display: inline-flex; align-items: center; gap: 9px; min-width: 180px; justify-content: flex-end; }
.account-dots { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px; max-width: 170px; }
.account-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--line); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--faint) 12%, transparent); }
.account-dot.is-used { background: var(--primary); box-shadow: 0 0 0 2px var(--primary-dim); }
.account-dots-label { min-width: 34px; color: var(--muted); font: 0.75rem/1 var(--font-mono); text-align: right; }

/* --- notification delivery settings --- */
.notification-control { display: flex; align-items: center; justify-content: flex-end; gap: 8px; max-width: min(430px, 54vw); }
.notification-input { width: min(250px, 31vw); min-width: 160px; height: 34px; padding: 6px 10px; font-size: 0.8125rem; }
.notification-control--telegram .notification-input { width: min(145px, 20vw); min-width: 110px; }
@media (max-width: 640px) {
  .usage-bar { width: 100%; }
  .billing-account-usage { width: 100%; justify-content: space-between; }
  .account-dots { justify-content: flex-start; }
  .notification-control { width: 100%; max-width: none; justify-content: flex-start; flex-wrap: wrap; }
  .notification-input, .notification-control--telegram .notification-input { flex: 1; width: auto; }
}

/* --- topbar sync icon button --- */
.topbar-sync-btn {
  width: 30px; height: 30px; border-radius: 9px; border: none; cursor: pointer; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; color: var(--muted);
  transition: color 140ms var(--ease-out-expo), background 140ms var(--ease-out-expo);
}
.topbar-sync-text { display: none; }
.topbar-sync-btn:hover { color: var(--primary); background: var(--primary-dim); }
.topbar-sync-btn:focus-visible { outline: 2px solid var(--primary-line); outline-offset: 1px; }
.topbar-sync-btn.is-spinning svg { animation: sync-spin 800ms linear infinite; }
@keyframes sync-spin { to { transform: rotate(360deg); } }

/* --- toolbar dropdowns (Статистика: статус/платформа/период) --- */
.stats-data-notice {
  margin: 0 16px 12px;
  padding: 9px 12px;
  border: 1px solid var(--warning-line, var(--line-soft));
  border-radius: 9px;
  color: var(--muted);
  background: var(--warning-dim);
  font-size: 0.78rem;
  line-height: 1.45;
}
.toolbar-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.toolbar-dropdown {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: 0.8125rem; font-weight: 600; color: var(--ink);
  background: var(--bg-alt); border: 1px solid var(--line-soft); border-radius: 9px;
  padding: 6px 12px; cursor: pointer;
  transition: border-color 150ms var(--ease-out-expo), background 150ms var(--ease-out-expo);
}
.toolbar-dropdown:hover { border-color: var(--primary-line); background: var(--bg); }
.toolbar-dropdown svg:not(.dropdown-caret) { color: var(--primary); }
.dropdown-caret { color: var(--faint) !important; transition: transform 180ms var(--ease-out-expo); }
.toolbar-dropdown[aria-expanded="true"] .dropdown-caret,
.period-trigger[aria-expanded="true"] .dropdown-caret { transform: rotate(180deg); }

/* Период — lives in .page-head-actions on both Обзор and Статистика (one
   shared popover/state, see setupPeriodPicker in app.js), so unlike
   .toolbar-dropdown it sits directly on the gray canvas, not inside a
   card — background:var(--bg-alt) would blend into the page there, needs
   a white surface + real border to read as a control instead of empty
   space. */
.period-trigger {
  display: inline-flex; align-items: center; gap: 7px; height: 36px;
  font: inherit; font-size: 0.8125rem; font-weight: 600; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 9px;
  padding: 0 13px; cursor: pointer;
  box-shadow: 0 1px 2px oklch(0 0 0 / 0.03);
  transition: border-color 150ms var(--ease-out-expo), box-shadow 150ms var(--ease-out-expo);
}
.period-trigger:hover { border-color: var(--primary-line); }
.period-trigger svg:not(.dropdown-caret) { color: var(--primary); }

/* Generic floating single-select menu (setupDropdown() in app.js) — status
   and platform filters. Appended to body at open time, positioned via JS
   off the trigger's rect, so it's never clipped by a card's overflow:hidden
   and always shows above the sticky topbar (same z-index tier as modals). */
.menu-popover {
  position: fixed; z-index: var(--z-modal);
  min-width: 180px; padding: 6px; background: var(--bg);
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  box-shadow: 0 18px 44px -14px oklch(0 0 0 / 0.28), 0 2px 8px oklch(0 0 0 / 0.06);
  display: flex; flex-direction: column; gap: 1px;
}
.menu-popover-item {
  font: inherit; font-size: 0.8125rem; text-align: left; color: var(--muted);
  background: none; border: none; border-radius: 8px; padding: 8px 10px; cursor: pointer;
  transition: background 140ms var(--ease-out-expo), color 140ms var(--ease-out-expo);
}
.menu-popover-item:hover { background: var(--bg-alt); color: var(--ink); }
.menu-popover-item.active { background: var(--primary-dim); color: var(--primary); font-weight: 600; }

/* Workspace switcher uses the same fixed, unclipped menu behaviour as the
   stats filters, while retaining a richer row hierarchy. */
.workspace-menu { min-width: 278px; padding: 7px; }
.workspace-menu-title { padding: 6px 8px 7px; color: var(--faint); font-size: 0.6875rem; font-weight: 650; letter-spacing: .05em; text-transform: uppercase; }
.workspace-menu-item { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; padding: 10px; border: none; border-radius: 9px; background: none; color: var(--ink); text-align: left; font: inherit; cursor: pointer; }
.workspace-menu-item:hover { background: var(--bg-alt); }
.workspace-menu-item.active { background: var(--primary-dim); }
.workspace-menu-item-name { font-size: .8438rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.workspace-menu-item-role { color: var(--faint); font-size: .6875rem; white-space: nowrap; }
.workspace-menu-action { display: flex; align-items: center; gap: 8px; width: 100%; margin-top: 5px; padding: 10px; border: 1px dashed var(--line); border-radius: 9px; background: var(--bg); color: var(--primary); font: inherit; font-size: .8125rem; font-weight: 600; cursor: pointer; }
.workspace-menu-action:hover { border-color: var(--primary-line); background: var(--primary-dim); }
.audit-account-select { font: inherit; font-size: .8125rem; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 9px; padding: 6px 30px 6px 10px; height: 34px; cursor: pointer; box-shadow: 0 1px 2px oklch(0 0 0 / .03); transition: border-color 150ms var(--ease-out-expo), box-shadow 150ms var(--ease-out-expo); }
.audit-account-select:hover { border-color: var(--primary-line); }
.audit-account-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-dim); }

/* --- period popover: compact menu that drops down from the toolbar ---
   position:fixed + JS-computed left/top (see openPeriodPopover in app.js) —
   the node lives in body (moved there by setupPeriodPicker), not inside any
   card, so it's immune to a card's overflow:hidden clipping it. */
.period-popover {
  display: grid; grid-template-columns: 132px 1fr; gap: 18px;
  position: fixed; z-index: var(--z-modal);
  width: 470px; padding: 14px 16px 12px;
  background: var(--bg); border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  box-shadow: 0 18px 44px -14px oklch(0 0 0 / 0.28), 0 2px 8px oklch(0 0 0 / 0.06);
}
.period-popover[hidden] { display: none; }
.period-calendar { width: 286px; min-width: 0; }
.period-presets { display: flex; flex-direction: column; gap: 2px; }
.period-presets button {
  font: inherit; font-size: 0.8125rem; text-align: left; color: var(--muted);
  background: none; border: none; border-radius: 8px; padding: 7px 10px; cursor: pointer;
  transition: background 140ms var(--ease-out-expo), color 140ms var(--ease-out-expo);
}
.period-presets button:hover { background: var(--bg-alt); color: var(--ink); }
.period-presets button.active { background: var(--primary-dim); color: var(--primary); font-weight: 600; }
.period-calendar { min-width: 0; }
.cal-nav { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal-nav button {
  width: 26px; height: 26px; border-radius: 8px; border: none; cursor: pointer;
  background: none; color: var(--faint); display: flex; align-items: center; justify-content: center;
}
.cal-nav button:hover { background: var(--bg-alt); color: var(--ink); }
.cal-title { font-size: 0.8125rem; font-weight: 600; color: var(--ink); text-transform: capitalize; }
.cal-weekdays {
  display: grid; grid-template-columns: repeat(7, 34px); gap: 2px; margin-bottom: 4px;
}
.cal-weekdays span { text-align: center; font-size: 0.625rem; color: var(--faint); font-weight: 600; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 34px); gap: 2px; }
.cal-day {
  width: 34px; height: 34px; border: none; border-radius: 8px; cursor: pointer;
  font: inherit; font-size: 0.75rem; color: var(--ink); background: none;
  display: flex; align-items: center; justify-content: center;
  transition: background 120ms var(--ease-out-expo), color 120ms var(--ease-out-expo);
}
.cal-day:hover:not(.cal-day--future) { background: var(--bg-alt); }
.cal-day--today { box-shadow: inset 0 0 0 1.5px var(--primary-line); font-weight: 600; }
.cal-day--future { color: var(--faint); opacity: 0.5; }
.cal-day--in { background: var(--primary-dim); color: var(--primary); border-radius: 0; }
.cal-day--start, .cal-day--end { background: var(--primary); color: var(--primary-ink); border-radius: 8px; font-weight: 600; }
.cal-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
.cal-today {
  font: inherit; font-size: 0.75rem; font-weight: 600; color: var(--primary);
  background: none; border: none; cursor: pointer; padding: 4px 6px; border-radius: 6px;
}
.cal-today:hover { background: var(--primary-dim); }
.cal-range-label { font-size: 0.75rem; color: var(--faint); }
.period-actions {
  grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding-top: 10px; border-top: 1px solid var(--line-soft); margin-top: 2px;
}
.period-action-btns { display: flex; gap: 8px; flex: none; margin-left: auto; }

/* --- category tag (clients block) ---
   Exact same pattern as .client-name-text/.client-name-edit-icon above:
   plain text, no pill chrome, pencil fades in on hover, cursor:text signals
   it's editable. Was a bordered pill before — read as a button, not text,
   and the edit icon was always-on instead of a hover affordance. */
.client-niche-wrap { display: flex; align-items: center; gap: 6px; }
.niche-tag-text {
  font-size: 0.8125rem; color: var(--ink); cursor: text;
  border-radius: 5px; padding: 1px 4px; margin: -1px -4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px; min-width: 0;
  transition: background 140ms var(--ease-out-expo), box-shadow 140ms var(--ease-out-expo);
}
.niche-tag-text:hover { background: var(--bg-alt); }
.niche-tag-text--empty { color: var(--faint); }
.niche-tag-text[contenteditable="true"] {
  outline: none; background: var(--bg); box-shadow: 0 0 0 2px var(--primary-dim); cursor: text;
  overflow: visible; text-overflow: clip; caret-color: var(--primary); max-width: none;
}
.niche-edit-icon { color: var(--faint); flex: none; opacity: 0; transition: opacity 140ms var(--ease-out-expo); }
.client-niche-wrap:hover .niche-edit-icon, .client-niche-wrap:focus-within .niche-edit-icon { opacity: 1; }

/* --- fixed-position tooltip popup ---
   left/top place it (set instantly in JS, never transitioned); transform is
   only the small enter-offset, so hopping between two far-apart triggers
   fades in place at the new spot instead of sliding across the screen. */
/* popover="manual" puts it in the top layer: a modal <dialog> (showModal) sits
   there too, and no z-index can lift a tooltip above it. display:block keeps
   the opacity fade working while the popover is not "open". */
.tip-popup {
  position: fixed; inset: auto; left: 0; top: 0; margin: 0; border: 0; overflow: visible; display: block;
  z-index: var(--z-tooltip);
  background: var(--tooltip-bg); color: var(--tooltip-fg);
  font-size: var(--text-xs); line-height: 1.45; font-weight: 450;
  padding: 8px 11px; border-radius: var(--r-sm); width: min(230px, calc(100vw - 24px));
  opacity: 0; pointer-events: none;
  transform: translateY(4px);
  transition: opacity 150ms var(--ease-out-expo), transform 150ms var(--ease-out-expo);
}
.tip-popup.visible { opacity: 1; transform: none; }
.tip-popup--right { transform: translateX(-6px); }
.tip-popup--right.visible { transform: none; }
@media (prefers-reduced-motion: reduce) { .tip-popup { transition: none; } }
@media (max-width: 640px) {
  .workspace-currency-select, .workspace-vat-select { width: 100%; max-width: none; }
  .view[data-view="settings"] .setting-row .v,
  .view[data-view="settings"] .setting-row > .field-input,
  .view[data-view="settings"] .setting-row > .btn { width: 100%; max-width: none; }
  .onboarding-card { width: calc(100vw - 24px); padding: 16px; }
}

/* Structured .tip-popup content (data-tip-rich, e.g. campaignDetailsTipHtml)
   — same label-left/value-right language as .trend-tooltip-row, so the
   chart hover tooltip and these popovers read as one system. */
.tip-row { display: flex; align-items: baseline; gap: 12px; }
.tip-row + .tip-row { margin-top: 4px; }
.tip-row-label { color: oklch(1 0 0 / 0.6); flex: none; }
/* flex:1 + min-width:0 (not justify-content:space-between) so a long value
   (e.g. "Реклама в Telegram-каналах") wraps inside the popup's fixed width
   instead of forcing it wider — same fix as .tree-cell's sibling rule. */
.tip-row-value { flex: 1; min-width: 0; color: var(--tooltip-fg); font-weight: 600; text-align: right; }
.tip-note {
  margin-top: 8px; padding-top: 8px; border-top: 1px solid oklch(1 0 0 / 0.14);
  color: oklch(1 0 0 / 0.75);
}

/* --- responsive QA fixes -------------------------------------------------
   These rules are intentionally kept together so the narrow-screen contract
   is easy to audit: every fixed-width overlay must fit the viewport, every
   scrollable data surface needs an affordance, and modal actions must remain
   reachable after the form itself scrolls. */

@media (max-width: 900px) {
  .mobile-nav {
    scroll-snap-type: x proximity;
    padding-inline: max(16px, 4vw);
    box-shadow: inset -18px 0 14px -18px oklch(0 0 0 / 0.45);
  }
  .mobile-nav button { scroll-snap-align: center; }
}

@media (max-width: 480px) {
  .topbar { gap: 8px; padding-inline: 12px; }
  .topbar-left { gap: 6px; }
  .topbar-right { gap: 6px; }
  .workspace-switcher { max-width: min(154px, 42vw); padding-inline: 4px; }
  .workspace-switcher { max-width: min(118px, 34vw); }
  .workspace-name { display: block; max-width: 88px; font-size: 0.75rem; }
  .topbar-sync-btn { width: auto; max-width: 78px; padding-inline: 5px; gap: 4px; font-size: .6875rem; }
  .topbar-sync-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .plan-tag { max-width: 96px; overflow: hidden; padding-inline: 8px; font-size: 0.75rem; }
  .plan-tag span { overflow: hidden; text-overflow: ellipsis; }
  .plan-tag .plan-sep { flex: none; }
  .plan-tag #plan-name, .plan-tag .plan-sep { display: none; }

  .chat-input { padding-inline: 10px; font-size: 0.75rem; }
  .chat-send-btn { width: 112px; font-size: 0.75rem; }

  #history-category {
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  #history-category::-webkit-scrollbar { display: none; }
  #history-category button { flex: none; }
}

/* Final topbar contract: the workspace consumes the free middle space, while
   refresh and freshness stay fixed at the right edge of the left cluster.
   When the viewport tightens only the name ellipsizes; controls never float
   away or get pushed below the bar. */
.topbar-left .workspace-switcher { flex: 1 1 auto; max-width: none; }
.topbar-left .workspace-name { flex: 1 1 auto; max-width: none; }
.topbar-left .topbar-sync-btn, .topbar-left .workspace-badge { flex: 0 0 auto; }
@media (max-width: 480px) {
  .topbar-left .workspace-switcher { max-width: none; }
  .topbar-left .workspace-name { max-width: 100%; }
}

/* Narrow screens: keep the app's information density, but remove the large
   desktop gutters that made overview/statistics/history cards and their data
   surfaces feel squeezed inside the remaining width. Tables still preserve
   their honest minimum width and scroll horizontally where needed. */
@media (max-width: 640px) {
  .canvas { padding: 18px 10px 42px; }
  .page-head { gap: 12px; margin-bottom: 18px; }
  .page-head p { font-size: .8125rem; line-height: 1.45; margin-top: 4px; }
  .page-head-actions { width: 100%; }
  .page-head-actions .period-trigger { max-width: 100%; }

  .card + .card { margin-top: 12px; }
  .card-head { padding: 13px 14px; }
  .card-body { padding: 14px; }
  .card-empty { padding: 24px 14px; }
  .stat-grid { gap: 8px; margin-bottom: 12px; }
  .stat, .overview-stat-grid .stat { padding: 12px 13px; }
  .overview-stat-grid .stat .value { font-size: 1.1rem; }
  .overview-two-col { gap: 12px; margin-top: 12px; }

  .toolbar { gap: 8px; padding: 10px 14px; }
  .toolbar-controls { width: 100%; gap: 6px; }
  .toolbar-dropdown { min-width: 0; max-width: 100%; padding-inline: 9px; }
  .segmented { max-width: 100%; }
  .chart-legend { gap: 6px; padding: 12px 14px 14px; }
  .table-scroll table.data th,
  .table-scroll table.data td,
  .overview-niche-table table.data th,
  .overview-niche-table table.data td { padding-inline: 12px; }
  table.data th { padding-top: 10px; padding-bottom: 10px; }
  table.data td { padding-top: 11px; padding-bottom: 11px; }

  .row { gap: 10px; padding: 12px 14px; }
  .log-row { gap: 10px; padding: 11px 14px; }
  .log-day { padding-inline: 14px; }
  .log-detail-panel { padding: 4px 14px 14px; }
  .setting-row { gap: 6px; padding: 13px 14px; }
  .workspace-members { padding-inline: 14px; }
  .integration-group-label { padding-inline: 14px; }
  .integration-row { align-items: flex-start; text-align: left; }
  .integration-row .k { width: 100%; align-items: center; }
  .client-row { padding: 10px 14px; }
  .monitoring-issue { padding: 13px 14px; }
  .audit-methodology { padding-inline: 14px; }
  .audit-block-header { padding-inline: 14px; }
  .audit-item { padding-inline: 14px; }
  .audit-narrative { margin-inline: 14px; }
  .audit-conclusion { padding-inline: 14px; }
}

/* On phones the workspace is useful context, so give it a dedicated first
   line and keep the freshness badge on a second line instead of ellipsizing
   either value. The sync control stays an icon-only action beside the badge. */
@media (max-width: 640px) {
  .topbar { height: auto; min-height: 86px; padding-top: 8px; padding-bottom: 8px; align-items: flex-start; }
  .topbar-left { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; gap: 3px 8px; flex: 1; overflow: visible; }
  .workspace-switcher { grid-column: 1 / -1; width: 100%; max-width: none; margin-left: 0; padding: 3px 0; justify-content: flex-start; text-align: left; }
  .workspace-name { display: block; max-width: none; overflow: visible; text-overflow: clip; white-space: normal; overflow-wrap: anywhere; line-height: 1.2; text-align: left; }
  .workspace-badge { display: inline-flex; grid-column: 1; max-width: none; overflow: visible; }
  .topbar-sync-btn { grid-column: 2; grid-row: 2; width: 30px; max-width: none; padding: 0; }
  .topbar-sync-text { display: none; }
  .topbar-right { padding-top: 2px; }
  .plan-tag { max-width: none; }
  .plan-tag span { max-width: none; overflow: visible; text-overflow: clip; }
  .mobile-nav { top: 86px; }
  .workspace-menu { min-width: min(340px, calc(100vw - 24px)); max-width: calc(100vw - 24px); }
  .workspace-menu-item-name { overflow: visible; text-overflow: clip; white-space: normal; overflow-wrap: anywhere; }
}

@media (max-width: 1180px) {
  /* At tablet widths a two-column audit/agent layout is still too narrow once
     the app shell and the side card are accounted for. Keep the working card
     readable and make the contextual column an explicit overlay instead. */
  .mobile-drawer-trigger {
    display: inline-flex; align-items: center; gap: 8px; width: fit-content; min-height: 36px;
    margin: -8px 0 14px; padding: 0 12px; border: 1px solid var(--primary-line);
    border-radius: 10px; background: var(--primary-dim); color: var(--primary);
    font: inherit; font-size: .8125rem; font-weight: 620; cursor: pointer;
  }
  .mobile-drawer-trigger:hover { background: var(--primary-line); }
  .mobile-drawer-trigger-meta { color: var(--muted); font-size: .6875rem; font-weight: 500; }
  .mobile-drawer-backdrop:not([hidden]) { display: block; position: fixed; inset: 0; z-index: calc(var(--z-modal) - 1); background: oklch(0.16 0 0 / .38); backdrop-filter: blur(2px); }
  .mobile-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px 10px; color: var(--ink); font-size: .875rem; font-weight: 650; border-bottom: 1px solid var(--line-soft); }
  .mobile-drawer-close { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 30px; height: 30px; border: 1px solid var(--line); border-radius: 9px; background: var(--bg); color: var(--muted); font: 1.25rem/1 sans-serif; cursor: pointer; }
  .mobile-drawer-close:hover { border-color: var(--primary-line); color: var(--primary); background: var(--primary-dim); }
  .agent-side-card, .audit-side-card { display: none; }
  .agent-side-card.is-mobile-drawer-open, .audit-side-card.is-mobile-drawer-open {
    display: flex; position: fixed; z-index: var(--z-modal); top: 122px; right: max(12px, env(safe-area-inset-right)); bottom: max(12px, env(safe-area-inset-bottom));
    width: min(420px, calc(100vw - 24px)); max-height: none; min-height: 0; height: auto; border-radius: 18px;
    box-shadow: 0 24px 70px -24px oklch(0 0 0 / .48); animation: mobile-drawer-in 220ms var(--ease-out-expo) both;
  }
  .agent-side-card.is-mobile-drawer-open .agent-side-panel,
  .audit-side-card.is-mobile-drawer-open .audit-side-panel { min-height: 0; overflow-y: auto; }
  .agent-side-card.is-mobile-drawer-open .agent-side-tabs,
  .audit-side-card.is-mobile-drawer-open .audit-side-tabs { margin-top: 10px; }
  @keyframes mobile-drawer-in { from { opacity: 0; transform: translateX(18px) scale(.985); } to { opacity: 1; transform: translateX(0) scale(1); } }
}

@media (max-width: 520px) {
  #rule-dialog { width: calc(100vw - 20px); max-height: calc(100dvh - 20px); border-radius: 16px; }
  #rule-dialog .modal-body { display: flex; max-height: calc(100dvh - 20px); overflow-y: auto; padding: 20px 16px 16px; gap: 12px; }
  #rule-dialog .monitoring-field--name,
  #rule-dialog .monitoring-field--check,
  #rule-dialog .monitoring-field--period,
  #rule-dialog .monitoring-field--timezone,
  #rule-dialog .monitoring-field--schedule { width: 100%; }
  #rule-dialog .checkbox-list { max-height: 180px; }
  .pagination { align-items: flex-start; flex-direction: column; padding-inline: 16px; }
  .pagination-actions { width: 100%; justify-content: space-between; }
  .pagination-btn { flex: 1; }
  .mobile-drawer-trigger { width: 100%; justify-content: flex-start; margin-top: -4px; }
  .mobile-drawer-trigger-meta { margin-left: auto; }
  .agent-side-card.is-mobile-drawer-open, .audit-side-card.is-mobile-drawer-open { top: 112px; left: 10px; right: 10px; width: auto; }
}

body.mobile-drawer-lock { overflow: hidden; }

/* Data tables keep their truthful wide shape, but make the interaction
   discoverable on phones and tablets. */
.table-scroll {
  position: relative;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.table-scroll.has-overflow::after {
  content: "";
  position: absolute;
  z-index: 4;
  inset: 0 0 0 auto;
  width: 28px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--bg));
  opacity: 1;
  transition: opacity 160ms ease;
}
.table-scroll.has-overflow.is-scrolled::after { opacity: 0; }
.table-scroll.has-overflow table.data th:first-child,
.table-scroll.has-overflow table.data td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg);
  box-shadow: 8px 0 12px -12px oklch(0 0 0 / 0.55);
}
.table-scroll.has-overflow table.data th:first-child { z-index: 3; }
.table-scroll.has-overflow table.data tbody tr:hover td:first-child { background: var(--bg-alt); }

/* The overview table is intentionally compact and therefore crosses the
   card boundary earlier than the campaign table. Preserve the CPA column by
   making the first column the stable reading anchor. */
.overview-niche-table.table-scroll.has-overflow table.data th:first-child,
.overview-niche-table.table-scroll.has-overflow table.data td:first-child { min-width: 150px; }

/* Client/account rows use a second line for platform and actions on narrow
   screens instead of squeezing the editable name and category into ellipses. */
.client-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: none;
}
@media (max-width: 640px) {
  .client-row {
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr);
    grid-template-areas: "icon main" ". actions";
    align-items: center;
    column-gap: 10px;
    row-gap: 6px;
  }
  .client-icon { grid-area: icon; }
  .client-main { grid-area: main; width: 100%; }
  .client-actions { grid-area: actions; width: 100%; justify-content: flex-end; }
  .client-platform { margin-right: auto; max-width: 14ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .niche-tag-text { max-width: none; }
}

/* Three-button monitoring forms and two-button settings forms both become a
   single, reachable action stack on a phone. This prevents the first button
   from being laid out at a negative x-coordinate in a narrow dialog. */
@media (max-width: 520px) {
  .modal-actions {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
    width: 100%;
  }
  .modal-actions .btn { width: 100%; min-width: 0; }
}

/* Period picker: the desktop two-column calendar becomes a compact stacked
   popover. The calendar cells also become fluid so the full week remains
   visible at 375px. */
@media (max-width: 540px) {
  .period-popover {
    width: calc(100vw - 24px);
    max-height: calc(100vh - 24px);
    overflow-y: auto;
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
    padding: 12px;
  }
  .period-presets {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px;
  }
  .period-presets button { min-width: 0; padding-inline: 8px; }
  .period-calendar { width: 100%; }
  .cal-weekdays, .cal-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .cal-day { width: 100%; min-width: 0; }
  .period-actions { grid-column: auto; }
  .period-action-btns { width: 100%; }
  .period-action-btns .btn { flex: 1; }
}

/* The audit is a long document on mobile. Keep the full evidence readable,
   but provide a compact in-page outline for jumping between its blocks. */
.audit-outline {
  position: sticky;
  top: 72px;
  z-index: 2;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 10px 22px;
  background: var(--bg);
  border-bottom: 1px solid var(--line-soft);
  scrollbar-width: none;
}
.audit-outline::-webkit-scrollbar { display: none; }
.audit-outline a {
  flex: none;
  padding: 5px 9px;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  color: var(--muted);
  font-size: 0.75rem;
  text-decoration: none;
  white-space: nowrap;
}
.audit-outline a:hover, .audit-outline a:focus-visible { color: var(--primary); border-color: var(--primary-line); background: var(--primary-dim); }

/* --- compact single-line topbar -----------------------------------------
   Keep the shell on one row at every viewport width. The workspace is the
   only flexible item and truncates with an ellipsis; refresh and freshness
   stay immediately after it, while the token tag remains pinned on the
   right. */
.topbar { height: 56px; min-height: 56px; align-items: center; gap: 8px; padding-inline: clamp(10px, 3vw, 40px); }
.topbar-left { display: flex; align-items: center; flex: 1 1 auto; min-width: 0; gap: 5px; overflow: hidden; }
.workspace-switcher { display: inline-flex; flex: 1 1 clamp(96px, 22vw, 220px); width: auto; min-width: 0; max-width: 220px; margin-left: 0; padding-inline: 3px; }
.workspace-name { display: block; min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar-sync-btn { flex: 0 0 30px; width: 30px; max-width: 30px; padding: 0; }
.workspace-badge { display: inline-flex; align-items: center; flex: 0 0 auto; min-width: max-content; max-width: none; overflow: visible; text-overflow: clip; white-space: nowrap; padding: 3px 4px; background: none; }
.topbar-right { display: flex; align-items: center; flex: 0 0 auto; min-width: 0; gap: 0; }
.plan-tag { max-width: none; min-width: max-content; overflow: visible; padding-inline: 9px; gap: 5px; }
.plan-tag #plan-days { min-width: max-content; overflow: visible; text-overflow: clip; white-space: nowrap; }

@media (max-width: 640px) {
  .topbar { padding-inline: 8px; gap: 5px; }
  .topbar-left { gap: 3px; }
  .workspace-switcher { flex-basis: clamp(72px, 30vw, 160px); width: auto; max-width: 160px; padding-inline: 1px; }
  .workspace-name { font-size: .75rem; }
  .workspace-badge { padding-inline: 1px; font-size: .625rem; background: none; }
  .plan-tag { padding-inline: 7px; font-size: .6875rem; gap: 4px; }
  .plan-tag #plan-name, .plan-tag .plan-sep { display: none; }
}

@media (max-width: 900px) {
  .mobile-nav { top: 56px; }
}

/* Final topbar contract: the workspace consumes free middle space, while
   refresh and freshness remain fixed controls beside it. Only the name
   ellipsizes on narrow screens. */
.topbar { height: 56px; min-height: 56px; align-items: center; }
.topbar-left { display: flex; align-items: center; flex: 1 1 auto; min-width: 0; gap: 8px; overflow: hidden; }
.topbar-left .workspace-switcher { display: inline-flex; flex: 1 1 auto; max-width: none; min-width: 0; width: auto; margin-left: 0; }
.topbar-left .workspace-name { display: block; flex: 1 1 auto; max-width: none; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar-left .topbar-sync-btn, .topbar-left .workspace-badge { flex: 0 0 auto; }
.topbar-right { flex: 0 0 auto; }
@media (max-width: 640px) {
  .topbar { height: 56px; min-height: 56px; padding-inline: 10px; gap: 6px; }
  .topbar-left { display: flex; gap: 5px; overflow: hidden; }
  .topbar-left .workspace-switcher { flex: 1 1 auto; max-width: none; width: auto; padding-inline: 2px; }
  .topbar-left .workspace-name { max-width: none; font-size: .75rem; white-space: nowrap; overflow-wrap: normal; }
  .topbar-left .workspace-badge { display: inline-flex; max-width: 86px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-inline: 2px; font-size: .625rem; }
  .topbar-sync-btn { width: 30px; max-width: 30px; padding: 0; }
  .topbar-right { display: none; padding-top: 0; }
  .plan-tag { max-width: 34px; min-width: 30px; padding-inline: 7px; }
  .plan-tag #plan-name, .plan-tag #plan-days, .plan-tag .plan-sep { display: none; }
  .mobile-nav { top: 56px; }
}

/* Final content-sized workspace contract. Keep the workspace left-aligned and
   let only its label give up width when the fixed controls need the space. */
.topbar-left .workspace-switcher {
  flex: 0 1 auto;
  width: max-content;
  max-width: min(420px, calc(100vw - 180px));
}
.topbar-left .workspace-name {
  flex: 0 1 auto;
  width: max-content;
  max-width: calc(100vw - 220px);
}
.mobile-app-brand { display: none; }
@media (max-width: 640px) {
  .mobile-app-brand { display: inline-flex; align-items: center; flex: 0 0 auto; }
  .mobile-app-brand img { display: block; width: auto; height: 18px; }
  .topbar-left .workspace-switcher {
    max-width: min(190px, calc(100vw - 210px));
  }
  .topbar-left .workspace-name {
    max-width: min(160px, calc(100vw - 240px));
  }
}
