/* Общая геометрия действий: эффекты не участвуют в раскладке. */
:root{--space-1:8px;--space-2:12px;--space-3:16px;--space-4:24px;--action-height:44px}
.main,.view,.panel,.modal,.modal-body,.category-body,.chat-thread,.chat-sidebar,.module-card{min-width:0}
.button,.file-label{min-height:var(--action-height);padding:10px 16px;gap:var(--space-1);line-height:1.4;white-space:normal;overflow-wrap:anywhere;max-width:100%;flex-shrink:1}
.button svg,.file-label svg{width:18px;height:18px;flex:0 0 18px}
.icon-button{width:var(--action-height);height:var(--action-height);min-width:var(--action-height);min-height:var(--action-height);padding:10px;flex:0 0 var(--action-height)}
.button:hover:not(:disabled),button:active:not(:disabled){transform:none}
button[aria-busy="true"]::after{position:absolute;inset:auto 8px 4px auto;width:11px;height:11px;margin:0;pointer-events:none}
.zone-toggle[aria-busy="true"]::after{content:""}
.action-row,.module-actions,.header-actions,.row-actions,.finance-row-actions,.modal-footer,.pagination>div,.notification-actions,.table-pagination{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-1)}
.action-row{margin:var(--space-3) 0}.row-actions{min-width:max-content}.module-actions{margin-top:auto;padding-top:var(--space-3)}
.module-card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-4)}
.module-grid{gap:var(--space-3);margin:var(--space-4) 0}.module-card-heading{gap:var(--space-1)}
.module-lot{display:grid;grid-template-columns:minmax(0,1fr) repeat(2,minmax(100px,130px)) var(--action-height);align-items:end;gap:var(--space-2);padding:var(--space-2) 0}
/* У лота KoSell три собственных поля: предложение, срок и бонус. Лот занимает
   всю строку, поля идут под ним, кнопка удаления остаётся справа. */
.module-lot.kosell-lot{grid-template-columns:repeat(3,minmax(110px,1fr)) var(--action-height)}
.module-lot.kosell-lot>[data-lot]{grid-column:1/-1}
.module-lot:not(:has(label)){grid-template-columns:minmax(0,1fr) var(--action-height)}
/* Строка автовыдачи: склад и кнопка «Убрать» сверху, его собственные настройки
   отдельной строкой под ними — кнопки относятся к выбранному здесь хранилищу. */
.module-lot.delivery-lot{grid-template-columns:minmax(0,1fr) var(--action-height)}
.delivery-lot-actions{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:var(--space-2)}
.delivery-lot-actions .button{flex:1 1 auto;min-height:var(--action-height)}
/* У лота Sandromania несколько групп полей: товар и хранилище идут строкой,
   режим — отдельной (у него самые длинные подписи), запас и лимит цены своими
   подстроками на всю ширину, переключатель отдельной строкой. */
.module-lot.sandro-lot{grid-template-columns:repeat(2,minmax(110px,1fr))}
.module-lot.sandro-lot>.sandro-fields,.module-lot.sandro-lot>.switch-row,.module-lot.sandro-lot>.sandro-mode-field{grid-column:1/-1}
/* Кнопка «Убрать лот» занимает всю ширину строки, как соседний переключатель
   «Автоматически пополнять». Прежде она жила в отдельной узкой колонке шириной
   в одну кнопку (44px против 486px у переключателя) и висела квадратиком под
   полями: по ней было непонятно, к чему она относится и куда нажимать.
   Колонка из шаблона сетки убрана — иначе справа осталась бы пустая полоса. */
.module-lot.sandro-lot>[data-helper="lot-remove"]{
 grid-column:1/-1;width:100%;justify-content:center;gap:8px;
 min-height:var(--action-height)}
.sandro-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:var(--space-2);align-items:end}
.sandro-fields[hidden]{display:none}
.sandro-lot-state{padding:var(--space-3);margin-top:var(--space-2);display:flex;flex-direction:column;gap:var(--space-1)}
/* Строка с флажком — сама цель нажатия: по WCAG 2.2 AA её короткая сторона
   не меньше 24px. Сам флажок остаётся прежнего размера. */
.check-label,.switch-row{min-height:24px}
.module-lot label,.module-lot select{min-width:0;width:100%;max-width:100%}
.module-lot select{min-height:var(--action-height)}
.toolbar{gap:var(--space-2);flex-wrap:wrap;align-items:end}.toolbar label{min-width:0}.toolbar select{max-width:100%;width:100%}
/* Иконка поиска. Прежнее правило в styles.css метит `.search-box > svg`, но
   иконка обёрнута в <span data-icon> (app.js вкладывает svg внутрь), поэтому
   абсолютное позиционирование не применялось: значок выпадал над полем, а
   padding-left оставлял под него пустое место. Позиционируем саму обёртку и
   выравниваем по центру поля, не завися от его высоты. */
.search-box>[data-icon]{
 position:absolute;left:12px;top:50%;transform:translateY(-50%);
 display:inline-flex;width:18px;height:18px;pointer-events:none;color:var(--muted);z-index:1}
.search-box>[data-icon]>svg{width:18px;height:18px}
.section-top{flex-wrap:wrap;gap:var(--space-3);align-items:center}.header-actions{flex-shrink:1;justify-content:flex-end}
.page-header{flex-wrap:wrap}.page-header>div{min-width:0}.page-footer{align-items:center}
/* Ссылка в подвале — полноценная цель нажатия: без этого её высота равна
   высоте строки (15px), что меньше пригодного для пальца минимума. */
.page-footer a{display:inline-flex;align-items:center;min-height:24px;padding:4px 0}
.modal-footer{justify-content:flex-end;padding:var(--space-3) var(--space-4)}
/* Подвал диалога плагинов: «Отмена» и «Сохранить» делят ширину пополам и
   стоят по центру. В остальных диалогах кнопки остаются прижатыми вправо —
   там их набор разный (бывает третья, разрушающая, кнопка «Удалить»), и
   равная доля развела бы их по смыслу неверно. Здесь кнопок ровно две, и
   это две равнозначные развязки длинной формы. */
#helper-dialog .modal-footer{justify-content:center}
#helper-dialog .modal-footer>.button{flex:1 1 0;max-width:260px;min-height:var(--action-height)}
/* Диалог настроек плагина прокручивался целиком: при открытых категориях он
   перерастал окно, и «Отмена»/«Сохранить» уезжали за нижний край — на экране
   720px их не было видно вовсе, а заголовок уходил вверх при прокрутке.

   Теперь прокручивается только тело: шапка и кнопки закреплены. Та же
   раскладка уже стоит у диалога склада (inventory.css) и у выбора обоев —
   здесь она просто распространена на весь диалог плагина, а не на один вид.

   Высота в dvh, а не vh: на мобильных адресная строка скрывается и обратно,
   и vh считается по большему размеру — кнопки снова оказались бы за краем. */
#helper-dialog{overflow:hidden}
#helper-dialog>form{display:flex;flex-direction:column;max-height:calc(90dvh - 2px)}
#helper-dialog>form>:is(.modal-heading,.modal-footer){flex-shrink:0}
#helper-dialog>form>.modal-body{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
.modal-heading{gap:var(--space-3)}.modal-heading h2{min-width:0;overflow-wrap:anywhere}.modal-body{padding:var(--space-4)}
.modal form{min-width:0}.form-row,.rule-repeat-fields{gap:var(--space-3)}.form-row>*{min-width:0}
.category-body{gap:var(--space-3);padding:var(--space-1) var(--space-3) var(--space-3)}
.settings-category>summary{gap:var(--space-2)}.settings-category>summary::after{flex-shrink:0}
.statistics-controls{padding:var(--space-3);margin-bottom:var(--space-3);overflow:visible}
.statistics-toolbar{display:grid;grid-template-columns:minmax(150px,1.3fr) minmax(170px,1fr) repeat(2,minmax(135px,.8fr));margin:0}
.statistics-toolbar input,.statistics-toolbar select{width:100%;max-width:100%;min-height:var(--action-height)}
.financial-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-3);margin-bottom:var(--space-3)}
.stat-card{padding:var(--space-3)}.stat-card strong{overflow-wrap:anywhere}.stat-card small{display:block;line-height:1.5;color:var(--muted)}
.metric-comparison{margin-top:var(--space-1);font-size:11px}.metric-extra{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-3)}
/* Направление изменения видно до чтения подписи: цвет зависит от того, хорош ли рост. */
.metric-trend{display:inline-flex;align-items:center;gap:6px;margin-top:var(--space-1);padding:3px 8px;border-radius:999px;font-size:11px;font-weight:600;white-space:nowrap;width:max-content;max-width:100%;font-variant-numeric:tabular-nums}
.metric-trend.good{background:color-mix(in srgb,var(--green,#2f9e6e) 14%,transparent);color:var(--green,#1f7a53)}
.metric-trend.bad{background:color-mix(in srgb,var(--bad-ink,#bf5665) 14%,transparent);color:var(--bad-ink,#bf5665)}
.metric-trend.flat{background:var(--surface-soft);color:var(--muted)}
.metric-trend svg.icon{flex-basis:14px;width:14px;height:14px}
.stat-card[data-unknown="true"] strong,.extra-metric[data-unknown="true"] strong{color:var(--muted)}
#statistics-status{display:grid;gap:var(--space-1)}
#statistics-status .status-meta{font-size:11px;opacity:.85}
.status-issues{margin:var(--space-1) 0 0;padding-left:var(--space-3);display:grid;gap:4px;font-size:11px}
.status-issues li{line-height:1.5}
.extra-metric{border-bottom:1px solid var(--border);padding:var(--space-2) 0}.extra-metric strong{font-size:20px;display:block}.extra-metric small{display:block;color:var(--muted)}
.chart-grid{gap:var(--space-3);margin:var(--space-3) 0}.chart-card{padding:var(--space-3);overflow:visible;display:flex;flex-direction:column;gap:var(--space-2)}
.chart-card h3{margin:0}.chart-legend{display:flex;flex-wrap:wrap;gap:var(--space-1)}.chart-legend .button{padding:8px 12px;font-size:12px;text-align:left}
.chart-legend [aria-pressed="false"]{opacity:.55}.legend-dot{display:inline-block;width:9px;height:9px;flex:0 0 9px;border-radius:50%;background:var(--series-color)}
.chart-plot{min-width:0;min-height:150px}.chart-plot svg{width:100%;height:auto;display:block;overflow:visible}
.chart-axis,.chart-text,.chart-line,.chart-dot{pointer-events:none}.chart-hit{cursor:crosshair;outline:none}.chart-hit:focus-visible{stroke:var(--accent);stroke-width:1.5;fill:color-mix(in srgb,var(--accent) 6%,transparent)}
.chart-empty{padding:var(--space-4) var(--space-2);color:var(--muted)}.chart-caption{font-size:11px;color:var(--muted);margin-top:auto}
.chart-tooltip{position:fixed;z-index:2000;width:max-content;max-width:min(340px,calc(100vw - 16px));padding:var(--space-3);border:1px solid var(--border);background:var(--surface);color:var(--ink);pointer-events:none;font-size:12px;overflow-wrap:anywhere}
.tooltip-value{display:flex;justify-content:space-between;gap:var(--space-3);margin-top:var(--space-1)}.tooltip-value strong{white-space:nowrap;font-variant-numeric:tabular-nums}.chart-tooltip small{display:block;color:var(--muted);margin-top:var(--space-2)}
.table-pagination{justify-content:space-between;padding:var(--space-3)}td:last-child>.button+ .button{margin-left:var(--space-1)}
#cost-editor-list,#group-results{margin-top:var(--space-3);min-width:0}#cost-editor-list .table-scroll{max-height:45vh;overflow:auto}
.analytic-group>summary{gap:var(--space-2);padding:var(--space-3)}.analytic-group>summary strong{min-width:0;flex-basis:180px}
.grouping-toolbar{margin:0 0 var(--space-3)}.group-selection{gap:var(--space-2)}.group-selection label{min-width:0}
#chat-send-form textarea{min-width:0;width:100%}
.sidebar .panel-control-row{gap:var(--space-1)}.sidebar .panel-control-row .icon-button{flex-shrink:0}
/* Панели-формы: содержимое прилипало к рамке, так как .panel не задаёт padding. */
#admin-settings-form{display:grid;gap:var(--space-3);padding:var(--space-4)}
#admin-settings-form h3{margin:var(--space-2) 0 0}
#admin-settings-form>label{display:grid;gap:6px}
#top-products,#financial-expenses,#cost-editor-list>.table-scroll{min-width:0}
#top-products:not(:has(table)),#financial-expenses:not(:has(table)){padding:var(--space-3)}
@media(max-width:1100px){.statistics-toolbar{grid-template-columns:repeat(2,minmax(0,1fr))}.header-actions{justify-content:flex-start}.chart-grid{grid-template-columns:1fr}}
@media(max-width:640px){
 .financial-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.stat-card>strong{font-size:23px}
 .main{padding:var(--space-3)}.toolbar{align-items:stretch}.toolbar>*{max-width:100%}
 .action-row>.button,.module-actions>.button{flex:1 1 140px}.action-row>.button.primary{flex-basis:100%}
 .module-lot{grid-template-columns:repeat(2,minmax(0,1fr)) var(--action-height)}.module-lot>[data-lot]{grid-column:1/-1}
 .module-lot.kosell-lot{grid-template-columns:repeat(2,minmax(0,1fr)) var(--action-height)}
 .module-lot.kosell-lot>label:last-of-type{grid-column:1/-1}
 .sandro-fields{grid-template-columns:repeat(2,minmax(0,1fr))}
 .module-lot:not(:has(label)){grid-template-columns:minmax(0,1fr) var(--action-height)}.module-lot:not(:has(label))>[data-lot]{grid-column:auto}
 .modal-body,.modal-footer,.module-card{padding:var(--space-3)}.modal-footer>.button{flex:1 1 120px}
 #chat-send-form{grid-template-columns:minmax(0,1fr)}#chat-send-form>.button{width:100%}
 .sidebar .icon-button{width:36px;height:36px;min-width:36px;min-height:36px;flex-basis:36px;padding:8px}
 .sidebar-bottom{min-width:0;flex-wrap:wrap}.panel-controls{gap:var(--space-1)}.nav-item{min-height:44px}
}
@media(max-width:380px){.statistics-toolbar,.metric-extra{grid-template-columns:1fr}.financial-grid{gap:var(--space-1)}.stat-card{padding:var(--space-2)}.stat-heading{font-size:11px}.stat-card>strong{font-size:21px}.module-actions>.button{flex-basis:100%}
 /* На 320px две колонки оставляют лоту Sandromania по 76px, а «Sandromania»
    в подписи не переносится и обрезается. Товар и хранилище встают друг под
    друга: подписи читаются целиком, кнопка «Убрать лот» остаётся справа. */
 .module-lot.sandro-lot{grid-template-columns:minmax(0,1fr) var(--action-height)}
 .module-lot.sandro-lot>label{grid-column:1}
 .sandro-fields{grid-template-columns:minmax(0,1fr)}
}
@media(prefers-reduced-motion:reduce){.chart-hit,.button{transition:none}}
/* Keep separate hit areas across menus, wrapped actions and modal controls. */
.navigation{gap:10px}
.action-row,.module-actions,.header-actions,.row-actions,.finance-row-actions,.modal-footer,.footer-right,.pagination>div,.notification-actions,.table-pagination,.panel-controls,.panel-control-row{gap:12px}
.toolbar{column-gap:12px;row-gap:16px}
.sidebar .panel-control-row,.sidebar .panel-controls{gap:10px}
.settings-category+.settings-category{margin-top:12px}
.header-actions .button{min-height:var(--action-height)}
