/* Компоненты UI-kit Iris. Зависят от tokens.css. */

/* ===================== Button ===================== */
/* 🔴 Iris 2.0 (23.09.2026): кнопки — «материал»: primary = градиент + блик по верхней кромке + мягкий ореол;
   light = стеклянная плашка с обводкой; нажатие чуть «вдавливает» кнопку. */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: none; border-radius: var(--radius); cursor: pointer;
  font-family: var(--font); font-weight: 600; line-height: 1; white-space: nowrap;
  transition: filter .15s, background .15s, border-color .15s, opacity .15s, box-shadow .2s, transform .08s;
}
.ui-btn:active:not(:disabled) { transform: translateY(1px); }
.ui-btn { outline: none; }
/* Iris 2.0 (23.09.2026): фокус с клавиатуры — кольцо акцента с мягким свечением (раньше фокуса не было видно). */
.ui-btn:focus-visible, .ui-iconbtn:focus-visible { box-shadow: 0 0 0 3px var(--accent-soft), 0 0 16px -4px var(--glow); }
.ui-btn:disabled { opacity: .55; cursor: not-allowed; box-shadow: none; }
.ui-iconbtn { outline: none; }
.ui-btn--sm { padding: 7px 12px; font-size: 12.5px; }
.ui-btn--md { padding: 10px 16px; font-size: 13px; }
.ui-btn--lg { padding: 12px 20px; font-size: 14px; }
.ui-btn--block { width: 100%; }
.ui-btn--primary { background: var(--grad); color: var(--on-accent); box-shadow: var(--pri-hl), 0 6px 18px -10px var(--glow); }
.ui-btn--primary:hover:not(:disabled) { filter: brightness(1.07); box-shadow: var(--pri-hl), 0 10px 28px -10px var(--glow); }
.ui-btn--solid { background: var(--accent); color: var(--on-accent); box-shadow: var(--pri-hl), 0 6px 18px -10px var(--glow); }
.ui-btn--solid:hover:not(:disabled) { filter: brightness(1.08); box-shadow: var(--pri-hl), 0 10px 28px -10px var(--glow); }
.ui-btn--light { background: var(--btn-bg); color: var(--text); box-shadow: inset 0 0 0 1px var(--ctl-border), var(--btn-hl); }
.ui-btn--light:hover:not(:disabled) { background: var(--btn-bg-hover); box-shadow: inset 0 0 0 1px var(--border-strong), var(--btn-hl); }
.ui-btn--outline { background: transparent; border: 1px solid var(--border-strong); color: var(--text); }
.ui-btn--outline:hover:not(:disabled) { background: var(--hover); border-color: color-mix(in srgb, var(--accent) 45%, var(--border-strong)); }
.ui-btn--subtle { background: transparent; color: var(--muted); }
.ui-btn--subtle:hover:not(:disabled) { background: var(--hover); color: var(--text); }
.ui-btn--danger { background: var(--danger-soft); color: var(--danger); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger) 28%, transparent); }
.ui-btn--danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 22%, transparent); }
.ui-btn__spinner { width: 15px; height: 15px; }

/* Icon-only button */
.ui-iconbtn {
  display: grid; place-items: center; width: 36px; height: 36px; border: none;
  background: transparent; color: var(--muted); border-radius: var(--radius-sm); cursor: pointer;
}
.ui-iconbtn { transition: background .15s, color .15s, box-shadow .2s; }
.ui-iconbtn:hover { background: var(--btn-bg); color: var(--text); box-shadow: inset 0 0 0 1px var(--ctl-border); }

/* ===================== Field / Input ===================== */
.ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ui-field__label { color: var(--muted); font-size: 12px; }
.ui-field__req { color: var(--danger); margin-left: 2px; }
.ui-field__hint { color: var(--muted); font-size: 11.5px; }
.ui-field__error { color: var(--danger); font-size: 11.5px; }
.ui-charcount { color: var(--muted); font-size: 11.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ui-charcount--warn { color: var(--warning); }
.ui-charcount--over { color: var(--danger); }

.ui-inputwrap { position: relative; display: flex; align-items: center; }
/* Поле шириной по содержимому (NumberInput autoWidth). inline-flex — чтобы поле подчинялось выравниванию
   родителя (в правой ячейке таблицы встаёт на место значения, а не прыгает влево при активации правки). */
.ui-inputwrap--auto { display: inline-flex; width: max-content; max-width: 100%; vertical-align: middle; }
.ui-inputwrap__icon { position: absolute; left: 12px; display: grid; place-items: center; color: var(--muted); pointer-events: none; }
/* Iris 2.0: поле — «колодец»: чуть темнее поверхности, внутренняя тень, при наведении ярче рамка,
   в фокусе — рамка акцента + кольцо со свечением и светлее фон. */
.ui-input {
  width: 100%; background: var(--ctl-bg); border: 1px solid var(--ctl-border); color: var(--text);
  padding: 10px 13px; border-radius: var(--radius); font-size: 14px; font-family: var(--font);
  box-shadow: var(--ctl-inset);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.ui-input:hover:not(:focus):not(:disabled) { border-color: var(--border-strong); }
.ui-input--with-icon { padding-left: 36px; }
/* Поле формы с кнопкой-действием справа (напр. выбор контрагента из справочника). */
.ui-fieldact { display: flex; align-items: flex-end; gap: 8px; min-width: 0; }
.ui-fieldact__main { flex: 1; min-width: 0; }
.ui-input::placeholder { color: var(--dim); }

/* ===================== RichText (rich-text редактор) ===================== */
.ui-rte { display: flex; flex-direction: column; min-height: 0; border: 1px solid var(--ctl-border); border-radius: var(--radius); overflow: hidden; background: var(--ctl-bg); box-shadow: var(--ctl-inset); }
.ui-rte__bar { display: flex; flex-wrap: wrap; gap: 8px; padding: 6px 8px; border-bottom: 1px solid var(--border); background: var(--surface); }
.ui-rte__group { display: flex; gap: 2px; }
.ui-rte__group + .ui-rte__group { padding-left: 8px; border-left: 1px solid var(--border); }
.ui-rte__btn { width: 30px; height: 30px; border-radius: var(--radius-sm); }
.ui-rte__btn.is-active { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.ui-rte__area { flex: 1; min-height: 6rem; padding: 12px 14px; color: var(--text); font-size: 14px; line-height: 1.5; overflow-y: auto; outline: none; }
/* Фокус редактора — как у поля ввода (Iris 2.0): рамка акцента + кольцо со свечением на всём блоке. */
.ui-rte { transition: border-color .15s, box-shadow .15s; }
.ui-rte:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft), 0 0 18px -6px var(--glow); }
.ui-rte__area:empty::before { content: attr(data-placeholder); color: var(--muted); pointer-events: none; }
.ui-rte__area p { margin: 0 0 8px; }
.ui-rte__area ul, .ui-rte__area ol { margin: 0 0 8px; padding-left: 24px; }
.ui-rte--disabled { opacity: .6; }
.ui-input:focus { outline: none; background: var(--ctl-bg-focus); border-color: color-mix(in srgb, var(--accent) 70%, transparent); box-shadow: 0 0 0 3px var(--accent-soft), 0 0 18px -6px var(--glow); }
.ui-input--invalid { border-color: var(--danger); }
textarea.ui-input {
  resize: vertical; min-height: 84px; line-height: 1.5;
  /* Своя ручка растягивания (две диагональные риски) в углу — в гамме темы. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><path d='M9 1 1 9M9 5 5 9' stroke='%23828893' stroke-width='1.2' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat; background-position: bottom 3px right 3px;
}
textarea.ui-input::-webkit-resizer { background: transparent; }
/* autosize: высота строго по контенту (1 строка пустое → растёт по числу строк); без ручки и внутреннего скролла */
textarea.ui-input--autosize { resize: none; overflow: hidden; min-height: 0; background-image: none; }

/* ===================== NumberInput ===================== */
.ui-numwrap { position: relative; }
.ui-num { padding-right: 32px; }
.ui-num-steps { position: absolute; right: 5px; top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: 1px; }
.ui-num-step { display: grid; place-items: center; width: 20px; height: 14px; padding: 0; border: none; background: var(--btn-bg); box-shadow: inset 0 0 0 1px var(--ctl-border); color: var(--muted); cursor: pointer; transition: color .12s, background .12s; }
.ui-num-step:first-child { border-radius: 5px 5px 0 0; }
.ui-num-step:last-child { border-radius: 0 0 5px 5px; }
.ui-num-step:hover:not(:disabled) { color: var(--accent); }
.ui-num-step:disabled { opacity: .4; cursor: default; }
/* Без стрелок (noStepper): обычный правый отступ поля */
.ui-num--nostep { padding-right: 13px; }

/* Select (кастомный) + общий поповер */
.ui-selectwrap { position: relative; }
.ui-select {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
  cursor: pointer; text-align: left; user-select: none; outline: none;
}
.ui-select:focus-visible, .ui-select--open { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft), 0 0 18px -6px var(--glow); }
.ui-select__val { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-select__val--ph { color: var(--muted); }
.ui-select__arrow { color: var(--muted); transition: transform .15s; flex: none; }
.ui-select--open .ui-select__arrow { transform: rotate(180deg); }

.ui-popover {
  position: absolute; z-index: 1200; margin-top: 6px; background: var(--pop-bg);
  border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-pop), var(--mat-hl);
}
/* Поповер в портале: позицию (с клампом в экран) считает Popover.tsx, предел размера — здесь,
   чтобы широкая/высокая панель (календарь, диапазон дат) не вылезала за экран, а скроллилась. */
.ui-popover--fixed { position: fixed; margin-top: 0; max-width: calc(100vw - 16px); max-height: calc(100dvh - 16px); overflow: auto; }
.ui-select__menu { padding: 6px; max-height: 260px; overflow: auto; }
.ui-select__opt {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 10px; border-radius: 8px; cursor: pointer; color: var(--text); font-size: 14px;
}
.ui-select__opt { transition: background .12s; }
.ui-select__opt:hover { background: var(--btn-bg-hover); }
.ui-select__opt--sel { background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }
.ui-select__opt > .ui-opt-lbl { flex: 1; }
.ui-opt-lbl { display: inline-flex; align-items: center; gap: 9px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-opt-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; box-shadow: 0 0 8px -1px currentColor; }

/* PasswordInput — кнопка показать/скрыть */
.ui-input--pw { padding-right: 38px; }
.ui-pw-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: var(--radius-sm); }
.ui-pw-toggle:hover { color: var(--text); background: var(--surface-2); }

/* TimePicker — поповер только с колонками времени (без бордюра календаря) */
.ui-timepop .ui-time { border-left: none; }

/* ===================== Alert ===================== */
/* Iris 2.0: иконка оповещения — в плитке своего тона (как значки разделов), фон — мягкий тон. */
.ui-alert { --al: var(--muted); display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; border-radius: var(--radius); border: 1px solid var(--border-strong); background: var(--surface-2); }
.ui-alert__icon {
  display: grid; place-items: center; flex: none; width: 26px; height: 26px; margin-top: -2px; border-radius: var(--radius-sm);
  color: var(--al); background: color-mix(in srgb, var(--al) 16%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--al) 28%, transparent);
}
.ui-alert__body { flex: 1; min-width: 0; }
.ui-alert__title { font-weight: 600; font-size: 13.5px; }
.ui-alert__msg { font-size: 13px; color: var(--muted); margin-top: 2px; }
/* С кнопкой действия: всё по центру строки, кнопка справа; на узком — переносится под текст. */
.ui-alert--action { align-items: center; flex-wrap: wrap; }
.ui-alert--action .ui-alert__icon { margin-top: 0; }
.ui-alert--action .ui-alert__msg { margin-top: 0; color: var(--text); }
.ui-alert__action { flex: none; margin-left: auto; display: flex; align-items: center; gap: var(--space-2); }
.ui-alert--info { background: var(--info-soft); border-color: color-mix(in srgb, var(--info) 40%, transparent); }
.ui-alert--info { --al: var(--info); }
.ui-alert--success { background: var(--success-soft); border-color: color-mix(in srgb, var(--success) 40%, transparent); }
.ui-alert--success { --al: var(--success); }
.ui-alert--warning { background: var(--warning-soft); border-color: color-mix(in srgb, var(--warning) 40%, transparent); }
.ui-alert--warning { --al: var(--warning); }
.ui-alert--danger { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.ui-alert--danger { --al: var(--danger); }

/* ===================== Toggles ===================== */
.ui-check, .ui-switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; user-select: none; }
.ui-check input, .ui-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.ui-check__box {
  width: 18px; height: 18px; border-radius: 6px; border: 1px solid var(--border-strong);
  background: var(--ctl-bg); box-shadow: var(--ctl-inset); display: grid; place-items: center; color: transparent; transition: .15s; flex: none;
}
.ui-check:hover .ui-check__box { border-color: color-mix(in srgb, var(--accent) 55%, var(--border-strong)); }
.ui-check input:checked + .ui-check__box { background: var(--grad); border-color: transparent; color: var(--on-accent); box-shadow: var(--pri-hl), 0 0 10px -3px var(--glow); }
.ui-check input:focus-visible + .ui-check__box { box-shadow: 0 0 0 3px var(--accent-soft); }

.ui-switch__track { width: 38px; height: 22px; border-radius: 999px; background: var(--surface-3); box-shadow: var(--ctl-inset), inset 0 0 0 1px var(--ctl-border); position: relative; transition: background .15s, box-shadow .15s; flex: none; }
.ui-switch__thumb { position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: var(--knob); box-shadow: 0 1px 3px rgba(0, 0, 0, .35); transition: transform .18s cubic-bezier(.2, .8, .2, 1.2); }
.ui-switch input:checked + .ui-switch__track { background: var(--grad); box-shadow: var(--pri-hl), 0 0 12px -3px var(--glow); }
.ui-switch input:checked + .ui-switch__track .ui-switch__thumb { transform: translateX(16px); }
.ui-switch input:focus-visible + .ui-switch__track { box-shadow: 0 0 0 3px var(--accent-soft); }

/* ===================== Badge / Chip / Avatar ===================== */
/* Iris 2.0: бейдж — мягкая заливка + тонкое кольцо своего цвета (currentColor — работает и для `color`-бейджей). */
.ui-badge { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: var(--radius-pill); font-size: 12px; font-weight: 600; box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 26%, transparent); }
.ui-badge--neutral { background: var(--surface-3); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }
.ui-badge--success { background: var(--success-soft); color: var(--success); }
.ui-badge--warning { background: var(--warning-soft); color: var(--warning); }
.ui-badge--danger { background: var(--danger-soft); color: var(--danger); }
.ui-badge--info { background: var(--info-soft); color: var(--info); }
.ui-badge--accent { background: var(--accent-soft); color: var(--accent); }
.ui-badge--gradient { background: var(--grad); color: var(--on-accent); box-shadow: var(--pri-hl), 0 4px 14px -6px var(--glow); }
/* Бейдж с цветной точкой перед текстом (проект, категория): `className="ui-badge--dot"`, цвет точки = цвет бейджа. */
.ui-badge--dot::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none; background: currentColor; box-shadow: 0 0 6px -1px currentColor; }

.ui-chip {
  padding: 6px 12px; border-radius: var(--radius-pill); border: 1px solid var(--ctl-border);
  color: var(--muted); font-size: 12px; cursor: pointer; background: var(--btn-bg); box-shadow: var(--btn-hl); transition: .15s;
}
.ui-chip:hover { color: var(--text); border-color: var(--border-strong); }
.ui-chip--on { color: var(--text); border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 12px -4px var(--glow); }

/* Iris 2.0: аватар — тёмный диск с градиентным кольцом Iris (инициалы — цветом текста), а не сплошной градиент. */
.ui-avatar {
  display: grid; place-items: center; border-radius: 50%; flex: none; overflow: hidden; font-weight: 700; color: var(--text);
  border: 1.5px solid transparent;
  background: linear-gradient(var(--surface-solid), var(--surface-solid)) padding-box, var(--grad) border-box;
  box-shadow: 0 4px 14px -8px var(--glow);
}
/* Фото в аватаре: квадратный кроп по центру — портреты из мессенджеров приходят разных пропорций. */
.ui-avatar__img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ===================== Progress / Spinner ===================== */
.ui-progress { height: 8px; width: 100%; background: var(--ctl-bg); box-shadow: var(--ctl-inset), inset 0 0 0 1px var(--ctl-border); border-radius: 999px; overflow: hidden; }
.ui-progress--thin { height: 4px; }
.ui-progress__bar { height: 100%; background: var(--grad); border-radius: 999px; transition: width .3s; box-shadow: 0 0 10px -2px var(--glow); }
.ui-spinner { border: 2px solid var(--surface-3); border-top-color: var(--accent); border-radius: 50%; animation: ui-spin .7s linear infinite; }
.ui-btn--primary .ui-spinner, .ui-btn--solid .ui-spinner { border-color: rgba(255,255,255,.35); border-top-color: var(--on-accent); }
@keyframes ui-spin { to { transform: rotate(360deg); } }

/* ===================== Card / KPI ===================== */
/* Iris 2.0: карточка — материал (лёгкий вертикальный градиент + блик по верхней кромке). */
.ui-card {
  background: var(--mat); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow), var(--mat-hl);
}
.ui-card--pad { padding: var(--space-5); }
/* Плоская карточка: та же геометрия, но без тени и заливки — в один ряд с `.ui-panel`. */
.ui-card--flat { background: transparent; box-shadow: none; }
.ui-card__title { font-weight: 600; margin-bottom: var(--space-3); }
/* Карточка-список (`Card pad={false}`): внутренних отступов у неё нет, поэтому заголовок несёт свои —
   иначе текст ложится вплотную на рамку и наезжает на неё. */
.ui-card:not(.ui-card--pad) > .ui-card__title { padding: var(--space-4) var(--space-4) 0; }

.ui-kpi { padding: 16px; min-width: 0; }
.ui-kpi__head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ui-kpi__label { color: var(--muted); font-size: 11.5px; font-weight: 500; letter-spacing: .02em; min-width: 0; }
.ui-kpi__value { font-size: 25px; font-weight: 700; margin-top: 6px; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.ui-kpi__delta { font-size: 12px; margin-top: 4px; }
.ui-kpi__delta--up { color: var(--success); }
.ui-kpi__delta--down { color: var(--warning); }
.ui-kpi__hint { color: var(--muted); font-size: 11.5px; margin-top: 3px; }
/* Цветной вариант: иконка в плашке своего цвета + значение тем же цветом. Цвет приходит пропом
   `color` (токен палитры --ic-*) через переменную --kpi-color. */
.ui-kpi--accent { position: relative; padding: 13px 14px; border-color: color-mix(in srgb, var(--kpi-color, var(--accent)) 26%, var(--border)); }
/* Iris 2.0: светящаяся кромка сверху цветом плитки — как у колонок канбана. */
.ui-kpi--accent::before {
  content: ''; position: absolute; left: 14px; right: 14px; top: -1px; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--kpi-color, var(--accent)) 25%, var(--kpi-color, var(--accent)) 75%, transparent);
  box-shadow: 0 0 10px color-mix(in srgb, var(--kpi-color, var(--accent)) var(--st-glow), transparent);
}
.ui-kpi--accent .ui-kpi__value { color: var(--kpi-color, var(--accent)); font-size: 22px; margin-top: 5px; }
/* Компактная плитка (`compact`): ростом с поле ввода — итоги стоят в одной строке с фильтрами реестра. */
.ui-kpi--compact { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 7px 12px; }
.ui-kpi--compact .ui-kpi__head { flex: none; }
.ui-kpi--compact .ui-kpi__value { font-size: 15px; font-weight: 700; margin-top: 0; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.ui-kpi--compact .ui-kpi__hint { margin-top: 0; }
.ui-kpi__ic {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--kpi-color, var(--accent)) 18%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kpi-color, var(--accent)) 30%, transparent), 0 0 14px -5px color-mix(in srgb, var(--kpi-color, var(--accent)) var(--st-glow), transparent);
  color: var(--kpi-color, var(--accent));
}

/* ===================== Tabs (pill) ===================== */
/* Контейнер-рамка; лента тянется мышью на узких экранах (scrollbar скрыт). */
.ui-tabs {
  display: flex; flex-wrap: nowrap; gap: 6px;
  /* Без подложки (контейнер прозрачный). padding нужен, чтобы overflow не обрезал свечение/рамку активной пилюли;
     отрицательный margin гасит этот отступ — визуально табы прижаты к краю, как без padding. */
  padding: 8px; margin: -8px;
  overflow-x: auto; scrollbar-width: none; cursor: grab;
  width: fit-content; max-width: calc(100% + 16px);
}
.ui-tabs::-webkit-scrollbar { display: none; }
/* Свайп по ленте не «пробрасывается» странице/браузеру (жест «назад» у края экрана перехватывал прокрутку). */
.ui-tabs { overscroll-behavior-x: contain; }
.ui-tabs:active { cursor: grabbing; }
.ui-tab {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 8px 14px;
  border: 1px solid var(--border); border-radius: var(--radius); background: transparent; color: var(--muted);
  cursor: pointer; font-size: 13px; font-weight: 500; font-family: var(--font); white-space: nowrap;
  transition: color .15s, background .15s, box-shadow .15s, border-color .15s;
}
.ui-tab:hover { color: var(--text); }
.ui-tab:not(.ui-tab--active):not(.ui-tab--done):hover { background: var(--btn-bg); border-color: var(--border-strong); }
.ui-tab__ic { display: inline-flex; align-items: center; transition: filter .15s, transform .15s; }
.ui-tab__label { line-height: 1; }
/* Пилюля с вторичной подписью (hint) под основной строкой — напр. время в стадии на ленте стадий сделки. */
.ui-tab--hint { flex-direction: column; align-items: center; gap: 3px; }
.ui-tab--hint .ui-tab__row { display: inline-flex; align-items: center; gap: 8px; }
.ui-tab__hint { line-height: 1; font-size: 10px; font-weight: 600; letter-spacing: .2px; opacity: .75; white-space: nowrap; }
/* Активная: акцент пункта (--tab-accent, по умолч. общий --accent) — мягкая заливка + свечение рамки. */
.ui-tab--active {
  color: var(--tab-accent, var(--accent)); border-color: transparent;
  background: color-mix(in srgb, var(--tab-accent, var(--accent)) 16%, transparent);
  box-shadow: 0 0 0 1.5px var(--tab-accent, var(--accent)), 0 0 10px color-mix(in srgb, var(--tab-accent, var(--accent)) 35%, transparent);
}
.ui-tab--active .ui-tab__ic { filter: drop-shadow(0 0 6px currentColor); transform: scale(1.08); }
/* Пройденная вкладка (прогресс-ленты, напр. стадии сделки): мягкая заливка цветом пункта, без свечения. */
.ui-tab--done {
  color: var(--tab-accent, var(--accent));
  background: color-mix(in srgb, var(--tab-accent, var(--accent)) 12%, transparent);
  border-color: color-mix(in srgb, var(--tab-accent, var(--accent)) 32%, transparent);
}
.ui-tab__count { background: var(--surface-3); color: var(--muted); border-radius: 999px; padding: 1px 7px; font-size: 11px; font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; }
.ui-tab--active .ui-tab__count { background: color-mix(in srgb, var(--tab-accent, var(--accent)) 18%, transparent); color: var(--tab-accent, var(--accent)); }
/* Градиентный бейдж Iris (`accent`) — держит цвет и на неактивной, и на активной вкладке. */
.ui-tab__count--accent, .ui-tab--active .ui-tab__count--accent { background: var(--grad); color: var(--on-accent); }
/* Лента-индикатор (read-only): без grab-курсора и без ховер-подсветки непройденных пунктов. */
.ui-tabs--readonly { cursor: default; }
.ui-tabs--readonly:active { cursor: default; }
.ui-tabs--readonly .ui-tab { cursor: default; }
.ui-tabs--readonly .ui-tab:not(.ui-tab--active):not(.ui-tab--done):hover { color: var(--muted); background: transparent; border-color: var(--border); }
/* Компактные пилюли (встраивание в списки/мини-карточки). */
.ui-tabs--compact { gap: 4px; }
.ui-tabs--compact .ui-tab { min-height: 26px; padding: 3px 9px; gap: 5px; font-size: 12px; }
/* ===================== GroupedBarChart (столбчатый график по группам) ===================== */
.ui-gbc { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
/* Область построения — высота относительная (clamp), столбики позиционируются от нулевой базы. */
.ui-gbc__plot { position: relative; display: flex; align-items: stretch; gap: 4px; height: clamp(140px, 22vh, 200px); }
.ui-gbc__zero { position: absolute; left: 0; right: 0; height: 0; border-top: 1px dashed var(--border); pointer-events: none; }
/* Колонка группы = триггер подсказки (кит Tooltip → span.ui-tip). Растягивается на всю высоту и делит ширину поровну. */
.ui-gbc__plot > .ui-tip { position: relative; flex: 1 1 0; min-width: 0; align-self: stretch; }
.ui-gbc__group { position: absolute; inset: 0; display: block; }
.ui-gbc__bar { position: absolute; border-radius: 3px 3px 0 0; transition: filter .15s; min-height: 2px; }
.ui-gbc__bar--neg { border-radius: 0 0 3px 3px; }
.ui-gbc__plot > .ui-tip:hover .ui-gbc__bar { filter: brightness(1.12); }
.ui-gbc__x { display: flex; gap: 4px; }
.ui-gbc__xlabel { flex: 1 1 0; min-width: 0; text-align: center; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; }
.ui-gbc__legend { display: flex; flex-wrap: wrap; gap: 12px; }
.ui-gbc__legitem { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12px; }
.ui-gbc__dot { width: 9px; height: 9px; border-radius: 3px; flex: none; }
/* Подсказка группы: заголовок + строки серий (значения — текстовыми токенами, цвет несёт точка). */
.ui-gbc__tip { display: flex; flex-direction: column; gap: 5px; min-width: 150px; }
.ui-gbc__tiphead { font-weight: 700; font-variant-numeric: tabular-nums; }
.ui-gbc__tiprow { display: flex; align-items: center; gap: 7px; }
.ui-gbc__tiplbl { color: var(--muted); }
.ui-gbc__tipval { margin-left: auto; font-variant-numeric: tabular-nums; }

/* Строка «табы + поиск + кнопка добавления» (контрагенты и т.п.). */
.cg-toprow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.cg-toprow__right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cg-search { width: min(260px, 42vw); }
/* Список контрагентов: таблица без подложки (как состав сделки), значения в ячейке — столбиком. */
.cg-tablewrap { min-width: 0; }
.cg-stack { display: flex; flex-direction: column; gap: 2px; min-width: 0; align-items: flex-start; }
/* Название компании — главная колонка: переносится по словам, а не режется многоточием. */
.cg-name { white-space: normal; text-align: left; }

/* ===================== Table ===================== */
/* Таблица живёт в карточке-подложке: рамка + фон + скруг­ление, горизонтальный скролл на узком контейнере. */
/* 🔴 Таблица БЕЗ карточки-подложки (фидбек 29.07.2026): строки-линии на фоне страницы,
   как в таблице состава сделки. Подложка под каждым списком давала лишний уровень поверхности. */
.ui-tablewrap { overflow: auto; max-width: 100%; }
.ui-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 14px; }
/* Заголовки переносятся ПО СЛОВАМ (не nowrap): длинная подпись над коротким числом («Компенсация налога»,
   «Скидка реселлера») иначе растягивает колонку на всю фразу и таблица перестаёт помещаться. */
.ui-table thead th {
  /* Липкая шапка непрозрачна (иначе строки просвечивают): фон ТЕКУЩЕЙ поверхности —
     страницы, слайдера или модалки (переменная --surface-bg). */
  position: sticky; top: 0; z-index: 1; background: var(--surface-bg, var(--bg));
  text-align: left; color: var(--muted); font-weight: 600; font-size: 11px; padding: 11px 16px;
  border-bottom: 1px solid var(--border); text-transform: uppercase; letter-spacing: .07em;
  /* Перенос ТОЛЬКО ПО СЛОВАМ: с `hyphens: auto` браузер рвал короткие заголовки по слогам
     («Сде-лок» в узкой колонке) — фидбек 19.08.2026. */
  white-space: normal; overflow-wrap: normal; hyphens: manual; vertical-align: bottom;
}
.ui-table tbody td { padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
/* 🔴 Числовые колонки (align:right) сжимаются ПО СОДЕРЖИМОМУ: `width:1%` в table-layout:auto = «минимально
   возможная», весь свободный остаток забирают текстовые колонки слева. Без этого браузер раздувал узкие
   колонки чисел («Наценка», «Компенсация налога») до трети экрана. Значения в них НЕ переносятся. */
.ui-table thead th.ui-td--right { width: 1%; }
.ui-table tbody td.ui-td--right { white-space: nowrap; }
.ui-table tbody tr:last-child td { border-bottom: none; }
/* Ховер-заливка — на ЯЧЕЙКАХ, а не на `tr`: фон строки не подчиняется скруглению угловых ячеек
   (border-collapse: separate) и торчал бы квадратом за скруглением подложки. */
.ui-table tbody td { transition: background .15s, box-shadow .15s; }
/* 🔴 Iris 2.0 (23.09.2026): строка при наведении — мягкая заливка + скруглённая обводка цветом `--st`
   (в слайдере со стадией — цвет стадии, иначе акцент), как строки состава сделки и карточки канбана.
   Обводка рисуется inset-тенями ячеек (у `tr` рамки и скругления нет); строки с тоном — без обводки. */
.ui-table tbody tr:hover > td { background: color-mix(in srgb, var(--st, var(--accent)) 7%, transparent); }
.ui-table tbody tr:not(.ui-tr--tone):hover > td { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--st, var(--accent)) 45%, transparent), inset 0 -1px 0 color-mix(in srgb, var(--st, var(--accent)) 45%, transparent); }
.ui-table tbody tr:not(.ui-tr--tone):hover > td:first-child {
  border-top-left-radius: var(--radius); border-bottom-left-radius: var(--radius);
  box-shadow: inset 1px 1px 0 color-mix(in srgb, var(--st, var(--accent)) 45%, transparent), inset 0 -1px 0 color-mix(in srgb, var(--st, var(--accent)) 45%, transparent);
}
.ui-table tbody tr:not(.ui-tr--tone):hover > td:last-child {
  border-top-right-radius: var(--radius); border-bottom-right-radius: var(--radius);
  box-shadow: inset -1px 1px 0 color-mix(in srgb, var(--st, var(--accent)) 45%, transparent), inset 0 -1px 0 color-mix(in srgb, var(--st, var(--accent)) 45%, transparent);
}
.ui-table tbody tr:not(.ui-tr--tone):hover > td:only-child { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 45%, transparent); }
.ui-table tbody tr.ui-tr--click { cursor: pointer; }
.ui-table tbody tr.ui-tr--click:hover > td { background: color-mix(in srgb, var(--st, var(--accent)) 10%, transparent); }
/* Строка, ждущая действия (проп `rowTone` у Table): полоса слева + лёгкая заливка — видно ВСЮ строку,
   а не значок в дальней колонке. Заливка, как и ховер, на ЯЧЕЙКАХ (см. выше), полоса — на первой из них. */
.ui-tr--tone-danger { --row-tone: var(--ic-red); }
.ui-tr--tone-warning { --row-tone: var(--ic-amber); }
.ui-tr--tone-success { --row-tone: var(--ic-green); }
.ui-table tbody tr.ui-tr--tone > td { background: color-mix(in srgb, var(--row-tone) 10%, transparent); }
.ui-table tbody tr.ui-tr--tone > td:first-child { box-shadow: inset 3px 0 0 var(--row-tone); }
.ui-table tbody tr.ui-tr--tone:hover > td { background: color-mix(in srgb, var(--row-tone) 16%, transparent); }
.ui-table .ui-td--right { text-align: right; font-variant-numeric: tabular-nums; }
/* Колонка по содержимому (`width: 'min'` у Column): `width:1%` = «минимально возможная»,
   весь остаток забирают обычные колонки — так название компании получает максимум места. */
.ui-table thead th.ui-td--min { width: 1%; }
.ui-table tbody td.ui-td--min { white-space: nowrap; }
/* Колонка по содержимому (`width: 'min'` у Column): `width:1%` в table-layout:auto = «минимально возможная»,
   весь остаток забирают обычные колонки. Так название компании получает максимум места. */
.ui-table thead th.ui-td--min { width: 1%; }
.ui-table tbody td.ui-td--min { white-space: nowrap; }
/* Колонка-«тянучка» (`width: 'grow'` у Column): забирает весь свободный остаток, а слишком
   длинное значение усекается многоточием. `max-width: 0` в table-layout:auto = «предпочтительная ширина
   минимальна», `width: 100%` — «забери остаток»; вместе это даёт усечение вместо распирания таблицы. */
.ui-table thead th.ui-td--grow { width: 100%; }
/* min-width — страховка от схлопывания: в table-layout:auto min важнее max, поэтому колонка
   никогда не уже этого предела, даже если соседи просят больше места. */
.ui-table tbody td.ui-td--grow { max-width: 0; min-width: min(14rem, 40vw); overflow: hidden; text-overflow: ellipsis; }
.ui-table tbody td.ui-td--grow > * { max-width: 100%; }
/* Таблица, вставленная ПРЯМО в карточку (`Card pad={false}`): у `.ui-card` нет `overflow: hidden`
   (иначе sticky-шапка перестала бы липнуть при скролле страницы), поэтому квадратные углы заливки
   шапки и ховера последней строки вылезали за скругление карточки. Скругляем угловые ячейки сами;
   −1px — на рамку карточки. */
.ui-card > .ui-table thead tr:first-child th:first-child { border-top-left-radius: calc(var(--radius-lg) - 1px); }
.ui-card > .ui-table thead tr:first-child th:last-child { border-top-right-radius: calc(var(--radius-lg) - 1px); }
.ui-card > .ui-table tbody tr:last-child td:first-child { border-bottom-left-radius: calc(var(--radius-lg) - 1px); }
.ui-card > .ui-table tbody tr:last-child td:last-child { border-bottom-right-radius: calc(var(--radius-lg) - 1px); }

/* ===================== Modal / Drawer ===================== */
/* Подложка под модалкой/слайдером — только затемнение, БЕЗ backdrop-filter (решение 0090):
   размытие выносило подложку в отдельный GPU-слой (DirectComposition), из-за чего запись экрана
   через GDI-захват мерцала — в кадр попадал экран из-под слайдера. Плюс при стеке A→B→C
   пересчитывалось несколько полноэкранных блюров на каждой перерисовке страницы под ними. */
.ui-overlay { position: fixed; inset: 0; background: var(--overlay-bg); z-index: 1000; animation: ui-fade .15s; }
@keyframes ui-fade { from { opacity: 0; } }
.ui-modal {
  --surface-bg: var(--modal-bg); /* фон поверхности — для липкой шапки таблиц внутри */
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1001;
  width: min(440px, calc(100vw - 32px)); background: var(--modal-bg); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-pop); animation: ui-pop .16s ease-out;
  color: var(--text); font-family: var(--font);
  display: flex; flex-direction: column; max-height: calc(100dvh - 32px);
  /* Iris 2.0: мягкое свечение акцента в верхнем углу — фоном, под содержимым. */
  background:
    radial-gradient(70% 10rem at 15% 0, color-mix(in srgb, var(--accent) calc(var(--st-tint) * 2), transparent), transparent 72%) no-repeat,
    var(--modal-bg);
}
/* Светящаяся кромка сверху (как у слайдера); отступ от краёв — чтобы не заходить на скругление углов. */
.ui-modal::before {
  content: ''; position: absolute; left: 18px; right: 18px; top: -1px; height: 1px; z-index: 2; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--accent) 25%, var(--accent) 75%, transparent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--accent) var(--st-glow), transparent);
}
@keyframes ui-pop { from { opacity: 0; transform: translate(-50%, -46%); } }
.ui-modal__head, .ui-drawer__head { display: flex; align-items: center; justify-content: space-between; padding: 18px 20px; border-bottom: 1px solid var(--border); }
.ui-modal__title, .ui-drawer__title { font-weight: 700; font-size: 16px; letter-spacing: -.01em; }
.ui-modal__head, .ui-modal__foot { flex: none; }
/* Карточка товара (lg): фиксированная высота — окно и вкладки не прыгают при смене вкладок, контент скроллится внутри */
.ui-modal--lg { width: min(960px, calc(100vw - 32px)); height: min(82vh, 780px); }
/* Карточка товара (xl): широкая витрина-обзор */
.ui-modal--xl { width: min(1180px, calc(100vw - 32px)); height: min(88vh, 880px); }
/* Плавающий крестик закрытия для модалки без шапки */
.ui-modal__close { position: absolute; top: 12px; right: 12px; z-index: 3; }
.ui-modal__body, .ui-drawer__body { padding: 20px; }
.ui-modal__body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.ui-modal__foot, .ui-drawer__foot { display: flex; justify-content: flex-end; gap: 8px; padding: 16px 20px; border-top: 1px solid var(--border); }

/* Drawer (слайдер) — фиксированная ширина: занимает всю область справа от левого меню
   (левый край ровно у сайдбара). Ширину задаёт раскладка (left..right), проп width не нужен. */
.ui-drawer {
  --st: var(--accent); /* цвет подсветки (проп `accent`, по умолчанию акцент) */
  --surface-bg: var(--drawer-bg); /* фон поверхности — для липкой шапки таблиц внутри */
  position: fixed; top: 0; right: 0; bottom: 0; left: var(--sidebar-w); z-index: 1001;
  /* Iris 2.0: мягкое свечение цветом стадии в верхнем углу — фоном, под содержимым (не перекрывает текст). */
  background:
    radial-gradient(60% 14rem at 12% 0, color-mix(in srgb, var(--st) calc(var(--st-tint) * 3), transparent), transparent 72%) no-repeat,
    var(--drawer-bg);
  border-left: 1px solid var(--border-strong); box-shadow: var(--shadow-pop); display: flex; flex-direction: column;
  animation: ui-slide .2s ease-out; color: var(--text); font-family: var(--font);
}
/* Светящаяся кромка сверху цветом стадии. */
.ui-drawer::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 1px; z-index: 2; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--st) 20%, var(--st) 70%, transparent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--st) var(--st-glow), transparent);
}
@keyframes ui-slide { from { transform: translateX(100%); } }
.ui-drawer__body { flex: 1; overflow: auto; }
/* Плавающий крестик для drawer без шапки (напр. карточка-витрина товара) */
.ui-drawer__close { position: absolute; top: 12px; right: 12px; z-index: 3; }
/* Крестик ЗА левой границей слайдера — плавающая круглая кнопка в зазоре над сайдбаром (карточка сделки) */
.ui-drawer__close--left {
  left: -48px; right: auto; top: 16px;
  background: var(--surface-2); border: 1px solid var(--border-strong);
  border-radius: 999px; box-shadow: var(--shadow-pop);
}
.ui-drawer__close--left:hover { background: var(--surface-3); }
/* 🔴 Значок подсказок — за левой границей слайдера, ВНИЗУ (правило заказчика 31.08.2026): пояснения не занимают
   строки карточки, а живут в одном тултипе. Геометрия — как у крестика, только снизу. */
.ui-drawer__help {
  /* 🔴 Приподнят над подвалом сайдбара (03.09.2026): на bottom:16px круглый значок ложился ровно на
     аватар и кнопки внизу левого меню — две круглые кнопки в одной точке. Высота подвала (`ui-sidebar__foot`
     ≈ 50px) плюс зазор. */
  position: absolute; left: -48px; right: auto; bottom: 76px; z-index: 3;
  background: var(--surface-2); border: 1px solid var(--border-strong);
  border-radius: 999px; box-shadow: var(--shadow-pop); color: var(--muted);
}
.ui-drawer__help:hover { background: var(--surface-3); color: var(--text); }
.ui-drawer__hintlist { display: flex; flex-direction: column; gap: 6px; text-align: left; }
.ui-drawer__hint { display: block; }

/* ===================== Layout: Sidebar / Topbar / AppShell ===================== */
.ui-shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; height: 100vh; height: 100dvh; }
.ui-main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* Плашка «нет связи» (`app/NetStatus.tsx`): лежит между топбаром и контентом, ширину берёт от оболочки —
   ничего не фиксируем в px, чтобы не ломать раскладку на узких экранах. */
.ui-netstatus { padding: var(--content-pad) var(--content-pad) 0; }
.ui-netstatus__row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-width: 0; }
.ui-netstatus__row > span { flex: 1 1 240px; min-width: 0; }

/* Топбар фиксирован, прокручивается только контент (страница не «уезжает»).
   Отступ страницы — переменная (на узких экранах меньше); снизу добавляется высота мобильной
   нижней навигации + безопасная зона, иначе последняя строка/кнопка прячется под панелью. */
.ui-content {
  padding: var(--content-pad); flex: 1; min-height: 0; overflow-y: auto;
  padding-bottom: calc(var(--content-pad) + var(--bottomnav-h) + var(--safe-b));
}

/* Сайдбар всегда закреплён у верха вьюпорта (не уходит за верхнюю границу при скролле); прокручивается внутри себя, если длинный. */
.ui-sidebar { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 0; border-right: 1px solid var(--border); padding: 18px 12px; background: var(--sidebar-bg); }
.ui-sidebar__top { padding: 0 4px 4px; }
.ui-sidebar__nav { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.ui-sidebar__nav::-webkit-scrollbar { width: 0; display: none; }
.ui-sidebar__foot { display: flex; align-items: center; gap: 4px; padding-top: 12px; margin-top: 8px; border-top: 1px solid var(--border); }
.ui-brand { display: flex; align-items: center; gap: 10px; padding: 6px 10px 14px; }
/* Марка в шапке сайдбара и на логине — знак TOPODRONE (компонент Logo). Размер задаётся пропом height,
   белые части знака идут на currentColor: на тёмной теме светлые, на светлой — тёмные. */
.ui-brand__mark { display: block; flex: none; color: var(--text); }
.ui-brand__name { font-weight: 700; letter-spacing: .3px; }
.ui-brand__sub { color: var(--muted); font-size: 11px; }
.ui-navgroup { margin-top: 14px; }
.ui-navgroup__title { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .6px; padding: 4px 10px; }
.ui-navitem { position: relative; display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 9px; color: var(--text); cursor: pointer; margin: 2px 0; opacity: .86; background: none; border: none; width: 100%; font: inherit; text-align: left; }
.ui-navitem:hover { background: var(--hover); opacity: 1; }
/* Iris 2.0: иконка раздела — в плитке своего цвета (`--st` пункта); у активного плитка ярче и светится. */
.ui-navitem__ic {
  width: 26px; height: 26px; display: grid; place-items: center; flex: none; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--st, var(--accent)) 12%, transparent); transition: background .15s, box-shadow .2s;
}
/* 🔴 Iris 2.0 (23.09.2026): активный раздел светится ЦВЕТОМ СВОЕЙ ИКОНКИ (`--st` ставит Sidebar), а не общим акцентом:
   мягкая заливка + тонкая обводка + ореол, метка слева и иконка — тем же цветом со свечением. */
.ui-navitem--active {
  background: color-mix(in srgb, var(--st, var(--accent)) 13%, transparent); opacity: 1;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 26%, transparent), 0 0 18px -10px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
.ui-navitem--active:hover { background: color-mix(in srgb, var(--st, var(--accent)) 19%, transparent); opacity: 1; }
.ui-navitem--active::before {
  content: ''; position: absolute; left: 0; top: 7px; bottom: 7px; width: 3px; border-radius: 0 3px 3px 0;
  background: var(--st, var(--accent)); box-shadow: 0 0 8px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
.ui-navitem--active .ui-navitem__ic {
  background: color-mix(in srgb, var(--st, var(--accent)) 24%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 35%, transparent), 0 0 16px -3px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
/* SectionNav — меню разделов внутри страницы (настройки): слева колонка, справа содержимое. */
.ui-sectionlayout { display: grid; grid-template-columns: clamp(13rem, 17vw, 16rem) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.ui-sectionlayout__main { min-width: 0; }
.ui-sectionnav { position: sticky; top: 0; display: flex; flex-direction: column; }
.ui-sectionnav__group:first-child { margin-top: 0; }
.ui-sectionnav__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 900px) {
  .ui-sectionlayout { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .ui-sectionnav { position: static; flex-direction: row; overflow-x: auto; gap: var(--space-1); padding-bottom: 4px; }
  .ui-sectionnav__group { display: contents; }
  .ui-sectionnav .ui-navgroup__title { display: none; }
  .ui-sectionnav .ui-navitem { width: auto; flex: none; }
}
.ui-navitem__badge { margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--grad); color: var(--on-accent); font-size: 11px; font-weight: 700; line-height: 18px; text-align: center; flex: none; }

.ui-topbar { display: flex; align-items: center; gap: 14px; padding: 12px var(--space-6); border-bottom: 1px solid var(--border); background: var(--topbar-bg); }
.ui-topbar__search { flex: 1; max-width: 440px; }

/* ===================== Мобильный каркас: верхняя полоска + нижняя навигация ===================== */
/* Рендерятся каркасом только на компакт-ширине (useIsCompact), поэтому своих @media не требуют. */
.ui-mtop {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: 8px var(--content-pad); border-bottom: 1px solid var(--border); background: var(--topbar-bg);
  padding-top: calc(8px + env(safe-area-inset-top, 0px));
}
.ui-mtop__burger {
  flex: none; display: grid; place-items: center; width: 38px; height: 38px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--text); cursor: pointer;
}
.ui-mtop__burger:active { background: var(--surface-3); }
.ui-mtop__title { flex: 1; min-width: 0; font-weight: 700; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-mtop__right { flex: none; display: flex; align-items: center; gap: 6px; }

/* Затемнение под выехавшим меню (на компакт-ширине меню плавает поверх контента). */
.ui-navscrim { position: fixed; inset: 0; z-index: 1090; background: var(--overlay-bg); animation: ui-fade .15s; }

/* Нижняя навигация: 4 главных раздела + «Ещё». Высота — токен --bottomnav-h (на неё закладываются
   отступы контента/тостов), плюс безопасная зона снизу. */
.ui-bnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
  display: flex; align-items: stretch;
  height: calc(var(--bottomnav-h) + var(--safe-b)); padding-bottom: var(--safe-b);
  background: var(--pop-bg); border-top: 1px solid var(--border-strong);
}
.ui-bnav__item {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  padding: 6px 2px; border: none; background: none; color: var(--muted); font: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ui-bnav__item--active { color: var(--accent); }
.ui-bnav__item--active .ui-bnav__ic { background: var(--accent-soft); }
.ui-bnav__ic {
  position: relative; display: grid; place-items: center; width: 40px; height: 26px;
  border-radius: var(--radius-pill); transition: background .15s;
}
.ui-bnav__lbl { font-size: 10.5px; font-weight: 600; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-bnav__badge {
  position: absolute; top: -3px; right: 2px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px; background: var(--grad); color: var(--on-accent);
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
}

/* ===================== Утилиты раскладки витрины ===================== */
.ui-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.ui-stack { display: flex; flex-direction: column; gap: 12px; }
.ui-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.ui-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }

/* 🔴 Сетка полей формы — ЕДИНЫЙ примитив кита (не писать инлайн `gridTemplateColumns: '1fr 1fr'`:
   на телефоне такие сетки оставляли две нечитаемые колонки). N колонок на широком экране,
   одна — на телефоне (см. раздел адаптивности). `--label` — раскладка «метка → поле». */
.ui-formgrid { display: grid; gap: 14px; min-width: 0; }
.ui-formgrid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ui-formgrid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ui-formgrid--label { grid-template-columns: minmax(0, 11rem) minmax(0, 1fr); gap: 12px; }
.ui-page-title { font-size: 24px; font-weight: 800; letter-spacing: -.3px; background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }

/* ===================== Notification badge ===================== */
.ui-notif { position: relative; display: inline-flex; }
.ui-notif__count {
  position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px; background: var(--danger); color: var(--on-accent); font-size: 10px; font-weight: 700;
  display: grid; place-items: center; box-shadow: 0 0 0 2px var(--bg), 0 0 10px -2px var(--danger); pointer-events: none;
}

/* ===================== Radio ===================== */
.ui-radio { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; user-select: none; }
.ui-radio input { position: absolute; opacity: 0; width: 0; height: 0; }
.ui-radio__dot {
  width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--border-strong);
  background: var(--ctl-bg); box-shadow: var(--ctl-inset); display: grid; place-items: center; transition: .15s; flex: none;
}
.ui-radio:hover .ui-radio__dot { border-color: color-mix(in srgb, var(--accent) 55%, var(--border-strong)); }
.ui-radio__dot::after { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--on-accent); transform: scale(0); transition: transform .15s; }
.ui-radio input:checked + .ui-radio__dot { background: var(--grad); border-color: transparent; box-shadow: var(--pri-hl), 0 0 10px -3px var(--glow); }
.ui-radio input:checked + .ui-radio__dot::after { transform: scale(1); }
.ui-radio input:focus-visible + .ui-radio__dot { box-shadow: 0 0 0 3px var(--accent-soft); }
.ui-radio input:disabled + .ui-radio__dot { opacity: .5; }
.ui-radiogroup { display: flex; flex-direction: column; gap: 10px; }
.ui-radiogroup--row { flex-direction: row; flex-wrap: wrap; gap: 16px; }

/* ===================== TagInput ===================== */
.ui-taginput { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 7px 9px; cursor: text; }
.ui-taginput:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft), 0 0 18px -6px var(--glow); }
.ui-tag {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 4px 3px 9px; border-radius: var(--radius-pill);
  background: var(--accent-soft); color: var(--accent); font-size: 12.5px; font-weight: 600;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 26%, transparent);
}
.ui-tag__x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; padding: 0; line-height: 0; border: none; border-radius: 50%; background: transparent; color: inherit; cursor: pointer; opacity: .7; flex: none; }
.ui-tag__x:hover { opacity: 1; background: var(--overlay-hover); }
.ui-tag--plain { background: var(--surface-3); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }
.ui-taginput__field { flex: 1; min-width: 80px; border: none; outline: none; background: transparent; color: var(--text); font: inherit; padding: 3px 2px; }
.ui-taginput__field::placeholder { color: var(--muted); }

/* ===================== MultiSelect ===================== */
.ui-multiselect { height: auto; min-height: 42px; align-items: center; padding: 6px 9px; }
.ui-multiselect__tags { display: flex; flex-wrap: wrap; gap: 5px; flex: 1; min-width: 0; }
.ui-ms__search { padding: 2px 2px 8px; }
.ui-ms__search .ui-input { padding: 8px 11px; }
.ui-ms__empty { padding: 9px 10px; color: var(--muted); font-size: 13px; text-align: center; }
.ui-ms__check {
  width: 18px; height: 18px; border-radius: 5px; border: 1px solid var(--border-strong);
  background: var(--surface-2); display: grid; place-items: center; color: var(--on-accent); flex: none; transition: .15s;
}
.ui-ms__check[data-on="true"] { background: var(--grad); border-color: transparent; box-shadow: var(--pri-hl), 0 0 10px -3px var(--glow); }

/* ===================== Tooltip ===================== */
.ui-tip { display: inline-flex; max-width: 100%; outline: none; }
.ui-tip--block { display: block; width: 100%; min-width: 0; }
/* Обрезка текста с многоточием (компонент Ellipsis). Одна строка — nowrap; N строк — line-clamp. */
.ui-ellipsis { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-ellipsis--multi { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; }
.ui-tip__pop {
  position: fixed; z-index: 1300; pointer-events: none;
  max-width: 320px; width: max-content; white-space: normal; overflow-wrap: anywhere;
  font-size: 12px; line-height: 1.35; font-weight: 500; color: var(--text);
  background: var(--surface-solid);
  border: 1px solid var(--tip-border); padding: 7px 11px; border-radius: 10px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55), var(--mat-hl);
  animation: ui-tip-in .12s ease-out;
}
@keyframes ui-tip-in { from { opacity: 0; } to { opacity: 1; } }
/* Стрелка — по горизонтали следует за триггером (--arrow-x), угол в сторону триггера. */
.ui-tip__pop::after {
  content: ''; position: absolute; width: 9px; height: 9px; left: var(--arrow-x, 50%); margin-left: -4.5px;
  background: var(--surface-solid); border: 1px solid var(--tip-border); transform: rotate(45deg);
}
.ui-tip__pop[data-side="top"]::after    { bottom: -5px; border-top: none; border-left: none; }
.ui-tip__pop[data-side="bottom"]::after { top: -5px; border-bottom: none; border-right: none; }

/* Маркер-предупреждение в строке списка (WarnMark): треугольник, не сжимается и не растягивает строку.
   Тон: warning — янтарный («обрати внимание»), danger — красный («сущности больше нет»). */
.ui-warnmark { display: inline-flex; align-items: center; flex: none; color: var(--ic-amber); cursor: help; }
.ui-warnmark--danger { color: var(--danger); }

/* ===================== Skeleton ===================== */
.ui-skeleton { display: inline-block; background: var(--surface-2); position: relative; overflow: hidden; }
.ui-skeleton::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--shimmer), transparent);
  transform: translateX(-100%); animation: ui-shimmer 1.4s infinite;
}
@keyframes ui-shimmer { to { transform: translateX(100%); } }

/* ===================== EmptyState ===================== */
.ui-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; padding: 40px 20px; }
.ui-empty__icon {
  display: grid; place-items: center; width: 60px; height: 60px; border-radius: 16px; margin-bottom: 4px;
  background: var(--mat); color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--border-strong), var(--mat-hl), 0 14px 34px -18px var(--glow);
}
.ui-empty__title { font-weight: 600; font-size: 15px; }
.ui-empty__desc { color: var(--muted); font-size: 13px; max-width: 320px; }
.ui-empty__action { margin-top: 8px; }

/* ===================== Toast ===================== */
.ui-toasts { position: fixed; left: 20px; bottom: 20px; z-index: 1400; display: flex; flex-direction: column; gap: 10px; width: min(360px, calc(100vw - 40px)); }
/* Iris 2.0 (23.09.2026): тон тоста — светящейся кромкой сверху (`--toast-c`) вместо полосы слева. */
.ui-toast {
  --toast-c: var(--accent);
  position: relative; display: flex; align-items: center; gap: 10px; padding: 12px 12px 12px 14px;
  background: radial-gradient(80% 5rem at 10% 0, color-mix(in srgb, var(--toast-c) 10%, transparent), transparent 75%) no-repeat, var(--pop-bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-pop), var(--mat-hl); animation: ui-toast-in .2s ease-out;
}
.ui-toast::before {
  content: ''; position: absolute; left: 14px; right: 14px; top: -1px; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--toast-c) 20%, var(--toast-c) 80%, transparent);
  box-shadow: 0 0 10px color-mix(in srgb, var(--toast-c) var(--st-glow), transparent);
}
@keyframes ui-toast-in { from { opacity: 0; transform: translateX(-20px); } }
.ui-toast__icon { display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--radius-sm); flex: none; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--toast-c) 28%, transparent); }
.ui-toast__body { flex: 1; min-width: 0; }
.ui-toast__title { font-weight: 600; font-size: 13.5px; }
.ui-toast__msg { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.ui-toast--success { --toast-c: var(--success); }
.ui-toast--success .ui-toast__icon { background: var(--success-soft); color: var(--success); }
.ui-toast--danger { --toast-c: var(--danger); }
.ui-toast--danger .ui-toast__icon { background: var(--danger-soft); color: var(--danger); }
.ui-toast--warning { --toast-c: var(--warning); }
.ui-toast--warning .ui-toast__icon { background: var(--warning-soft); color: var(--warning); }
.ui-toast--info { --toast-c: var(--info); }
.ui-toast--info .ui-toast__icon { background: var(--info-soft); color: var(--info); }

/* ===================== Menu (Dropdown) ===================== */
.ui-menu__trigger { display: inline-flex; }
.ui-menu { padding: 6px; min-width: 180px; }
.ui-menu__item {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 9px 10px; border: none;
  background: transparent; color: var(--text); font: inherit; font-size: 13.5px; text-align: left;
  border-radius: 8px; cursor: pointer;
}
.ui-menu__item { transition: background .12s; }
.ui-menu__item:hover:not(:disabled) { background: var(--btn-bg-hover); }
.ui-menu__item:disabled { opacity: .45; cursor: not-allowed; }
.ui-menu__item--danger { color: var(--danger); }
.ui-menu__item--danger:hover:not(:disabled) { background: var(--danger-soft); }
.ui-menu__sep { height: 1px; background: var(--border); margin: 5px 4px; }

/* ===================== SegmentedControl ===================== */
.ui-seg { display: inline-flex; padding: 3px; gap: 2px; background: var(--ctl-bg); border: 1px solid var(--ctl-border); border-radius: var(--radius); box-shadow: var(--ctl-inset); }
.ui-seg--block { display: flex; }
.ui-seg__btn { flex: 1; padding: 7px 14px; border: none; background: transparent; color: var(--muted); font: inherit; font-size: 13px; font-weight: 600; border-radius: 9px; cursor: pointer; transition: .15s; white-space: nowrap; }
.ui-seg__btn:hover { color: var(--text); }
/* Iris 2.0: активный сегмент — как активная вкладка (мягкая заливка акцентом + светящаяся обводка). */
.ui-seg__btn--on {
  background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent), 0 0 12px -4px var(--glow);
}

/* ===================== Breadcrumbs ===================== */
.ui-crumbs { display: flex; flex-wrap: wrap; align-items: center; font-size: 13px; }
.ui-crumbs__item { display: inline-flex; align-items: center; }
.ui-crumbs__link { border: none; background: none; color: var(--muted); cursor: pointer; font: inherit; padding: 0; text-decoration: none; }
.ui-crumbs__link { transition: color .12s; }
.ui-crumbs__link:hover { color: var(--accent); }
.ui-crumbs__txt { color: var(--muted); }
.ui-crumbs__cur { color: var(--text); font-weight: 600; }
.ui-crumbs__sep { display: inline-flex; color: var(--muted); margin: 0 6px; opacity: .6; }

/* ===================== Pagination ===================== */
.ui-pager { display: inline-flex; align-items: center; gap: 4px; }
.ui-pager__btn {
  min-width: 34px; height: 34px; padding: 0 8px; display: grid; place-items: center;
  border: 1px solid var(--ctl-border); background: var(--btn-bg); color: var(--text); box-shadow: var(--btn-hl);
  border-radius: var(--radius-sm); cursor: pointer; font: inherit; font-size: 13px; font-variant-numeric: tabular-nums; transition: .15s;
}
.ui-pager__btn:hover:not(:disabled) { background: var(--btn-bg-hover); border-color: var(--border-strong); }
.ui-pager__btn:disabled { opacity: .4; cursor: not-allowed; }
.ui-pager__btn--on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 700; box-shadow: 0 0 12px -4px var(--glow); }
.ui-pager__gap { min-width: 24px; text-align: center; color: var(--muted); }

/* ===================== Stepper ===================== */
.ui-stepper { display: flex; }
.ui-step { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; }
.ui-step__marker {
  width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; z-index: 1;
  font-size: 13px; font-weight: 700; border: 1px solid var(--border-strong); background: var(--ctl-bg); box-shadow: var(--ctl-inset); color: var(--muted);
}
.ui-step--current .ui-step__marker { background: var(--grad); color: var(--on-accent); border: none; box-shadow: 0 0 16px -4px var(--glow); }
.ui-step--done .ui-step__marker { background: var(--accent-soft); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 60%, transparent); box-shadow: none; }
.ui-step__label { font-size: 13px; font-weight: 600; }
.ui-step--todo .ui-step__label { color: var(--muted); }
.ui-step__desc { color: var(--muted); font-size: 11.5px; margin-top: 2px; }
.ui-step__line { position: absolute; top: 16px; left: calc(50% + 20px); width: calc(100% - 40px); height: 2px; background: var(--border); z-index: 0; }
.ui-step--done .ui-step__line { background: var(--grad); box-shadow: 0 0 8px -1px var(--glow); }

/* ===================== Kanban ===================== */
/* Доска занимает всю доступную высоту; скроллятся только тела колонок (страница статична). */
.ui-kanwrap { position: relative; height: 100%; display: flex; flex-direction: column; min-height: 0; }
.ui-kanban { display: flex; gap: 14px; overflow-x: auto; align-items: flex-start; flex: 1; min-height: 0; padding-bottom: 4px; scroll-behavior: smooth; scrollbar-width: none; scroll-snap-type: x proximity; }
.ui-kanban::-webkit-scrollbar { height: 0; display: none; }
/* Панель стрелок прокрутки — над доской, справа (не перекрывает заголовки колонок). */
.ui-kan-tools { display: flex; justify-content: flex-end; gap: 6px; margin-bottom: 8px; }
.ui-kan-tools .ui-iconbtn { background: var(--btn-bg); border: 1px solid var(--ctl-border); border-radius: 999px; box-shadow: var(--btn-hl); }
.ui-kan-tools .ui-iconbtn:hover { background: var(--btn-bg-hover); }
/* 🔴 Iris 2.0 (23.09.2026): колонка «светится» цветом своей стадии — `--st` ставит Kanban.tsx из `column.color`
   (нет цвета → акцент). Тонкая светящаяся линия по верхней кромке + мягкая заливка верха; сила — токены `--st-*`
   (в светлой теме слабее). Ширина — относительная: колонки делят экран, но не уже ~17.5rem и не шире 26rem. */
.ui-kan-col {
  --st: var(--accent);
  position: relative; display: flex; flex-direction: column; min-height: 0; max-height: 100%;
  flex: 1 0 clamp(17.5rem, 18%, 21rem); min-width: 0; max-width: 26rem; scroll-snap-align: start;
  background: linear-gradient(180deg, color-mix(in srgb, var(--st) var(--st-tint), transparent), transparent 9rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px;
  transition: background .15s, border-color .15s, box-shadow .2s;
}
.ui-kan-col::before {
  content: ''; position: absolute; left: 16px; right: 16px; top: -1px; height: 1px; border-radius: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--st) 22%, var(--st) 78%, transparent);
  box-shadow: 0 0 12px 0 color-mix(in srgb, var(--st) var(--st-glow), transparent);
}
.ui-kan-col--over {
  border-color: color-mix(in srgb, var(--st) 45%, transparent);
  box-shadow: 0 0 40px -18px color-mix(in srgb, var(--st) var(--st-glow), transparent);
}
.ui-kan-col__head--grab { cursor: grab; user-select: none; touch-action: none; }
.ui-kan-col__head--grab:active { cursor: grabbing; }
.ui-kan-col__ic {
  display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--st) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st) 26%, transparent);
}
.ui-kan-ph { height: 40px; border: 2px dashed color-mix(in srgb, var(--st) 65%, transparent); border-radius: var(--radius); background: color-mix(in srgb, var(--st) 8%, transparent); flex: none; }
.ui-kan-col__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; padding: 0 2px; }
.ui-kan-col__title { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; }
.ui-kan-col__count {
  background: color-mix(in srgb, var(--st) 14%, transparent); color: color-mix(in srgb, var(--st) 60%, var(--text));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st) 24%, transparent);
  border-radius: 999px; padding: 1px 8px; font-size: 11px; font-weight: 600; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
/* Вертикальный padding 8px (компенсируется отрицательным margin — карточки на месте): даёт запас,
   чтобы линия-индикатор вставки у самой верхней/нижней карточки не обрезалась областью прокрутки. */
/* 🔴 Зазор до заголовка при прокрутке (фидбек 23.09.2026): край прокрутки отстоит от шапки на 6px, а карточки
   плавно гаснут у верхнего/нижнего края (маска 8px) — не упираются срезом прямо в заголовок стадии. В покое маска
   ложится на пустой padding и карточек не касается. */
.ui-kan-col__body {
  display: flex; flex-direction: column; gap: 8px; flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none;
  padding: 10px 6px 8px; margin: 0 -6px -8px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 8px, #000 calc(100% - 8px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 8px, #000 calc(100% - 8px), transparent 100%);
}
.ui-kan-col__body::-webkit-scrollbar { width: 0; display: none; }
/* Стрелки прокрутки доски, вынесенные страницей в свою шапку (проп scrollRef). На телефоне скрываются —
   там стадии листаются свайпом, а положение показывают точки Kanban. */
.kan-scrollnav { display: inline-flex; gap: 6px; }

/* Панель-секция (Panel) — бордер-контейнер с заголовком «иконка+название+счётчик», как колонки канбана. */
.ui-panel { display: flex; flex-direction: column; min-width: 0; min-height: 0; background: transparent; border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px; }
.ui-panel--fill { flex: 1; }
.ui-panel__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; padding: 0 2px; }
.ui-panel__title { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; min-width: 0; }
.ui-panel__ic { display: inline-grid; place-items: center; flex: none; }
/* Iris 2.0: панель с цветной иконкой (`ui-panel--tint`, `--st` = iconColor) — иконка в плитке своего цвета и светящаяся
   кромка сверху (фоном: без position и псевдоэлементов — не меняет раскладку вложенного). */
.ui-panel--tint {
  background-image: linear-gradient(90deg, transparent, var(--st) 20%, var(--st) 80%, transparent);
  background-size: calc(100% - 32px) 1px; background-position: center top; background-repeat: no-repeat; background-origin: border-box;
}
.ui-panel--tint > .ui-panel__head .ui-panel__ic {
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--st) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st) 26%, transparent);
}
.ui-panel__aside { display: inline-flex; align-items: center; gap: 8px; flex: none; }
.ui-panel__count { background: var(--surface-3); color: var(--muted); border-radius: 999px; padding: 1px 8px; font-size: 11px; font-weight: 600; font-family: var(--font-mono); font-variant-numeric: tabular-nums; flex: none; }
.ui-panel__body { display: flex; flex-direction: column; gap: 12px; min-width: 0; min-height: 0; }
.ui-panel--fill .ui-panel__body { flex: 1; }

/* Слайдеры контрагентов (компания/контакт): шапка + скроллируемое тело с панелями. */
.cg-drawer .ui-drawer__body { display: flex; flex-direction: column; overflow: hidden; }
.cg-card { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 14px; }
.cg-head { display: flex; align-items: center; gap: 10px; }
.cg-head__ic { display: inline-grid; place-items: center; flex: none; }
.cg-head__num { color: var(--muted); font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; flex: none; }
.cg-head__title { font-size: 20px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Тело слайдера — две колонки (пополам): слева инфо+контакты, справа реквизиты. Каждая колонка скроллится сама. */
.cg-cols { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: stretch; }
.cg-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.cg-col::-webkit-scrollbar { width: 0; height: 0; }
/* Панели в колонке НЕ сжимаются ниже своей высоты — иначе их содержимое (overflow:visible) вылезает и налезает на соседнюю панель; вместо этого прокручивается сама колонка. */
.cg-col > .ui-panel { flex: none; }
@media (max-width: 900px) { .cg-cols { grid-template-columns: 1fr; overflow-y: auto; } .cg-col { overflow: visible; } }
.cg-rolespop { padding: 10px; min-width: min(280px, 80vw); }
/* Персональная ссылка реселлера на прайс — строка инфо-списка карточки: показывается МАСКИРОВАННОЙ
   (целиком уходит только в буфер), поэтому не переносится и не растягивает строку. */
.cg-plink { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: help; }
/* Подпись набора цен реселлера бывает длинной («Для экспорта (0% НДС) — ООО …») — не распирает строку инфо. */
.cg-pvariant { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Слайдер «Прайс для реселлеров» (состояние снимка + что не попало). */
.plist { display: flex; flex-direction: column; gap: 14px; }
.plist__facts { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); }
.plist__fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.plist__cap { font-size: 12px; color: var(--muted); }
.plist__val { font-size: 13px; }
.plist__hint { margin-top: var(--space-3); font-size: 12px; color: var(--muted); line-height: 1.45; }
.plist__err { margin-top: var(--space-3); display: flex; align-items: center; gap: var(--space-2); font-size: 12px; color: var(--danger); flex-wrap: wrap; }
.plist__cat, .plist__skip { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.plist__cat > span:first-child { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plist__skipname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Бар вкладок «Инфо / Сделки» — в строке шапки, справа от названия (перед кнопкой удаления). */
.cg-head__tabs { flex: none; margin-left: auto; }
/* Вкладка «Сделки» — список на всю ширину, скроллится сам (скроллбар скрыт). */
.cg-mailtab { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.cg-mailtab::-webkit-scrollbar { width: 0; height: 0; }
/* Вкладка «Сделки»: суб-табы (Продажи/Ремонты/Аренда) закреплены сверху, список сделок скроллится сам. */
.cg-dealstab { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* Бар суб-табов: слева типы сделок (ужимаются), справа кнопка создания — прижата краем, не сжимается. */
.cg-dealstab__bar { flex: none; margin-bottom: 10px; display: flex; align-items: center; gap: 10px; min-width: 0; }
.cg-dealstab__bar > :first-child { min-width: 0; }
.cg-dealstab__add { margin-left: auto; flex: none; }
.cg-dealstab__list { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.cg-dealstab__list::-webkit-scrollbar { width: 0; height: 0; }
/* Вкладка «Файлы» — блок файлов (Panel fill) на всю высоту; своя прокрутка внутри тела панели. */
.cg-filestab { flex: 1; min-height: 0; display: flex; }
/* Блок банковских реквизитов (несколько на владельца) */
.cg-bank__add { margin-top: 4px; }
/* Список связанных сущностей (контакты у компании, компании у контакта): выровненные колонки (иконка · имя · телефон · почта) через subgrid —
   флаги телефонов и конверты почт стоят на одной вертикали у всех строк; телефон/почта прижаты вправо (имя = 1fr). */
.cg-contacts { display: grid; grid-template-columns: auto 1fr auto auto auto; row-gap: 8px; column-gap: 12px; }
.cg-crow {
  display: grid; grid-template-columns: subgrid; grid-column: 1 / -1; align-items: center;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 10px 12px; cursor: pointer; color: inherit; text-align: left;
  transition: background .15s, border-color .15s;
}
.cg-crow { transition: background .15s, border-color .15s, box-shadow .2s; }
.cg-crow:hover { background: color-mix(in srgb, var(--st, var(--accent)) 10%, var(--surface-3)); border-color: color-mix(in srgb, var(--st, var(--accent)) 50%, transparent); box-shadow: 0 0 22px -10px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent); }
.cg-crow__ic { display: inline-grid; place-items: center; flex: none; }
.cg-crow__name { min-width: 0; display: flex; align-items: baseline; gap: 8px; overflow: hidden; }
.cg-crow__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.cg-crow__inn { color: var(--muted); font-size: 12px; flex: none; white-space: nowrap; }
.cg-crow__phone, .cg-crow__email { justify-self: start; min-width: 0; }
.cg-crow__act { justify-self: end; display: inline-flex; }
/* Кнопка «сделать основным»: рыжий человек → при наведении блеклая галочка (иконки наложены через grid-area). */
.cg-primabtn { position: relative; width: 26px; height: 26px; display: inline-grid; place-items: center; border: none; background: none; padding: 0; cursor: pointer; }
.cg-primabtn__person, .cg-primabtn__check { grid-area: 1 / 1; display: inline-grid; place-items: center; transition: opacity .15s; }
.cg-primabtn__check { opacity: 0; color: var(--muted); }
.cg-primabtn:hover .cg-primabtn__person { opacity: 0; }
.cg-primabtn:hover .cg-primabtn__check { opacity: .65; }
/* Канал в строке связанной сущности (телефон/почта) — [иконка-действие][копировать], БЕЗ текста значения
   (значение в тултипе): ширину строки не занимает, поэтому имя (+ИНН) получает максимум места. */
.cg-chan { display: inline-flex; align-items: center; flex: none; }
.cg-chan .ui-iconbtn, .cg-chan .ui-copybtn { width: 26px; height: 26px; flex: none; }
/* Карточка связанной сделки: № · стадия · сумма · маржа + превью позиций (сколько влезет в строку). */
.cg-deals { display: flex; flex-direction: column; gap: 8px; }
.cg-deal {
  display: flex; flex-direction: column; gap: 8px; width: 100%; text-align: left; cursor: pointer;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius);
  color: inherit; font: inherit; padding: 10px 12px; transition: background .15s, border-color .15s;
}
.cg-deal { transition: background .15s, border-color .15s, box-shadow .2s; }
.cg-deal:hover { background: color-mix(in srgb, var(--st, var(--accent)) 10%, var(--surface-3)); border-color: color-mix(in srgb, var(--st, var(--accent)) 50%, transparent); box-shadow: 0 0 22px -10px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent); }
/* Одна строка: № · лента стадий (сжимается и скроллится сама) · сумма · маржа. */
.cg-deal__head { display: flex; align-items: center; gap: 10px; min-width: 0; flex-wrap: nowrap; }
.cg-deal__num { font-weight: 700; font-variant-numeric: tabular-nums; flex: none; }
.cg-deal__head > .ui-tabs { min-width: 0; } /* лента отдаёт место №/сумме/марже, при нехватке — свой горизонт. скролл */
.cg-deal__sum { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; flex: none; }
.cg-deal__margin { font-variant-numeric: tabular-nums; flex: none; }
/* Узкий (compact) вид мини-сделки: бейдж текущей стадии вместо ленты (иконка + название стадии). */
.cg-deal__stage { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.cg-deal__stage .ui-badge__txt, .cg-deal__stage { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cg-deal__thumbs { display: flex; gap: 6px; overflow: hidden; flex-wrap: nowrap; }
/* Превью позиции — размер как на карточке канбана (квадрат ~52px, contain). */
.cg-deal__thumb { flex: 0 0 auto; width: 52px; aspect-ratio: 1; object-fit: contain; border-radius: 7px; background: var(--photo-bg); border: 1px solid var(--border); padding: 2px; }
/* Навигационные ссылки-названия (каталог/контакты/компании): без цвета и подчёркивания — только курсор-палец. */
.cg-tablelink { background: none; border: none; padding: 0; font: inherit; color: inherit; cursor: pointer; text-align: left; }
/* Колонка «Сделки» в списках контрагентов — ряд кликабельных бейджей активных сделок (иконка+цвет стадии, номер). */
.cg-dealbadges { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.cg-dealbadge { border: none; background: transparent; padding: 0; cursor: pointer; display: inline-flex; }
/* Карточка наследует `--st` колонки. Наведение (Iris 2.0): рамка и ореол цветом стадии вместо заливки акцентом.
   Рамка — обычный border (градиентная рамка маской утончается в углах — пройдено на лендинге, см. .ui-ring). */
.ui-kan-card { position: relative; background: var(--surface-solid); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; transition: background .15s, border-color .15s, box-shadow .2s; }
.ui-kan-card:hover {
  background: color-mix(in srgb, var(--st, var(--accent)) 7%, var(--surface-solid));
  border-color: color-mix(in srgb, var(--st, var(--accent)) 55%, transparent);
  box-shadow: 0 0 22px -8px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent),
    0 14px 34px -18px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
.ui-kan-card--drag { opacity: .45; }
/* Линия места вставки — наложение в зазоре между карточками (gap 8px), раскладку не двигает. */
.ui-kan-card--itop::before, .ui-kan-card--ibot::after {
  content: ''; position: absolute; left: 0; right: 0; height: 3px; border-radius: 3px;
  background: var(--st, var(--accent)); box-shadow: 0 0 8px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
.ui-kan-card--itop::before { top: -5px; }
.ui-kan-card--ibot::after { bottom: -5px; }

/* Карточка сделки на доске: ID · блок контрагента (имя/ИНН/юрлицо) · блок финансов (сумма/маржа).
   Блоки разделены линиями; все строки — метка слева (приглушённо) + значение справа (моно-цифры). */
.deal-card { display: flex; flex-direction: column; gap: 10px; cursor: pointer; }
/* Номер + бейдж типа ремонта в одной строке (бейдж по правому краю). */
.deal-card__idrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/* Ручка перетаскивания — только номер (верх карточки). */
.deal-card__id {
  font-family: var(--font-mono); font-size: 17px; font-weight: 700; letter-spacing: -.01em; font-variant-numeric: tabular-nums;
  text-shadow: 0 0 18px color-mix(in srgb, currentColor var(--st-text), transparent);
  cursor: grab; user-select: none; align-self: flex-start;
}
.deal-card__id:active { cursor: grabbing; }
.deal-card__info, .deal-card__fin { display: flex; flex-direction: column; gap: 5px; padding-top: 9px; border-top: 1px solid var(--border); }
.deal-card__cp { font-weight: 600; font-size: 14px; line-height: 1.3; word-break: break-word; }
/* Время в текущей стадии — вторичная, неброская строка (по требованию заказчика). */
.deal-card__stagetime { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--muted); opacity: .85; }
.deal-card__stagetime svg { opacity: .8; }
.deal-card__contact { font-size: 12px; font-weight: 500; color: var(--text); margin-top: 1px; }
.deal-card__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px; }
.deal-card__row > span:first-child { color: var(--muted); flex: none; }
.deal-card__row > span:last-child { color: var(--text); text-align: right; font-variant-numeric: tabular-nums; word-break: break-word; }
.deal-card__row > b { text-align: right; font-variant-numeric: tabular-nums; }
.deal-card__sum { font-size: 15px; font-weight: 700; color: var(--text); }
.deal-card__margin { font-size: 14px; font-weight: 600; }
/* Превью фото товаров сделки — один ряд, ровно 4 по ширине карточки; 5-е и далее обрезаются. */
.deal-card__thumbs { display: flex; gap: 5px; overflow: hidden; padding-top: 9px; margin-top: 2px; border-top: 1px solid var(--border); }
.deal-card__thumb { flex: 0 0 calc((100% - 15px) / 4); min-width: 0; width: 0; aspect-ratio: 1; object-fit: contain; border-radius: 7px; background: var(--photo-bg); border: 1px solid var(--border); padding: 2px; }

/* 🔴 Шапка страницы — ЕДИНЫЙ примитив кита (фидбек 21.07.2026: «поиск всегда справа от заголовка, а не под ним»).
   Раскладка: заголовок сжимается, поиск занимает свободное место справа от него, действия — в конце строки.
   Адаптивно: ширина поиска через clamp(), у заголовка min-width:0 + ellipsis; на узком экране строка переносится. */
.ui-pagehead { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.ui-pagehead__title { margin: 0; font-size: 22px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Поиск идёт сразу за заголовком; ширина относительная, `min-width:0` — чтобы не выдавливать соседей. */
/* Подсказка везде короткая («Поиск») — поле и сделано узким: место в шапке нужно фильтрам и действиям
   (фидбек 19.08.2026). */
.ui-pagehead__search { flex: 0 1 clamp(150px, 16%, 240px); min-width: 0; max-width: min(240px, 100%); }
/* Модификатор для шапок, где ПОСЛЕ поиска идут только действия справа (переключатель вида, кнопки):
   auto-отступ прижимает их к правому краю. Не нужен там, где следом идёт растягивающийся блок (напр. лента табов). */
.ui-pagehead__search--push { margin-right: auto; }

/* Страница сделок: тулбар статичен, доска заполняет остаток высоты (канбан со скроллом внутри колонок);
   список — со своим вертикальным скроллом. */
.deals-page { display: flex; flex-direction: column; height: 100%; }
.deals-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.deals-body--scroll { overflow-y: auto; }

/* Карточка сделки (слайдер). Шапка: крупный номер + крупный бейдж стадии (цвета иконки) со стрелкой смены + статус. */
.deal-head { flex: 1; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.deal-head__num { font-size: 28px; font-weight: 800; letter-spacing: .3px; font-variant-numeric: tabular-nums; }
.deal-head__grp { display: flex; align-items: center; gap: 4px; }
.deal-head__stage .ui-badge { font-size: 15px; padding: 6px 14px; }
.deal-head__stage .ui-badge svg { width: 16px; height: 16px; }
/* Блок сумм сделки — крупно (как ID), рядом: сумма к оплате | маржа. */
.deal-totals { display: flex; justify-content: space-between; gap: 20px; }
.deal-total { min-width: 0; }
.deal-total:last-child:not(:first-child) { text-align: right; } /* маржа/остаток — по правому краю; единственный блок в строке остаётся слева */
.deal-total__label { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin-bottom: 4px; }
.deal-total__val { font-size: 26px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Обзор сделки: слева — информация (узкая, но адаптивная колонка), справа — лента активности с полем комментария сверху.
   Ширина левой колонки масштабируется (~40% контейнера) с мягкими пределами через clamp — без жёсткого px. */
/* Карточка сделки: верхняя панель (номер+стадии слева, История/Удалить справа); крестик плавает слева. */
/* Карточка сделки фиксирована по высоте слайдера; скроллит содержимое колонок (правая: комплектация + документы). */
.deal-drawer .ui-drawer__body { display: flex; flex-direction: column; overflow: hidden; }
.deal-card2 { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 16px; }
.deal-card2__top { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
/* Плавающие иконки (История/Удалить) ЗА левым краем слайдера, у самого низа — как крестик закрытия сверху,
   круглые кнопки в зазоре над сайдбаром. z-index скромный → перекрываются слайдерами каталога/истории. */
.deal-actions-float { position: fixed; left: calc(var(--sidebar-w) - 48px); bottom: 16px; z-index: 3; display: flex; flex-direction: column; gap: 8px; }
.deal-actions-float .ui-iconbtn { width: 36px; height: 36px; background: var(--btn-bg); border: 1px solid var(--ctl-border); border-radius: 999px; box-shadow: var(--shadow-pop), var(--btn-hl); }
.deal-actions-float .ui-iconbtn:hover { background: var(--btn-bg-hover); border-color: var(--border-strong); }

/* Слева инфо (до ~460px), справа — комплектация + документы. Колонки заполняют высоту и скроллятся каждая сама. */
.deal-overview { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 0.48fr) minmax(0, 1fr); gap: 16px; align-items: stretch; }
.deal-overview__col { display: flex; flex-direction: column; gap: 14px; min-width: 0; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.deal-overview__col::-webkit-scrollbar { width: 0; height: 0; }
/* Правая колонка НЕ скроллит сама: сверху комплектация (растягивается), снизу документы (≤50% со своим скроллом). */
.deal-right { overflow: hidden; }
@media (max-width: 900px) { .deal-overview { grid-template-columns: 1fr; overflow-y: auto; } .deal-overview__col { overflow: visible; } }

/* Вкладки полного экрана (Инфо/Товары) — сразу справа от номера сделки. */
.deal-head__viewtabs { flex: none; }

/* Вкладка «Товары» — полный список позиций на всю ширину слайдера. */
.deal-tabpanel--items { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* Вкладка «Документы» — дерево на всю ширину со своим скроллом (docs-wrap растягивается). */
.deal-tabpanel--docs { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; scrollbar-width: thin; }
.deal-tabpanel--docs .docs-wrap { flex: 1; min-height: 0; max-height: none; }

/* Разделённый таб «Документы»: слева схема (своя прокрутка), справа блок файлов на подложке (Panel fill). */
.deal-tabpanel--docs-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, clamp(24rem, 42%, 40rem)); gap: 16px; align-items: stretch; overflow: hidden; }
.deal-tabpanel--docs-split .deal-docs-split__schema { min-width: 0; min-height: 0; overflow-y: auto; scrollbar-width: thin; }
.deal-tabpanel--docs-split .deal-docs-split__schema .docs-wrap { flex: 1; min-height: 0; max-height: none; }
.deal-tabpanel--docs-split .deal-docs-split__files { min-width: 0; min-height: 0; display: flex; }
/* ≤900px: одна колонка — но FLEX, а не grid (grid сжимал бы строки до min-content = 0 у детей
   с `min-height: 0`, и схема с файлами наложились бы друг на друга, как во вкладке «Инфо»). */
@media (max-width: 900px) {
  .deal-tabpanel--docs-split { display: flex; flex-direction: column; overflow-y: auto; }
  .deal-tabpanel--docs-split .deal-docs-split__schema,
  .deal-tabpanel--docs-split .deal-docs-split__files { flex: none; overflow: visible; }
}

/* Блок «Файлы»: загрузка сверху, список со своей прокруткой (внутри тела Panel fill). */
/* Слайдер-редактор исходящего письма (создаётся из блока «Файлы»; карточки писем — в стиле .files-card). */
.letter-editor { display: flex; flex-direction: column; gap: 14px; min-height: 0; }
.letter-editor__addr { display: flex; flex-direction: column; gap: 10px; }
.letter-editor__row2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.letter-editor__foot { display: flex; gap: 8px; flex-wrap: wrap; }

/* Журнал СФ: строка фильтров (год, юрлицо) + итоги года СПРАВА в той же строке — над таблицей,
   а не под ней (фидбек 19.08.2026). На узком экране итоги переезжают на следующую строку (flex-wrap). */
.journal-filters { margin-bottom: 12px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.journal-totals { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: stretch; }

/* Раздел «Шаблоны» — раскрывающийся список доступных модификаторов шаблона. */
.tpl-tokens { display: flex; flex-direction: column; gap: 2px; padding: 12px; background: var(--mat); box-shadow: var(--mat-hl); border-radius: var(--radius-sm); }
/* Кнопки действий в ячейке таблицы шаблонов — одной строкой, на узком экране переносятся. */
.tpl-acts { display: inline-flex; gap: 4px; align-items: center; justify-content: flex-end; }
.tpl-tokbtn { display: inline-flex; align-items: center; gap: 4px; }
.tpl-tokens__row { display: grid; grid-template-columns: max-content max-content minmax(0, 1fr); align-items: center; gap: 10px; padding: 3px 0; }
.tpl-tokens__code { justify-self: start; white-space: nowrap; }
.tpl-tokens__label { min-width: 0; color: var(--muted); font-size: 13px; }

.files-panel { display: flex; flex-direction: column; gap: 12px; min-height: 0; }
/* Весь блок «Файлы» — зона перетаскивания; кнопки действий строкой сверху. */
.files-dnd { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; border-radius: var(--radius); }
.files-dnd--over { outline: 2px dashed var(--accent); outline-offset: -3px; }
.files-panel__actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.files-dnd__overlay { position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; border-radius: var(--radius); border: 2px dashed var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--surface-2)); color: var(--accent); font-weight: 600; pointer-events: none; }
.files-panel__state { display: grid; place-items: center; padding: 24px 0; }
.files-list { min-height: 0; overflow-y: auto; scrollbar-width: thin; display: flex; flex-direction: column; gap: 10px; }
/* Группа по дню создания (как лента событий): заголовок-дата один на весь день, файлы под ним без своих дат. */
.files-group { display: flex; flex-direction: column; gap: 6px; }
.files-day { margin: 2px 0; }
.files-day span { display: inline-block; font-size: 11.5px; color: var(--muted); background: var(--btn-bg); border: 1px solid var(--ctl-border); box-shadow: var(--btn-hl); border-radius: var(--radius-pill); padding: 3px 12px; font-variant-numeric: tabular-nums; }
.files-cards { display: flex; flex-direction: column; gap: 8px; }
/* Карточка файла — как карточка документа в схеме (.doccard), но без линий дерева: подложка, рамка, цветной левый акцент. */
/* Карточка файла — как карточка документа: заливка + цветная полоска формата, без серой окантовки. */
/* Iris 2.0: как карточка документа — материал, плитка значка цвета формата, ореол при наведении. */
.files-card { display: flex; align-items: stretch; gap: 4px; background: linear-gradient(90deg, color-mix(in srgb, var(--doc-accent, var(--muted)) 6%, transparent), transparent 55%), var(--mat), var(--surface-2); box-shadow: var(--mat-hl); border: 0; border-radius: var(--radius); overflow: hidden; transition: box-shadow .2s; }
.files-card:has(> .files-card__body:hover) { box-shadow: var(--mat-hl), 0 0 22px -10px color-mix(in srgb, var(--doc-accent, var(--accent)) var(--st-glow), transparent); }
.files-card__body { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 8px 10px; text-align: left; background: none; border: 0; cursor: pointer; color: var(--text); transition: background .15s; }
.files-card__body:hover { background: color-mix(in srgb, var(--doc-accent, var(--accent)) 8%, transparent); }
.files-card__ic { flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--doc-accent, var(--muted)) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--doc-accent, var(--muted)) 26%, transparent); }
.files-card__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.files-card__title { display: flex; align-items: center; gap: 6px; min-width: 0; }
.files-card__name { font-size: 13px; font-weight: 600; color: var(--text); min-width: 0; }
.files-card__num { flex: none; font-size: 12px; }
/* Бейдж формата файла (PDF/DOCX/XLS…) — цветом акцента карточки. */
.files-card__fmt { flex: none; font-size: 9.5px; font-weight: 700; letter-spacing: .03em; line-height: 1; padding: 3px 5px; border-radius: var(--radius-sm); color: var(--doc-accent); background: color-mix(in srgb, var(--doc-accent) 16%, transparent); }
.files-card__sign { flex: none; display: inline-flex; align-items: center; gap: 3px; font-size: 10px; font-weight: 600; line-height: 1; padding: 3px 6px; border-radius: 999px; border: 1px solid currentColor; background: color-mix(in srgb, currentColor 12%, transparent); }
.files-card__meta { font-size: 11.5px; color: var(--muted); }
.files-card__acts { flex: none; display: flex; align-items: center; padding: 2px 4px 2px 0; }

/* Диалог загрузки: карточка на каждый файл (шапка + поля тип/дата/номер). */
.upl { display: flex; flex-direction: column; gap: 12px; }
.upl-row { border: 1px solid var(--border); border-radius: var(--radius); background: var(--mat); box-shadow: var(--mat-hl); padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.upl-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.upl-name { font-size: 13px; font-weight: 600; color: var(--text); min-width: 0; }
.upl-size { flex: none; font-size: 11.5px; color: var(--muted); margin-left: auto; }
.upl-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 10px; }
.upl-foot { display: flex; gap: 10px; }
/* Строка ожидания внутри карточки загрузки (спиннер по центру) — пока грузятся цели «Добавить в файлы». */
.upl-state { display: flex; justify-content: center; padding: 12px 0; }
/* Слайдер «Отправить на email»: короткая форма (адресат + формат + заверение).
   🔴 Контент — УЗКОЙ КОЛОНКОЙ СЛЕВА (фидбек 20.07.2026): поля во всю ширину слайдера выглядят некрасиво.
   Ширина относительная (`min()`) — колонка сжимается на узком экране, а не режется. */
.senddoc { display: flex; flex-direction: column; gap: 14px; width: min(26rem, 100%); }
.senddoc__doc { font-size: 13px; font-weight: 600; color: var(--text); }
.senddoc__state { display: grid; place-items: center; padding: 20px 0; }
.senddoc__group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.senddoc__label { font-size: 12px; color: var(--muted); }
.senddoc__row { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.senddoc__warn { font-size: 12px; color: var(--warning); }
.senddoc__hint { font-size: 12px; line-height: 1.5; color: var(--muted); }
.senddoc__foot { display: flex; gap: 10px; }

/* Факсимиле юрлица (подпись/печать) в карточке юрлица: два слота с превью и кнопкой загрузки. */
.facsimile { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 14px; }
.facsimile__slot { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.facsimile__head { display: flex; align-items: center; gap: 6px; }
.facsimile__label { font-size: 12px; color: var(--muted); }
.facsimile__head .ui-iconbtn { margin-left: auto; }
.facsimile__box {
  display: grid; place-items: center; min-height: clamp(4.5rem, 12vh, 7rem);
  border: 1px dashed var(--border); border-radius: var(--radius-md); background: var(--surface-2); padding: 8px;
}
.facsimile__img { max-width: 100%; max-height: clamp(4rem, 11vh, 6.5rem); object-fit: contain; }
.facsimile__empty { font-size: 12px; color: var(--muted); }
.facsimile__hint { grid-column: 1 / -1; font-size: 12px; line-height: 1.5; color: var(--muted); }


/* Корзина (Настройки портала): строки удалённых файлов + срок хранения + восстановить/удалить навсегда. */
/* Настройки — во всю ширину страницы, как остальные разделы (фидбек 31.07.2026). */
.settings-page { max-width: 100%; }
.trash-state { display: grid; place-items: center; padding: 40px 0; }
.trash-list { display: flex; flex-direction: column; gap: 8px; }
.trash-card { display: flex; align-items: center; gap: 10px; background: var(--mat), var(--surface-2); box-shadow: var(--mat-hl); border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 12px; }
.trash-card__ic { flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--doc-accent, var(--muted)) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--doc-accent, var(--muted)) 26%, transparent); }
.trash-card__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.trash-card__title { display: flex; align-items: center; gap: 6px; min-width: 0; }
.trash-card__name { font-size: 13px; font-weight: 600; color: var(--text); min-width: 0; }
.trash-card__meta { font-size: 11.5px; color: var(--muted); }
.trash-card__left { flex: none; font-size: 12px; color: var(--muted); white-space: nowrap; }
.trash-card__left--soon { color: var(--danger); }
.trash-card__acts { flex: none; display: flex; align-items: center; gap: 2px; }

/* Слайдер-превью файла: тело (изображение/PDF) тянется, кнопки прижаты снизу. */
.filepv { display: flex; flex-direction: column; min-height: 0; height: 100%; gap: 12px; }
.filepv__body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
.filepv__state { flex: 1; display: grid; place-items: center; }
.filepv__img { max-width: 100%; height: auto; margin: auto; border-radius: var(--radius-md); }
.filepv__foot { flex: none; display: flex; gap: 10px; }

/* ---- Редактор простановки подписи/печати на PDF (PdfSignEditor) ---- */
.sign-drawer .ui-drawer__body { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.sign { display: flex; min-height: 0; height: 100%; }
.sign__side {
  flex: none; width: clamp(180px, 22%, 260px); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 12px; padding: 14px; overflow: auto; background: var(--surface);
}
.sign__side-hint { font-size: 12px; color: var(--muted); line-height: 1.4; }
.sign__side-state { display: grid; place-items: center; padding: 20px 0; }
.sign-ent { display: flex; flex-direction: column; gap: 8px; }
.sign-ent__name { font-size: 12px; font-weight: 600; color: var(--muted); min-width: 0; overflow-wrap: anywhere; }
.sign-ent__thumbs { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.sign-thumb {
  display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 8px 6px; min-width: 0;
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-2); cursor: pointer;
}
.sign-thumb:hover { border-color: var(--accent); }
.sign-thumb--active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.sign-thumb img { width: 100%; height: 44px; object-fit: contain; }
.sign-thumb span { font-size: 11px; color: var(--muted); }

.sign__main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.sign__doc { flex: 1; min-height: 0; overflow: auto; padding: 16px; display: flex; flex-direction: column; align-items: center; gap: 16px; background: var(--surface-2); }
.sign__state { padding: 40px 0; display: grid; place-items: center; }
.sign-page {
  position: relative; flex: none; width: 100%; max-width: 900px; background: #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,0.18); border-radius: 2px; overflow: hidden;
}
.sign-page__canvas { display: block; width: 100%; height: auto; }
.sign-page__layer { position: absolute; inset: 0; container-type: size; } /* container-type → размер текста в cqh (% высоты страницы) */
.sign-page--armed .sign-page__layer { cursor: crosshair; }
.sign-item { position: absolute; touch-action: none; cursor: move; }
.sign-item img { width: 100%; height: 100%; object-fit: fill; pointer-events: none; user-select: none; }
.sign-item--sel { outline: 1.5px dashed var(--accent); outline-offset: 1px; }
/* Текстовое поле: ВСЕГДА редактируемое (клик — курсор, сразу набор), один шрифт, размер на всё поле (font-size в cqh).
   Перетаскивание — за грип (появляется при выделении), а не за сам текст. */
.sign-item--text { cursor: default; }
.sign-text { white-space: pre; color: #111; padding: 0 0.1em; min-width: 10px; min-height: 1em; outline: none; cursor: text; caret-color: #111; }
.sign-text:empty::before { content: attr(data-ph); color: rgba(0, 0, 0, 0.35); pointer-events: none; }
.sign-item__grip {
  position: absolute; left: 0; top: 0; transform: translate(-50%, -110%); display: grid; place-items: center;
  width: 20px; height: 18px; border-radius: 4px; background: var(--accent); color: #fff; cursor: move; touch-action: none;
}
/* Инструмент «Текстовое поле» и степпер размера шрифта */
.sign-tool {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--surface-2); cursor: pointer; color: var(--text); font-size: 13px;
}
.sign-tool:hover { border-color: var(--accent); }
.sign-tool--active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.sign-fs { display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.sign-fs button { width: 26px; height: 28px; border: none; background: var(--surface-2); cursor: pointer; color: var(--text); font-size: 15px; }
.sign-fs button:hover { background: var(--surface-3); }
.sign-fs__val { padding: 0 8px; font-size: 12px; font-variant-numeric: tabular-nums; min-width: 46px; text-align: center; }
.sign-item__del {
  position: absolute; top: -10px; right: -10px; width: 20px; height: 20px; display: grid; place-items: center;
  border: none; border-radius: 50%; background: var(--danger); color: #fff; cursor: pointer; padding: 0;
}
.sign-item__handle {
  position: absolute; right: -7px; bottom: -7px; width: 14px; height: 14px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--drawer-bg); cursor: nwse-resize; touch-action: none;
}
.sign__foot { flex: none; display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--border); }

/* Вкладка «Инфо» — 3 колонки: сводка · документы · товары (узкая, по контенту превью). */
.deal-overview--info { grid-template-columns: minmax(0, 0.55fr) minmax(0, 1fr) max-content; }
@media (max-width: 900px) { .deal-overview--info { grid-template-columns: 1fr; } }
/* Центральная колонка: «Документы» по контенту (автовысота) сверху + «События» на всё оставшееся место со своим скроллом. */
.deal-docs-col { overflow: hidden; }
.deal-docs-col .docs-wrap { flex: none; max-height: none; }
.deal-docs-col .deal-events { flex: 1; min-height: 0; }
/* Тело «Событий»: лента скроллится, кнопка «Добавить»/композер прижаты снизу. */
.deal-events__body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.deal-events__feed { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.deal-events__feed::-webkit-scrollbar { width: 0; height: 0; display: none; }
.deal-events__add { flex: none; padding-top: 8px; }
.deal-events__composer { flex: none; padding-top: 8px; display: flex; flex-direction: column; gap: 8px; }
.deal-events__composer-acts { display: flex; justify-content: flex-end; gap: 8px; }
/* Колонка товаров: панель на всю высоту, вертикальный список превью со своим скроллом. */
.deal-items-col { overflow: hidden; }

/* Товары (вкладка «Инфо»): сетка квадратных превью 90px в 2 колонки (слева-направо, сверху-вниз: 1 2 / 3 4 / …), свой скролл. */
.deal-thumbcol { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(2, 90px); gap: 8px; align-content: start; overflow-y: auto; overflow-x: hidden; scrollbar-width: none; }
.deal-thumbcol::-webkit-scrollbar { width: 0; height: 0; }
.deal-thumb {
  width: 90px; height: 90px; position: relative; overflow: hidden; padding: 0;
  border-radius: 12px; border: 1px solid var(--border); background: var(--surface-3);
  display: grid; place-items: center; color: var(--muted);
}
.deal-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; background: var(--photo-bg); }
.deal-thumb--link { cursor: pointer; font: inherit; }
/* Кол-во товара — маленький бейдж на скруглённой квадратной тёмной подложке в правом нижнем углу превью. */
.deal-thumb__qty {
  position: absolute; right: 4px; bottom: 4px; min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 6px;
  background: var(--photo-badge-bg); color: var(--on-accent);
  font-size: 11px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
}

/* ---- Блок «Документы» (под комплектацией): своя область высотой не более половины колонки, свой скролл ---- */
.docs-wrap { flex: 0 1 auto; min-height: 0; max-height: 50%; }
.docs-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 14px; overflow: auto; container-type: inline-size; }

/* Схема связей: вертикальное древо (как файловое) — корень сверху, дочерние ветви ниже с отступом.
   Линия из родителя уходит ВНИЗ, затем ВПРАВО к каждому дочернему блоку (занимает больше высоты, меньше ширины). */
.doctree { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; min-width: 0; max-width: 100%; }
.doctree__node { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
/* Дочерние ветви — колонка ниже родителя с отступом; вертикальная шина слева + отводы к карточкам. */
/* Коннектор-«уголок»: ось вертикали проходит по ЦЕНТРУ значка родителя (X=26 — воображаемо от центра значка вниз),
   но ВИДИМАЯ линия начинается от КРАЯ БЛОКА (нижней грани карточки родителя), идёт вниз, затем вправо к ребёнку, со скруглением.
   Параметры (px — мелкие константы геометрии карточки, не влияют на отзывчивость):
   --tree-x  — X оси от левого края карточки родителя (центр значка = padding 10 + значок/2 13 = 23; рельса слева больше нет);
   --tree-h  — длина горизонтального отвода (≈ вертикальной части);
   --tree-ch — высота карточки (значок 26 + 2×padding 8) = 42; --tree-ic — середина значка по Y (высота/2 = 21);
   --tree-gap — вертикальный зазор между карточками; --tree-r — радиус скругления угла. */
.doctree__kids {
  --tree-x: 23px; --tree-h: 40px; --tree-ch: 42px; --tree-ic: 21px; --tree-gap: 14px; --tree-r: 12px;
  display: flex; flex-direction: column; gap: var(--tree-gap);
  margin-left: calc(var(--tree-x) + var(--tree-h)); padding-top: var(--tree-gap); position: relative; min-width: 0;
}
.doctree__kids > .doctree__node { position: relative; }
/* ::before ребёнка — ЦЕЛОСТНАЯ линия связи родитель→ребёнок ОДНИМ штрихом: вертикаль от низа карточки родителя
   (через зазор сверху — `top:-gap`, у первого ребёнка это padding-top контейнера) вниз + скруглённый загиб вправо
   к карточке на уровне центра значка. Прямая часть + дуга — единый border-path, без наложения второй линии. */
.doctree__kids > .doctree__node::before {
  content: ''; position: absolute; left: calc(-1 * var(--tree-h));
  top: calc(-1 * var(--tree-gap)); height: calc(var(--tree-gap) + var(--tree-ic)); width: var(--tree-h); background: none;
  border-left: 2px solid var(--border-strong); border-bottom: 2px solid var(--border-strong);
  border-bottom-left-radius: var(--tree-r);
}
/* Продолжение шины к СЛЕДУЮЩЕМУ ребёнку — прямая вертикаль ОТ ТОЧКИ ЗАГИБА (`ic-r`) вниз через своё поддерево.
   Стыкуется с прямой частью ::before встык (без перекрытия дуги). У последнего ребёнка отсутствует — шина обрывается на загибе. */
.doctree__kids > .doctree__node:not(:last-child)::after {
  content: ''; position: absolute; left: calc(-1 * var(--tree-h)); top: calc(var(--tree-ic) - var(--tree-r)); bottom: 0;
  width: 2px; background: var(--border-strong);
}

/* Карточка документа в схеме. Ширина — по содержимому (одна строка), в пределах доступной ширины колонки. */
/* 🔴 Iris 2.0 (24.09.2026, решение заказчика): цветной полосы-«скобки» слева больше нет — цвет типа уже несут плитка
   значка и лёгкий тон заливки. Цвет перенесён туда, где он значит связь: отвод линии дерева к карточке окрашен в цвет
   документа, а в точке входа стоит «порт» (кружок цвета типа). Без серой окантовки (фидбек 29.07.2026) — как было.
   `overflow` не режем: порт и отвод выступают за левый край карточки. */
.doccard {
  position: relative;
  flex: none; width: fit-content; min-width: min(100%, 240px); max-width: 100%; display: flex; align-items: stretch; gap: 4px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--doc-accent) 9%, transparent), transparent 60%), var(--mat), var(--surface-2);
  box-shadow: var(--mat-hl); border: 0;
  border-radius: var(--radius); transition: box-shadow .2s;
}
/* Отвод линии к карточке-ребёнку — цветом документа, из нейтрального цвета шины (кладётся поверх прямой части
   серого отвода `.doctree__node::before`; скруглённый загиб остаётся нейтральным). */
.doctree__kids > .doctree__node > .doccard::before {
  content: ''; position: absolute; pointer-events: none;
  left: calc(-1 * (var(--tree-h) - var(--tree-r))); width: calc(var(--tree-h) - var(--tree-r));
  top: calc(var(--tree-ic) - 2px); height: 2px;
  background: linear-gradient(90deg, var(--border-strong), color-mix(in srgb, var(--doc-accent) 80%, transparent));
}
/* Порт — точка входа связи: кружок цвета типа с вырезом под фон и мягким свечением. */
.doctree__kids > .doctree__node > .doccard::after {
  content: ''; position: absolute; pointer-events: none; z-index: 1;
  left: -5px; top: calc(var(--tree-ic) - 5px); width: 8px; height: 8px; border-radius: 50%;
  background: var(--doc-accent);
  box-shadow: 0 0 0 2px var(--drawer-bg), 0 0 8px 0 color-mix(in srgb, var(--doc-accent) var(--st-glow), transparent);
}
.doccard:has(> .doccard__body:not(.doccard__body--static):hover) { box-shadow: var(--mat-hl), 0 0 22px -10px color-mix(in srgb, var(--doc-accent, var(--accent)) var(--st-glow), transparent); }
.doccard__body { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 8px 10px; text-align: left; background: none; border: 0; cursor: pointer; color: var(--text); }
.doccard__body { transition: background .15s; border-radius: inherit; }
.doccard__body:hover:not(.doccard__body--static) { background: color-mix(in srgb, var(--doc-accent) 8%, transparent); }
.doccard__body--static { cursor: default; }
/* Корень схемы — сама сделка: контрастная тёмная карточка (как «Заказ покупателя» в МС). */
.doccard--root { background: linear-gradient(90deg, color-mix(in srgb, var(--doc-accent) 12%, transparent), transparent 70%), var(--surface-4); }
/* Iris 2.0: значок типа — в плитке цвета типа документа (как значки разделов). */
.doccard__ic { flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--doc-accent, var(--muted)) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--doc-accent, var(--muted)) 26%, transparent); }
/* Всё содержимое карточки — в ОДНУ строку: тип · № · дата · сумма (обёртки __top/__sub «прозрачны» — display:contents).
   ЕДИНЫЙ размер шрифта у всех элементов (13px) — различие только по жирности/цвету, без «частокола» из разных кеглей. */
.doccard__main { flex: 1; min-width: 0; display: flex; flex-direction: row; align-items: center; gap: 8px; flex-wrap: nowrap; font-size: 13px; }
.doccard__top, .doccard__sub { display: contents; }
.doccard__type { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 0 1 auto; }
.doccard__num { flex: none; }
.doccard__stale { display: inline-flex; align-items: center; flex: none; }
.doccard__date { flex: none; white-space: nowrap; color: var(--muted); }
/* 🔴 Ячейка таблицы с правкой по клику (01.09.2026): значение — ПЛОСКИЙ текст без рамки, поле ввода или меню
   появляются только в правке. Тот же язык, что у строк карточек (`.ui-info__text--edit`), но без метки. */
.ui-cellwrap { min-width: 0; max-width: 100%; display: inline-flex; align-items: center; }
.ui-cellval {
  min-width: 0; max-width: 100%; padding: 1px 6px; border: 0; background: none; color: var(--text);
  font: inherit; text-align: left; border-radius: var(--radius-sm); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ui-cellval:hover:not(:disabled) { background: var(--surface-3); }
.ui-cellval:disabled { cursor: default; }
.ui-cellval--empty { color: var(--muted); }

/* 🔴 ДВЕ КОЛОНКИ БЛОКОВ в карточках-слайдерах (правило заказчика 31.08.2026): содержимое раскладывается
   в два столбца, ничего не растягивается на всю ширину. Общий примитив — брать его, а не верстать свою сетку
   на каждом экране. `.ui-cols2__wide` — исключение для блока, которому две колонки не подходят (таблица).
   На узком экране (слайдер, телефон) схлопывается в одну колонку. */
.ui-cols2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.ui-cols2 > * { min-width: 0; }
.ui-cols2__wide { grid-column: 1 / -1; }
@media (max-width: 900px) { .ui-cols2 { grid-template-columns: 1fr; } }

/* Название узла схемы рядом с его типом (напр. название планируемого платежа): сжимается первым. */
.doccard__name { flex: 1 1 auto; min-width: 0; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.doccard__amount { margin-left: auto; flex: none; color: var(--text); font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.doccard__acts { flex: none; display: flex; align-items: center; padding: 2px 4px 2px 0; gap: 0; }

/* ---- Редактор документа (Modal) ---- */
.doced { display: flex; flex-direction: column; gap: 14px; }
.doced__title { display: inline-flex; align-items: center; gap: 8px; }
.doced__head { display: flex; flex-wrap: wrap; gap: 12px; }
.doced__grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 12px; }
.doced__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1 1 160px; }
.doced__field--wide { flex-basis: 100%; grid-column: 1 / -1; }
.doced__lbl { font-size: 12px; color: var(--muted); }

/* Строки состава: адаптивная сетка с колонками фиксированного веса; на узком — переносится через min(). */
.doced__lines { display: flex; flex-direction: column; gap: 6px; }
.doced__lrow {
  display: grid; align-items: center; gap: 8px;
  /* Набор колонок переопределяется через --doced-cols (см. .doced__lines--rcpt) — единый источник раскладки строк. */
  grid-template-columns: var(--doced-cols, minmax(0, 2.4fr) minmax(0, 1fr) minmax(0, 0.7fr) minmax(0, 1fr) minmax(0, 0.6fr) minmax(0, 1fr) auto);
}

/* Ячейка сопоставления: подтверждённая позиция, подсказка из справочника либо «не сопоставлено». */
.doced__match { display: flex; align-items: center; gap: 6px; min-width: 0; }
.doced__match-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doced__match-none { color: var(--ic-red); font-size: 12px; white-space: nowrap; }

.doced__lrow--head { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .03em; padding: 0 2px; }
/* Заголовок числовой колонки — по правому краю, как её значение (Сумма); --c — по центру (S/N). */
.doced__lth--r { text-align: right; }
.doced__lth--c { text-align: center; }
.doced__lsum { text-align: right; font-weight: 600; white-space: nowrap; }
/* Телефон: шапка колонок не нужна, строка становится карточкой в 2 колонки, наименование — во всю ширину. */
@media (max-width: 700px) {
  .doced__lrow--head { display: none; }
  .doced__lrow {
    grid-template-columns: 1fr 1fr; padding: 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
  }
  .doced__lrow > *:first-child { grid-column: 1 / -1; }
}

/* Быстрый выбор доли платежа (50/100%) + подсказка. */
.doced__quick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.doced__hint { color: var(--muted); font-size: 12px; }
.doced__pinfo { padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--mat); box-shadow: var(--mat-hl); color: var(--muted); }
.doced__pinfo b { color: var(--text); }
/* Блок «Привязан к» в слайдере документа/платежа из реестра. */
.doced__linkbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--mat); box-shadow: var(--mat-hl); }
.doced__linkbar-lbl { color: var(--muted); font-size: 12px; }
.doced__linkbar-item { border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); border-radius: var(--radius-sm); padding: 3px 10px; font-size: 13px; cursor: pointer; transition: background .15s; }
.doced__linkbar-item:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.doced__linkbar-empty { color: var(--muted); font-size: 13px; }
/* Read-строка «метка → значение» в карточках-просмотрщиках реестра (исходящий/отгрузка/договор). */
.doced__rorow { display: grid; grid-template-columns: minmax(0, 40%) 1fr; gap: 10px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid var(--border); }
.doced__rorow:last-child { border-bottom: none; }
.doced__roval { min-width: 0; overflow-wrap: anywhere; }

/* Просмотрщик документа (рендер УПД/АСЧФ). */
.upd-view { display: flex; flex-direction: column; gap: 14px; }
.upd-view__head { display: flex; flex-direction: column; gap: 6px; padding-bottom: 10px; border-bottom: 1px solid var(--border-strong); }
.upd-view__title { font-size: 16px; font-weight: 700; }
.upd-view__meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; color: var(--muted); }
.upd-view__parties { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 12px; }
.upd-view__party { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--mat); box-shadow: var(--mat-hl); padding: 10px 12px; min-width: 0; }
.upd-view__plabel { font-size: 12px; color: var(--muted); margin-bottom: 3px; }
.upd-view__pname { font-weight: 600; }
.upd-view__scroll { overflow-x: auto; }
.upd-view__table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 640px; }
.upd-view__table th, .upd-view__table td { padding: 7px 10px; border-bottom: 1px solid var(--border); text-align: left; white-space: nowrap; }
.upd-view__table th { color: var(--muted); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .02em; }
.upd-view__table td.r, .upd-view__table th.r { text-align: right; }
.upd-view__table tbody td:nth-child(2) { white-space: normal; min-width: 180px; }
.upd-view__table tfoot td { font-weight: 700; border-top: 2px solid var(--border-strong); border-bottom: none; }
.upd-view__signer, .upd-view__note { color: var(--muted); font-size: 13px; }

/* ---- Печатная форма УПД/СФ — вёрстка по Диадоку (одна table на 16 колонок), «под бумагу» ---- */
/* Шрифты мелкие намеренно (фидбек 17.07.2026): лист PDF = A4 альбомная во всю ширину бланка (1120px → 297мм),
   при прежних размерах таблица товаров сжимала «Наименование» в столбик и документ рвался на вторую страницу. */
.pf {
  background: #fff; color: #000; width: 100%; max-width: none; margin: 0; padding: 18px 22px 22px;
  font-family: Arial, sans-serif; font-size: 9px; line-height: 1.2; box-sizing: border-box;
}
.pf-caption { text-align: right; font-size: 9px; color: #555; margin-bottom: 8px; line-height: 1.3; }

/* Основная таблица (16 колонок), рамки у всех ячеек; шапка/подписи гасят рамки инлайном. */
.pf-body { width: 100%; border-collapse: collapse; table-layout: fixed; }
.pf-body > tbody > tr > td { border: 1px solid #000; padding: 2px 4px; vertical-align: top; overflow-wrap: break-word; }
.pf-body td.c { text-align: center; }
.pf-body td.r { text-align: right; }
.pf-h1 { font-weight: 700; font-size: 13px; }
.pf-status { font-size: 9px; margin-top: 5px; line-height: 1.25; }

/* Вложенная таблица счёта-фактуры (без рамок): метка · значение · № поля. */
.pf-header { width: 100%; border-collapse: collapse; }
.pf-header td { border: 0 !important; padding: 1px 5px; vertical-align: top; }
.pf-header .pf-h1 { font-size: 12px; }
.pf-h3 { font-size: 9px; }
.pf-h-first { color: #555; width: 300px; }
.pf-h-second { color: #000; }
.pf-h-last { color: #555; text-align: right; width: 34px; white-space: nowrap; }

/* Заголовки таблицы товаров. */
.pf-thead td { text-align: center; font-size: 7px; font-weight: 400; line-height: 1.1; vertical-align: middle; }
.pf-tbody td { font-size: 8px; }

/* Подписи внутри таблицы. */
.pf-sign { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
.pf-sign-tbl { width: 100%; border-collapse: collapse; }
/* Линия подписи — снизу у всех ячеек строки данных (как в блоке «передал/получил»); в строке-подписях снимаем. */
.pf-sign-tbl td { border: 0 !important; padding: 1px 5px; font-size: 8px; vertical-align: bottom; border-bottom: 1px solid #000 !important; }
.pf-sign-titles td { color: #555; border-bottom: 0 !important; }
.pf-sign-pos { width: 38%; }
.pf-sign-mid { width: 24%; }

/* Блоки (10)(11) под таблицей. */
.pf-add { display: flex; gap: 8px; padding: 4px 0 2px; align-items: flex-end; }
.pf-add-num { color: #555; width: 34px; flex: none; text-align: right; order: 2; }
.pf-add-val { flex: 1; min-width: 0; border-bottom: 1px solid #000; padding-bottom: 2px; }
.pf-add-lbl { margin: 0 0 1px; color: #555; font-size: 8px; }

/* Передал / получил — две колонки. */
.pf-df { width: 100%; border-collapse: collapse; margin-top: 10px; table-layout: fixed; }
.pf-df-cell { vertical-align: top; padding: 0 14px; border: 0; }
.pf-df-cell:first-child { padding-left: 0; border-right: 1px solid #000; }
.pf-df-cell:last-child { padding-right: 0; }
.pf-df-title { font-weight: 700; font-size: 8px; }
.pf-df-pad { margin-top: 9px; }
.pf-df-block { display: flex; gap: 8px; padding: 2px 0; align-items: flex-end; }
.pf-df-num { color: #555; width: 30px; flex: none; text-align: right; order: 2; }
.pf-df-val { flex: 1; min-width: 0; }
.pf-df-underline { border-bottom: 1px solid #000; padding-bottom: 2px; }
.pf-df-lbl { margin: 0 0 1px; color: #555; font-size: 8px; }
.pf-df-person { width: 100%; border-collapse: collapse; }
.pf-df-person td { border: 0 !important; padding: 1px 4px; font-size: 8px; vertical-align: bottom; border-bottom: 1px solid #000 !important; }
.pf-df-person-pos { width: 34%; }
.pf-df-person-sig { width: 30%; }
.pf-df-person-t td { color: #555; border-bottom: 0 !important; }

/* Обёртка просмотра в слайдере — белый лист во всю ширину, без серого «стола». */
.docview { background: #fff; border-radius: var(--radius-sm); overflow-x: auto; }
/* Превью PDF (КП/договор/счёт) — рендер PDF.js в canvas: скролл-область со страницами.
   🔴 Полоса прокрутки СКРЫТА (фидбек 28.07.2026): документ и так листается колесом и «хваталкой», а полоса рядом
   с листом только мешала. overscroll-behavior:contain — докрутив до края, не утягиваем за собой страницу под слайдером. */
.docpdf {
  position: relative; width: 100%; height: 78vh; overflow: auto; overscroll-behavior: contain;
  border-radius: var(--radius-sm); background: var(--surface-3); scrollbar-width: none;
}
.docpdf::-webkit-scrollbar { width: 0; height: 0; }
.docpdf__pages { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 12px; min-width: 0; }
.docpdf__page { flex: none; height: auto; display: block; border-radius: 2px; background: #fff; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4); }
.docpdf__state { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
/* Страница PDF = картинка (canvas) + прозрачный текстовый слой поверх: текстовый PDF можно выделять курсором
   и копировать. Слой сам не ловит указатель (иначе не потаскать документ мышью) — ловят только строки текста;
   размеры/позиции строк слой считает от `--scale-factor`, её ставит PdfViewer. */
.docpdf__pagebox { position: relative; flex: none; line-height: 0; }
.docpdf__text {
  position: absolute; left: 0; top: 0; overflow: clip; line-height: 1; text-align: initial;
  transform-origin: 0 0; text-size-adjust: none; forced-color-adjust: none; pointer-events: none; z-index: 1;
}
.docpdf__text :is(span, br) { position: absolute; color: transparent; white-space: pre; cursor: text; transform-origin: 0 0; pointer-events: auto; }
.docpdf__text span.markedContent { top: 0; height: 0; }
.docpdf__text span[role="img"] { user-select: none; cursor: default; }
.docpdf__text ::selection { background: rgba(80, 140, 255, 0.35); }
/* 🔴 Служебный canvas PDF.js (им он меряет ширину строк текстового слоя): библиотека кладёт его прямо в <body>
   и рассчитывает на стиль из своего pdf_viewer.css. Без него это обычный canvas 300×150 в конце страницы —
   он удлинял документ, и при открытом превью сбоку появлялась полоса прокрутки всего экрана (28.07.2026). */
.hiddenCanvasElement { position: absolute; top: 0; left: 0; width: 0; height: 0; display: none; }
/* Таскание содержимого мышью при увеличенном масштабе: «ладонь», пока есть куда тащить; «схватил» во время перетаскивания. */
.docpdf--pannable { cursor: grab; }
.docpdf.is-panning { cursor: grabbing; user-select: none; }
/* Панель масштаба — в футере слайдера (первым пунктом). */
.docpdf__zoom {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px;
  background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
}
.docpdf__zoom button {
  min-width: 28px; height: 26px; padding: 0 8px; border: 0; background: none; color: var(--text);
  font: inherit; font-size: 15px; cursor: pointer; border-radius: var(--radius-pill); display: grid; place-items: center;
}
.docpdf__zoom button:hover:not(:disabled) { background: var(--surface-3); }
.docpdf__zoom button:disabled { color: var(--muted); cursor: default; }
.docpdf__zoom-val { font-size: 12px !important; font-variant-numeric: tabular-nums; }
.doced--drawer { display: flex; flex-direction: column; gap: 12px; }
.doc-drawer__foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; width: 100%; }

/* Новая отгрузка: выбор позиций состава с остатками (частичная отгрузка). */
.shipnew { display: flex; flex-direction: column; gap: 12px; }
.shipnew__date { max-width: min(100%, 220px); }
/* Список позиций — Panel + Table из кита; здесь только специфика ячейки «К отгрузке». */
.shipnew__qty { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.shipnew__dash { color: var(--muted); }
.shipnew__qty .ui-num { width: min(30vw, 90px); }
.shipnew__of { color: var(--muted); font-size: 12px; white-space: nowrap; }
.shipnew__total { color: var(--muted); font-size: 13px; }
.shipnew__total b { color: var(--text); }

/* Печатная форма Акта (бланк «под бумагу»). Чёрным по белому — как печатный документ, вне тем. */
.actpf { background: #fff; color: #000; padding: 24px 28px; font-size: 12px; line-height: 1.35; font-family: 'Times New Roman', Georgia, serif; }
.actpf__title { font-size: 15px; font-weight: 700; text-align: center; margin-bottom: 14px; }
.actpf__parties { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
.actpf__parties td { vertical-align: top; padding: 2px 6px 2px 0; }
.actpf__plabel { white-space: nowrap; font-weight: 700; width: 90px; }
.actpf__table { width: 100%; border-collapse: collapse; margin-bottom: 10px; }
.actpf__table th, .actpf__table td { border: 1px solid #000; padding: 4px 6px; text-align: center; }
.actpf__table th { font-weight: 700; background: #f2f2f2; }
.actpf__l { text-align: left !important; }
.actpf__num { text-align: right !important; white-space: nowrap; font-variant-numeric: tabular-nums; }
.actpf__total td { font-weight: 700; }
.actpf__summary { margin-top: 4px; }
.actpf__words { font-style: italic; margin: 2px 0 10px; }
.actpf__note { margin-bottom: 20px; }
.actpf__sign { width: 100%; border-collapse: collapse; }
.actpf__sign td { width: 50%; padding: 4px 6px; vertical-align: bottom; }
.actpf__signline { display: inline-block; }
.actpf__signsub td, .actpf__mp td { font-size: 10px; color: #444; }
.actpf__mp td { padding-top: 12px; }

/* Карточка сделки — корень дерева документов (акцент по стадии, чуть заметнее прочих). */
.doccard--deal { background: linear-gradient(90deg, color-mix(in srgb, var(--doc-accent) 16%, transparent), transparent 70%), var(--mat), var(--surface-2); }
.doccard--deal .doccard__type { font-weight: 700; }

/* Печатные бланки ТОРГ-12 / СФ «под бумагу» (чёрным по белому, вне тем). */
.pfx { background: #fff; color: #000; padding: 22px 26px; font-size: 11px; line-height: 1.3; font-family: 'Times New Roman', Georgia, serif; }
.pfx__formhdr { text-align: right; font-size: 10px; margin-bottom: 8px; }
.pfx__title { font-size: 14px; font-weight: 700; text-align: center; margin: 10px 0; }
.pfx__parties { width: 100%; border-collapse: collapse; margin-bottom: 8px; }
.pfx__parties td { vertical-align: top; padding: 2px 6px 2px 0; border-bottom: 1px solid #000; }
.pfx__pl { white-space: nowrap; font-weight: 700; width: 150px; border-bottom: none !important; }
.pfx__table { width: 100%; border-collapse: collapse; margin-bottom: 8px; }
.pfx__table th, .pfx__table td { border: 1px solid #000; padding: 3px 5px; text-align: center; vertical-align: top; }
.pfx__table th { font-weight: 700; background: #f2f2f2; font-size: 10px; }
.pfx__gnum th { font-weight: 400; font-size: 9px; color: #555; background: #fafafa; }
.pfx__l { text-align: left !important; }
.pfx__num { text-align: right !important; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pfx__total td { font-weight: 700; }
.pfx__row { margin: 4px 0; }
.pfx__sfhead { width: 100%; border-collapse: collapse; margin-bottom: 8px; }
.pfx__sfhead td { border: 1px solid #000; padding: 3px 6px; vertical-align: top; }
.pfx__sfl { font-weight: 700; width: 210px; }
.pfx__sfc { width: 34px; text-align: center; color: #555; }
.pfx__sftable th { font-size: 9px; }
.pfx__trace { font-size: 10px; font-style: italic; color: #333; margin: 4px 0 12px; }
.pfx__sign2 { width: 100%; border-collapse: collapse; margin-top: 14px; }
.pfx__sign2 td { width: 50%; padding: 6px; vertical-align: bottom; }
.pfx__sl { display: inline-block; min-width: 90px; }

/* Выбор/создание договора перед формой «Спецификация/Счёт». */
.contractpick__spin { padding: 16px; display: grid; place-items: center; } /* спиннер в слайдере «Новый УПД» */

/* Полный редактор документа */
.docform { display: flex; flex-direction: column; gap: 12px; }
.docform__list { display: flex; flex-direction: column; gap: 8px; }
.docform__ref { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; }
.docform__ref--basis { grid-template-columns: minmax(0, 1.6fr) minmax(0, 0.8fr) auto auto; }
.docform__basis-name { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
@media (max-width: 700px) { .docform__ref, .docform__ref--basis { grid-template-columns: 1fr; } }

/* Строка реестра платежей в слайдере привязки. */
.reg-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); }
.reg-row + .reg-row { margin-top: 8px; }
.reg-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.reg-row__top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.reg-row__date { color: var(--muted); font-size: 12px; }
.reg-row__sub { color: var(--muted); font-size: 12px; }
.reg-row__sub b { color: var(--text); }
.reg-row__purpose { color: var(--muted); font-size: 12px; white-space: pre-wrap; overflow-wrap: anywhere; }


/* ---- Приёмка по закупке (модуль 9, P3): реквизиты и строки документа поставщика в слайдере ---- */
.rcpt { display: flex; flex-direction: column; gap: 14px; }
.rcpt__req { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr)); gap: 10px; }
.rcpt__field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.rcpt__field > span { color: var(--muted); font-size: 12px; }
.rcpt__field--wide { grid-column: 1 / -1; }
.rcpt__head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rcpt__total { color: var(--muted); font-size: 13px; margin-left: auto; }
.rcpt__rows { display: flex; flex-direction: column; gap: 10px; }
.rcpt-new { display: flex; flex-direction: column; gap: 12px; }

.rcpt-item {
  display: flex; flex-direction: column; gap: 8px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
}
.rcpt-item--unmatched { border-color: color-mix(in srgb, var(--ic-red) 45%, var(--border)); }
.rcpt-item__supplier { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 8px; }
.rcpt-item__match { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.rcpt-item__matched { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.rcpt-item__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rcpt-item__nomatch { color: var(--ic-red); font-size: 13px; }
.rcpt-item__hint {
  display: inline-flex; align-items: center; gap: 6px; padding: 2px 8px; font: inherit; font-size: 13px;
  color: var(--text); background: none; border: 1px dashed var(--border); border-radius: var(--radius-sm); cursor: pointer;
}
.rcpt-item__hint:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.rcpt-item__acts { display: inline-flex; gap: 4px; margin-left: auto; }
.rcpt-item__nums { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.rcpt-item__nums label { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1 1 90px; }
.rcpt-item__nums label > span { color: var(--muted); font-size: 12px; }
.rcpt-item__sum { flex: none; padding-bottom: 8px; white-space: nowrap; font-weight: 600; }
.rcpt-item__serials { display: flex; flex-direction: column; gap: 4px; }
.rcpt-item__serials > span { color: var(--muted); font-size: 12px; }

/* ---- Ремонты: вкладка «Заключение», фото, комплектация приёмки, поля заключения ---- */
.deal-conc { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.deal-conc__wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; overflow-y: auto; padding: 2px; }
/* Услуги — высота не более ~3 строк (на подложке-панели), дальше свой скролл таблицы. */
.deal-conc__services { flex: none; }
.deal-conc__services .deal-tablewrap { max-height: clamp(130px, 26vh, 240px); }
.deal-conc__bottom { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
@media (max-width: 900px) { .deal-conc__bottom { grid-template-columns: 1fr; } }
.deal-conc__right { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
/* Себестоимость ремонта — Panel как другие блоки вкладки; число внутри крупное (как «Сумма к оплате»).
   Специфичность .rep-edit.rep-edit--big — чтобы перебить `font: inherit` базового .rep-edit ниже по файлу. */
.rep-edit.rep-edit--big { font-size: 26px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; text-align: left; padding: 2px; }
.ui-input.ui-num--big { font-size: 24px; font-weight: 800; }

/* Тип ремонта (платный/гарантийный) — строка «метка → сегмент-переключатель» в шапке блока «О ремонте». */
.rep-type { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rep-type__lbl { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 13px; color: var(--muted); }
.rep-type .ui-seg { margin-left: auto; }

/* Загруженные фото (правая колонка «Инфо») — квадраты 1:1. */
.rep-photos__add { margin-bottom: 10px; }
.rep-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 8px; }
.rep-photo { position: relative; aspect-ratio: 1; border-radius: var(--radius-sm); overflow: hidden; background: var(--photo-bg); border: 1px solid var(--border); }
.rep-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rep-photo__del { position: absolute; top: 4px; right: 4px; background: color-mix(in srgb, var(--surface-1) 70%, transparent); backdrop-filter: blur(2px); }

/* Комплектация приёмки — чистая таблица в стиле блока «Заключение» (без карточек-плашек): шапка с подчёркиванием + плоские строки с тонкими разделителями. */
.rep-intake { display: flex; flex-direction: column; }
.rep-intake__head, .rep-intake__row { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.67fr) 84px 32px; column-gap: 12px; align-items: center; }
.rep-intake__head { padding: 0 2px 5px; border-bottom: 1px solid var(--border); }
.rep-intake__head > span { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); white-space: nowrap; display: inline-flex; align-items: center; gap: 5px; }
.rep-intake__head > .rep-intake__c { justify-content: center; }
.rep-intake__head > :last-child, .rep-intake__row > :last-child { justify-self: center; }
.rep-intake__row { padding: 3px 2px; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); }
.rep-intake__row:last-of-type { border-bottom: none; }
.rep-intake__row .rep-edit { padding: 4px 0; }
.rep-intake__row .ui-input, .rep-intake__row .ui-num { min-width: 0; width: 100%; }
.rep-intake__c { text-align: center; }
/* Обёртка ячейки комплектации (нужна для подписи data-label на телефоне). На широком экране — прозрачная
   грид-ячейка: раскладку по-прежнему задаёт `.rep-intake__row`. */
.rep-intake__cell { display: block; min-width: 0; }
.rep-intake__empty { color: var(--muted); padding: 8px 2px; }
/* Кнопки под таблицей комплектации: «Добавить строку» и «Из шаблона» — переносятся на узком слайдере. */
.rep-intake__add { margin-top: 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Поля заключения СЦ: подпись слева, значение — в правой части строки напротив заголовка.
   Единая сетка (подпись auto = по самой длинной, значение 1fr) → значения выровнены в один столбец. */
.rep-fields { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 14px; row-gap: 10px; align-items: start; }
.rep-fields__item { display: contents; }
.rep-fields__label { display: flex; align-items: center; gap: 6px; font-weight: 600; font-size: 13px; min-width: 0; padding-top: 3px; }
/* Значение прижато к правому краю строки (как на «Инфо»). */
.rep-fields .rep-edit { padding: 3px 2px; text-align: right; }
/* Клик-по-тексту (как на «Инфо»): значение текстом, по клику — редактор кита; пунктир при ховере. */
.rep-edit { display: block; width: 100%; min-width: 0; text-align: left; background: none; border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--text); font: inherit; padding: 8px 10px; cursor: text; white-space: pre-wrap; overflow-wrap: anywhere; }
.rep-edit:hover:not(:disabled) { text-decoration: underline dotted; text-underline-offset: 3px; }
.rep-edit:disabled { cursor: default; }
.rep-edit--empty { color: var(--muted); }
.rep-edit--num { text-align: right; white-space: nowrap; }
.rep-edit--center { text-align: center; }

/* ---- Состав = полноценная ТАБЛИЦА (вкладка «Товары»): шапка колонок сверху, строки в одну строчку ---- */
.deal-comp { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
/* Обёртка таблицы — свой скролл (верт.; гориз. при нехватке ширины), скроллбар СКРЫТ. */
.deal-tablewrap { flex: 1; min-height: 0; overflow: auto; scrollbar-width: none; -ms-overflow-style: none; }
.deal-tablewrap::-webkit-scrollbar { width: 0; height: 0; }
/* Единый grid; шапка и строки — subgrid (колонки выровнены между всеми строками). Товар тянется, числовые — по контенту.
   10 колонок: превью | Товар | Цена | Кол-во | Скидка | Ставка НДС | Сумма НДС | Сумма | Маржа | удалить.
   row-gap → промежуток между строками (это отдельные карточки, но выровнены по заголовкам). */
.deal-table {
  display: grid;
  grid-template-columns: auto minmax(140px, 1fr) repeat(10, auto);
  column-gap: 14px; row-gap: 0; align-items: center;
}
/* Состав ЗАКУПКИ (модуль 9): нет колонки скидки (её покупателю не дают), вместо маржи — фактическая себестоимость. */
.deal-table--purchase { grid-template-columns: auto minmax(140px, 1fr) repeat(8, auto); }
/* Состав РЕМОНТА (28.08.2026): у услуги в строке ещё три поля — себестоимость, наценка и компенсация налога,
   от них считается цена. Колонок на три больше, чем у продажи. */
.deal-table--repair { grid-template-columns: auto minmax(140px, 1fr) repeat(13, auto); }
/* Позиции ПРИЁМКИ — та же таблица состава: превью · товар · тип · артикул · кол-во · цена · НДС · сумма · S/N · удалить. */
.deal-table--receipt { grid-template-columns: auto minmax(160px, 1fr) repeat(8, auto); }
/* У ремонта по центру стоят наценка, компенсация, кол-во, скидка и ставка НДС, а цена (8-я) — по правому краю. */
.deal-table--repair .deal-trow > .fin:nth-child(8) { justify-content: flex-end; }
.deal-table--repair .deal-trow > .fin:nth-child(9),
.deal-table--repair .deal-trow > .fin:nth-child(10),
.deal-table--repair .deal-trow > .fin:nth-child(11) { justify-content: center; }
/* Прозрачная рамка у шапки И строк одинаковой толщины → субгрид-треки совпадают (у строк рамка видимая — карточка). */
.deal-thead, .deal-trow { display: grid; grid-template-columns: subgrid; grid-column: 1 / -1; align-items: center; position: relative; border: 1px solid transparent; }
/* Шапка колонок — прилипает к верху при прокрутке. */
.deal-thead { position: sticky; top: 0; z-index: 1; background: var(--drawer-bg); border-bottom-color: var(--border); }
.deal-th { padding: 8px 0; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); white-space: nowrap; }
.deal-th--r { text-align: right; }
.deal-th--c { text-align: center; }
/* Строка = отдельная КАРТОЧКА: рамка, скругление, фон. Вертикальные отступы — у ячеек; боковой внутренний отступ — через
   крайние ячейки (padding на самих ячейках НЕ сдвигает субгрид-треки, в отличие от padding на строке-контейнере). */
/* 🔴 Строка СОСТАВА — строка ТАБЛИЦЫ, а не карточка (фидбек 29.07.2026): данные здесь колоночные
   (цена · кол-во · скидка · ставка · сумма · маржа), и лесенка из скруглённых прямоугольников с заливкой
   мешала читать колонки вертикально. Теперь: без фона и рамки-коробки, строки вплотную, между ними —
   тонкий разделитель; выделение строки даёт ховер (`.ui-hoverable`). */
.deal-trow { border-color: transparent; border-bottom-color: var(--border); border-radius: 0; background: transparent; }
.deal-trow:last-of-type { border-bottom-color: transparent; }
/* Без вертикального padding у ячеек: высоту строки задаёт квадрат-превью (самый высокий), прочие центрируются в ней. */
.deal-trow > * { min-width: 0; }
/* Первая ячейка (превью) — БЕЗ отступов: превью заподлицо к левой/верхней/нижней грани карточки. */
.deal-trow > *:first-child, .deal-thead > *:first-child { padding: 0; }
.deal-trow > *:last-child, .deal-thead > *:last-child { padding-right: 12px; }
/* Кол-во/Скидка/Ставка НДС (6–8-я ячейки после добавления колонок Тип/Артикул) — по центру, под свои заголовки. */
.deal-trow > .fin:nth-child(6), .deal-trow > .fin:nth-child(7), .deal-trow > .fin:nth-child(8) { justify-content: center; }
/* Линия-индикатор места вставки при перетаскивании — по центру промежутка между карточками, во всю ширину строки. */
.deal-trow.ui-insert--before::before, .deal-trow.ui-insert--after::after {
  content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--accent); border-radius: 2px; pointer-events: none; z-index: 2;
}
.deal-trow.ui-insert--before::before { top: -6px; }
.deal-trow.ui-insert--after::after { bottom: -6px; }
/* Превью — строго КВАДРАТ 1:1 (изображения каталога всегда квадратные, см. память).
   🔴 Iris 2.0 (23.09.2026): скруглённая плитка с воздухом вокруг (как значок в карточке документа), а не белый
   квадрат встык к краю строки. Оно самое высокое в строке → задаёт высоту строки, прочие ячейки центрируются.
   Без фото — плитка-заглушка на поверхности (`--empty`), а не белый квадрат с серой иконкой. */
.deal-tcell__thumb {
  width: 44px; height: 44px; flex: none; padding: 0; margin: 8px 0 8px 8px; overflow: hidden;
  background: var(--photo-bg); color: var(--muted); display: grid; place-items: center;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.deal-tcell__thumb--empty { background: var(--surface-3); }
.deal-tcell__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.deal-tcell__thumb--link { cursor: pointer; }
/* Ячейка «Товар»: только название (тянется, ellipsis). Тип и артикул — отдельными колонками. */
.deal-tcell__name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.deal-tname { font-weight: 600; font-size: 14px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.deal-tcell__type, .deal-tcell__sku { display: flex; align-items: center; min-width: 0; }
.deal-tcell__del { flex: none; justify-self: center; }
/* В таблице у мини-полей метки не нужны (есть заголовки колонок); ширину задаёт grid. */
.deal-table .fin { width: auto !important; flex: none; }
/* Цена — минимальная ширина под «999 999 999.00 ₽» (и в покое, и в правке), чтобы столбец не дёргался
   от значения/входа в правку. 🔴 Именно MIN-WIDTH, а не width (фидбек 28.08.2026): при жёсткой ширине ячейка
   не растягивалась на колонку, если та шире (в ремонте колонок стало больше), — значение и поле ввода
   прижимались к ЛЕВОМУ краю колонки, а заголовок стоял справа. */
.deal-table .fin--price { width: auto !important; min-width: 150px; }
.deal-table .fin--price .fin__edit { width: 100%; }
/* В РЕМОНТЕ колонок больше (себестоимость, наценка, компенсация), а суммы услуг короче миллионных —
   держать под цену 150px незачем, иначе строка распирается и место под числом пустует. */
.deal-table--repair .fin--price { min-width: 110px; }
.deal-table .fin__lbl { display: none; }
.deal-table .fin--right { justify-content: flex-end; }
.deal-table__add { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; justify-content: flex-start; padding: 12px 0 4px; }
/* Двойная цена валютной ЗАКУПКИ: сверху валюта инвойса, снизу рубли (появляются после приёмки). */
.deal-dualprice { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 2px; min-width: 0; }
.deal-dualprice__rub { color: var(--muted); font-size: 12px; white-space: nowrap; }

/* Выбор валюты цен закупки — рядом с кнопками состава (модуль 9). */
.deal-curpick { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.deal-curpick .ui-select { min-width: 150px; }
/* Карточка позиции — компактная в 2 ряда: строка 1 = название, строка 2 = расчёты (метка+значение в одну строку). Превью уменьшено. */
.deal-item2 { display: flex; gap: 12px; align-items: center; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--mat); box-shadow: var(--mat-hl); padding: 12px; scroll-snap-align: start; }
/* Ховер строки (Iris 2.0, 23.09.2026): рамка и мягкий ореол цветом стадии слайдера (`--st` от Drawer `accent`),
   как у карточек канбана, вместо заливки акцентом. Колонки остаются колонками — строка не превращается в карточку. */
.deal-trow.ui-hoverable:hover {
  border-radius: var(--radius); border-color: color-mix(in srgb, var(--st, var(--accent)) 50%, transparent);
  background: color-mix(in srgb, var(--st, var(--accent)) 6%, transparent);
  box-shadow: 0 0 22px -10px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
/* Панель «Товары» в карточке сделки — прозрачная, как «Документы» (фидбек 23.09.2026). Липкая шапка колонок
   залита фоном слайдера: свечение слайдера гаснет выше таблицы (~10rem от верха), так что полосой она не читается.
   Скролл — у таблицы внутри. */
.deal-items-panel .deal-comp { flex: 1; min-height: 0; }
/* Перетаскиваемая карточка (reorder состава) — курсор grab за тело; интерактивные поля сохраняют свой курсор. */
.deal-item2--drag { cursor: grab; }
.deal-item2--drag:active { cursor: grabbing; }
.deal-item2__thumb { flex: none; width: 46px; height: 46px; position: relative; overflow: hidden; border-radius: 10px; border: 1px solid var(--border); background: var(--surface-3); display: grid; place-items: center; color: var(--muted); }
.deal-item2__thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; background: var(--photo-bg); }
.deal-item2__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
/* Строка 1: название (тянется) → артикул. Кнопка удаления вынесена в отдельную колонку карточки (вверху справа). */
.deal-item2__row1 { display: flex; align-items: center; gap: 9px; min-width: 0; }
.deal-item2__name { font-weight: 600; font-size: 15px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Кликабельные превью/название товара в составе (открывают карточку-слайдер): только курсор-палец, без цвета/подчёркивания. */
.deal-item2__thumb--link { padding: 0; cursor: pointer; }
.deal-item2__name--link { background: none; border: none; padding: 0; font-family: inherit; text-align: left; cursor: pointer; }
/* Бейдж артикула — под размер бейджа типа позиции (`.ui-badge`: 12px / 3px 10px / pill). Составной селектор — перебить `.ui-code`. */
.ui-code.deal-item2__sku { flex: none; display: inline-flex; align-items: center; font-size: 12px; padding: 3px 10px; border-radius: var(--radius-pill); }
.deal-item2__del { flex: none; }
/* Финансовая строка: редактируемые поля слева (текст+карандаш), read-only блок справа. Метка и значение — в одну строку. */
.deal-item2__fin { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; }
.deal-item2__sum { margin-left: auto; display: flex; align-items: baseline; gap: 6px 12px; flex-wrap: wrap; }
/* Мини-поле: метка и значение — в одну строку. Фикс-ширина (проп `col`, инлайн `width`) → колонки выровнены
   по направляющим между всеми строками: метка в столбце всегда одинаковая → значения встают по одной вертикали.
   `flex:none` — ширина не сжимается под flex; на узком контейнере поля переносятся (flex-wrap). */
.fin { flex: none; display: flex; flex-direction: row; align-items: baseline; gap: 4px; min-width: 0; }
/* Значение прижато к ПРАВОМУ краю колонки (метка остаётся слева) — для денежных полей: Цена/Сумма/Маржа. */
.fin--right { justify-content: space-between; }
.fin__lbl { flex: none; font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.fin__box { min-width: 0; font-size: 14px; line-height: 1.35; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fin__box--strong { font-weight: 700; }
.fin__box--muted { color: var(--muted); }
/* Редактируемое значение = кликабельный текст (карандаша нет). Подсказка редактируемости — пунктир на ховере. */
/* Маркер-предупреждение внутри мини-поля (напр. «цена отличается от каталога» у цены позиции сделки):
   прижимается к значению справа — метка остаётся у левого края, маркер идёт вплотную перед числом. */
.fin > .ui-warnmark { margin-left: auto; align-self: center; }
.fin__val { display: inline-flex; align-items: center; min-width: 0; max-width: 100%; padding: 0; border: none; background: none; font: inherit; color: var(--text); cursor: pointer; }
.fin__val:disabled { cursor: default; }
.fin__val:hover:not(:disabled) .fin__box { text-decoration: underline dotted; text-underline-offset: 3px; text-decoration-color: var(--muted); }
/* Инпут в режиме правки: по умолчанию тянется на всю колонку (метка слева, небольшой отступ `.fin gap`).
   Узким полям (Кол-во/Скидка) фикс-ширина задаётся инлайн через проп `editW` (flex:none). */
.deal-item2__fin .ui-input { padding: 6px 10px; line-height: 1.35; }
.fin__edit { flex: 1; min-width: 0; }
.fin__edit .ui-numwrap { width: 100%; }
.ui-num--right { text-align: right; }
.ui-num--center { text-align: center; }
/* Поле ИНЛАЙН-правки (в ячейке таблицы, строке характеристик): отступы ТЕ ЖЕ, что у .ui-editval — текст
   в поле встаёт ровно там, где стоял текст значения, без «скачка» при активации. Выравнивание наследуется
   от ячейки (в правой колонке — вправо), поэтому text-align здесь НЕ задаём. */
.ui-num--cell { padding: 4px 8px; text-align: inherit; }
.ui-num--cell.ui-num--nostep { padding-right: 8px; }
/* Бейджи типа клиента в инфо-строке. */
.ui-info__badges { display: inline-flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }
/* Лента событий сделки: строки идут вплотную и разделяются линией (рамка тут одна — панельная).
   Дата дня — примитив кита `.ui-daysep--plain`; своя пилюля убрана (была четвёртым видом разделителя дня). */
/* Событие: [иконка] текст ....... [аватар ФИ время]. */
/* Строки ленты событий — примитив кита `.ui-feedrow` (см. «Лента переписки и событий»). */
/* ФИ с аватаром в инфо-блоке (Ответственный). */
.deal-person { display: inline-flex; align-items: center; gap: 7px; }
/* Пустой выпадающий список (нет вариантов). */
.ui-menu__empty { padding: 10px 14px; color: var(--muted); font-size: 13px; }
/* Слайдер-пикер компании/контакта: поиск сверху + прокручиваемый список строк. */
.picker { display: flex; flex-direction: column; gap: 12px; height: 100%; min-height: 0; }
.picker__head { display: flex; align-items: center; gap: 8px; }
.picker__list { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.picker__list .ui-list__row { border-bottom: none; }
.picker__row { width: 100%; text-align: left; border: 0; border-radius: var(--radius); padding: 10px 14px; background: var(--btn-bg); box-shadow: inset 0 0 0 1px var(--ctl-border), var(--btn-hl); cursor: pointer; font: inherit; color: var(--text); transition: background .15s, box-shadow .2s; }
/* Iris 2.0: ховер строки пикера — обводка и ореол цветом `--st` (иначе акцент). */
.picker__row:hover { background: color-mix(in srgb, var(--st, var(--accent)) 8%, var(--btn-bg)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 50%, transparent), 0 0 22px -10px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent); }
.picker__name { font-weight: 600; }
.picker__sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
/* Заголовок группы в пикере (напр. «Контакты компании» / «Другие контакты»). */
.picker__group { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); padding: 8px 4px 2px; }
.picker__group:not(:first-child) { border-top: 1px solid var(--border); margin-top: 4px; }
/* Условия сделки живут в общих строках .ui-info__row (те же отступы). Значение — текст (иконка правки слева, как у контактов). */
/* Правка условия: поле «расширяется» на всю строку, под ним — список вариантов (Popover). */
.ui-info__editcell { flex: 1; min-width: 0; margin-left: auto; }
.ui-info__editcell .ui-inputwrap { width: 100%; min-width: 0; }
/* Текст в поле правки условия — по правому краю (как значение в режиме просмотра); список тоже прижат вправо (Popover align=right). */
.ui-info__editcell .ui-input { text-align: right; }
/* Лента стадий в шапке: быстрый перевод сделки на любую стадию (в любую сторону).
   Прижата к ПРАВОМУ краю шапки (`margin-left:auto`). Все пилюли ОДИНАКОВОЙ ширины = по самой длинной:
   inline-grid + `grid-auto-columns:1fr` под max-content выравнивает все колонки к максимальной. */
/* Лента стадий — кит-Tabs; обёртка прижимает её вправо и даёт скролл при нехватке места. */
.deal-head__stages { min-width: 0; margin-left: auto; }
/* Инфо-блок сделки — компактные строки: метка слева, значение справа (по правой направляющей);
   у телефона/почты иконки действий стоят СЛЕВА от значения, не сбивая правый край чисел. */
.ui-info { display: flex; flex-direction: column; gap: 2px; }
.ui-info__row { display: flex; align-items: center; gap: 12px; min-height: 30px; }
.ui-info__label { display: inline-flex; align-items: center; gap: 9px; color: var(--muted); flex: none; }
.ui-info__val { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; min-width: 0; text-align: right; font-variant-numeric: tabular-nums; }
.ui-info__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Редактируемое значение = кликабельный текст (карандаша нет). Подсказка редактируемости — пунктир на ховере. */
.ui-info__text--edit { max-width: 100%; padding: 0; border: none; background: none; font: inherit; color: inherit; text-align: right; cursor: pointer; }
.ui-info__text--edit:hover { text-decoration: underline dotted; text-underline-offset: 3px; text-decoration-color: var(--muted); }
/* Навигационная ссылка внутри инфо-строки (открывает карточку): только курсор-палец, без цвета/подчёркивания. */
.ui-info__text--link { max-width: 100%; padding: 0; border: none; background: none; font: inherit; color: inherit; text-align: right; cursor: pointer; }
.ui-info__acts { display: inline-flex; align-items: center; flex: none; }
.ui-info__acts .ui-iconbtn { width: 26px; height: 26px; }
.ui-info__sep { height: 1px; background: var(--border); margin: 5px 0; }
/* 🔴 ЕДИНЫЙ примитив «кликабельное значение → инлайн-правка» (кнопка-текст без оформления кнопки,
   пунктирная подсказка на ховере). Использовать везде, где значение по клику превращается в поле:
   характеристики товара, ячейки цены и т.п. Не дублировать per-screen. */
/* Отступы и прозрачная рамка ТОЧНО как у поля ввода (.ui-num--cell) — при клике поле встаёт на то же место,
   текст не смещается ни по горизонтали, ни по вертикали. Менять padding здесь → менять и у .ui-num--cell. */
.ui-editval {
  display: inline-block; padding: 4px 8px; border: 1px solid transparent; border-radius: var(--radius);
  background: none; font: inherit; color: inherit; cursor: pointer; text-align: inherit;
}
.ui-editval:hover { text-decoration: underline dotted; text-underline-offset: 3px; text-decoration-color: var(--muted); }
/* НЕредактируемое значение в той же колонке (нет права / считается автоматически): те же отступы и рамка,
   чтобы правый край чисел совпадал со редактируемыми строками. Без курсора и подчёркивания. */
.ui-editval--static { cursor: default; }
.ui-editval--static:hover { text-decoration: none; }

/* Многострочное инфо-поле (InfoField multiline): метка сверху, текст во всю ширину с переносами. */
.ui-info__block { display: flex; flex-direction: column; gap: 5px; padding: 5px 0; min-width: 0; }
.ui-info__long { white-space: pre-wrap; word-break: break-word; text-align: left; }
.ui-info__long--edit { width: 100%; padding: 0; border: none; background: none; font: inherit; color: inherit; cursor: pointer; }
.ui-info__long--edit:hover { text-decoration: underline dotted; text-underline-offset: 3px; text-decoration-color: var(--muted); }
.ui-info__ph { color: var(--muted); }

/* ===================== Chat ===================== */
.ui-chat { position: relative; display: flex; flex-direction: column; background: var(--mat); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--mat-hl); overflow: hidden; min-height: 0; }
.ui-chat--bare { border: none; border-radius: 0; background: transparent; }
.ui-chat__body { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 14px; }
/* Пустая лента (проп `empty`): приглушённая подпись по центру. */
.ui-chat__empty { margin: auto; max-width: 28rem; text-align: center; color: var(--muted); font-size: 13px; line-height: 1.5; }
.ui-chat__row { display: flex; gap: 10px; max-width: 78%; }
/* wide — пузырь без потолка 78%: ширина по содержимому, предел — вся ширина ленты (развёрнутое письмо, крупная картинка). */
.ui-chat__row--wide { max-width: 100%; }
/* Разделитель ленты (дата, «Предыдущая переписка», кнопка подгрузки старых) — строка по центру с линиями по бокам. */
.ui-chat__divider { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; }
.ui-chat__divider::before, .ui-chat__divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.ui-chat__row--own { margin-left: auto; flex-direction: row-reverse; }
.ui-chat__group { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ui-chat__author { color: var(--muted); font-size: 11.5px; padding-left: 2px; }
/* Подпись своего сообщения — по правому краю, как время под пузырём. */
.ui-chat__row--own .ui-chat__author { padding: 0 2px 0 0; text-align: right; }
.ui-chat__bubble { background: var(--surface-3); color: var(--text); padding: 9px 13px; border-radius: 14px; border-top-left-radius: 4px; font-size: 13.5px; line-height: 1.45; word-break: break-word; }

/* Пузырь, требующий внимания (пропущенный звонок без ответа): красится ЦЕЛИКОМ — заливка и текст,
   без внутренних полос и рамок. Разобрали — тон снимается. */
.ui-chat__bubble--warning {
  background: color-mix(in srgb, var(--ic-amber) 18%, var(--surface-2));
  color: var(--text);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ic-amber) 45%, transparent);
}
/* Свой пузырь залит градиентом, поэтому внутри него ПЕРЕОПРЕДЕЛЯЮТСЯ сами токены, а не цвета конкретных
   элементов: любое вложение (строка звонка, письмо, вложения, ссылки) рассчитано на фон приложения и на
   фиолетовом читается плохо — серый `--muted` и цветные иконки просто тонут. Правило одно и работает для
   всего, что когда-либо попадёт в пузырь. Красный оставлен цветным, но светлым: у исходящего звонка цвет
   иконки — единственный признак «не дозвонились» (янтарный тон пузыря включается только у пропущенных). */
.ui-chat__row--own .ui-chat__bubble {
  background: var(--grad); box-shadow: var(--pri-hl), 0 8px 22px -14px var(--glow);
  color: var(--on-accent);
  border-top-left-radius: 14px;
  border-top-right-radius: 4px;
  --text: var(--on-accent);
  --muted: color-mix(in srgb, var(--on-accent) 75%, transparent);
  --border: color-mix(in srgb, var(--on-accent) 28%, transparent);
  --accent-soft: color-mix(in srgb, var(--on-accent) 14%, transparent);
  --overlay-hover: color-mix(in srgb, var(--on-accent) 18%, transparent);
  --ic-green: var(--on-accent);
  --ic-blue: var(--on-accent);
  --ic-slate: var(--on-accent);
  --ic-red: #ff9d9d;
  --ic-rose: #ff9d9d;
}
.ui-chat__time { color: var(--muted); font-size: 10.5px; padding: 0 2px; }
.ui-chat__row--own .ui-chat__time { text-align: right; }
/* --chat-ctl-h — общая высота строки композера: поле в одну строку, скрепка и «отправить» ровно одной высоты
   (поле растёт по контенту дальше, кнопки остаются прижаты к низу). */
.ui-chat__composer { --chat-ctl-h: 42px; display: flex; align-items: flex-end; gap: 8px; padding: 12px; border-top: 1px solid var(--border); }
.ui-chat__composer .ui-input { flex: 1; min-width: 0; min-height: var(--chat-ctl-h); }
.ui-chat__send { flex: none; height: var(--chat-ctl-h); padding: 0 14px; }
/* Вложения ответа: чипы над строкой ввода + скрепка слева от поля. */
.ui-chat__atts { padding: 10px 12px 8px; }
.ui-chat__attach {
  flex: none; display: grid; place-items: center; width: var(--chat-ctl-h); height: var(--chat-ctl-h);
  border: 1px solid var(--ctl-border); border-radius: var(--radius); background: var(--btn-bg); box-shadow: var(--btn-hl); color: var(--muted); cursor: pointer;
  transition: color .15s, border-color .15s;
}
.ui-chat__attach:hover:not(:disabled) { color: var(--text); border-color: var(--border-strong); }
.ui-chat__attach:disabled { opacity: .5; cursor: default; }
/* Канал ответа (почта / мессенджер) — кнопка-иконка слева от «Отправить»; тот же размер, что у скрепки. */
.ui-chat__channel {
  flex: none; display: grid; place-items: center; width: var(--chat-ctl-h); height: var(--chat-ctl-h);
  border: 1px solid var(--ctl-border); border-radius: var(--radius); background: var(--btn-bg); box-shadow: var(--btn-hl); color: var(--text); cursor: pointer;
  transition: border-color .15s, background .15s;
}
.ui-chat__channel:hover:not(:disabled) { border-color: var(--border-strong); background: var(--overlay-hover); }
/* Единственный доступный канал: кнопка остаётся индикатором «куда уйдёт ответ», но не кликается. */
.ui-chat__channel--fixed { cursor: default; }
.ui-chat__channel:disabled { opacity: .75; cursor: default; }
/* Отложенная отправка: яркий бабл над строкой ввода с крупным числовым + графическим (кольцо) отсчётом и отменой */
.ui-chat__undobar {
  display: flex; align-items: center; gap: clamp(10px, 2.5%, 16px);
  margin: 10px 12px 0; padding: clamp(10px, 2.5%, 14px) clamp(12px, 3%, 18px);
  border-radius: 16px; background: var(--grad); color: var(--on-accent);
  box-shadow: 0 8px 24px -6px color-mix(in srgb, var(--accent) 55%, transparent);
  animation: ui-undobar-in .22s cubic-bezier(.2, .8, .3, 1.2);
}
@keyframes ui-undobar-in { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.ui-chat__undobar-timer { position: relative; flex: none; width: 48px; height: 48px; }
.ui-chat__undobar-ring { width: 100%; height: 100%; transform: rotate(-90deg); }
.ui-chat__undobar-ring-track { fill: none; stroke: color-mix(in srgb, var(--on-accent) 28%, transparent); stroke-width: 4; }
.ui-chat__undobar-ring-fill {
  fill: none; stroke: var(--on-accent); stroke-width: 4; stroke-linecap: round;
  transition: stroke-dashoffset 1s linear;
}
.ui-chat__undobar-sec {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.5px;
}
.ui-chat__undobar-info { flex: 1; min-width: 0; }
.ui-chat__undobar-title { font-size: 13px; font-weight: 700; opacity: .95; }
.ui-chat__undobar-text {
  font-size: 12.5px; opacity: .85; margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word;
}
.ui-chat__undobar-files {
  display: flex; align-items: center; gap: 5px; margin-top: 3px;
  font-size: 11.5px; opacity: .85; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ui-chat__undobar-btn {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 10px; border: none; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 700;
  background: var(--on-accent); color: var(--accent);
  transition: transform .12s ease, box-shadow .12s ease;
}
.ui-chat__undobar-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 12px -2px rgba(0, 0, 0, .3); }
.ui-chat__undobar-btn:active { transform: none; }

/* ===================== Slider (range) ===================== */
.ui-rangewrap { display: flex; align-items: center; gap: 12px; }
.ui-range {
  -webkit-appearance: none; appearance: none; flex: 1; height: 6px; border-radius: 999px; outline: none; cursor: pointer;
  background: linear-gradient(90deg, var(--bar1), var(--accent) var(--pct, 0%), var(--surface-3) var(--pct, 0%));
  box-shadow: var(--ctl-inset);
}
.ui-range::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; border: 3px solid var(--accent); border-radius: 50%; background: var(--knob); box-shadow: 0 1px 4px rgba(0,0,0,.5), 0 0 12px -2px var(--glow); cursor: pointer; }
.ui-range::-moz-range-thumb { width: 12px; height: 12px; border: 3px solid var(--accent); border-radius: 50%; background: var(--knob); box-shadow: 0 1px 4px rgba(0,0,0,.5), 0 0 12px -2px var(--glow); cursor: pointer; }
.ui-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--accent-soft); }
.ui-range:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px var(--accent-soft); }
.ui-range__val { min-width: 34px; text-align: right; font-variant-numeric: tabular-nums; font-size: 13px; }

/* ===================== FileInput ===================== */
.ui-file { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border: 1.5px dashed var(--border-strong); border-radius: var(--radius); background: var(--surface-2); cursor: pointer; transition: border-color .15s, background .15s; }
.ui-file:hover { border-color: var(--accent); box-shadow: 0 0 22px -12px var(--glow); }
.ui-file--drag { border-color: var(--accent); background: var(--accent-soft); }
.ui-file--invalid { border-color: var(--danger); }
.ui-file__input { display: none; }
.ui-file__icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 10px; background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 28%, transparent); flex: none; }
.ui-file__text { font-size: 13px; color: var(--muted); }

/* ===================== Перетаскивание файлов + чип вложения ===================== */
.ui-dropover {
  position: absolute; inset: 0; z-index: 6; display: grid; place-items: center; pointer-events: none;
  border: 2px dashed var(--accent); border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface) 76%, transparent);
}
.ui-dropover__box {
  display: inline-flex; align-items: center; gap: 8px; max-width: 90%;
  padding: 10px 16px; border-radius: var(--radius); background: var(--surface-2); color: var(--accent);
  font-size: 13px; font-weight: 600; text-align: center;
}
/* Чип вложения (AttachmentChip). Iris 2.0: стеклянная плашка с лёгким тоном цвета типа файла; значок — в плитке цвета
   типа. 🔴 Без цветной полосы слева (24.09.2026, как у карточек схемы документов): тип уже несут плитка и бейдж формата.
   Кликабельный (`--open`) при наведении светится цветом типа. */
.ui-attchip {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%;
  padding: 3px 4px 3px 4px; border: 1px solid var(--ctl-border);
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, color-mix(in srgb, var(--doc-accent, var(--muted)) 9%, transparent), transparent 60%), var(--btn-bg);
  box-shadow: var(--btn-hl); color: var(--text); font-size: 12px;
  transition: background .15s, box-shadow .15s, border-color .15s;
}
.ui-attchip__ic {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--doc-accent, var(--muted)) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--doc-accent, var(--muted)) 26%, transparent);
}
.ui-attchip__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ui-attchip__fmt { flex: none; font-size: 9px; font-weight: 700; letter-spacing: .03em; line-height: 1; padding: 3px 5px; border-radius: var(--radius-sm); color: var(--doc-accent); background: color-mix(in srgb, var(--doc-accent) 16%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 26%, transparent); }
.ui-attchip__size { color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }
.ui-attchip__x { width: 18px; height: 18px; flex: none; }
/* Кликабельное тело чипа (предпросмотр/скачивание) и действие справа за разделителем. */
.ui-attchip__body { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
.ui-attchip__act { flex: none; display: inline-flex; align-self: stretch; align-items: center; margin: -3px -4px -3px 0; border-left: 1px solid var(--border); }
.ui-attchip__act .ui-iconbtn { width: 30px; height: 100%; border-radius: 0; }
.ui-attchip--open:hover {
  border-color: color-mix(in srgb, var(--doc-accent, var(--accent)) 45%, transparent);
  background: color-mix(in srgb, var(--doc-accent, var(--accent)) 8%, var(--btn-bg-hover));
  box-shadow: var(--btn-hl), 0 0 22px -10px color-mix(in srgb, var(--doc-accent, var(--accent)) var(--st-glow), transparent);
}
/* Файла у нас нет (вложение осталось в почте): пунктир, приглушено, без «руки» и ореола. */
.ui-attchip--absent { border-style: dashed; opacity: .65; }
.ui-attchip--absent:hover { background: var(--btn-bg); box-shadow: var(--btn-hl); }
.ui-attchip__body:disabled { cursor: default; }
/* Заблокировано антивирусом: тон опасности. */
.ui-attchip--virus { border-color: var(--danger); background: var(--danger-soft); }
.ui-attchip--virus:hover { background: var(--danger-soft); box-shadow: var(--btn-hl); }
.ui-attchip--virus .ui-attchip__ic { background: color-mix(in srgb, var(--danger) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger) 26%, transparent); }
.ui-attchip--virus .ui-attchip__name { color: var(--danger); }
/* Ряд чипов — общая раскладка для любого композера с вложениями. */
.ui-attlist { display: flex; flex-wrap: wrap; gap: var(--space-2); min-width: 0; }
.ui-file__link { color: var(--accent); font-weight: 600; }
.ui-file__names { color: var(--text); }

/* ===================== ColorInput ===================== */
.ui-color { display: inline-flex; align-items: center; gap: 10px; }
.ui-color__pick { -webkit-appearance: none; appearance: none; width: 38px; height: 34px; padding: 0; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: transparent; cursor: pointer; }
.ui-color__pick::-webkit-color-swatch-wrapper { padding: 3px; }
.ui-color__pick::-webkit-color-swatch { border: none; border-radius: 5px; }
.ui-color__pick::-moz-color-swatch { border: none; border-radius: 5px; }
.ui-color__hex { font-family: var(--font-mono); font-size: 13px; }
/* Swatches — палитра кита: кружки цветов токенами (--sw). Выбранный — кольцом, размер не меняется. */
.ui-swatches { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ui-swatch {
  width: 20px; height: 20px; padding: 0; border-radius: var(--radius-pill); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--sw, var(--border-strong)) 60%, var(--border-strong));
  background: var(--sw); display: grid; place-items: center; color: var(--muted);
  transition: box-shadow .15s;
}
.ui-swatch:hover { box-shadow: 0 0 0 2px var(--pop-bg, var(--bg)), 0 0 0 3px color-mix(in srgb, var(--sw, var(--text)) 60%, transparent); }
.ui-swatch.is-active { box-shadow: 0 0 0 2px var(--pop-bg, var(--bg)), 0 0 0 4px var(--sw, var(--accent)); }
.ui-swatch--fill { background: color-mix(in srgb, var(--sw) 30%, transparent); }
.ui-swatch--none { background: var(--ctl-bg); border-color: var(--border-strong); }

/* ===================== Divider ===================== */
.ui-divider { height: 1px; background: linear-gradient(90deg, transparent, var(--border-strong) 12%, var(--border-strong) 88%, transparent); border: none; margin: 4px 0; }
.ui-divider--label { height: auto; background: none; display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 12px; }
.ui-divider--label::before, .ui-divider--label::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* ===================== Accordion ===================== */
.ui-acc { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--mat); box-shadow: var(--mat-hl); }
.ui-acc__item { border-bottom: 1px solid var(--border); }
.ui-acc__item:last-child { border-bottom: none; }
.ui-acc__sum { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 13px 16px; cursor: pointer; font-weight: 600; font-size: 14px; list-style: none; user-select: none; }
.ui-acc__sum::-webkit-details-marker { display: none; }
.ui-acc__sum:hover { background: var(--hover); }
.ui-acc__sum svg { color: var(--muted); flex: none; transition: transform .15s; }
.ui-acc__item[open] .ui-acc__sum svg { transform: rotate(180deg); color: var(--accent); }
.ui-acc__item[open] > .ui-acc__sum { color: var(--text); background: linear-gradient(90deg, var(--accent-soft), transparent 70%); }
.ui-acc__body { padding: 8px 16px 16px; color: var(--muted); font-size: 13.5px; line-height: 1.5; }

/* ===================== Calendar / DatePicker ===================== */
.ui-cal { width: 272px; padding: 12px; }
.ui-cal__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.ui-cal__title { display: flex; align-items: center; gap: 4px; }
.ui-cal__titlebtn { border: none; background: transparent; color: var(--text); font: inherit; font-weight: 600; font-size: 14px; padding: 4px 7px; border-radius: 7px; cursor: pointer; text-transform: capitalize; }
.ui-cal__titlebtn:hover { background: var(--surface-2); color: var(--accent); }
.ui-cal__title-static { font-weight: 600; font-size: 14px; padding: 4px 7px; }
.ui-cal__nav { display: grid; place-items: center; width: 30px; height: 30px; border: none; background: transparent; color: var(--muted); border-radius: 8px; cursor: pointer; }
.ui-cal__nav:hover { background: var(--surface-2); color: var(--text); }
.ui-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.ui-cal__dow { color: var(--muted); font-size: 11px; text-align: center; padding: 4px 0; }
.ui-cal__day { aspect-ratio: 1; display: grid; place-items: center; border: none; background: transparent; color: var(--text); border-radius: 8px; cursor: pointer; font-size: 13px; }
.ui-cal__day:hover { background: var(--surface-2); }
.ui-cal__day--out { color: var(--muted); opacity: .45; }
.ui-cal__day { transition: background .12s; }
.ui-cal__day--today { color: var(--accent); font-weight: 700; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 70%, transparent); }
.ui-cal__day--sel { background: var(--grad); color: var(--on-accent); box-shadow: var(--pri-hl), 0 6px 16px -8px var(--glow); }

/* Выбор месяца/года */
.ui-cal__mgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding-top: 4px; }
.ui-cal__mbtn { padding: 12px 0; border: none; background: transparent; color: var(--text); font: inherit; font-size: 13px; border-radius: 8px; cursor: pointer; }
.ui-cal__mbtn:hover { background: var(--surface-2); }
.ui-cal__mbtn--on { background: var(--accent-soft); color: var(--accent); font-weight: 600; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }

/* Диапазон дат: слитная заливка */
.ui-cal__grid--range { gap: 0; }
.ui-cal__grid--range .ui-cal__day { border-radius: 0; }
.ui-cal__day--inrange { background: var(--accent-soft); color: var(--text); }
.ui-cal__grid--range .ui-cal__day--rstart { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }
.ui-cal__grid--range .ui-cal__day--rend { border-top-right-radius: 8px; border-bottom-right-radius: 8px; }

/* Двойной календарь диапазона. Узкий экран — месяцы друг под другом (иначе не влезает по ширине). */
.ui-rangecal { display: flex; flex-wrap: wrap; }
.ui-rangecal .ui-cal { padding: 12px; flex: none; }
.ui-rangecal .ui-cal + .ui-cal { border-left: 1px solid var(--border); }
@media (max-width: 700px) {
  .ui-rangecal .ui-cal + .ui-cal { border-left: none; border-top: 1px solid var(--border); }
}

/* DateTimePicker: календарь + колонки времени + футер */
.ui-dtp { display: flex; }
.ui-dtp .ui-cal { padding: 12px; }
.ui-time { display: flex; border-left: 1px solid var(--border); }
.ui-time__col { width: 52px; max-height: 268px; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 2px; }
.ui-time__col + .ui-time__col { border-left: 1px solid var(--border); }
.ui-time__opt { border: none; background: transparent; color: var(--text); font: inherit; font-size: 13px; padding: 7px 0; border-radius: 8px; cursor: pointer; text-align: center; font-variant-numeric: tabular-nums; }
.ui-time__opt:hover { background: var(--surface-2); }
.ui-time__opt--on { background: var(--accent-soft); color: var(--accent); font-weight: 600; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }
.ui-dtp__foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; border-top: 1px solid var(--border); }
.ui-dtp__preview { font-size: 13px; font-variant-numeric: tabular-nums; }

/* ============================ Каталог (модуль 4) ============================ */
/* 🔴 Каталог занимает высоту экрана и НЕ прокручивается целиком (фидбек 20.08.2026): шапка страницы,
   дерево разделов и шапка таблицы неподвижны — крутится только список позиций (`.items-wrap`).
   Раньше страница скроллилась целиком, и липкая шапка таблицы «уезжала» по списку. */
.catalog-page { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.catalog-page > .ui-pagehead { flex: none; }
.catalog-layout { display: grid; grid-template-columns: 320px 1fr; gap: 16px; align-items: start; }
.catalog-page > .catalog-layout { flex: 1; min-height: 0; align-items: stretch; }
@media (max-width: 900px) { .catalog-layout { grid-template-columns: 1fr; } }
.catalog-aside { max-height: 100%; overflow: auto; }
.catalog-main { min-width: 0; display: flex; flex-direction: column; min-height: 0; }
/* Панель позиций: подсказка сверху неподвижна, скроллится только таблица со своей липкой шапкой. */
.items-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.items-wrap { flex: 1; min-height: 0; overflow: auto; }
/* Узкий экран: колонки схлопываются, и внутренний скролл списка дал бы «скролл в скролле» на крошечной
   высоте — возвращаем обычный поток, страница прокручивается целиком. Блок идёт ПОСЛЕ правил выше:
   специфичность та же, побеждает последнее правило. (`.catalog-aside` на мобиле уже переопределён ниже —
   `position: static; max-height: 40dvh`.) */
@media (max-width: 900px) {
  .catalog-page { height: auto; }
  .items-panel, .items-wrap { flex: none; overflow: visible; }
}

/* Дерево разделов */
.cat-tree { padding: 8px; }
.cat-tree__head { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px; }
.cat-node { position: relative; display: flex; align-items: center; gap: 4px; min-height: 34px; padding: 4px 6px 4px 8px; border-radius: var(--radius-sm); cursor: pointer; user-select: none; }
.cat-node { transition: background .12s, box-shadow .15s; }
.cat-node:hover { background: var(--btn-bg-hover); }
/* Iris 2.0: активный раздел — мягкая заливка + тонкое кольцо акцента. */
.cat-node--active { background: var(--accent-soft); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }
.cat-node--active .cat-node__name { color: var(--accent); font-weight: 600; }
.cat-node--dropover { background: var(--accent-soft); outline: 2px dashed var(--accent); outline-offset: -2px; }
.cat-node--dropover .cat-node__name { color: var(--accent); }
.cat-node--dropinside { background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: -2px; }
.cat-node--dropinside .cat-node__name { color: var(--accent); }
.cat-node__caret { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border: none; background: transparent; color: var(--muted); cursor: pointer; padding: 0; flex: none; }
.cat-node .ui-tip { flex: 1; min-width: 0; }
/* Тултип-обёртка иконки прайса не должна забирать долю ширины у названия раздела */
.cat-node .ui-tip:has(.cat-node__price) { flex: none; }
.cat-node__name { display: block; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-node__count { font-size: 11px; font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--muted); background: var(--surface-2); border-radius: var(--radius-pill); padding: 1px 7px; flex: none; }
/* Отметка «раздел показан в прайсе для реселлеров» в узле дерева каталога и раскладка формы раздела. */
.cat-node__price { display: inline-flex; align-items: center; flex: none; }
.cat-form { display: flex; flex-direction: column; gap: var(--space-4); }
.cat-form__flag { display: flex; flex-direction: column; gap: var(--space-2); }
.cat-form__hint { font-size: 12px; color: var(--muted); }
/* Меню «три точки»: место зарезервировано всегда (нет горизонтального прыжка), видно на hover/активном */
.cat-node__menu { flex: none; opacity: 0; transition: opacity .12s; }
.cat-node:hover .cat-node__menu, .cat-node--active .cat-node__menu { opacity: 1; }
.cat-iconbtn.ui-iconbtn { width: 26px; height: 26px; }
/* Линия-индикатор места вставки раздела (как слои в граф-редакторах) */
.cat-line { position: absolute; right: 8px; height: 2px; background: var(--accent); border-radius: 2px; pointer-events: none; z-index: 2; }
.cat-line--top { top: -1px; }
.cat-line--bot { bottom: -1px; }
.cat-line::before { content: ''; position: absolute; left: -3px; top: -2px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }

/* Тулбар и таблица позиций */
.items-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
/* Строка над таблицей каталога: текущий раздел + подсказка про клик/перетаскивание (поиск и кнопки — в шапке страницы). */
.items-subrow { flex: none; display: flex; align-items: center; gap: 10px; margin: 4px 2px 12px; min-height: 20px; opacity: .7; }
.items-subrow__hint { color: var(--muted); display: inline-flex; cursor: help; }
.items-table tbody tr.items-row { cursor: pointer; }
.items-table tbody tr.items-row:active { cursor: grabbing; }
.items-table .item-name { font-weight: 500; }
/* Название + маркер закупки в одной строке: текст сжимается, треугольник не отрывается и не сжимается. */
.item-name__wrap { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
/* Карточка товара (слайдер) и lg-модалка: шапка с вкладками фиксирована, скроллится только содержимое — без наложения */
.ui-modal--lg .ui-modal__body,
.item-card-drawer .ui-drawer__body { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.item-card__head { flex: none; padding: 20px 56px 0 20px; } /* правый отступ — под плавающий крестик */
.item-card__scroll { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 16px 20px 20px; }
/* Витрина «Обзор» — как карточка в интернет-магазине; без внутреннего скролла страницы */
.item-card__scroll--show { overflow: hidden; padding: 20px; }
.show { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 28px; height: 100%; min-height: 0; align-items: stretch; }
/* Левая колонка — квадратное фото, под ним блок цен */
.show-left { display: flex; flex-direction: column; gap: 16px; min-width: 0; min-height: 0; }
.show-main { width: 100%; aspect-ratio: 1 / 1; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); background: var(--surface-2); display: grid; place-items: center; }
.show-main img { width: 100%; height: 100%; object-fit: contain; display: block; }
.show-main--empty { color: var(--muted); }
/* Правая часть — сведения о товаре */
.show-info { display: flex; flex-direction: column; gap: 16px; min-height: 0; min-width: 0; }
.show-title { font-size: 24px; font-weight: 700; line-height: 1.2; }
.show-crumbs { margin-top: -8px; } /* путь раздела (хлебные крошки) ближе к названию */
/* Бейджи-теги: тип, артикул, раздел, единица — единого размера, крупнее */
.show-tags { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.show-tags .ui-badge { font-size: 13px; padding: 5px 12px; line-height: 1.25; }
.show-tags .ui-code { padding: 5px 10px; }
/* Описание тянется на всю доступную высоту карточки; скролл — только внутри него (сама карточка не скроллится) */
.show-descwrap { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
.show-desc-head { display: flex; align-items: center; gap: 8px; }
.show-desc-head > span { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.show-desc { flex: 1 1 auto; min-height: 0; overflow-y: auto; font-size: 13px; line-height: 1.55; color: var(--text); white-space: pre-wrap; padding-right: 4px; }
.show-desc--empty { color: var(--muted); }
/* Блок цен — строгая сетка: юрлицо · НДС · прямая цена · реселлер (числа выровнены по правому краю) */
.show-prices { padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--mat); box-shadow: var(--mat-hl); }
.show-prices__title { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin-bottom: 12px; }
.show-prices__grid { display: grid; grid-template-columns: max-content max-content 1fr max-content; column-gap: 16px; row-gap: 12px; align-items: center; }
.show-price__name { font-weight: 600; }
.show-price__vat { display: flex; }
.show-price__vat .ui-badge { min-width: 84px; text-align: center; }
.show-price__main { justify-self: end; display: inline-flex; align-items: center; gap: 6px; font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.show-price__res { justify-self: start; display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); white-space: nowrap; }
.show-price__res b { color: var(--text); font-weight: 700; }
.item-thumb { width: 38px; height: 38px; border-radius: 7px; overflow: hidden; border: 1px solid var(--border); background: var(--surface-2); display: grid; place-items: center; color: var(--muted); }
.item-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--photo-bg); }
/* Линия-индикатор места вставки при перетаскивании товара (сверху/снизу строки) */
.items-row--before > td { box-shadow: inset 0 2px 0 var(--accent); }
.items-row--after > td { box-shadow: inset 0 -2px 0 var(--accent); }
.items-table .sort-cell { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 13px; }
/* Цена продажи и маржа в списке каталога — цифры в одну вертикаль, без переноса. */
.items-table .item-price { white-space: nowrap; font-variant-numeric: tabular-nums; }
.link-btn { border: none; background: transparent; color: var(--text); font: inherit; cursor: pointer; padding: 0; text-align: left; }
.link-btn:hover { color: var(--accent); text-decoration: underline; }

/* Состав (техкарта/комплект) в карточке */
.comp-line { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--mat); box-shadow: var(--mat-hl); }
.comp-add { border: 1px dashed var(--border-strong); border-radius: var(--radius-sm); padding: 10px; }
.comp-results { margin-top: 6px; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.comp-result { display: flex; align-items: center; gap: 10px; padding: 8px 10px; cursor: pointer; }
.comp-result:hover { background: var(--btn-bg-hover); }

/* Единый компонент «Закупка» (decisions 0053): раскладка вкладки. Поверхности — из кита (Panel/Card flat/ui-list),
   здесь только адаптивная раскладка (относительные величины, min-width:0 для сжатия).
   🔴 ЕДИНАЯ ТИПОГРАФИКА вкладки: строки 13px, метки/пояснения 12px muted, все суммы — `.proc-num`
   (tabular-nums, nowrap). Колонки чисел заданы переменными, поэтому итог источника, шаги раскладки и
   «Итого закупка» стоят на ОДНОЙ вертикали. */
.proc-tab {
  display: flex; flex-direction: column; gap: 12px;
  --proc-sum-w: clamp(6.5rem, 13%, 10.5rem); /* колонка накопленного итога */
  --proc-add-w: clamp(5.5rem, 11%, 9rem);    /* колонка прибавки шага */
}
.proc-label { font-size: 12px; color: var(--text-muted); }
.proc-num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.proc-muted { color: var(--text-muted); }
.proc-hint { color: var(--text-muted); font-size: 12px; margin: 10px 16px 2px; }
.proc-hint--inline { margin: 2px 0 0; }

/* Плашка себестоимости: слева метка + главное число, справа метрики; ниже — разбивка по нашим юрлицам. */
.proc-cost { display: flex; flex-direction: column; gap: 10px; }
.proc-cost__main { display: flex; align-items: baseline; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; }
.proc-cost__head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
.proc-cost__val { font-size: clamp(1.15rem, 2.2vw, 1.5rem); font-variant-numeric: tabular-nums; }
/* Сумма + маркер «источника нет» рядом (не разъезжаются при переносе строки). */
.proc-cost__valwrap { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.proc-cost__none { font-size: 13px; }
/* Метрики (без НДС / входной НДС) и себестоимость по юрлицам — одинаковые ячейки «метка → число». */
.proc-cost__meta, .proc-cost__ents {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: 2px 20px; margin: 0; font-size: 13px;
}
.proc-cost__ents { padding-top: 8px; border-top: 1px solid var(--border); }
.proc-cost__meta > div, .proc-cost__ents > div { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; }
.proc-cost__meta dt, .proc-cost__ents dt { color: var(--text-muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proc-cost__meta dd, .proc-cost__ents dd { margin: 0; }
.proc-cost__ents dd { font-weight: 600; }

/* Список источников: строки-карточки со скруглённой подсветкой (без разделителей, с зазором). */
.proc-srclist { gap: 6px; }
.ui-list.proc-srclist .ui-list__row { border-bottom: none; border-radius: var(--radius); }

/* Источник закупки — карточка в 2 строки (шапка + финансы) и раскрываемый расчёт. Итог финансовой строки
   стоит в колонке `--proc-sum-w` — на одной вертикали с суммами раскладки ниже. */
.proc-src { display: flex; flex-direction: column; gap: 6px; }
.proc-src--off { opacity: .55; }
.proc-src__line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.proc-src__ic { display: inline-flex; color: var(--ic-amber); }
.proc-src__name { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proc-src__scen { font-size: 12px; }
.proc-src__spacer { flex: 1 1 auto; }
.proc-src__badges { display: flex; gap: 6px; flex-wrap: wrap; }
.proc-src__acts { display: inline-flex; gap: 2px; }
.proc-src__fin { display: grid; grid-template-columns: minmax(0, 1fr) var(--proc-sum-w); gap: 10px; align-items: center; font-size: 13px; }
.proc-src__price { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.proc-src__link { color: var(--accent); font-size: 12px; }
.proc-sumcell { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Раскрывающийся расчёт внутри строки списка: без своей рамки и боковых отступов, только разделитель сверху. */
.proc-src .ui-acc { border: none; border-radius: 0; border-top: 1px solid var(--border); }
.proc-src .ui-acc__item { border-bottom: none; }
.proc-src .ui-acc__sum { padding: 7px 0; font-size: 12px; font-weight: 500; }
.proc-src .ui-acc__body { padding: 2px 0 8px; font-size: 13px; color: var(--text); }

/* Состав («Компоненты») — ТА ЖЕ таблица, что список каталога (`.items-table` + ячейки `ItemRowCells`),
   поэтому своей раскладки строк тут нет: только поле количества и подложка блока. */
.proc-addcomp { padding-top: 4px; }
.proc-ctable { margin: 0; }
.proc-ctable .proc-qty { width: clamp(72px, 12vw, 104px); }
.proc-ctotal { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 16px 2px; border-top: 1px solid var(--border); }
.proc-ctotal__val { font-weight: 600; font-size: 15px; font-variant-numeric: tabular-nums; }

/* «Где используется» — строка-ссылка на позицию-родителя (имя растёт, роль и количество прижаты вправо). */
.usedin-row { display: flex; align-items: center; gap: 12px; }
.usedin-row > .ui-cell { flex: 1 1 auto; min-width: 0; }
.usedin-row__role { flex: none; }
.usedin-row__qty { flex: none; white-space: nowrap; color: var(--text-muted); }

/* Локальные переопределения строк формулы у источника: «название + тип» слева, поле и единица — в одной
   колонке у всех строк (в т.ч. у сводки ступеней, которую править нельзя). */
/* Строки переопределений — по две в ряд на широком контейнере (в узком — по одной); подсказка на всю ширину. */
.proc-flines { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr)); gap: 10px 24px; }
.proc-flines > .proc-hint { grid-column: 1 / -1; }
.proc-fline { display: grid; grid-template-columns: minmax(0, 1fr) clamp(8rem, 40%, 12rem); gap: 10px; align-items: center; }
.proc-fline__lbl { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.proc-fline__name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.proc-fline__kind { font-size: 12px; color: var(--text-muted); }
/* Единица (%, код валюты, «USDT/ед.», «% спред») — своя колонка: узкой она ломалась на две строки. */
.proc-fline__val { display: grid; grid-template-columns: minmax(0, 1fr) 4.75rem; gap: 8px; align-items: center; }
.proc-fline__unit { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.proc-fline__tiers { font-size: 12px; color: var(--text-muted); text-align: right; }

/* Раскладка расчёта себестоимости: шаг — название/пояснение слева, прибавка и накопленный итог в своих колонках. */
.proc-brk { display: flex; flex-direction: column; }
.proc-brk__row {
  display: grid; grid-template-columns: minmax(0, 1fr) var(--proc-add-w) var(--proc-sum-w);
  gap: 10px; align-items: baseline; padding: 4px 0;
}
.proc-brk__row--total { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 8px; }
.proc-brk__lbl { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.proc-brk__name { font-size: 13px; }
.proc-brk__det { color: var(--text-muted); font-size: 12px; }
.proc-brk__add { text-align: right; white-space: nowrap; font-size: 12px; font-variant-numeric: tabular-nums; }
.proc-brk__sum { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Редактор источника — смысловые группы (разделители кита `Divider label`) и автосетка полей:
   3 колонки на широком контейнере → 2 → 1 в узком слайдере (без фиксированных px, только minmax/clamp). */
.proc-ed { display: flex; flex-direction: column; gap: 10px; }
.proc-ed__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); gap: 12px; align-items: start; }
/* Группы с широкими полями (название поставщика, список юрлиц, заметка) — не более двух в ряд. */
.proc-ed__grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.proc-ed__formula { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.proc-ed__col-title { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; }
.proc-ed__ro { padding: 10px 12px; border-radius: var(--radius-sm); background: var(--mat); box-shadow: var(--mat-hl); border: 1px solid var(--border); font-size: 13px; }
.proc-ed__foot { display: flex; align-items: center; gap: 12px; padding-top: 2px; border-top: 1px solid var(--border); }
.proc-ed__acts { margin-left: auto; display: flex; gap: 8px; padding-top: 10px; }
/* Медиазапрос не нужен: сетки редактора складываются сами (`auto-fit` + `minmax(min(100%, …))`). */

/* Фото-галерея */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.photo-thumb { position: relative; display: block; aspect-ratio: 1; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--border); background: var(--surface-2); }
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--photo-bg); }
.photo-thumb .photo-del {
  position: absolute; top: 4px; right: 4px; width: 24px; height: 24px; display: grid; place-items: center;
  border: none; border-radius: 50%; background: rgba(0, 0, 0, .6); color: #fff; cursor: pointer; opacity: 0; transition: opacity .12s;
}
.photo-thumb:hover .photo-del { opacity: 1; }
.photo-thumb .photo-del:hover { background: var(--danger, #e5484d); }
.photo-drop {
  display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center;
  padding: 20px; margin-bottom: 14px; border: 1.5px dashed var(--border-strong); border-radius: var(--radius);
  color: var(--muted); cursor: pointer; transition: border-color .12s, background .12s;
}
.photo-drop:hover { border-color: var(--accent); color: var(--text); }
.photo-drop--over { border-color: var(--accent); background: var(--accent-soft); color: var(--text); }

/* ===================== Длинный текст: статьи и инструкции ===================== */
/* Примитивы для текста, который читают, а не заполняют: цитата, блок кода, клавиша, выделение найденного,
   номер шага, плитка-иконка, оглавление, отметка чек-листа, «прозаические» варианты Alert и Accordion,
   полоска без дорожки. Появились с читалкой базы знаний (02.10.2026) — годятся для любых справок в ERP. */
.ui-quote { margin: 0; padding: 12px 16px; border-inline-start: 3px solid var(--accent); background: var(--surface-2); border-radius: var(--radius); color: var(--muted); }
.ui-quote__cite { display: block; margin-top: 8px; font-size: 13px; font-style: normal; color: var(--dim); }
/* Блок кода — «колодец», как поле ввода: моноширинный, прокрутка по горизонтали внутри блока. */
.ui-pre {
  position: relative; margin: 0; padding: 14px 16px; overflow-x: auto;
  background: var(--ctl-bg); border: 1px solid var(--ctl-border); box-shadow: var(--ctl-inset); border-radius: var(--radius);
  font-family: var(--font-mono); font-size: 13px; line-height: 1.55; color: var(--text);
}
.ui-pre__copy { position: absolute; top: 6px; inset-inline-end: 6px; opacity: .55; }
.ui-pre:hover .ui-pre__copy, .ui-pre__copy:focus-visible { opacity: 1; }
/* Клавиша (подсказки сочетаний: Ctrl K, Esc, ↑ ↓). */
.ui-kbd {
  display: inline-grid; place-items: center; min-width: 1.6em; padding: 1px 6px; border-radius: 5px;
  border: 1px solid var(--border-strong); border-bottom-width: 2px; background: var(--surface-2); color: var(--muted);
  font-family: var(--font-mono); font-size: 11px; line-height: 1.5; white-space: nowrap;
}
/* Выделение в тексте: найденное слово в результатах поиска, маркер в статье. */
.ui-mark { background: color-mix(in srgb, var(--ic-amber) 32%, transparent); color: inherit; border-radius: 3px; padding: 0 2px; }
/* Номер шага инструкции (вертикальный список шагов; горизонтальный индикатор этапов — `.ui-stepper`). */
.ui-stepnum {
  display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 50%;
  font-size: 13px; font-weight: 700; color: var(--accent); background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}
/* Плитка-иконка: цветной квадрат с иконкой (карточки книг, заголовки разделов). Цвет — `--tile-c`. */
.ui-icontile {
  --tile-c: var(--accent);
  display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: var(--radius-sm); color: var(--tile-c);
  background: color-mix(in srgb, var(--tile-c) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tile-c) 26%, transparent), 0 0 14px -6px color-mix(in srgb, var(--tile-c) var(--st-glow), transparent);
}
.ui-icontile--lg { width: 48px; height: 48px; border-radius: var(--radius); }
/* Оглавление длинного текста: линия слева, текущий раздел — акцентом. */
.ui-toc { font-size: 13px; }
.ui-toc__title { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin-bottom: 8px; }
.ui-toc__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.ui-toc__link { display: block; padding: 3px 0 3px 12px; color: var(--muted); text-decoration: none; border-left: 2px solid var(--border); transition: color .12s, border-color .12s; }
.ui-toc__link:hover { color: var(--text); text-decoration: none; }
.ui-toc__link--current { color: var(--accent); border-left-color: var(--accent); }
.ui-toc__link--l3 { padding-left: 24px; }
.ui-toc__link--l4 { padding-left: 36px; }
/* Отметка чек-листа без поля ввода (только показ) — тот же квадрат, что у Checkbox. */
.ui-check__box--on { background: var(--grad); border-color: transparent; color: var(--on-accent); box-shadow: var(--pri-hl), 0 0 10px -3px var(--glow); }
/* Строка списка, выбранная с клавиатуры (палитры поиска, пикеры) — как при наведении. */
.ui-list__row--active {
  background: color-mix(in srgb, var(--st, var(--accent)) 9%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 40%, transparent);
  border-radius: var(--radius-sm);
}
/* Alert внутри длинного текста (выделения «Внимание», «Совет» в инструкции): текст обычного размера и
   цвета — у обычного Alert он мелкий и серый, это для уведомлений; кромка цветом вида слева. */
.ui-alert--prose { gap: 12px; padding: 12px 16px; border-inline-start: 3px solid var(--al); background: color-mix(in srgb, var(--al) 8%, var(--surface)); }
.ui-alert--prose .ui-alert__icon { margin-top: 1px; }
.ui-alert--prose .ui-alert__title { font-size: 14.5px; }
.ui-alert--prose .ui-alert__msg { font-size: inherit; color: var(--text); margin-top: 0; line-height: 1.6; }
.ui-alert--prose .ui-alert__title + .ui-alert__msg { margin-top: 4px; }
/* Accordion с длинным текстом внутри: тело — обычным текстом, а не мелкой серой подписью. */
.ui-acc--prose .ui-acc__body { color: var(--text); font-size: inherit; line-height: inherit; padding: 4px 16px 16px; }
/* Полоска без дорожки — прогресс чтения у верхнего края колонки. */
.ui-progress--bare { background: none; box-shadow: none; border-radius: 0; }
.ui-progress--bare .ui-progress__bar { border-radius: 0; transition: width .08s linear; }

/* ===================== Общие примитивы списка (единый источник оформления) ===================== */
/* Ховер-подсветка карточки — акцентная заливка (как у карточек канбана `.ui-kan-card`). Единый примитив кита:
   вешать на любую карточку/строку, где нужна подсветка при наведении. */
/* Iris 2.0: ховер-подсветка — рамка и ореол цветом `--st` (иначе акцент), как карточки канбана. */
.ui-hoverable { transition: background .15s, border-color .15s, box-shadow .2s; }
.ui-hoverable:hover {
  background: color-mix(in srgb, var(--st, var(--accent)) 7%, var(--surface-solid));
  border-color: color-mix(in srgb, var(--st, var(--accent)) 50%, transparent);
  box-shadow: 0 0 22px -10px color-mix(in srgb, var(--st, var(--accent)) var(--st-glow), transparent);
}
/* Настройки → «Банки»: строка юрлица. Слева название/статус/мета, справа действия; на узком экране
   действия переносятся под текст (относительный flex-basis, без фиксированных ширин). */
.ui-list__row.bank-row { padding: 14px 16px; } /* строка двухуровневая — тесный «списочный» отступ ей мал */
.bank-row { display: flex; align-items: center; gap: 12px 20px; flex-wrap: wrap; }
.bank-row__info { flex: 1 1 20rem; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.bank-row__title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.bank-row__name { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bank-row__meta { color: var(--muted); font-size: 13px; }
.bank-row__err { color: var(--ic-red); font-size: 13px; }
.bank-row__actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }
/* Разделитель между переключателем приёма и кнопками — чтобы действия не читались одной кашей. */
.bank-row__sep { width: 1px; align-self: stretch; min-height: 1.5rem; background: var(--border); }

/* Ограничитель ширины ячейки таблицы: длинное значение (название контрагента из выписки, назначение платежа)
   не должно распирать таблицу и выталкивать колонки за экран. Предел относительный — сжимается вместе с окном. */
.ui-clamp { max-width: min(24rem, 34vw); min-width: 0; overflow: hidden; }

/* Распорка в строке-раскладке (тулбар страницы, футер слайдера): раздвигает соседей по краям.
   Единый примитив вместо инлайнового `style={{ flex: 1 }}` и одноразовых классов `*__sp` на экранах. */
.ui-sp { flex: 1; min-width: 0; }

/* Полоска-«сентинел» под длинным списком: пока не догружено — спиннер, дальше счётчик «Показано N из M».
   Высота держится постоянной, чтобы прокрутка не дёргалась в момент подгрузки. */
.ui-infinite { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 14px 0; min-height: 44px; }
.ui-infinite__note { color: var(--muted); font-size: 13px; }

/* Интерактивный список строк с разделителем и акцентным ховером (как строки товаров каталога). */
.ui-list { display: flex; flex-direction: column; }
.ui-list__row { padding: 10px 16px; border-bottom: 1px solid var(--border); }
.ui-list__row:last-child { border-bottom: none; }
/* Шапка колонок списка-сетки (как шапка таблицы кита, но без липкости и фона) и строка «добавить» под списком
   (Iris 2.0, этап 3 — раньше каждый экран держал свои: формулы закупки, шаблоны ремонтов). Колонки задаёт экран. */
.ui-list__head { padding: 4px 16px; color: var(--muted); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; border-bottom: 1px solid var(--border); }
.ui-list__add { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; padding: 6px 16px; }
.ui-list__add .ui-btn { min-width: min(9.5rem, 100%); justify-content: flex-start; }
/* Выделение (ховер) строки — СКРУГЛЁННОЕ, как заливка карточек: единый вид во всём проекте,
   поэтому радиус живёт здесь, а не в стилях экранов. Разделитель остаётся border-bottom. */
.ui-list--hover .ui-list__row { border-radius: var(--radius-sm); transition: background .15s, box-shadow .15s; }
/* Iris 2.0: заливка + тонкая обводка цветом `--st` (иначе акцент) — как строки таблиц. */
.ui-list--hover .ui-list__row:hover {
  background: color-mix(in srgb, var(--st, var(--accent)) 9%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 40%, transparent);
}
/* Строка списка целиком кликабельна (кнопка): сброс стилей button + акцент на главной строке при наведении. */
.ui-list__row--btn { width: 100%; background: none; border: none; border-bottom: 1px solid var(--border); color: inherit; font: inherit; text-align: left; cursor: pointer; }
.ui-list__row--btn:last-child { border-bottom: none; }
.ui-list__row--btn:hover .ui-cell__main { color: var(--accent); }
.ui-list--draggable .ui-list__row { cursor: grab; }
.ui-list--draggable .ui-list__row:active { cursor: grabbing; }
/* Строка компактного списка обращений (InquiryLinks) — на .ui-list кита: иконка канала · №, тема (сжимается), статус. */
.inq-link { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; }
.inq-link__subj { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Линия-индикатор места вставки при перетаскивании строки (сверху/снизу). */
.ui-list__row--before { box-shadow: inset 0 2px 0 var(--accent); }
.ui-list__row--after { box-shadow: inset 0 -2px 0 var(--accent); }
/* Подсветка зоны-приёмника (бросить в конец блока). */
.ui-droptarget { outline: 2px dashed var(--accent); outline-offset: -2px; border-radius: var(--radius); }
/* Линия-индикатор места вставки в зазоре между карточками (для DnD блоков и т.п.). */
.ui-insert { position: relative; }
.ui-insert--before::before, .ui-insert--after::after { content: ''; position: absolute; left: 0; right: 0; height: 3px; background: var(--accent); border-radius: 3px; pointer-events: none; }
.ui-insert--before::before { top: -9px; }
.ui-insert--after::after { bottom: -9px; }
/* Счётчик-пилюля (кол-во в заголовке блока/раздела). */
.ui-count { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--radius-pill); background: var(--surface-3); color: var(--muted); font-size: 11px; font-weight: 600; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* Моно-чип технического кода/ключа. */
/* inline-flex + fit-content: чип не растягивается на всю ширину, даже если стоит в блочном контейнере (div/ячейка). */
/* 🔴 Контраст (фидбек 24.07.2026): было `color: var(--muted)` на `--surface-3` — «серое по серому», ID/артикулы
   не читались НИГДЕ (схема документов, реестры, журнал СФ). Текст — основной `--text`, рамка отделяет чип от фона. */
/* Техническое значение (артикул, номер, адрес, серийник). 🔴 НЕ моноширинный мелкий шрифт (фидбек 01.08.2026):
   читается в один ряд с текстом, цифры выровнены по ширине (tabular-nums), фон мягкий, рамки нет. */
.ui-code {
  display: inline-flex; align-items: center; width: fit-content; max-width: 100%;
  font-size: 13px; line-height: 1.3; font-variant-numeric: tabular-nums; letter-spacing: .01em;
  color: var(--text); background: var(--surface-2);
  padding: 3px 9px; border-radius: var(--radius-sm);
}
/* Длинный текст «как есть» (расшифровка разговора, письмо в исходном виде, вставленный кусок).
   Переносы строк исходника сохраняются, длинные слова ломаются, высота ограничена относительно
   экрана — дальше своя прокрутка внутри блока, чтобы карточка не растягивалась на километр. */
.ui-longtext {
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: 13px; line-height: 1.55; color: var(--text);
  background: var(--surface-2); border-radius: var(--radius-sm);
  padding: 10px 12px; min-width: 0;
  /* 🔴 Высота раскрытого текста ограничена ЧИСЛОМ СТРОК (правило заказчика 28.08.2026): длинный разговор
     не должен уезжать за границу экрана и под соседние элементы — показываем разумный кусок, остальное
     прокручивается внутри блока. Переопределяется на месте через `--longtext-lines`. Второй предел (60vh)
     держит блок в пределах экрана на низких окнах и на телефоне, где 14 строк уже не помещаются.
     `overscroll-behavior: contain` — докрутив текст до конца, не пролистываем ленту под ним. */
  --longtext-lines: 14;
  max-height: min(calc(var(--longtext-lines) * 1.55em + 20px), 60vh);
  overflow-y: auto; overscroll-behavior: contain;
}

/* Длинный текст с раскрытием (компонент `LongText`): сам текст — `.ui-longtext` выше, под ним ссылка-кнопка
   «Показать полностью». Свёрнутый вид без своей прокрутки: в ленте это несколько строк превью. */
.ui-longtext-wrap { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ui-longtext__more {
  align-self: flex-start; padding: 0; border: none; background: none; cursor: pointer;
  font-size: 12.5px; color: var(--muted);
}
.ui-longtext__more:hover { color: var(--text); }

/* Расшифровка разговора репликами (компонент `Transcript`, 28.08.2026): слева — аватар сотрудника или
   цветная иконка контрагента, справа — текст реплики. 🔴 Именно grid, а не отступ у абзаца: перенос длинной
   реплики идёт под НАЧАЛО ТЕКСТА, а не под аватар (правило заказчика). Время реплики — в подсказке на аватаре. */
.ui-transcript { display: flex; flex-direction: column; gap: 7px; min-width: 0; font-size: 13px; line-height: 1.55; color: var(--text); }
.ui-transcript__row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 9px; align-items: start; }
.ui-transcript__who { flex: none; display: inline-grid; place-items: center; }
/* Иконка собеседника в кружке своей же заливкой — тот же приём, что у `.ui-cell__ico`. */
.ui-transcript__peer {
  width: 100%; height: 100%; border-radius: 50%; display: inline-grid; place-items: center;
  background: color-mix(in srgb, currentColor 16%, transparent);
}
.ui-transcript__text { min-width: 0; overflow-wrap: anywhere; padding-top: 2px; }
/* clamp — тот же предел по числу строк, что у `.ui-longtext`: в карточке звонка и в ленте общения длинный
   разговор не должен уезжать за экран. В диалоге обращения расшифровка разворачивается целиком, как письмо. */
.ui-transcript--clamp {
  --longtext-lines: 14;
  max-height: min(calc(var(--longtext-lines) * 1.55em + 20px), 60vh);
  overflow-y: auto; overscroll-behavior: contain;
}

/* Обёртка произвольного тела в `LongText` (когда текст рисуется не «как есть», а компонентом —
   напр. расшифровка репликами): только отступы, БЕЗ своей подложки (правило заказчика 31.08.2026).
   Своя светлая плашка поверх цветной карточки звонка в ленте съедала контраст — текст переставал читаться
   в обеих темах. Расшифровка ложится прямо на фон карточки. */
.ui-longbox {
  padding: 10px 12px; min-width: 0;
}
/* Нераспознанный формат расшифровки рисуется примитивом «как есть» — внутри `.ui-longbox` он тоже
   идёт без своей подложки и без двойных отступов. */
.ui-longbox > .ui-longtext { background: none; padding: 0; }

/* Ячейка списка/таблицы: опц. цветная иконка-лид + главная строка и вторичная подпись под ней.
   Цвет иконки задаётся через `color` на `.ui-cell__ico` (заливка — color-mix от currentColor). */
.ui-cell { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ui-cell__ico {
  flex: none; display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: var(--radius-sm); background: color-mix(in srgb, currentColor 16%, transparent);
}
.ui-cell__body { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.ui-cell__main { min-width: 0; max-width: 100%; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-cell__sub { min-width: 0; max-width: 100%; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Денежное/числовое значение — акцент веса и моноширинные цифры. */
.ui-sum { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Направление денег (Iris 2.0, этап 3): приход — зелёный, расход — розовый (раньше — экранные `budget-sum--*`). */
.ui-sum--in { color: var(--ic-green); }
.ui-sum--out { color: var(--ic-rose); }
/* Телефон с флагом страны + форматирование. */
.ui-phone { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.ui-phone__num { font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-flag { flex: none; border-radius: 2px; box-shadow: 0 0 0 1px color-mix(in srgb, var(--text) 15%, transparent); display: block; }
/* Контактные каналы: пометка «основной» (галочка-акцент) и строка-добавление. */
.cg-star { width: 26px; height: 26px; flex: none; display: inline-grid; place-items: center; color: var(--muted); }
.cg-star--on { color: var(--accent); }
.cg-add { color: var(--muted); }
.cg-more { display: inline-flex; align-items: center; gap: 4px; }
/* Кнопка копирования — компактная, приглушённая; на успех подсвечивается акцентом. */
.ui-copybtn { width: 26px; height: 26px; flex: none; color: var(--muted); }
.ui-copybtn:hover { color: var(--text); }
.ui-copybtn--done { color: var(--accent); }
/* Проигрыватель записи (`AudioPlayer`): кнопка, шкала и время — в оформлении кита.
   Штатный `<audio controls>` рисуется браузером и выбивается из тёмной темы. */
.ui-audio {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 8px 12px; background: var(--mat); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--mat-hl);
}
.ui-audio__btn { flex: none; }
.ui-audio__time { flex: none; color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.ui-audio__range {
  flex: 1 1 auto; min-width: 0; height: 4px; appearance: none; cursor: pointer;
  border-radius: var(--radius-pill);
  background: linear-gradient(to right, var(--accent) var(--ui-audio-pct, 0%), var(--surface-3) var(--ui-audio-pct, 0%));
}
.ui-audio__range::-webkit-slider-thumb {
  appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); border: none; cursor: pointer;
}
.ui-audio__range::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: var(--accent); border: none; cursor: pointer; }
.ui-audio__range:disabled { cursor: default; opacity: .6; }
.ui-audio--error .ui-audio__time { color: var(--ic-red); }

/* 🔴 Web SDK Voximplant вставляет в конец страницы свой контейнер с аудио-элементами. Он занимает место
   и при звонке добавлял пустую полосу со скроллом — прячем (звук от этого не страдает). */
#voximplantcontainer, #voximplantlocalvideo { position: absolute !important; width: 0; height: 0; overflow: hidden; opacity: 0; pointer-events: none; }

/* Метки «разобрано» (`MarkDone`). Не отмечено — полая точка цвета внимания (как непрочитанное письмо):
   наведение заливает её. Отмечено — яркая зелёная галочка без кнопки: действие уже совершено. */
.ui-markdone { display: inline-flex; align-items: center; justify-content: center; padding: 8px; flex: none; }
.ui-markdone--done { color: var(--ic-green); }
.ui-markdone__btn { flex: none; color: var(--ic-amber); }
.ui-markdone__btn:hover { color: var(--ic-amber); background: color-mix(in srgb, var(--ic-amber) 16%, transparent); }
.ui-markdone__btn:hover svg { fill: currentColor; }

/* Поле «готовое значение» (адрес трубки, ключ, пароль интеграции): геометрия обычного поля ввода —
   такие значения по весу и есть поля, а не подписи, — но только для чтения, с действиями справа. */
.ui-copyfield {
  display: flex; align-items: center; gap: 4px; min-width: 0;
  padding: 0 6px 0 12px; min-height: 38px;
  background: var(--ctl-bg); border: 1px solid var(--ctl-border); border-radius: var(--radius); box-shadow: var(--ctl-inset);
}
.ui-copyfield__value {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: .01em;
}

/* Секрет (токен/пароль интеграции): значение под точками + «глаз» и копирование. Моноширинное значение
   не переносится по буквам, а сжимается многоточием — иначе длинный токен ломает строку. */
.ui-secret { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; flex-wrap: wrap; }
.ui-secret__label { color: var(--muted); }
.ui-secret__value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: .04em; }
/* Строка «характеристика — значение» (просмотр спецификаций). */
.spec-row { display: grid; grid-template-columns: minmax(0, 280px) minmax(0, 1fr); gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border); }
.spec-row:last-child { border-bottom: none; }
.spec-row__name { color: var(--muted); }
.spec-row__val { white-space: pre-wrap; min-width: 0; }
/* Инлайн-правка характеристики: значение — кликабельный текст (.ui-editval), в правке — контрол по типу. */
.spec-row--edit { align-items: center; min-height: 34px; }
.spec-row--edit .spec-row__val { display: flex; align-items: center; gap: 6px; }
.spec-row__btn { flex: 1; min-width: 0; text-align: left; white-space: pre-wrap; }
.spec-row__ph { color: var(--muted); }
/* В правке: текст/список занимают всю ширину ячейки, числовое поле — по содержимому (autoWidth). */
/* Строка «как это выглядит в ТЗ» под значением характеристики (07.09.2026): приглушённая подпись
   во всю ширину колонки значения — «Не менее 300 м». Показывается, когда формулировка отличается от значения. */
.spec-row__tz { grid-column: 2; margin-top: 2px; color: var(--muted); font-size: 12px; min-width: 0; }
.spec-row__ctl { flex: 1; min-width: 0; display: flex; align-items: center; }
.spec-row__ctl > textarea, .spec-row__ctl > .ui-select { flex: 1; min-width: 0; }

/* ===================== Акцентная обводка и подсветка ===================== */
/* Выделение «главного» элемента на экране: ровное кольцо акцентом и мягкое свечение под блоком.
   Вешаются на любую карточку/панель/окно ПОВЕРХ их собственных стилей (радиус берётся у элемента).
   🔴 Кольцо — обычный `border`, а НЕ `outline`/градиентный псевдоэлемент: у outline со сдвигом внутрь
   содержимое выглядывает наружу кольца, а градиентная рамка маской утончается в углах. */
.ui-ring { border: 2px solid color-mix(in srgb, var(--accent) 72%, transparent); }
.ui-ring--soft { border-width: 1px; border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
/* Подсветка под блоком — «свет» в цвет акцента; --sm для мелких элементов (строка, кнопка). */
.ui-glow { box-shadow: 0 24px 64px -28px var(--glow), var(--shadow-sm); }
.ui-glow--sm { box-shadow: 0 10px 26px -14px var(--glow); }
/* На модалке подсветка НЕ заменяет глубокую тень портала — окно должно отрываться от затемнённого фона. */
.ui-modal.ui-glow { box-shadow: 0 24px 64px -28px var(--glow), var(--shadow-pop); }

/* ===================== Лента переписки и событий (единая) ===================== */
/* Одна и та же лента в карточке СДЕЛКИ/РЕМОНТА («События») и в карточке КОНТРАГЕНТА («Переписка»).
   До 29.07.2026 её рисовали два разных компонента своими стилями (`deal-item*` и `mail-tl*`), и один и тот же
   список выглядел по-разному. Строка: иконка канала · заголовок + первая строка текста · справа время/автор.
   Панель вокруг уже в рамке, поэтому строка — БЕЗ рамки-коробки: только нижний разделитель. */
.ui-feed { display: flex; flex-direction: column; }
.ui-feed__group { display: flex; flex-direction: column; }
.ui-feedrow {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left; font: inherit;
  padding: 10px 12px; border: 1px solid transparent; border-bottom-color: var(--border);
  border-radius: 0; background: transparent; color: var(--text);
}
.ui-feed__group:last-child .ui-feedrow:last-child { border-bottom-color: transparent; }
/* Кликабельная строка (письмо, сообщение мессенджера): ховер акцентом, как у списков кита. */
.ui-feedrow--link { cursor: pointer; align-items: center; }
.ui-feedrow--link { transition: background .15s, box-shadow .15s; }
.ui-feedrow--link:hover { background: color-mix(in srgb, var(--st, var(--accent)) 9%, transparent); border-color: transparent; border-radius: var(--radius-sm); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st, var(--accent)) 40%, transparent); }
.ui-feedrow--link:disabled { cursor: default; }
/* Строка ленты + прицепленный к ней блок (расшифровка разговора под звонком, 28.08.2026): строка сама
   по себе кнопка, поэтому дополнение живёт рядом с ней, а не внутри — вложенные кнопки недопустимы. */
.ui-feedrow-stack { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
/* Текст под строкой выравнивается по её содержимому: отступ = иконка (15px) + гап строки (10px) + паддинг. */
.ui-feedrow-stack .ui-longtext-wrap { margin: 0 12px 8px 37px; }
/* `--tall` — раскрытый блок забирает ОСТАТОК высоты контейнера и прокручивается внутри себя (в диалоге
   обращения расшифровка открывается на всю область ленты, как письмо). Высоту задаёт контейнер снаружи;
   без этого длинный текст растил бы блок и вываливался за границы пузыря. */
.ui-feedrow-stack--tall { flex: 1; min-height: 0; }
.ui-feedrow-stack--tall > .ui-longtext-wrap { flex: 1; min-height: 0; }
.ui-feedrow-stack--tall > .ui-longtext-wrap > .ui-longbox { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.ui-feedrow__ic { flex: none; display: inline-flex; margin-top: 1px; }
.ui-feedrow__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; line-height: 1.5; }
/* Системное событие — текст в несколько строк (без обрезки), у письма/сообщения строки однострочные. */
.ui-feedrow__body--wrap { white-space: pre-wrap; word-break: break-word; }
.ui-feedrow__title { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-feedrow--unread .ui-feedrow__title { font-weight: 700; }
.ui-feedrow__sub { color: var(--muted); font-size: 12px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-feedrow__aside { flex: none; display: flex; align-items: center; gap: 7px; margin-left: 8px; }
/* Кнопки-действия в строке ленты (позвонить/скопировать номер) — компактные, как в инфо-блоках:
   36px кнопки кита распирают строку. */
.ui-feedrow__acts { flex: none; display: flex; align-items: center; gap: 2px; margin-left: 8px; }
.ui-feedrow__acts .ui-iconbtn { width: 26px; height: 26px; }
.ui-feedrow__author { font-size: 12px; font-weight: 500; color: var(--text); white-space: nowrap; }
.ui-feedrow__time { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ui-feed__center { display: flex; justify-content: center; padding: var(--space-3); }

/* ===================== Очередь переписки: строка диалога/письма ===================== */
/* Общий примитив разделов «Почта», «Обращения» и «Поддержка» (до 29.07.2026 жил тремя копиями в
   pages/mail/mail.css и pages/inbox/inbox.css). Строка = индикатор непрочитанного · опц. аватар ·
   две-три текстовые строки (привязки/адрес + время сверху, дальше тема и превью). Специфика раздела
   (напр. трёхстрочная строка письма) добавляется НАДСТРОЙКОЙ в его css, базовый вид — здесь. */
.ui-daysep {
  position: sticky; top: 0; z-index: 1; padding: var(--space-2) var(--space-3);
  font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
  background: var(--surface-solid); border-bottom: 1px solid var(--border);
}
/* Разделитель в ленте внутри карточки (события/переписка контрагента): без липкости и подложки. */
.ui-daysep--plain { position: static; padding: var(--space-2) var(--space-1); background: none; border-bottom: none; }

.ui-qrow {
  display: flex; align-items: stretch; gap: var(--space-2); width: 100%; text-align: left; padding: 0;
  border: none; border-bottom: 1px solid var(--border); background: transparent; cursor: pointer; color: var(--text);
}
.ui-qrow:hover { background: var(--btn-bg-hover); }
/* Iris 2.0: открытый диалог — заливка акцентом + тонкое кольцо. */
.ui-qrow--active { background: var(--accent-soft); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent); }
/* Индикатор прочитанности: широкая зона клика на всю высоту строки, внутри — полоска чуть короче высоты,
   у левого края, со скруглёнными правыми углами. Залита у непрочитанных, у прочитанных — приглушённо при наведении. */
.ui-qrow__bar { flex: none; align-self: stretch; width: 12px; display: flex; align-items: center; justify-content: flex-start; cursor: pointer; }
.ui-qrow__bar::before { content: ''; width: 4px; height: 78%; border-radius: 0 3px 3px 0; background: transparent; }
/* Индикатор с подсказкой (в «Почте» клик по нему переключает прочитано/непрочитано): обёртка Tooltip
   становится flex-элементом строки — она не должна ни сжиматься, ни ломать растяжку полоски по высоте. */
.ui-qrow > .ui-tip { flex: none; align-self: stretch; }
.ui-qrow--unread .ui-qrow__bar::before { background: var(--accent); }
.ui-qrow:not(.ui-qrow--unread):hover .ui-qrow__bar::before { background: var(--muted); }
/* Фото собеседника (мессенджеры): у почтовых диалогов его нет — кружок просто не рисуется, строка не меняется. */
.ui-qrow__ava { flex: none; display: flex; align-items: center; padding: var(--space-3) 0; }
.ui-qrow__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; padding: var(--space-3) var(--space-3) var(--space-3) 0; }
/* Верхняя строка: привязки CRM либо адрес, справа — номер и время. Одинаковая высота у всех строк списка. */
.ui-qrow__row1 { display: flex; align-items: center; gap: var(--space-2); min-width: 0; min-height: 26px; }
.ui-qrow__addr { flex: 1; min-width: 0; font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-qrow__no { flex: none; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.ui-qrow__time { flex: none; font-size: 12px; color: var(--muted); white-space: nowrap; }
.ui-qrow__line { display: flex; align-items: center; gap: var(--space-1); min-width: 0; font-size: 13px; }
.ui-qrow__ic { flex: none; display: inline-flex; align-items: center; }
.ui-qrow__txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Счётчик кита в непрочитанной строке — акцентный (число писем в цепочке). */
.ui-qrow--unread .ui-count { background: var(--accent-soft); color: var(--accent); }

/* Привязки к CRM (сделка · контакт · компания) — цветной ТЕКСТ с иконкой, а НЕ пилюли: так высота строки
   равна строке текста и отступы в списке остаются ровными. Цвет: сделка — цвет стадии, контакт — --ic-pink,
   компания — --ic-blue (задаётся инлайн-стилем компонентом MailLinkBadges).
   🔴 Длинное название компании в списке СОКРАЩАЕТСЯ многоточием, а не прячется (фидбек заказчика 28.08.2026):
   обёртке компании ставится `--shrink`, остальные бейджи (номер сделки, имя контакта) не сжимаются. */
.ui-crmlinks { min-width: 0; display: flex; align-items: center; gap: 6px; }
.ui-crmlinks--list { flex: 1; overflow: hidden; }
.ui-crmlinks--full { flex-wrap: wrap; }
.ui-crmlink { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; font-size: 13px; font-weight: 600; line-height: 1; }
/* Иконки стадий/сущностей нарисованы со смещением вниз во вьюбоксе — оптически поднимаем к центру текста. */
.ui-crmlink svg { flex: none; stroke-width: 2.2; display: block; transform: translateY(-1.5px); }
.ui-crmlink__txt, .ui-crmlink__co { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1; }
/* Приписка рядом с названием (проп `note`: ИНН компании в реестрах) — своим, вторичным цветом,
   не наследует цвет сущности и не сжимается: рвётся название, а не ИНН. */
.ui-crmlink__note { flex: none; color: var(--muted); font-weight: 500; font-size: 12px; white-space: nowrap; }
.ui-crmlink-wrap { display: inline-flex; align-items: center; gap: 2px; flex: none; min-width: 0; }
/* Единственный сжимаемый бейдж строки: длинное название компании укорачивается многоточием (`.ui-crmlink__co`
   уже с ellipsis), а не исчезает целиком — в очереди обращений по нему видно, чья это строка. */
.ui-crmlink-wrap--shrink { flex: 0 1 auto; min-width: 0; }
.ui-crmlink-open { border: none; background: transparent; padding: 0; cursor: pointer; min-width: 0; display: inline-flex; max-width: 100%; }
.ui-crmlink__x { flex: none; width: 18px; height: 18px; }

/* ===================== Клиент «список | просмотр» (почта, обращения) ===================== */
/* 🔴 Iris 2.0, этап 3 (23.09.2026): единый примитив двухколоночного клиента — до этого «Почта» и «Обращения» держали
   одинаковую раскладку каждый у себя (`.mail-client/.mail-list`, `.inbox-client/.inbox-list`). Колонки — поверхности-
   материал. Ширина списка — переменная `--client-list` (у обращений шире: `--wide`). На телефоне по одной панели за раз —
   это делает `.ui-md` (мастер-деталь), ставится рядом с `__body`/`__list`/`__view`. */
.ui-client { display: flex; flex-direction: column; height: 100%; min-height: 0; gap: var(--space-4); }
.ui-client > .ui-pagehead { margin-bottom: 0; }
.ui-client__body { --client-list: clamp(260px, 32%, 440px); flex: 1; min-height: 0; display: grid; grid-template-columns: var(--client-list) 1fr; gap: var(--space-4); }
.ui-client__body--wide { --client-list: clamp(280px, 34%, 460px); }
.ui-client__list, .ui-client__view {
  min-height: 0; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--mat); box-shadow: var(--mat-hl); overflow: hidden;
}
.ui-client__list { display: flex; flex-direction: column; }
.ui-client__view { display: flex; }
.ui-client__filters { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border-bottom: 1px solid var(--border); }
.ui-client__filters > *:first-child { flex: 1; min-width: 0; }
.ui-client__scroll { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.ui-client__scroll::-webkit-scrollbar { width: 0; display: none; }
.ui-client__center { display: flex; justify-content: center; padding: var(--space-6); }
@media (max-width: 700px) {
  /* Телефон: правая колонка — столбиком (кнопка «К списку» сверху, содержимое под ней). */
  .ui-client__view { flex-direction: column; }
  .ui-client__view > .ui-md__back { flex: none; align-self: flex-start; margin: var(--space-2) 0 0 var(--space-2); }
}

/* ===================== Статус-точка (звонилка, присутствие на сайте) ===================== */
/* Точка + подпись. Цвет — `--st` (по умолчанию приглушённый). `--live` — у точки ореол (состояние «живое»),
   `--tone` — подпись тоже цветом состояния, `--sm` — компактнее (рядом с номером/заголовком). */
.ui-status { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-size: 13px; white-space: nowrap; }
.ui-status__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--st, var(--muted)); }
.ui-status--live .ui-status__dot {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--st, var(--muted)) 22%, transparent), 0 0 10px -1px var(--st, var(--muted));
}
.ui-status--tone { color: var(--st, var(--muted)); }
.ui-status--sm { gap: 6px; font-size: 12px; }
.ui-status--sm .ui-status__dot { width: 7px; height: 7px; }

/* ===================== Справочник характеристик ===================== */
.attr-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
.attr-back { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-size: 13px; text-decoration: none; }
.attr-back:hover { color: var(--text); }
.attr-sub { color: var(--muted); font-size: 13px; margin-top: 4px; }

.attr-groups { display: flex; flex-direction: column; gap: 16px; }
.attr-card__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
.attr-card__head--drag { cursor: grab; }
.attr-card__head--drag:active { cursor: grabbing; }
.attr-card__title { font-weight: 600; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.attr-row__main { display: flex; align-items: center; gap: 10px; }
.attr-row__name { font-size: 14px; color: var(--text); }
.attr-row__unit { color: var(--muted); font-size: 12px; }
.attr-row__actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.attr-row__opts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; padding-left: 2px; }
.attr-opt-add { display: inline-flex; align-items: center; gap: 6px; }
.attr-opt-add .ui-input { height: 30px; width: 150px; }

/* ============================================================================
   🔴 АДАПТИВНОСТЬ — сводный раздел кита (единый источник поведения на узких экранах).
   Пороги дублированы в ui/responsive.ts (BP.compact = 1024, BP.mobile = 700) — править синхронно.
   Правило: НЕ заводить per-screen медиазапросы под то, что решается здесь; экран описывает только
   свою специфичную раскладку. Токены раскладки (--sidebar-w, --content-pad, --bottomnav-h) — в tokens.css.
   ============================================================================ */

/* ---- Мастер-деталь: «список ИЛИ карточка» на телефоне (решение заказчика 26.07.2026) ----
   Двухпанельные экраны (обращения/поддержка, почта) на телефоне показывают ТОЛЬКО ОДНУ панель.
   Как применять: обёртке — класс `ui-md` (свои колонки экран задаёт сам, десктоп не меняется),
   панелям — `ui-md__master` и `ui-md__detail`, и на обёртку добавляется `ui-md--detail`, когда
   запись выбрана. Кнопка «Назад к списку» — любой элемент с классом `ui-md__back`: на десктопе
   он скрыт, на телефоне показывается (условный рендер в JS не нужен). */
.ui-md__back { display: none; }

/* ---- Десктоп: сетки-утилиты подстраиваются под ширину (разные разрешения и масштабы) ---- */
/* Раньше было фиксированное число колонок → на 1280px колонки жались, на 2560px растягивались. */
.ui-grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
.ui-grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }

/* ---- ≤1024px (планшет/телефон): меню off-canvas, слайдер на всю ширину ---- */
@media (max-width: 1024px) {
  /* 🔴 Оболочка — ОДНА колонка: меню ниже становится `position: fixed`, а фиксированный элемент ВЫПАДАЕТ
     из грид-размещения, поэтому `.ui-main` занимал бы первый трек — а он равен `--sidebar-w`, т.е. 0px
     (страница рисовалась в полоске шириной 0 и выглядела как чёрный экран). */
  .ui-shell { grid-template-columns: 1fr; }

  /* Левое меню выезжает поверх контента (в раскладке его ширина 0 — см. --sidebar-w в tokens.css). */
  .ui-sidebar {
    position: fixed; left: 0; top: 0; z-index: 1100;
    width: min(19rem, 86vw); max-width: 86vw;
    padding-top: calc(18px + env(safe-area-inset-top, 0px));
    background: var(--pop-bg); border-right: 1px solid var(--border-strong); box-shadow: var(--shadow-pop);
    transform: translateX(-100%); transition: transform .22s ease;
  }
  .ui-sidebar--open { transform: none; }

  /* Слайдер занимает всю ширину экрана; крестик переезжает ВНУТРЬ (за левой границей его было бы не видно). */
  .ui-drawer { border-left: none; }
  .ui-drawer__close--left {
    left: auto; right: 8px; top: calc(8px + env(safe-area-inset-top, 0px));
    background: var(--surface-2); border: 1px solid var(--border);
  }
  /* На телефоне слайдер во всю ширину — значок подсказок тоже переезжает внутрь, в левый нижний угол. */
  .ui-drawer__help { left: 8px; bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
  /* Большинство слайдеров рисуют СВОЮ шапку внутри тела (карточка сделки/контрагента) — плавающий крестик
     накрыл бы её. Полоска сверху ровно под крестик; со штатной шапкой (`.ui-drawer__head`) она не нужна —
     там крестик стоит в её правом углу (padding-right ниже). */
  /* Высота полоски = крестик (40px) + отступы, иначе он и кнопки История/Удалить залезали бы на контент. */
  .ui-drawer:not(:has(> .ui-drawer__head)) { padding-top: calc(52px + env(safe-area-inset-top, 0px)); }
  /* Заголовок слайдера не залезает под крестик. */
  .ui-drawer__head { padding: 14px 56px 14px var(--content-pad); }
  .ui-drawer__body { padding: var(--content-pad); overflow-x: hidden; }
  .ui-drawer__foot { padding: 12px var(--content-pad); padding-bottom: calc(12px + var(--safe-b)); }

  /* Плавающие кнопки действий слайдера (История/Удалить) были привязаны к сайдбару (left: --sidebar-w − 48px).
     На узком экране им негде висеть слева, а внизу они НАКРЫВАЛИ содержимое карточки (фидбек заказчика
     26.07.2026) — поэтому уводим их в верхнюю полоску слайдера, левее крестика закрытия. */
  .deal-actions-float {
    left: 8px; right: auto; bottom: auto; top: calc(8px + env(safe-area-inset-top, 0px));
    flex-direction: row; gap: 10px; z-index: 4;
  }
  /* Размер РОВНО как у крестика закрытия (см. `.ui-iconbtn` на телефоне) — кнопки строки одной высоты
     и на одной линии; свои 34px здесь не задаём, иначе строка выглядит неровной. */
  .deal-actions-float .ui-iconbtn { width: 40px; height: 40px; }

  /* Тосты не прячутся под нижней навигацией. */
  .ui-toasts { right: 12px; left: 12px; width: auto; bottom: calc(12px + var(--bottomnav-h) + var(--safe-b)); }

}

/* ---- ≤700px (телефон) ---- */
@media (max-width: 700px) {
  /* Поля ввода — 16px: при меньшем размере Safari/iOS зумит страницу при фокусе и раскладка «съезжает». */
  .ui-input, .ui-taginput__field, .ui-select { font-size: 16px; }
  .ui-input { padding: 11px 12px; }
  /* Поле с иконкой сохраняет отступ слева: правило `.ui-input` выше сбрасывало его, и placeholder
     налезал на иконку поиска (замечено на публичном прайсе 17.08.2026). */
  .ui-input--with-icon { padding-left: 38px; }
  /* Тач-цели крупнее. */
  .ui-iconbtn { width: 40px; height: 40px; }
  .ui-btn--sm { padding: 9px 13px; }

  /* Слайдер «Прайс для реселлеров»: строки списков — в карточку (артикул и причина уходят на свою строку,
     название перестаёт обрезаться). Правило заказчика 26.07.2026: на телефоне всё становится карточками. */
  .plist__cat, .plist__skip { flex-wrap: wrap; row-gap: var(--space-1); }
  .plist__cat > span:first-child, .plist__skipname { flex: 1 1 100%; white-space: normal; overflow: visible; }
  .plist__facts { gap: var(--space-2); }

  /* Заголовки — по ширине экрана. */
  .ui-page-title { font-size: clamp(19px, 5.2vw, 24px); }
  .ui-pagehead__title { font-size: clamp(17px, 4.8vw, 22px); white-space: normal; }
  .ui-pagehead { gap: 8px; margin-bottom: 12px; }
  .ui-pagehead__search, .ui-pagehead__search--push { flex: 1 1 100%; max-width: 100%; margin-right: 0; }
  .ui-kpi__value { font-size: clamp(20px, 5.5vw, 25px); }

  /* Модалка/слайдер — во всю ширину, высота по видимой области (dvh). */
  .ui-modal, .ui-modal--lg, .ui-modal--xl { width: calc(100vw - 20px); }
  .ui-modal { max-height: calc(100dvh - 24px); }
  .ui-modal--lg, .ui-modal--xl { height: min(88dvh, 900px); }
  .ui-modal__body, .ui-modal__head, .ui-modal__foot { padding-left: 14px; padding-right: 14px; }

  /* Поповеры/подсказки/календари — в пределах экрана. */
  .ui-popover--fixed { max-width: calc(100vw - 16px); max-height: calc(100dvh - 16px); }
  .ui-tip__pop { max-width: min(20rem, calc(100vw - 24px)); }

  /* 🔴 Таблица → карточки: шапка скрыта, каждая ячейка = «метка (data-label) → значение».
     `.ui-td--main` — главная ячейка (шапка карточки, без метки, полужирная; кит ставит её на первую
     колонку сам). `.ui-td--nolabel` и ячейки БЕЗ data-label (фото, кнопки-действия) идут без метки.
     Отключается пропом mobileCards={false} у Table. */
  .ui-table--cards { display: block; }
  .ui-table--cards thead { display: none; }
  .ui-table--cards tbody, .ui-table--cards tbody tr { display: block; width: auto; }
  .ui-table--cards tbody tr { padding: 10px 12px; border-bottom: 1px solid var(--border); }
  .ui-table--cards tbody tr:last-child { border-bottom: none; }
  /* Метка слева, значение справа (единое правило карточек, подтверждено заказчиком 26.07.2026). */
  .ui-table--cards tbody td {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    width: auto; padding: 3px 0; border: none; text-align: right;
  }
  .ui-table--cards tbody td::before {
    content: attr(data-label); flex: none; max-width: 55%; text-align: left;
    color: var(--muted); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
    overflow-wrap: anywhere;
  }
  .ui-table--cards tbody td.ui-td--main { display: block; font-weight: 600; padding-bottom: 5px; text-align: left; }
  .ui-table--cards tbody td.ui-td--nolabel { display: block; text-align: left; }
  .ui-table--cards tbody td.ui-td--main::before,
  .ui-table--cards tbody td.ui-td--nolabel::before,
  .ui-table--cards tbody td:not([data-label])::before { display: none; }
  /* Числовые колонки в карточке идут в общий столбик значений (не прижимаются к правому краю). */
  .ui-table--cards tbody td.ui-td--right { text-align: left; white-space: normal; }
  /* В карточке (телефон) усечение не нужно: ячейка занимает всю ширину карточки. */
  .ui-table--cards tbody td.ui-td--grow { max-width: none; }
  .ui-table--cards thead th.ui-td--right { width: auto; }
  /* Ховер-заливка — на всю карточку-строку. */
  .ui-table--cards tbody tr:hover > td { background: none; }
  .ui-table--cards tbody tr:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
  .ui-table--cards tbody tr.ui-tr--click:hover { background: color-mix(in srgb, var(--accent) 13%, transparent); }
  /* Подсветка строки, ждущей действия — на всю карточку (на широком экране те же полоса и заливка живут на ячейках). */
  .ui-table--cards tbody tr.ui-tr--tone > td { background: none; box-shadow: none; }
  .ui-table--cards tbody tr.ui-tr--tone {
    background: color-mix(in srgb, var(--row-tone) 10%, transparent);
    box-shadow: inset 3px 0 0 var(--row-tone);
  }
  .ui-table--cards tbody tr.ui-tr--tone:hover { background: color-mix(in srgb, var(--row-tone) 16%, transparent); }

  /* 🔴 Канбан: одна стадия на экран, свайп влево/вправо листает стадии (scroll-snap), карточки внутри
     стадии скроллятся вертикально. Точки-индикатор рисует сам Kanban (mobile). */
  /* 🔴 Один свайп = одна стадия: нативная инерция со scroll-snap пролистывала по нескольку колонок,
     поэтому горизонтальный нативный скролл выключен (`touch-action: pan-y` оставляет вертикальный внутри
     колонки), а листание страницами делает Kanban.tsx по touch-жесту. */
  .ui-kanban { gap: 10px; scroll-snap-type: none; overflow-x: hidden; touch-action: pan-y; }
  .ui-kan-col { flex: 0 0 100%; width: 100%; max-width: none; scroll-snap-align: none; }
  .ui-kan-dots { display: flex; align-items: center; justify-content: center; gap: 6px; flex: none; padding: 0 0 8px; }
  .ui-kan-dot {
    width: 7px; height: 7px; padding: 0; border: none; border-radius: 999px;
    background: var(--surface-3); cursor: pointer; transition: width .15s, background .15s;
  }
  .ui-kan-dot--on { width: 20px; background: var(--accent); }
  .kan-scrollnav { display: none; }

  /* Мастер-деталь: одна панель за раз + кнопка «Назад» (см. описание примитива выше).
     Селектор удвоен (`.ui-md.ui-md`) НАМЕРЕННО: свои колонки обёртке задаёт экран, а его CSS-файл
     подключается ПОЗЖЕ кита — при равной специфичности победил бы он, и панель не схлопнулась бы. */
  .ui-md.ui-md { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr); }
  .ui-md--detail > .ui-md__master { display: none; }
  .ui-md:not(.ui-md--detail) > .ui-md__detail { display: none; }
  .ui-md__back { display: inline-flex; }

  /* Чат: пузырь шире (на узком экране 78% выглядит обрезанным). */
  .ui-chat__row { max-width: 92%; }
  .ui-chat__body { padding: 12px; gap: 12px; }

  /* Табло-сетки витрины/страниц и сетки полей формы — одна колонка. */
  .ui-grid-2, .ui-grid-4 { grid-template-columns: 1fr; }
  .ui-formgrid--2, .ui-formgrid--3, .ui-formgrid--label { grid-template-columns: 1fr; }

  /* 🔴 Состав документа (сделка/закупка/приёмка): 12-колоночный grid не помещается на телефон →
     строка становится КАРТОЧКОЙ в стиле карточек канбана (просьба заказчика 26.07.2026): сверху превью и
     название, ниже — по строке на параметр, где МЕТКА СЛЕВА, ЗНАЧЕНИЕ СПРАВА (как `.deal-card__row`).
     Метки внутри `.fin` на десктопе скрыты (их роль играет шапка колонок) — здесь возвращаем. */
  .deal-table, .deal-table--purchase, .deal-table--receipt {
    display: flex; flex-direction: column; gap: 10px; grid-template-columns: none;
  }
  .deal-thead { display: none; }
  /* Строка 1: превью + название (с воздухом сверху/снизу). Строка 2: бейдж типа и артикул.
     Дальше — по строке на параметр. Раскладку держит flex-wrap: у названия базис «вся ширина минус
     превью», поэтому следующие элементы переносятся на новую строку и идут в ряд. */
  .deal-trow {
    display: flex; flex-wrap: wrap; align-items: center;
    column-gap: 10px; row-gap: 6px; padding: 0 12px 12px 0;
  }
  .deal-trow > .deal-tcell__thumb { flex: none; align-self: flex-start; }
  .deal-trow > .deal-tcell__name { flex: 1 1 calc(100% - 5.5rem); min-width: 0; padding: 10px 0 6px; }
  .deal-trow > .deal-tcell__type, .deal-trow > .deal-tcell__sku { flex: 0 0 auto; }
  .deal-trow > .deal-tcell__type { margin-left: 12px; }
  .deal-trow .deal-tname { white-space: normal; font-size: 14px; line-height: 1.35; }
  /* Каждое числовое поле — своя строка на всю ширину: метка слева, значение справа. */
  .deal-trow > .fin, .deal-trow > .deal-dualprice {
    flex: 0 0 100%; display: flex; align-items: baseline; justify-content: space-between;
    gap: 10px; padding-left: 12px; font-size: 13px;
  }
  .deal-trow > .deal-dualprice { flex-direction: row; flex-wrap: wrap; }
  .deal-table .fin__lbl { display: block; flex: none; }
  .deal-table .fin__val, .deal-table .fin__box { text-align: right; }
  .deal-table .fin--price { width: auto !important; }
  /* Кнопка удаления — в правом нижнем углу карточки, отдельной строкой. */
  .deal-trow > .deal-tcell__del { flex: 0 0 100%; justify-self: end; margin-left: auto; }
  /* Фото позиции: скруглены ЛЕВЫЙ ВЕРХНИЙ и ПРАВЫЙ НИЖНИЙ углы (просьба заказчика 26.07.2026). */
  .deal-trow > .deal-tcell__thumb {
    width: 56px; height: 56px; margin: 0; border: 0;
    border-radius: calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px) 0;
  }
  /* Кол-во / Скидка / Ставка НДС стояли по ЦЕНТРУ (на широком это выравнивание под шапку колонок,
     селектор с :nth-child перебивал общее правило) — в карточке они такие же строки «метка → значение». */
  .deal-trow > .fin:nth-child(n) { justify-content: space-between; }
  /* Карточки — компактнее внутренний отступ. */
  .ui-card--pad { padding: var(--space-4); }
  /* Инфо-строки, шаги, календарь диапазона — в один столбец (см. также @media в разделах компонентов). */
  .ui-stepper { flex-direction: column; gap: 12px; }
  .ui-step { flex-direction: row; align-items: center; text-align: left; }
  .ui-step__line { display: none; }
  .ui-seg { width: 100%; }
  .ui-seg__btn { flex: 1 1 0; padding: 8px 10px; }

  /* ---- Экранные раскладки, которые на телефоне обязаны стать одноколоночными ---- */
  /* Характеристика — значение (просмотр/правка спецификаций). */
  .spec-row { grid-template-columns: 1fr; gap: 2px; }
  /* Редактор письма: «Кому/Копия» в столбик. */
  .letter-editor__row2 { grid-template-columns: 1fr; }
  /* Приёмка закупки: наименование поставщика и артикул — в столбик. */
  .rcpt-item__supplier { grid-template-columns: 1fr; }
  /* 🔴 Комплектация принятого оборудования — КАРТОЧКА на строку: метка слева, значение справа
     (правило заказчика «всё карточками», 26.07.2026). Шапка колонок не нужна — её заменяют метки. */
  .rep-intake__head { display: none; }
  .rep-intake__row {
    display: flex; flex-direction: column; align-items: stretch; gap: 3px;
    padding: 9px 11px; margin-bottom: 8px;
    border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
  }
  .rep-intake__row:last-of-type { margin-bottom: 0; }
  .rep-intake__cell { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .rep-intake__cell::before {
    content: attr(data-label); flex: none;
    color: var(--muted); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  }
  .rep-intake__cell .rep-edit, .rep-intake__cell .ui-input { text-align: right; padding: 2px 0; }
  /* Кол-во в комплектации на широком экране центрируется под своей колонкой — в карточке центр не нужен. */
  .rep-intake__cell .rep-edit--center, .rep-intake__cell.rep-intake__c { text-align: right; }
  .rep-intake__row > .ui-iconbtn, .rep-intake__row > :last-child { align-self: flex-end; justify-self: end; }
  /* Связанные контакты/компании контрагента: 5-колоночный subgrid не помещается — строка переносится. */
  .cg-contacts { display: flex; flex-direction: column; gap: 8px; }
  .cg-crow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; grid-template-columns: none; }
  .cg-crow__name { flex: 1 1 60%; min-width: 0; }
  /* Каталог: дерево разделов сверху со своей прокруткой (иначе список товаров уезжает далеко вниз). */
  .catalog-aside { position: static; max-height: 40dvh; }
  /* Карточка сделки/ремонта: крупные числа шапки — по ширине экрана. */
  .deal-head__num { font-size: clamp(20px, 6vw, 28px); }
  .deal-total__val { font-size: clamp(18px, 5.5vw, 26px); }
  .deal-totals { gap: 12px; }
  .cg-head__title { font-size: clamp(16px, 4.6vw, 20px); white-space: normal; }
  /* Витрина кита. */
  .show, .show-prices__grid { grid-template-columns: 1fr; gap: 16px; }
  /* 🔴 Схема документов (вкладка «Документы» на всех экранах) — вертикальные карточки во всю ширину,
     без горизонтальной прокрутки (фидбек заказчика 26.07.2026). Было: карточка по содержимому, всё
     содержимое в ОДНУ строку (тип · № · дата · сумма) и отступ уровня 66px — дерево уезжало за экран. */
  .doctree { align-items: stretch; }
  .doctree__node { align-items: stretch; }
  /* Отступ уровня меньше: геометрия коннектора считается от этих же переменных, линии не разъезжаются. */
  .doctree__kids { --tree-h: 12px; --tree-gap: 10px; }
  .doccard { width: 100%; min-width: 0; }
  /* Содержимое — в две строки: сверху тип и №, снизу дата/количество/сумма. */
  .doccard__main { flex-wrap: wrap; row-gap: 3px; }
  .doccard__top, .doccard__sub {
    display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; flex: 0 0 100%; min-width: 0;
  }
  .doccard__body { padding: 8px 10px; }

  /* Заключение ремонта: заголовок, под ним текст ПО ЛЕВОМУ КРАЮ (текста много, «метка ↔ значение»
     в одну строку не влезает — фидбек заказчика 26.07.2026). */
  .rep-fields { grid-template-columns: 1fr; row-gap: 4px; }
  .rep-fields .rep-edit { text-align: left; padding: 2px 0 10px; }
  .rep-fields__label { padding-top: 8px; }
}

/* ---- Тач-устройства: ховер-подсветка НЕ «залипает» ----
   🔴 На телефоне после тапа `:hover` остаётся висеть до касания другого места: карточка позиции застывала
   залитой акцентом, и цвета названия/бейджей читались неверно (фидбек заказчика 26.07.2026).
   Поэтому ховер-эффекты — только для устройств с настоящим указателем. */
@media (hover: none) {
  .ui-hoverable:hover { background: inherit; border-color: var(--border); box-shadow: none; }
  .ui-list--hover .ui-list__row:hover { background: transparent; box-shadow: none; }
  .ui-table tbody tr:hover > td,
  .ui-table tbody tr.ui-tr--click:hover > td,
  .ui-table--cards tbody tr:hover,
  .ui-table--cards tbody tr.ui-tr--click:hover { background: transparent; }
  .ui-kan-card:hover { background: var(--surface-2); }
}

/* ---- ≤900px: карточка сделки/ремонта уже В ОДНУ КОЛОНКУ (см. @media 900 у `.deal-overview*` выше) ----
   🔴 Схлопывание колонок само по себе ломало вкладку «Инфо»: на широком экране КАЖДАЯ колонка живёт на всю
   высоту со своим скроллом (`flex: 1` + `overflow: hidden/auto`), а в одну колонку такие панели сжимались
   почти в ноль, и их содержимое вылезало ПОВЕРХ соседних блоков — лента событий и товары накладывались на
   «Инфо» (скриншот заказчика 26.07.2026). В одноколоночном режиме логика обратная: блоки — по своему
   контенту, прокручивается вся вкладка. Тот же приём уже применён в карточке контрагента (`.cg-col > .ui-panel`).
   Блок стоит в КОНЦЕ файла намеренно — он перебивает `.deal-docs-col`/`.deal-items-col { overflow: hidden }`. */
@media (max-width: 900px) {
  /* 🔴 ГЛАВНОЕ: в одну колонку раскладку кладёт FLEX, а не grid. Grid сжимает auto-строки до их
     min-content, а у колонок стоит `min-height: 0` → min-content = 0, поэтому все три строки
     схлопывались почти в ноль и блоки рисовались ДРУГ ПОВЕРХ ДРУГА (сначала казалось, что дело в
     `overflow` — нет, дело в сжатии треков). Во flex-колонке с `flex: none` дети занимают свою высоту. */
  .deal-overview, .deal-overview--info, .cg-cols {
    display: flex; flex-direction: column; gap: 16px; overflow-y: auto;
  }
  .deal-overview__col, .cg-col { flex: none; }
  .deal-overview__col, .deal-docs-col, .deal-items-col, .deal-right, .cg-col { overflow: visible; }
  .deal-overview__col > .ui-panel, .deal-docs-col > .ui-panel, .deal-items-col > .ui-panel { flex: none; }
  .deal-docs-col .deal-events, .deal-docs-col .docs-wrap { flex: none; min-height: 0; }
  .deal-events__body { flex: none; min-height: 0; }
  /* «Услуги и позиции» в заключении ремонта: сколько позиций — такая и высота (на широком экране список
     ограничен ~26vh со своим скроллом, на узком это резало карточки позиций). */
  .deal-conc__services .deal-tablewrap { max-height: none; overflow: visible; }
  /* Карточка позиции тянется на всю ширину блока (не по содержимому) — просьба заказчика 26.07.2026. */
  .deal-tablewrap, .deal-table, .deal-trow, .deal-item2 { width: 100%; min-width: 0; }

  /* Лента событий не растягивается на километр — предел со своим скроллом. */
  .deal-events__feed { flex: none; max-height: 60dvh; overflow-y: auto; }
  /* Превью товаров: сетка по ширине блока, своя прокрутка не нужна. */
  .deal-thumbcol { flex: none; overflow: visible; grid-template-columns: repeat(auto-fill, minmax(5rem, 90px)); }
  /* Дерево документов — по контенту (на широком оно ограничено половиной высоты колонки). */
  .docs-wrap { flex: none; max-height: none; }

  /* Шапка карточки сделки/ремонта (запрос заказчика 26.07.2026): в ПЕРВОЙ строке номер и лента СТАДИЙ,
     во ВТОРОЙ — лента вкладок (Инфо/Товары/Документы). Обе ленты занимают всю доступную ширину и
     прокручиваются пальцем (у `Tabs` кита свой горизонтальный скролл; `width: fit-content` из кита
     здесь снимается, иначе лента распирала бы строку вместо прокрутки). */
  .deal-card2, .deal-card2__top { min-width: 0; max-width: 100%; }
  .deal-head { flex-wrap: wrap; align-items: center; gap: 8px 10px; min-width: 0; max-width: 100%; }
  .deal-head__num { order: 1; flex: none; }
  /* Лента стадий — ОТДЕЛЬНОЙ строкой во ВСЮ ширину (просьба заказчика 26.07.2026: видимая часть = вся
     ширина экрана, а не остаток после номера). `flex-basis: 100%` переносит её на свою строку,
     `overflow: hidden` держит видимую область в пределах строки — длинный ряд пилюль прокручивается внутри. */
  .deal-head__stages {
    order: 2; flex: 1 1 100%; min-width: 0; margin-left: 0; overflow: hidden; max-width: 100%;
  }
  .deal-head__viewtabs { order: 3; flex: 1 1 100%; min-width: 0; max-width: 100%; overflow: hidden; }
  .deal-head__stages .ui-tabs, .deal-head__viewtabs .ui-tabs {
    width: 100%; max-width: 100%; min-width: 0;
    /* Отрицательные margin кита (−8px) делали ленту шире строки, и её правый конец уходил за границу —
       последние стадии становились недостижимы. Здесь margin снимаем, запас под свечение — в padding. */
    margin: 0; padding: 6px 2px;
  }
}
