/* Altimabox PWA — токены и компоненты по мобильному дизайну (Altimabox Mobile.dc.html).
   Тёмная тема по умолчанию, светлая — [data-theme="light"]. Значения oklch — из хэндовера.
   Hue у всех нейтральных/акцентных токенов сдвинут с 258 на 232 (светлота L и
   насыщенность C не менялись) — на hue 258 нейтральные тона и акцент читались
   как устаревший сине-фиолетовый; 232 — более чистый сине-серый оттенок, по
   прямому требованию владельца проекта. */

:root, [data-theme="dark"] {
  --bg: oklch(0.17 0.03 232);
  --bg-elevated: oklch(0.20 0.03 232);
  --card: oklch(0.23 0.03 232);
  --card-hover: oklch(0.27 0.03 232);
  --border: oklch(0.32 0.03 232);
  --text: oklch(0.95 0.01 232);
  --text-muted: oklch(0.65 0.02 232);
  /* Насыщенность акцента снижена (0.19→0.13 и пропорционально у -soft/-text)
     — тот же оттенок и светлота, но менее «электрический» синий, паритет с
     десктопом (js/../css/styles.css --accent). */
  --accent: oklch(0.64 0.13 232);
  --accent-soft: oklch(0.30 0.055 232);
  --accent-text: oklch(0.82 0.06 232);
  --success: oklch(0.70 0.15 150);
  --success-soft: oklch(0.28 0.06 150);
  --warning: oklch(0.78 0.15 75);
  --warning-soft: oklch(0.32 0.07 75);
  --danger: oklch(0.66 0.20 25);
  --danger-soft: oklch(0.30 0.09 25);
  /* заливка плиток срочности (заказы/закупки/задачи/производство) — тем же
     приёмом, что и desktop --success-row-tint/--danger-row-tint (там это
     alpha rgba, здесь -soft непрозрачный oklch без альфы, поэтому снижаем
     интенсивность подмесом нейтрального серого). ВАЖНО: подмешивать нужно
     ахроматический серый (C=0), а НЕ var(--card) напрямую — у --card в
     тёмной теме chroma=0.03/hue=232 (лёгкий сине-серый оттенок), и color-mix
     в oklch интерполирует по КРАТЧАЙШЕЙ дуге окружности оттенков; от
     красного (hue≈25) к синему (hue≈232) кратчайший путь идёт «в другую
     сторону», через фиолетовый/пурпурный — отсюда «странные фиолетовые
     заливки» вместо ожидаемого красно-зелёного градиента. Ахроматический
     (C=0) цвет не имеет своего оттенка, поэтому не тянет интерполяцию в
     сторону. */
  --tile-tint-neutral: oklch(0.23 0 0);
  --success-tile-tint: color-mix(in oklch, var(--success-soft) 72%, var(--tile-tint-neutral) 28%);
  --danger-tile-tint: color-mix(in oklch, var(--danger-soft) 72%, var(--tile-tint-neutral) 28%);
  /* «Обработано ИИ» — фиолетовый, намеренно далёкий от всех занятых оттенков
     (синий accent, зелёный success, жёлтый warning, красный danger/срочность)
     — не путается со срочностью (оранжево-красной). Только рамка, без заливки
     и без окраски текста — см. .ai-touched ниже. */
  --ai: oklch(0.72 0.14 300);
}

[data-theme="light"] {
  --bg: oklch(0.97 0.004 232);
  --bg-elevated: oklch(1 0 0);
  --card: oklch(1 0 0);
  --card-hover: oklch(0.95 0.01 232);
  --border: oklch(0.885 0.01 232);
  --text: oklch(0.22 0.02 232);
  --text-muted: oklch(0.50 0.02 232);
  --accent: oklch(0.55 0.13 232);
  --accent-soft: oklch(0.92 0.03 232);
  --accent-text: oklch(0.45 0.11 232);
  --success: oklch(0.52 0.14 150);
  --success-soft: oklch(0.92 0.06 150);
  --warning: oklch(0.60 0.15 75);
  --warning-soft: oklch(0.93 0.07 75);
  --danger: oklch(0.55 0.20 25);
  --danger-soft: oklch(0.93 0.08 25);
  --success-tile-tint: color-mix(in oklch, var(--success-soft) 72%, var(--card) 28%);
  --danger-tile-tint: color-mix(in oklch, var(--danger-soft) 72%, var(--card) 28%);
  --ai: oklch(0.55 0.14 300);
}

* { box-sizing: border-box; }
/* Нативные чекбоксы/радио без явного accent-color берут системный AccentColor
   браузера — паритет с десктопом (там это было заметнее из-за акцентного
   цвета Windows), здесь просто для единообразия темы во всех формах. */
:root { accent-color: var(--accent); }
html, body { margin: 0; height: 100%; }
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  background: var(--bg);
  color: var(--text);
  overscroll-behavior-y: none;
}
::-webkit-scrollbar { display: none; }
input, button, select, textarea { font-family: inherit; }
button { cursor: pointer; }

/* ── app shell ── */
.app { display: flex; flex-direction: column; height: 100dvh; max-width: 480px; margin: 0 auto; position: relative; background: var(--bg); }

/* Разложенные (foldable) экраны и планшеты: внутренний дисплей близок к квадрату
   (~7-8:9), обычный узкий колонковый шелл на 480px оставляет почти половину
   ширины пустой. На таких широких/квадратных вьюпортах даём шеллу больше
   воздуха, сохраняя центрирование — не трогаем обычные телефонные пропорции. */
@media (min-width: 600px), (min-aspect-ratio: 3/4) {
  .app { max-width: 760px; }
}

.hdr {
  /* было max(54px, env(safe-area-inset-top)) — на части Android-устройств
     (standalone PWA) env(safe-area-inset-top) возвращает сильно завышенное
     значение (больше высоты статус-бара), и max() с уже немаленьким 54px-полом
     давал огромный пустой промежуток над шапкой. Складываем небольшой
     собственный отступ с safe-area аддитивно — как .tabbar делает снизу
     (max(26px, env(safe-area-inset-bottom))), только без раздутого пола. */
  flex-shrink: 0; padding: calc(14px + env(safe-area-inset-top, 0px)) 18px 10px 18px;
  display: flex; flex-direction: column; gap: 12px;
  background: var(--bg-elevated); border-bottom: 1px solid var(--border);
}
.hdr-top { display: flex; align-items: center; gap: 8px; }
.logo-mark {
  width: 22px; height: 22px; border-radius: 7px; border: 1.6px solid var(--accent);
  color: var(--accent); display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 12px; flex-shrink: 0;
}
.logo-word { font-weight: 800; font-size: 13px; letter-spacing: 0.4px; }
.hdr-title { font-size: 22px; font-weight: 800; }
.icon-btn {
  width: 32px; height: 32px; border-radius: 9px; background: var(--card);
  border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
  color: var(--text); padding: 0;
}
.back-link { display: flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 600; color: var(--text-muted); background: none; border: 0; padding: 0; }

.search { position: relative; }
.search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-muted); }
.search input {
  width: 100%; height: 38px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--card); color: var(--text); padding: 0 12px 0 34px; font-size: 14px; outline: none;
}
.search.has-refresh input { padding-right: 40px; }
.search .search-refresh { position: absolute; right: 3px; top: 50%; transform: translateY(-50%); }

/* ── scroll area ── */
.scroll { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.page { display: flex; flex-direction: column; gap: 16px; padding: 16px 16px 24px 16px; overflow-x: hidden; }

/* ── cards ── */
.card { background: var(--card); border: 1px solid var(--border); border-radius: 16px; padding: 16px; }
.card-sm { border-radius: 14px; padding: 14px; }
.card-title { font-size: 14px; font-weight: 700; }
.muted { color: var(--text-muted); }
.row-between { display: flex; justify-content: space-between; align-items: center; }

/* action banner */
.banner { display: flex; gap: 12px; padding: 13px 14px; border-radius: 14px; }
.banner-ic { width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.banner-text { font-size: 13px; font-weight: 700; line-height: 1.4; }

/* stat strip (horizontal scroll) */
/* компактные пилюли вместо больших плиток — как на десктопе: dot + подпись +
   число, вместо коробки, которая непропорционально много места занимала под
   простую статистику. */
.stat-strip { display: flex; gap: 8px; overflow-x: auto; margin: 0 -16px; padding: 0 16px; }
.stat { flex-shrink: 0; display: flex; align-items: center; gap: 7px; height: 32px; padding: 0 12px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; white-space: nowrap; }
.stat-dot { width: 7px; height: 7px; border-radius: 999px; flex-shrink: 0; }
.stat-label { font-size: 12px; color: var(--text-muted); font-weight: 600; }
.stat-value { font-size: 13px; font-weight: 800; }
.stat-value.sm { font-size: 13px; }
.stat-sub { display: none; } /* было под числом в большой плитке — в пилюле не помещается, доступно по тапу (см. dashboard.js) */

/* order row (dashboard "ближайшие сроки") */
.olist { display: flex; flex-direction: column; gap: 12px; }
/* было background:none;border:0;padding:0 — заливка срочности (color-mix,
   инлайн style) шла прямо от края до края без скругления/паддинга, отсюда
   «уродские обрубленные плитки» на фоне остальных карточек (.ocard) с их
   border-radius:14px/padding. Приведено к тому же виду карточки, что и
   .ocard/.banner. */
/* .orow — <button>, не <div>: без box-sizing:border-box и align-self:stretch
   явных браузерные квирки растяжения кнопок внутри flex-column (.olist)
   иногда не давали ширине дойти до 100% — плитка казалась уже своей рамки
   («Ближайшие сроки»), особенно заметно рядом с padding родителя. */
.orow { display: block; width: 100%; box-sizing: border-box; align-self: stretch; text-align: left; background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px; color: inherit; }
.orow-head { display: flex; justify-content: space-between; gap: 8px; }
.orow-title { font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.orow-urg { font-size: 12px; font-weight: 700; white-space: nowrap; }
.orow-sub { display: flex; justify-content: space-between; margin-top: 4px; font-size: 11.5px; color: var(--text-muted); }
.progress { height: 6px; border-radius: 3px; background: var(--border); margin-top: 6px; overflow: hidden; }
.progress > div { height: 100%; border-radius: 3px; }
.link-accent { font-size: 12px; font-weight: 700; color: var(--accent); background: none; border: 0; padding: 0; }

/* calendar */
.cal-head, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.cal-head { font-size: 10.5px; color: var(--text-muted); text-align: center; margin-bottom: 4px; }
.cal-cell { aspect-ratio: 1; display: flex; align-items: center; justify-content: center; font-size: 11px; font-family: inherit; border-radius: 7px; position: relative; border: 1.5px solid transparent; background: none; color: var(--text); cursor: pointer; padding: 0; }
.cal-cell.today { background: var(--accent-soft); color: var(--accent-text); border-color: var(--accent); }
.cal-cell.sel { border-color: var(--accent); font-weight: 700; }
.cal-dot { position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); width: 3.5px; height: 3.5px; border-radius: 50%; background: var(--danger); }
.cal-cell .cal-dot ~ .cal-dot { transform: translateX(2px); }

/* quick tiles */
.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.tile { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 8px; border-radius: 14px; border: 1px solid var(--border); background: var(--card); color: var(--text); font-size: 12px; font-weight: 700; }
.tile.accent { background: var(--accent-soft); color: var(--accent-text); border-color: transparent; }

/* orders list cards */
.ocard { display: block; width: 100%; box-sizing: border-box; align-self: stretch; text-align: left; background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 14px; color: inherit; }
.ocard-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
/* flex:1 — название забирает всё доступное место в строке (раньше было
   сжато под естественную ширину текста, соседствуя с плашкой статуса) */
.ocard-title { font-size: 14px; font-weight: 700; flex: 1; min-width: 0; }
.ocard-essence { font-size: 12.5px; color: var(--text-muted); margin-top: 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ocard-foot { display: flex; justify-content: space-between; margin-top: 6px; }
.ocard-urg { font-size: 11.5px; font-weight: 700; }
.ocard-amount { font-size: 13px; font-weight: 700; }

/* status pill / chips */
.pill { font-size: 11px; font-weight: 700; padding: 4px 9px; border-radius: 20px; white-space: nowrap; }

/* Task 2: карточка закупки, тонированная по срочности оплаты (см.
   purchaseUrgencyPct в public/js/stages.js) — фон всегда смешан из
   --success-soft/--danger-soft (оба уже приглушённые/полупрозрачные-по-духу
   токена), близок к обычному фону карточки, обычного var(--text)/
   var(--text-muted) достаточно. Halo (как у .stage-tile-label, где фон
   непрозрачный) здесь не нужен — только «размывал» текст на самых срочных
   карточках, поэтому не используется. */
/* Производство: сетка статусов по операциям */
.prod-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.prod-cell { display: flex; flex-direction: column; gap: 3px; }
.prod-cell > label { font-size: 10.5px; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: .3px; }
.prod-sel { width: 100%; border: none; border-radius: 8px; padding: 7px 6px; font-size: 12.5px; font-weight: 700; text-align: center; text-align-last: center; cursor: pointer; -webkit-appearance: none; appearance: none; }
.prod-badge { display: inline-block; text-align: center; border-radius: 8px; padding: 7px 6px; font-size: 12px; font-weight: 700; }
.prod-prio { }
.chips { display: flex; gap: 8px; overflow-x: auto; margin: 0 -16px; padding: 0 16px 2px; }
.sort-label { font-size: 11px; color: var(--text-muted); white-space: nowrap; align-self: center; flex-shrink: 0; }
.chip { flex-shrink: 0; padding: 7px 13px; border-radius: 20px; font-size: 12px; font-weight: 600; white-space: nowrap; background: var(--card); color: var(--text-muted); border: 1px solid var(--border); }
.chip.active { background: var(--accent); color: #fff; border-color: transparent; }

/* этапы заказа — плитки (заменили степпер из кружков с соединительной линией):
   плитка на каждый этап, заливка — градиент var(--danger)→var(--success) по
   прогрессу (см. stageTileStyle в order-detail.js), клик по плитке разворачивает
   её на всю ширину строки вместо отдельного попапа */
.stage-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.stage-tile { grid-column: span 1; border-radius: 14px; border: 1px solid transparent; overflow: hidden; }
.stage-tile.open { grid-column: 1 / -1; }
.stage-tile-head { display: flex; align-items: center; gap: 8px; padding: 9px 12px; cursor: pointer; height: 100%; box-sizing: border-box; }
.stage-tile-icon { flex-shrink: 0; width: 20px; height: 20px; border-radius: 50%; background: rgba(0,0,0,0.18); display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 800; }
/* текст плитки — на градиенте color-mix(--success→--danger-soft), который на
   участках со сплошным --success (текущая/финальная плитка) даёт средний по
   светлоте фон, где обычного var(--text) недостаточно для контраста. Фикс:
   var(--text) + halo противоположной полярности (тёмный по умолчанию/dark-тема,
   светлый в [data-theme="light"]) — читаемо на всём диапазоне градиента.
   Ещё не достигнутые этапы (i > curIdx) теперь без заливки (bg: transparent —
   см. stageTileStyle/pStageTileColors) — halo применяется безусловно, но там
   не мешает: цвет halo совпадает с фоном под прозрачной плиткой, поэтому
   фактически невидим. */
.stage-tile-label, .stage-tile-icon { color: var(--text); text-shadow: 0 1px 2px rgba(0,0,0,0.6), 0 0 4px rgba(0,0,0,0.4); }
[data-theme="light"] .stage-tile-label, [data-theme="light"] .stage-tile-icon { text-shadow: 0 1px 2px rgba(255,255,255,0.6), 0 0 4px rgba(255,255,255,0.4); }
.stage-tile-label { flex: 1; font-size: 11.5px; font-weight: 700; line-height: 1.25; }
.stage-tile.current .stage-tile-label { font-weight: 800; }
.stage-tile-chevron { flex-shrink: 0; color: inherit; opacity: 0.6; display: flex; transition: transform 0.15s; }
.stage-tile-chevron.open { transform: rotate(90deg); }
.stage-tile-detail { padding: 10px 10px 12px; border-top: 1px solid rgba(0,0,0,0.12); }

/* meta grid */
.meta-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.meta { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 12px; }
.meta-label { font-size: 10.5px; color: var(--text-muted); font-weight: 600; }
.meta-value { font-size: 13.5px; font-weight: 700; margin-top: 4px; }

/* fields */
.field-label { font-size: 10.5px; font-weight: 700; color: var(--text-muted); margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.4px; }
/* Аккордеон — независимое сворачивание/разворачивание карточек (заказ/закупка/
   задача), паритет с desktop .card-h.accordion — каждая карточка сворачивается
   сама по себе, без ограничения «открыта только одна». */
.field-label.accordion { cursor: pointer; display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.field-label.accordion .accordion-chevron { transition: transform .15s; }
.card-sm.collapsed > *:not(.field-label) { display: none; }
.card-sm.collapsed > .field-label.accordion .accordion-chevron { transform: rotate(-90deg); }
.card-sm details { border-top: 1px solid var(--border); }
.card-sm details:first-of-type { border-top: none; }
.card-sm details summary { cursor: pointer; padding: 8px 0; font-size: 13.5px; font-weight: 600; list-style: none; }
.card-sm details summary::-webkit-details-marker { display: none; }
.card-sm details summary::before { content: '▸ '; color: var(--text-muted); }
.card-sm details[open] summary::before { content: '▾ '; }
.select, .input, .textarea {
  width: 100%; border: 1px solid var(--border); background: var(--bg); color: var(--text);
  border-radius: 10px; padding: 10px 12px; font-size: 14px; outline: none;
}
.textarea { resize: vertical; min-height: 66px; line-height: 1.5; }
/* «Обработано ИИ» (OCR-коррекция и т.п.) — только рамка, без заливки и без
   окраски текста внутри, см. --ai выше. */
.ai-touched { border-color: var(--ai) !important; }
/* Всё, что ВЫЗЫВАЕТ ИИ, — лавандовое (правило проекта, паритет с desktop
   .ai-action в css/styles.css): узнаётся по var(--ai) и не путается ни с
   обычным действием, ни со срочностью. Поля, куда ИИ подставил значение,
   помечаются отдельно — .ai-touched выше, только рамка. */
.ai-action { background: color-mix(in oklch, var(--ai) 14%, transparent) !important;
  color: var(--ai) !important; border-color: var(--ai) !important; }
.ai-action:disabled { opacity: .5; }
/* Иконка ассистента в шапке — тот же цвет, но без заливки: в ряду остальных
   иконок заливка выбивалась бы. */
.icon-btn.ai-action { background: transparent !important; border-color: transparent !important; }
/* Ссылка на событие в ответе ассистента — открывает заказ/закупку/задачу
   (см. views/assistant.js linkifyRefs). Паритет с desktop .ai-ref. */
.ai-ref { color: var(--ai); border-bottom: 1px dashed var(--ai); font-weight: 600; }

/* Всплывающие подсказки ИИ (правый верхний угол) — паритет с desktop
   #aiToastWrap в css/styles.css. Ниже модалок, но выше содержимого страниц. */
.ai-toast-wrap { position: fixed; top: 60px; right: 12px; z-index: 450; display: flex;
  flex-direction: column; gap: 8px; align-items: flex-end;
  max-width: min(340px, calc(100vw - 24px)); pointer-events: none; }
.ai-toast-wrap > * { pointer-events: auto; }
.ai-toast { width: 100%; background: var(--card); border: 1px solid var(--ai);
  border-left: 3px solid var(--ai); border-radius: 12px;
  box-shadow: 0 10px 26px rgba(0,0,0,.3); overflow: hidden; }
.ai-toast-hdr { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 7px 10px; background: color-mix(in oklch, var(--ai) 14%, transparent);
  border-bottom: 1px solid var(--border); }
.ai-toast-title { font-weight: 700; font-size: 12px; color: var(--ai); }
.ai-toast-x { background: none; border: none; color: var(--text-muted); font-size: 13px;
  line-height: 1; padding: 2px 4px; }
.ai-toast-body { padding: 9px 11px; font-size: 12.5px; line-height: 1.5; white-space: pre-wrap; }
.ai-toast-body.dim { color: var(--text-muted); }
.ai-toast-body.err { color: var(--danger); }
.ai-toast-foot { padding: 0 11px 9px; display: flex; justify-content: flex-end; }
.ai-toast-off { background: none; border: none; color: var(--text-muted); font-size: 11px;
  text-decoration: underline; padding: 2px 0; }
/* Свёрнутая кнопка возврата — остаётся в углу после отключения. */
.ai-toast-reopen { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
  border-radius: 20px; font-size: 11.5px; font-weight: 600; border: 1px solid var(--ai);
  background: color-mix(in oklch, var(--ai) 14%, transparent); color: var(--ai);
  box-shadow: 0 4px 14px rgba(0,0,0,.2); }
/* Подсказки отключены — та же кнопка, приглушённая: состояние видно сразу. */
.ai-toast-reopen.off { opacity: .7; border-style: dashed; }
/* .claude-hint не имеет своей рамки (в отличие от .input/.field) — общего
   правила выше (border-color без border) недостаточно, нужна своя рамка. */
.claude-hint.ai-touched { border: 1px solid var(--ai); border-radius: 8px; padding: 8px 10px; }
/* Заголовок карточки выписки (контрагент) и šifra — как .claude-hint выше,
   у них нет собственной рамки, общего border-color-override недостаточно. */
.ocard-title.ai-touched { border: 1px solid var(--ai); border-radius: 6px; padding: 1px 6px; }
.ocard-essence .ai-touched { border: 1px solid var(--ai); border-radius: 6px; padding: 0 4px; }

/* dropzone */
.dropzone { border: 1.5px dashed var(--border); border-radius: 14px; padding: 20px; display: flex; flex-direction: column; align-items: center; gap: 6px; color: var(--text-muted); }
.dropzone .mono { font-family: monospace; font-size: 11.5px; text-align: center; }

/* notifications */
.notif { display: flex; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--border); }
.notif-dot { width: 9px; height: 9px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
.notif-text { font-size: 13.5px; line-height: 1.4; }
.notif-time { font-size: 11.5px; color: var(--text-muted); margin-top: 3px; }

/* workflow card */
.wf-history { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.wf-item { font-size: 12px; color: var(--text-muted); border-left: 2px solid var(--border); padding-left: 8px; }
.wf-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* buttons */
.btn { border: 0; border-radius: 12px; padding: 12px; font-size: 14px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.btn-primary { background: var(--accent); color: #fff; }
.btn-outline { background: transparent; border: 1px solid var(--border); color: var(--text); }
.btn-danger { background: var(--danger-soft); color: var(--danger); }
.btn-sm { padding: 8px 12px; font-size: 12.5px; border-radius: 10px; }

/* sticky action bar (order detail) */
.sticky-bar { flex-shrink: 0; padding: 10px 16px max(30px, env(safe-area-inset-bottom)) 16px; background: var(--bg-elevated); border-top: 1px solid var(--border); display: flex; gap: 8px; }
.sticky-bar .btn-primary { flex: 1; }
.sticky-bar .icon-secondary { width: 46px; display: flex; align-items: center; justify-content: center; border-radius: 12px; border: 1px solid var(--border); background: transparent; color: var(--text); }

/* tab bar */
.tabbar { flex-shrink: 0; display: flex; padding: 8px 8px max(26px, env(safe-area-inset-bottom)) 8px; background: var(--bg-elevated); border-top: 1px solid var(--border); }
.tab { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; color: var(--text-muted); background: none; border: 0; position: relative; }
.tab.active { color: var(--accent); }
.tab-label { font-size: 10.5px; font-weight: 600; }
.tab-badge { position: absolute; top: -2px; right: 26px; width: 7px; height: 7px; border-radius: 50%; background: var(--danger); }
/* «к последним сообщениям» — как в Telegram, видна только когда прокрутили историю вверх */
.chat-jump-btn { position: fixed; bottom: 96px; right: 20px; width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border); background: var(--card); color: var(--text); display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 14px rgba(0,0,0,.25); z-index: 20; transition: opacity .15s, transform .15s; }
.chat-jump-btn.hidden { opacity: 0; pointer-events: none; transform: translateY(6px); }
/* всплывающее уведомление о новом сообщении чата (правый нижний угол, клик — открыть беседу) */
.chat-toast-stack { position: fixed; right: 16px; bottom: 96px; z-index: 60; display: flex; flex-direction: column-reverse; gap: 8px; max-width: min(300px, calc(100vw - 32px)); }
.chat-toast { pointer-events: auto; cursor: pointer; background: var(--card); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.3); padding: 10px 12px; }
.chat-toast .ct-title { font-weight: 700; font-size: 12.5px; margin-bottom: 2px; }
.chat-toast .ct-body { font-size: 12.5px; color: var(--text-muted); white-space: pre-wrap; word-break: break-word; }
/* поле/блок, подменённые фоновой синхронизацией заказа правкой другого
   пользователя (см. applyRemoteUpdate в views/order-edit.js) — паритет с
   desktop css/styles.css .field-updated-remote */
.field-updated-remote { box-shadow: 0 0 0 2px var(--warning) inset !important; border-radius: 8px; transition: box-shadow .2s; }

/* login */
.login { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 16px; padding: 24px; }
.login-logo { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 8px; }
.login-logo .logo-mark { width: 40px; height: 40px; border-radius: 12px; font-size: 20px; border-width: 2px; }
.login-logo .logo-word { font-size: 24px; }
.login h1 { font-size: 18px; font-weight: 700; text-align: center; margin: 0; }
.login-remember { display: flex; align-items: center; gap: 9px; font-size: 13.5px; color: var(--text-muted); cursor: pointer; user-select: none; padding: 2px 2px; }
.login-remember input { width: 18px; height: 18px; cursor: pointer; accent-color: var(--accent); }
.login .err { color: var(--danger); font-size: 13px; font-weight: 600; text-align: center; min-height: 18px; }

/* toast */
.toast { position: fixed; left: 50%; bottom: 90px; transform: translateX(-50%); background: var(--card); border: 1px solid var(--border); color: var(--text); padding: 10px 16px; border-radius: 12px; font-size: 13px; font-weight: 600; box-shadow: 0 8px 24px rgba(0,0,0,0.3); z-index: 50; max-width: 90%; text-align: center; }
.toast.err { border-color: var(--danger); color: var(--danger); }

/* модальное подтверждение (замена ненадёжного window.confirm в PWA) */
.confirm-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 80; display: flex; align-items: center; justify-content: center; padding: 24px; }
.confirm-box { background: var(--card); border: 1px solid var(--border); border-radius: 16px; padding: 20px; width: 100%; max-width: 340px; box-shadow: 0 12px 40px rgba(0,0,0,0.4); }
.confirm-msg { font-size: 14px; line-height: 1.4; color: var(--text); margin-bottom: 18px; white-space: pre-line; }
.confirm-actions { display: flex; gap: 10px; }
.confirm-actions .btn { flex: 1; }

.spinner { width: 26px; height: 26px; border: 3px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; margin: 40px auto; }
@keyframes spin { to { transform: rotate(360deg); } }
.empty { text-align: center; color: var(--text-muted); font-size: 13px; padding: 40px 20px; }

/* ── order editor (калькулятор) ── */
.oe { gap: 12px; }
.oe-name { font-size: 16px; font-weight: 700; }
.oe-tabs { display: flex; gap: 8px; }
.oe-lines { display: flex; flex-direction: column; gap: 10px; margin-bottom: 8px; }
.oe-line { position: relative; }
.oe-del { position: absolute; top: 8px; right: 8px; width: 26px; height: 26px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg); color: var(--text-muted); font-size: 16px; line-height: 1; }
.oe-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.oe-field > label { font-size: 11px; color: var(--text-muted); font-weight: 600; }
/* Склад: количество листов больше 0 — лёгкая подсветка поля (паритет с
   десктопом), и предупреждения по мин. остатку (все металлы): оранжевый —
   вплотную к порогу, красный — ниже порога. */
.input.wh-has-stock { background: var(--success-soft); border-color: var(--success); color: var(--text); font-weight: 600; }
.muted.wh-area-orange { color: var(--warning); font-weight: 700; }
.muted.wh-area-red { color: var(--danger); font-weight: 700; }
/* краска: осталось меньше 2кг — подсветить, чтобы вовремя дозаказать */
.input.wh-area-orange-field { border-color: var(--warning); color: var(--warning); font-weight: 600; }
.oe-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.oe-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; }
.oe-props { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 8px; }
.oe-chk { display: flex; align-items: center; gap: 6px; font-size: 13px; margin-bottom: 6px; }
.oe-mini { font-size: 11.5px; margin-top: 2px; }
.oe-add { width: 100%; }
.oe-result { position: sticky; bottom: 0; }
.oe-rrow { display: flex; justify-content: space-between; font-size: 13px; padding: 3px 0; }
.oe-sum { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.oe-sum th { text-align: left; color: var(--text-muted); font-weight: 600; padding: 4px 6px; border-bottom: 1px solid var(--border); }
.oe-sum td { padding: 4px 6px; border-bottom: 1px solid var(--border); }
.oe-in { }

/* .hidden использовался повсеместно (oe-props, oe-round, oe-coat, вкладки
   oe-tabs и т.д.) через classList.toggle, но самого CSS-правила не было —
   переключаемые элементы никогда фактически не скрывались. */
.hidden { display: none !important; }

/* ── инструменты: калькулятор металла/гибки ── */
/* переключатель металл/гибка — заметный сегмент-контрол (не мелкие чипы,
   которые терялись рядом с остальными чипами на странице) */
.tool-seg { display: flex; gap: 4px; background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 4px; margin-bottom: 4px; }
.tool-seg button { flex: 1; border: none; background: transparent; color: var(--text-muted); font-family: inherit; font-weight: 700; font-size: 13px; padding: 11px 6px; border-radius: 11px; }
.tool-seg button.active { background: var(--accent); color: #fff; }

.tool-result-val { font-size: 19px; font-weight: 800; }
.tool-result.accent .tool-result-val { color: var(--accent-text); }
/* overflow:hidden, не auto — зум/пан теперь свой (pointer events на самом
   svg), а не системный скролл контейнера */
.tool-viz-wrap { overflow: hidden; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 8px; touch-action: none; }
.tool-viz-wrap svg { display: block; width: 100%; height: auto; touch-action: none; }
.tool-check-banner { padding: 10px 14px; border-radius: 10px; font-weight: 700; font-size: 12.5px; margin-bottom: 10px; border: 1px solid var(--border); }
.tool-check-banner.ok { background: var(--success-soft); border-color: var(--success); color: var(--success); }
.tool-check-banner.fail { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.tool-badge { display: inline-block; padding: 1px 6px; border-radius: 5px; font-size: 9.5px; font-weight: 700; }
.tool-badge.ok { background: var(--success-soft); color: var(--success); border: 1px solid var(--success); }
.tool-badge.fail { background: var(--danger-soft); color: var(--danger); border: 1px solid var(--danger); }

/* ── sections / drawer ── */
.sec-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; margin-bottom: 4px; }
.sec-title { font-size: 22px; font-weight: 800; }
.drawer-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 60; display: flex; align-items: flex-end; }
.drawer { width: 100%; max-width: 480px; margin: 0 auto; background: var(--bg-elevated); border-radius: 18px 18px 0 0; padding: 8px 16px max(20px, env(safe-area-inset-bottom)); border-top: 1px solid var(--border); }
.drawer-grip { width: 40px; height: 4px; border-radius: 2px; background: var(--border); margin: 8px auto 14px; }
.drawer-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.drawer-item { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 16px 8px; border-radius: 14px; background: var(--card); border: 1px solid var(--border); color: var(--text); font-size: 12.5px; font-weight: 600; }
.stbl, .rate-matrix { width: 100%; border-collapse: collapse; font-size: 12px; }
.stbl th, .rate-matrix th { text-align: center; color: var(--text-muted); font-weight: 600; padding: 5px 6px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.stbl td { padding: 5px 6px; border-bottom: 1px solid var(--border); text-align: center; }
.stbl td:first-child { text-align: left; }
.rate-matrix td { padding: 2px; }
.rate-matrix input { width: 56px; padding: 4px 6px; font-size: 11px; }

/* ── Себестоимость по накладным + тумблер обработки Claude (форма заказа) ── */
.cost-card { margin-top: 12px; }
.oe-cost-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.oe-cost-h .t { font-weight: 700; font-size: 14px; }
.cost-sub { font-weight: 500; font-size: 11px; color: var(--text-muted); margin-left: 4px; }
.cost-rows .oe-rrow.good b { color: var(--success); }
.cost-rows .oe-rrow.warn b { color: #cc7722; }
.cost-rows .oe-rrow.bad b { color: var(--danger); }
.cost-dim { color: var(--text-muted); font-size: 11px; font-weight: 400; }
.cost-meta { margin-top: 8px; font-size: 11px; color: var(--text-muted); line-height: 1.45; }
/* Свёрнутая разбивка накладных — паритет с десктопом css/styles.css
   .cost-meta-fold (см. public/js/cost-panel.js renderMeta). */
.cost-meta-fold > summary { cursor: pointer; list-style: none; color: var(--text-muted); user-select: none; }
.cost-meta-fold > summary::-webkit-details-marker { display: none; }
.cost-meta-fold > summary::before { content: '▸ '; display: inline-block; }
.cost-meta-fold[open] > summary::before { content: '▾ '; }
.cost-meta-body { margin-top: 4px; }
.cost-flags { margin-top: 5px; font-size: 11px; color: #cc7722; line-height: 1.4; }

/* Тумблер Claude — штатный лавандовый ИИ-цвет (var(--ai), паритет с десктопом
   js/cost-panel.js/css/styles.css), не фирменный оранжевый Claude. */
.claude-toggle { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border);
  background: transparent; border-radius: 999px; padding: 4px 10px 4px 7px; cursor: pointer;
  color: var(--text-muted); font-weight: 600; font-size: 11.5px; transition: all .15s; }
.claude-mark { width: 15px; height: 15px; flex-shrink: 0; transition: transform .2s; }
.claude-toggle.on { color: var(--ai); border-color: var(--ai); background: color-mix(in oklch, var(--ai) 14%, transparent); }
.claude-toggle.on .claude-mark { transform: rotate(15deg); }
.claude-box { margin-top: 11px; padding-top: 10px; border-top: 1px dashed var(--border); }
.claude-hint { font-size: 12.5px; line-height: 1.5; white-space: pre-wrap; min-height: 18px; margin-bottom: 9px; }
.claude-hint.dim { color: var(--text-muted); }
.claude-hint.err { color: var(--danger); }
