/* Верстак заказ-наряда: рабочая консоль поверх панели. Челюсть в центре —
   рабочая поверхность, работы стоят карточками по краям и привязаны к своим зубам
   линиями. Палитра и типографика — из согласованного макета (24.08.2026).

   Тема наследуется от панели: светлая по умолчанию, тёмная — когда тему переключили
   в админке (body.admin-theme-dark) или в рабочем месте цеха (body.dark-theme).
   Роли цветов вынесены в токены целиком, поэтому смена темы не оставляет тёмных
   заплат на светлом фоне. */

.ot-desk {
    /* --- светлая тема (по умолчанию) --- */
    --ot-void: #eef2f5;
    --ot-line: #d3dce3;
    --ot-line-soft: #e6ecf0;
    --ot-ink: #16232e;
    --ot-ink-dim: #5d7180;
    --ot-ink-faint: #5f7382;
    --ot-beam: #0d9488;
    --ot-beam-deep: #0a6f66;
    --ot-amber: #b06a00;
    --ot-ok: #147d5a;
    --ot-warn: #8a6100;
    --ot-crit: #c0392b;
    --ot-grid: rgba(13, 148, 136, .05);
    --ot-face: Play, "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --ot-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
    --ot-tooth-fill: #ffffff;
    --ot-tooth-stroke: #8aa0ad;
    --ot-tooth-detail: #c3d0d8;
    --ot-tooth-det-on: rgba(255, 255, 255, .75);
    --ot-midline: rgba(13, 148, 136, .28);

    /* поверхности и роли */
    --ot-field: #f2f5f8;
    --ot-sunken: #eef2f6;
    --ot-deep: #e9eef2;
    --ot-tint: rgba(0, 0, 0, .02);
    --ot-on-beam: #ffffff;
    --ot-scroll: #c2ced7;
    --ot-scroll-hover: #a9b8c3;
    --ot-scroll-track: rgba(0, 0, 0, .03);
    --ot-sw-track: #c9d5dd;
    --ot-sw-knob: #ffffff;
    --ot-sw-knob-on: #ffffff;

    --ot-bar-bg: linear-gradient(180deg, #ffffff, #f7f9fb);
    --ot-head-bg: linear-gradient(180deg, #ffffff, #f4f7f9);
    --ot-stage-bg: radial-gradient(120% 80% at 50% 42%, #ffffff 0%, #f3f7f9 62%, #e9eef2 100%);
    --ot-modal-bg: linear-gradient(180deg, #ffffff, #f7f9fb);
    --ot-foot-bg: linear-gradient(0deg, #ffffff, rgba(255, 255, 255, .85));
    --ot-sheet-bg: #ffffff;
    --ot-go-bg: linear-gradient(180deg, #12b3a4, #0d9488);
    --ot-shadow-up: 0 24px 60px -24px rgba(16, 36, 48, .28);
    --ot-shadow-down: 0 -24px 60px -24px rgba(16, 36, 48, .2);

    --ot-beam-wash: rgba(13, 148, 136, .10);
    --ot-beam-edge: rgba(13, 148, 136, .35);
    --ot-beam-glow: rgba(13, 148, 136, .35);
    --ot-amber-wash: rgba(176, 106, 0, .12);
    --ot-amber-edge: rgba(176, 106, 0, .45);
    --ot-warn-wash: rgba(138, 97, 0, .10);
    --ot-warn-edge: rgba(138, 97, 0, .35);
    --ot-ok-wash: rgba(20, 125, 90, .10);
    --ot-ok-edge: rgba(20, 125, 90, .35);

    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    background: var(--ot-void);
    color: var(--ot-ink);
    font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 14px;
}

/* --- тёмная тема: включается переключателем панели --- */
body.admin-theme-dark .ot-desk,
body.dark-theme .ot-desk {
    --ot-void: #080d12;
    --ot-line: #1e2e3b;
    --ot-line-soft: #16232e;
    --ot-ink: #dbe7ef;
    --ot-ink-dim: #7d93a3;
    --ot-ink-faint: #93a9b8;
    --ot-beam: #2ee6d6;
    --ot-beam-deep: #0f8f86;
    --ot-amber: #ffb347;
    --ot-ok: #52e3a0;
    --ot-warn: #ffd166;
    --ot-crit: #ff6b6b;
    --ot-grid: rgba(46, 230, 214, .055);
    --ot-tooth-fill: #16232e;
    --ot-tooth-stroke: #38566b;
    --ot-tooth-detail: #2a4257;
    --ot-tooth-det-on: rgba(6, 20, 26, .55);
    --ot-midline: rgba(46, 230, 214, .28);

    --ot-field: #131e28;
    --ot-sunken: #121c25;
    --ot-deep: #101a22;
    --ot-tint: rgba(255, 255, 255, .015);
    --ot-on-beam: #04231f;
    --ot-scroll: #27404f;
    --ot-scroll-hover: #355a6c;
    --ot-scroll-track: rgba(255, 255, 255, .02);
    --ot-sw-track: #25384a;
    --ot-sw-knob: #7d93a3;
    --ot-sw-knob-on: #eafffb;

    --ot-bar-bg: linear-gradient(180deg, rgba(12, 20, 27, .96), rgba(12, 20, 27, .72));
    --ot-head-bg: linear-gradient(180deg, rgba(22, 33, 44, .97), rgba(15, 23, 32, .97));
    --ot-stage-bg: radial-gradient(120% 80% at 50% 42%, #101c26 0%, #0a1118 62%, #070c11 100%);
    --ot-modal-bg: linear-gradient(180deg, rgba(20, 31, 41, .99), rgba(13, 20, 28, .99));
    --ot-foot-bg: linear-gradient(0deg, rgba(10, 17, 23, .98), rgba(10, 17, 23, .78));
    --ot-sheet-bg: rgba(11, 18, 25, .99);
    --ot-go-bg: linear-gradient(180deg, #48f2e2, #1fc7b8);
    --ot-shadow-up: 0 24px 60px -24px rgba(0, 0, 0, .9);
    --ot-shadow-down: 0 -24px 60px -24px rgba(0, 0, 0, .9);

    --ot-beam-wash: rgba(46, 230, 214, .09);
    --ot-beam-edge: rgba(46, 230, 214, .3);
    --ot-beam-glow: rgba(46, 230, 214, .55);
    --ot-amber-wash: rgba(255, 179, 71, .14);
    --ot-amber-edge: rgba(255, 179, 71, .45);
    --ot-warn-wash: rgba(255, 209, 102, .08);
    --ot-warn-edge: rgba(255, 209, 102, .4);
    --ot-ok-wash: rgba(82, 227, 160, .08);
    --ot-ok-edge: rgba(82, 227, 160, .4);
}

/* Раздел показывается инлайновым display:block из setSection — флекс на нём не
   удержится, поэтому цепочка идёт высотой, а не растяжением. */
body:has(#job-order-new.active) .content-body {
    height: 100dvh;
    overflow: hidden;
    padding-bottom: 0;
}

/* Верстак занимает страницу целиком: инструменту не нужны поля и рамка вокруг —
   окно в окне (владелец, 24.08.2026). Заголовок раздела и отступы контента снимаются. */
body:has(#job-order-new.active) .content-body { padding: 0; }
body:has(#job-order-new.active) .content-header { display: none; }
#job-order-new.active { height: 100%; }
#job-order-new.active .jo-new-mount { height: 100%; margin: 0; min-height: 0; display: flex; }

.ot-desk--page { flex: 1 1 auto; min-height: 0; }

/* Полноэкранный лист рабочего места цеха: внутри та же консоль. */
body .modal-backdrop.order-teeth-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(4, 8, 12, .72);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 12000;
    padding: 0;
}

body .modal-backdrop.order-teeth-backdrop > .modal.order-teeth-modal {
    background: var(--ot-void, #080d12);
    border: 0;
    border-radius: 0;
    width: 100%;
    max-width: 100%;
    height: 100dvh;
    max-height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 0;
}

.order-teeth-modal .modal-header {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 18px;
    background: #0f1720;
    border-bottom: 1px solid #1e2e3b;
    color: #dbe7ef;
    font-family: Play, sans-serif;
    font-size: 15px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.order-teeth-close {
    border: 0;
    background: transparent;
    color: #7d93a3;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}

.order-teeth-close:hover { color: var(--ot-ink); }

/* ---------- шапка наряда ---------- */

.ot-hud {
    flex: none;
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 0 18px;
    height: 58px;
    background: var(--ot-bar-bg);
    border-bottom: 1px solid var(--ot-line);
}

/* Блоки шапки делят свободную ширину поровну: прижатые влево списки оставляли
   половину строки пустой, а длинные названия клиник при этом обрезались. */
.ot-hud__id { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 0; }
#otCardUrgentSw.is-on i { background: var(--ot-warn); }
.ot-hud__tag {
    flex: none;
    font-family: var(--ot-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ot-ink-faint);
}
.ot-hud__sep { width: 1px; height: 26px; background: var(--ot-line); flex: none; }
.ot-hud__grow { flex: 1 1 auto; }

/* Состояние расчётов — своей строкой над списками, а не сбоку от них: в строке
   оно отъедало место у самих списков, ради которых шапка и существует. */
.ot-hud__note {
    flex: none;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 18px;
    background: var(--ot-bar-bg);
    border-bottom: 1px solid var(--ot-line);
}
.ot-hud__patient { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1 1 auto; }

/* Оболочка верстака — .modal, и правила панели (.modal select в цехе,
   select.form-control в админке) перебивали стили консоли: список получал
   фон карточки, чужую стрелку и ширину во всю строку. Поэтому селекторы
   консоли закрыты .ot-desk — этого хватает, чтобы взять верх. */
.ot-desk .ot-sel {
    flex: 0 1 auto;
    min-width: 132px;
    max-width: 260px;
    appearance: none;
    -webkit-appearance: none;
    /* Стрелку рисует сам список (.zsel-btn__a) — своей у поля быть не должно. */
    padding-right: 12px;
    border: 1px solid var(--ot-line);
    /* Сплошной цвет, а не полупрозрачный белый: нативный список рисует своё поле
       поверх прозрачности, и в консоли оно выходило белым. */
    background-color: var(--ot-field);
    color: var(--ot-ink);
    font: inherit;
    font-size: 13.5px;
    font-weight: 600;
    padding: 5px 8px;
    border-radius: 2px;
}

/* В шапке список растягивается по своему блоку; вне её остаётся компактным. */
.ot-desk .ot-hud .ot-sel { flex: 1 1 auto; min-width: 0; max-width: none; }

.ot-desk .ot-sel:focus-visible { outline: 2px solid var(--ot-beam); outline-offset: 1px; }
.ot-desk .ot-sel option { background: var(--ot-deep); color: var(--ot-ink); }

.ot-icon {
    flex: none;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--ot-line);
    background-color: var(--ot-field);
    color: var(--ot-ink-dim);
    border-radius: 2px;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
}

.ot-icon:hover { border-color: var(--ot-beam); color: var(--ot-beam); }

.ot-chip {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 3px 10px;
    border-radius: 2px;
    border: 1px solid;
    font-family: var(--ot-mono);
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    white-space: nowrap;
}

.ot-chip b { font-weight: 600; }
.ot-chip--ok { color: var(--ot-ok); border-color: var(--ot-ok-edge); background: var(--ot-ok-wash); }
.ot-chip--warn { color: var(--ot-warn); border-color: var(--ot-warn-edge); background: var(--ot-warn-wash); }
.ot-chip--muted { color: var(--ot-ink-faint); border-color: var(--ot-line); background-color: var(--ot-field); }

/* ---------- холст ---------- */

.ot-canvas {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: 292px minmax(0, 1fr) 292px;
    /* Ряд ровно по высоте холста: иначе колонка карточек растёт по содержимому,
       вылезает за холст и прокрутка в ней не включается — четвёртая работа
       оказывалась за краем. */
    grid-template-rows: minmax(0, 1fr);
    background:
        linear-gradient(var(--ot-grid) 1px, transparent 1px) 0 0 / 40px 40px,
        linear-gradient(90deg, var(--ot-grid) 1px, transparent 1px) 0 0 / 40px 40px,
        var(--ot-stage-bg);
}

.ot-rail {
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    scrollbar-width: thin;
}

.ot-rail--right { align-items: flex-end; }

/* Полоса прокрутки видна всегда: в macOS накладные полосы появляются только во время
   прокрутки, и колонка выглядела обрезанной, а не прокручиваемой. */
.ot-desk ::-webkit-scrollbar { width: 10px; height: 10px; }
.ot-desk ::-webkit-scrollbar-track { background: var(--ot-scroll-track); }
.ot-desk ::-webkit-scrollbar-thumb {
    background: var(--ot-scroll);
    border: 3px solid transparent;
    background-clip: content-box;
    border-radius: 6px;
}
.ot-desk ::-webkit-scrollbar-thumb:hover { background: var(--ot-scroll-hover); background-clip: content-box; }
.ot-desk .ot-rail, .ot-desk .ot-pick__body, .ot-desk .ot-sheet__body { scrollbar-width: thin; scrollbar-color: var(--ot-scroll) transparent; }

/* Поля по бокам — отведённое место для блока набора: он всплывает поверх сцены,
   и без резерва карта прыгала бы в размере при каждом открытии. Резерв
   симметричный, поэтому и сторона набора ничего не сдвигает.
   Ширина: блок (380) + отступ (12) − колонка карточек (292). */
.ot-stage {
    position: relative;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 10px 100px 6px;
}

.ot-zones { display: flex; justify-content: center; gap: 8px; padding-bottom: 6px; }
.ot-zones[hidden], .ot-zone[hidden] { display: none; }

.ot-zone {
    border: 1px dashed var(--ot-line);
    background-color: var(--ot-field);
    color: var(--ot-ink-dim);
    border-radius: 2px;
    padding: 4px 12px;
    font-size: 12px;
    cursor: pointer;
}

.ot-zone:hover:not(:disabled) { border-color: var(--ot-beam); color: var(--ot-beam); }
.ot-zone:disabled { opacity: .4; cursor: not-allowed; }

.ot-map { position: relative; flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center; }

.ot-stage.is-teethless .ot-chart { opacity: .16; filter: grayscale(1); pointer-events: none; }

.ot-map__lock {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    padding: 0 40px;
}

.ot-map__lock[hidden] { display: none; }
.ot-map__lock-title { font-family: var(--ot-face); font-size: 14px; font-weight: 700; }

/* линии-выноски */
.ot-leads { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.ot-desk .ot-lead { fill: none; stroke-width: 1.2; opacity: .85; }
.ot-desk .ot-lead--thin { stroke-width: 1; opacity: .5; stroke-dasharray: 3 4; }
.ot-lead__dot { stroke: none; }
.ot-desk .ot-lead__node { fill: none; stroke-width: 1.4; }

@media (prefers-reduced-motion: no-preference) {
    .ot-lead.is-picking, .ot-lead__node.is-picking { animation: ot-pulse 2.4s ease-in-out infinite; }
    @keyframes ot-pulse { 0%, 100% { opacity: .4; } 50% { opacity: 1; } }
}

/* ---------- карточка работы ---------- */

.ot-card {
    position: relative;
    z-index: 3;
    width: 264px;
    flex: none;
    background: var(--ot-head-bg);
    border: 1px solid var(--ot-line);
    border-left: 2px solid var(--w, var(--ot-beam));
    padding: 10px 12px 11px;
    cursor: pointer;
}

.ot-card:hover, .ot-card.is-open { border-color: var(--w, var(--ot-beam)); }
.ot-card.is-open { box-shadow: 0 0 0 1px var(--w, var(--ot-beam)); }
.ot-card.is-flagged { border-top-color: var(--ot-warn); }
.ot-card:focus-visible { outline: 2px solid var(--ot-beam); outline-offset: 2px; }

.ot-card__top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.ot-card__n { font-family: var(--ot-mono); font-size: 10px; color: var(--ot-ink-faint); }
.ot-card__name { font-family: var(--ot-face); font-size: 14px; font-weight: 700; line-height: 1.25; flex: 1; min-width: 0; overflow-wrap: anywhere; }
.ot-card__del { width: 20px; height: 20px; font-size: 13px; border-color: transparent; background: transparent; }
.ot-card__del:hover { border-color: var(--ot-crit); color: var(--ot-crit); }

.ot-card__teeth { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 7px; }

.ot-tnum {
    font-family: var(--ot-mono);
    font-size: 11px;
    font-weight: 600;
    padding: 1px 6px;
    border: 1px solid var(--w, var(--ot-beam));
    color: var(--w, var(--ot-beam));
    border-radius: 2px;
}

.ot-card__meta { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.ot-card__q { font-family: var(--ot-mono); font-size: 10.5px; color: var(--ot-ink-faint); }
.ot-card__params { font-size: 12px; line-height: 1.45; color: var(--ot-ink-dim); margin-bottom: 8px; overflow-wrap: anywhere; }

.ot-card__warn {
    font-size: 11.5px;
    color: var(--ot-warn);
    border-left: 2px solid var(--ot-warn);
    padding-left: 7px;
    margin-bottom: 8px;
}

.ot-card__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    border-top: 1px solid var(--ot-line-soft);
    padding-top: 7px;
}

.ot-card__due { font-family: var(--ot-mono); font-size: 11px; color: var(--ot-ink-faint); }
.ot-card__sum { font-family: var(--ot-face); font-size: 16px; font-weight: 700; color: var(--w, var(--ot-beam)); }
.ot-card__dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 7px; }

/* Свёрнутая карточка: место кончилось — уходят подробности, а не работы. Порядок
   отказа: параметры и срок → зубы. Правящаяся карточка остаётся развёрнутой. */
.ot-rail.is-dense .ot-card { padding: 7px 10px 8px; }
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__params,
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__meta,
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__warn { display: none; }
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__top { margin-bottom: 5px; }
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__teeth { margin-bottom: 5px; }
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__foot { padding-top: 0; border-top: 0; }
.ot-rail.is-dense .ot-card:not(.is-open) .ot-card__due { display: none; }

.ot-rail.is-tight .ot-card { padding: 5px 10px 6px; }
.ot-rail.is-tight .ot-card:not(.is-open) .ot-card__teeth { display: none; }
.ot-rail.is-tight .ot-card:not(.is-open) .ot-card__top { margin-bottom: 2px; }
.ot-rail.is-tight .ot-card:not(.is-open) .ot-card__name { font-size: 12.5px; line-height: 1.2; }
.ot-rail.is-tight .ot-card:not(.is-open) .ot-card__sum { font-size: 14px; }

/* ---------- набор работы ---------- */

.ot-pick {
    position: absolute;
    z-index: 6;
    width: 380px;
    max-height: calc(100% - 24px);
    display: flex;
    flex-direction: column;
    background: var(--ot-modal-bg);
    border: 1px solid var(--ot-amber-edge);
    box-shadow: var(--ot-shadow-up), 0 0 0 1px var(--ot-amber-wash);
}

.ot-pick[hidden] { display: none; }

.ot-pick__head { flex: none; display: flex; align-items: flex-start; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ot-line); }

/* Перечень зубов бывает на всю челюсть — он переносится по строкам внутри шапки,
   а не растягивает её мимо блока. */
.ot-pick__at {
    font-family: var(--ot-face);
    font-size: 13px;
    font-weight: 700;
    color: var(--ot-amber);
    border: 1px solid var(--ot-amber-edge);
    padding: 2px 9px;
    border-radius: 2px;
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

.ot-pick__title { font-family: var(--ot-face); font-size: 14px; font-weight: 700; flex: 0 1 auto; }
.ot-pick__head .ot-icon { flex: none; margin-left: auto; }

/* Исход набора — сразу под шапкой: «Взять параметры» и цену не должно приходиться
   искать прокруткой (владелец, 24.08.2026). */
.ot-pick__out { flex: none; padding: 9px 12px 0; }

/* Срок, курьер и режим количества закреплены под исходом: они нужны на каждой работе,
   а внизу за осями до них было не долистать (владелец, 24.08.2026). */
.ot-pick__set {
    flex: none;
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--ot-line);
}

.ot-pick__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 9px; }

.ot-pick__row { display: flex; flex-direction: column; gap: 5px; }
.ot-pick__row--flat { flex-direction: row; align-items: center; flex-wrap: wrap; gap: 8px 10px; }
.ot-pick__label {
    font-family: var(--ot-mono);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ot-ink-faint);
}
.ot-pick__label b { color: var(--ot-warn); }
.ot-pick__note { font-size: 12px; color: var(--ot-ink-dim); }
.ot-pick__hint { font-size: 12px; color: var(--ot-ink-faint); }

.ot-chips { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }

/* Курсор в поле каталога: сверху поле, под ним весь список видов работ.
   Высота ограничена — список длиннее карточки набора. */
.ot-chips.is-open { flex-direction: column; align-items: stretch; }
.ot-chips.is-open .ot-ch__search { flex: 0 0 auto; }
.ot-chips__list {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    align-items: center;
    max-height: 168px;
    overflow-y: auto;
}

.ot-ch {
    font: inherit;
    font-size: 12px;
    padding: 3px 9px;
    border: 1px solid var(--ot-line);
    border-radius: 2px;
    color: var(--ot-ink-dim);
    background-color: var(--ot-sunken);
    cursor: pointer;
}

.ot-ch:hover { border-color: var(--ot-beam); color: var(--ot-beam); }
.ot-ch.is-on { border-color: var(--ot-beam); color: var(--ot-on-beam); background: var(--ot-beam); font-weight: 600; }
.ot-ch.is-off { opacity: .34; border-style: dashed; }
.ot-ch.is-off:hover { opacity: .7; }
.ot-ch.is-more { border-style: dashed; }
.ot-ch i { font-style: normal; font-family: var(--ot-mono); font-size: 10px; opacity: .7; margin-left: 6px; }
.ot-ch__search { flex: 1 1 120px; min-width: 110px; display: flex; }

.ot-input {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--ot-mono);
    font-size: 12.5px;
    color: var(--ot-ink);
    border: 1px solid var(--ot-line);
    background-color: var(--ot-field);
    padding: 4px 9px;
    border-radius: 2px;
}

.ot-input:focus-visible { outline: 2px solid var(--ot-beam); outline-offset: 1px; }

.ot-solved {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--ot-ink-dim);
    background-color: var(--ot-sunken);
    border: 1px solid var(--ot-line);
    border-radius: 2px;
    padding: 2px 4px 2px 9px;
}

.ot-solved b { color: var(--ot-ink); font-weight: 600; }
.ot-solved button { border: 0; background: transparent; color: var(--ot-ink-faint); cursor: pointer; font-size: 13px; line-height: 1; padding: 0 3px; }
.ot-solved button:hover { color: var(--ot-crit); }

/* Блок «Решено» — корзина, куда складываются выбранные параметры. Без каймы он
   сливался с открытыми осями, и было непонятно, куда уходит выбор (владелец,
   04.09.2026). Кайма та же, что у найденного совпадения: один язык для «набрано». */
.ot-pick__row--solved {
    padding: 7px 10px;
    border: 1px solid var(--ot-beam);
    border-radius: 2px;
    background: linear-gradient(var(--ot-beam-wash), var(--ot-beam-wash)), var(--ot-field);
    box-shadow: 0 0 0 1px var(--ot-beam-edge);
    /* Корзина стоит на месте, пока оси под ней прокручиваются: подложка непрозрачная,
       чтобы сквозь неё не просвечивали уезжающие чипы. */
    position: sticky;
    top: -10px;
    z-index: 1;
}
.ot-pick__row--solved .ot-pick__label { color: var(--ot-beam-deep); }

.ot-out {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    font-size: 12.5px;
    border: 1px solid var(--ot-line);
    background-color: var(--ot-sunken);
}

.ot-out span { flex: 1; line-height: 1.35; }
.ot-out b { color: var(--ot-ink); }
/* Совпадение найдено — блок берётся в акцентную кайму: это главный сигнал набора,
   и его видно, не читая текста (владелец, 24.08.2026). */
.ot-out--ok,
.ot-out--hit {
    border-color: var(--ot-beam);
    background-color: var(--ot-beam-wash);
    box-shadow: 0 0 0 1px var(--ot-beam-edge), 0 0 20px -6px var(--ot-beam-glow);
}
.ot-out--warn { border-color: var(--ot-warn-edge); background: var(--ot-warn-wash); color: var(--ot-warn); }
.ot-out__price { font-family: var(--ot-face); font-size: 17px; font-weight: 700; color: var(--ot-beam); white-space: nowrap; }

/* Тумблер и его подпись — один элемент: раздельными они разъезжались по строкам,
   когда полоса переносилась. */
.ot-sw { display: inline-flex; align-items: center; gap: 8px; flex: none; cursor: pointer; }
.ot-sw > span { font-size: 12px; color: var(--ot-ink-dim); white-space: nowrap; }
.ot-sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.ot-sw i { flex: none; width: 30px; height: 16px; border-radius: 9px; background: var(--ot-sw-track); position: relative; display: inline-block; transition: background .15s; }
.ot-sw i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--ot-sw-knob); transition: left .15s, background .15s; }
.ot-sw.is-on i { background: var(--ot-beam-deep); }
.ot-sw.is-on i::after { left: 16px; background: var(--ot-sw-knob-on); }
.ot-sw input:focus-visible + i { outline: 2px solid var(--ot-beam); outline-offset: 2px; }

.ot-seg { display: inline-flex; border: 1px solid var(--ot-line); border-radius: 999px; padding: 2px; gap: 2px; }
.ot-seg button { font: inherit; font-size: 11.5px; padding: 2px 10px; border: 0; border-radius: 999px; background: transparent; color: var(--ot-ink-dim); cursor: pointer; }
.ot-seg button.is-on { background: var(--ot-beam); color: var(--ot-on-beam); font-weight: 600; }
.ot-seg--sm button { font-size: 11px; padding: 1px 8px; }

.ot-pick__go { flex: none; display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-top: 1px solid var(--ot-line); background: var(--ot-tint); }
.ot-pick__go .ot-pick__note { flex: 1; }

/* Поле даты приходит из общего модуля со светлыми классами панели — в консоли
   оно перекрашивается, чтобы не выглядеть заплаткой. */
.ot-desk .dmy-date-field { display: flex; align-items: center; gap: 6px; flex: 0 1 190px; min-width: 150px; }
.ot-desk .dmy-date-field .form-control {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--ot-mono);
    font-size: 12.5px;
    color: var(--ot-ink);
    background-color: var(--ot-field);
    border: 1px solid var(--ot-line);
    border-radius: 2px;
    padding: 5px 9px;
    height: auto;
}
.ot-desk .dmy-date-field .form-control::placeholder { color: var(--ot-ink-faint); }
.ot-desk .dmy-date-calendar-btn {
    flex: none;
    margin: 0;
    height: 28px;
    padding: 0 10px;
    border: 1px solid var(--ot-line);
    background-color: var(--ot-field);
    color: var(--ot-ink-dim);
    border-radius: 2px;
    font-size: 13px;
}
.ot-desk .dmy-date-calendar-btn:hover { border-color: var(--ot-beam); color: var(--ot-beam); }

/* материалы работы */
.ot-mat { font-size: 12px; color: var(--ot-ink-dim); display: flex; flex-direction: column; gap: 6px; }
.ot-mat__title { font-family: var(--ot-mono); font-size: 9.5px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--ot-ink-faint); }
.ot-mat--err { color: var(--ot-crit); }
.ot-desk .ot-mat select, .ot-desk .ot-mat-pick {
    width: 100%;
    font: inherit;
    font-size: 12px;
    color: var(--ot-ink);
    border: 1px solid var(--ot-line);
    background-color: var(--ot-field);
    appearance: none;
    -webkit-appearance: none;
    padding: 4px 8px;
    border-radius: 2px;
}
.ot-desk .ot-mat option { background: var(--ot-deep); }

/* ---------- командная строка ---------- */

.ot-cmd {
    flex: none;
    display: flex;
    align-items: center;
    gap: 16px;
    height: 68px;
    padding: 0 18px;
    background: var(--ot-foot-bg);
    border-top: 1px solid var(--ot-line);
}

.ot-cmd__totals { display: flex; align-items: baseline; gap: 22px; }
.ot-cmd__grow { flex: 1 1 auto; }
.ot-tot { display: flex; align-items: baseline; gap: 8px; }
.ot-tot .k { font-family: var(--ot-mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase; color: var(--ot-ink-faint); }
.ot-tot b { font-family: var(--ot-face); font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ot-tot--sum b { color: var(--ot-beam); }

.ot-btn {
    font-family: var(--ot-face);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: 10px 18px;
    border: 1px solid var(--ot-line);
    background: transparent;
    color: var(--ot-ink-dim);
    border-radius: 2px;
    cursor: pointer;
}

.ot-btn:hover:not(:disabled) { border-color: var(--ot-beam); color: var(--ot-beam); }

.ot-btn--go {
    border-color: var(--ot-beam);
    color: var(--ot-on-beam);
    background: var(--ot-go-bg);
    box-shadow: 0 0 0 1px var(--ot-beam-edge), 0 10px 30px -12px var(--ot-beam-glow);
}

.ot-btn--go:hover:not(:disabled) { color: var(--ot-on-beam); filter: brightness(1.06); }
.ot-btn--sm { font-size: 11.5px; padding: 6px 12px; }
.ot-btn:disabled { opacity: .38; cursor: not-allowed; }

/* ---------- список работ ---------- */

/* Список — полоса стола, а не слой поверх него: наложением он закрывал кнопку
   «Поставить на карту» в наборе (владелец, 24.08.2026). Открытый список поджимает
   холст, и набор переезжает вместе с ним. */
.ot-sheet {
    flex: 0 0 auto;
    max-height: 42%;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--ot-sheet-bg);
    border-top: 1px solid var(--ot-line);
    box-shadow: var(--ot-shadow-down);
}

.ot-sheet[hidden] { display: none; }
.ot-sheet__head { flex: none; display: flex; align-items: center; gap: 10px; padding: 9px 16px; border-bottom: 1px solid var(--ot-line); }
.ot-sheet__title { font-family: var(--ot-face); font-size: 14px; font-weight: 700; }
.ot-sheet__body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.ot-sheet__empty { padding: 18px; text-align: center; color: var(--ot-ink-faint); font-size: 12.5px; }

.ot-desk .ot-led { width: 100%; border-collapse: collapse; font-size: 12.5px; color: var(--ot-ink); background: transparent; }
.ot-desk .ot-led th {
    position: sticky;
    top: 0;
    text-align: left;
    padding: 6px 12px;
    font-family: var(--ot-mono);
    font-size: 9.5px;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ot-ink-faint);
    background: var(--ot-deep);
    border-bottom: 1px solid var(--ot-line);
    white-space: nowrap;
}
.ot-desk .ot-led td {
    padding: 6px 12px;
    border: 0;
    border-bottom: 1px solid var(--ot-line-soft);
    background: transparent;
    color: var(--ot-ink);
    vertical-align: middle;
}
.ot-desk .ot-led tr { background: transparent; }
.ot-desk .ot-led__row { cursor: pointer; }
.ot-desk .ot-led__row:hover td { background: var(--ot-sunken); }
.ot-desk .ot-led__params { color: var(--ot-ink-dim); }

/* Полосатость таблиц админки объявлена через id и :nth-child — по специфичности она
   бьёт любой классовый селектор, и каждая нечётная строка списка выходила белой.
   Отвечаем селектором той же силы; в рабочем месте цеха #adminPanel нет, и работают
   обычные правила выше. */
#adminPanel main.content-body .ot-desk table.ot-led > tbody > tr > td { background-color: transparent; color: var(--ot-ink); }
#adminPanel main.content-body .ot-desk table.ot-led > tbody > tr:hover > td { background-color: var(--ot-sunken); }
#adminPanel main.content-body .ot-desk table.ot-led > thead > tr > th { background-color: var(--ot-deep); color: var(--ot-ink-faint); }

.ot-desk .ot-led__warn { display: block; color: var(--ot-warn); }

/* ---------- узкий экран ---------- */

@media (max-width: 1180px) {
    .ot-canvas { grid-template-columns: 240px minmax(0, 1fr) 240px; }
    .ot-card { width: 212px; }
    .ot-pick { width: 340px; }
    /* 340 + 12 − 240 */
    .ot-stage { padding-left: 112px; padding-right: 112px; }
}

/* Переключатель челюстей: на узком экране показывается одна, иначе шаг дуги
   падает вдвое и в зуб не попасть пальцем. Счётчик говорит, сколько отмечено
   на той челюсти, которая сейчас скрыта. */
.ot-jawsel { display: none; }
.ot-jawsel[hidden] { display: none; }

@media (max-width: 900px) {
    /* Один вертикальный поток: шапка, карта, набор, список работ, итоги. */
    .ot-desk { overflow: auto; }
    .ot-desk--page { height: auto; }
    .ot-hud { flex-wrap: wrap; height: auto; padding: 8px 12px; gap: 8px 14px; }
    .ot-canvas { display: block; }
    /* Набор здесь лист снизу, боковой резерв не нужен. */
    .ot-stage { height: auto; padding-left: 8px; padding-right: 8px; }
    .ot-map { min-height: 46vh; }

    .ot-jawsel:not([hidden]) { display: flex; gap: 8px; padding: 8px 0 4px; }
    .ot-jawsel button {
        flex: 1 1 0;
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        border: 1px solid var(--ot-line);
        background: var(--ot-field);
        color: var(--ot-ink-dim);
        border-radius: 2px;
        font-size: 13px;
        cursor: pointer;
    }
    .ot-jawsel button.is-on { background: var(--ot-beam); border-color: var(--ot-beam); color: var(--ot-on-beam); font-weight: 600; }
    .ot-jawsel button b { font-weight: 700; font-size: 12px; opacity: .85; }
    .ot-jawsel button b:empty { display: none; }

    /* Набранные работы идут списком под картой: боковых колонок нет, а лента
       поперёк экрана дала бы горизонтальную прокрутку. */
    .ot-rail {
        flex-direction: column;
        overflow: visible;
        border-top: 1px solid var(--ot-line);
        padding: 12px;
    }
    .ot-rail:empty { display: none; }
    .ot-rail--right { align-items: stretch; }
    .ot-card { width: auto; }
    .ot-leads { display: none; }
    /* Лист в две высоты: пока вид работ не выбран, карта и отмеченные зубы
       должны оставаться на виду; после выбора лист поднимается под параметры. */
    .ot-pick {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        top: auto;
        width: auto;
        max-height: 42vh;
        border-left: 0;
        border-right: 0;
    }
    .ot-pick.is-tall { max-height: 78vh; }
    .ot-pick__head {
        position: sticky;
        top: 0;
        z-index: 1;
        background: var(--ot-modal-bg);
    }
    /* Шапка на телефоне — столбик строк «подпись + поле», а не одна строка:
       четыре списка в ряд сжимались до стрелки, а подписи налезали друг на друга. */
    .ot-hud { flex-direction: column; align-items: stretch; gap: 8px; }
    .ot-hud__id { flex: none; width: 100%; }
    .ot-hud__tag { width: 92px; }
    .ot-hud__sep, .ot-hud__grow { display: none; }
    .ot-desk .ot-hud .ot-sel { width: 100%; min-height: 40px; }

    /* Нижняя строка переносится: итоги над кнопками, кнопки во всю ширину —
       иначе она вылезала за экран и тянула за собой горизонтальную прокрутку. */
    .ot-cmd {
        position: sticky;
        bottom: 0;
        height: auto;
        flex-wrap: wrap;
        gap: 10px;
        padding: 10px 12px;
    }
    .ot-cmd__totals { width: 100%; justify-content: space-between; gap: 10px; }
    .ot-cmd__grow { display: none; }
    .ot-cmd .ot-btn { flex: 1 1 auto; min-height: 44px; }
    .ot-tot b { font-size: 17px; }
}

.ot-chart { width: 100%; height: 100%; }

.ot-tooth { cursor: pointer; }

.ot-tooth__shape {
    fill: var(--ot-tooth-fill);
    stroke: var(--ot-tooth-stroke);
    stroke-width: 1.3;
    stroke-linejoin: round;
    transition: fill 0.12s, stroke 0.12s;
}

.ot-tooth__det { fill: none; stroke: var(--ot-tooth-detail); stroke-width: 1; stroke-linecap: round; pointer-events: none; }
.ot-tooth:hover .ot-tooth__shape { stroke: var(--color-accent); stroke-width: 2; }
/* Заливка отмеченного зуба вне верстака: в карточке работы отмеченный зуб
   отличался только жирным номером — цвет описан лишь под .ot-desk, а карта
   наряда красится инлайном по цвету работы и потому казалась исправной. */
.ot-tooth.is-on .ot-tooth__shape {
    fill: color-mix(in srgb, var(--color-accent) 32%, var(--color-bg-surface));
    stroke: var(--color-accent);
}

.ot-tooth.is-on .ot-tooth__det { stroke: var(--ot-tooth-det-on); }

.ot-tooth.is-pending .ot-tooth__shape {
    fill: var(--color-bg-hover);
    stroke: var(--color-accent);
    stroke-dasharray: 4 3;
    stroke-width: 1.8;
}

.ot-tooth.is-focus .ot-tooth__shape { stroke: var(--color-accent); stroke-width: 2.6; }

.ot-tooth__num {
    font-size: 10px;
    font-weight: 600;
    fill: var(--color-text-muted);
    text-anchor: middle;
    dominant-baseline: central;
    pointer-events: none;
}

.ot-tooth.is-on .ot-tooth__num { fill: var(--color-text-primary); font-weight: 700; }
.ot-tooth.is-pending .ot-tooth__num { fill: var(--color-accent); font-weight: 700; }

.ot-tooth__badge {
    font-size: 9px;
    font-weight: 700;
    fill: #fff;
    text-anchor: middle;
    dominant-baseline: central;
    pointer-events: none;
}

.ot-jaw { font-size: 11px; fill: var(--color-text-muted); text-anchor: middle; letter-spacing: 0.06em; }
.ot-midline { stroke: var(--ot-midline); stroke-width: 1.4; stroke-dasharray: 5 5; pointer-events: none; }

/* Зубы внутри консоли живут в её палитре, а не в теме панели: карта — часть
   инструмента. Цвет отмеченного зуба приходит инлайном от работы и перебивает заливку. */
.ot-desk .ot-tooth__hit { fill: transparent; stroke: none; }
.ot-desk .ot-tooth__shape { fill: var(--ot-tooth-fill); stroke: var(--ot-tooth-stroke); stroke-width: 1.2; }
.ot-desk .ot-tooth__det { stroke: var(--ot-tooth-detail); }
.ot-desk .ot-tooth__num { font-family: var(--ot-mono); font-size: 8.5px; font-weight: 500; fill: var(--ot-ink-faint); }
.ot-desk .ot-tooth:hover .ot-tooth__shape { stroke: var(--ot-beam); stroke-width: 2; }
.ot-desk .ot-tooth.is-on .ot-tooth__shape { fill: var(--ot-beam); stroke: var(--ot-beam); filter: drop-shadow(0 0 6px var(--ot-beam-glow)); }
.ot-desk .ot-tooth.is-on .ot-tooth__num { fill: var(--ot-ink); font-weight: 700; }
.ot-desk .ot-tooth.is-on .ot-tooth__det { stroke: var(--ot-tooth-det-on); }
.ot-desk .ot-tooth.is-pending .ot-tooth__shape {
    fill: var(--ot-amber-wash);
    stroke: var(--ot-amber);
    stroke-width: 2.2;
    stroke-dasharray: none;
    filter: drop-shadow(0 0 7px var(--ot-amber-edge));
}
.ot-desk .ot-tooth.is-pending .ot-tooth__num { fill: var(--ot-amber); font-weight: 700; }
.ot-desk .ot-tooth.is-focus .ot-tooth__shape { stroke-width: 2.6; }
.ot-desk .ot-jaw { font-family: var(--ot-mono); font-size: 10px; fill: var(--ot-ink-faint); letter-spacing: .18em; }
.ot-desk .ot-midline { stroke: var(--ot-midline); stroke-width: 1; stroke-dasharray: 3 7; }
.ot-desk .ot-tooth__badge { font-family: var(--ot-mono); }

/* ============================================================
   Зубная карта в карточке заказа
   Компактная и статичная: ни кликов, ни подсветки под курсором. Стоит рядом
   с подписью, а не отдельной плитой — иначе отодвигает название работы вниз.
   ============================================================ */

/* Зубы заказа в карточке «Параметры вида работ»: ширина по правому рельсу карточки. */
.order-teeth-card {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
}

.order-teeth-card__label {
    font-size: 12px;
    color: var(--color-text-muted);
    white-space: nowrap;
}

.order-teeth-card__chart {
    display: block;
    /* 340, а не 260: после распрямления дуги одна челюсть стала вдвое шире своей
       высоты, и при прежней ширине зубы в карточке мельчали на четверть. */
    width: 340px;
    max-width: 100%;
}

.order-teeth-card .ot-chart {
    width: 100%;
    height: auto;
    display: block;
}

.order-teeth-card .ot-jaw { display: none; }

.order-teeth-card .ot-tooth { cursor: default; }

.order-teeth-card .ot-tooth:hover .ot-tooth__shape {
    stroke: var(--ot-tooth-stroke);
    stroke-width: 1.3;
}

.order-teeth-card .ot-tooth.is-on:hover .ot-tooth__shape { stroke-width: 1.3; }
