:root {
  /* Палитра и типографика — в духе Apple/iOS: системный синий акцент,
     нейтральный серый (без лилового оттенка), плотный почти-чёрный
     текст для контраста, светло-серая "групповая" подложка вместо
     цветной. Шрифт — системный San Francisco (macOS/iOS), с понятным
     фоллбэком на других системах. */
  --brand: #0071e3;
  --brand-dark: #0060df;
  --brand-light: #e8f0fe;
  --brand-mid: #5ea1ff;
  --ink-900: #1d1d1f;
  --ink-800: #1d1d1f;
  --ok: #34c759;
  --ok-light: #e3f8ea;
  --danger: #ff3b30;
  --danger-light: #ffece9;
  --warn: #ff9500;
  --warn-light: #fff1de;
  --paper: #f5f5f7;
  --border: #d2d2d7;
  --text: #1d1d1f;
  --text-muted: #6e6e73;
  --text-on-dark-muted: #a1a1a6;

  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 22px;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.06);
  --shadow-md: 0 6px 18px rgba(0,0,0,.10);
  --shadow-lg: 0 20px 48px rgba(0,0,0,.20);

  --dur: .18s;
  --dur-slow: .32s;
  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(0, 0, .2, 1);

  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--paper); color: var(--text); font-size: 15px; line-height: 1.47;
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; letter-spacing: -.01em;
}

:focus { outline: none; }
:focus-visible { outline: 2.5px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

@keyframes fadeInUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes scaleIn { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: scale(1); } }
@keyframes slideUpSheet { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: translateY(0); } }
@keyframes pulseRing { 0% { box-shadow: 0 0 0 0 rgba(255,59,48,.35); } 70% { box-shadow: 0 0 0 8px rgba(255,59,48,0); } 100% { box-shadow: 0 0 0 0 rgba(255,59,48,0); } }

/* ============================================================
   ШАПКА (админ)
   ============================================================ */
.topbar {
  background: var(--ink-900); color: #fff;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--sp-5); height: 56px; gap: var(--sp-4);
  position: sticky; top: 0; z-index: 10; box-shadow: var(--shadow-sm);
}
.brand { font-weight: 700; letter-spacing: .02em; font-size: 16px; display: flex; align-items: center; gap: var(--sp-2); white-space: nowrap; }
.brand-mark { color: var(--brand-mid); font-size: 20px; }
.tabs { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; flex: 1 1 auto; min-width: 0; }
.tabs::-webkit-scrollbar { display: none; }
.tab-btn {
  background: transparent; border: none; color: var(--text-on-dark-muted); padding: 10px 16px;
  font-size: 13.5px; cursor: pointer; border-bottom: 3px solid transparent; font-weight: 600;
  white-space: nowrap; transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease);
  border-radius: 4px 4px 0 0;
}
.tab-btn:hover { color: #fff; background: rgba(255,255,255,.06); }
.tab-btn.active { color: #fff; border-bottom-color: var(--brand-mid); }
.topbar-right { display: flex; align-items: center; gap: var(--sp-3); font-size: 13px; color: var(--text-on-dark-muted); white-space: nowrap; }

main { max-width: 1200px; margin: 0 auto; padding: var(--sp-5) var(--sp-5) 60px; }
.tab-panel { display: none; }
.tab-panel.active { display: block; animation: fadeInUp var(--dur-slow) var(--ease-out); }

h2 { font-size: 17px; margin: 0 0 var(--sp-4); color: var(--ink-800); font-weight: 700; }
h3 { font-size: 13px; margin: var(--sp-4) 0 var(--sp-2); color: var(--ink-800); font-weight: 700; text-transform: uppercase; letter-spacing: .02em; }

.card {
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-5);
  box-shadow: var(--shadow-sm); transition: box-shadow var(--dur) var(--ease);
}
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); align-items: start; }
@media (max-width: 900px) { .grid-2 { grid-template-columns: 1fr; } }

label { display: block; margin-bottom: var(--sp-3); font-size: 12.5px; color: var(--text-muted); font-weight: 600; }
label input, label select, label textarea {
  display: block; width: 100%; margin-top: 4px; padding: 9px 11px; border: 1.5px solid var(--border);
  border-radius: var(--r-sm); font-size: 14px; font-family: inherit; color: var(--text); background: #fff;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
label input:hover, label select:hover, label textarea:hover { border-color: var(--brand-mid); }
label input:focus, label select:focus, label textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(0,113,227,.18);
}
label.row { display: flex; gap: var(--sp-4); }
label.row span { flex: 1; font-weight: 600; }
label.checkbox { display: flex; align-items: center; gap: var(--sp-2); cursor: pointer; }
label.checkbox input { width: auto; margin: 0; accent-color: var(--brand); }

.dims-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-3); }
.options-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px var(--sp-3); margin-bottom: var(--sp-3); }
.stage-checklist { max-height: 260px; overflow-y: auto; border: 1.5px solid var(--border); border-radius: var(--r-sm); padding: var(--sp-2) var(--sp-3); grid-template-columns: 1fr 1fr; }
.route-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.route-chip { background: var(--brand-light); color: var(--brand-dark); font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 20px; }
.route-note { font-size: 12px; color: var(--text-muted); background: var(--brand-light); border-radius: var(--r-sm); padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); }

@media (max-width: 560px) {
  .dims-fields, .options-grid { grid-template-columns: 1fr; }
  label.row { flex-direction: column; gap: var(--sp-2); }
}

/* ============================================================
   КНОПКИ
   ============================================================ */
.btn {
  background: var(--brand-light); border: 1.5px solid var(--border); color: var(--ink-800);
  padding: 10px 16px; border-radius: var(--r-sm); font-weight: 700; font-size: 13.5px; cursor: pointer;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn:hover { background: #d6e7ff; box-shadow: var(--shadow-sm); }
.btn:active { transform: scale(.97); }
.btn-primary { background: var(--brand); border-color: var(--brand-dark); color: #fff; box-shadow: 0 2px 8px rgba(0,113,227,.28); }
.btn-primary:hover { background: var(--brand-dark); box-shadow: 0 4px 14px rgba(0,113,227,.38); }
.btn-ghost { background: transparent; border: 1.5px solid #48484a; color: #f2f2f7; }
.btn-ghost:hover { background: rgba(255,255,255,.1); border-color: #6e6e73; }
/* Вторичная кнопка на СВЕТЛОЙ подложке (карточки, модалки) — .btn-ghost
   рассчитан на тёмный фон (топбар) и даёт почти невидимый белый текст на
   белой карточке; для светлого фона нужен именно этот вариант. */
.btn-outline { background: #fff; border: 1.5px solid var(--border); color: var(--ink-800); }
.btn-outline:hover { background: var(--paper); border-color: var(--brand-mid); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none !important; box-shadow: none !important; }
.btn-small { padding: 5px 10px; font-size: 12px; }
.btn-big { padding: 15px 18px; font-size: 15px; width: 100%; margin-bottom: var(--sp-2); border-radius: var(--r-md); min-height: 50px; }

@media (hover: none) { .btn:hover { box-shadow: none; } }

.calc-result { margin-top: var(--sp-4); border-top: 2px solid var(--border); padding-top: var(--sp-4); animation: fadeInUp var(--dur-slow) var(--ease-out); }

/* ============================================================
   ТАБЛИЦЫ
   ============================================================ */
table.data-table { width: 100%; border-collapse: collapse; margin-bottom: var(--sp-2); }
table.data-table th, table.data-table td { border: 1px solid var(--border); padding: 9px 10px; text-align: left; font-size: 13px; }
table.data-table th { background: var(--brand-light); color: var(--ink-800); font-size: 11.5px; text-transform: uppercase; letter-spacing: .03em; font-weight: 700; }
table.data-table.small th, table.data-table.small td { padding: 5px 8px; font-size: 12px; }
table.data-table tbody tr { transition: background var(--dur) var(--ease); }
table.data-table tbody tr:hover { background: #f5f5f7; }
table.profiles-table td.profile-cell { font-weight: 700; color: var(--brand-dark); white-space: nowrap; }
/* Правка 04.09: размеры и названия деталей — крупнее и жирнее шапки
   таблицы (это то, что реально читают в цеху, не заголовки колонок);
   и визуальная группировка строк раскроя профиля по сечению трубы —
   жирная граница сверху при смене сечения. */
table.profiles-table td.profile-name-cell { font-size: 13.5px; font-weight: 700; color: var(--ink-900); }
table.profiles-table td.profile-size-cell { font-size: 15.5px; font-weight: 800; color: var(--ink-900); }
table.profiles-table td.profile-code-cell { font-weight: 800; color: var(--ink-900); }
table.profiles-table td.profile-qty-cell { font-weight: 800; color: var(--ink-900); }
table.profiles-table tr.profile-group-start td { border-top: 2.5px solid var(--ink-800); }
.blank-table td.blank-size { font-size: 14.5px; font-weight: 800; color: var(--ink-900); }

@media (max-width: 640px) {
  table.data-table:not(.small) { display: block; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch; }
}

.blanks { display: flex; flex-direction: column; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.blank {
  border: 2px solid var(--ink-800); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); background: #fff;
  transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.blank:hover { box-shadow: var(--shadow-md); }
.blank-top { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px dashed var(--border); padding-bottom: var(--sp-2); margin-bottom: var(--sp-2); font-size: 12px; }
.blank-no { font-weight: 700; color: var(--ink-800); }
.blank-queue { color: var(--danger); font-weight: 700; }
.blank-title { font-size: 14px; font-weight: 700; text-align: center; margin: 2px 0 4px; color: var(--ink-900); }
.blank-sub { font-size: 11.5px; color: var(--text-muted); text-align: center; margin-bottom: var(--sp-2); }
.blank-table { margin-bottom: 0; }

.notes-box { background: var(--warn-light); border: 1.5px solid var(--warn); padding: var(--sp-3) var(--sp-3); border-radius: var(--r-sm); font-size: 12.5px; margin-top: var(--sp-2); color: #9a5b00; animation: fadeInUp var(--dur-slow) var(--ease-out); }
/* Правка 22.09: пометка "брак с заказа №Х" — привязана к КОНКРЕТНОЙ
   позиции (order_items.defect_origin), не ко всему заказу — иначе при
   добавлении ещё позиции в тот же заказ на брак она тоже получала бы
   пометку. Не путать с notes-box (то для калькулятора/каталога). */
.defect-origin-tag { font-size: 11px; font-weight: 700; color: #9a5b00; margin-top: 2px; }

/* --- Лента истории заказа --- */
.history-timeline { display: flex; flex-direction: column; gap: 2px; margin-top: var(--sp-2); }
.history-event {
  display: flex; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm);
  transition: background var(--dur) var(--ease); font-size: 13px; align-items: flex-start;
}
.history-event:hover { background: var(--paper); }
.history-event-icon {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto; display: flex; align-items: center;
  justify-content: center; font-size: 13px; background: var(--brand-light); color: var(--brand-dark); margin-top: 1px;
}
.history-event-icon.ok { background: var(--ok-light); color: var(--ok); }
.history-event-icon.danger { background: var(--danger-light); color: var(--danger); }
.history-event-icon.warn { background: var(--warn-light); color: var(--warn); }
.history-event-body { flex: 1 1 auto; min-width: 0; }
.history-event-title { font-weight: 600; color: var(--ink-800); }
.history-event-meta { color: var(--text-muted); font-size: 12px; margin-top: 1px; }
.history-empty { color: var(--text-muted); font-size: 13px; padding: var(--sp-3) 0; }

.order-edit-bar { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin: var(--sp-2) 0 var(--sp-4); }
.order-edit-bar input[type="date"] { padding: 7px 10px; border: 1.5px solid var(--border); border-radius: var(--r-sm); font-family: inherit; font-size: 13px; }

/* ============================================================
   ДАШБОРД (Обзор) — для директора/администратора
   ============================================================ */
.kpi-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--sp-3); }
@media (max-width: 900px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); } }
.kpi-card {
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-4);
  box-shadow: var(--shadow-sm); animation: fadeInUp var(--dur-slow) var(--ease-out);
}
.kpi-value { font-size: 30px; font-weight: 700; color: var(--ink-900); line-height: 1.1; letter-spacing: -.02em; }
.kpi-value.danger { color: var(--danger); }
.kpi-value.warn { color: var(--warn); }
.kpi-value.ok { color: var(--ok); }
.kpi-label { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; font-weight: 600; }

.bar-chart { display: flex; flex-direction: column; gap: var(--sp-3); }
.bar-row { display: grid; grid-template-columns: 140px 1fr 34px; align-items: center; gap: var(--sp-3); font-size: 13px; }
.bar-row-label { color: var(--ink-800); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 10px; background: var(--paper); border-radius: 6px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--brand); border-radius: 6px; transition: width var(--dur-slow) var(--ease); }
.bar-row-count { text-align: right; font-weight: 700; color: var(--ink-800); }
.chart-empty { color: var(--text-muted); font-size: 13px; padding: var(--sp-3) 0; }

.rank-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.rank-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) 0; border-bottom: 1px solid var(--paper); font-size: 13px; }
.rank-row:last-child { border-bottom: none; }
.rank-medal { width: 24px; height: 24px; border-radius: 50%; background: var(--brand-light); color: var(--brand-dark); font-weight: 700; font-size: 11.5px; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.rank-row:nth-child(1) .rank-medal { background: #fff1de; color: #b45309; }
.rank-row:nth-child(2) .rank-medal { background: #f0f0f2; color: #6e6e73; }
.rank-row:nth-child(3) .rank-medal { background: #ffe9db; color: #b25d1f; }
.rank-name { flex: 1 1 auto; font-weight: 600; color: var(--ink-800); }
.rank-stats { color: var(--text-muted); font-size: 12px; white-space: nowrap; }

/* ============================================================
   КАНБАН (админ) — карточка = ЗАДАЧА (у позиции может быть сразу
   несколько параллельных задач в разных колонках одновременно)
   ============================================================ */
/* Настоящий перетаскиваемый скроллбар прокрутки канбана СВЕРХУ (пункт 4,
   24.09) — по факту ровно то же самое, что обычный горизонтальный
   скроллбар браузера под колонками, только продублирован сверху, чтобы
   не нужно было долистывать глазами всю доску вниз, чтобы его найти.
   Синхронизирован с реальной прокруткой .board в обе стороны (app.js):
   тянешь этот — крутится доска; крутишь доску (колёсиком/пальцем/родным
   скроллбаром снизу) — двигается и этот. */
.board-top-scrollbar { margin-bottom: var(--sp-2); padding: 4px; }
.board-top-scrollbar-track {
  height: 14px; background: var(--paper); border-radius: 8px; position: relative; cursor: pointer;
}
.board-top-scrollbar-thumb {
  position: absolute; top: 0; left: 0; height: 100%; background: var(--ink-800); border-radius: 8px;
  cursor: grab; min-width: 40px; transition: background var(--dur-slow) var(--ease);
}
.board-top-scrollbar-thumb:hover, .board-top-scrollbar-thumb.dragging { background: var(--ink-900); }
.board-top-scrollbar-thumb.dragging { cursor: grabbing; }

.board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(175px, 1fr); gap: var(--sp-2); overflow-x: auto; padding: 4px 4px 12px; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; align-items: start; scrollbar-width: none; -ms-overflow-style: none; }
/* Правка 24.09 (по просьбе убрать нижнюю полосу совсем) — родной
   скроллбар браузера снизу скрыт визуально, сама прокрутка (колёсиком,
   пальцем, программно через board.scrollLeft) продолжает работать как
   обычно — просто без видимой полосы внизу. Управление прокруткой
   остаётся только через полосу сверху (#boardTopScrollbar). */
.board::-webkit-scrollbar { display: none; }
/* Правка 22.09: раньше колонка росла по высоте вместе со всеми карточками
   внутри неё, и вся страница вытягивалась вниз — заголовок этапа ("Раскрой
   металла" и т.п.) в тёмной шапке колонки при этом уезжал вверх за
   пределы экрана при скролле. Теперь у колонки фиксированная максимальная
   высота, а прокручивается только список карточек ВНУТРИ неё — заголовок
   остаётся на месте всегда. Сама доска по-прежнему скроллится вбок
   (overflow-x: auto на .board), это уже было и не менялось. */
.board-col {
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg);
  scroll-snap-align: start; box-shadow: var(--shadow-sm); overflow: hidden;
  display: flex; flex-direction: column; max-height: calc(100vh - 170px); min-height: 200px;
}
.board-col-head {
  background: var(--ink-800); color: #fff; padding: 10px 12px; font-weight: 600; font-size: 12.5px;
  display: flex; justify-content: space-between; align-items: center; flex-shrink: 0;
}
.board-col-head span:last-child { background: rgba(255,255,255,.16); padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 700; }
.board-col-body { padding: var(--sp-2); display: flex; flex-direction: column; gap: var(--sp-2); min-height: 60px; overflow-y: auto; flex: 1; -webkit-overflow-scrolling: touch; }
.card-lyuk {
  border: 1px solid var(--border); border-left: 4px solid var(--brand); border-radius: var(--r-sm); padding: var(--sp-2) var(--sp-3);
  background: #ffffff; font-size: 12.5px; transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease); animation: fadeInUp var(--dur-slow) var(--ease-out);
}
.card-lyuk:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.card-lyuk.urgent { border-left-color: var(--danger); }
.card-lyuk .order-no { font-weight: 700; color: var(--ink-800); }
.card-lyuk .dims { color: var(--text-muted); margin: 3px 0; }
.card-lyuk .wc-taken-admin { color: var(--brand-dark); font-weight: 600; }
.card-lyuk .actions { display: flex; gap: 6px; margin-top: var(--sp-2); flex-wrap: wrap; }
.card-progress { height: 5px; border-radius: 4px; background: var(--border); overflow: hidden; margin: 5px 0; }
.card-progress > div { height: 100%; background: var(--ok); border-radius: 4px; transition: width var(--dur-slow) var(--ease); }

/* Колонка "Готово к отгрузке" — визуально спокойнее и "завершённо":
   зелёный акцент вместо нейтрально-тёмного, чтобы сразу отличалась от
   рабочих колонок и не выглядела как ещё один активный участок. */
.board-col-head-done { background: var(--ok); }
.board-col-done { border-color: var(--ok-light); }
.card-lyuk-done { border-left-color: var(--ok); background: var(--ok-light); }
.card-lyuk-done .actions button { opacity: .85; }
.card-lyuk-waiting { border-left-color: var(--warn); border-left-style: dashed; opacity: .85; }
/* Подсветка всех этапов ОДНОГО заказа при наведении на любую его
   карточку (могут быть в разных колонках одновременно) — по просьбе
   заказчика: "чтобы при наведении на заказ выделялись все его этапы". */
.card-lyuk.order-highlight { box-shadow: 0 0 0 2.5px var(--brand), var(--shadow-md); transform: translateY(-1px); }
@media (max-width: 640px) { .board { grid-auto-columns: minmax(78vw, 1fr); } }

/* Канбан — расширяем зону видимости столбцов за пределы обычного max-width
   контента (1200px у <main>): чем шире доступная область, тем больше
   этапов видно одновременно без горизонтального скролла. На широких
   экранах вкладка "вырывается" на всю ширину окна (классический приём
   full-bleed), с собственными отступами по краям. */
@media (min-width: 1300px) {
  #tab-board {
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding-left: var(--sp-5);
    padding-right: var(--sp-5);
    box-sizing: border-box;
  }
}

.status-pill { padding: 3px 10px; border-radius: 20px; font-size: 11px; font-weight: 700; display: inline-block; }
.status-new { background: var(--brand-light); color: var(--brand-dark); }
.status-in_production { background: var(--warn-light); color: var(--warn); }
.status-ready { background: var(--ok-light); color: var(--ok); }
.status-shipped { background: #e5e5ea; color: #48484a; }
.status-cancelled { background: var(--danger-light); color: var(--danger); }
.status-bitrix { background: var(--brand-light); color: var(--brand-dark); }
.priority-2 { background: var(--warn-light); color: var(--warn); padding: 2px 8px; border-radius: 20px; font-size: 10.5px; font-weight: 700; }

/* ============================================================
   ЗАКАЗЫ / ИСТОРИЯ — сетка карточек вместо плоской таблицы: срочность,
   срок и статус видны сразу, без построчного сканирования
   ============================================================ */
.orders-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: var(--sp-4); }
.order-tile {
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-4);
  box-shadow: var(--shadow-sm); transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
  display: flex; flex-direction: column; gap: var(--sp-2); animation: fadeInUp var(--dur-slow) var(--ease-out);
}
.order-tile:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.order-tile.urgent { border: 2px solid var(--danger); }
.order-tile-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.order-tile-number { font-weight: 700; font-size: 15.5px; color: var(--ink-900); }
.order-tile-badges { display: flex; gap: 6px; flex-wrap: wrap; }
.order-tile-customer { font-size: 13.5px; color: var(--text-muted); font-weight: 600; }
.order-tile-progress { display: flex; align-items: center; gap: var(--sp-2); margin: 2px 0; }
.order-tile-progress .card-progress { flex: 1; }
.order-tile-progress span { font-size: 11px; color: var(--text-muted); font-weight: 600; white-space: nowrap; }
.order-tile-meta { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2); margin: var(--sp-1) 0; padding-top: var(--sp-2); border-top: 1px solid var(--paper); }
.order-tile-meta-4 { grid-template-columns: repeat(4, 1fr); }
.order-tile-meta-item { display: flex; flex-direction: column; gap: 1px; }
.order-tile-meta-item span { font-size: 10.5px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .02em; }
.order-tile-meta-item b { font-size: 13px; color: var(--ink-800); font-weight: 700; }
.order-tile-meta-item.overdue b { color: var(--danger); }
.order-tile-meta-item.soon b { color: var(--warn); }
.order-tile-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-1); }


/* ============================================================
   ВХОД (login.html) — теперь логин/пароль + выбор специализации
   ============================================================ */
body.login-body {
  background: linear-gradient(160deg, var(--ink-900) 0%, var(--brand-dark) 100%);
  min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: var(--sp-5);
}
.login-screen { width: 100%; max-width: 420px; text-align: center; }
.login-logo { color: #fff; font-size: 34px; font-weight: 650; letter-spacing: .08em; animation: fadeInUp var(--dur-slow) var(--ease-out); }
.login-sub { color: #e5e5ea; font-size: 13.5px; margin-bottom: 26px; }
.login-card { background: #fff; border-radius: var(--r-xl); padding: var(--sp-5); box-shadow: var(--shadow-lg); animation: scaleIn var(--dur-slow) var(--ease-out); text-align: left; }
.login-card h2 { text-align: center; }
.login-field { margin-bottom: var(--sp-4); }
.login-field label { margin-bottom: 6px; }
.login-submit { width: 100%; margin-top: var(--sp-2); }
.login-error { color: var(--danger); font-size: 13px; text-align: center; margin-top: var(--sp-3); min-height: 18px; font-weight: 600; animation: fadeIn var(--dur) var(--ease); }

/* Выбор вида люка — настоящая плиточная сетка (как иконки приложений):
   2 колонки, квадратные карточки с иконкой сверху и подписью снизу, а не
   список строк. Только для удобства/на будущее — какие именно участки
   доступны сотруднику, решает администратор (см. вкладка "Сотрудники"). */
.category-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-3); margin-bottom: var(--sp-4); }
@media (max-width: 360px) { .category-grid { grid-template-columns: 1fr 1fr; gap: var(--sp-2); } }
.category-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  aspect-ratio: 1 / 1; padding: 14px 8px;
  border: 1.5px solid var(--border); border-radius: var(--r-lg); background: var(--paper); cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  text-align: center; font-family: inherit; position: relative;
}
.category-tile:hover { border-color: var(--brand); background: var(--brand-light); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.category-tile:active { transform: scale(.97); }
.category-tile.ready { border-color: var(--brand-mid); }
.category-tile.selected { border-color: var(--brand); background: var(--brand-light); box-shadow: 0 0 0 2px var(--brand) inset; }
.category-tile-icon {
  width: 44px; height: 44px; border-radius: 13px; background: var(--brand); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 21px; flex: 0 0 auto;
}
.category-tile-label { font-size: 12.5px; font-weight: 600; color: var(--ink-800); line-height: 1.3; }
.category-tile .soon { position: absolute; top: 6px; right: 6px; font-size: 9.5px; font-weight: 700; color: var(--text-muted); background: var(--border); padding: 2px 7px; border-radius: 20px; }

.link-back { background: none; border: none; color: var(--brand-dark); font-weight: 600; cursor: pointer; margin-bottom: var(--sp-2); padding: 6px 0; transition: opacity var(--dur) var(--ease); }
.link-back:hover { opacity: .7; }

/* ============================================================
   ПЛАНШЕТ РАБОЧЕГО (worker.html)
   ============================================================ */
body.worker-body { background: var(--paper); }
.worker-topbar {
  background: var(--ink-900); color: #fff; display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--sp-5); height: 56px; position: sticky; top: 0; z-index: 5; box-shadow: var(--shadow-sm); gap: var(--sp-3);
}
.worker-who { display: flex; align-items: center; gap: var(--sp-3); font-weight: 700; font-size: 15px; flex-wrap: wrap; min-width: 0; }
.worker-who #workerName { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 34vw; }
.worker-topbar-actions { display: flex; align-items: center; gap: var(--sp-2); }
.stage-section-title { color: var(--ink-800); font-size: 15px; margin: 26px 0 var(--sp-3); border-bottom: 2px solid var(--brand-light); padding-bottom: var(--sp-2); font-weight: 700; }
.worker-main { max-width: 1100px; margin: 0 auto; padding: var(--sp-5) var(--sp-4) 80px; }

@media (max-width: 480px) {
  .worker-topbar { padding: 0 var(--sp-3); }
  .worker-main { padding: var(--sp-4) var(--sp-3) 80px; }
}

.stage-bar {
  display: flex; gap: var(--sp-2); overflow-x: auto; padding: var(--sp-3) var(--sp-4); background: var(--ink-800);
  position: sticky; top: 56px; z-index: 4; scrollbar-width: thin; -webkit-overflow-scrolling: touch;
  box-shadow: 0 4px 10px rgba(0,0,0,.12);
}
.stage-pill {
  flex: 0 0 auto; background: rgba(255,255,255,.09); border: 1.5px solid rgba(255,255,255,.14); color: var(--text-on-dark-muted);
  padding: 8px 13px; border-radius: 20px; font-size: 12.5px; font-weight: 600; cursor: pointer;
  white-space: nowrap; display: flex; align-items: center; gap: 6px; min-height: 36px;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.stage-pill:hover { background: rgba(255,255,255,.18); color: #fff; }
.stage-pill:active { transform: scale(.96); }
.stage-pill.own { background: var(--brand-light); border-color: var(--brand-light); color: var(--brand-dark); font-weight: 700; }
.stage-pill.own:hover { background: #d6e7ff; }
.stage-pill.active { outline: 2px solid #fff; outline-offset: -1px; box-shadow: var(--shadow-md); }
.stage-badge {
  background: var(--danger); color: #fff; font-size: 11px; font-weight: 650; min-width: 19px; height: 19px;
  border-radius: 20px; display: inline-flex; align-items: center; justify-content: center; padding: 0 5px;
}
.stage-pill.own .stage-badge { background: var(--brand-dark); }

.view-only-banner {
  background: var(--warn-light); border: 1.5px solid var(--warn); color: #9a5b00; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md);
  font-size: 13px; font-weight: 600; margin-bottom: var(--sp-4); animation: fadeInUp var(--dur-slow) var(--ease-out);
}
/* Пункт 5: явно видно, на каком участке сотрудник сейчас находится — не
   только маленькая пилюля в полосе сверху (может уехать за экран). */
.current-stage-banner {
  background: var(--brand-light); border: 1.5px solid var(--brand-mid); color: var(--brand-dark); padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md); font-size: 14px; margin-bottom: var(--sp-4); animation: fadeInUp var(--dur-slow) var(--ease-out);
}
.current-stage-banner b { font-size: 15px; }

.worker-empty { text-align: center; color: var(--text-muted); font-size: 18px; padding: 90px 20px; animation: fadeIn var(--dur-slow) var(--ease); }

.urgent-dot {
  background: var(--danger); color: #fff; font-weight: 650; font-size: 11px; padding: 4px 10px;
  border-radius: 20px; letter-spacing: .02em; flex: 0 0 auto; white-space: nowrap; animation: pulseRing 2s var(--ease) infinite;
}
.priority-badge { background: var(--warn-light); color: var(--warn); font-weight: 650; font-size: 10.5px; padding: 3px 9px; border-radius: 20px; }

.type-columns { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--sp-4); margin-bottom: var(--sp-6); }
.type-column {
  flex: 1 1 460px; min-width: 280px; max-width: 760px; background: #f5f5f7; border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-4);
}
.type-column-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.type-column-title { font-weight: 650; font-size: 14.5px; color: var(--ink-800); }
.type-column-finish { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
/* Раньше карточки шли одна под одной (1 ряд = 1 сделка) даже когда места
   по ширине навалом — на планшете это лишний скролл. Теперь плитка: сама
   подбирает, сколько карточек влезает в ряд, минимум ~230px на карточку,
   на узком экране (мобильный) естественно схлопывается в одну колонку. */
.type-column-body { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: var(--sp-3); align-items: start; }

@media (max-width: 480px) {
  .type-column { min-width: 100%; max-width: 100%; padding: var(--sp-3); }
  .type-columns { gap: var(--sp-3); }
}

.worker-card {
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-4);
  box-shadow: var(--shadow-sm); transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
  animation: fadeInUp var(--dur-slow) var(--ease-out);
}
.worker-card:hover { box-shadow: var(--shadow-md); }
.worker-card.urgent { border: 2px solid var(--danger); }
.worker-card.mine { border-color: var(--brand); background: var(--brand-light); }
/* Задача "ждёт" (часть зависимостей ещё не готова) — видна, но взять
   нельзя: приглушённый пунктирный стиль, явно отличается от обычной
   готовой-к-взятию карточки, чтобы не выглядело как баг/зависание. */
.worker-card.waiting { border-style: dashed; background: #fafafa; opacity: .92; }
.wc-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; gap: 6px; flex-wrap: wrap; }
.wc-order { font-weight: 650; color: var(--ink-800); font-size: 14px; }
.wc-urgent { background: var(--danger); color: #fff; font-size: 10.5px; font-weight: 650; padding: 3px 9px; border-radius: 20px; }
.wc-shape { font-weight: 700; font-size: 13.5px; color: var(--brand-dark); margin-bottom: var(--sp-2); }
.wc-stage-name {
  font-size: 13.5px; color: var(--ink-800); font-weight: 700; margin-bottom: var(--sp-2); padding: 4px 10px;
  background: var(--brand-light); border-radius: var(--r-sm); display: inline-block;
}
.wc-drawing { background: #fff; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; margin-bottom: var(--sp-2); }
.wc-dims { font-size: 14px; font-weight: 700; color: var(--ink-900); margin-bottom: 2px; }
.wc-meta { font-size: 12px; color: var(--text-muted); margin-bottom: var(--sp-3); }
/* Размер люка под заголовком "Раскрой профиля" в модалке сотрудника —
   размер уже показан выше в карточке, но если список этапов/примечаний
   длинный, до этой таблицы приходится долго скроллить — дублируем
   размер прямо здесь же, рядом с деталями раскроя. */
.section-dims { font-size: 13px; font-weight: 700; color: var(--ink-900); margin: -4px 0 8px; }
.wc-taken { font-size: 12.5px; color: var(--danger); font-weight: 700; margin-bottom: var(--sp-3); }
.wc-waiting { font-size: 12px; color: var(--warn); font-weight: 600; margin-bottom: var(--sp-3); }
.wc-video-required {
  background: var(--warn-light); border: 1.5px dashed var(--warn); border-radius: var(--r-sm); padding: var(--sp-3);
  font-size: 12.5px; font-weight: 600; color: #9a5b00; margin-bottom: var(--sp-3); text-align: center;
}
.wc-video-input { display: block; width: 100%; margin-top: var(--sp-2); font-size: 12px; }
.wc-video-progress { font-size: 12px; color: var(--brand-dark); font-weight: 600; margin-bottom: var(--sp-3); text-align: center; }
.wc-video-ok { font-size: 12.5px; color: var(--ok); font-weight: 600; margin-bottom: var(--sp-3); }
/* Правка 08.09 — прогресс видео поштучно на партию */
.wc-video-progress-bar { height: 5px; border-radius: 4px; background: var(--border); overflow: hidden; margin-bottom: 4px; }
.wc-video-progress-bar > div { height: 100%; background: var(--brand); border-radius: 4px; transition: width var(--dur-slow) var(--ease); }
.wc-video-count { font-size: 12px; color: var(--text-muted); font-weight: 600; margin-bottom: var(--sp-2); }
.unit-video-block { margin-bottom: var(--sp-3); }
/* Правка от 24.09 — блок видео у сотрудника свёрнут по умолчанию
   (<details>), чтобы не приходилось долго скроллить до раскроя, когда
   видео много (частичная отгрузка большой партии). */
.video-collapse { margin-bottom: var(--sp-3); }
.video-collapse summary {
  cursor: pointer; font-weight: 700; font-size: 14px; padding: var(--sp-2) 0;
  color: var(--ink-800); list-style: none;
}
.video-collapse summary::-webkit-details-marker { display: none; }
.video-collapse summary::before { content: '▸ '; }
.video-collapse[open] summary::before { content: '▾ '; }
.unit-video-label { font-size: 12.5px; font-weight: 700; color: var(--ink-800); margin-bottom: 4px; }
.wc-chain-note {
  background: var(--warn-light); border: 1.5px solid var(--warn); border-radius: var(--r-sm); padding: 6px 10px;
  font-size: 12.5px; font-weight: 700; color: #9a5b00; margin-bottom: var(--sp-3);
}
.wc-progress { height: 5px; border-radius: 4px; background: var(--border); overflow: hidden; margin-bottom: var(--sp-2); }
.wc-progress > div { height: 100%; background: var(--warn); border-radius: 4px; transition: width var(--dur-slow) var(--ease); }
.wc-actions { display: flex; flex-direction: column; }
.wc-actions .btn { min-height: 44px; }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,.45); display: flex; align-items: center;
  justify-content: center; z-index: 50; padding: var(--sp-5); animation: fadeIn var(--dur) var(--ease);
}
.modal-backdrop[hidden] { display: none; }
.modal {
  background: #fff; border-radius: var(--r-xl); width: 100%; max-width: 380px;
  max-height: 88vh; display: flex; flex-direction: column; overflow: hidden;
  box-shadow: var(--shadow-lg); animation: scaleIn var(--dur-slow) var(--ease-out);
}
.modal.modal-wide { max-width: 640px; }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-5) var(--sp-5) 0; flex: 0 0 auto; }
.modal-head h3 { margin: 0; font-size: 16px; color: var(--ink-800); text-transform: none; letter-spacing: normal; }
.modal-x {
  background: var(--brand-light); border: none; color: var(--brand-dark); width: 34px; height: 34px;
  border-radius: 50%; font-size: 15px; font-weight: 700; cursor: pointer; flex: 0 0 auto; line-height: 1;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.modal-x:hover { background: var(--brand); color: #fff; transform: rotate(90deg); }
.modal-scroll { padding: var(--sp-4) var(--sp-5); overflow-y: auto; flex: 1 1 auto; min-height: 0; -webkit-overflow-scrolling: touch; }
.modal-footer { padding: 0 var(--sp-5) var(--sp-5); flex: 0 0 auto; }
.transfer-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.detail-body h3 { margin-top: var(--sp-4); }
.detail-drawing { background: #fff; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; margin-bottom: var(--sp-2); }
.detail-progress { height: 8px; border-radius: 6px; background: var(--border); overflow: hidden; margin: var(--sp-2) 0; }
.detail-progress > div { height: 100%; background: var(--ok); border-radius: 6px; transition: width var(--dur-slow) var(--ease); }
.detail-video { width: 100%; max-height: 360px; border-radius: var(--r-md); background: #000; margin-bottom: var(--sp-2); }
.graph-tasks { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.graph-task { border: 1.5px solid var(--border); border-radius: var(--r-sm); padding: 6px 10px; font-size: 12px; flex: 1 1 140px; }
.graph-task.done { border-color: var(--ok); background: var(--ok-light); }
.graph-task.claimed { border-color: var(--warn); background: var(--warn-light); }
.graph-task.pending { border-color: var(--brand-mid); background: var(--brand-light); }
.graph-task.waiting { border-color: var(--warn); border-style: dashed; background: #fffaf2; }
.graph-task.locked { opacity: .55; }
.graph-task .gt-name { font-weight: 700; display: block; }
.graph-task .gt-status { color: var(--text-muted); }

/* Сетка люков партии (08.09) — чипы №1, №2... в модалке "Управление
   этапами" у администратора: серый — видео нет, синий — есть видео (не
   отгружен), зелёный — отгружен. Клик по синему/зелёному открывает видео. */
.unit-video-grid { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--sp-3); }
.unit-video-chip {
  border: 1.5px solid var(--border); border-radius: var(--r-sm); padding: 4px 9px; font-size: 12px; font-weight: 700;
  color: var(--text-muted); background: #fff;
}
.unit-video-chip.ready { border-color: var(--brand-mid); background: var(--brand-light); color: var(--brand-dark); cursor: pointer; }
.unit-video-chip.shipped { border-color: var(--ok); background: var(--ok-light); color: var(--ok); cursor: pointer; }
.unit-video-chip.missing { opacity: .6; }

/* Правка от 24.09 — "частичная готовность на этапах". Карточка-агрегат
   у сотрудника (партия целиком, с числами вместо одной кнопки) и
   модалка работы с конкретными номерами люков внутри партии. */
.wc-unit-counts { display: flex; flex-wrap: wrap; gap: 6px; margin: var(--sp-2) 0; }
.unit-count-chip { font-size: 11.5px; font-weight: 700; padding: 3px 9px; border-radius: 20px; border: 1.5px solid var(--border); }
.unit-count-chip.ready { border-color: var(--brand-mid); background: var(--brand-light); color: var(--brand-dark); }
.unit-count-chip.mine { border-color: var(--warn); background: var(--warn-light); color: #9a5b00; }
.unit-count-chip.others { border-color: var(--border); background: var(--paper); color: var(--text-muted); }
.unit-count-chip.done { border-color: var(--ok); background: var(--ok-light); color: var(--ok); }

.unit-stage-section { border-top: 1px solid var(--paper); padding: var(--sp-3) 0; }
.unit-stage-section:first-child { border-top: none; padding-top: 0; }
.unit-stage-section-title { font-weight: 700; font-size: 13.5px; margin-bottom: var(--sp-2); }
.unit-stage-claim-row { display: flex; gap: var(--sp-2); align-items: center; }
.unit-stage-claim-row input[type=number] { width: 80px; padding: 8px 10px; border: 1.5px solid var(--border); border-radius: var(--r-sm); font-size: 14px; font-family: inherit; }

.unit-chip-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.unit-chip {
  border: 1.5px solid var(--warn); background: var(--warn-light); color: #9a5b00; border-radius: var(--r-sm);
  padding: 6px 10px; font-size: 12.5px; font-weight: 700; display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.unit-chip.has-video { border-color: var(--ok); background: var(--ok-light); color: var(--ok); }
.unit-chip .unit-video-input { font-size: 10px; max-width: 100px; }

@media (max-width: 560px) {
  .modal-backdrop { padding: 0; align-items: flex-end; }
  .modal, .modal.modal-wide { max-width: 100%; width: 100%; max-height: 92vh; border-radius: var(--r-xl) var(--r-xl) 0 0; animation: slideUpSheet var(--dur-slow) var(--ease-out); }
  .modal-head, .modal-scroll, .modal-footer { padding-left: var(--sp-4); padding-right: var(--sp-4); }
}

/* ============================================================
   GSAP "вау"-эффекты (public/js/effects.js) — частицы конфетти для
   момента отгрузки заказа. Позиционируются и двигаются через GSAP
   (по x/y от точки появления), здесь только базовый вид самой частицы.
   ============================================================ */
.confetti-piece {
  position: fixed; width: 8px; height: 8px; top: 0; left: 0; z-index: 999;
  pointer-events: none; will-change: transform, opacity;
}


/* 29.10: вид люка на карточке заказа */
.order-tile-hatch { font-size: 13px; color: var(--brand-dark, #1f4e79); }

/* 26.10: атрибут hidden не должен перебиваться display у label/div и т.п. */
[hidden] { display: none !important; }
