/* Оформление мини-аппа: мастерская, а не мессенджер.

   Цвета не берутся из темы Telegram намеренно. Приложение должно выглядеть
   одинаково у всех и читаться как панель станка: тёмный стол с сеткой,
   детали цвета PEI-панели, оранжевый нагрев сопла на действиях, мятный
   остывший пластик на доходах, красный обрыв прутка на удалении.

   Числа, даты и номера записей — моноширинные: их сравнивают глазами
   столбиком, и разная ширина цифр этому мешает. */
:root {
  --bed: #14171a;       /* стол принтера — фон */
  --plate: #1d2126;     /* PEI-панель — карточка */
  --field: #232830;     /* поле ввода */
  --line: #2c333b;      /* линия слоя, граница */
  --pla: #e8e4dc;       /* белый филамент — основной текст */
  --dim: #8b939c;       /* вторичный текст */
  --hot: #ff5a1f;       /* сопло под нагревом — главные действия */
  --hot-2: #ffab1f;     /* верх градиента нагрева */
  --cool: #5fd0c0;      /* остывший пластик — доход */
  --runout: #e04a3f;    /* обрыв прутка — удаление */
  --chamber: #0f1215;   /* дно камеры — каретка и техстроки */
  --ink: #2a1206;       /* тёмный текст поверх нагрева */

  --sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Consolas, monospace;
  --cond: "IBM Plex Sans Condensed", var(--sans);
  --tabbar-h: 60px;
  color-scheme: dark;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Атрибут hidden скрывает элемент только браузерным правилом display:none,
   а любое авторское правило с display его перебивает — шторка с display:flex
   иначе висела бы на экране всегда, приглушая контент и перехватывая нажатия. */
[hidden] { display: none !important; }

body {
  margin: 0; background: var(--bed); color: var(--pla);
  font: 15px/1.45 var(--sans);
  padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 14px);
}

/* Сетка стола 26 мм: гаснет к низу, чтобы не спорить с содержимым. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    linear-gradient(rgba(255, 255, 255, .028) 1px, transparent 1px) 0 0 / 100% 26px,
    linear-gradient(90deg, rgba(255, 255, 255, .028) 1px, transparent 1px) 0 0 / 26px 100%;
  -webkit-mask-image: linear-gradient(#000 0, #000 32%, transparent 80%);
  mask-image: linear-gradient(#000 0, #000 32%, transparent 80%);
}

#shell, #denied, .sheet, .toast { position: relative; z-index: 1; }

:focus-visible { outline: 2px solid var(--hot-2); outline-offset: 2px; }

.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* --- Шапка: панель управления станком --- */
.machine {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  padding: calc(12px + env(safe-area-inset-top)) 14px 12px;
  background: linear-gradient(180deg, #1a1e23, #15181c);
  border-bottom: 1px solid var(--line);
}
.machine__mark {
  width: 36px; height: 36px; flex: none; display: grid; place-items: center;
  border-radius: 8px;
  background: linear-gradient(158deg, var(--hot-2), var(--hot) 46%, #c8360a);
  box-shadow: 0 0 0 1px #3a2016, 0 6px 15px rgba(255, 90, 31, .3);
}
.machine__mark svg {
  width: 20px; height: 20px; fill: none; stroke: var(--ink);
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.machine__name {
  font-family: var(--cond); font-weight: 700; font-size: 21px;
  letter-spacing: .14em; line-height: 1;
}
.machine__state {
  font-family: var(--mono); font-size: 11px; color: var(--dim);
  letter-spacing: .03em; margin-top: 5px;
}
.machine__led {
  width: 6px; height: 6px; border-radius: 1px; background: var(--cool);
  display: inline-block; margin-right: 6px; vertical-align: 1px;
  box-shadow: 0 0 7px var(--cool); animation: led 2.6s infinite;
}
@keyframes led { 50% { opacity: .3; box-shadow: none; } }
.machine__tally { margin-left: auto; text-align: right; }
.machine__tally span {
  font-family: var(--mono); font-size: 10.5px; color: var(--dim); letter-spacing: .05em;
}
.machine__tally b {
  display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 15px; font-weight: 600; color: var(--cool); margin-top: 3px;
}
.machine__tally b.down { color: var(--hot-2); }

#screens { padding: 14px 12px 0; }
.screen { display: flex; flex-direction: column; gap: 12px; }
/* Содержимое этих блоков собирает app.js: расстояния держит контейнер,
   иначе отчёт и расчёт слипались бы в одну простыню. */
#reportBody, #calcResult, #modelInfo, #adminBlock, #sheetBody {
  display: flex; flex-direction: column; gap: 12px;
}

/* Подзаголовок раздела — не капслок, а маркер слоя слева. */
.section-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 600; color: var(--pla); margin: 6px 2px -2px;
}
.section-title::before {
  content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--hot); flex: none;
}

/* --- Панель = напечатанная деталь: сверху торец из линий слоёв --- */
.panel {
  position: relative; overflow: hidden;
  background: var(--plate); border: 1px solid var(--line); border-radius: 10px;
  padding: 20px 14px 15px; display: flex; flex-direction: column; gap: 12px;
}
.panel::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 7px;
  background: repeating-linear-gradient(180deg, rgba(255, 255, 255, .07) 0 1px, transparent 1px 3px);
}

.cards { display: flex; flex-direction: column; gap: 9px; }
.hint { color: var(--dim); font-size: 13px; line-height: 1.55; margin: 0; }

/* --- Формы --- */
.field { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.field__label { font-size: 12px; color: var(--dim); }
.field__label i { font-style: normal; opacity: .7; }
.field-row { display: flex; gap: 10px; }

input[type="text"], input[type="number"], input[type="date"], input[type="time"] {
  width: 100%; padding: 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--field); color: var(--pla); font: inherit; min-width: 0;
  transition: border-color .15s, box-shadow .15s;
}
input[inputmode="decimal"], input[type="number"], input[type="date"], input[type="time"] {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
input::placeholder { color: #5c646d; }
input:focus { outline: none; border-color: var(--hot); box-shadow: 0 0 0 3px rgba(255, 90, 31, .15); }
input::-webkit-calendar-picker-indicator { filter: invert(.65); }

/* --- Кнопки --- */
.btn {
  padding: 13px 14px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--field); color: var(--pla);
  font: inherit; font-weight: 500; cursor: pointer; width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 9px;
}
.btn svg {
  width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.btn:disabled { opacity: .55; }

/* Главное действие = выдавленный пруток: нагрев сверху вниз, блик по кромке,
   диагональная штриховка экструзии и оранжевое свечение под кнопкой. */
.btn--primary {
  position: relative; overflow: hidden; border: 0; color: var(--ink); font-weight: 600;
  background: linear-gradient(180deg, var(--hot-2), var(--hot) 52%, #e24a12 88%, #c2380c);
  box-shadow: 0 7px 20px rgba(255, 90, 31, .3), inset 0 1px 0 rgba(255, 255, 255, .5);
}
.btn--primary::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, .11) 0 2px, transparent 2px 9px);
}
.btn--primary:active { transform: translateY(1px); }

/* --- Переключатель периода: одна калибровочная линейка --- */
.segmented {
  display: flex; gap: 0; overflow-x: auto; scrollbar-width: none;
  border: 1px solid var(--line); border-radius: 9px; background: var(--plate);
}
.segmented::-webkit-scrollbar { display: none; }
.segmented--wrap { flex-wrap: nowrap; }
.segmented button {
  flex: 1 0 auto; min-width: 62px; padding: 11px 12px;
  border: 0; border-right: 1px solid var(--line); border-radius: 0;
  background: transparent; color: var(--dim);
  font: inherit; font-size: 13px; white-space: nowrap; cursor: pointer;
  transition: background .15s, color .15s;
}
.segmented button:last-child { border-right: 0; }
/* Внутри детали линейка светлее фона, иначе сливается с панелью. */
.panel .segmented { background: var(--field); }
.segmented button.is-active {
  color: var(--ink); font-weight: 600;
  background: linear-gradient(180deg, var(--hot-2), var(--hot));
}

/* --- Два материала: расход и продажа --- */
.switch-row { display: flex; gap: 8px; }
.pill {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 12px 8px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--plate); color: var(--dim);
  font: inherit; font-size: 14.5px; font-weight: 600; cursor: pointer;
  transition: color .16s, border-color .16s, background .16s;
}
.pill::before {
  content: ""; width: 9px; height: 9px; border-radius: 2px; background: #4a525b;
  flex: none; transition: background .16s, box-shadow .16s;
}
.pill.is-active {
  color: var(--pla); border-color: #4a3125;
  background: linear-gradient(180deg, #2a1d16, #221a15);
}
.pill.is-active::before { background: var(--hot); box-shadow: 0 0 8px var(--hot); }
[data-form="sale"].is-active, [data-records="sales"].is-active {
  border-color: #1f4a44; background: linear-gradient(180deg, #16292a, #152225);
}
[data-form="sale"].is-active::before, [data-records="sales"].is-active::before {
  background: var(--cool); box-shadow: 0 0 8px var(--cool);
}

/* --- Категории: выбранная деталь обведена юбкой --- */
.toggles { display: flex; flex-wrap: wrap; gap: 7px; }
.toggles button {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 11px; border: 1px solid var(--line); border-radius: 7px;
  background: transparent; color: var(--dim); font: inherit; font-size: 13.5px;
  cursor: pointer; transition: .15s;
}
.toggles button::before {
  content: ""; width: 8px; height: 8px; border-radius: 2px; background: #525a63; transition: .15s;
}
.toggles button.is-on {
  color: var(--pla); border-color: var(--hot); background: rgba(255, 90, 31, .1);
  box-shadow: 0 0 0 3px rgba(255, 90, 31, .09);
}
.toggles button.is-on::before { background: var(--hot); }

/* --- Строка с тумблером --- */
.row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 4px 0; }
.row--switch { cursor: pointer; }
.switch {
  width: 46px; height: 26px; appearance: none; -webkit-appearance: none;
  background: #333b44; border-radius: 8px; position: relative; flex: none;
  transition: background .18s; cursor: pointer;
}
.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
  border-radius: 6px; background: var(--dim); transition: transform .18s, background .18s;
}
.switch:checked { background: linear-gradient(180deg, var(--hot-2), var(--hot)); }
.switch:checked::after { transform: translateX(20px); background: var(--ink); }
.time-input { width: auto; flex: none; }

/* --- Отчёт --- */
.totals { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.tile {
  background: var(--plate); border: 1px solid var(--line); border-radius: 10px; padding: 13px;
}
.tile--wide { grid-column: 1 / -1; }
.tile__label { font-size: 12px; color: var(--dim); }
.tile__value {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 21px; font-weight: 600; margin-top: 5px;
}
.tile--wide .tile__value { font-size: 27px; color: var(--hot-2); }
.tile__delta { font-family: var(--mono); font-size: 11.5px; margin-top: 5px; color: var(--dim); }
.up { color: var(--cool); }
.down { color: var(--runout); }

.bar-row { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; }
.bar-row + .bar-row { border-top: 1px solid var(--line); }
.bar-head { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; }
.bar-head span:last-child {
  color: var(--dim); white-space: nowrap;
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 12.5px;
}
.bar { height: 5px; border-radius: 1px; background: #333b44; overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--hot); opacity: .85; }

/* --- Запись = деталь на плите: слева кромка цвета материала --- */
.card {
  position: relative; overflow: hidden;
  background: var(--plate); border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 13px 12px 15px; display: flex; flex-direction: column; gap: 6px;
}
.card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--line);
}
.card--expense::before { background: var(--hot); }
.card--sale::before { background: var(--cool); }
.card__top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.card__title { font-weight: 600; font-size: 14.5px; min-width: 0; }
.card__sum {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-weight: 600; font-size: 14.5px; white-space: nowrap;
}
.card--expense .card__sum { color: var(--hot-2); }
.card--sale .card__sum { color: var(--cool); }
.card__meta {
  font-family: var(--mono); font-size: 11px; color: var(--dim);
  display: flex; gap: 10px; flex-wrap: wrap;
}
.card__actions { display: flex; justify-content: flex-end; gap: 14px; }
.link-btn {
  background: none; border: none; color: var(--runout); font: inherit;
  font-size: 13px; cursor: pointer; padding: 2px 0;
}

/* Удаление — компактная иконка справа, а не строка во всю карточку.
   Так живут записи, задания печати, принтеры и катушки. */
.card--tight { padding-right: 52px; }
.card--tight .card__actions {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
}
.card--tight .link-btn {
  width: 30px; height: 30px; padding: 0; border: 1px solid #3b2c2a; border-radius: 7px;
  display: grid; place-items: center;
}
.card--tight .link-btn svg {
  width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round;
}
.card--tight .link-btn:active { background: rgba(224, 74, 63, .14); }

/* Мастерская: задание печати, основной принтер, пустая катушка. */
.card--job::before { background: var(--cool); }
.card--fail::before { background: var(--runout); }
.card--job .card__sum { color: var(--pla); }
.card--on { border-color: #4a3125; }
.card--on::before { background: var(--hot); }
.card--off { opacity: .55; }
.card .bar { margin-top: 9px; }
.bar i.is-up { background: var(--hot-2); }

/* Списки принтеров и катушек редко длинные — выбор в один тап, без шторок. */
select {
  width: 100%; padding: 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--field); color: var(--pla); font: inherit; min-width: 0;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'><path d='M1 1l6 6 6-6' fill='none' stroke='%238b939c' stroke-width='1.6' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat; background-position: right 12px center;
  padding-right: 34px;
}
select:focus { outline: none; border-color: var(--hot); box-shadow: 0 0 0 3px rgba(255, 90, 31, .15); }

/* --- Расчёт: стек слоёв с зазором в один пиксель --- */
.calc-lines { display: flex; flex-direction: column; gap: 1px; margin-top: 4px; }
.calc-line {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
  padding: 11px 13px; background: var(--field); font-size: 14px;
}
.calc-line:first-child { border-radius: 8px 8px 0 0; }
.calc-line > div:last-child {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  text-align: right; white-space: nowrap;
}
.calc-line__sub {
  display: block; font-family: var(--mono); font-size: 11px; color: var(--dim);
  margin-top: 3px; font-style: normal;
}
/* Итог — спечённый блок: крупное моно-число на остывающем оранжевом. */
.calc-line--total {
  border-radius: 0 0 8px 8px; padding: 15px 13px; font-size: 15px;
  background: linear-gradient(180deg, #2c1e16, #221a15);
  border: 1px solid #4a3125; border-top: 0;
}
.calc-line--total > div:last-child { font-size: 24px; font-weight: 600; color: var(--hot-2); }

/* --- Деталь по описанию --- */
textarea {
  width: 100%; padding: 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--field); color: var(--pla); font: inherit; resize: vertical;
  min-height: 76px; outline: none; transition: border-color .15s, box-shadow .15s;
}
textarea::placeholder { color: #5c646d; }
textarea:focus { border-color: var(--hot); box-shadow: 0 0 0 3px rgba(255, 90, 31, .15); }

/* Каретка над слоем: та же картинка, что бот рисует в чате. */
.gen-track {
  font-family: var(--mono); font-size: 15px; letter-spacing: 2px; color: var(--hot);
  background: var(--chamber); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; text-align: center; margin-bottom: 8px;
}
#genFlow { display: flex; flex-direction: column; gap: 10px; }
#genFlow:empty { display: none; }

/* --- Просмотр модели --- */
.viewer {
  position: relative; width: 100%; aspect-ratio: 1 / 1; max-height: 52vh;
  background: radial-gradient(120% 90% at 50% 0%, #20252c, #15181c 70%);
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
}
/* Жесты холста — только вращение модели: без этого webview уводит страницу
   в скролл, а вертикальный свайп сворачивает мини-апп. */
.viewer canvas { width: 100%; height: 100%; display: block; touch-action: none; }
.viewer__empty {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 24px; color: var(--dim); font-size: 14px; line-height: 1.6;
  pointer-events: none;
}
.viewer__empty b { color: var(--pla); }
.viewer__tools { position: absolute; right: 8px; top: 8px; display: flex; flex-direction: column; gap: 6px; }
.viewer__tools .icon-btn { background: rgba(15, 18, 21, .72); border: 1px solid var(--line); }
.viewer__tools .icon-btn.is-on { border-color: var(--hot); color: var(--hot); }
/* Кнопка вращения показывает то, что произойдёт по нажатию. */
#modelSpin .i-play { display: none; }
#modelSpin[data-spin="off"] .i-pause { display: none; }
#modelSpin[data-spin="off"] .i-play { display: block; }

.file-btn { display: flex; text-align: center; cursor: pointer; }
.model-meta { display: flex; flex-wrap: wrap; gap: 7px 16px; font-size: 13px; color: var(--dim); }
.model-meta b { color: var(--pla); font-family: var(--mono); font-variant-numeric: tabular-nums; }
.model-actions { display: flex; gap: 8px; }
.model-actions .btn { flex: 1; }

/* --- Служебное --- */
.stats { display: flex; gap: 9px; }
.stats > div {
  flex: 1; background: var(--plate); border: 1px solid var(--line);
  border-radius: 10px; padding: 11px; text-align: center;
}
.stats b {
  display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 19px; font-weight: 600;
}
.stats span { font-size: 11px; color: var(--dim); }

/* Пусто — не сообщение об отсутствии данных, а плита в ожидании детали. */
.empty {
  position: relative; text-align: center; color: var(--dim); font-size: 14px; line-height: 1.6;
  padding: 30px 20px; border: 1px dashed #333b44; border-radius: 10px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='34.64' viewBox='0 0 40 34.64'><path d='M10 1 L30 1 L40 17.32 L30 33.64 L10 33.64 L0 17.32 Z' fill='none' stroke='%232b323b' stroke-width='1.2'/></svg>");
}
.skeleton {
  height: 64px; border-radius: 10px; background: var(--plate);
  border: 1px solid var(--line); opacity: .5;
}

.denied { padding: 32px 20px; white-space: pre-wrap; line-height: 1.6; }
.about {
  color: var(--dim); font-family: var(--mono); font-size: 11px;
  text-align: center; padding: 20px 0 8px;
}

/* --- Нижнее меню = каретка --- */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  display: flex; background: var(--chamber); border-top: 1px solid var(--line);
}
.tab {
  position: relative; flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  border: none; background: none; color: #6f7982; font: inherit; font-size: 10px; cursor: pointer;
}
.tab svg {
  width: 21px; height: 21px; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.tab.is-active { color: var(--hot); }
/* Активная вкладка помечена свечением каретки над иконкой. */
.tab.is-active::before {
  content: ""; position: absolute; top: 0; left: 24%; right: 24%; height: 3px;
  border-radius: 0 0 2px 2px; background: var(--hot); box-shadow: 0 0 10px var(--hot);
}

.icon-btn {
  border: 1px solid transparent; background: var(--field); color: var(--pla);
  width: 34px; height: 34px; border-radius: 8px; cursor: pointer; flex: none;
  display: grid; place-items: center; font-size: 15px;
}
.icon-btn svg {
  width: 16px; height: 16px; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}

/* --- Шторка --- */
.sheet { position: fixed; inset: 0; z-index: 40; display: flex; align-items: flex-end; }
.sheet__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .62); }
.sheet__body {
  position: relative; width: 100%; max-height: 82vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  background: var(--bed); border-top: 1px solid var(--line); border-radius: 14px 14px 0 0;
  padding: 14px 12px calc(14px + env(safe-area-inset-bottom));
  animation: rise .22s ease;
}
@keyframes rise { from { transform: translateY(18px); opacity: .4; } }
.sheet__head { display: flex; align-items: center; justify-content: space-between; }
.sheet__head b { font-size: 16px; }

.toast {
  position: fixed; left: 50%; bottom: calc(var(--tabbar-h) + 24px); z-index: 50;
  transform: translateX(-50%); max-width: 88vw; padding: 11px 16px;
  border: 1px solid var(--line); border-left: 3px solid var(--hot); border-radius: 8px;
  background: var(--chamber); color: var(--pla); font-size: 14px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .5);
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
