/* ============================================================================
   ЭТОПОСТ — дизайн-система
   ----------------------------------------------------------------------------
   Bootstrap 5.3 не пересобирается из Sass: тема задаётся перекрытием его же
   CSS-переменных. Так в проекте не появляется npm и шага сборки, а обновление
   Bootstrap сводится к замене одного файла.

   Правила, которых держимся:
     • Никаких градиентов и теней. Глубина — границей в 1px и оттенком фона.
     • Отступы только из шкалы ниже, не «на глаз».
     • Каждая пара цветов проверена по WCAG 2.1 (минимум 4.5:1 для текста).
   ========================================================================= */

:root {
    /* --- Зелёная шкала ------------------------------------------------- */
    --eto-accent:        #1B6B4C;   /* кнопки, активные состояния, ссылки  */
    --eto-accent-hover:  #155A3F;
    --eto-accent-press:  #114A34;
    --eto-accent-tint:   #E8F2ED;   /* подложка активного пункта меню      */
    --eto-accent-tint-2: #F3F8F5;   /* самая светлая подложка              */
    --eto-accent-border: #C6DED2;

    /* --- Поверхности и текст ------------------------------------------- */
    --eto-bg:            #F6F8F7;   /* фон страницы                        */
    --eto-surface:       #FFFFFF;   /* карточки, поля ввода                */
    --eto-border:        #E2E8E5;
    --eto-border-strong: #CDD6D1;   /* граница поля ввода — видна чётче    */

    --eto-text:          #14211B;
    --eto-muted:         #59685F;   /* вторичный текст, 5.5:1 на фоне      */
    /* Только плейсхолдеры, иконки и крупный текст: 3.4:1 на фоне страницы.
       Для содержательного текста этого мало, там --eto-muted (5.5:1). */
    --eto-subtle:        #7B8A82;

    --eto-danger:        #B3261E;
    --eto-danger-tint:   #FDECEA;
    --eto-warning:       #8A5A00;
    --eto-warning-tint:  #FDF4E3;

    /* --- Шкала отступов -------------------------------------------------
       Кратна 4px. Значения из шкалы, а не произвольные, — то, что делает
       вёрстку «спокойной»: расстояния повторяются и глаз их не замечает. */
    --eto-space-1: .25rem;   /*  4px */
    --eto-space-2: .5rem;    /*  8px */
    --eto-space-3: .75rem;   /* 12px */
    --eto-space-4: 1rem;     /* 16px */
    --eto-space-5: 1.5rem;   /* 24px */
    --eto-space-6: 2rem;     /* 32px */
    --eto-space-7: 2.5rem;   /* 40px */
    --eto-space-8: 4rem;     /* 64px */

    /* --- Скругления ---------------------------------------------------- */
    --eto-radius-sm: 8px;
    --eto-radius:    10px;
    --eto-radius-lg: 14px;

    /* --- Размеры ------------------------------------------------------- */
    --eto-control-h:  2.75rem;  /* 44px — минимальная цель для пальца      */
    --eto-topbar-h:   4rem;

    /* Кабинету нужна ширина: сюда придут таблицы, календарь и списки
       публикаций. Ограничение только сверху, чтобы на мониторе 27"
       строки не растягивались через весь экран. */
    --eto-page-w:     78rem;   /* 1248px */

    /* А поля ввода широкими быть не должны: ширина поля — подсказка о длине
       ввода, и поле на 1100px под имя выглядит так, будто туда ждут абзац.
       Формы ограничиваются отдельно от страницы. */
    --eto-form-w:     30rem;   /* 480px */

    /* ==================================================================
       Перекрытие переменных Bootstrap
       ================================================================== */
    --bs-body-bg:            var(--eto-bg);
    --bs-body-color:         var(--eto-text);
    --bs-body-color-rgb:     20, 33, 27;
    --bs-emphasis-color:     var(--eto-text);
    --bs-secondary-color:    var(--eto-muted);
    --bs-tertiary-bg:        var(--eto-bg);
    --bs-border-color:       var(--eto-border);

    --bs-primary:            var(--eto-accent);
    --bs-primary-rgb:        27, 107, 76;

    --bs-link-color:         var(--eto-accent);
    --bs-link-color-rgb:     27, 107, 76;
    --bs-link-hover-color:   var(--eto-accent-hover);

    --bs-border-radius:      var(--eto-radius);
    --bs-border-radius-sm:   var(--eto-radius-sm);
    --bs-border-radius-lg:   var(--eto-radius-lg);
    --bs-border-radius-xl:   var(--eto-radius-lg);

    --bs-focus-ring-color:   rgba(27, 107, 76, .22);
    --bs-focus-ring-width:   3px;
}

/* ============================================================================
   База
   ========================================================================= */

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
    font-weight: 600;
    /* Системные шрифты в крупных кеглях выглядят разреженно */
    letter-spacing: -.011em;
    color: var(--eto-text);
}

/* Клавиатурная навигация должна быть видна всегда */
:focus-visible {
    outline: 2px solid var(--eto-accent);
    outline-offset: 2px;
}

.eto-text-subtle { color: var(--eto-muted) !important; }

/* ============================================================================
   Кнопки
   Высота 44px, плотный вес, без теней. Разница между уровнями — заливкой,
   а не размером: три одинаковых по форме кнопки читаются как один ряд.
   ========================================================================= */

.btn {
    --bs-btn-padding-y: .625rem;
    --bs-btn-padding-x: 1.125rem;
    --bs-btn-font-weight: 500;
    --bs-btn-border-radius: var(--eto-radius);
    min-height: var(--eto-control-h);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--eto-space-2);
    transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}

.btn-sm {
    --bs-btn-padding-y: .375rem;
    --bs-btn-padding-x: .875rem;
    --bs-btn-font-size: .875rem;
    --bs-btn-border-radius: var(--eto-radius-sm);
    /* 40px. Меньше делать нельзя: в эту кнопку попадают пальцем на телефоне */
    min-height: 2.5rem;
}

.btn-lg {
    --bs-btn-padding-y: .8125rem;
    --bs-btn-padding-x: 1.5rem;
    --bs-btn-font-size: 1rem;
    min-height: 3rem;
}

.btn-primary {
    --bs-btn-bg: var(--eto-accent);
    --bs-btn-border-color: var(--eto-accent);
    --bs-btn-hover-bg: var(--eto-accent-hover);
    --bs-btn-hover-border-color: var(--eto-accent-hover);
    --bs-btn-active-bg: var(--eto-accent-press);
    --bs-btn-active-border-color: var(--eto-accent-press);
    --bs-btn-disabled-bg: var(--eto-accent);
    --bs-btn-disabled-border-color: var(--eto-accent);
}

.btn-outline-primary {
    --bs-btn-color: var(--eto-accent);
    --bs-btn-border-color: var(--eto-accent-border);
    --bs-btn-hover-bg: var(--eto-accent-tint);
    --bs-btn-hover-border-color: var(--eto-accent);
    --bs-btn-hover-color: var(--eto-accent-hover);
    --bs-btn-active-bg: var(--eto-accent-tint);
    --bs-btn-active-border-color: var(--eto-accent);
    --bs-btn-active-color: var(--eto-accent-press);
}

/* Нейтральная кнопка: белая с границей. Используется для «Выйти»,
   «Показать пароль» и прочих действий, не являющихся основными. */
.btn-outline-secondary {
    --bs-btn-color: var(--eto-text);
    --bs-btn-border-color: var(--eto-border-strong);
    --bs-btn-bg: var(--eto-surface);
    --bs-btn-hover-bg: var(--eto-bg);
    --bs-btn-hover-border-color: var(--eto-border-strong);
    --bs-btn-hover-color: var(--eto-text);
    --bs-btn-active-bg: var(--eto-bg);
    --bs-btn-active-border-color: var(--eto-border-strong);
    --bs-btn-active-color: var(--eto-text);
}

.btn:disabled, .btn.disabled { opacity: .5; }

/* ============================================================================
   Поля ввода
   ========================================================================= */

.form-label {
    font-size: .875rem;
    font-weight: 500;
    color: var(--eto-text);
    margin-bottom: var(--eto-space-2);
}

.form-control,
.form-select {
    min-height: var(--eto-control-h);
    padding: .625rem .875rem;
    border-color: var(--eto-border-strong);
    border-radius: var(--eto-radius);
    background-color: var(--eto-surface);
    color: var(--eto-text);
    transition: border-color .12s ease, box-shadow .12s ease;
}

.form-control::placeholder { color: var(--eto-subtle); }

.form-control:focus,
.form-select:focus {
    border-color: var(--eto-accent);
    box-shadow: 0 0 0 3px rgba(27, 107, 76, .15);
}

.form-control:disabled,
.form-control[readonly] {
    background-color: var(--eto-bg);
    color: var(--eto-muted);
    border-color: var(--eto-border);
}

.form-text {
    font-size: .8125rem;
    color: var(--eto-muted);
    margin-top: var(--eto-space-2);
}

.form-control.is-invalid,
.form-select.is-invalid {
    border-color: var(--eto-danger);
    /* Штатная иконка-восклицание внутри поля лишняя: рядом уже есть текст */
    background-image: none;
    padding-right: .875rem;
}

.form-control.is-invalid:focus {
    box-shadow: 0 0 0 3px rgba(179, 38, 30, .15);
}

.invalid-feedback {
    font-size: .8125rem;
    color: var(--eto-danger);
    margin-top: var(--eto-space-2);
}

.form-check-input {
    width: 1.125rem;
    height: 1.125rem;
    margin-top: .125rem;
    border-color: var(--eto-border-strong);
}

.form-check-input:checked {
    background-color: var(--eto-accent);
    border-color: var(--eto-accent);
}

.form-check-input:focus {
    border-color: var(--eto-accent);
    box-shadow: 0 0 0 3px rgba(27, 107, 76, .15);
}

.form-check-label { color: var(--eto-muted); }

/* Кнопка «показать пароль» примыкает к полю и не должна с ним спорить */
.input-group > .btn-outline-secondary {
    border-color: var(--eto-border-strong);
    border-left: 0;
    color: var(--eto-subtle);
}

.input-group > .btn-outline-secondary:hover { color: var(--eto-text); }

.input-group:focus-within > .form-control,
.input-group:focus-within > .btn { border-color: var(--eto-accent); }

.input-group > .form-control:focus { box-shadow: none; }

.input-group:focus-within { border-radius: var(--eto-radius); box-shadow: 0 0 0 3px rgba(27, 107, 76, .15); }

/* ============================================================================
   Карточки
   Граница вместо тени: на светлом фоне тень выглядит грязью, а 1px даёт
   ровно столько разделения, сколько нужно.
   ========================================================================= */

.card {
    --bs-card-bg: var(--eto-surface);
    --bs-card-border-color: var(--eto-border);
    --bs-card-border-radius: var(--eto-radius-lg);
    --bs-card-inner-border-radius: var(--eto-radius);
    --bs-card-spacer-x: var(--eto-space-6);
    --bs-card-spacer-y: var(--eto-space-6);
    box-shadow: none;
}

.card-header {
    background-color: transparent;
    border-bottom: 1px solid var(--eto-border);
    padding: var(--eto-space-5) var(--eto-space-6);
}

/* Отменяем тени Bootstrap, если они остались в разметке */
.shadow, .shadow-sm, .shadow-lg { box-shadow: none !important; }

/* ============================================================================
   Сообщения
   ========================================================================= */

.alert {
    --bs-alert-border-radius: var(--eto-radius);
    padding: var(--eto-space-3) var(--eto-space-4);
    font-size: .9375rem;
    border-width: 1px;
    margin-bottom: var(--eto-space-5);
}

.alert-success {
    --bs-alert-color: var(--eto-accent-press);
    --bs-alert-bg: var(--eto-accent-tint);
    --bs-alert-border-color: var(--eto-accent-border);
}

.alert-danger {
    --bs-alert-color: var(--eto-danger);
    --bs-alert-bg: var(--eto-danger-tint);
    --bs-alert-border-color: #F3CFCB;
}

.alert-warning {
    --bs-alert-color: var(--eto-warning);
    --bs-alert-bg: var(--eto-warning-tint);
    --bs-alert-border-color: #EEDCB4;
}

.toast {
    --bs-toast-border-radius: var(--eto-radius);
    --bs-toast-border-color: var(--eto-border);
    box-shadow: none;
    border: 1px solid var(--eto-border);
}

.toast.text-bg-success {
    background-color: var(--eto-accent) !important;
    color: #fff !important;
    border-color: var(--eto-accent);
}

/* ============================================================================
   Оболочка личного кабинета
   ========================================================================= */

.eto-topbar {
    height: var(--eto-topbar-h);
    background: var(--eto-surface);
    border-bottom: 1px solid var(--eto-border);
    position: sticky;
    top: 0;
    z-index: 1020;
}

.eto-brand {
    grid-area: brand;
    display: inline-flex;
    align-items: center;
    gap: var(--eto-space-2);
    font-weight: 600;
    font-size: 1.0625rem;
    letter-spacing: -.01em;
    color: var(--eto-text);
    text-decoration: none;
}

.eto-brand:hover { color: var(--eto-text); }
.eto-brand .bi { color: var(--eto-accent); font-size: 1.25rem; }

.eto-shell {
    max-width: var(--eto-page-w);
    margin-inline: auto;
    padding: var(--eto-space-6) var(--eto-space-5) var(--eto-space-8);
}

/* Пока идёт проверка сессии, содержимое скрыто: иначе на долю секунды
   мелькает пустой каркас до переброса на /login */
.eto-app-body[data-session="checking"] .eto-shell { visibility: hidden; }

/* --- Меню ----------------------------------------------------------------
   Горизонтальный ряд в шапке. Пункты — таблетки, а не подчёркивания:
   в одной строке с логотипом и пользователем подчёркивание читается
   как случайная линия, а заливка сразу показывает, где вы находитесь. */

.eto-nav {
    grid-area: nav;
    display: flex;
    align-items: center;
    gap: var(--eto-space-1);
    min-width: 0;
    overflow-x: auto;
    /* Полосу прокрутки прячем: пунктов мало, она только шумит */
    scrollbar-width: none;
}

.eto-nav::-webkit-scrollbar { display: none; }

.eto-nav-link {
    display: inline-flex;
    align-items: center;
    gap: var(--eto-space-2);
    padding: var(--eto-space-2) var(--eto-space-4);
    min-height: 2.5rem;
    border-radius: var(--eto-radius);
    color: var(--eto-muted);
    text-decoration: none;
    font-size: .9375rem;
    font-weight: 500;
    white-space: nowrap;
    transition: background-color .12s ease, color .12s ease;
}

.eto-nav-link .bi { font-size: 1.0625rem; }

.eto-nav-link:hover {
    background: var(--eto-accent-tint-2);
    color: var(--eto-text);
}

.eto-nav-link[aria-current="page"] {
    background: var(--eto-accent-tint);
    color: var(--eto-accent);
}

/* Форма живёт в широкой карточке, но сама широкой не становится.
   Отдельного снятия ограничения для телефона не нужно: max-width
   там просто не срабатывает, потому что экран и так уже. */
.eto-form { max-width: var(--eto-form-w); }

/* Кнопка отправки — по содержимому, а не во всю ширину формы */
.eto-form > .btn { align-self: flex-start; }

/* --- Заголовок страницы --- */

.eto-page-head { margin-bottom: var(--eto-space-6); }

.eto-page-head h1 {
    font-size: 1.5rem;
    margin-bottom: var(--eto-space-2);
}

.eto-page-head p {
    color: var(--eto-muted);
    margin-bottom: 0;
}

/* Секции внутри страницы разделяются воздухом, а не линейками */
.eto-sections {
    display: flex;
    flex-direction: column;
    gap: var(--eto-space-5);
}

/* --- Пользователь в шапке --- */

.eto-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: var(--eto-accent-tint);
    color: var(--eto-accent);
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .01em;
}

.eto-user-name {
    font-size: .875rem;
    font-weight: 500;
    line-height: 1.3;
    color: var(--eto-text);
}

.eto-user-email {
    font-size: .8125rem;
    line-height: 1.3;
    color: var(--eto-muted);
}

/* --- Пары «свойство — значение» --- */

.eto-facts {
    display: grid;
    /* Ограничение по ширине: иначе значение уезжает от своей подписи
       через полэкрана и связать их глазом становится трудно */
    max-width: 34rem;
    grid-template-columns: minmax(8rem, auto) minmax(0, 1fr);
    gap: var(--eto-space-3) var(--eto-space-5);
    margin: 0;
    font-size: .9375rem;
}

.eto-facts dt {
    font-weight: 400;
    color: var(--eto-muted);
}

.eto-facts dd {
    margin: 0;
    color: var(--eto-text);
    overflow-wrap: anywhere;
}

/* --- Пустое состояние --- */

.eto-empty {
    text-align: center;
    padding: var(--eto-space-7) var(--eto-space-5);
    color: var(--eto-muted);
}

.eto-empty .bi {
    font-size: 1.75rem;
    color: var(--eto-subtle);
    margin-bottom: var(--eto-space-4);
    display: block;
}

.eto-empty p { margin-bottom: var(--eto-space-1); }
.eto-empty p:last-child { margin-bottom: 0; font-size: .875rem; color: var(--eto-muted); }

/* --- Список активных входов --- */

.eto-session {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--eto-space-4);
    padding: var(--eto-space-4) 0;
    border-bottom: 1px solid var(--eto-border);
    font-size: .875rem;
}

/* Левая колонка должна СЖИМАТЬСЯ. Без min-width: 0 флекс-элемент
   не уменьшается ниже ширины содержимого, и длинный User-Agent
   растягивает строку далеко за экран вместо обрезания многоточием. */
.eto-session > :first-child { flex: 1 1 auto; min-width: 0; }

.eto-session:last-child { border-bottom: 0; padding-bottom: 0; }
.eto-session:first-child { padding-top: 0; }
.eto-session-ip { font-weight: 500; color: var(--eto-text); }
.eto-session-when { color: var(--eto-muted); white-space: nowrap; font-size: .8125rem; }
.eto-session-agent {
    color: var(--eto-muted);
    font-size: .8125rem;
    margin-top: var(--eto-space-1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ============================================================================
   Вход, регистрация, заглушка
   ========================================================================= */

.eto-auth-wrap {
    min-height: 100vh;
    min-height: 100dvh;   /* на мобильных исключает панель браузера */
    display: grid;
    place-items: center;
    padding: var(--eto-space-6) var(--eto-space-4);
}

.eto-auth-card {
    width: 100%;
    max-width: 24rem;
}

.eto-auth-card .card { --bs-card-spacer-x: var(--eto-space-6); }

.eto-auth-title {
    font-size: 1.25rem;
    margin-bottom: var(--eto-space-1);
}

.eto-auth-sub {
    font-size: .9375rem;
    color: var(--eto-muted);
    margin-bottom: var(--eto-space-6);
}

/* Сетка вместо флекса: на узком экране меню должно уехать на вторую строку
   ЦЕЛИКОМ, а пользователь остаться рядом с логотипом. Флекс с переносом дал бы
   обратное — «логотип + меню» в первой строке, а пользователя во вторую. */
.eto-topbar-inner {
    height: 100%;
    max-width: var(--eto-page-w);
    margin-inline: auto;
    padding-inline: var(--eto-space-5);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "brand nav user";
    align-items: center;
    column-gap: var(--eto-space-6);
}

.eto-topbar-user {
    grid-area: user;
    display: flex;
    align-items: center;
    gap: var(--eto-space-4);
    min-width: 0;
}

.eto-topbar-user > div { min-width: 0; }
.eto-user-name, .eto-user-email { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Без этого длинный User-Agent распирает флекс-строку и обрезание не работает */
.min-w-0 { min-width: 0; }

/* Ссылка-приписка под заглушкой: отделена воздухом, а не линией */
.eto-auth-aside {
    margin-top: var(--eto-space-8);
    margin-bottom: 0;
}

/* Код ошибки: крупный, но приглушённый — это не заголовок страницы,
   а пояснение к нему */
.eto-error-code {
    font-size: 2.5rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--eto-subtle);
    margin-bottom: var(--eto-space-4);
}

/* ============================================================================
   Раскладка страниц кабинета

   Кабинет широкий, поэтому на большом экране разделы встают в два столбца.
   Одна колонка карточек на 1248px оставляла бы половину экрана пустой.
   ========================================================================= */

.eto-grid-2 {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--eto-space-5);
    align-items: start;
}

/* Внутри столбца разделы идут друг под другом */
.eto-col {
    display: flex;
    flex-direction: column;
    gap: var(--eto-space-5);
}

@media (min-width: 62em) {
    .eto-grid-2 {
        /* Левый столбец шире: там формы, справа — короткие блоки */
        grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
        gap: var(--eto-space-5);
    }

    /* В два столбца карточка уже сама достаточно узкая — форма заполняет её
       целиком. Отдельное ограничение в 480px оставляло бы пустоту справа
       и карточка выглядела бы недоделанной. Ограничение работает там,
       где столбец один и карточка растянута на всю страницу. */
    .eto-grid-2 .eto-form { max-width: none; }
}

/* ============================================================================
   Адаптив

   Два состояния, одна точка перестроения:
     ≥ 992px  меню в одной строке с логотипом, разделы в два столбца
     < 992px  меню на второй строке шапки (по-прежнему горизонтальное),
              разделы в один столбец, форма во всю ширину карточки
   ========================================================================= */

@media (max-width: 61.99em) {
    .eto-shell { padding: var(--eto-space-5) var(--eto-space-4) var(--eto-space-7); }
    .card { --bs-card-spacer-x: var(--eto-space-5); --bs-card-spacer-y: var(--eto-space-5); }
    .eto-page-head h1 { font-size: 1.375rem; }
}

@media (max-width: 61.99em) {
    /* Логотип, меню, имя с почтой и кнопка выхода в одну строку уже
       не помещаются: до этой правки меню обрезалось об аватар на 900px.
       Меню опускается вниз ЦЕЛИКОМ и остаётся горизонтальным — бургер
       ради двух пунктов добавил бы лишний шаг.
       Порог совпадает с переходом разделов в один столбец: одна точка
       перестроения вместо двух близких. */
    .eto-topbar { height: auto; }

    .eto-topbar-inner {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "brand user"
            "nav   nav";
        row-gap: var(--eto-space-2);
        padding-block: var(--eto-space-3);
    }

    .eto-nav { padding-bottom: var(--eto-space-1); }
    .eto-nav-link { padding-inline: var(--eto-space-3); }
}

@media (max-width: 35.99em) {
    /* E-mail в шапке съедает всю строку — оставляем имя */
    .eto-user-email { display: none; }

    .eto-facts { grid-template-columns: minmax(0, 1fr); gap: var(--eto-space-1); }
    .eto-facts dd { margin-bottom: var(--eto-space-3); }
    .eto-facts dd:last-child { margin-bottom: 0; }

    /* align-items: stretch, а не flex-start: при flex-start колонка
       принимает ширину содержимого, и обрезание по ширине не работает */
    .eto-session { flex-direction: column; align-items: stretch; gap: var(--eto-space-1); }
    .eto-session > :first-child { width: 100%; }
}

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

/* ============================================================================
   Проекты
   ========================================================================= */

/* Заголовок страницы с действием справа */
.eto-page-head--action {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--eto-space-4);
    flex-wrap: wrap;
}

.eto-projects {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: var(--eto-space-4);
}

/* Карточка проекта — ссылка целиком: попасть по ней проще, чем
   выцеливать заголовок, и не нужен отдельный элемент «открыть» */
.eto-project {
    display: flex;
    flex-direction: column;
    gap: var(--eto-space-3);
    padding: var(--eto-space-5);
    background: var(--eto-surface);
    border: 1px solid var(--eto-border);
    border-radius: var(--eto-radius-lg);
    text-decoration: none;
    color: inherit;
    min-height: 9.5rem;
    transition: border-color .12s ease, background-color .12s ease;
}

.eto-project:hover {
    border-color: var(--eto-accent-border);
    background: var(--eto-accent-tint-2);
    color: inherit;
}

.eto-project-top {
    display: flex;
    align-items: center;
    gap: var(--eto-space-3);
    min-width: 0;
}

/* Метка проекта: первая буква названия на подложке. Оттенок выводится
   из идентификатора, а не выбирается человеком, — это лишнее поле в форме,
   а различать проекты в сетке всё равно нужно. Когда появятся карусели,
   плитка станет превью первого слайда. Цвета ставит JS: CSP запрещает
   атрибут style, а классы под каждый оттенок ограничили бы палитру. */
.eto-project-dot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: var(--eto-radius-sm);
    flex-shrink: 0;
    font-size: .875rem;
    font-weight: 600;
    text-transform: uppercase;
    background: var(--eto-accent-tint);
    color: var(--eto-accent);
}

.eto-project-name {
    font-weight: 600;
    font-size: 1rem;
    color: var(--eto-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.eto-project-desc {
    font-size: .875rem;
    color: var(--eto-muted);
    margin: 0;
    flex-grow: 1;
    /* Две строки максимум: карточки в сетке должны быть одной высоты */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.eto-project-meta {
    font-size: .8125rem;
    color: var(--eto-muted);
}

/* --- Шапка страницы проекта --- */

.eto-project-head {
    display: flex;
    align-items: flex-start;
    gap: var(--eto-space-4);
    flex-wrap: wrap;
    margin-bottom: var(--eto-space-6);
}

.eto-project-head .eto-project-dot {
    width: 3rem;
    height: 3rem;
    border-radius: var(--eto-radius);
    font-size: 1.25rem;
}

.eto-project-head-text { flex-grow: 1; min-width: 12rem; }

.eto-project-head h1 {
    font-size: 1.5rem;
    margin-bottom: var(--eto-space-2);
    overflow-wrap: anywhere;
}

.eto-project-head p {
    color: var(--eto-muted);
    margin-bottom: 0;
    overflow-wrap: anywhere;
}

/* --- Модальные окна --- */

.modal-content {
    border: 1px solid var(--eto-border);
    border-radius: var(--eto-radius-lg);
}

.modal-header, .modal-footer {
    border-color: var(--eto-border);
    padding: var(--eto-space-5) var(--eto-space-6);
}

.modal-body { padding: var(--eto-space-6); }
.modal-title { font-size: 1.0625rem; font-weight: 600; }

@media (max-width: 35.99em) {
    .eto-projects { grid-template-columns: minmax(0, 1fr); }
    .eto-page-head--action > .btn { width: 100%; }
}

/* Кнопка удаления: красная заливка из нашей палитры, а не бутстраповская */
.btn-danger {
    --bs-btn-bg: var(--eto-danger);
    --bs-btn-border-color: var(--eto-danger);
    --bs-btn-hover-bg: #92201A;
    --bs-btn-hover-border-color: #92201A;
    --bs-btn-active-bg: #7A1B16;
    --bs-btn-active-border-color: #7A1B16;
}

.btn-outline-danger {
    --bs-btn-color: var(--eto-danger);
    --bs-btn-border-color: #F0CDCA;
    --bs-btn-hover-bg: var(--eto-danger-tint);
    --bs-btn-hover-border-color: var(--eto-danger);
    --bs-btn-hover-color: var(--eto-danger);
    --bs-btn-active-bg: var(--eto-danger-tint);
    --bs-btn-active-border-color: var(--eto-danger);
    --bs-btn-active-color: var(--eto-danger);
}

.eto-project-dot-lg {
    width: 3rem;
    height: 3rem;
    border-radius: var(--eto-radius);
    font-size: 1.25rem;
}
