/* Saxap Aura — интерфейс портала */
:root{
  color-scheme:light;
  --bg:#f5f6fb; --surface:#ffffff; --ink:#191b2e; --muted:#5b6080;
  --border:#e8eaf3; --border-strong:#d8dbec;
  --accent:#7c5cff; --accent-2:#ff5c9d; --accent-ink:#5b3fd6;
  --ok:#16a36a; --warn:#c77700; --danger:#e5484d;
  /* ориентир в матрице «Смены»: заливка строки/колонки под курсором и сама подпись */
  --mtx-hl:rgba(124,92,255,.07); --mtx-hl-strong:rgba(124,92,255,.16);
  --grad:linear-gradient(135deg,#7c5cff 0%,#ff5c9d 100%);
  --shadow:0 1px 2px rgba(25,27,46,.04),0 8px 24px rgba(25,27,46,.06);
  --shadow-hover:0 4px 10px rgba(25,27,46,.07),0 16px 40px rgba(124,92,255,.12);
  --radius:14px;
}
/* тёмная тема: атрибут ставит анти-flash скрипт в base.html (localStorage aura_theme,
   дефолт — системная prefers-color-scheme). Градиент бренда остаётся тем же. */
[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0f1020; --surface:#1a1c30; --ink:#e9eaf6; --muted:#979dc4;
  --border:#272a44; --border-strong:#363a5c;
  --accent:#8f73ff; --accent-2:#ff6ea8; --accent-ink:#b5a4ff;
  --ok:#2ec98a; --warn:#ffb224; --danger:#ff6b6f;
  --mtx-hl:rgba(143,115,255,.13); --mtx-hl-strong:rgba(143,115,255,.26);
  --shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.35);
  --shadow-hover:0 4px 10px rgba(0,0,0,.35),0 16px 40px rgba(124,92,255,.22);
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  background:var(--bg); color:var(--ink);
  -webkit-font-smoothing:antialiased; font-size:14px; line-height:1.45;
}
a{color:inherit; text-decoration:none}
b{font-weight:700}

/* ===== Бренд AURA + раздел ===== */
.brand{display:flex; align-items:center; gap:9px}
.brand-mark{width:22px; height:22px; border-radius:50%; background:var(--grad);
  box-shadow:0 2px 8px rgba(124,92,255,.45); flex:0 0 auto}
.brand-mark.big{width:46px;height:46px;margin-bottom:8px}
.brand-name{font-size:16px; font-weight:600; letter-spacing:.2px; display:inline-flex; align-items:center; gap:9px}
.brand-name b{background:var(--grad); -webkit-background-clip:text; background-clip:text; color:transparent;
  font-weight:800; letter-spacing:1.4px}
/* название раздела продукта (Finance / CRM / …): разделитель + приглушённая подпись.
   Фундамент под мультиразделы — берётся из nav_section (context_processors). */
.brand-section{font-size:12.5px; font-weight:600; letter-spacing:.2px; color:var(--muted);
  padding-left:9px; border-left:1px solid var(--border-strong)}

/* ===== Лаунчер разделов (waffle-грид) ===== */
.applauncher{margin-right:6px}
.launch-btn{padding:0 10px 0 9px; height:36px; gap:8px; border:1px solid var(--border-strong);
  border-radius:10px; background:var(--surface); color:var(--ink)}
.launch-btn:hover{border-color:var(--accent)}
.applauncher[open] .launch-btn{border-color:var(--accent)}
.waffle{color:var(--accent); flex:none; display:block}
.launch-cur{font-weight:700; font-size:13px; letter-spacing:.2px}
.launch-panel{width:428px; max-width:calc(100vw - 24px); padding:12px}
/* minmax(0,1fr) — колонки РАВНОЙ ширины (иначе 1fr=minmax(auto,1fr) тянется по контенту) */
.launch-grid{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px}
.launch-card{display:flex; flex-direction:column; align-items:flex-start; gap:7px; padding:12px 12px 13px;
  border:1px solid var(--border); border-radius:13px; background:var(--surface); transition:border-color .14s, box-shadow .14s, transform .14s}
.launch-tg{min-height:2.5em}   /* резерв под 2 строки — карточки одинаковой высоты и без «рванины» */
.launch-card:hover{border-color:var(--accent); box-shadow:var(--shadow); transform:translateY(-1px)}
.launch-card.is-active{border-color:var(--accent); background:rgba(124,92,255,.06)}
.launch-nm{font-weight:700; font-size:13.5px; display:flex; align-items:center; gap:7px}
.launch-tg{font-size:11.5px; color:var(--muted); line-height:1.3}
/* иконка-плитка раздела (свой градиент на каждый раздел, белый глиф) */
.sec-ic{width:36px; height:36px; border-radius:11px; display:inline-flex; align-items:center; justify-content:center;
  color:#fff; flex:none; box-shadow:0 3px 10px rgba(25,27,46,.14)}
.sec-ic--finance{background:linear-gradient(135deg,#7c5cff,#ff5c9d)}
.sec-ic--crm{background:linear-gradient(135deg,#3aa0ff,#43c6ac)}
.sec-ic--academy{background:linear-gradient(135deg,#ff9f43,#ff5c9d)}
.sec-ic--keyhunter{background:linear-gradient(135deg,#4f7cff,#8f73ff)}
/* ⚠️ Градиент обязан быть у КАЖДОГО раздела из AURA_SECTIONS. Глиф белый (color:#fff
   выше), фона у .sec-ic нет — раздел без своей строки здесь получает белую иконку на
   белой карточке, то есть пустую плитку в переключателе. Так и жили Voice (глиф был,
   градиента нет) и Landings (не было ни того, ни другого). */
.sec-ic--voice{background:linear-gradient(135deg,#e0459c,#4f7cff)}
.sec-ic--landings{background:linear-gradient(135deg,#0fb87f,#8bd94a)}
.sec-ic--board{background:linear-gradient(135deg,#00c2a8,#2f6bff)}
.section-soon{font-size:9px; font-weight:800; text-transform:uppercase; letter-spacing:.5px; color:var(--accent-ink);
  background:rgba(124,92,255,.14); padding:2px 6px; border-radius:999px}
[data-theme="dark"] .section-soon{background:rgba(143,115,255,.2)}

/* ===== Заглушка раздела «в разработке» ===== */
.soon-wrap{min-height:calc(100vh - var(--topbar-h) - 48px); display:flex; align-items:center; justify-content:center; padding:24px}
.soon-card{max-width:520px; text-align:center; display:flex; flex-direction:column; align-items:center;
  padding:44px 40px; border:1px solid var(--border); border-radius:20px; background:var(--surface); box-shadow:var(--shadow)}
.sec-ic-lg{width:64px; height:64px; border-radius:18px; margin-bottom:20px}
.sec-ic-lg svg{width:32px; height:32px}
.soon-badge{font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.6px; color:var(--accent-ink);
  background:rgba(124,92,255,.12); padding:5px 12px; border-radius:999px; margin-bottom:16px}
.soon-title{font-size:34px; font-weight:800; letter-spacing:-.6px; margin:0 0 8px}
.soon-title .grad{background:var(--grad); -webkit-background-clip:text; background-clip:text; color:transparent}
.soon-tagline{font-size:15px; font-weight:600; color:var(--ink); margin:0 0 12px}
.soon-text{font-size:14px; color:var(--muted); line-height:1.55; margin:0 0 26px; max-width:400px}
.soon-btn{text-decoration:none}

/* ===== Логотип клиента (Saxap): инлайн-SVG с фирменным градиентом (одинаков в обеих темах) ===== */
.saxap-logo{display:block; width:108px; height:auto}
/* блок клиента в сайдбаре — над городом */
.side-brand{padding:2px 6px 14px; margin-bottom:8px; border-bottom:1px solid var(--border)}

/* ===== Каркас: топбар (главный) на всю ширину + тихий сайдбар ===== */
:root{--sidebar-w:240px; --topbar-h:60px}
html[data-sidebar="off"]{--sidebar-w:0px}
body.app{display:grid; min-height:100vh;
  grid-template-columns:var(--sidebar-w) minmax(0,1fr);
  grid-template-rows:var(--topbar-h) minmax(0,1fr);
  grid-template-areas:"topbar topbar" "sidebar main"}
.topbar{grid-area:topbar; position:sticky; top:0; z-index:70; display:flex; align-items:center; gap:14px;
  padding:0 20px 0 14px; background:var(--surface);
  border-bottom:1px solid var(--border); box-shadow:0 1px 2px rgba(25,27,46,.03)}
.topbar .brand{margin-right:10px}
.nav-toggle{display:inline-flex; flex-direction:column; justify-content:center; gap:4px;
  width:36px; height:36px; padding:8px; border:0; border-radius:9px; background:none; cursor:pointer}
.nav-toggle:hover{background:var(--bg)}
.nav-toggle-bar{display:block; width:18px; height:2px; border-radius:2px; background:var(--muted)}
.fresh-chip{display:inline-flex; align-items:center; gap:7px; font-size:12px; font-weight:600;
  color:var(--muted); padding:6px 11px; border:1px solid var(--border); border-radius:999px;
  background:var(--bg); white-space:nowrap}
.fresh-dot{width:7px; height:7px; border-radius:50%; background:var(--ok); flex:none}
.theme-btn{width:36px; height:36px; display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--border-strong); border-radius:10px; background:var(--surface);
  color:var(--muted); cursor:pointer; flex:none}
.theme-btn:hover{border-color:var(--accent); color:var(--accent-ink)}
/* кнопка состояния системы (топбар). Три состояния, по возрастанию срочности:
   зелёная окантовка — всё в порядке; янтарная — что-то отстало (данные не обновляются),
   мигает красным — связи с сервером нет. Янтарное НЕ мигает намеренно: это «посмотри,
   когда дойдут руки», а не авария. Правила .offline идут ПОСЛЕ .warn — при равной
   специфичности побеждает последнее, и красный перекрывает янтарный. */
.status-btn{width:36px; height:36px; min-height:36px; padding:0; display:inline-flex; align-items:center;
  justify-content:center; border:1.5px solid var(--ok); border-radius:10px; background:var(--surface);
  cursor:pointer; flex:none; list-style:none}
.status-btn::-webkit-details-marker{display:none}
.status-dot{width:9px; height:9px; border-radius:50%; background:var(--ok); box-shadow:0 0 0 3px rgba(22,163,106,.18)}
.status-btn.warn{border-color:var(--warn)}
.status-btn.warn .status-dot{background:var(--warn); box-shadow:0 0 0 3px rgba(199,119,0,.20)}
.status-btn.offline{border-color:var(--danger); animation:statusblink 1.1s ease-in-out infinite}
.status-btn.offline .status-dot{background:var(--danger); box-shadow:0 0 0 3px rgba(229,72,77,.22)}
@keyframes statusblink{0%,100%{border-color:var(--danger)}50%{border-color:rgba(229,72,77,.25)}}
.status-menu{min-width:236px; padding:12px 14px}
.status-line{font-weight:700; font-size:13px; margin:0 0 8px; color:var(--ok); display:flex; align-items:center; gap:7px}
.status-line::before{content:'●'; font-size:11px}
.status-line.warn{color:var(--warn)}
.status-line.off{color:var(--danger)}
.status-row{display:flex; justify-content:space-between; gap:16px; font-size:12.5px; padding:5px 0; align-items:baseline}
.status-row[hidden]{display:none}
.status-k{color:var(--muted)}
.status-v{color:var(--ink); font-weight:600; font-variant-numeric:tabular-nums; white-space:nowrap}
/* контекстное меню по правому клику (static/js/menu.js) — одно на страницу.
   ⚠️ display здесь не задаём: узел скрывается атрибутом hidden, а авторское правило
   с display было бы сильнее браузерного [hidden]{display:none} — и меню не закрылось бы. */
.ctx-menu{position:fixed; z-index:140; min-width:172px; padding:5px;
  border:1px solid var(--border); border-radius:11px; background:var(--surface); box-shadow:var(--shadow-hover)}
.ctx-menu button{display:block; width:100%; text-align:left; padding:8px 10px; font:inherit; font-size:13px;
  color:var(--ink); border:0; border-radius:7px; background:none; cursor:pointer}
.ctx-menu button:hover{background:var(--bg)}
.ctx-menu button.is-danger{color:var(--danger)}
/* модальное подтверждение */
.modal-backdrop{position:fixed; inset:0; z-index:120; padding:20px; background:rgba(20,22,40,.5);
  display:flex; align-items:center; justify-content:center}
.modal-backdrop[hidden]{display:none}
.modal{background:var(--surface); border:1px solid var(--border); border-radius:16px;
  box-shadow:var(--shadow-hover); padding:24px; max-width:400px; width:100%}
.modal-title{font-size:18px; font-weight:800; margin:0 0 8px; letter-spacing:-.2px}
.modal-text{color:var(--muted); font-size:14px; line-height:1.5; margin:0 0 20px}
.modal-actions{display:flex; justify-content:flex-end; gap:10px}
.theme-btn .icon-sun{display:none}
[data-theme="dark"] .theme-btn .icon-sun{display:block}
[data-theme="dark"] .theme-btn .icon-moon{display:none}

/* ===== Сайдбар: второстепенный, сливается с фоном ===== */
.sidebar{grid-area:sidebar; position:sticky; top:var(--topbar-h); height:calc(100vh - var(--topbar-h));
  overflow-y:auto; overflow-x:hidden; display:flex; flex-direction:column;
  padding:14px 12px 10px; border-right:1px solid var(--border); background:transparent}
html[data-sidebar="off"] .sidebar{display:none}
.side-group{display:flex; flex-direction:column; gap:8px; padding-bottom:14px; margin-bottom:6px;
  border-bottom:1px solid var(--border)}
.side-label{font-size:10px; text-transform:uppercase; letter-spacing:.7px; color:var(--muted);
  font-weight:700; margin:12px 6px 2px}
.side-context .side-label{margin-top:0}
.side-city{width:100%; justify-content:space-between; background:var(--surface)}
.side-salon-single{font-weight:600}
.side-city-single{font-weight:700; font-size:15px; padding:2px 6px}
/* у админа один салон — город/салон не кликабельны (просто подпись контекста) */
.side-static{cursor:default; color:var(--ink); pointer-events:none}
span.side-salon-single.side-static{background:transparent; border-color:transparent; box-shadow:none}
.side-nav{display:flex; flex-direction:column; gap:1px}
.side-link{position:relative; padding:8px 10px 8px 14px; border-radius:8px; font-weight:600;
  font-size:13.5px; color:var(--ink)}
.side-link:hover{background:rgba(124,92,255,.06)}
/* пункт со счётчиком (новые заявки): число прижато вправо, как каретка у ветки */
.side-link.side-with-count{display:flex; align-items:center; justify-content:space-between; gap:8px}
.side-link.is-active{background:var(--surface); box-shadow:var(--shadow); color:var(--accent-ink)}
.side-link.is-active::before{content:""; position:absolute; left:0; top:7px; bottom:7px; width:3px;
  border-radius:3px; background:var(--grad)}

/* ===== Главная колонка ===== */
.maincol{grid-area:main; min-width:0}

/* ===== Крошки и правая часть топбара ===== */
.crumbs{display:flex; align-items:center; gap:8px; font-size:14px; min-width:0; overflow:hidden}
.crumb{font-weight:600; white-space:nowrap}
.crumb:first-child{color:var(--muted); font-weight:500}
.crumb-sep{color:var(--border-strong)}
.topbar-user .dd-menu{right:0; left:auto}
.topbar .avatar{width:26px;height:26px}

/* ===== Дропдаун (details/summary) ===== */
.dd{position:relative}
.dd summary{list-style:none; cursor:pointer}
.dd summary::-webkit-details-marker{display:none}
.dd-btn{display:inline-flex; align-items:center; gap:7px; font-weight:600;
  padding:7px 12px; border:1px solid var(--border-strong); border-radius:10px;
  background:var(--surface); transition:border-color .15s, box-shadow .15s}
.dd-btn:hover{border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,92,255,.10)}
.caret{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;
  border-top:5px solid var(--muted); margin-left:2px}
.dd-menu{position:absolute; top:calc(100% + 8px); left:0; min-width:200px;
  background:var(--surface); border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-hover); padding:6px; z-index:60; max-height:60vh; overflow:auto}
.dd-right .dd-menu{left:auto; right:0}
.dd-item{display:block; width:100%; text-align:left; padding:9px 11px; border-radius:8px;
  font-size:14px; color:var(--ink); border:0; background:none; cursor:pointer; font-weight:500}
.dd-item:hover{background:var(--bg)}
.dd-item.is-active{color:var(--accent-ink); font-weight:700; background:rgba(124,92,255,.07)}
.dd-head{padding:8px 11px 6px; font-size:12px; color:var(--muted); border-bottom:1px solid var(--border); margin-bottom:4px}
.dd-danger{color:var(--danger)}
.dd-danger:hover{background:rgba(229,72,77,.08)}

/* ===== Пользователь ===== */
.user-btn{padding:5px 10px 5px 6px}
.avatar{width:26px;height:26px;border-radius:50%; background:var(--grad); color:#fff; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center; font-weight:700; font-size:12px; flex:0 0 auto}
.avatar img{width:100%; height:100%; object-fit:cover; display:block}
.user-name{max-width:170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* редактор аватара в аккаунте */
.avatar-lg{width:72px; height:72px; font-size:28px}
.avatar-edit{display:flex; align-items:center; gap:16px; margin:4px 0 14px}
.av-pick{display:inline-block; cursor:pointer; padding:8px 14px}
.av-remove{display:inline-flex; align-items:center; gap:5px; margin-left:10px; font-size:13px; color:var(--muted); cursor:pointer}

/* ===== Контейнер ===== */
.content{padding:24px 28px 56px; max-width:none}
.wrap{max-width:1180px; margin:0 auto; padding:28px 24px 64px}
.page-head{display:flex; align-items:flex-end; justify-content:space-between; margin:6px 0 22px}
.h1{font-size:26px; font-weight:700; margin:0; letter-spacing:-.4px}
.h2{font-size:15px; font-weight:700; margin:26px 0 12px; display:flex; align-items:center; gap:9px}
.sub{color:var(--muted); margin:5px 0 0}
.count{font-size:12px; font-weight:700; color:var(--accent-ink); background:rgba(124,92,255,.10);
  padding:2px 9px; border-radius:20px}
.muted{color:var(--muted)}
.small{font-size:12px}
.back{display:inline-block; color:var(--muted); font-weight:600; margin-bottom:6px}
.back:hover{color:var(--accent-ink)}

/* ===== Нормализация контролов (одна высота) и табличные цифры ===== */
.field, .btn, .btn-primary, .btn-ghost, .btn-danger, .dd-btn{min-height:36px}
.btn-primary{margin-top:0}
.auth-form .btn-primary{margin-top:16px}
.tbl td, .kpi-n, .et-row, .fresh-chip{font-variant-numeric:tabular-nums}
.tbl td.num, .tbl th.num{text-align:right}

/* ===== Сегмент-переключатель (пресеты периодов) ===== */
.seg{display:inline-flex; border:1px solid var(--border-strong); border-radius:10px; overflow:hidden; background:var(--surface)}
.seg-item{padding:10px 14px; font-size:13.5px; font-weight:600; color:var(--muted); border:0; background:none; cursor:pointer; white-space:nowrap}
.seg-item + .seg-item{border-left:1px solid var(--border)}
.seg-item:hover{color:var(--ink); background:var(--bg)}
.seg-item.is-active{color:#fff; background:var(--accent)}

/* ===== Тулбар фильтров (отчёты и пр.) ===== */
.toolbar{display:flex; align-items:flex-end; gap:12px; flex-wrap:wrap;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:14px 16px; box-shadow:var(--shadow); margin-bottom:16px}
.toolbar .lbl{margin:0 0 5px}
.tb-field{display:flex; flex-direction:column}
.tb-actions{display:flex; gap:8px; margin-left:auto; align-items:flex-end}
.delta-chip{display:inline-flex; align-items:center; gap:6px; font-size:12.5px; font-weight:700;
  padding:5px 11px; border-radius:999px; background:var(--bg); border:1px solid var(--border)}
.delta-up{color:var(--ok)} .delta-down{color:var(--danger)}

/* ===== KPI ===== */
.mtd-note{font-size:12px; color:var(--muted); margin:0 0 12px}
.kpis{display:grid; grid-template-columns:repeat(auto-fit,minmax(176px,1fr)); gap:14px; margin-bottom:6px}
.kpi{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:16px 18px; box-shadow:var(--shadow); position:relative; overflow:hidden}
.kpi::before{content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--grad)}
.kpi-n{font-size:25px; font-weight:800; letter-spacing:-.5px; white-space:nowrap}
.kpi-n .rub{font-size:15px; font-weight:600; color:var(--muted)}
.kpi-l{font-size:12px; color:var(--muted); margin-top:3px; font-weight:500}

/* ===== Карточки салонов ===== */
.cards{display:grid; grid-template-columns:repeat(auto-fill,minmax(248px,1fr)); gap:14px}
.card{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:16px 17px; box-shadow:var(--shadow); transition:transform .14s, box-shadow .14s, border-color .14s;
  display:flex; flex-direction:column; gap:9px; min-height:104px}
.card:hover{transform:translateY(-2px); box-shadow:var(--shadow-hover); border-color:var(--border-strong)}
.card-top{display:flex; align-items:center; justify-content:space-between; gap:10px}
.card-title{font-weight:700; font-size:15px}
.card-addr{font-size:12.5px; color:var(--muted); line-height:1.35}
.card-foot{margin-top:auto; display:flex; gap:14px; font-size:12.5px; padding-top:6px; border-top:1px solid var(--border)}
.pill{background:rgba(124,92,255,.10); color:var(--accent-ink); font-weight:700; font-size:12px;
  padding:2px 9px; border-radius:20px; min-width:26px; text-align:center}
.pill-muted{background:var(--bg); color:var(--muted)}
.empty{grid-column:1/-1; color:var(--muted); padding:24px; text-align:center;
  border:1px dashed var(--border-strong); border-radius:var(--radius)}
.salon-search{max-width:300px; margin:0 0 14px}
.head-actions{display:flex; gap:10px; align-items:center; flex-wrap:wrap}
.row-actions{white-space:nowrap}
.linkbtn{border:0; background:none; color:var(--accent-ink); cursor:pointer; font:inherit; padding:0; margin-left:10px}
.linkbtn:hover{text-decoration:underline}
.day-flag{font-size:11px; font-weight:700; white-space:nowrap}
.day-flag.on{color:var(--ok)}
.day-flag.off{color:var(--border-strong)}

/* ===== Две колонки: специальности + ростер ===== */
.cols{display:grid; grid-template-columns:300px 1fr; gap:16px; align-items:start; margin-top:8px}
.panel{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:16px 18px; box-shadow:var(--shadow)}
.panel .h2{margin-top:4px}
.panel-head{display:flex; align-items:center; justify-content:space-between}
.bars{display:flex; flex-direction:column; gap:2px}
.bar-row{display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:7px 8px; border-radius:8px}
.bar-row:hover{background:var(--bg)}
.bar-l{font-size:13px}
.bar-n{font-weight:700; font-size:13px; color:var(--accent-ink); background:rgba(124,92,255,.08);
  padding:1px 8px; border-radius:14px}

/* ===== Таблица мастеров ===== */
.tbl{width:100%; border-collapse:collapse; font-size:13.5px}
.tbl th{text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.5px;
  color:var(--muted); font-weight:700; padding:8px 10px; border-bottom:1px solid var(--border)}
.tbl td{padding:9px 10px; border-bottom:1px solid var(--border)}
.tbl tr:last-child td{border-bottom:0}
.tbl tr:hover td{background:var(--bg)}
/* td-name — обычная table-cell: display:flex на <td> ломает высоту ячейки
   (разрывы фона и «поехавшие» линии-разделители в строках) */
.td-name{font-weight:600}
/* цветная точка мастера: в списках убрана (цвет из легаси красил сетку графика,
   которой у нас нет). Правило оставлено на случай экрана смен, поле color синк пишет. */
.dot{width:9px;height:9px;border-radius:50%; display:inline-block; flex:0 0 auto; box-shadow:0 0 0 1px var(--border-strong)}
.td-name .dot{margin-right:6px; vertical-align:-1px}
/* кликабельное число издержек в отчётах → открывает разбивку */
.cost-link{color:inherit; text-decoration:none; border-bottom:1px dashed var(--border-strong)}
.cost-link:hover{color:var(--accent-ink); border-bottom-color:var(--accent)}
.flags{text-align:right; white-space:nowrap}
.tag{display:inline-block; font-size:11px; font-weight:600; color:var(--muted);
  background:var(--bg); border:1px solid var(--border); padding:1px 7px; border-radius:12px; margin-left:4px}
.tag.tag-warn{color:#c07a00; background:rgba(245,159,0,.12); border-color:rgba(245,159,0,.3)}
.pager{display:flex; align-items:center; justify-content:center; gap:18px; margin-top:14px; font-weight:600}
.pager a{color:var(--accent-ink)} .pager a:hover{text-decoration:underline}
.pager .off{color:var(--border-strong)} .pager .pg{color:var(--muted)}

/* параметры расчёта: одинаковая сетка колонок во всех таблицах городов
   (.tbl.tbl-params — иначе проигрывает более позднему .tbl{min-width:420px}) */
.tbl.tbl-params{table-layout:fixed; min-width:640px}
.tbl-params td{overflow-wrap:break-word}

/* навигация по дате (город за день): стрелки + дата в одну линию */
.datenav{display:flex; align-items:center; gap:8px}
.datenav .field{margin:0; width:auto}
.datenav .btn-ghost{padding:0 12px; text-decoration:none; display:inline-flex; align-items:center; color:var(--ink)}
.datenav .is-off{opacity:.45; pointer-events:none}

/* настройка столбцов (columns.js): кнопка над таблицей + меню */
.cols-bar{display:flex; justify-content:flex-end; margin:-4px 0 8px}
.panel-head{display:flex; align-items:center; justify-content:space-between; gap:12px; margin:0 0 12px}
.panel-head .h2{margin:0}
.cols-btn{display:inline-flex; align-items:center; font-size:12.5px; font-weight:600; color:var(--muted);
  padding:5px 11px; border:1px solid var(--border); border-radius:8px; background:var(--surface); cursor:pointer}
.cols-btn:hover{border-color:var(--accent); color:var(--accent-ink)}
.cols-menu{min-width:240px}
.cols-row{display:flex; align-items:center; gap:2px; padding:3px 6px; border-radius:8px}
.cols-row:hover{background:var(--bg)}
.cols-row label{display:flex; align-items:center; gap:8px; flex:1; font-size:13.5px; cursor:pointer; min-width:0}
.cols-row label span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.cols-move{border:0; background:none; cursor:pointer; color:var(--muted); font-size:13px;
  padding:3px 6px; border-radius:6px; line-height:1}
.cols-move:hover{color:var(--ink); background:var(--border)}
.cols-move:disabled{opacity:.25; cursor:default}
.cols-move:disabled:hover{color:var(--muted); background:none}
.cols-reset{margin-top:4px; border-top:1px solid var(--border); border-radius:0 0 8px 8px; color:var(--muted)}

/* сортируемые заголовки таблиц (sortable.js) */
.th-sort{cursor:pointer; user-select:none}
.th-sort:hover{color:var(--ink)}
.th-sort[aria-sort]{color:var(--accent-ink)}
.th-sort[aria-sort]::after{content:'▲'; font-size:8px; margin-left:4px; vertical-align:1px}
.th-sort[aria-sort="descending"]::after{content:'▼'}

/* свёрнутый список «не закрыли день» под таблицей */
.missing-days{margin-top:12px}
.missing-days summary{cursor:pointer; font-size:13.5px; font-weight:600; color:var(--muted); user-select:none}
.missing-days summary:hover{color:var(--ink)}
.missing-days p{margin:8px 2px 0}

/* Присутствие пользователей (онлайн/офлайн) */
.pres-dot{display:inline-block; width:8px; height:8px; border-radius:50%; flex:0 0 auto}
.pres-on{background:var(--ok); box-shadow:0 0 0 3px rgba(22,163,106,.18)}
.pres-off{background:var(--border-strong)}

/* Город за день: салон не закрыл день — красная строка (видно халтуру) */
.row-unclosed td{background:rgba(229,72,77,.07)}
.row-unclosed .td-name a{color:var(--danger)}
.row-unclosed .td-name a:hover{text-decoration:underline}
.day-unclosed{text-align:left; color:var(--danger); font-weight:600; opacity:.75}
.bad-tag{display:inline-block; font-size:11px; font-weight:700; color:#fff; background:var(--danger);
  padding:1px 8px; border-radius:12px; white-space:nowrap}

/* Издержки по дням: раскрываемые строки */
.cost-days{display:flex; flex-direction:column; gap:6px}
.cost-day{border:1px solid var(--border); border-radius:10px; background:var(--surface); overflow:hidden}
.cost-day > summary{list-style:none; cursor:pointer; display:flex; align-items:center; gap:14px;
  padding:12px 14px; font-weight:600}
.cost-day > summary::-webkit-details-marker{display:none}
.cost-day > summary:hover{background:var(--bg)}
.cost-day .spacer{flex:1}
.cost-day-date{font-variant-numeric:tabular-nums}
.cost-day-meta{font-size:12.5px; font-weight:500}
.cost-day-sum{font-variant-numeric:tabular-nums; font-weight:700}
.cost-day-caret{width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;
  border-top:6px solid var(--muted); transition:transform .15s; flex:0 0 auto}
.cost-day[open] .cost-day-caret{transform:rotate(180deg)}
.cost-day .table-wrap{border-top:1px solid var(--border)}
.cost-day-tbl{margin:0; min-width:0; table-layout:fixed}
.cost-day-tbl td, .cost-day-tbl th{padding:8px 14px; overflow:hidden; text-overflow:ellipsis}
.cost-day-tbl td.num, .cost-day-tbl th.num{white-space:nowrap}

/* ===== Сообщения ===== */
.messages{margin-bottom:16px}
.msg{padding:10px 14px; border-radius:10px; margin-bottom:8px; font-weight:500}
.msg-error{background:#fdecec; color:#b42318}
.msg-success{background:#e9f9f1; color:#0f7a4d}

/* ===== Пустой стейт ===== */
.empty-state{max-width:440px; margin:14vh auto 0; text-align:center; display:flex;
  flex-direction:column; align-items:center; gap:6px}
.empty-state .sub{margin-bottom:18px}

/* ===== Логин =====
   Экран входа ВСЕГДА тёмный, независимо от выбранной темы приложения: это порог,
   а не рабочее место. Поэтому здесь СВОЯ палитра, а не переменные --bg/--surface —
   иначе скрипт темы в base.html перекрасил бы экран у тех, у кого светлая.

   Шрифты названы AuraSans/AuraMono намеренно: если объявить их как 'Inter',
   шрифт подхватит ВСЁ приложение (в body он уже указан первым), а это совсем
   другое по масштабу изменение. Здесь — только вход.

   Поля приходят из Python с классом .field, поэтому базовые стили приложения
   перекрываются через обёртку .lg-page (специфичность 0,2,0 против 0,1,0). */
@font-face{font-family:'AuraSans';font-style:normal;font-weight:400;font-display:swap;src:url("../fonts/inter-400-cyrillic.22ca3f6004fb.woff2") format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'AuraSans';font-style:normal;font-weight:400;font-display:swap;src:url("../fonts/inter-400-latin.aedc4605f3b0.woff2") format('woff2')}
@font-face{font-family:'AuraSans';font-style:normal;font-weight:500;font-display:swap;src:url("../fonts/inter-500-cyrillic.22ca3f6004fb.woff2") format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'AuraSans';font-style:normal;font-weight:500;font-display:swap;src:url("../fonts/inter-500-latin.aedc4605f3b0.woff2") format('woff2')}
@font-face{font-family:'AuraSans';font-style:normal;font-weight:600;font-display:swap;src:url("../fonts/inter-600-cyrillic.22ca3f6004fb.woff2") format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'AuraSans';font-style:normal;font-weight:600;font-display:swap;src:url("../fonts/inter-600-latin.aedc4605f3b0.woff2") format('woff2')}
@font-face{font-family:'AuraMono';font-style:normal;font-weight:400;font-display:swap;src:url("../fonts/jetbrains-mono-400-cyrillic.775ea040fc36.woff2") format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'AuraMono';font-style:normal;font-weight:400;font-display:swap;src:url("../fonts/jetbrains-mono-400-latin.73309d4ee2de.woff2") format('woff2')}
@font-face{font-family:'AuraMono';font-style:normal;font-weight:500;font-display:swap;src:url("../fonts/jetbrains-mono-500-cyrillic.775ea040fc36.woff2") format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'AuraMono';font-style:normal;font-weight:500;font-display:swap;src:url("../fonts/jetbrains-mono-500-latin.73309d4ee2de.woff2") format('woff2')}

.lg-page{--lg-bg:#0a0b0f; --lg-ink:#eceef4; --lg-muted:rgba(236,238,244,.44);
  --lg-faint:rgba(236,238,244,.26); --lg-line:rgba(236,238,244,.09);
  --lg-line-2:rgba(236,238,244,.05); --lg-accent:#8f73ff; --lg-danger:#ff6b6f;
  --lg-sans:'AuraSans',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --lg-mono:'AuraMono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  position:relative; min-height:100dvh; display:flex; flex-direction:column;
  background:var(--lg-bg); color:var(--lg-ink); font-family:var(--lg-sans);
  -webkit-font-smoothing:antialiased}
/* фон страницы за пределами main (overscroll) — тоже тёмный */
html:has(.lg-page), body:has(.lg-page){background:#0a0b0f}

.lg-grid{position:fixed; inset:0; z-index:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(236,238,244,.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(236,238,244,.028) 1px, transparent 1px),
    linear-gradient(rgba(236,238,244,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(236,238,244,.05) 1px, transparent 1px);
  background-size:22px 22px,22px 22px,132px 132px,132px 132px;
  -webkit-mask-image:radial-gradient(100% 86% at 64% 42%, #000 0%, transparent 78%);
  mask-image:radial-gradient(100% 86% at 64% 42%, #000 0%, transparent 78%)}
.lg-wash{position:fixed; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(700px 540px at 76% 24%, rgba(143,115,255,.16), transparent 64%)}
.lg-grain{position:fixed; inset:-50%; z-index:1; pointer-events:none; opacity:.035; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

.lg-shell{position:relative; z-index:3; flex:1; display:flex; flex-direction:column;
  max-width:1180px; width:100%; margin:0 auto; padding:0 clamp(24px,4.5vw,56px)}
.lg-head{display:flex; align-items:center; justify-content:space-between; padding:26px 0 0}
.lg-wordmark{font-family:var(--lg-mono); font-size:13px; font-weight:500; letter-spacing:.42em;
  text-transform:uppercase; color:var(--lg-ink)}
.lg-meta{font-family:var(--lg-mono); font-size:10.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--lg-faint)}
.lg-main{flex:1; display:grid; grid-template-columns:minmax(0,1fr) minmax(0,392px);
  gap:clamp(32px,6vw,88px); align-items:center; padding:28px 0}
.lg-eyebrow{font-family:var(--lg-mono); font-size:10px; letter-spacing:.34em; text-transform:uppercase;
  color:var(--lg-accent); margin:0 0 24px; display:flex; align-items:center; gap:14px}
.lg-eyebrow::before{content:''; width:26px; height:1px; background:var(--lg-accent)}
.lg-side .saxap-logo{width:190px; filter:brightness(0) invert(1); opacity:.92}

/* панель — поверхность НАД сеткой: свой фон, рамка, тень и подсветка снизу */
.lg-panel{position:relative; padding:30px 28px 28px; border-radius:10px;
  background:linear-gradient(180deg,#14161e 0%,#101219 100%);
  border:1px solid rgba(236,238,244,.16);
  box-shadow:0 40px 90px rgba(0,0,0,.62), 0 8px 24px rgba(0,0,0,.45),
             inset 0 1px 0 rgba(255,255,255,.05)}
.lg-panel::before{content:''; position:absolute; inset:-32px -18px -22px; z-index:-1; border-radius:22px;
  background:radial-gradient(60% 55% at 50% 45%, rgba(143,115,255,.20), transparent 72%);
  filter:blur(14px); pointer-events:none}
/* приводочные метки вынесены НАРУЖУ: на скруглённой рамке они с ней сливаются */
.lg-tick{position:absolute; width:13px; height:13px; border:1.5px solid var(--lg-accent)}
.lg-tick.tl{top:-7px; left:-7px; border-right:0; border-bottom:0}
.lg-tick.br{bottom:-7px; right:-7px; border-left:0; border-top:0}
.lg-panel h1{font-size:19px; font-weight:600; letter-spacing:-.02em; margin:0 0 22px}

.lg-page .lbl{display:block; font-family:var(--lg-mono); font-size:9.5px; letter-spacing:.22em;
  text-transform:uppercase; color:var(--lg-faint); margin:0 0 8px; font-weight:400}
.lg-page .field{width:100%; padding:12px 13px; font-size:14px; font-family:var(--lg-sans);
  color:var(--lg-ink); background:rgba(0,0,0,.32); border:1px solid rgba(236,238,244,.13);
  border-radius:6px; margin-bottom:18px;
  transition:border-color .2s, box-shadow .2s, background .2s}
.lg-page .field::placeholder{color:rgba(236,238,244,.24)}
.lg-page .field:focus{outline:none; border-color:var(--lg-accent); background:rgba(143,115,255,.06);
  box-shadow:0 0 0 3px rgba(143,115,255,.14)}
.lg-page .pw-wrap{position:relative; display:block; margin-bottom:18px}
.lg-page .pw-wrap .field{padding-right:44px; margin-bottom:0}
.lg-page .pw-toggle{position:absolute; right:5px; top:50%; transform:translateY(-50%);
  width:34px; height:34px; display:flex; align-items:center; justify-content:center;
  border:0; border-radius:6px; background:none; color:var(--lg-faint); cursor:pointer}
.lg-page .pw-toggle:hover{color:var(--lg-accent); background:rgba(143,115,255,.1)}
.lg-page .pw-toggle.on{color:var(--lg-accent)}
.lg-page .check{display:flex; align-items:center; gap:9px; font-size:13px; font-weight:400;
  color:var(--lg-muted); cursor:pointer; margin:2px 0 20px}
.lg-page .check input{width:15px; height:15px; accent-color:var(--lg-accent)}
.lg-page .btn-primary{width:100%; margin:0; padding:13px 18px; font-family:var(--lg-mono);
  font-size:11.5px; font-weight:500; letter-spacing:.22em; text-transform:uppercase;
  color:#0a0b0f; background:var(--lg-ink); border:0; border-radius:6px; cursor:pointer;
  transition:transform .18s, box-shadow .18s}
.lg-page .btn-primary:hover{transform:translateY(-1px); box-shadow:0 10px 28px rgba(0,0,0,.5)}

/* ошибка входа — свой класс, а НЕ .auth-err: тот же .auth-err используется
   в настройках аккаунта на светлом фоне, перекрашивать его нельзя */
.lg-err{display:flex; gap:10px; align-items:flex-start; font-size:12.5px; line-height:1.5;
  color:#ffb4b6; background:rgba(255,107,111,.08); border:1px solid rgba(255,107,111,.28);
  border-radius:6px; padding:10px 12px; margin-bottom:20px}
.lg-err::before{content:''; flex:none; width:5px; height:5px; border-radius:50%;
  background:var(--lg-danger); margin-top:6px}
.lg-err b{color:#fff; font-weight:600}
.lg-page .is-locked{opacity:.5}

.lg-foot{position:relative; z-index:3; max-width:1180px; width:100%; margin:0 auto;
  padding:0 clamp(24px,4.5vw,56px) 22px; display:flex; justify-content:space-between; gap:12px;
  font-family:var(--lg-mono); font-size:9.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--lg-faint)}

.lg-rise{opacity:0; transform:translateY(14px); animation:lgrise .9s cubic-bezier(.16,1,.3,1) forwards}
@keyframes lgrise{to{opacity:1; transform:none}}
.lg-d1{animation-delay:.04s}.lg-d2{animation-delay:.16s}.lg-d3{animation-delay:.3s}
@media (prefers-reduced-motion:reduce){.lg-rise{animation:none; opacity:1; transform:none}}

@media (max-width:900px){
  .lg-main{grid-template-columns:1fr; gap:36px; padding:24px 0 36px}
  .lg-side .saxap-logo{width:150px}
}
.lbl{font-size:12px; font-weight:600; color:var(--muted); margin:12px 0 6px}
.field{width:100%; padding:11px 13px; font-size:14px; border:1px solid var(--border-strong);
  border-radius:10px; background-color:var(--surface); transition:border-color .15s, box-shadow .15s;
  font-family:inherit; -webkit-appearance:none; appearance:none; color:var(--ink)}
.field:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,92,255,.14)}

/* ===== Пикер даты AURA (свой календарь вместо системного) ===== */
/* нативный input остаётся в потоке (валидация/required/фокус), но невидим под нашим UI */
.dp{position:relative; display:inline-flex; align-items:center; gap:6px; vertical-align:middle}
.dp-native{position:absolute; left:0; top:0; width:100%; height:100%; opacity:0;
  pointer-events:none; border:0; padding:0; margin:0; background:none}
.dp-trigger{display:inline-flex; align-items:center; gap:9px; width:auto; cursor:pointer;
  text-align:left; font-weight:600; font-variant-numeric:tabular-nums; color:var(--ink)}
.dp-trigger.is-empty .dp-txt{color:var(--muted); font-weight:500}
.dp-ic{display:inline-flex; color:var(--muted); flex:none}
.dp-ic svg{width:15px; height:15px; display:block}
.dp-trigger:hover{border-color:var(--accent)}
.dp.is-disabled{opacity:.55; pointer-events:none}
/* навигатор дня («Смена») */
.dp-nav{gap:7px}
.daynav-btn{display:inline-flex; align-items:center; justify-content:center; width:36px; min-height:40px;
  border:1px solid var(--border-strong); border-radius:10px; background:var(--surface);
  color:var(--muted); cursor:pointer; font-size:16px; line-height:1; flex:none}
.daynav-btn:hover:not(:disabled){border-color:var(--accent); color:var(--accent-ink)}
.daynav-btn.is-off,.daynav-btn:disabled{opacity:.35; cursor:default}
.daynav-cur{display:inline-flex; flex-direction:column; align-items:center; gap:1px; cursor:pointer;
  padding:5px 18px; min-height:40px; justify-content:center; min-width:158px;
  border:1px solid var(--border-strong); border-radius:10px; background:var(--surface); color:var(--ink)}
.daynav-cur:hover{border-color:var(--accent)}
.daynav-cur b{font-size:14px; font-weight:700; line-height:1.15}
.daynav-cur span{font-size:10.5px; color:var(--muted); line-height:1.2}
/* поповер календаря */
.dp-pop{position:absolute; top:calc(100% + 8px); left:0; z-index:80; width:264px; padding:12px;
  background:var(--surface); border:1px solid var(--border); border-radius:14px; box-shadow:var(--shadow-hover)}
.dp-pop.dp-up{top:auto; bottom:calc(100% + 8px)}
.dp-nav .dp-pop{left:50%; transform:translateX(-50%)}
.dp-head{display:flex; align-items:center; justify-content:space-between; gap:6px; margin-bottom:10px}
.dp-title{flex:1; padding:5px 8px; border:0; border-radius:8px; background:none; cursor:pointer;
  font:inherit; font-weight:700; font-size:13.5px; color:var(--ink)}
.dp-title:hover{background:var(--bg)}
.dp-nav-btn{width:26px; height:26px; display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--border-strong); border-radius:8px; background:var(--surface);
  color:var(--muted); cursor:pointer; font-size:13px; line-height:1; flex:none}
.dp-nav-btn:hover{border-color:var(--accent); color:var(--accent-ink)}
.dp-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:2px; text-align:center}
.dp-grid-m{grid-template-columns:repeat(3,1fr); gap:5px}
.dp-wd{font-size:10px; text-transform:uppercase; letter-spacing:.5px; color:var(--muted);
  font-weight:700; padding:4px 0}
.dp-cell{padding:7px 0; border:0; border-radius:8px; background:none; cursor:pointer;
  font:inherit; font-size:12.5px; color:var(--ink); font-variant-numeric:tabular-nums}
.dp-cell:hover:not(:disabled){background:var(--bg)}
.dp-grid-m .dp-cell{padding:9px 0; font-size:13px}
.dp-day.is-out{color:var(--muted); opacity:.5}
.dp-day.is-we{color:var(--accent-ink)}
.dp-day.is-today{background:var(--grad); color:#fff; font-weight:800}
.dp-cell.is-pick{box-shadow:inset 0 0 0 1px var(--accent); color:var(--accent-ink); font-weight:700}
/* выделение с клавиатуры: показывает, куда применится Enter (значение ещё не изменено) */
.dp-cell.is-cursor{background:var(--bg)}
.dp-cell.is-cursor.is-pick{box-shadow:inset 0 0 0 2px var(--accent)}
.dp-day.is-off{opacity:.28; cursor:default; text-decoration:line-through}
.dp-foot{display:flex; gap:6px; margin-top:10px; padding-top:10px; border-top:1px solid var(--border)}
.dp-chip{flex:1; padding:6px 0; border:1px solid var(--border-strong); border-radius:8px;
  background:none; cursor:pointer; font:inherit; font-size:11.5px; font-weight:700; color:var(--accent-ink)}
.dp-chip:hover{border-color:var(--accent); background:var(--bg)}

/* Кроссбраузерная нормализация date/select (Safari/WebKit рисует их своим нативным
   стилем — плавающая высота дат и стрелки-степпер у селекта). Приводим к общему виду. */
input[type="date"].field, input[type="time"].field{min-height:41px}
input[type="date"].field::-webkit-date-and-time-value{text-align:left; margin:0; padding:0}
input[type="date"].field::-webkit-datetime-edit{padding:0; line-height:1.2}
input[type="date"].field::-webkit-calendar-picker-indicator{opacity:.65; cursor:pointer}
input[type="date"].field::-webkit-calendar-picker-indicator:hover{opacity:1}
select.field{padding-right:36px; cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%239097b8' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 13px center; background-size:12px 8px}
select.field::-ms-expand{display:none}
/* (русский формат даты и сам календарь теперь делает datepicker.js — см. блок «Пикер даты AURA») */
/* убираем нативный степпер у числовых полей (тот же «⇅», ввод с клавиатуры остаётся) */
.field::-webkit-outer-spin-button, .field::-webkit-inner-spin-button{-webkit-appearance:none; margin:0}
input[type="number"].field{-moz-appearance:textfield}
.btn-primary{margin-top:22px; padding:12px 16px; border:0; border-radius:10px; cursor:pointer;
  font-size:15px; font-weight:700; color:#fff; background:var(--grad);
  box-shadow:0 6px 18px rgba(124,92,255,.32); transition:transform .12s, box-shadow .12s}
.btn-primary:hover{transform:translateY(-1px); box-shadow:0 10px 26px rgba(124,92,255,.40)}
.btn-primary:active{transform:translateY(0)}
.btn-ghost{padding:10px 18px; border:1px solid var(--border-strong); border-radius:10px;
  background:var(--surface); font-weight:600; cursor:pointer}
.btn-ghost:hover{border-color:var(--accent)}
/* Главное действие экрана в рабочих разделах: та же геометрия, что у .btn-ghost, —
   они часто стоят парой («Применить» + «Сбросить») и обязаны совпадать по высоте.
   От .btn-primary отличается тем, что не тащит margin-top:22px и крупный кегль: та
   рассчитана на форму входа и низ формы, а не на панель инструментов.

   Заливка сплошная, без градиента и тени, — намеренно сдержаннее .btn-primary: на одном
   экране таких кнопок бывает несколько сразу (в карточке лендинга их пять), и градиент
   с тенью на каждой превращает страницу в ярмарку. Отклик на наведение — сменой тона:
   в светлой теме --accent-ink темнее акцента, в тёмной светлее, поэтому работает в обеих.

   ⚠️ Класс использовался в 26 местах (Landings, Voice), НЕ БУДУЧИ ОБЪЯВЛЕННЫМ вовсе —
   все эти кнопки рисовались системными средствами браузера. Правило «каждый класс
   кнопки объявлен» держит тест test_every_button_class_is_defined. */
.btn{display:inline-flex; align-items:center; justify-content:center; padding:10px 18px;
  border:1px solid transparent; border-radius:10px; cursor:pointer;
  font-family:inherit; font-size:14px; font-weight:600; color:#fff; background:var(--accent);
  transition:background .12s}
.btn:hover{background:var(--accent-ink)}
.btn:active{opacity:.9}
.auth-err{background:#fdecec; color:#b42318; font-weight:500; font-size:13px;
  padding:10px 13px; border-radius:10px; margin-bottom:6px}
.auth-form.is-locked{opacity:.6}
.field:disabled, .btn-primary:disabled{opacity:.55; cursor:not-allowed; box-shadow:none; transform:none}

/* ===== Параметры расчёта (форма) ===== */
.pf-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin-bottom:14px}
.params-form label{display:flex; flex-direction:column; gap:5px; font-size:12px; font-weight:600; color:var(--muted)}
.params-form .field{font-weight:400; color:var(--ink)}
.pf-wide{grid-column:1/-1}
.row-eff td{background:rgba(124,92,255,.06)}

/* ===== Сверка (golden master) ===== */
.yearbar{display:flex; flex-wrap:wrap; gap:8px}
.ycell{background:var(--surface); border:1px solid var(--border); border-radius:10px;
  padding:8px 12px; text-align:center; min-width:64px; box-shadow:var(--shadow)}
.yyear{font-size:11px; color:var(--muted); font-weight:600}
.ypct{font-size:17px; font-weight:800; margin-top:2px}
.yhi{color:var(--ok)} .ymid{color:#c98a00} .ylo{color:var(--danger)}
.ok{color:var(--ok); font-weight:700}
.bad{color:var(--danger); font-weight:600; font-size:12.5px; white-space:nowrap}
.page-head .btn-ghost{align-self:center}

/* ===== Блок «на проверку» (пустые салоны) ===== */
.review{margin-top:22px; border-top:1px dashed var(--border-strong); padding-top:14px}
.review summary{cursor:pointer; font-weight:600; color:var(--muted); list-style:none; padding:6px 0}
.review summary::-webkit-details-marker{display:none}
.review summary::before{content:"▸ "; color:var(--accent-ink)}
.review[open] summary::before{content:"▾ "}
.review .cards{margin-top:12px}
.card-dim{opacity:.62}
.card-dim:hover{opacity:1}

/* ===== Обзор сети (плитки городов) ===== */
.netgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:12px; margin-bottom:6px}
.netcard{background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:14px 16px;
  box-shadow:var(--shadow); display:flex; flex-direction:column; gap:5px; transition:transform .14s, box-shadow .14s, border-color .14s}
.netcard:hover{transform:translateY(-2px); box-shadow:var(--shadow-hover)}
.netcard.is-current{border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,92,255,.12)}
.netcard-name{font-weight:700; font-size:15px; display:flex; align-items:center; gap:8px}
.netcard-here{font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.4px;
  color:var(--accent-ink); background:rgba(124,92,255,.10); padding:2px 7px; border-radius:10px}
.netcard-stats{font-size:12.5px; color:var(--muted)}

/* ===== Свитчер салона в топбаре ===== */
.ctx-sep{color:var(--border-strong); font-weight:400}
.dd-salon{max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

/* ===== Обёртка таблицы (моб. скролл) + пустые состояния ===== */
.table-wrap{width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch}
.tbl{min-width:420px}
.empty-row{color:var(--muted); text-align:center; padding:18px 10px !important}
/* пояснение под итогом таблицы (почему сумма расходится с отчётами) */
.foot-note td{color:var(--muted); font-weight:400; font-size:12px; padding-top:8px !important}
.card-title{overflow-wrap:anywhere}

/* ввод бизнес-дня */
.dateform{margin-bottom:16px}
.dateform label{font-size:13px; font-weight:600; color:var(--muted); display:inline-flex; gap:8px; align-items:center}
.dateform .field{margin:0; width:auto}
.entry-tbl td{padding:5px 6px; vertical-align:middle}
.entry-tbl .field{padding:6px 8px; font-size:13px; margin:0}
.r-name{min-width:140px}
.entry-inputs{display:grid; grid-template-columns:1fr 1fr; gap:10px 14px}
.entry-inputs label{font-size:12px; font-weight:600; color:var(--muted); display:flex; flex-direction:column; gap:4px}
.entry-inputs .field{padding:8px 10px; margin:0}
.entry-totals{margin-top:16px; padding-top:12px; border-top:1px solid var(--border)}
.et-row{display:flex; justify-content:space-between; padding:6px 0; font-size:14px}
/* Строка «План» в итогах дня приходит с атрибутом hidden и показывается скриптом только
   когда план задан. Без этого правила hidden не действовал, и строка висела всегда —
   с пустым значением (авторский display сильнее браузерного [hidden]). */
.et-row[hidden]{display:none}
.et-row b{font-weight:800}
/* пояснение под итогами архивной смены (почему налог «—», от чего эквайринг) */
.et-note{margin:10px 0 0; font-size:12px; line-height:1.5; color:var(--muted)}
.rowdel{border:0; background:none; color:var(--danger); cursor:pointer; font-size:14px; padding:4px}
/* индикатор «план выполнен» на смене */
.plan-status{border-radius:8px; padding:6px 10px; margin-top:2px; font-weight:700}
.plan-status.ok{background:rgba(46,160,67,.12); color:var(--ok)}
.plan-status.warn{background:rgba(245,159,0,.14); color:#c07a00}
/* экран «Планы» и селектор базы плана */
.field-plan{max-width:110px; text-align:right}
.plan-base-form .inline-lbl{display:inline-flex; align-items:center; gap:8px; font-size:13px; color:var(--muted)}
.field-inline{display:inline-block; width:auto; padding:5px 8px}

/* ===== Экран «Смена» (матрица + блоки) — десктоп ===== */
.smena-matrix{overflow-x:auto; -webkit-overflow-scrolling:touch; border:1px solid var(--border); border-radius:12px}
.mtx{border-collapse:separate; border-spacing:0; font-size:13px; min-width:100%}
.mtx th, .mtx td{border-bottom:1px solid var(--border); border-right:1px solid var(--border); padding:0}
/* титульная колонка: ФИКСИРОВАННАЯ ширина — иначе при малом числе мастеров браузер
   растягивал её на свободное место, и подписи строк «ездили» от смены к смене */
.mtx .rl{position:sticky; left:0; z-index:2; background:var(--bg); padding:8px 12px; font-weight:600;
  color:var(--muted); white-space:nowrap; text-align:right; border-right:1px solid var(--border-strong);
  width:170px; min-width:170px; max-width:170px}
.mtx thead th{position:sticky; top:0; z-index:1; background:var(--bg); border-bottom:2px solid var(--border-strong)}
.mtx thead .rl{z-index:3}
.mtx .corner{vertical-align:middle; font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted); text-align:center; opacity:.7}
.mtx .mcol{padding:8px 10px; min-width:152px; vertical-align:top; text-align:center; position:relative}
/* ===== Матрицы планов: таблица как в «Смене» — ячейка к ячейке, без скруглений =====
   Вертикально страница листается сама: своей прокрутки у панели нет, иначе колесо
   мыши сначала прокручивает таблицу и лишь потом страницу. Панель ловит только ширину,
   а шапку при прокрутке прижимает к верху отдельная плавающая копия (matrix.js). */
.matrix-pane{overflow-x:auto; -webkit-overflow-scrolling:touch;
  border:1px solid var(--border); border-radius:12px}
.plans-matrix{border-collapse:separate; border-spacing:0; font-size:12.5px; min-width:100%}
.plans-matrix th, .plans-matrix td{padding:0; white-space:nowrap;
  border-bottom:1px solid var(--border); border-right:1px solid var(--border)}
.plans-matrix thead th{background:var(--bg); padding:5px 8px; font-size:11px;
  text-align:center; font-weight:600}
.plans-matrix thead tr:last-child th{border-bottom:2px solid var(--border-strong)}
.plans-matrix .pm-day{border-left:1px solid var(--border-strong); font-size:11.5px;
  text-transform:none; letter-spacing:0}
.plans-matrix .pm-sub{color:var(--muted); font-size:10px; text-transform:uppercase; letter-spacing:.04em}
.plans-matrix .pm-over{background:rgba(124,92,255,.045)}
/* колонка салонов фиксированной ширины: иначе она «ездит» от города к городу */
.plans-matrix .pm-salon{position:sticky; left:0; z-index:3; background:var(--surface);
  text-transform:none; letter-spacing:0;
  border-right:1px solid var(--border-strong); text-align:left; padding:6px 10px; font-weight:600;
  width:186px; min-width:186px; max-width:186px; overflow:hidden; text-overflow:ellipsis}
.plans-matrix thead .pm-salon{z-index:5; background:var(--bg); font-weight:600}
.plans-matrix td .field-plan{width:100%; min-width:76px; border:0; border-radius:0; background:var(--surface);
  padding:6px 8px; text-align:right; font-size:12.5px; font-variant-numeric:tabular-nums; color:var(--ink)}
.plans-matrix td .field-plan:focus{outline:2px solid var(--accent); outline-offset:-2px;
  position:relative; z-index:1}
.plans-matrix td .field-plan::placeholder{color:var(--muted); opacity:.5}
/* браузерные стрелки «плюс/минус тысяча» в таблице только мешают целиться в ячейку */
.plans-matrix input[type=number]{-moz-appearance:textfield; appearance:textfield}
.plans-matrix input[type=number]::-webkit-outer-spin-button,
.plans-matrix input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none; margin:0}
/* «Весь город» и «Бонус админу» — опорные строки: от них отсчитываются все салоны */
.plans-matrix .pm-city td, .plans-matrix .pm-bonus td,
.plans-matrix tr.pm-city:hover td, .plans-matrix tr.pm-bonus:hover td{background:rgba(124,92,255,.06)}
.plans-matrix .pm-city .field-plan, .plans-matrix .pm-bonus .field-plan{background:transparent; font-weight:600}
.plans-matrix .pm-bonus td{border-bottom:2px solid var(--border-strong)}
/* подсветка: заголовок колонки и название салона окрашиваются ОДИНАКОВО —
   это две координаты одной ячейки, и разный вид читался бы как разный смысл */
.plans-matrix th.is-hot, .plans-matrix tr.is-hot .pm-salon{background:var(--accent); color:#fff}
.plans-matrix th.is-hot.pm-sub{color:#fff; opacity:.95}
.plans-matrix td.is-hot .field-plan{background:rgba(124,92,255,.10)}
/* плавающая копия шапки: показывается, когда настоящая уехала вверх */
.matrix-float{position:fixed; z-index:30; overflow:hidden; pointer-events:none;
  box-shadow:0 6px 14px rgba(25,27,46,.10)}
.matrix-float table{margin:0; border-collapse:separate; border-spacing:0; table-layout:fixed}
.matrix-float .pm-salon{position:static}
/* адрес текущей ячейки словами — рядом с кнопкой сохранения */
.pm-addr{font-weight:600; color:var(--accent-ink)}

/* «Планы» в сайдбаре раскрываются деревом: вертикаль вниз и веточки вправо к пунктам.
   Класс side-group тут занят контекстным блоком сверху — отсюда своё имя side-tree. */
.side-tree > .side-sum{display:flex; align-items:center; justify-content:space-between;
  cursor:pointer; list-style:none}
.side-tree > .side-sum::-webkit-details-marker{display:none}
.tree-caret{width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent;
  border-top:5px solid var(--muted); transition:transform .15s ease}
.side-tree[open] > .side-sum .tree-caret{transform:rotate(180deg)}
.side-kids{margin:2px 0 2px 22px; display:flex; flex-direction:column; gap:1px}
.side-link.side-sub{position:relative; margin-left:9px; padding:7px 10px 7px 10px;
  font-weight:500; font-size:13px}
/* вертикаль: у последнего пункта обрывается на его середине — как в выводе tree */
.side-link.side-sub::before{content:""; position:absolute; left:-9px; top:0; height:50%;
  border-left:1px solid var(--border-strong)}
.side-link.side-sub:not(:last-child)::before{height:100%}
.side-link.side-sub::after{content:""; position:absolute; left:-9px; top:50%; width:7px;
  border-top:1px solid var(--border-strong)}
.side-link.side-sub.is-active::before, .side-link.side-sub.is-active::after{border-color:var(--accent)}
/* меню выгрузки: CSV / Excel / PDF */
.export-dd{display:inline-block; position:relative}
.export-dd .dd-menu{right:0; left:auto; min-width:170px}
.export-dd .dd-item{display:block; width:100%; text-align:left; padding:9px 12px; border-radius:8px;
  font-size:13px; color:var(--ink); background:none; border:0; cursor:pointer}
.export-dd .dd-item:hover{background:var(--bg)}
/* мастер создания пользователя */
.wz{max-width:620px}
.wz-bar{height:4px; border-radius:3px; background:var(--bg); margin-bottom:22px; overflow:hidden}
.wz-fill{display:block; height:100%; background:var(--grad); transition:width .2s}
.wz-h{font-size:18px; font-weight:700; margin:0 0 6px}
.wz-hint{color:var(--muted); font-size:13px; margin:0 0 14px}
.wz-cards{display:grid; gap:10px; margin-bottom:8px}
.wz-card{display:block; padding:14px 16px; border:1px solid var(--border); border-radius:12px; cursor:pointer}
.wz-card:hover{border-color:var(--accent)}
.wz-card input{margin-right:8px}
.wz-card:has(input:checked){border-color:var(--accent); background:rgba(124,92,255,.06)}
.wz-card-t{font-weight:700; font-size:14px}
.wz-card-d{display:block; color:var(--muted); font-size:12.5px; margin-top:4px; padding-left:22px}
.wz-row{display:flex; gap:10px; align-items:center}
.wz-row .field{max-width:220px}
.wz-found{margin-top:12px; font-size:13px; color:var(--accent-ink)}
.wz-sum{display:grid; grid-template-columns:150px 1fr; gap:8px 14px; margin:0 0 20px; font-size:13.5px}
.wz-sum dt{color:var(--muted)}
.wz-sum dd{margin:0; font-weight:600}
.wz-nav{display:flex; align-items:center; gap:10px; margin-top:24px; padding-top:18px; border-top:1px solid var(--border)}
.wz-spacer{flex:1}
/* приглашения: форма создания */
.inv-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-bottom:16px}
.lbl-block{display:flex; flex-direction:column; gap:6px; font-size:12px; color:var(--muted); font-weight:600}
.inv-form .city-checks{margin-bottom:14px}
/* мягкое напоминание про почту */
.msg-hint{display:flex; align-items:center; justify-content:space-between; gap:14px;
  background:rgba(124,92,255,.08); border:1px solid rgba(124,92,255,.25); color:var(--ink)}
/* Без этой строки атрибут hidden на плашке не действовал (авторский display сильнее
   браузерного [hidden]{display:none}): «Скрыть на неделю» ставила куку и hidden, а
   подсказка оставалась на экране и возвращалась после перезагрузки. */
.msg-hint[hidden]{display:none}
.msg-hint .hint-actions{display:flex; align-items:center; gap:8px; flex:none}
.hint-close{border:0; background:none; color:var(--muted); font-size:18px; line-height:1;
  cursor:pointer; padding:2px 6px; border-radius:6px}
.hint-close:hover{background:var(--bg); color:var(--ink)}
/* статьи издержек: форма добавления и построчное редактирование */
.ct-add{display:flex; gap:10px; align-items:center; margin-bottom:16px}
.ct-add .field{max-width:280px}
.field-sort{max-width:90px; text-align:right}
.ct-tbl td .field{padding:6px 9px}
.ct-actions{display:flex; gap:8px; justify-content:flex-end; white-space:nowrap}
.ct-del:hover:not(:disabled){border-color:var(--danger); color:var(--danger)}
.ct-del:disabled{opacity:.45; cursor:not-allowed}
/* ручной набор смены: список штата над матрицей */
.mtx-head{display:flex; align-items:center; gap:10px; margin-bottom:12px}
.mtx-add .field-inline{min-width:230px}
/* действия по мастеру живут в меню на правый клик (title ставит скрипт, и только
   на открытой смене) — курсор подсказывает, что меню здесь есть */
.mtx .mcol[title]{cursor:context-menu}
/* колонка администратора (только в архивной смене) — отделяем от мастеров */
.mtx .mcol.is-admin{border-left:2px solid var(--border)}
.mtx .mcol.is-admin .mspec{color:var(--accent-ink)}
.mtx .mname-txt{display:block; font-weight:600; font-size:13px; padding:2px 2px; line-height:1.3; word-break:break-word}
.mtx .mspec{display:block; font-size:11px; color:var(--muted); margin-top:3px}
.mtx .mdel{position:absolute; top:3px; right:3px; border:0; background:none; color:var(--danger); cursor:pointer; font-size:12px; line-height:1}
.mtx td .cell{width:100%; border:0; border-radius:0; padding:7px 8px; text-align:right; background:var(--surface); font-variant-numeric:tabular-nums}
.mtx td .cell:focus{outline:2px solid var(--accent); outline-offset:-2px; position:relative; z-index:1}
.mtx tr.auto td, .mtx tr.auto .rl{background:var(--bg)}
/* ===== Ориентир при вводе: где именно я сейчас пишу =====
   Матрица разрослась (у каждой ставки есть двойник «без НДС»), и между крайней
   колонкой и подписью строки помещается пол-экрана. Поэтому под курсором подсвечены
   подпись строки и имя мастера, а сама строка и колонка залиты бледным — глаз ведёт
   от ячейки к подписи по сплошной полосе.
   Строку берёт на себя браузер (:focus-within), колонку в CSS выразить нечем —
   таблица знает строки, но не столбцы, поэтому ячейки столбца помечает smena.js.
   ⚠️ Красим И ячейку, И поле ввода: поле растянуто на всю ячейку и имеет свой
   непрозрачный фон, так что правило только для td не видно вообще. */
.mtx tbody tr:focus-within > td, .mtx tbody tr:focus-within .cell,
.mtx tbody td.is-col, .mtx tbody td.is-col .cell{background:var(--mtx-hl)}
.mtx tbody tr:focus-within > .rl, .mtx thead th.is-col{
  background:var(--mtx-hl-strong); color:var(--accent-ink)}
.mtx .wcell{padding:7px 10px; text-align:right; font-weight:700; font-variant-numeric:tabular-nums}
/* Сверхплан мастера: полоска до порога. Шкала — верхний включённый порог, риска — на
   первой ступени; мерить «до следующей невзятой ступени» нельзя, иначе в момент взятия
   первой полоска прыгает назад и рост читается как откат. */
.mtx .spcell{padding:8px 10px; text-align:center; vertical-align:middle}
.spbar{position:relative; display:block; height:6px; border-radius:4px; background:var(--border)}
.spbar i{position:absolute; left:0; top:0; bottom:0; border-radius:4px; background:var(--muted)}
.spbar.is-done i{background:var(--ok)}
.spbar b{position:absolute; top:-3px; width:1px; height:12px; background:var(--border-strong)}
.spcap{display:block; margin-top:5px; font-size:11px; color:var(--muted); white-space:nowrap}
.spcap.is-done{color:var(--ok); font-weight:600}
.sp-none{color:var(--muted)}
/* ===== Панель «Моя смена»: за что администратор получает то, что получает =====
   Три колонки в строке: название, сумма, пояснение под ними во всю ширину — иначе
   пояснения («план 120 000 · сделали 134 000») ломают выравнивание сумм. */
.ern-block + .ern-block{margin-top:14px; padding-top:12px; border-top:1px solid var(--border)}
.ern-who{font-weight:700; font-size:13px; margin-bottom:8px}
.ern-row{display:grid; grid-template-columns:1fr auto; gap:2px 10px; padding:5px 0}
.ern-t{font-size:13px}
.ern-v{font-weight:700; font-size:13px; font-variant-numeric:tabular-nums; text-align:right}
.ern-n{grid-column:1 / -1; font-size:11.5px; color:var(--muted); line-height:1.4}
.ern-total{display:flex; justify-content:space-between; align-items:baseline; margin-top:10px;
  padding-top:10px; border-top:1px solid var(--border); font-weight:800; font-size:14px}
.ern-total b{font-variant-numeric:tabular-nums}
.ern-note, .ern-empty{margin:12px 0 0; font-size:12px; color:var(--muted); line-height:1.5}
.ern-empty{margin:0 0 10px}
.mtx tr:last-child td, .mtx tr:last-child .rl{border-bottom:0}
.smena-cols{display:grid; grid-template-columns:1.6fr 1fr; gap:16px; margin-top:16px; align-items:start}
.smena-side{display:flex; flex-direction:column; gap:16px}
.mtx-empty{padding:44px 20px; text-align:center; color:var(--muted); border:1px dashed var(--border-strong); border-radius:12px; margin-top:2px}
.cashfact{display:flex; flex-direction:column; gap:4px; margin-top:14px; font-size:12px; font-weight:600; color:var(--muted)}
.reconcile{margin-top:10px; padding:9px 12px; border-radius:10px; font-weight:700; text-align:center; font-size:14px}
.reconcile.bad{background:rgba(224,49,49,.12); color:var(--danger)}
.reconcile.warn{background:rgba(245,159,0,.14); color:#c07a00}
.reconcile.ok{background:rgba(46,160,67,.12); color:var(--ok)}
.costline{display:grid; grid-template-columns:100px 1fr 1.2fr auto; gap:8px; align-items:center; margin-bottom:8px}
.costline .field{margin:0; padding:8px 10px}
.costdel{border:0; background:none; color:var(--danger); cursor:pointer; font-size:14px; padding:4px}
.costs-total{margin-top:6px; padding-top:10px; border-top:1px solid var(--border); font-weight:700}
.head-actions .dateform{margin-bottom:0}
.head-actions .field{height:40px; padding-top:0; padding-bottom:0}
.head-actions .btn-ghost{height:40px; padding-top:0; padding-bottom:0; display:inline-flex; align-items:center}
.smena-foot{display:flex; align-items:center; justify-content:flex-end; gap:12px; margin-top:18px; padding-top:16px; border-top:1px solid var(--border)}
.smena-foot .btn-primary{margin-top:0; padding:11px 20px}
.smena-foot .btn-ghost{padding:11px 20px}
.confirm-box{display:flex; align-items:center; gap:7px; font-size:13px; font-weight:600; margin-right:auto}
.ok-tag{color:var(--ok); font-weight:700}

/* профиль / форма аккаунта */
.kv{display:flex; justify-content:space-between; gap:12px; padding:7px 0; border-bottom:1px solid var(--border)}
.acc-form input{width:100%; padding:10px 12px; font-size:14px; border:1px solid var(--border-strong);
  border-radius:10px; margin-bottom:6px; font-family:inherit; background:var(--surface); color:var(--ink)}
.acc-form input:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,92,255,.14)}
.acc-form .helptext{font-size:11px; color:var(--muted); display:block; margin:-2px 0 6px}
.acc-form select.field{width:100%}
.check{display:flex; align-items:center; gap:8px; margin-top:14px; font-weight:600; font-size:14px; color:var(--ink)}
.check input{width:16px; height:16px}

/* пояснение-плашка */
.note-box{background:rgba(124,92,255,.06); border:1px solid var(--border);
  border-radius:12px; padding:12px 16px; font-size:13px; color:var(--muted); margin-bottom:18px; line-height:1.5}
.note-box b{color:var(--ink)}

/* ===== Адаптив ===== */
@media (max-width:900px){
  body.app{grid-template-columns:0 minmax(0,1fr)}
  .sidebar{position:fixed; left:0; top:var(--topbar-h); bottom:0; width:264px; z-index:55; height:auto;
    background:var(--surface); box-shadow:0 18px 50px rgba(25,27,46,.18)}
  html[data-sidebar="off"] .sidebar{display:none}
  .topbar{padding:0 12px}
  .user-name{display:none}
  .fresh-chip{display:none}
  .content{padding:18px 14px 40px}
  .cols{grid-template-columns:1fr}
  .wrap{padding:20px 16px 48px}
}

/* Текущий штат салона */
.staff-groups{display:flex; flex-direction:column; gap:14px}
.staff-list{display:flex; flex-wrap:wrap; gap:8px}
.staff-chip{display:inline-flex; align-items:center; gap:8px; padding:7px 12px;
  background:var(--bg); border:1px solid var(--border); border-radius:999px; font-size:13px}
.staff-chip .dot{width:9px; height:9px; border-radius:50%; flex:none; border:1px solid var(--border-strong)}
.staff-name{font-weight:600; color:var(--ink)}
.staff-seen{color:var(--muted); font-size:11px}

/* a11y: видимый фокус с клавиатуры (WCAG 2.4.7) */
a:focus-visible, button:focus-visible, summary:focus-visible, .card:focus-visible,
.side-link:focus-visible, .dd-item:focus-visible, input:focus-visible, select:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px}
/* закрытое меню-дропдаун не держим в tab-порядке/потоке */
details.dd:not([open]) .dd-menu{display:none}
/* контраст: бледную рамку-как-текст заменяем на серый */
.pager .off, .day-flag.off, .crumb-sep{color:var(--muted)}
.empty-search{padding:18px; color:var(--muted); text-align:center}

/* выравнивание кнопок в шапке (btn-primary имеет margin-top для формы — гасим в шапке) */
.head-actions .btn-primary{margin-top:0}
/* разделители-группы в дропдауне городов (наши/зарубежные/франшизы) */
.dd-group{padding:8px 12px 4px; font-size:10px; text-transform:uppercase; letter-spacing:.6px; color:var(--muted); font-weight:700}
.dd-group:not(:first-child){border-top:1px solid var(--border); margin-top:4px}
/* мультивыбор городов в форме пользователя */
.city-checks{display:flex; flex-direction:column; gap:6px; padding:6px 0}

.side-foot-link{padding:6px 10px; font-size:12px; color:var(--muted); border-radius:8px}
.side-foot-link:hover{color:var(--ink); background:var(--bg)}


a.side-city-single:hover{color:var(--accent-ink)}
.side-dd{position:relative}
.side-dd > summary{list-style:none; cursor:pointer}
.side-dd > summary::-webkit-details-marker{display:none}

/* кликабельные крошки в топбаре */
.crumb-link{color:var(--ink)}
.crumb-link:first-child{color:var(--muted)}
.crumb-link:hover{color:var(--accent-ink)}
.field-error{border-color:var(--danger); box-shadow:0 0 0 3px rgba(229,72,77,.12)}
/* строка кнопок формы (сохранить + отмена) */
.form-actions{display:flex; gap:10px; align-items:center; margin-top:16px}
.form-actions .btn-primary{margin-top:0}
.btn-danger{padding:10px 18px; border:1px solid var(--danger); border-radius:10px; font-weight:600; color:#fff; background:var(--danger); cursor:pointer; white-space:nowrap}
.btn-danger:hover{opacity:.92}
/* поле пароля: глазик + генерация */
.pw-row{display:flex; gap:8px; align-items:center}
.pw-row .field{flex:1}
.pw-hint{margin-top:6px; font-size:13px; color:var(--accent-ink); word-break:break-all}
/* онбординг нового салона (чеклист) */
.onboard{display:flex; flex-direction:column; gap:10px}
.ob-item{display:flex; align-items:center; gap:14px; padding:14px 16px; border:1px solid var(--border); border-radius:12px}
.ob-item.ob-done{background:var(--bg)}
.ob-num{width:30px; height:30px; flex:none; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:700; background:var(--bg); color:var(--muted)}
.ob-item.ob-done .ob-num{background:var(--ok); color:#fff}
.ob-body{flex:1; min-width:0}
.ob-title{font-weight:600}
.ob-skip{margin-top:16px; padding-top:14px; border-top:1px solid var(--border); display:flex; align-items:center; gap:12px; flex-wrap:wrap}
/* проверка yclients ID при создании салона */
.yc-row{display:flex; gap:8px; align-items:center}
.yc-row .field{flex:1}
.yc-result{margin-top:6px; font-size:13px}
.yc-result.ok{color:var(--ok)}
.yc-result.err{color:var(--danger)}
.yc-result.warn{color:#c98a00}
/* поиск в городских списках (мастера/услуги) */
.masters-search{display:flex; gap:8px; align-items:center; margin-bottom:12px; flex-wrap:wrap}
.masters-search .field{max-width:340px}
.bars a.bar-row{text-decoration:none; border-radius:8px; padding:6px 8px}
.bars a.bar-row:hover{background:var(--bg)}
.bars a.bar-row.is-active{background:var(--bg); font-weight:600; color:var(--accent-ink)}
/* поиск внутри дропдауна городов */
.dd-search{width:100%; margin-bottom:6px; font-size:13px}
.dd-noresult{padding:8px 12px; color:var(--muted); font-size:13px}
.citymenu{max-height:60vh; overflow:auto}
/* топбар: дропдаун юзера прижимаем в правый угол */
.spacer{flex:1 1 auto}
/* кнопка-действие в крошках топбара («+ Создать салон») */
.crumb-action{margin-left:8px; padding:5px 12px; border:1px solid var(--accent); border-radius:8px;
  font-size:13px; font-weight:600; color:var(--accent-ink); white-space:nowrap}
.crumb-action:hover{background:var(--accent); color:#fff}

/* футер сайдбара (о компании/программе) */
.side-foot{margin-top:auto; padding-top:10px; border-top:1px solid var(--border); display:flex; flex-direction:column; gap:2px}
/* дропдаун салонов раскрывается вниз, на ширину сайдбара */
.side-dd .dd-menu{position:absolute; left:0; right:0; min-width:0; z-index:60}

/* ===== Тёмная тема: оверрайды сообщений (фоны захардкожены выше) ===== */
[data-theme="dark"] .msg-error, [data-theme="dark"] .auth-err{background:rgba(229,72,77,.18); color:#ff9a9d}
[data-theme="dark"] .msg-success{background:rgba(46,201,138,.16); color:#63e2ab}

/* плашки ввода дня (были инлайн-стилями — вынесены ради тёмной темы) */
.note-warn{background:#fdecec; color:#b42318; border-color:#f3c0c0}
.note-info{background:#eef6ff; color:#1b4a7a; border-color:#cfe0f7}
[data-theme="dark"] .note-warn{background:rgba(229,72,77,.16); color:#ff9a9d; border-color:rgba(229,72,77,.35)}
[data-theme="dark"] .note-info{background:rgba(124,92,255,.14); color:#b5c6ff; border-color:rgba(124,92,255,.35)}

/* подсказка по штату в форме пользователя */
.staff-suggest{border:1px solid var(--border); border-radius:8px; margin-top:4px; overflow:hidden;
  background:var(--surface)}
.staff-suggest-row{display:block; width:100%; text-align:left; padding:8px 10px;
  background:none; border:0; cursor:pointer; font:inherit; color:inherit}
.staff-suggest-row:hover, .staff-suggest-row:focus-visible{background:rgba(124,92,255,.06)}

/* ─────────────────────────────────────────────────────────────────────────────
   VOICE — отзывы и репутация.

   Графики намеренно одноцветные. Раскрашивать серии нечем: проверка палитры
   показала, что красный (--danger) и янтарный (--warn) проекта различаются хуже
   порога — ΔE 4.6 при дейтеранопии и 13.0 даже при нормальном зрении, то есть
   соседние полосы слились бы. Длина полосы, число и подпись несут всё значение,
   а цвет остаётся одиночным акцентом там, где рядом нет конкурента.
   ───────────────────────────────────────────────────────────────────────────── */

/* плитки с числами-заголовками */
.vtiles{display:grid; grid-template-columns:repeat(auto-fit,minmax(184px,1fr)); gap:12px; margin-bottom:16px}
.vtile{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:14px 16px; display:flex; flex-direction:column; gap:4px; box-shadow:var(--shadow)}
.vtile-k{font-size:12px; color:var(--muted); font-weight:600}
.vtile-v{font-size:26px; font-weight:800; line-height:1.1; display:flex; align-items:baseline; gap:8px}
.vtile-h{font-size:11.5px; color:var(--muted)}
.vtile-pct{font-size:14px; font-weight:700; color:var(--muted)}
.vtile.is-alert .vtile-v{color:var(--danger)}

/* график */
.vchart{margin:0}
.vchart-cap{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:8px}
.vchart-t{font-weight:700; font-size:14px}
.vchart-h{font-size:12px; color:var(--muted)}
.vchart-now{margin-left:auto; font-weight:800; font-size:18px}
/* Высоту диктуют атрибуты width/height на самом теге: у SVG появляются собственные
   размеры, и height:auto выводит высоту ровно из них.

   ⚠️ Ни max-width, ни overflow:visible сюда возвращать нельзя. Предел ширины
   разъезжался с высотой — блок считался по одной ширине, рисунок по другой, — а
   overflow:visible не давал лишнему обрезаться, и подписи дат ложились на соседнюю
   панель. Размер на широких мониторах держит вытянутое соотношение viewBox. */
.vchart-svg{width:100%; height:auto; display:block}
.vchart-grid{stroke:var(--border); stroke-width:1}
.vchart-line{fill:none; stroke:var(--accent); stroke-width:2; stroke-linejoin:round; stroke-linecap:round}
.vchart-area{fill:var(--accent); opacity:.09; stroke:none}
.vchart-dot{fill:var(--accent); stroke:var(--surface); stroke-width:2}
.vchart-lbl{fill:var(--muted); font-size:11px}
.vchart-empty{padding:26px 12px; text-align:center; color:var(--muted); font-size:13px;
  border:1px dashed var(--border-strong); border-radius:10px; display:flex; flex-direction:column; gap:4px}

/* полосы салонов */
.vbar-track{flex:1; height:8px; min-width:80px; background:var(--bg); border-radius:6px; overflow:hidden}
.vbar-fill{display:block; height:100%; background:var(--accent); border-radius:6px}

/* сетка из трёх графиков */
.vgrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); gap:12px; margin-bottom:16px}

/* отзыв */
.vrev{padding:12px 0; border-bottom:1px solid var(--border)}
.vrev:last-child{border-bottom:none}
.vrev-head{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:12.5px}
.vrev-stars{font-weight:800; font-size:14px; display:inline-flex; align-items:center; gap:2px}
.vrev-star{color:var(--muted); font-size:11px}
.vrev.is-bad .vrev-stars{color:var(--danger)}
.vrev-place{font-weight:600; color:var(--accent-ink); text-decoration:none}
.vrev-place:hover{text-decoration:underline}
.vrev-author,.vrev-date{color:var(--muted)}
.vrev-answered,.vrev-open{margin-left:auto; font-size:11.5px; font-weight:700; padding:2px 8px; border-radius:20px}
.vrev-answered{color:var(--ok); background:rgba(22,163,106,.10)}
.vrev-open{color:var(--danger); background:rgba(229,72,77,.10)}
.vrev-text{margin:8px 0 0; font-size:13.5px; line-height:1.5; white-space:pre-line}
.vrev-answer{margin:8px 0 0 14px; padding-left:12px; border-left:2px solid var(--border-strong);
  font-size:12.5px; color:var(--muted); line-height:1.5; white-space:pre-line}
.vrev-answer-k{display:block; font-weight:700; font-size:11px; text-transform:uppercase;
  letter-spacing:.04em; margin-bottom:2px}

/* предупреждение о сбоях сборщика */
.vwarn{border-color:var(--warn)}
.vwarn-list{margin:8px 0 0; padding-left:18px; font-size:12.5px; color:var(--muted)}

.vpager{display:flex; align-items:center; gap:12px; justify-content:center; padding:12px 0}
/* Voice: панели складываются в столбец, между ними нужен воздух. Класс отдельный,
   чтобы не менять отступы .panel на других экранах. */
.vpanel{margin-bottom:16px}
.vpanel:last-child{margin-bottom:0}
