/* forge — design-system: Toast + Dialog (confirm).
 *
 * Префикс `ds-` (design-system) — общие компоненты для всех приложений.
 * Все цвета/типографика — через CSS-переменные с fallback'ами:
 *   --ds-bg, --ds-line, --ds-ink, --ds-dim, --ds-font, --ds-radius
 *   --ds-info, --ds-success, --ds-warn, --ds-error
 *
 * Приложение переопределяет переменные в своём tokens.css — стили
 * автоматически подстраиваются. Никаких inline-стилей в JS.
 *
 * Toast структура:
 *   <div class="ds-toast ds-toast--info [ds-toast--closable]">
 *     <span class="ds-toast__text">...</span>
 *     [<button class="ds-toast__close">×</button>]
 *   </div>
 *
 * Dialog структура:
 *   <div class="ds-overlay">
 *     <div class="ds-dialog ds-dialog--warn">
 *       <p class="ds-dialog__text">...</p>
 *       <div class="ds-dialog__actions">
 *         <button class="ds-btn ds-btn--ghost">Отмена</button>
 *         <button class="ds-btn ds-btn--primary">Подтвердить</button>
 *       </div>
 *     </div>
 *   </div>
 */

/* ── переменные с fallback'ами на тёмную палитру по умолчанию ─────────────── */
:root {
    --ds-bg:      var(--bg,    #181410);
    --ds-line:    var(--line,  #2a2014);
    --ds-ink:     var(--ink,   #e5dcc0);
    --ds-dim:     var(--dim,   #5a4a30);
    --ds-font:    var(--font);
    --ds-radius:  2px;

    /* Высота интерактивных контролов (input, button, toggle, icon-only btn).
       Базовая клетка дизайн-системы — должна быть одинакова чтобы поля и
       кнопки в одной строке выравнивались идеально. */
    --ds-control-height: 38px;

    --ds-info:    var(--gold,  #d4af6a);
    --ds-success: var(--murm,  #4b8c32);
    --ds-warn:    var(--cyan,  #50b4dc);
    --ds-error:                #c54b3a;

    /* ON-цвет toggle-switch (pill `.ctgl`). Отдельный токен (не --ds-info), чтобы
       проект перекрашивал switch одной строкой `--switch-on: <цвет>` в tokens.css,
       не трогая семантический info. Дефолт — охровый (как info). Весь pill
       (фон/точка/glow) тянет эту переменную (через color-mix для прозрачностей). */
    --ds-switch-on: var(--switch-on, var(--ds-info));
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Toast container (фиксированный сверху по центру)                            */
/* ─────────────────────────────────────────────────────────────────────────── */

#toast-root {
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    /* Поверх `.ds-overlay` (1100) — toast обязан перекрывать открытую
       модалку, иначе ошибка валидации формы внутри модалки невидима. */
    z-index: 1200;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    max-width: calc(100vw - 32px);
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Toast                                                                       */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-toast {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 240px;
    max-width: 480px;
    padding: 12px 16px;
    background: var(--ds-bg);
    color: var(--ds-ink);
    border: 1px solid var(--ds-line);
    border-radius: var(--ds-radius);
    font: 300 13px/1.4 var(--ds-font);
    letter-spacing: 0.04em;
    opacity: 0;
    transform: translateY(-12px);
    transition: opacity .25s ease, transform .25s ease;
}

.ds-toast--visible {
    opacity: 1;
    transform: translateY(0);
}

.ds-toast__text {
    flex: 1;
    word-break: break-word;
}

.ds-toast__close {
    flex: 0 0 auto;
    background: transparent;
    border: 0;
    color: var(--ds-dim);
    cursor: pointer;
    font: 300 18px/1 var(--ds-font);
    padding: 0 4px;
    transition: color .15s;
}
.ds-toast__close:hover { color: var(--ds-ink); }

/* типы — задают акцентный цвет рамки и текста */
.ds-toast--info    { border-color: var(--ds-info);    color: var(--ds-info);    }
.ds-toast--success { border-color: var(--ds-success); color: var(--ds-success); }
.ds-toast--warn    { border-color: var(--ds-warn);    color: var(--ds-warn);    }
.ds-toast--error   { border-color: var(--ds-error);   color: var(--ds-error);   }

/* persistent (closable) — без авто-закрытия, видна кнопка × */
.ds-toast--closable .ds-toast__close { display: inline; }

/* Check (зелёная галка) — левая иконка success-toast'ов. Добавляется в DOM
   только для type=success (см. toast.js), поэтому CSS-условия не нужны. */
.ds-toast__check {
    flex: 0 0 auto;
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Dialog (overlay + confirm)                                                  */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity .2s ease;
}
.ds-overlay--visible { opacity: 1; }

.ds-dialog {
    background: var(--ds-bg);
    border: 1px solid var(--ds-line);
    border-radius: var(--ds-radius);
    padding: 28px 32px;
    max-width: 440px;
    width: 90%;
    transform: scale(0.96);
    transition: transform .2s ease;
}
.ds-overlay--visible .ds-dialog { transform: scale(1); }

.ds-dialog__text {
    color: var(--ds-ink);
    font: 300 14px/1.55 var(--ds-font);
    margin: 0 0 24px;
    text-align: center;
    letter-spacing: 0.04em;
}

.ds-dialog__actions {
    display: flex;
    gap: 12px;
    justify-content: center;
}

.ds-dialog--info    { border-color: var(--ds-info);    }
.ds-dialog--success { border-color: var(--ds-success); }
.ds-dialog--warn    { border-color: var(--ds-warn);    }
.ds-dialog--error   { border-color: var(--ds-error);   }

/* ─────────────────────────────────────────────────────────────────────────── */
/* Buttons (минимальный design-system, переопределяется проектом)              */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: transparent;
    border: 1px solid var(--ds-line);
    color: var(--ds-ink);
    font: 300 12px/1 var(--ds-font);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    padding: 10px 20px;
    cursor: pointer;
    border-radius: var(--ds-radius);
    transition: all .15s ease;
    text-decoration: none;
}
.ds-btn:hover {
    border-color: var(--ds-info);
    color: var(--ds-info);
    text-decoration: none;
}
/* Disabled — заметно приглушённая кнопка, без hover-реакции.
   `not-allowed` курсор делает кликабельность визуально явной. */
.ds-btn:disabled {
    cursor: not-allowed;
    opacity: 0.4;
    pointer-events: none;
}

/* icon-only — квадратная кнопка без текста (delete/edit в таблицах,
   toolbar action-кнопки). Padding согласован с обычными `.ds-btn`
   (10px вертикали) — высота совпадает с кнопками с текстом, поэтому
   в одной toolbar-строке они одного размера. */
.ds-btn--icon-only {
    padding: 0;
    width: var(--ds-control-height);
    height: var(--ds-control-height);
    gap: 0;
    justify-content: center;
}

/* spinner-слот всегда есть в DOM, но скрыт. Активируется при .is-loading
   (см. ui-actions.runHandler). В loading-режиме обычная иконка прячется. */
.ds-btn__icon, .ds-btn__spinner {
    display: inline-flex;
    align-items: center;
    line-height: 0;
}
.ds-btn__spinner { display: none; }
.ds-btn.is-loading .ds-btn__icon    { display: none; }
.ds-btn.is-loading .ds-btn__spinner { display: inline-flex; }

.ds-btn--ghost   { border-color: var(--ds-dim);     color: var(--ds-dim); }
.ds-btn--primary { border-color: var(--ds-info);    color: var(--ds-info); }
.ds-btn--success { border-color: var(--ds-success); color: var(--ds-success); }
.ds-btn--danger  { border-color: var(--ds-error);   color: var(--ds-error); }

.ds-btn--primary:hover { background: var(--ds-info);    color: var(--ds-bg); }
.ds-btn--success:hover { background: var(--ds-success); color: var(--ds-bg); }
.ds-btn--danger:hover  { background: var(--ds-error);   color: var(--ds-bg); }

/* ─────────────────────────────────────────────────────────────────────────── */
/* Dialog form — обёртка для полей в модалах                                   */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-dialog__form {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ds-dialog__form .ds-dialog__actions {
    margin-top: 12px;
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* ds-field — каркасное поле формы (рендерится макросом `forms::field`).        */
/* Структура: <input.ds-field__input> + <span.ds-field__error>.                */
/* Сообщение об ошибке всегда занимает место — layout не прыгает.              */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ds-field__input {
    background: transparent;
    border: 1px solid var(--ds-line);
    color: var(--ds-ink);
    font: 300 14px/1.4 var(--ds-font);
    /* padding 8px+2px(border)+~20px(line)+8px = 38px — той же высоты что
       у `.ds-btn--icon-only` (38×38), `.ds-bool` (38×38) и
       `.ds-bool-toggle__square` (38×38). Контролы admin-форм визуально
       выровнены по нижнему краю в одну линию. */
    padding: 8px 12px;
    border-radius: var(--ds-radius);
    outline: none;
    transition: border-color .15s ease;
}

.ds-field__input:focus {
    border-color: var(--ds-info);
}

.ds-field__error {
    display: block;
    min-height: 14px;          /* резерв места — layout не прыгает */
    line-height: 14px;
    font-size: 11px;
    color: var(--ds-error);
    padding-left: 2px;
    visibility: hidden;
}

.ds-field.is-error .ds-field__input {
    border-color: var(--ds-error);
}

.ds-field.is-error .ds-field__error {
    visibility: visible;
}

/* readonly-поле — визуально приглушённое, не интерактивное */
.ds-field--readonly .ds-field__input {
    background: var(--ds-line);
    color: var(--ds-dim);
    cursor: not-allowed;
    border-color: transparent;
}
.ds-field--readonly .ds-field__input:focus {
    border-color: transparent;
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Icons (универсальный SVG-компонент `<icon name="..." />`)                   */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-icon {
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
}

/* Spinner — добавляется как иконка через `<icon name="spinner" />`. */
.ds-icon--spin {
    animation: ds-spin 0.8s linear infinite;
    transform-origin: center;
}
@keyframes ds-spin {
    to { transform: rotate(360deg); }
}

/* label над input в ds-field — стильный, мелкий, uppercase, акцентный */
.ds-field__label {
    display: block;
    font: 300 11px/1.2 var(--ds-font);
    color: var(--ds-dim);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 4px;
}
.ds-field__required {
    color: var(--ds-error);
    margin-left: 2px;
}

/* checkbox row — лейбл слева от input. */
.ds-field__checkbox-row {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font: 300 14px/1.4 var(--ds-font);
    color: var(--ds-ink);
}
.ds-field__checkbox-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--ds-info);
    cursor: pointer;
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Toggle — iOS-style switch для bool-полей.                                   */
/* Обычный <input type="checkbox"> + визуальный track+thumb.                   */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-toggle {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font: 300 14px/1.4 var(--ds-font);
    color: var(--ds-ink);
    user-select: none;
}
.ds-toggle__input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.ds-toggle__track {
    display: inline-block;
    position: relative;
    width: 36px;
    height: 20px;
    background: var(--ds-line);
    border-radius: 999px;
    transition: background .18s ease;
    flex-shrink: 0;
}
.ds-toggle__thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: var(--ds-bg);
    border: 1px solid var(--ds-line);
    border-radius: 50%;
    transition: transform .18s ease, border-color .18s ease;
}
.ds-toggle__input:checked + .ds-toggle__track {
    background: var(--ds-info);
}
.ds-toggle__input:checked + .ds-toggle__track .ds-toggle__thumb {
    transform: translateX(16px);
    border-color: var(--ds-info);
}
.ds-toggle__input:focus-visible + .ds-toggle__track {
    box-shadow: 0 0 0 2px var(--ds-info);
}

/* toggle-поле — стандартный layout [label]/[объект], как у всех ds-field.
   Высота input'а в input-полях ≈ 38px (10px padding + ~14px line-height + border).
   У toggle track 20px — выравниваем визуально по вертикали через padding-top. */
.ds-field--toggle .ds-toggle {
    padding-top: 9px; /* визуальное выравнивание track'а с input в соседних колонках */
}
.ds-field--toggle .ds-field__error { display: none; }

/* ─────────────────────────────────────────────────────────────────────────── */
/* Chips — выбор из набора (один из многих). hidden input хранит value.        */
/* JS: forge/static/js/chips.js — клик меняет .is-selected + hidden value.      */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-chips__list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
/* Multi-select chips — визуально подчёркиваем что можно выбирать несколько
   (рамка пунктиром на контейнере, чуть шире gap). Single-select (default) —
   радио-стиль без визуальной отбивки контейнера. */
.ds-chips--multi .ds-chips__list {
    gap: 8px;
    padding: 6px 0;
}
.ds-chips--multi .ds-chip {
    border-style: dashed;
}
.ds-chips--multi .ds-chip.is-selected {
    border-style: solid;
}
.ds-chip {
    display: inline-flex;
    align-items: center;
    background: transparent;
    border: 1px solid var(--ds-line);
    color: var(--ds-dim);
    font: 300 12px/1 var(--ds-font);
    letter-spacing: 0.04em;
    padding: 10px 14px;
    border-radius: var(--ds-radius, 2px);
    cursor: pointer;
    transition: all .15s ease;
}
.ds-chip:hover {
    border-color: var(--ds-accent, #c8a04a);
    color: var(--ds-accent, #c8a04a);
}
.ds-chip.is-selected {
    background: var(--ds-accent, #c8a04a);
    border-color: var(--ds-accent, #c8a04a);
    color: var(--ds-bg);
}
.ds-chip.is-selected:hover {
    opacity: 0.92;
}

/* readonly-chip — отображение для list-view (например в строках таблицы users).
   Не button, без cursor-эффекта, hover не меняет вид. */
.ds-chip--readonly {
    cursor: default;
}
.ds-chip--readonly:hover,
.ds-chip--readonly.is-selected:hover {
    opacity: 1;
    border-color: var(--ds-info);
    color: var(--ds-bg);
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Textarea — многострочный input. Тот же базовый стиль ds-field__input,       */
/* но с min-height и vertical resize.                                          */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-field__textarea {
    min-height: 80px;
    resize: vertical;
    line-height: 1.55;
    font-family: var(--ds-font);
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* WYSIWYG — Quill 2 (snow theme). Vanilla, без jQuery.                         */
/* Quill рисует своё дерево ql-toolbar + ql-container > ql-editor рядом с       */
/* hidden <textarea>. Минимальные правки чтобы вписать в нашу палитру.          */
/* ─────────────────────────────────────────────────────────────────────────── */

.ds-field--wysiwyg .ds-wysiwyg-wrap {
    border-radius: var(--ds-radius);
    overflow: hidden;
}

/* объединяем border toolbar + container в один цельный блок */
.ds-field--wysiwyg .ql-toolbar.ql-snow,
.ds-field--wysiwyg .ql-container.ql-snow {
    border-color: var(--ds-line);
    background: transparent;
}
.ds-field--wysiwyg .ql-toolbar.ql-snow {
    border-top-left-radius: var(--ds-radius);
    border-top-right-radius: var(--ds-radius);
}
.ds-field--wysiwyg .ql-container.ql-snow {
    border-bottom-left-radius: var(--ds-radius);
    border-bottom-right-radius: var(--ds-radius);
}
.ds-field--wysiwyg .ds-wysiwyg-wrap:focus-within .ql-toolbar.ql-snow,
.ds-field--wysiwyg .ds-wysiwyg-wrap:focus-within .ql-container.ql-snow {
    border-color: var(--ds-info);
}

/* содержимое редактора */
.ds-field--wysiwyg .ql-editor {
    background: transparent;
    color: var(--ds-ink);
    font: 300 14px/1.55 var(--ds-font);
}
.ds-field--wysiwyg .ql-editor.ql-blank::before {
    color: var(--ds-dim);
    font-style: normal;
    opacity: 0.6;
}

/* иконки тулбара под нашу палитру */
.ds-field--wysiwyg .ql-snow .ql-stroke   { stroke: var(--ds-dim); }
.ds-field--wysiwyg .ql-snow .ql-fill,
.ds-field--wysiwyg .ql-snow .ql-stroke.ql-fill { fill: var(--ds-dim); }
.ds-field--wysiwyg .ql-snow .ql-picker-label   { color: var(--ds-dim); }
.ds-field--wysiwyg .ql-snow button:hover .ql-stroke,
.ds-field--wysiwyg .ql-snow button.ql-active .ql-stroke {
    stroke: var(--ds-info);
}
.ds-field--wysiwyg .ql-snow button:hover .ql-fill,
.ds-field--wysiwyg .ql-snow button.ql-active .ql-fill {
    fill: var(--ds-info);
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Admin-form layout — кнопки, отступы полей, горизонтальные ряды.             */
/* Каждый ряд: <div class="admin-form__row">…ds-field…</div>                   */
/* Поля растягиваются равномерно по flex; узким полям — width-override через   */
/* модификатор (`.ds-field--narrow`). На мобилке — flex-direction: column.     */
/* ─────────────────────────────────────────────────────────────────────────── */

/* Кнопки на admin-формах — по правому краю (default — center из dialog). */
.admin-form .ds-dialog__actions {
    justify-content: flex-end;
    gap: 8px;
    margin-top: 24px;
}

/* Поля admin-формы — расстояние между ds-field больше чем в модалах. */
.admin-form .ds-field {
    margin-bottom: 16px;
}

.admin-form__row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: flex-start;
    margin-bottom: 16px;
}
.admin-form__row > .ds-field {
    flex: 1;
    min-width: 120px;
    margin-bottom: 0;
}
.admin-form__row > .ds-field--narrow { flex: 0 1 120px; }
.admin-form__row > .ds-field--wide   { flex: 2; }

/* Разделитель смысловых блоков формы (картинки → варианты и т.п.). */
.admin-form__sep {
    border: 0;
    border-top: 1px solid var(--ds-line);
    margin: 24px 0;
}

@media (max-width: 720px) {
    .admin-form__row { flex-direction: column; gap: 0; }
    .admin-form__row > .ds-field { flex: 1; }
}
