
/* ==== css/core.css ==== */
/* ============================
   CORE.CSS
   Глобальные переменные + база
   ============================ */

/* ====== Бренд-шрифты (само-хостинг, woff2, latin+cyrillic) ======
   Manrope — весь UI; веса под реальный font-weight в разметке (400/500/600/700/800).
   Geist Mono — акцентные тех-подписи (версия, реф-ссылка). font-display:swap —
   первый рендер не блокируется, текст рисуется системным и подменяется без FOIT. */
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/static/fonts/manrope-400.woff2") format("woff2");
}
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/static/fonts/manrope-500.woff2") format("woff2");
}
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/static/fonts/manrope-600.woff2") format("woff2");
}
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/static/fonts/manrope-700.woff2") format("woff2");
}
@font-face {
    font-family: "Manrope";
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url("/static/fonts/manrope-800.woff2") format("woff2");
}
@font-face {
    font-family: "Geist Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/static/fonts/geist-mono-400.woff2") format("woff2");
}

/* ====== Телеграм ТЕМА ====== */
:root {
    /* Светлая тема ЯВНО: meta color-scheme разрешает обе, и при тёмной ОС браузер
       иначе отрисовал бы нативные контролы (поля, скроллбары, автозаполнение)
       тёмными поверх нашей светлой вёрстки. Тёмная тема ставит dark сама. */
    color-scheme: light;

    /* Brand palette */
    --brand-olive:  #5B7A39;
    --brand-olive-dark: #4A6630;
    --brand-silver: #B8B8B8;
    --brand-red:    #E32A20;
    --brand-gray:   #D8D8D8;
    --brand-ivory:  #E4E3DF;
    --brand-black:  #191919;
    --brand-white:  #FFFFFF;
    /* Лёгкая заливка полей ввода — очень светлый нейтральный тон на базе ivory,
       чтобы поле «читалось» на белой карточке, не споря с оливковыми акцентами */
    --input-bg:     #F3F2EE;

    /* Типографика: Manrope — весь UI, Geist Mono — акцентные тех-подписи. Системный
       хвост — фолбэк на время swap и для отсутствующих глифов (напр. ₽ нет в Manrope). */
    --font:      "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

    /* ====== СЕМАНТИЧЕСКИЙ СЛОЙ (роли) — единственное, что переопределяет тема ======
       Компоненты должны обращаться СЮДА, а не к сырым --brand-*. Light-значения
       равны прежним: внешний вид светлой темы не меняется. Dark-набор — в конце
       файла, под html[data-theme="dark"]. */

    /* Поверхности: 1 — фон страницы, 2 — карточка, 3 — модалки/шиты/поповеры. */
    --surface-1: var(--brand-ivory);
    --surface-2: var(--brand-white);
    --surface-3: var(--brand-white);

    /* Текст: primary — основной, secondary — подписи/хинты, muted — самый тихий,
       on-accent — текст поверх заливок (олива/статусы), НЕ равен surface. */
    --text-primary:   var(--brand-black);
    --text-secondary: #7A7A72;
    --text-muted:     #9A9A92;
    --on-accent:      #FFFFFF;

    /* Границы */
    --border-subtle: var(--brand-gray);
    --border-strong: var(--brand-silver);

    /* Границы полей ввода/кнопок-пилюль — свой сине-серый оттенок (НЕ --border-subtle:
       там нейтральный серый). Две ступени = две альфы, что стоят в вёрстке. */
    /* ТРИПЛЕТЫ под полупрозрачные подмешки: каждое место держит СВОЮ альфу, а тема
       меняет только базовый цвет. Иначе тёмная тема получала бы чёрное на чёрном
       (тинты) и невидимые границы. Скримы/тени НЕ отсюда — они тёмные в обеих темах. */
    --tint-rgb:         0, 0, 0;
    --border-field-rgb: 148, 163, 184;

    --border-field:        rgba(var(--border-field-rgb), 0.45);
    --border-field-strong: rgba(var(--border-field-rgb), 0.5);

    /* Акцент триплетом — для полупрозрачных оливковых заливок/границ: rgba(var(...), a)
       сериализуется точь-в-точь как прежние литералы (color-mix даёт color(srgb …)
       и не поддерживается старыми WebKit). */
    --accent-rgb: 91, 122, 57;

    /* Нейтральные тинты поверх поверхности (пузырь чата собеседника, разделитель
       дат). На светлой — подмешка чёрного, на тёмной — белого: иначе на тёмном фоне
       чёрный тинт превращается в невидимый. */
    --tint-neutral:      rgba(var(--tint-rgb), 0.07);
    --tint-neutral-weak: rgba(var(--tint-rgb), 0.05);

    /* ИНВЕРСНАЯ поверхность — тост: тёмная пилюля на светлой теме и наоборот.
       Это НЕ --surface-3: тост намеренно контрастен фону, поэтому в тёмной теме
       он светлеет, а текст на нём темнеет. */
    --surface-inverse:  var(--brand-black);
    --text-on-inverse:  var(--brand-white);

    /* Слои: затемнение под шитами/меню/лайтбоксом */
    --overlay: rgba(0, 0, 0, 0.5);

    /* Валюта — единый токен листа (сейчас дублируется хардкодом в .gs-leaf и app.html;
       перевод потребителей на токен — Фаза 1/2). */
    --leaf: #6B8E23;

    /* Оливковый ТЕКСТ (подзаголовки статей): на тёмном фоне #41521f нечитаем. */
    --text-accent: #41521f;

    /* Semantic tokens — ЛЕГАСИ-ИМЕНА, оставлены алиасами на роли выше: всё, что уже
       использует --tg-*, флипается в тёмной теме автоматически. Новый код — роли. */
    --tg-bg:           var(--surface-1);
    --tg-text:         var(--text-primary);
    --tg-hint:         var(--text-secondary);
    --tg-secondary-bg: var(--surface-2);

    /* Brand / UI */
    --accent:      var(--brand-olive);
    --accent-dark: var(--brand-olive-dark);
    --danger:      var(--brand-red);
    --border:      var(--brand-gray);
    --silver:      var(--brand-silver);

    /* Семантические цвета статусов (бейджи растений/сделок, прогресс сделки).
       Значения зафиксированы — менять цвет статуса только здесь. */
    /* Приглушённая статус-палитра: не спорит с оливой бренда. Красный — единственный
       яркий маркер (отклонено/ошибка), поэтому идёт из палитры (--brand-red). */
    --status-pending:  #7D6036;  /* охра — на модерации / ожидание */
    --status-reserved: #3D648F;  /* синий — в брони */
    --status-approved: #347946;  /* зелёный — опубликовано / завершено */
    --status-rejected: var(--brand-red);  /* бренд-красный маркер — отклонено */
    --status-purple:   #7947A6;  /* фиолетовый — старт сделки (создана) */

    /* СВЕТЛЫЕ ПАРЫ цветного ТЕКСТА статусов: сам --status-* рассчитан как ЗАЛИВКА
       (белый текст поверх). Как текст НА поверхности он в тёмной теме проваливается
       по контрасту, поэтому у баннеров своя, осветлённая версия того же оттенка.
       Light-значения РАВНЫ --status-*, поэтому светлая тема не меняется. */
    --status-pending-text:  var(--status-pending);
    --status-approved-text: var(--status-approved);
    --status-rejected-text: var(--status-rejected);
    --status-purple-text:   var(--status-purple);

    /* Тинт-подложки баннеров — вынесены в токены, чтобы в тёмной теме поднять альфу
       (при низкой альфе оттенок на тёмном фоне не читается). */
    --banner-warn-bg:   rgba(241, 196, 15, 0.15);
    --banner-ok-bg:     rgba(91, 122, 57, 0.12);
    --banner-error-bg:  rgba(227, 42, 32, 0.08);
    --banner-purple-bg: rgba(121, 71, 166, 0.08);

    /* Цвета баннеров владельца растения (.pf-info-banner--*, .ps-owner-banner) */
    --banner-warn:        #c09020;  /* кнопка предупреждающего баннера */
    --banner-warn-text:   #7a6000;  /* текст предупреждающего баннера */
    --banner-warn-accent: #f1c40f;  /* акцентная полоса предупреждения */
    --banner-ok:          #1e7a47;  /* кнопка успешного баннера */
    --banner-purple:      #7947A6;  /* кнопка/полоса фиолетового баннера (= --status-purple) */
    --banner-purple-text: #6c3483;  /* текст фиолетового баннера */
    --banner-frame:        #B3B3B3;  /* серая рамка статус-баннера (темнее --brand-gray), общая для всех статусов */
    --banner-frame-strong: #8C8C8C;  /* полоса статуса черновика (neutral) — темнее рамки, как акцент */

    /* Shapes */
    --radius-xl:   24px;
    --radius-lg:   20px;
    --radius-md:   14px;
    --radius-sm:   12px;
    --radius-xs:   10px;
    --radius-pill: 999px;

    /* Effects */
    --shadow-soft:  0 2px 6px rgba(0, 0, 0, 0.07);
    --shadow-card:  0 2px 8px rgba(0, 0, 0, 0.08);
    --card-border:  1px solid rgba(0, 0, 0, 0.07);
    --shadow-olive: none;
    --shadow-chip:    0 1px 4px rgba(0, 0, 0, 0.2);    /* мелкие бейджи-кружки (аватар) */
    --shadow-popover: 0 4px 16px rgba(0, 0, 0, 0.12);  /* выпадашки подсказок */
    --shadow-up:    0 -8px 24px rgba(15, 23, 42, 0.22);

    --scroll-end-gap: 20px;   /* отступ от последнего элемента до нижней навигации */

    /* Клиренс нижнего бара под home-indicator (по режиму). Единый источник и для
       padding-bottom самого .bottom-nav, и для нижнего резерва .page-inner под нав —
       чтобы высота бара и резерв контента совпадали. Браузер/Safari: 0 (fixed;bottom:0
       сам над панелью). Standalone-переопределение — ниже, после :root. */
    --nav-clearance: 0px;

    --transition-fast: 0.15s ease-out;

    --fab-enter-duration: 250ms;
    --fab-enter-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
    /* высота «контента» шапки, без челки (резерв под fixed .topbar-container).
       Синхронно с .topbar padding: снижен 101→91 после сжатия шапки на 10px. */
    --app-header-content-height: 91px;

    --app-header-height: calc(
        env(safe-area-inset-top, 0px) + var(--app-header-content-height)
    );
}

/* ====== ТЁМНАЯ ТЕМА — переопределение РОЛЕЙ ======
   Тема ставится атрибутом html[data-theme] (инлайн-скрипт в <head> app.html, до
   первого кадра — против FOUC). Переключателя в UI пока нет: для превью —
   document.documentElement.dataset.theme = 'dark'.
   Сырые --brand-* НЕ переопределяем (их потребители мигрируют на роли в Фазе 1),
   статусы и --banner-* тоже пока светлые — отдельным шагом. */
html[data-theme="dark"] {
    color-scheme: dark;   /* нативные контролы/скроллбары/автозаполнение — тёмные */

    --surface-1: #1A1A18;
    --surface-2: #232320;
    --surface-3: #2B2B27;

    --text-primary:   #ECEBE6;
    --text-secondary: #9C9B92;
    --text-muted:     #6E6E66;
    --on-accent:      #FFFFFF;

    --border-subtle: rgba(255, 255, 255, 0.12);
    --border-strong: rgba(255, 255, 255, 0.20);

    --border-field:        rgba(var(--border-field-rgb), 0.14);
    --border-field-strong: rgba(var(--border-field-rgb), 0.18);

    --tint-rgb:         255, 255, 255;
    --border-field-rgb: 255, 255, 255;

    --tint-neutral:      rgba(var(--tint-rgb), 0.10);
    --tint-neutral-weak: rgba(var(--tint-rgb), 0.07);

    --text-accent: #8FB35E;

    /* Баннеры: осветлённый ТЕКСТ статуса того же оттенка + более плотный тинт-фон,
       чтобы цвет узнавался на тёмной поверхности. */
    --status-pending-text:  #D9A85A;   /* охра */
    --status-approved-text: #7FC48F;   /* зелёный */
    --status-rejected-text: #FF7A70;   /* красный */
    --status-purple-text:   #C9A3E8;   /* фиолетовый */

    --banner-warn-bg:   rgba(241, 196, 15, 0.22);
    --banner-ok-bg:     rgba(91, 122, 57, 0.22);
    --banner-error-bg:  rgba(227, 42, 32, 0.18);
    --banner-purple-bg: rgba(121, 71, 166, 0.20);

    --banner-warn-text:   #E8C766;
    --banner-purple-text: #C9A3E8;
    --banner-warn-accent: #F1C40F;
    --banner-ok:          #7FC48F;
    --banner-purple:      #C9A3E8;

    --banner-frame:        rgba(255, 255, 255, 0.28);
    --banner-frame-strong: rgba(255, 255, 255, 0.45);

    --shadow-chip:    0 1px 4px rgba(0, 0, 0, 0.55);
    --shadow-popover: 0 6px 20px rgba(0, 0, 0, 0.6);

    --surface-inverse: #ECEBE6;
    --text-on-inverse: #1A1A18;

    /* Заливка полей/скелетонов: светлый #F3F2EE в тёмной теме «горел» бы. */
    --input-bg: #2E2E2A;

    --overlay: rgba(0, 0, 0, 0.62);

    --leaf: #7BA02B;

    /* Тени на тёмном фоне должны быть глубже, иначе не читаются. */
    --shadow-soft: 0 2px 6px rgba(0, 0, 0, 0.5);
    --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.55);
    --shadow-up:   0 -8px 24px rgba(0, 0, 0, 0.6);
    --card-border: 1px solid rgba(255, 255, 255, 0.10);
}

/* Standalone (иконка на «Домой»): клиренс под home-indicator, подтянутый на ~22px
   (минимум 4px). -22px/4px подбираются на устройстве (подписи не касаются индикатора). */
@media (display-mode: standalone) {
    :root { --nav-clearance: max(4px, calc(env(safe-area-inset-bottom, 0px) - 22px)); }
}


/* =================== RESET =================== */

*, *::before, *::after {
    box-sizing: border-box;
}

html, body {
    height: 100%;
    /* Документ ЗАЛОЧЕН: overflow:hidden (не только -x) — иначе overflow-y вычислялся
       в auto (overflow-x:hidden + overflow-y:visible → auto), и html/body становились
       живым скролл-контейнером, который на iOS перехватывал нативный focus-scroll
       (поле улетало на ~высоту клавиатуры). Единственные скроллеры — внутренние
       .tab--active / #psScrollArea (ни один экран не зависит от document/window-скролла). */
    overflow: hidden;
}
/* Против рабербенда всего документа (жест у краёв внутренних скроллеров не
   «проваливается» в системный bounce окна). */
body {
    overscroll-behavior: none;
}

/* Скрываем скроллбар браузера — Telegram WebApp его не использует,
   на десктопе он создаёт асимметрию при margin: 0 auto */
html {
    scrollbar-width: none; /* Firefox */
}
html::-webkit-scrollbar {
    display: none; /* Chrome, Safari */
}

body {
    margin: 0;
    padding: 0;
    height: 100%;

    font-family: var(--font);   /* Manrope, наследуется в input/button/textarea (там inherit) */

    background: var(--tg-bg);
    color: var(--tg-text);

    -webkit-tap-highlight-color: transparent;
}

/* Form-элементы не наследуют font автоматически в браузерах */
input, button, textarea, select {
    font-family: inherit;
}

/* Курсор ввода — оливковый (белый дефолтный не виден на белом фоне полей) */
input, textarea {
    caret-color: var(--accent);
}

/* Telegram topbar takes space — add padding */

body.page {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding-top: 0;
}

/* Контейнер для страничного контента */

.page-inner {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;

    width: 100%;
    max-width: 480px;
    margin: 0 auto;

    /* Горизонтальный инсет 12px перенесён на ВНУТРЕННИЙ контент скроллеров (не на
       page-inner и не на сам скроллер) — чтобы полоса прокрутки была у края экрана.
       Здесь только вертикальные отступы: сверху высота шапки, снизу под нижнюю навигацию. */
    padding: var(--app-header-height) 0 calc(51px + var(--nav-clearance));
    min-height: 0;
}


/* Клавиатура открыта → нав скрыт (body.gs-kb-open), 51px-резерв под нав лишний —
   снимаем, чтобы контент (в т.ч. композер чата в потоке) вставал вплотную над
   клавиатурой без пустого зазора. Экран сделки при ЗАКРЫТОЙ клавиатуре использует
   базовый 51px-резерв: композер стоит НАД навом (нав виден). */
body.gs-kb-open .page-inner {
    /* Клавиатура открыта → home-индикатора нет → safe-area снизу не нужна (иначе зазор). */
    padding-bottom: 6px;
}

/* Клавиатура открыта на экране сделки: пиннингуем .page-inner к ВИДИМОЙ области.
   position:fixed; top:0 — верх видимой области; ВЫСОТУ задаёт ТОЛЬКО JS
   (.page-inner.style.height = visualViewport.height + "px", одна запись, без чтений).
   CSS-height НЕ ставим (height:100% фиксед-элемента конфликтовал с flex-цепочкой →
   .deal-page схлопывалась). Fixed-контейнер с реальной px-высотой → flex-цепочка
   (#appMain → #tab-deal-detail → .deal-page → .chat-messages flex:1) заполняет,
   композер уходит В НИЗ. Шапка (.topbar-container, сама fixed — вне flow) скрыта,
   резерв под неё снят (padding-top:8px). */
body.gs-kb-open.page--deal-detail-active .page-inner {
    position: fixed;
    /* top НЕ ставим здесь: fixed анкорится к layout-верху, а видимая область смещена
       на visualViewport.offsetTop → JS выставляет top=offsetTop (иначе контент уезжает
       вверх на offsetTop, замер rect.top=−413). */
    left: 0;
    right: 0;
    z-index: 20;
    padding-top: 4px;   /* чат чуть выше (по просьбе); скруглённый верх остаётся виден */
}
body.gs-kb-open.page--deal-detail-active .topbar-container {
    display: none;
}
/* Клавиатура открыта на сделке → залочить скролл документа: страница не скроллится/не
   дрожит/не рубер-бэндит, единственный скроллер — лента чата (.chat-messages). */
body.gs-kb-open.page--deal-detail-active {
    overflow: hidden;
    overscroll-behavior: none;
    touch-action: none;
}

/* Растение: резерв под нав (51px) в .page-inner НЕ снимаем — нав видна на экране
   растения, #psActions стоит НАД навом (bottom:0 у #screen-plant = верх нава).
   Прежний :has()-override (снимал резерв ради «бар у самого низа») убран вместе со
   скрытием нава. */
/* Вкладки */

.tab {
    display: none;
    width: 100%;
}

.tab--active {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Сделка управляет своим скроллингом сама (чат внутри) */
#tab-deal-detail.tab--active {
    overflow: hidden;
}

/* Утилита для скрытия */

.hidden {
    display: none !important;
}

/* ============================
   ВЕРХНЯЯ ПАНЕЛЬ ВИТРИНЫ
   ============================ */

.feed-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0 2px;
    margin-bottom: 0;

    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--surface-1);
}

/* Мягкое растворение контента под залипшей строкой (Стол/Сделки/Профиль):
   градиент в фон страницы, тапы не перехватывает. sticky даёт containing block. */
.feed-toolbar::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 8px;
    background: linear-gradient(to bottom, var(--tg-bg), transparent);
    pointer-events: none;
}

.feed-toolbar__search {
    flex: 1 1 auto;
    min-width: 0;
}

/* Обёртка-бокс поля поиска несёт ВЕСЬ визуал (рамка/фон/pill/высота/паддинг) и
   центрирует инпут через flex. Сам <input> внутри = высота line box, каретка = вся
   высота инпута → ей некуда съезжать при рефлоу вьюпорта (открытие клавиатуры на iOS).
   Значения = как были у .feed-search-input, чтобы вид не изменился. Класс навешен на
   существующие обёртки (.feed-toolbar__search / .admin-search-wrap). */
.search-box {
    display: flex;
    align-items: center;
    box-sizing: border-box;
    height: 31px;               /* = высота .feed-btn (Фильтр/Сортировка); border-box → с бордерами */
    padding: 0 12px;
    border: 1px solid var(--border-field);
    border-radius: var(--radius-pill);
    background: var(--tg-secondary-bg);
    /* iOS scroll-into-view при фокусе не заводит поле под залипшую шапку */
    scroll-margin-top: var(--app-header-height);
    /* Локальная система координат каретки: обёртка = containing block, и iOS Safari
       считает caret-rect относительно неё, а не вложенного скролл-предка (глубина
       обёрток у стола/профиля/сделок разная → каретка «ехала» по-разному). */
    transform: translateZ(0);
    transition:
        border-color 0.15s ease-out,
        box-shadow 0.15s ease-out,
        background-color 0.15s ease-out;
}

.search-box:focus-within {
    border-color: var(--accent);
    background: var(--surface-2);
    box-shadow:
        0 0 0 1px rgba(91, 122, 57, 0.18),
        0 4px 10px rgba(15, 23, 42, 0.12);
}

/* iOS caret-fix: локальный containing block. КРИТИЧНО — translateZ ДОЛЖЕН быть на
   ОБЁРТКЕ поля (родителе инпута), НЕ на самом инпуте: transform на инпуте не создаёт
   промежуточный CB для его СОБСТВЕННОЙ каретки, и iOS считает офсет относительно
   скролл-предка (особенно с -webkit-overflow-scrolling:touch). Рабочий эталон — .search-box
   (обёртка), инпут — ребёнок.
   Заход 1 (fixed-контекст, подтверждён на устройстве — оставлены как есть): чат
   (.chat-input-bar — обёртка композера), GsSheet (.gs-sheet-input/textarea), авторизация
   (.auth-input/.auth-code-input). Заход 2/3 (скролл + overflow-scrolling) — translateZ
   ПЕРЕНЕСЁН с инпутов на ОБЁРТКИ: растение название (.plant-detail-title-row), описание
   (.plant-detail-desc-block), пикер города (.lp-wrap — во всех хостах: растение/онбординг/
   профиль-edit), онбординг имя/био (.auth-field__wrap), профиль-edit имя/био (.pe-field-group). */
.gs-caret-fix,
.chat-input-bar,
.gs-sheet-input,
.gs-sheet-textarea,
.auth-input,
.auth-code-input,
.plant-detail-title-row,
.plant-detail-desc-block,
.lp-wrap,
.auth-field__wrap,
.pe-field-group {
    transform: translateZ(0);
}

/* Инпут раздет до текста: весь бокс — на .search-box. Высота = line box → каретка
   стабильна при открытии клавиатуры (нет вертикального padding/height внутри инпута). */
.feed-search-input {
    flex: 1;
    width: 100%;
    min-width: 0;
    margin: 0;
    padding: 0;
    height: auto;
    border: none;
    background: transparent;
    outline: none;
    font-size: 14px;
    line-height: revert;        /* сброс к UA-стилю Safari для инпута — выравнивает каретку/плейсхолдер там, где normal/1 не помогали (Adam Cap) */
    color: var(--tg-text);
    -webkit-appearance: none;
    appearance: none;

    /* Длинный плейсхолдер троеточится «…», а не режется по краю (узкий мобильный) */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* iOS применяет ellipsis именно к ::placeholder, не к самому input */
.feed-search-input::placeholder {
    color: var(--tg-hint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.feed-toolbar__actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

/* Кнопки фильтра/сортировки и кнопки в модалках */

.feed-btn {
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-field-strong);
    background: var(--tg-secondary-bg);
    color: var(--tg-text);

    padding: 7px 10px;
    font-size: 13px;
    font-weight: 500;

    cursor: pointer;
    white-space: nowrap;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;

    transition:
        background-color 0.12s ease-out,
        box-shadow 0.12s ease-out,
        transform 0.12s ease-out,
        border-color 0.12s ease-out;
}

.feed-btn:active {
    transform: translateY(1px);
    box-shadow: 0 3px 6px rgba(15, 23, 42, 0.12);
}

.feed-btn--primary {
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    border-color: transparent;
    color: var(--on-accent);
}

.feed-btn--secondary {
    background: var(--tg-secondary-bg);
    color: var(--tg-text);
}

.feed-btn--active,
.feed-btn.active {
    background: var(--accent);
    border-color: transparent;
    color: var(--on-accent);
}

/* ============================
   МОДАЛКИ ФИЛЬТРА И СОРТИРОВКИ
   ============================ */

.feed-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    z-index: 1100;
}

.feed-modal {
    width: 100%;
    max-width: 480px;

    background: var(--tg-bg);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-up);

    padding: 12px 12px calc(62px + env(safe-area-inset-bottom, 0px) + 8px);

    animation: feed-modal-slide-up 0.18s ease-out;
}

@keyframes feed-modal-slide-up {
    from {
        transform: translateY(16px);
        opacity: 0;
    }
    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.feed-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;

    margin-bottom: 8px;
}

.feed-modal__header span {
    font-size: 17px;
    font-weight: 600;
}

.feed-modal__close {
    border: none;
    background: transparent;
    color: var(--tg-hint);
    font-size: 20px;
    cursor: pointer;
    padding: 4px;
}

.feed-modal__body {
    padding: 6px 2px 10px;
    max-height: 60vh;
    overflow-y: auto;
}

.feed-modal__footer {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    margin-top: 6px;
}

.feed-modal__footer .feed-btn {
    flex: 1;
    padding: 12px 16px;
    min-height: 48px;
}

/* Секции внутри фильтра */

.feed-filter-section {
    margin-bottom: 14px;
    font-size: 15px;
}

.feed-filter-section__title {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 8px;
    color: var(--tg-hint);
}

.feed-filter-section label {
    font-size: 15px;
    color: var(--tg-text);
}

/* две секции рядом: Тип слева, Способ передачи справа */
.feed-filter-two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 12px;
    margin-bottom: 12px;
}

.feed-filter-two-col .feed-filter-section {
    margin-bottom: 0;
}

/* touch-friendly метка чекбокса */
.feed-filter-item {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    font-size: 15px;
    color: var(--tg-text);
    cursor: pointer;
}

/* ряд для "От / До" листочков — кнопки-пилюли */

.feed-leaf-range {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    gap: 20px;
}

.feed-leaf-range__row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.feed-leaf-range__label {
    font-size: 13px;
    color: var(--tg-hint);
    flex-shrink: 0;
}

.feed-leaf-stepper {
    display: inline-flex;
    align-items: center;
    border: 1.5px solid rgba(var(--border-field-rgb), 0.45);
    border-radius: var(--radius-pill);
    overflow: hidden;
    background: var(--tg-secondary-bg);
}

.feed-leaf-stepper__btn {
    width: 44px;
    height: 44px;
    font-size: 22px;
    line-height: 1;
    border: none;
    background: transparent;
    color: var(--tg-text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.feed-leaf-stepper__val {
    min-width: 32px;
    text-align: center;
    font-size: 17px;
    font-weight: 600;
    color: var(--tg-text);
    user-select: none;
}

.feed-number-input,
.feed-text-input {
    width: 100%;
    padding: 7px 10px;
    font-size: 14px;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(var(--border-field-rgb), 0.6);
    background: var(--tg-secondary-bg);
    color: var(--tg-text);
    outline: none;
    box-sizing: border-box;

    transition:
        border-color 0.15s ease-out,
        box-shadow 0.15s ease-out,
        background-color 0.15s ease-out;
}

.feed-number-input::placeholder,
.feed-text-input::placeholder {
    color: var(--tg-hint);
}

.feed-number-input:focus,
.feed-text-input:focus {
    border-color: var(--accent);
    background: var(--surface-2);
    box-shadow:
        0 0 0 1px rgba(91, 122, 57, 0.18),
        0 4px 10px rgba(15, 23, 42, 0.12);
}

/* Радио/чекбоксы */

.feed-filter-section input[type="radio"],
.feed-filter-section input[type="checkbox"] {
    accent-color: var(--accent);
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    cursor: pointer;
}

/* Профильный модал с мгновенным выбором */

.profile-modal {
    /* отступ снизу = нижняя панель навигации + safe area */
    padding-bottom: calc(62px + env(safe-area-inset-bottom, 0px) + 4px);
}

.profile-modal__options {
    display: flex;
    flex-direction: column;
}

.profile-modal__option {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 4px;
    font-size: 14px;
    color: var(--tg-text);
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--border-field-rgb), 0.12);
}

.profile-modal__option:last-child {
    border-bottom: none;
}

.profile-modal__option input[type="radio"] {
    width: 16px;
    height: 16px;
    accent-color: var(--accent);
    flex-shrink: 0;
    cursor: pointer;
}

.profile-modal__option--danger {
    border-top: 1px solid rgba(var(--border-field-rgb), 0.2);
    margin-top: 4px;
    color: var(--tg-hint);
}

/* Основной контейнер приложения */

/* FAB: анимация появления (fade) */
@keyframes fab-enter {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.feed-fab--entering {
    animation: fab-enter var(--fab-enter-duration) var(--fab-enter-ease);
}

#appMain {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#tab-deals,
#tab-deal-detail {
    width: 100%;
    align-self: stretch;
}

#tab-deal-detail .deal-page {
    width: 100%;
}

/* ============================
   ИКОНКА ГЕОЛОКАЦИИ В ПОЛЕ ГОРОДА (location_picker.js)
   ============================ */

/* Резервируем место под иконку (24×24), чтобы текст ввода не уходил под неё */
.gs-has-loc .lp-city-input,
.gs-has-loc .lp-loc-input {
    padding-right: 44px;
}

.gs-loc-btn {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);

    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
    padding: 10px;
    display: flex;
    align-items: center;
    justify-content: center;

    border: none;
    background: none;
    cursor: pointer;
    color: var(--tg-hint);
    opacity: 0.7;
    z-index: 40;          /* выше dropdown подсказок, чтобы тап доходил */
}

.gs-loc-btn svg {
    width: 24px;
    height: 24px;
}

/* В режиме очистки — единый крестик 16×16 (как в .auth-field__clear) */
.gs-loc-btn[data-mode="clear"] svg {
    width: 16px;
    height: 16px;
}

/* Крестик очистки должен выглядеть идентично .auth-field__clear:
   без приглушения и без padding (иконка геолокации остаётся opacity:0.7). */
.gs-loc-btn[data-mode="clear"] {
    opacity: 1;
    padding: 0;
}

.gs-loc-btn:active {
    opacity: 1;
}

/* Подсказка под полем города (только онбординг) */
.gs-loc-hint {
    margin: 6px 2px 0;
    font-size: 12px;
    color: var(--tg-hint);
    line-height: 1.4;
}

/* Сообщение об ошибке геолокации под полем локации (на 3 сек).
   Всегда в DOM и резервирует место (visibility, не display) — чтобы кнопка
   «Начать обмен» не сдвигалась при появлении/исчезновении текста. */
.lp-geo-hint {
    margin: 6px 2px 0;
    min-height: 1.4em;
    font-size: 12px;
    color: var(--brand-red);
    line-height: 1.3;
    visibility: hidden;
    /* Длинный текст ошибки гео («Не удалось найти месторасположение») переносится
       на несколько строк, а не обрезается в одну. */
    white-space: normal;
    overflow-wrap: anywhere;
}
.lp-geo-hint--visible { visibility: visible; }

/* Текст статуса «Определяем местоположение...» прямо в поле ввода.
   Двойной класс — чтобы перебить базовый `.lp-loc-input` из ui.css (та же
   специфичность, но ui.css грузится позже и иначе выигрывала бы). */
.lp-input--detecting,
.lp-loc-input.lp-input--detecting {
    /* Размер шрифта не менять — иначе поле прыгает по высоте. */
    color: var(--tg-hint);
    -webkit-text-fill-color: var(--tg-hint);
}

/* Ошибка валидации поля локации — красная рамка (как у поля имени/галки) */
.lp-input--error {
    border-color: var(--brand-red) !important;
}

/* ==== css/ui.css ==== */
/* ============================
   UI.CSS
   Компоненты + экраны
   ============================ */

button,
.btn,
.deal-btn {
    cursor: pointer;
}

/* =========================
   КАРТОЧКА РАСТЕНИЯ (универсальная)
   ========================= */

.plant-card {
    position: relative;
    background: var(--tg-secondary-bg);
    border-radius: 16px;
    border: var(--card-border);
    box-shadow: var(--shadow-card);

    padding: 10px;
    min-width: 0;
    display: flex;
    flex-direction: column;

    cursor: pointer;
    transition: transform 0.12s, box-shadow 0.12s;
}

.plant-card:active {
    transform: scale(0.97);
}
/* Во время горизонтального свайпа карусели гасим press-scale (иначе карточка
   «сжимается» пока палец удерживает :active). Обычный тап press-фидбек сохраняет. */
.plant-card.is-swiping,
.plant-card.is-swiping:active,
.plant-card:has(.plant-card__nav:active) {   /* десктоп: клик по стрелке не жмёт карточку */
    transform: none !important;
}

/* Свайп между разделами, начатый по телу плитки: гасим press-scale, иначе плитка
   «прожата» весь драг (swipe_tabs.js вешает body.gs-tab-swiping при подтверждённом
   драге, снимает на touchend/cancel). Плитки ленты/профиля (.plant-card) и Сделок
   (.deal-card). */
body.gs-tab-swiping .plant-card:active,
body.gs-tab-swiping .deal-card:active {
    transform: none !important;
    transition: none !important;   /* без 0.12s отката scale → нет «дёрга» при драге */
}

/* ── Единый слот фотографии растения ──────────────────────────
   Фон-заглушка no-photo-v2.svg + обрезка по слоту. Правило: «нет фото» и
   «ошибка загрузки» дают ОДНУ И ТУ ЖЕ заглушку — img гасится (пустой src
   правилом ниже, ошибка — через window.gsAttachPhotoFallback), из-под него
   проступает фон слота.

   Пропорции задаёт МЕСТО ПРИМЕНЕНИЯ: aspect-ratio 1/1 у карточек, 4/3 у
   детали, фиксированные px у миниатюр и ячеек формы. Здесь их нет.
   no-photo-v2.svg — иконка, поэтому 55% и no-repeat, НЕ cover (растянется).
   Аватары используют этот класс НЕ через img-заглушку: у них своя ветка
   (буква на оливковом), см. avatar.js. */

.gs-photo-slot {
    overflow: hidden;
    background: var(--surface-2) url('/static/img/no-photo-v2.svg') center / 55% no-repeat;
}

.gs-photo-slot__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Пустой src — скрываем img, видно фон-заглушку (ошибку гасит onerror) */
.gs-photo-slot__img[src=""],
.gs-photo-slot__img[src="undefined"],
.gs-photo-slot__img[src="null"] {
    opacity: 0;
}

/* Фото — КВАДРАТ с нормальной обрезкой. Обёртка несёт не только фото:
   относительно неё позиционируется .plant-status-badge. */
.plant-card__photo-wrapper {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-lg);

    display: flex;
    align-items: center;
    justify-content: center;

    flex-shrink: 0;
    position: relative;   /* якорь для точек/стрелок карусели */
}

/* === Карусель фото на карточке (gsBuildCardPhotos) === */
/* Слайд-трек: кадры в ряд, сдвиг translateX даёт эффект пролистывания.
   Контейнер .plant-card__photo-wrapper (gs-photo-slot) уже overflow:hidden. */
.plant-card__track {
    display: flex;
    width: 100%;
    height: 100%;
    transition: transform 0.25s ease;
    will-change: transform;
}
.plant-card__frame {
    flex: 0 0 100%;
    width: 100%;
    height: 100%;
    object-fit: cover;   /* обрезка по слоту, как у одиночного фото */
}
/* Точки: снизу по центру, поверх фото; не перехватывают тап/свайп. */
.plant-card__dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 6px;
    display: flex;
    justify-content: center;
    gap: 5px;
    pointer-events: none;
    z-index: 2;
}
.plant-card__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.55);
    box-shadow: 0 0 2px rgba(0, 0, 0, 0.35);
    transition: background 0.15s;
}
.plant-card__dot.is-active {
    background: var(--on-accent);   /* точка НА ФОТО — белая в обеих темах */
}

/* Стрелки: по краям фото, компактнее базового gs-img-ctrl; скрыты на тач,
   проявляются на hover десктопа. Не перекрывают угловые бейджи (те сверху).
   Селекторы с префиксом .plant-card — чтобы перебить .gs-img-ctrl {width:44px},
   объявленный ПОЗЖЕ с той же специфичностью (иначе стрелки остаются 44px). */
.plant-card .plant-card__nav {
    top: 50%;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    z-index: 2;
    opacity: 0;
    pointer-events: none;   /* скрытые стрелки не ловят тап (на тач всегда скрыты) */
    transition: opacity 0.15s;
}
.plant-card .plant-card__nav--prev { left: 6px; }
.plant-card .plant-card__nav--next { right: 6px; }
/* Шеврон — пропорционально уменьшенному кружку (базовый 11px торчал бы). */
.plant-card .plant-card__nav--prev::before,
.plant-card .plant-card__nav--next::before {
    width: 8px;
    height: 8px;
    border-top-width: 2px;
    border-left-width: 2px;
}
.plant-card .plant-card__nav--prev::before { transform: translateX(1px) rotate(-45deg); }
.plant-card .plant-card__nav--next::before { transform: translateX(-1px) rotate(135deg); }
/* Стрелки видны ТОЛЬКО на устройствах с настоящим hover-курсором (десктоп).
   На тач :hover эмулируется при свайпе → стрелки всплывали; жёстко гасим. */
@media (hover: hover) and (pointer: fine) {
    .plant-card:hover .plant-card__nav { opacity: 0.9 !important; pointer-events: auto; }
}

/* Текстовый блок карточки */
.plant-card__info {
    min-width: 0;
    overflow: hidden;
}

.plant-card__header {
    display: flex;
    align-items: flex-start;      /* листочки по ПЕРВОЙ строке названия (не baseline) */
    justify-content: space-between;
    gap: 4px;
    margin-top: 8px;
}

/* Контейнер «название + тип» — до 2 строк. Обрезка через JS gsFitCardTitle:
   режется ИМЯ (.plant-card__title) по словам с «…», ТИП (.plant-card__type) —
   всегда целиком (входит в замер, поэтому не «отрывается» и не пропадает).
   line-clamp НЕ используем — он ставит «…» в конце блока, т.е. на тип.
   max-height + overflow — предохранитель до срабатывания JS. */
.plant-card__title-wrap {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    line-height: 1.3;
    max-height: 2.6em;
    overflow: hidden;
}

.plant-card__title {
    font-weight: 600;             /* название жирным; без nowrap — перенос на 2 строки */
}

.plant-card__type {
    font-weight: 400;
    color: var(--tg-hint);        /* тип серым, инлайн сразу за названием */
    text-transform: lowercase;
    font-size: 13px;              /* название рядом 14px → тип чуть мельче */
}

/* Цена 🌿 — белая плашка в правом-нижнем углу фото (внутри .plant-card__photo-wrapper).
   Статус-бейдж — вверху-справа, точки карусели — снизу-по-центру: угол свободен. */
.plant-card__leaf {
    position: absolute;
    bottom: 8px;
    right: 8px;
    z-index: 3;
    background: var(--surface-2);
    color: var(--text-primary);
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
    /* Правый паддинг меньше левого: у листа справа есть внутренний воздух глифа,
       иначе справа визуально больше места, чем слева от числа. */
    padding: 4px 7px 4px 9px;
    border-radius: 10px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}

.plant-card__meta {
    font-size: 12px;
    color: var(--tg-hint);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Владелец (только Стол): мини-аватар + имя */
.plant-card__owner {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 6px;
    min-width: 0;
    font-size: 12px;
    color: var(--text-primary);
}
.plant-card__owner-avatar { flex-shrink: 0; }
.plant-card__owner-name {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.plant-card__delivery {
    font-size: 11px;
    color: var(--tg-hint);
    margin-top: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Стол — сетка */
.plants-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    /* Зазор = высота градиента .feed-toolbar::after (8px): первая плитка стартует
       ПОД градиентом при покое (не «заходит под фильтр»), уходит под него при прокрутке. */
    padding-top: 8px;
    padding-bottom: calc(var(--scroll-end-gap) + 20px); /* FAB кнопка добавить растение + зазор */
}

/* === Полоса «сторис»-подсказок (скролл-контент над лентой, НЕ sticky) === */
.stories-strip {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    /* #feedStories — flex-child колоночного #tab-feed.tab--active (flex-column):
       БЕЗ flex:0 0 auto он сжимался (flex-shrink:1) до высоты ~строки → кружки 60px
       обрезались. Не сжимаемся + min-height под содержимое (кружок 60 + подпись +
       вертикальный паддинг). */
    flex: 0 0 auto;
    min-height: 94px;
    overflow-x: auto;
    overflow-y: hidden;      /* только горизонтальный скролл; высота фикс — контент не клипуется */
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* Вертикальный паддинг вмещает кружок 60px + подпись ЦЕЛИКОМ (без обрезки дуг).
       Боковой 12px — инсет как у грида/тулбара. */
    padding: 10px 12px 8px;
}
.stories-strip::-webkit-scrollbar { display: none; }
.stories-strip.hidden { display: none; }

/* === Единая inline-SVG иконка (Tabler outline). Пути — в спрайте app.html; цвет —
   currentColor (наследует цвет текста/кнопки). Модификаторы success/danger — на
   этапе статусов. === */
.gs-icon {
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vertical-align: middle;
    flex: none;
}
/* Валюта листочков — СПЛОШНАЯ заливка, сочно-зелёный; выровнен под текст рядом с числом.
   Переопределяет .gs-icon (fill:none; stroke:currentColor). */
.gs-leaf {
    color: var(--leaf);
    fill: currentColor;
    stroke: none;
    /* Рядом с числом: пробела в разметке НЕТ, зазор даёт margin. Выравнивание —
       дефолтное (baseline), у нового глифа своя посадка. */
    margin-left: 0.1em;
    vertical-align: -0.2em;   /* 0 = baseline, минус = ниже */
}
/* На зелёных подложках — белый лист (вена-прорезь читается зелёным фоном, как иконка). */
.gs-leaf--on-dark { color: #fff; }

/* Цветовые модификаторы иконок (тинт через currentColor). */
.gs-icon--green { color: #3B6D11; }
.gs-icon--red   { color: var(--brand-red); }
.gs-icon--olive { color: var(--accent); }
.gs-icon--muted { color: var(--tg-hint); }
/* Залитый глиф (например #i-leaf-fill как категорийная иконка) — fill вместо stroke. */
.gs-icon--fill { fill: currentColor; stroke: none; }
/* Центрируем svg-иконку в кружках категории/причины (был текстовый эмодзи). */
.leaves-tx__icon, .notif-item__icon { display: flex; align-items: center; justify-content: center; }
/* Standalone-иконки (не рядом с числом) — без левого зазора. */
.topbar-balance-icon .gs-leaf,
.leaves-balance-icon .gs-leaf,
.feed-paywall__icon .gs-leaf { margin-left: 0; }
/* Баланс-баннер листочков: приподнять белый лист (flex-центр → двигаем transform'ом). */
.leaves-balance-icon .gs-leaf { transform: translateY(-3px); }

/* Бренд-вордмарк (топбар/онбординг используют gsLeaf) — своя посадка листа, НЕ
   зависит от валютного .gs-leaf (-0.2em). Раскрутить отдельно от валюты. */
.topbar-brand .gs-leaf,
.ob-header__brand .gs-leaf { vertical-align: -0.1em; }

/* Валютный margin-left (0.1em) у .gs-leaf в вордмарке даёт асимметрию: у правого
   листа отступ попадает МЕЖДУ текстом и листом (правый зазор больше), у левого —
   наружу. Гасим — зазор с обеих сторон задаётся только пробелами в разметке. */
.topbar-brand .gs-leaf,
.ob-header__brand .gs-leaf,
.stories-viewer__brand .gs-leaf { margin-left: 0; }

/* Симметрия бренд-вордмарка: ЛЕВЫЙ листок (первый в обёртке) зеркалим — оба листа
   смотрят единообразно. Правый не трогаем. Splash/auth (хардкод SVG в app.html) —
   зеркалятся инлайном (рендерятся до загрузки ui.css). */
.topbar-brand .gs-leaf:first-child,
.ob-header__brand .gs-leaf:first-child,
.stories-viewer__brand .gs-leaf:first-child { transform: scaleX(-1); }

/* === Полноэкранный просмотрщик сторис (по образцу gs-lightbox) === */
.stories-viewer {
    position: fixed;
    inset: 0;
    z-index: 10500;
    display: none;              /* JS ставит flex при открытии */
    align-items: center;
    justify-content: center;
    /* Тёмный backdrop по краям — на десктопе рамка уже вьюпорта, по бокам затемнение. */
    background: rgba(0, 0, 0, 0.6);
    opacity: 0;
    transition: opacity 0.2s ease;
    /* iOS: долгий тап не должен выделять текст / открывать callout-меню. */
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}
.stories-viewer.visible { opacity: 1; }

/* Рамка-«телефон»: ограничивает контент по ширине и центрирует. Все абсолютные дети
   (bg/scrim/segments/close/zone/actions) анкорятся к ней. На мобильном max-width=100%
   → визуально как раньше (во всю ширину). Оливковый фон живёт в рамке. */
.stories-viewer__frame {
    position: relative;
    width: 100%;
    max-width: 480px;   /* = колонка приложения (.page-inner/.topbar-container/.feed-modal) */
    height: 100%;
    margin: 0 auto;
    overflow: hidden;
    background: var(--accent);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: calc(env(safe-area-inset-top, 0px) + 16px) 20px calc(env(safe-area-inset-bottom, 0px) + 20px);
    box-sizing: border-box;
}

.stories-viewer__segments {
    position: absolute;
    top: calc(env(safe-area-inset-top, 0px) + 10px);
    left: 12px;
    right: 12px;
    display: flex;
    gap: 4px;
    z-index: 3;
}
.stories-viewer__seg {
    flex: 1;
    height: 3px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.35);
    overflow: hidden;
}
.stories-viewer__seg-fill {
    height: 100%;
    width: 0;
    background: var(--on-accent);
    border-radius: 2px;
}
.stories-viewer__seg-fill.is-active {
    width: 0;
    animation: storiesFill linear forwards;   /* duration задаёт JS */
}
@keyframes storiesFill { from { width: 0; } to { width: 100%; } }
@media (prefers-reduced-motion: reduce) {
    .stories-viewer__seg-fill.is-active { animation: none; width: 100%; }
}

.stories-viewer__close {
    position: absolute;
    top: calc(env(safe-area-inset-top, 0px) + 22px);
    right: 12px;
    z-index: 4;
    color: var(--on-accent);
}

/* Тап-зоны листания — под контентом-карточкой, но над фоном. НЕ накрывают верхнюю
   полосу (сегменты + крестик, ~56px), иначе next-зона перехватывала бы тап по крестику. */
.stories-viewer__zone {
    position: absolute;
    top: 56px;
    bottom: 0;
    width: 35%;
    z-index: 1;
}
.stories-viewer__zone--prev { left: 0; }
.stories-viewer__zone--next { right: 0; }

.stories-viewer__card {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    max-width: 340px;
    color: var(--on-accent);
    pointer-events: none;       /* тапы проходят к зонам листания */
}
.stories-viewer__icon {
    width: 88px;
    height: 88px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.15);
    margin-bottom: 20px;
}
.stories-viewer__icon svg { width: 44px; height: 44px; }
.stories-viewer__title {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.25;
    margin-bottom: 12px;
}
.stories-viewer__text {
    font-size: 15px;
    line-height: 1.5;
    opacity: 0.92;
}
/* Бренд-вордмарк внутри бренд-кадра сторис (brand:true) — крупнее заголовка,
   листья по бокам чуть приподняты (как в топбар-вордмарке). */
.stories-viewer__brand { font-size: 24px; }
.stories-viewer__brand .gs-leaf { vertical-align: -0.1em; }
/* Тело бренд-кадра: tagline по центру + список выгод слева. */
.stories-brand__body { opacity: 1; }
.stories-brand__tagline {
    font-size: 20px;
    font-weight: 500;
    line-height: 1.3;
    margin-bottom: 22px;
}
/* Подводка обычного кадра с features (текст по центру над списком). */
.stories-viewer__lead {
    margin-bottom: 22px;
}
.stories-brand__features {
    display: flex;
    flex-direction: column;
    gap: 16px;
    text-align: left;
}
.stories-brand__feature {
    display: flex;
    align-items: center;
    gap: 12px;
}
.stories-brand__feature-icon {
    flex-shrink: 0;
    display: inline-flex;
    color: var(--on-accent);
}
.stories-brand__feature-icon svg { width: 24px; height: 24px; }
.stories-brand__feature-text {
    font-size: 15px;
    line-height: 1.35;
}

/* Фон-фото кадра + затемняющий scrim (только для кадров с фото). */
.stories-viewer__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
/* Затемнение фото — РАВНОМЕРНЫЙ оверлей (легко подкрутить: --stories-scrim) +
   лёгкий доп-градиент снизу под CTA. Цель — белый текст читается по всей высоте. */
.stories-viewer { --stories-scrim: rgba(10, 14, 10, 0.45); }
.stories-viewer__scrim {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: none;
    background:
        linear-gradient(to bottom, rgba(0,0,0,0) 60%, rgba(0,0,0,0.35) 100%),
        var(--stories-scrim);
}
.stories-viewer.has-image .stories-viewer__scrim { display: block; }
/* С фото — контент ПО ЦЕНТРУ рамки (бренд/tagline/выгоды/CTA), иконку не показываем.
   Контент-флекс живёт в рамке → justify-content на ней, не на оверлее. */
.stories-viewer.has-image .stories-viewer__frame {
    justify-content: center;
    /* Тёмная подложка под #storiesBg — до готовности фото (и на первый показ) видна
       она, а не оливковый фон рамки → нет зелёной вспышки при листании. */
    background-color: rgba(10, 14, 10, 1);
}
.stories-viewer.has-image .stories-viewer__card { margin-bottom: 0; }
.stories-viewer.has-image .stories-viewer__text { opacity: 1; }

/* Значок темы над заголовком (только has-image): frosted-кружок с media.icon.
   :not([hidden]) — чтобы пустой/скрытый значок не рисовал кружок. */
.stories-viewer.has-image .stories-viewer__badge:not([hidden]) {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin: 0 auto 12px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.16);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 0.5px solid rgba(255, 255, 255, 0.25);
}
.stories-viewer__badge[hidden] { display: none; }
.stories-viewer.has-image .stories-viewer__badge svg {
    width: 22px;
    height: 22px;
    color: #fff;
    filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.5));
}

/* Читаемость на фото: тень белому контенту (только has-image; затемнение
   --stories-scrim не трогаем). Заголовок/бренд, tagline, текст, подписи выгод, ссылки. */
.stories-viewer.has-image .stories-viewer__title,
.stories-viewer.has-image .stories-viewer__brand,
.stories-viewer.has-image .stories-brand__tagline,
.stories-viewer.has-image .stories-viewer__lead,
.stories-viewer.has-image .stories-viewer__text,
.stories-viewer.has-image .stories-brand__feature-text {
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.55);
}
/* Иконки выгод (SVG stroke) — лёгкий drop-shadow для единообразия. */
.stories-viewer.has-image .stories-brand__feature-icon svg,
.stories-viewer.has-image .stories-viewer__brand .gs-leaf {
    filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.5));
}
/* Вторичная кнопка «Подробнее» — лёгкая тёмная заливка + тень подписи (не теряется
   на среднем тоне). CTA «К столу» (сплошная) не трогаем. */
.stories-viewer.has-image .stories-viewer__link {
    background: rgba(0, 0, 0, 0.22);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.55);
}

/* Панель действий: ряд вторичных ссылок над основной кнопкой. */
.stories-viewer__actions {
    position: absolute;
    left: 20px;
    right: 20px;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 20px);
    z-index: 4;
    display: flex;
    flex-direction: column;
    gap: 10px;
    pointer-events: auto;       /* карточка pointer-events:none; кнопки — кликабельны */
}
/* Вторичные ссылки — ПОД текстом внутри карточки (карточка pointer-events:none →
   ссылкам возвращаем pointer-events:auto). */
.stories-viewer__links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-top: 18px;
    pointer-events: auto;
}
.stories-viewer__links:empty { display: none; margin-top: 0; }
.stories-viewer__link {
    padding: 8px 14px;
    border-radius: var(--radius-pill);
    border: 1.5px solid rgba(255, 255, 255, 0.7);
    background: rgba(255, 255, 255, 0.14);
    color: var(--on-accent);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.stories-viewer__link:active { opacity: 0.8; }

.stories-viewer__cta {
    width: 100%;
    padding: 14px 16px;
    border: none;
    border-radius: var(--radius-pill);
    background: var(--on-accent);
    color: var(--accent);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
}
.stories-viewer__cta:active { opacity: 0.85; }

.stories-strip__item {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    width: 64px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.stories-strip__ring {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    background: var(--surface-2);
    border: 2px solid var(--accent);
    transition: transform 0.12s;
}
/* Просмотренная история — приглушённое серое кольцо (акцент снят). */
.stories-strip__ring.is-seen {
    color: var(--tg-hint);
    border-color: var(--border-subtle);
}
.stories-strip__item:active .stories-strip__ring { transform: scale(0.94); }
.stories-strip__label {
    font-size: 11px;
    line-height: 1.2;
    color: var(--text-primary);
    text-align: center;
    max-width: 64px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* === Горизонтальный инсет контента скроллеров (полоса прокрутки — у края экрана) ===
   .page-inner больше не даёт боковой отступ; 12px висят на ВНУТРЕННЕМ контенте, а сами
   скроллеры (.tab--active, .plant-detail-scroll, .admin-page) — во всю ширину. */
/* Feed: тулбар (sticky) и грид — прямые дети скроллера, обёртки нет → инсет на каждом. */
#tab-feed .feed-toolbar { padding-left: 12px; padding-right: 12px; }
#tab-feed .plants-grid  { padding-left: 12px; padding-right: 12px; }
/* Deals/Settings/Admin: инсет на внутреннем контейнере (sticky-тулбар внутри — вдвигается
   вместе с контентом, поэтому фон не «выглядывает» по краям). */
#dealsContainer    { padding-left: 12px; padding-right: 12px; }
#settingsContainer { padding-left: 12px; padding-right: 12px; }
#adminContent      { padding-left: 12px; padding-right: 12px; }
#helpContainer, #helpArticleContainer, #legalDocContainer { padding-left: 12px; padding-right: 12px; }
/* Notifications (.notifications-container) уже имеет собственный 12px — не трогаем. */

/* Истинно пустой стол (нет карточек, без фильтра/поиска) — центрируем блок
   по вертикали в доступной высоте фида. Класс вешается только в этом режиме
   (plants_feed.js), обычная сетка карточек и no-results не затрагиваются. */
.plants-grid--empty-center {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: center;
    padding-bottom: 0;
}

/* Базовый бейдж статуса (форма, топбар и т.п.) */

.plant-status-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;

    padding: 4px 8px;
    border-radius: var(--radius-pill);

    font-size: 12px;
    line-height: 1.2;
    font-weight: 500;

    background: var(--tg-secondary-bg);
    color: var(--tg-text);

    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Бейдж статуса поверх фото в карточке */

.plant-card .plant-status-badge {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;   /* над слайд-треком фото (wrapper position:relative) — иначе уходит за фото */

    background: rgba(0, 0, 0, 0.55);
    color: var(--on-accent);
    font-weight: 600;   /* заметнее на фото (база 500) */

    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

/* Варианты статусов — пастельная система (совпадает с deal-status-badge).
   Специфичность 0,2,0 — перебивает .plant-card .plant-status-badge (тёмный оверлей). */

.plant-card .plant-status-badge--new,
.plant-card .plant-status-badge--hidden,
.plant-card .plant-status-badge--deleted,
.plant-card .plant-status-badge--mine {   /* «Моё» на столе — тот же тёмный фростед, что «Удалено» */
    background: rgba(0, 0, 0, 0.6);   /* тёмный фростед — читаемо на фото (серого цвета у статуса нет) */
    color: var(--on-accent);
}

/* Цвета статусов — палитра профиля (--status-*). На карточке бейдж лежит НА ФОТО,
   поэтому заливка СПЛОШНАЯ цветом статуса + белый текст (пастельные rgba-тона не
   читались на фото). Баннер (на белом) остаётся пастельным — тот же оттенок. */
.plant-card .plant-status-badge--pending {
    background: var(--status-pending);
    color: var(--on-accent);
}

/* «Отдано» (completed) — ЗЕЛЁНЫЙ, как approved (читается как успех). Карточка бледнеет
   (.plant-card--faded), но бейдж — на полной яркости (приглушаем не всю карточку, а
   её внутренние блоки, см. ниже). */
.plant-card .plant-status-badge--approved,
.plant-card .plant-status-badge--completed {
    background: var(--status-approved);
    color: var(--on-accent);
}

/* Бледная карточка (профиль: Отдано/Удалено) — «этого растения по сути больше нет».
   Приглушаем ФОТО и ТЕКСТ, но НЕ статус-бейдж: opacity на всей .plant-card притушила бы
   и бейдж (child не может быть ярче faded-родителя), поэтому фейдим внутренние блоки —
   бейдж (прямой ребёнок карточки, absolute) остаётся на полной яркости и «выныривает». */
.plant-card--faded .plant-card__photo-wrapper,
.plant-card--faded .plant-card__info {
    opacity: 0.55;
}

.plant-card .plant-status-badge--reserved {
    background: var(--status-purple);   /* «Бронь» — как шаг сделки (deal-progress data-step=0) */
    color: var(--on-accent);
}

.plant-card .plant-status-badge--rejected {
    background: var(--status-rejected);
    color: var(--on-accent);
}

/* Плитка модерации (admin) — бейдж статуса ИНЛАЙН в строке (не оверлей на фото):
   берём ту же палитру --status-*, но БЕЗ position:absolute из .plant-card. */
.admin-plant-card .plant-status-badge--pending  { background: var(--status-pending);  color: var(--on-accent); }
.admin-plant-card .plant-status-badge--rejected { background: var(--status-rejected); color: var(--on-accent); }
.admin-plant-card .plant-status-badge--approved,
.admin-plant-card .plant-status-badge--completed { background: var(--status-approved); color: var(--on-accent); }
.admin-plant-card .plant-status-badge--reserved { background: var(--status-purple);   color: var(--on-accent); }

/* Комментарий модератора на карточке в профиле */
.plant-card__reject-note {
    font-size: 11px;
    color: var(--brand-red);
    line-height: 1.3;
    padding: 4px 2px 0;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}


/* =========================
   ДЕТАЛЬ РАСТЕНИЯ
   ========================= */

/* Визуально скрытый, но В ПОТОКЕ элемент. Для <input type=file>: iOS Safari у
   инпута с display:none НЕ диспатчит change после выбора фото → файл не добавляется.
   Этот приём (в потоке, 1×1px, прозрачный) — инпут кликается программно и надёжно
   шлёт change. НЕ использовать display:none/visibility:hidden на file-инпутах. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
}

/* Скролируемая область */
#screen-plant.tab--active,
#screen-plant-detail.tab--active {
    overflow: hidden;
    position: relative;
}

.plant-detail-scroll {
    flex: 1;
    overflow-y: auto;
    /* -webkit-overflow-scrolling:touch убран — legacy (на совр. iOS momentum и так есть),
       и он якорь caret-офсета: iOS считал позицию каретки полей относительно этого
       momentum-скроллера. Скролл остаётся плавным. */
    /* БЕЗ padding-top: он сдвигал пин sticky-головы (#psStickyHead top:0) на 8px вниз
       (WebKit sticky уважает padding скроллера) → между топбаром и баннером прозрачная
       полоса, где при скролле просвечивал контент. At-rest-зазор голова→карточка даёт
       .plant-detail-main-card margin-top:8px. Паттерн Стола: скроллер без верхнего
       паддинга, зазор — на контенте (.plants-grid padding-top:8px). */
    padding-bottom: var(--scroll-end-gap);
    /* Клавиатурный резерв — через scroll-padding (не content-padding): нативный
       scrollIntoView оставляет место под клавиатуру снизу для нижних полей (описание)
       БЕЗ пустого контента (не нужен focusout-возврат, пустоты при закрытой клавиатуре
       нет). Верх — под sticky-голову #psStickyHead (JS уточняет scrollPaddingTop по её
       реальной высоте на focusin; здесь дефолт-фолбэк). */
    scroll-padding-bottom: 340px;
    scroll-padding-top: 56px;
}
/* Скроллер во всю ширину (полоса у края); h-инсет 12 — на его прямых детях.
   Баннер владельца так вдвинут → его border-right/::before не заходят на полосу. */
#psScrollArea > #psFormError,
#psScrollArea > #psStickyHead,
#psScrollArea > .plant-detail-main-card,
#psScrollArea > #psSkeleton,
#psScrollArea > #psErrorState {
    margin-left: 12px;
    margin-right: 12px;
}

/* Sticky-голова (баннер + строка правки) держится единым блоком при скролле.
   padding-top:8px — ОПАКОВЫЙ зазор над баннером (фон tg-bg = фон страницы → читается
   как отступ от топбара, симметрично зазору голова→карточка снизу). Он ВНУТРИ sticky-
   элемента, поэтому при закреплении едет вместе с головой и накрывает уезжающий контент
   (в отличие от padding-top скроллера, который сдвигал пин и оставлял прозрачную щель).
   padding-bottom:2px — опаковый зазор под блоком. */
#psStickyHead {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--tg-bg);
    padding-top: 8px;
    padding-bottom: 2px;
}
/* Плавный градиент под sticky-головой (как .feed-toolbar::after на Столе):
   высота 8px, начинается от низа головы (top:100%), едет с ней при скролле;
   контент уходит под кнопки с мягким растворением. pointer-events:none. */
#psStickyHead::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 8px;
    background: linear-gradient(to bottom, var(--tg-bg), transparent);
    pointer-events: none;
}

/* Строка правки [Отмена][Сохранить]. Кнопки берут flex:1 + order из
   #screen-plant .secondary/.primary-button (Отмена белая слева, Сохранить зелёная
   справа). Свёрнута в view (0 высоты, «спрятана» под баннером); при входе в
   edit/create РАЗВОРАЧИВАЕТСЯ ВНИЗ из-под баннера — плавно (max-height+opacity). */
.ps-edit-actions {
    display: flex;
    gap: 8px;
    justify-content: center;   /* по центру строки (не на всю ширину) */
    max-height: 0;
    opacity: 0;
    margin-top: 0;
    overflow: hidden;
    pointer-events: none;
    transition: max-height 0.24s ease, opacity 0.18s ease, margin-top 0.24s ease;
}
#screen-plant[data-mode="edit"]   .ps-edit-actions,
#screen-plant[data-mode="create"] .ps-edit-actions {
    max-height: 56px;
    opacity: 1;
    margin-top: 12px;
    pointer-events: auto;
}
/* Кнопки правки — размер как «На модерацию» в баннере (8px 12px / 13px), по
   контенту (flex:0 0 auto), НЕ на всю ширину. ID-специфичность #screen-plant —
   перебить базовые .secondary/.primary-button (flex:1 + крупный паддинг). */
#screen-plant .ps-edit-actions .secondary-button,
#screen-plant .ps-edit-actions .primary-button {
    flex: 0 0 120px;   /* равная ширина обеих кнопок (Отмена = Сохранить) */
    padding: 8px 12px;
    font-size: 13px;
    text-align: center;
}
/* «Сохранить» — белая (не зелёная), как «Отмена»; отличается только жирностью. */
#screen-plant .ps-edit-actions .primary-button {
    background: var(--surface-2);
    color: var(--text-primary);
    border: 1.5px solid var(--border-subtle);
    font-weight: 600;
}
@media (prefers-reduced-motion: reduce) {
    .ps-edit-actions { transition: none; }
}

/* Основная карточка: фото + текст вместе */
.plant-detail-main-card {
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-lg);
    /* Зазор = высота градиента #psStickyHead::after (8px): карточка при покое
       стартует ПОД градиентом (не «заходит за него»), уходит под него на скролле. */
    margin-top: 8px;
    margin-bottom: 10px;
    padding: 10px;
}

/* ── Состояния экрана растения (loading/data/error) ────────────
   #screen-plant — ПЕРЕИСПОЛЬЗУЕМЫЙ статичный экран, как #tab-deal-detail:
   узлы захвачены в модульные $ps*-переменные (plant_screen.js), поэтому
   setListState сюда направлять нельзя (host.innerHTML="" их уничтожит).
   Состояние — data-state на секции; скелетон и error — сиблинги.
   data-mode (view/edit/create) живёт отдельно и с data-state не конфликтует. */

#psSkeleton,
#psErrorState {
    display: none;
}

#screen-plant[data-state="loading"] .plant-detail-main-card,
#screen-plant[data-state="loading"] #psStickyHead,
#screen-plant[data-state="loading"] #psFormError,
#screen-plant[data-state="error"]   .plant-detail-main-card,
#screen-plant[data-state="error"]   #psStickyHead,
#screen-plant[data-state="error"]   #psFormError,
#screen-plant[data-state="loading"] #psActions,
#screen-plant[data-state="error"]   #psActions {
    display: none !important;
}

#screen-plant[data-state="loading"] #psSkeleton {
    display: block;
}

#screen-plant[data-state="error"] #psErrorState {
    display: block;
}

/* Фото-враппер — как на столе */
.plant-detail-photo-main {
    width: 100%;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-sm);
    position: relative;         /* якорь для инлайн-стрелок .ps-main-nav */
}

/* Нет реальных фото — компактная заглушка вместо высокого слота 4/3 (иначе вокруг
   иконки много пустоты). Фикс. невысокий слот + иконка нормального размера. */
.plant-detail-photo-main--empty {
    aspect-ratio: auto;
    height: 150px;
    background-size: 128px auto;   /* иконка ×2 (крупнее, но слот всё ещё компактный) */
}

/* Инлайн-стрелки листания главного фото — кружок общий .gs-img-ctrl, вид 1-в-1
   с лайтбоксом. Видимость — JS (psRefreshMainNav). */
.ps-main-nav {
    display: none;              /* показ управляется JS (psRefreshMainNav) */
    top: 50%;
    transform: translateY(-50%);
}
.ps-main-nav--prev { left: 8px; }
.ps-main-nav--next { right: 8px; }

/* object-position и translateZ — сверх .gs-photo-slot__img (антиалиасинг на iOS) */
.plant-detail-photo-main img {
    object-position: center;
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}
/* Плавное пролистывание главного фото (psSlideMainPhoto): transition в классе,
   инлайном меняется только transform → надёжный запуск в WebView. */
.plant-detail-photo-main img.ps-photo-slide {
    transition: transform 260ms ease;
}

/* Миниатюры внутри карточки */
.plant-detail-thumbs {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 8px 0;
    scrollbar-width: none;
}

.plant-detail-thumbs::-webkit-scrollbar {
    display: none;
}

/* Обёртка миниатюры (view и edit): держит рамку/активное состояние; в edit —
   якорь для крестика удаления. Внутри — img .plant-detail-thumb на всю площадь. */
.ps-thumb {
    position: relative;
    width: 58px;
    height: 58px;
    flex-shrink: 0;
    border-radius: var(--radius-xs);
    border: 2px solid transparent;
    cursor: pointer;
    overflow: hidden;
    transition: border-color 0.12s;
    box-sizing: border-box;
}

.ps-thumb--active {
    border-color: var(--accent);
}

/* Миниатюра-img внутри обёртки: заполняет её, рамку/скругление держит .ps-thumb. */
.plant-detail-thumb {
    width: 100%;
    height: 100%;
    border: none;
    border-radius: 0;
}

/* Крестик удаления фото (edit) — в правом-верхнем углу миниатюры (как онбординг) */
.ps-thumb-del {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 18px;
    height: 18px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(25, 25, 25, 0.65);
    color: var(--on-accent);
    font-size: 13px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 2;
    -webkit-tap-highlight-color: transparent;
}

/* Плашка «добавить фото» — миниатюра-кнопка с пунктиром в конце ряда (edit) */
.ps-thumb-add {
    border-style: dashed;
    border-color: var(--border-subtle);
    background: var(--surface-1);
    overflow: visible;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ps-thumb-add:active { background: var(--input-bg); }
.ps-thumb-add__plus {
    font-size: 26px;
    font-weight: 300;
    line-height: 1;
    color: var(--tg-hint);
}
/* Ошибка «нужно фото»: НЕ обводим весь ряд миниатюр (убираем рамку контейнера от
   .ps-field--error), обводим ТОЛЬКО кнопку «+» — сплошной красной (не пунктиром). */
.plant-detail-thumbs.ps-field--error {
    border: none !important;
}
.plant-detail-thumbs.ps-field--error .ps-thumb-add {
    border-style: solid;
    border-color: var(--brand-red);
}

/* Текстовая часть карточки */
/* Группа «название → город → участник» — плотно, ровный зазор 5px.
   Отступ сверху (после фото) — на .plant-detail-info; между строками — pad-top 5px. */
.plant-detail-info {
    padding: 10px 0 0;
}

.plant-detail-title-row {
    display: flex;
    align-items: flex-start;      /* листочки по ПЕРВОЙ строке названия (не baseline) */
    justify-content: space-between;
    gap: 10px;
}

.plant-detail-title {
    font-size: 18px;
    font-weight: 700;
    line-height: 1.25;
    flex: 1;
    min-width: 0;
}

/* View-название — до 2 строк с обрезкой «…» (edit — input #psTitle) */
.plant-detail-title-view {
    flex: 1;
    min-width: 0;
    font-size: 18px;
    font-weight: 700;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.plant-detail-leaf {
    font-size: 16px;
    font-weight: 700;
    line-height: 1.25;            /* выравнивание по первой строке названия */
    white-space: nowrap;
    flex-shrink: 0;
}

/* Город — отдельная строка без заголовка (view = текст, edit = пикер) */
.plant-detail-city-row {
    padding: 5px 0 0;   /* 5px зазор к названию, без линии */
}
/* Edit/create: инлайн-поля (подчёркивание) название и город слипались — добавляем зазор. */
#screen-plant[data-mode="edit"]   .plant-detail-city-row,
#screen-plant[data-mode="create"] .plant-detail-city-row {
    margin-top: 8px;
}
.plant-detail-city-row #psCityView {
    font-size: 14px;
    font-weight: 400;   /* обычный вес, как участник/описание; жирным только название */
}

/* Участник — отдельная строка (view чужих): аватар + имя + стрелка → профиль */
.plant-detail-seller-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 0 0;   /* 5px зазор к городу; линии после города НЕТ */
    margin-top: 0;
    cursor: pointer;
}
.plant-detail-seller-row:active { opacity: 0.6; }
.plant-detail-seller__avatar { flex-shrink: 0; }
.plant-detail-seller__name {
    flex: 0 1 auto;   /* по контенту (не тянем во всю строку) — шеврон вплотную к имени;
                         может ужаться с «…» при длинном имени */
    min-width: 0;
    font-size: 14px;
    font-weight: 400;   /* обычный вес, как город/описание; жирным остаётся только название */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.plant-detail-seller__chevron {
    flex-shrink: 0;
    color: var(--tg-hint);
    font-size: 18px;
    font-weight: 400;
}

/* ── Общая info-сетка (2 колонки) ─────────────────────────────
   Разделители рисует ЗАЗОР сетки поверх фона-подложки контейнера, а НЕ
   бордюры ячеек по nth-child. Не зависит от высоты ячеек (stretch их равняет)
   и от числа видимых ячеек — скрытие ячейки не ломает решётку (в отличие от
   nth-child-бордюров). Внешние рамки (верх/низ) — НЕ здесь: gap рисует только
   внутренние линии, внешние остаются на конкретном контейнере по потребности.
   Применяется на экране растения и в деталях сделки. */
.gs-info-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1px;
    background: rgba(var(--tint-rgb), 0.07);
}

.gs-info-cell {
    background: var(--tg-secondary-bg);
}

.plant-detail-params {
    /* grid/gap/подложка — из .gs-info-grid; здесь внешняя верхняя рамка + вылет за
       padding карточки. margin-top 12px — заметное отделение группы (название/город/
       участник) от грида тип/доставка, одинаково с участником и без него. */
    border-top: 1px solid var(--tint-neutral);
    margin: 12px -10px 0;
}

.plant-detail-param {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 4px;
}

/* Раскладка: Город/Участник — на всю ширину; Тип|Передача — в ряд.
   Спан-ячейки заполняют сетку целиком → нет пустых клеток (серых пятен),
   линии-разделители (gap+подложка) ровные. Внешние края — padding 12, у
   границы центрального дивайдера — 8. */
.plant-detail-param--full {
    grid-column: 1 / -1;
    padding-left: 12px;
    padding-right: 12px;
}
.plant-detail-param--col1 {
    padding-left: 12px;
    padding-right: 8px;
}
.plant-detail-param--col2 {
    padding-left: 8px;
    padding-right: 12px;
}

.plant-detail-param--link {
    cursor: pointer;
    position: relative;
}

.plant-detail-param--link:active {
    opacity: 0.6;
}

.plant-detail-param--link .plant-detail-param__value::after {
    content: " ›";
    color: var(--tg-hint);
    font-size: 16px;
    font-weight: 400;
}

.plant-detail-param__label {
    /* Единая типографика подписей с секционными (.pf-section__label): 11/700/0.06 */
    font-size: 11px;
    font-weight: 700;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.plant-detail-param__value {
    font-size: 14px;
    font-weight: 600;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
}

/* View-значение параметра плашкой (Тип/Передача) — вид выбранного чипа, некликабельный */
#screen-plant .ps-view-chip {
    display: inline-flex;
    align-items: center;
    /* Отступы между плашками — margin (как в edit): flex row-gap в этом WebView
       не работает, при переносе плашки слипались бы. Контейнеры #psStageView/
       #psDeliveryView гасят свой gap (ниже), чтобы горизонталь не удвоилась. */
    margin: 0 4px 4px 0;
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    /* Прозрачная рамка 1.5px — чтобы размер совпадал с edit-плашкой (.delivery-chip
       имеет border:1.5px), иначе view-плашка была бы на 3px мельче. */
    border: 1.5px solid transparent;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
}
/* Контейнеры view-плашек (Тип/Доставка): gap:0 — отступы даёт margin плашек;
   компенсируем нижний margin последнего ряда. */
#psStageView, #psDeliveryView {
    gap: 0;
    margin-bottom: -4px;
}

.plant-detail-description {
    font-size: 14px;
    line-height: 1.55;
    color: var(--tg-text);
    margin: 0 -10px;
    padding: 10px 12px 4px;
}

.plant-detail-description:not(:empty) {
    border-top: 1px solid var(--tint-neutral);
}

/* ===== Inline-edit поля (этап 2/3 слияния view+edit) =====
   ОБЩИЙ приём (класс .ps-inline-field, не id — чтобы подключать будущие поля
   тип/локация/передача): вид просмотра в обоих режимах, редактируемость edit
   показывает ТОЛЬКО тонкое нижнее подчёркивание. Никакого бокса (рамка/фон/
   радиус/паддинг убраны — перебивают общие #screen-plant input/textarea).
   border-bottom присутствует всегда (в view прозрачный) → лейаут не прыгает
   при флипе view↔edit; в edit — приглушённый, на фокусе — акцентный. */
#psTitle.plant-detail-title {
    font-size: 18px; font-weight: 700; line-height: 1.25;
}
#psDesc.plant-detail-description {
    font-size: 14px; line-height: 1.55;
    width: 100%; resize: none; overflow: hidden;   /* высоту ведёт JS (psAutosize) */
}
/* В edit пустое поле — видимая область ввода. КЛЮЧЕВОЕ: перебить
   `.plant-detail-description:empty { display:none }` (0,2,0) — пустой textarea
   matches :empty (value не создаёт дочерних узлов) и иначе скрыт в edit тоже.
   display:block (спец. 2,2,0) возвращает поле; min-height — «пол», psAutosize растит выше. */
#screen-plant[data-mode="edit"]   #psDesc.plant-detail-description,
#screen-plant[data-mode="create"] #psDesc.plant-detail-description { display: block; min-height: 40px; }
#screen-plant .ps-inline-field {
    background: transparent;
    border: none;
    border-bottom: 1px solid transparent;   /* резерв под подчёркивание — без прыжка */
    border-radius: 0;
    padding: 0 0 4px;
    min-height: 0;
    box-shadow: none;
    color: var(--tg-text);
    box-sizing: border-box;
    /* readonly-контрол не «серый мёртвый» */
    opacity: 1;
    -webkit-text-fill-color: currentColor;
}
/* EDIT/CREATE: приглушённое подчёркивание; фокус — акцент (чуть заметнее, без рефлоу) */
#screen-plant[data-mode="edit"]   .ps-inline-field,
#screen-plant[data-mode="create"] .ps-inline-field {
    border-bottom-color: var(--border-subtle);
}
#screen-plant[data-mode="edit"]   .ps-inline-field:focus,
#screen-plant[data-mode="create"] .ps-inline-field:focus {
    border-bottom-color: var(--accent);
    box-shadow: inset 0 -1px 0 0 var(--accent);
}

/* Крестик очистки названия (edit/create) — абсолютом справа строки названия */
.plant-detail-title-row { position: relative; }
#screen-plant[data-mode="edit"]   #psTitle.ps-inline-field,
#screen-plant[data-mode="create"] #psTitle.ps-inline-field { padding-right: 30px; }  /* место под крестик 28px */
/* Крестик очистки названия — единый вид с крестиком города (.gs-loc-btn[clear]):
   центрирован по вертикали, бокс 28×28, глиф 16×16, цвет --tg-hint. */
.ps-inline-clear {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 28px;
    height: 28px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    cursor: pointer;
    line-height: 1;
    opacity: 1;
    color: var(--tg-hint);   /* SVG stroke=currentColor — как крестик города */
}
.ps-inline-clear svg { width: 16px; height: 16px; }   /* единый крестик 16×16, как у города (clear) и auth-полей */
.ps-inline-clear:active { opacity: .6; }

.plant-detail-description:not(:empty)::before {
    content: "ОПИСАНИЕ";
    display: block;
    font-size: 11px;
    font-weight: 500;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 3px;
}

/* Блок описания: верхний разделитель + выравнивание по инсету ячеек (как
   .plant-detail-params). Пустое описание скрывается КЛАССОМ .is-empty (textarea
   всегда :empty — .value без дочерних узлов; тоггл в psFillViewData/psReset),
   и только в view — в edit/create блок всегда виден (подпись + поле ввода). */
.plant-detail-desc-block {
    border-top: 1px solid var(--tint-neutral);
    /* margin-top:0 — граница-разделитель прижата к низу инфо-сетки, чтобы
       вертикаль между Тип|Передача касалась нижней горизонтали. Отступ
       контента — паддингом (12px), а не margin. */
    margin: 0 -10px 0;
    padding: 10px 12px 0;   /* единый шаг над разделителем (ровно с seller/params) */
}
/* Инсет/разделитель теперь на блоке → у самой textarea гасим собственный
   bleed-margin (-10px) и верхнюю рамку, чтобы не задваивать. */
.plant-detail-desc-block .plant-detail-description { margin: 0; border-top: none; }
#screen-plant:not([data-mode="edit"]):not([data-mode="create"]) .plant-detail-desc-block.is-empty {
    display: none;
}

/* Блок продавца (отдельная карточка) */

/* Кнопки снизу: Написать + Забрать */
.plant-detail-actions {
    /* Постоянный бар действий, прижат к низу #screen-plant (positioned-предок на
       полную layout-высоту). ABSOLUTE, НЕ fixed — при открытой клавиатуре бар
       уходит к layout-низу ЗА клавиатуру, а не всплывает над ней (как .bottom-nav).
       Общий для edit/create ([Сохранить][Отмена]) и view (Забронировать/К сделке). */
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    gap: 10px;
    /* Градиентный фон transparent → --tg-bg: контент доскролливается ПОД кнопками
       с мягким затуханием (не сплошная панель). pointer-events:none на баре пускает
       тапы сквозь прозрачную зону к контенту; кнопки перекрывают auto (ниже).
       Низ фиксированный 10px; бар стоит НАД навигацией (safe-area даёт сам нав). */
    /* Равные внутренние отступы сверху/снизу вокруг кнопок (единый шаг 12px). */
    padding: 12px 12px;
    background: linear-gradient(to bottom, transparent 0%, var(--tg-bg) 38%);
    pointer-events: none;
}

.plant-detail-actions > button {
    pointer-events: auto;
}

.plant-chat-btn {
    flex-shrink: 0;
    padding: 13px 16px;
    border-radius: var(--radius-pill);
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-2);
    color: var(--text-primary);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    transition: 0.12s;
    white-space: nowrap;
}

.plant-chat-btn:active {
    background: var(--border-subtle);
    transform: scale(0.97);
}

/* .take-button слит с .primary-button (единый вид primary) — см. секцию
   «#screen-plant .primary-button». Отдельного стиля больше нет. */

/* Заблокированные кнопки формы (на время запроса) — видимо неактивны,
   не молчаливо мертвы. Реэнейбл снимается в finally psHandleSubmit. */
#screen-plant .primary-button:disabled,
#screen-plant .take-button:disabled,
#screen-plant .secondary-button:disabled {
    opacity: 0.55;
    cursor: default;
}

/* =========================
   ЕДИНЫЙ ЭКРАН РАСТЕНИЯ (ps-)
   ========================= */

/* Видимость по режиму */
.ps-edit-section { display: none; }

#screen-plant[data-mode="edit"]   .ps-edit-section,
#screen-plant[data-mode="create"] .ps-edit-section { display: block; }

/* View: скрыть edit-контролы с бОльшей специфичностью — иначе #screen-plant
   .delivery-chips {display:flex} (1,1,0) перебивает .ps-edit-section (0,1,0)
   и чипы Тип/Передача просвечивали бы в view. В edit/create селектор не матчится. */
#screen-plant:not([data-mode="edit"]):not([data-mode="create"]) .ps-edit-section { display: none !important; }

#screen-plant[data-mode="edit"]   .ps-view-section,
#screen-plant[data-mode="create"] .ps-view-section { display: none !important; }

/* Подсказка «Не знаете точное название?» под полем названия (edit/create) —
   свёрнуто строка-ссылка (пунктирное подчёркивание, без шеврона), тап разворачивает. */
.ps-title-hint { margin-top: 6px; }
.ps-title-hint__toggle {
    display: inline-flex;      /* иконка + текст по вертикальному центру (без съезда) */
    align-items: center;
    gap: 5px;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 13px;
    color: var(--accent);
    cursor: pointer;
    text-align: left;
    /* пунктир только под текстом — SVG-иконка (replaced) подчёркивание не рендерит */
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}
.ps-title-hint__icon { flex: 0 0 auto; }

/* Единое окно одобрения растения (admin.js showAdminApproveSheet) — центральная
   модалка gsModal: название + тип + листочки. Ширина на всю карточку модалки.
   margin-bottom — зазор до ряда кнопок (.gs-modal__actions — сосед после body),
   чтобы чипы «Листочки» не липли к «Отмена»/«Одобрить». Scoped, общий .gs-modal не трогаем. */
.admin-approve { display: flex; flex-direction: column; width: 100%; margin-bottom: 18px; }
.admin-approve__label {
    font-size: 13px;
    font-weight: 600;
    color: var(--tg-text);
    margin: 12px 0 6px;
}
.admin-approve__label:first-child { margin-top: 0; }
.admin-approve__namewrap { width: 100%; }   /* обёртка поля названия (.gs-caret-fix → CB каретки) */

/* Окно причины отклонения (admin.js showAdminRejectSheet) — центральная модалка
   gsModal, симметрично одобрению. Поле — textarea в обёртке .gs-caret-fix. */
.admin-reject { display: flex; flex-direction: column; width: 100%; margin-bottom: 18px; }
.admin-reject__wrap { width: 100%; }
.admin-reject__input { resize: none; min-height: 76px; line-height: 1.4; }
.admin-reject .gs-field-error { margin-top: 6px; }

/* Формы админ-модалок (эконом-редактор, «Изменить баланс») — центральная gsModal.
   Зазор до ряда кнопок — как в .admin-approve/.admin-reject. Поля в .gs-caret-fix. */
.admin-modal-form { display: flex; flex-direction: column; width: 100%; margin-bottom: 18px; }
.admin-modal-form__wrap { width: 100%; }
.admin-modal-form__hint { font-size: 12px; color: var(--tg-hint); margin-bottom: 6px; }
.admin-approve .gs-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }

/* Чипы Тип/Листочки НА БЕЛОМ фоне модалки — не должны сливаться (у .gs-chip фон ivory).
   Невыбранные: белый фон + чёткий бордер; выбранный: зелёный #5B7A39 + белый текст. */
.admin-approve .gs-chip {
    background: var(--surface-2);
    border-color: rgba(var(--border-field-rgb), 0.55);
    /* Крупнее для попадания пальцем (тип и листочки — одинаковая высота). */
    padding: 9px 14px;
    font-size: 15px;
}
.admin-approve .gs-chip--active {
    background: var(--accent);           /* #5B7A39 */
    border-color: var(--accent);
    color: var(--on-accent);
}

/* Листочки (0–5) — крупнее для попадания пальцем: 6 равных чипов на всю ширину
   ряда (flex:1), больше вертикальный padding и шрифт. Цифра по центру. */
.admin-approve #apLeaf { gap: 6px; }
.admin-approve #apLeaf .gs-chip {
    flex: 1 1 0;
    min-width: 0;
    padding: 10px 0;
    font-size: 16px;
    text-align: center;
}
.ps-title-hint__body {
    margin-top: 6px;
    font-size: 13px;
    line-height: 1.4;
    color: var(--tg-hint);
}

/* Кнопка-карандаш редактирования */
.ps-pencil-btn {
    background: none;
    border: none;
    padding: 2px 4px;
    cursor: pointer;
    font-size: 17px;
    flex-shrink: 0;
    opacity: 0.45;
    line-height: 1;
    -webkit-tap-highlight-color: transparent;
}

.ps-pencil-btn:active { opacity: 0.75; }

/* Строка название + бейдж в режиме редактирования */
.ps-edit-title-row {
    padding: 14px 16px 0;
}

/* Единый блок фото (view + edit): большое главное фото + миниатюры.
   Инсет как у .plant-detail-desc-block/ячеек (12px): подпись «Фото», главное
   фото и миниатюры выровнены по левому краю с «Город»/«Описание». */
.ps-photos {
    margin: 0 -10px;
    padding: 0 12px;
}


/* В edit/create режиме кнопки могут переносится (submit + save + delete) */
#screen-plant .plant-detail-actions {
    flex-wrap: wrap;
}

/* В edit/create кнопки [Отмена][Сохранить] переехали в sticky-голову сверху,
   нижнего бара нет → нижний резерв ставит psUpdateScrollPadding (--scroll-end-gap). */

/* ===== Баннер владельца (view-режим) ===== */
/* Цвета и форма берутся из pf-info-banner--* — здесь только позиционирование и кнопки */

/* Вертикальная раскладка: строка-статус сверху на всю ширину, кнопки —
   рядом ПОД текстом. Селектор .pf-info-banner.ps-owner-banner (0,2,0) —
   выше специфичности базового .pf-info-banner (0,1,0), который идёт ПОЗЖЕ в
   файле и иначе перебивал бы align-items:center → дети центрировались по
   горизонтали (в column cross-axis = горизонталь). Не трогая другие баннеры. */
.pf-info-banner.ps-owner-banner {
    margin: 0;   /* нижний зазор даёт padding-bottom обёртки #psStickyHead (опаковый) */
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 12px;             /* зазор строка статуса ↔ кнопки (единый 12px-ритм баннеров) */
    padding: 12px 14px;    /* чуть просторнее базовых 10px по вертикали */
    /* Скругление как у других блоков (radius-md из базового .pf-info-banner).
       Sticky перенесён на обёртку #psStickyHead (баннер + строка правки держатся
       единым блоком). position:relative — контекст для ::before-подложки (inset:0
       якорится к баннеру, а не к обёртке). Непрозрачную подложку/углы даёт ::before. */
    position: relative;
    /* Цвет статуса единым акцентом --banner-accent-rgb (R,G,B — задаёт модификатор):
       боковые полосы 5.25px (левая+правая) — плотный акцент (верх/низ без рамки).
       Фон везде белый (непрозрачная подложка ::before). ТОЛЬКО .ps-owner-banner
       (0,2,0) — другие .pf-info-banner (форм-ошибки) не трогаем. */
    border: none;
    border-left: 5.25px solid rgb(var(--banner-accent-rgb, 216, 216, 216));
    border-right: 5.25px solid rgb(var(--banner-accent-rgb, 216, 216, 216));
}

/* Акцент статуса (R,G,B) — единый источник фона/рамки/полосы (см. базовое правило).
   Цвет ТЕКСТА статуса не трогаем (оставляем как у бейджа карточки). Только
   owner-banner — глобальные .pf-info-banner--* (psFormError и др.) не трогаем. */
.ps-owner-banner.pf-info-banner--warn {
    --banner-accent-rgb: 125, 96, 54;        /* На модерации — охра = --status-pending (#7D6036), как бейдж */
    --banner-status-color: var(--status-pending-text);   /* цветом только название статуса */
}
.ps-owner-banner.pf-info-banner--ok {
    --banner-accent-rgb: 91, 122, 57;        /* Опубликовано — olive */
    --banner-status-color: var(--status-approved-text);
}
.ps-owner-banner.pf-info-banner--error {
    --banner-accent-rgb: 227, 42, 32;        /* Отклонено — красный */
    --banner-status-color: var(--status-rejected-text);
}
.ps-owner-banner.pf-info-banner--purple {
    --banner-accent-rgb: 121, 71, 166;       /* В брони — фиолетовый (= --status-purple #7947A6) */
    --banner-status-color: var(--status-purple-text);
}
.ps-owner-banner.pf-info-banner--done {
    --banner-accent-rgb: 52, 121, 70;        /* Завершено — зелёный = --status-approved (#347946), как completed-бейдж профиля */
    --banner-status-color: var(--status-approved-text);
}

/* Черновик/Скрыто (neutral): акцент — тёмно-серый (#8C8C8C → 140,140,140),
   как neutral-статус на плитке в профиле. Полоса серая, текст не переопределяем. */
.ps-owner-banner.pf-info-banner--neutral {
    --banner-accent-rgb: 140, 140, 140;   /* тёмно-серый (--banner-frame-strong #8C8C8C), как neutral на плитке */
}

/* Непрозрачная белая подложка — контент не просвечивает при sticky. Цвет статуса
   несут только рамка и левая полоса; фон везде белый. Рисуется в ::before (negative-z)
   — фон самого элемента был бы скрыт этим же ::before. Скруглена как баннер (inherit). */
.ps-owner-banner::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: var(--surface-2);
}


/* Шапка баннера: только строка статуса. ⋮ вынесена position:absolute (см. ниже),
   поэтому НЕ раздувает высоту шапки — кнопки поднимаются вплотную к тексту.
   padding-right — резерв под абсолютную ⋮, чтобы длинный статус не заходил под неё. */
.ps-owner-banner__head {
    align-self: stretch;
    padding-right: 30px;
}

/* ⋮ баннера — точь-в-точь как в профиле (.profile-settings-btn): SVG из трёх
   залитых кружков, тёмный (--brand-black) с opacity .6, absolute в правом углу. */
.ps-owner-banner__menu {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    cursor: pointer;
    line-height: 1;
    color: var(--text-primary);
    opacity: 0.6;
    transition: opacity 0.15s;
}
.ps-owner-banner__menu svg { display: block; }
.ps-owner-banner__menu:active { opacity: 0.3; }

.ps-owner-banner__text {
    align-self: stretch;   /* на всю ширину, чтобы text-align:left был виден */
    margin-bottom: 0;
    font-size: 13px;
    line-height: 1.4;
    text-align: left;
    color: var(--text-primary);   /* комментарий (не жирный) — чёрный; цвет только у названия статуса */
}

/* Кнопки баннера — компактнее нижнего бара (#psActions); ряд под текстом,
   по контенту слева. danger — красная ссылка на всю ширину отдельной строкой. */
.ps-owner-banner__actions {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-self: stretch;        /* на всю ширину баннера, чтобы центрирование было видно */
    justify-content: center;    /* кнопки по центру */
    gap: 8px;
}

.ps-owner-banner__btn {
    flex: 0 0 auto;
    padding: 8px 12px;
    border-radius: var(--radius-pill);
    font-size: 13px;
    font-weight: 500;
    /* secondary по умолчанию: белая с серой рамкой (как .secondary-button) */
    color: var(--text-primary);
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-2);
    cursor: pointer;
    white-space: nowrap;
    line-height: 1;
    transition: background 0.12s, transform 0.12s;
}
.ps-owner-banner__btn:active { background: var(--border-subtle); transform: scale(0.97); }

/* primary — ВСЕГДА зелёная (цвет не зависит от статуса/панели) */
.ps-owner-banner__btn--primary {
    color: var(--on-accent);
    font-weight: 600;
    border: none;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
}
.ps-owner-banner__btn--primary:active { background: linear-gradient(135deg, var(--accent), var(--accent-dark)); }

/* danger — красная ссылка на всю ширину отдельной строкой (как .danger-button) */
.ps-owner-banner__btn--danger {
    flex-basis: 100%;
    order: 2;
    padding: 6px 0;
    border: none;
    background: transparent;
    color: var(--danger);
    font-size: 13px;
    font-weight: 500;
    text-align: center;
    text-decoration: underline;
    text-decoration-color: rgba(227, 42, 32, 0.35);
    text-underline-offset: 2px;
}
.ps-owner-banner__btn--danger:active { background: transparent; transform: none; opacity: 0.55; }

/* Жирное слово-статус в тексте баннера */
.ps-owner-banner__text strong {
    font-weight: 700;
    color: var(--banner-status-color, var(--text-primary));   /* название статуса — в цвете статуса (neutral → чёрный) */
}

/* Оверлей успеха (поверх экрана, не ломает DOM формы) */
.ps-success-overlay {
    position: absolute;
    inset: 0;
    background: var(--tg-bg);
    z-index: 10;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

/* =========================
   МОИ СДЕЛКИ — СПИСОК
   ========================= */

/* Вкладки роли (Получаю / Отдаю) — стиль с подчёркиванием */

.deals-role-tabs {
    display: flex;
    border-bottom: 1px solid var(--border-subtle);
    flex-shrink: 0;
    margin-bottom: 2px;
}

.deals-role-tab {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 8px 10px;
    font-size: 15px;
    font-weight: 500;
    color: var(--tg-hint);
    text-align: center;
    cursor: pointer;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color 0.15s, border-color 0.15s;
}

.deals-role-tab.active {
    color: var(--accent);
    border-bottom-color: var(--accent);
    font-weight: 600;
}

.deals-role-tab__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--radius-pill);
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    background: var(--border-subtle);
    color: var(--tg-hint);
    transition: background 0.15s, color 0.15s;
}

.deals-role-tab.active .deals-role-tab__count {
    background: var(--accent);
    color: var(--on-accent);
}

/* Кастомный список фильтра в шите */

.gs-filter-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0 -4px;
}

.gs-filter-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background 0.15s;
    -webkit-tap-highlight-color: transparent;
}

.gs-filter-item:active {
    background: rgba(var(--tint-rgb), 0.05);
}

.gs-filter-item--active {
    background: rgba(91, 122, 57, 0.10);
}

.gs-filter-item__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.gs-filter-item__label {
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
}

.gs-filter-item--active .gs-filter-item__label {
    font-weight: 600;
    color: var(--accent);
}

.gs-filter-item__desc {
    font-size: 13px;
    color: var(--tg-hint);
}

.gs-filter-item__check {
    font-size: 17px;
    font-weight: 600;
    color: var(--accent);
    flex-shrink: 0;
    width: 20px;
    text-align: center;
}

/* Список и пустой стейт */

.deals-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 8px;   /* зазор под градиент .feed-toolbar::after — первая плитка не под фильтром */
    padding-bottom: var(--scroll-end-gap);
}

/* ── Единый компонент пустых состояний (empty states) ──────
   Три размера: default (lifecycle + кнопка), compact (no-results + ссылка),
   inline (одна строка). Без иконок-эмодзи. См. webapp/empty_state.js. */

.gs-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 48px 24px 32px;
    gap: 0;
}

.gs-empty-state__title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 8px;
}

.gs-empty-state__desc {
    font-size: 14px;
    color: var(--tg-hint);
    line-height: 1.45;
    margin-bottom: 20px;
    max-width: 260px;
}

.gs-empty-state__btn {
    padding: 13px 24px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 600;
    border: none;
    cursor: pointer;
    box-shadow: none;
}

/* compact — результат фильтра/поиска: тише заголовок, подсказка со ссылкой */
.gs-empty-state--compact {
    padding: 32px 16px;
    grid-column: 1 / -1; /* растянуть на всю ширину grid-стола */
}
.gs-empty-state--compact .gs-empty-state__title {
    font-size: 15px;
    font-weight: 500;
    color: var(--tg-hint);
    margin-bottom: 4px;
}
.gs-empty-state--compact .gs-empty-state__desc {
    margin-bottom: 0;
    max-width: none;
    line-height: 1.5;
}
.gs-empty-state__link {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.gs-empty-state__link:active {
    opacity: 0.6;
}

/* inline — одна строка (чат, история, уведомления, дропдаун) */
.gs-empty-state--inline {
    display: block;
    text-align: center;
    color: var(--tg-hint);
    font-size: 14px;
    padding: 32px 16px;
}
/* Чат — плейсхолдер центрируется по всей высоте области сообщений.
   Узел СТРОИТ setListState прямо в #chatMessages (host), отдельного #chatEmpty
   в разметке нет: он лежал ВНУТРИ host и уничтожался его же innerHTML="".
   display здесь, чтобы показ давал flex, а не block. */
.chat-messages > .gs-empty-state--inline {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

/* ── Скелетоны загрузки ────────────────────────────────────
   Заглушки формы контента: скелетон занимает тот же контейнер,
   что и данные → переход loading→data без сдвига. Приглушённый
   серый в тон surface + мягкий pulse по opacity (layout не трогает).
   Типы: plant-card (сетка стола/профиля), deal-row (сделки),
   line-row (листочки, уведомления). См. webapp/empty_state.js. */

.gs-skel {
    animation: gs-skel-pulse 1.4s ease-in-out infinite;
    pointer-events: none;
}

.gs-skel__box,
.gs-skel__line,
.gs-skel__thumb {
    background: var(--input-bg);
}

.gs-skel__line {
    height: 12px;
    border-radius: var(--radius-sm);
}

/* Карточка сетки: квадрат-картинка + 2 строки текста (как .plant-card) */
.gs-skel--plant-card {
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: 16px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}

.gs-skel--plant-card .gs-skel__box {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-lg);
    flex-shrink: 0;
}

/* Строка сделки: миниатюра + две строки + короткий хвост справа */
.gs-skel--deal-row {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 72px;
    padding: 0 12px;
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: var(--radius-lg);
}

.gs-skel--deal-row .gs-skel__thumb {
    width: 48px;
    height: 48px;
    border-radius: var(--radius-md);
    flex-shrink: 0;
}

/* Каркас карточки пользователя в профиле (только на время загрузки) */
.gs-skel--profile-card {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px;
    margin-bottom: 16px;
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: var(--radius-xl);
}

.gs-skel--profile-card .gs-skel__avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--input-bg);
    flex-shrink: 0;
}

/* Экран растения: фото 4/3 (форма .plant-detail-photo-main) + три строки */
.gs-skel--plant-detail {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 10px;
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-lg);
}

.gs-skel--plant-detail .gs-skel__box {
    width: 100%;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-sm);
}

/* Шапка сделки: квадрат 80×80 + две строки (форма .deal-info-card__plant) */
.gs-skel--deal-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
}

.gs-skel--deal-header .gs-skel__thumb {
    width: 80px;
    height: 80px;
    border-radius: var(--radius-md);
    flex-shrink: 0;
}

/* Простая строка: одна длинная + одна короткая линия */
.gs-skel--line-row {
    display: flex;
    align-items: center;
    height: 56px;
    padding: 0 4px;
}

.gs-skel__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

@keyframes gs-skel-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
    .gs-skel { animation: none; }
}

/* Горизонтальная карточка сделки */

/* ── Горизонтальная плитка сделки ──────────────────────────────
   Фото слева → инфо (flex:1, справа резерв 72px под листочки/статус) →
   листочки (absolute, по центру) + статус (absolute, верх-право). */
.deal-card {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px;
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: var(--radius-lg);
    cursor: pointer;
    min-width: 0;
    transition: transform 0.12s ease-out;
}
.deal-card:active { transform: scale(0.98); }

.deal-card__photo {
    flex-shrink: 0;
    width: 72px;
    height: 72px;
    border-radius: var(--radius-md);
    align-self: flex-start;   /* фото к верху → точка непрочитанного ложится на угол одинаково */
}
.deal-card__photo-img { width: 100%; height: 100%; object-fit: cover; }

.deal-card__info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Терминальные сделки (Получено/Отменено) — «этой сделки по сути больше нет».
   Гасим ТОЛЬКО фото и инфо; .deal-card__right (статус/листочки/дата) и шеврон
   остаются яркими и выныривают (тот же приём, что .plant-card--faded в профиле). */
.deal-card--faded .deal-card__photo,
.deal-card--faded .deal-card__info {
    opacity: 0.55;
}

/* Правый столбец: статус → листочки → дата, выравнивание по правому краю */
.deal-card__right {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    min-width: 0;
}
/* title-wrap переиспользован из плитки растения (2 строки, «…»); гасим его flex:1,
   чтобы в колонке инфо он не растягивался. */
.deal-card .plant-card__title-wrap { flex: 0 0 auto; }

.deal-card__city {
    font-size: 12px;
    color: var(--tg-hint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.deal-card__partner {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    margin-top: 2px;
    font-size: 12px;
    color: var(--text-primary);
}
.deal-card__partner-avatar { flex-shrink: 0; }
.deal-card__partner-name {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Листочки — в правом столбце */
.deal-card__leaves {
    font-size: 14px;
    font-weight: 700;
    white-space: nowrap;
    color: var(--text-primary);
}

/* Статус — solid-плашка в правом столбце (вид как profile plant-status-badge) */
.deal-card__status {
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    padding: 3px 8px;
    border-radius: var(--radius-pill);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--on-accent);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.deal-card__status--orange { background: var(--status-pending); }   /* Ожидает */
.deal-card__status--blue   { background: var(--status-reserved); }  /* В пути */
.deal-card__status--green  { background: var(--status-approved); }  /* Завершено */
.deal-card__status--gray   { background: rgba(0, 0, 0, 0.55); }     /* Отменено */

/* Бейдж статуса сделки */

.deal-status-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    border-radius: var(--radius-pill);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

.deal-status-badge--purple {
    background: rgba(175, 82, 222, 0.12);
    color: var(--status-purple);
}

.deal-status-badge--orange {
    background: rgba(255, 149, 0, 0.15);
    color: var(--status-pending);
}

.deal-status-badge--blue {
    background: rgba(0, 122, 255, 0.12);
    color: var(--status-reserved);
}

.deal-status-badge--green {
    background: rgba(91, 122, 57, 0.14);
    color: var(--status-approved);
}

.deal-status-badge--gray {
    background: rgba(var(--tint-rgb), 0.06);
    color: var(--tg-hint);
}

.deal-card__date {
    font-size: 11px;
    color: var(--tg-hint);
    white-space: nowrap;
}

/* Шеврон-намёк на переход в сделку (метрики как у .deal-more-chevron) */
.deal-card__chevron {
    flex: 0 0 auto;
    align-self: center;
    font-size: 22px;
    line-height: 1;
    color: var(--tg-hint);
}

/* Точка непрочитанных — левый-верхний угол фото (правый угол занят статусом) */
.deal-card__unread-dot {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 2;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--accent, #5B7A39);
    border: 2px solid var(--tg-secondary-bg);
}

/* Кликабельная строка параметра (например, переход в профиль) */
.deal-param--tappable {
    cursor: pointer;
    transition: background 0.15s ease;
}

.deal-param--tappable:active {
    background: rgba(91, 122, 57, 0.08);
}

/* Стрелка после имени партнёра — показывает что строка тапабельна */
.deal-partner-link::after {
    content: ' ›';
    color: var(--tg-hint);
    font-size: 15px;
}


/* =========================
   ЭКРАН СДЕЛКИ
   ========================= */

/* --- Прогресс --- */

/* Единая карточка: прогресс + статус + кнопка */

.deal-state-card {
    position: relative;   /* под абсолютное ⋮-меню */
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-md);
    flex-shrink: 0;
    overflow: hidden;
    /* Цветные боковые полосы по статусу — как у .ps-owner-banner (border-left/right в
       цвет статуса через --banner-accent-rgb; верх/низ БЕЗ акцента). Ширина 5.25px —
       та же, что у баннера растения (.ps-owner-banner). Значение rgb ставит inline
       renderProgress (deal_detail.js) из ЕДИНОГО getDealStatusMeta → цвет = бейджу
       списка. Дефолт (до установки) — серый. */
    border-left: 5.25px solid rgb(var(--banner-accent-rgb, 140, 140, 140));
    border-right: 5.25px solid rgb(var(--banner-accent-rgb, 140, 140, 140));
}

/* ⋮-меню сделки — в СТРОКЕ с комментарием (напротив хинта), не над прогрессом.
   Вид как .ps-owner-banner__menu (три кружка, тёмный с opacity). */
.deal-actions__menu {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    cursor: pointer;
    line-height: 1;
    color: var(--text-primary);
    opacity: 0.6;
    transition: opacity 0.15s;
}
.deal-actions__menu svg { display: block; }
.deal-actions__menu:active { opacity: 0.3; }

.deal-state-card__divider {
    height: 1px;
    background: rgba(var(--tint-rgb), 0.07);
    margin: 0 14px;
}

.deal-progress {
    display: flex;
    align-items: center;
    padding: 14px 16px 10px;
}

.deal-progress__step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    flex: 1;
}

.deal-progress__dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--border-subtle);
    border: 2px solid var(--border-subtle);
    transition: background 0.2s, border-color 0.2s;
}

/* Цвет ТЕКУЩЕГО шага = цвет статуса (единая палитра getDealStatusMeta):
   0 Бронь → фиолет, 1 Отправлено → синий, 2 Получено → зелёный. (Фикс: step1 был
   оранжевым, step2 синим.) */
.deal-progress__step[data-step="0"] { --step-color: var(--status-purple);   --step-glow: rgba(121, 71, 166, 0.25); }
.deal-progress__step[data-step="1"] { --step-color: var(--status-reserved); --step-glow: rgba( 61, 100, 143, 0.25); }
.deal-progress__step[data-step="2"] { --step-color: var(--status-approved); --step-glow: rgba( 52, 121, 70, 0.25); }
.deal-progress__step[data-step="3"] { --step-color: var(--status-approved); --step-glow: rgba( 52, 121, 70, 0.25); }

/* ГОТОВЫЕ шаги — зелёная точка с белой галочкой; линия к ним зелёная. */
.deal-progress__step--done .deal-progress__dot {
    background: var(--status-approved);
    border-color: var(--status-approved);
    position: relative;
}
.deal-progress__step--done .deal-progress__dot::after {
    content: "";
    position: absolute;
    left: 4px; top: 1px;
    width: 3px; height: 6px;
    border: solid var(--on-accent);
    border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
}

/* ТЕКУЩИЙ шаг — цвет статуса (--step-color); будущие — серый контур (дефолт .dot). */
.deal-progress__step--active .deal-progress__dot {
    background: var(--step-color);
    border-color: var(--step-color);
    box-shadow: 0 0 0 3px var(--step-glow);
}

.deal-progress__label {
    font-size: 11px;
    color: var(--tg-hint);
    white-space: nowrap;
    transition: color 0.2s, font-weight 0.2s;
}

.deal-progress__step--done .deal-progress__label {
    color: var(--status-approved);   /* готово — зелёный (как точка-галочка) */
    font-weight: 600;
}
.deal-progress__step--active .deal-progress__label {
    color: var(--step-color);        /* текущий — цвет статуса */
    font-weight: 600;
}

.deal-progress__line {
    flex: 1 1 auto;
    height: 2px;
    background: var(--border-subtle);
    margin: 0 4px;
    margin-bottom: 18px;
    border-radius: 1px;
    transition: background 0.2s;
}

.deal-progress__line--done {
    background: var(--status-approved);   /* пройденный участок — зелёный */
}

/* --- Финальный блок --- */

.deal-done-block {
    padding: 10px 14px 14px;
    text-align: center;
}

.deal-done-block__line {
    font-size: 14px;
    font-weight: 500;
}

.deal-done-block__line--ok     { color: var(--status-approved); }
.deal-done-block__line--cancel { color: var(--tg-hint); }

/* ============================
   УНИВЕРСАЛЬНЫЙ BOTTOM SHEET (GsSheet)
   ============================ */

/* ============================
   Полноэкранный лайтбокс с зумом (gsLightbox)
   z-index 10500 — выше sheet (10000), ниже toast/splash (99999).
   ============================ */

.gs-lightbox-overlay {
    position: fixed;
    inset: 0;
    z-index: 10500;
    background: rgba(0, 0, 0, 0.92);
    display: none;              /* flex ставит JS при open() */
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s ease;
    touch-action: none;
    overscroll-behavior: contain;
}

.gs-lightbox-overlay.visible {
    opacity: 1;
}

.gs-lightbox__img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    touch-action: none;
    will-change: transform;
    user-select: none;
    -webkit-user-select: none;
    -webkit-user-drag: none;
}

/* Стандартный кружок-контрол поверх изображений (лайтбокс И инлайн-фото):
   единый вид (кружок 44×44 + CSS-глиф, font-independent). Текстовые символы
   (✕ ‹ ›) в разметке скрыты (font-size:0), глиф рисуется бордером/штрихами →
   центрируется надёжно, не зависит от шрифта WebView. Позиции — в контекстных
   классах (лайтбокс — по краям экрана; инлайн — по краям фото). Новые
   кружки-контролы над фото заводить через этот класс. */
.gs-img-ctrl {
    position: absolute;
    z-index: 1;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.45);
    font-size: 0;               /* прячет текстовый глиф в разметке */
    line-height: 1;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}

/* --- глиф-chevron стрелок (border-top+border-left, поворот) --- */
.gs-img-ctrl--prev::before,
.gs-img-ctrl--next::before {
    content: "";
    display: block;
    width: 11px;
    height: 11px;
    border-top: 2.5px solid var(--on-accent);
    border-left: 2.5px solid var(--on-accent);
}
/* translateX компенсирует оптический вынос «остриё» chevron за геометрический центр */
.gs-img-ctrl--prev::before { transform: translateX(2px) rotate(-45deg); }
.gs-img-ctrl--next::before { transform: translateX(-2px) rotate(135deg); }

/* nav-кнопки лайтбокса показываются по JS (refreshNav) — display управляется JS */
.gs-lightbox__nav { display: none; }

/* --- глиф-крест close (два штриха ±45°, тем же приёмом) --- */
.gs-lightbox__close::before,
.gs-lightbox__close::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 18px;
    height: 2.5px;
    background: var(--on-accent);
    border-radius: 1px;
}
.gs-lightbox__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.gs-lightbox__close::after  { transform: translate(-50%, -50%) rotate(-45deg); }

/* --- позиции --- */
.gs-lightbox__close { top: calc(env(safe-area-inset-top, 0px) + 12px); right: 12px; }
.gs-lightbox__nav   { top: 50%; transform: translateY(-50%); }
.gs-lightbox__nav--prev { left: calc(env(safe-area-inset-left, 0px) + 8px); }
.gs-lightbox__nav--next { right: calc(env(safe-area-inset-right, 0px) + 8px); }

.gs-lightbox__counter {
    position: absolute;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 1;
    display: none;              /* показ управляется JS (refreshNav) */
    padding: 4px 12px;
    border-radius: var(--radius-pill);
    background: rgba(0, 0, 0, 0.45);
    color: var(--on-accent);
    font-size: 13px;
    line-height: 1.4;
}

/* Формовые классы .gs-sheet-* (label/input/textarea) остались от компонента
   нижнего шита (удалён в фазе 3) — переиспользуются контентом центральной
   модалки gsModal. Оболочка шита (.gs-sheet-overlay/.gs-sheet/__*/-btn) удалена. */

/* Подпись внутри контента */
.gs-sheet-label {
    font-size: 13px;
    color: var(--tg-hint);
    text-align: center;
    margin-bottom: 10px;
}

/* Текстовые поля ввода */
.gs-sheet-input {
    width: 100%;
    box-sizing: border-box;
    padding: 12px 14px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-size: 15px;
    font-family: inherit;
    background: var(--surface-2);
    color: var(--text-primary);
    outline: none;
    transition: border-color 0.15s;
    -webkit-appearance: none;
    display: block;
}

.gs-sheet-input:focus {
    border-color: var(--accent);
}

/* Тумблер начислить/списать в админском шите изменения баланса */
.gs-leaf-adjust__toggle {
    display: flex;
    gap: 8px;
}
.gs-leaf-adjust__sign {
    flex: 1;
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    background: var(--surface-2);
    color: var(--tg-hint);
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.gs-leaf-adjust__sign.selected {
    border-color: var(--accent);
    color: var(--accent);
    background: rgba(91, 122, 57, 0.10);
    font-weight: 600;
}
.gs-leaf-adjust__error {
    margin-top: 8px;
    min-height: 16px;
    font-size: 13px;
    color: var(--brand-red);
}

/* Textarea */
.gs-sheet-textarea {
    width: 100%;
    min-height: 90px;
    padding: 12px 14px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-size: 15px;
    font-family: inherit;
    resize: none;
    box-sizing: border-box;
    background: var(--surface-2);
    color: var(--text-primary);
    outline: none;
    transition: border-color 0.15s;
    display: block;
}

.gs-sheet-textarea:focus {
    border-color: var(--accent);
}

/* Список опций (pickOption → _adminPickOptionModal) */
.gs-options-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 4px 0;
}

.gs-option-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 0.12s, background 0.12s;
}

.gs-option-item.selected {
    border-color: var(--accent);
    background: rgba(91, 122, 57, 0.06);
}

.gs-option-item:active:not(.selected) {
    background: var(--surface-1);
}

.gs-option-dot {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 2px solid var(--border-subtle);
    flex-shrink: 0;
    transition: border-color 0.12s, background 0.12s;
}

.gs-option-item.selected .gs-option-dot {
    border-color: var(--accent);
    background: var(--accent);
}

.gs-option-item__label {
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
}

.gs-option-item__desc {
    font-size: 12px;
    color: var(--tg-hint);
    margin-top: 2px;
}

/* Дни — пресеты (pickDays) */
.gs-days-presets {
    display: flex;
    gap: 8px;
    margin-bottom: 12px;
}

.gs-days-preset {
    flex: 1;
    padding: 11px 8px;
    border: 1.5px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    text-align: center;
    color: var(--text-primary);
    transition: border-color 0.12s, background 0.12s, color 0.12s;
}

.gs-days-preset.selected {
    border-color: var(--accent);
    background: rgba(91, 122, 57, 0.06);
    color: var(--accent);
}

.gs-days-preset:active:not(.selected) {
    background: var(--surface-1);
}

.deal-page {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    gap: 10px;
    padding: 8px 12px 0;   /* h-инсет 12 на контенте сделки (карточки/чат) */
}

/* ── Состояния экрана сделки (loading/data/error) ──────────────
   #tab-deal-detail — ПЕРЕИСПОЛЬЗУЕМЫЙ статичный экран: его разметка не
   пересоздаётся, а узлы захвачены в модульные const (deal_detail.js).
   Поэтому setListState сюда направлять НЕЛЬЗЯ (он делает innerHTML="" и
   уничтожил бы эти узлы). Состояние переключается data-атрибутом, а
   скелетон и error живут отдельными узлами-сиблингами. */

#dealSkeleton,
#dealErrorState {
    display: none;
}

.deal-page[data-state="loading"] > .deal-info-card,
.deal-page[data-state="loading"] > .deal-state-card,
.deal-page[data-state="loading"] > .deal-chat-container,
.deal-page[data-state="error"]   > .deal-info-card,
.deal-page[data-state="error"]   > .deal-state-card,
.deal-page[data-state="error"]   > .deal-chat-container {
    display: none;
}

.deal-page[data-state="loading"] > #dealSkeleton {
    display: block;
}

.deal-page[data-state="error"] > #dealErrorState {
    display: block;
}

/* Карточки-обёртки скелетона повторяют геометрию реальных (без сдвига) */
.deal-skel-card {
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: var(--radius-lg);
    margin-bottom: 10px;
    padding: 4px 0;
}

/* Единый блок: растение + партнёр + доставка */

.deal-info-card {
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-lg);
    border: var(--card-border);
    box-shadow: var(--shadow-card);
    flex-shrink: 0;
    overflow: hidden;
    /* Вся плитка кликабельна (→ карточка растения). Press-фидбек тем же приёмом,
       что .deal-param--tappable: лёгкий оливковый тон подложки, без scale/сдвигов. */
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s ease;
}
.deal-info-card:active {
    background: rgba(91, 122, 57, 0.08);
}

/* Инфо-карточка сделки — по образцу детали растения: фото слева (к верху), колонка
   (название+тип, город, участник), листочки справа по центру. Без статус-плашки. */
.deal-info-card__row {
    display: flex;
    gap: 12px;
    padding: 12px;
    align-items: flex-start;   /* фото и колонка выравниваются к верху */
}

.deal-info-photo {
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    flex-shrink: 0;
}
.deal-info-photo:active { opacity: 0.7; }

.deal-plant-photo-wrapper {
    width: 76px;
    height: 76px;
    border-radius: var(--radius-md);
    flex-shrink: 0;
    overflow: hidden;
}

.deal-plant-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Название + тип инлайн (жирное + серый), до 2 строк с «…». */
.deal-plant-title {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.deal-plant-type {
    font-weight: 400;
    color: var(--tg-hint);
    text-transform: lowercase;
    font-size: 14px;             /* название рядом 16px → тип чуть мельче */
}

.deal-plant-meta {
    font-size: 13px;
    color: var(--tg-hint);
}

/* Участник — под городом: аватар + имя + шеврон, кнопка, без разделителя. */
.deal-partner-inline {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 2px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    text-align: left;
    max-width: 100%;
}
.deal-partner-inline:active { opacity: 0.6; }
.deal-partner-avatar {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    display: block;
}
.deal-partner-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.deal-partner-chevron {
    font-size: 18px;
    color: var(--tg-hint);
    line-height: 1;
    flex-shrink: 0;
}

/* Листочки — справа, по центру по вертикали. */
.deal-plant-leaves {
    font-size: 14px;
    font-weight: 700;
    color: var(--tg-hint);
    flex-shrink: 0;
    white-space: nowrap;
    align-self: center;
}

/* Шеврон «открыть растение» — у правого края строки, по центру по вертикали.
   Вся плитка кликабельна (onclick .deal-info-card → растение), шеврон лишь индикатор:
   клик по нему всплывает к секции. align-self:center центрирует его в строке, не трогая
   верхнее выравнивание фото/колонки (.deal-info-card__row align-items:flex-start). */
.deal-more-chevron {
    flex: 0 0 auto;
    align-self: center;
    font-size: 22px;
    line-height: 1;
    color: var(--tg-hint);
}

/* Сохранён для админ-детали растения (admin.js), где ещё используется. */
.deal-info-card__divider {
    height: 1px;
    background: rgba(var(--tint-rgb), 0.07);
    margin: 0 12px;
}



/* Плейсхолдер пустого чата */

/* .chat-empty унифицирован в .gs-empty-state--inline (.chat-messages > …, см. выше) */

/* Блок статуса + действий */

.deal-status-hint {
    font-size: 13px;
    color: var(--tg-hint);
    margin: 0;
    text-align: center;
}

.deal-plant-busy {
    font-size: 13px;
    color: var(--tg-hint);
    margin: 0;
    text-align: center;
}

/* Одна строка: подсказка (hint) слева, кнопка + ⋮ справа. Отмена ушла в ⋮-меню. */
.deal-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    padding: 12px 14px 14px;
}
.deal-status-hint,
.deal-plant-busy {
    flex: 1;
    min-width: 0;
    text-align: left;
    margin: 0;
}

/* Отмена — вторичная пилюля с красным текстом (secondary баннера + --danger). */
.deal-actions__cancel {
    flex: 0 0 auto;
    padding: 8px 12px;
    border-radius: var(--radius-pill);
    font-size: 13px;
    font-weight: 500;
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-2);
    color: var(--danger);
    cursor: pointer;
    white-space: nowrap;
    line-height: 1;
    text-decoration: none;
    transition: background 0.12s, transform 0.12s;
}
.deal-actions__cancel:active {
    background: var(--border-subtle);
    transform: scale(0.97);
}

/* Primary («Отправил»/«Получил») — акцентная пилюля (как .ps-owner-banner__btn--primary). */
.deal-btn {
    flex: 0 0 auto;
    padding: 8px 12px;
    border-radius: var(--radius-pill);
    font-size: 13px;
    font-weight: 600;
    border: none;
    cursor: pointer;
    white-space: nowrap;
    line-height: 1;
    color: var(--on-accent);
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    transition: transform 0.12s ease-out;
}
.deal-btn:active,
.deal-btn--primary:active {
    transform: scale(0.97);
}
.deal-btn--primary {
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
}

.deal-chat-title {
    position: absolute;
    top: 8px;
    left: 10px;
    font-size: 11px;
    font-weight: 700;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    pointer-events: none;
    z-index: 1;
}

.deal-chat-container {
    position: relative;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
/* ===== Чат сделки ===== */

.chat-messages {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Единственный скроллер экрана: рубер-бэнд не уходит в документ, вертикальный пан
       разрешён (при залоченном скролле документа — core.css). */
    overscroll-behavior: contain;
    touch-action: pan-y;

    background: var(--tg-secondary-bg);
    /* Композер теперь В ПОТОКЕ (не fixed) — нижний резерв не нужен. */
    padding: 10px;
    border-radius: var(--radius-md);

    display: flex;
    flex-direction: column;
    gap: 6px;
}

.chat-input-bar {
    /* Композер В ПОТОКЕ: последний flex-элемент .deal-chat-container (после ленты
       .chat-messages flex:1). Клавиатура открыта → layout сжимается
       (interactive-widget=resizes-content, viewport-meta) → колонка укорачивается,
       композер встаёт над клавиатурой БЕЗ JS. Ширина/центр — от .page-inner (480px). */
    flex: 0 0 auto;
    box-sizing: border-box;
    background: var(--tg-bg);
    /* Без safe-area снизу: закрыта клавиатура → нав снизу держит home-индикатор;
       открыта → индикатора нет. Иначе композер стоял слишком далеко от нижней панели.
       Низ 12px против верха 6px — компенсация: 51px-резерв .page-inner ставит бар
       вплотную на нав, и симметричные 6px читались бы поджато. При открытой клавиатуре
       добавка снимается (правило ниже) — поле стоит вплотную над клавиатурой. */
    padding: 6px 0 12px;
}

/* Клавиатура открыта → нав скрыт, компенсация низа не нужна: поле вплотную над клавиатурой. */
body.gs-kb-open.page--deal-detail-active .chat-input-bar {
    padding-bottom: 6px;
}

/* Клавиатура открыта → скрыть инфо/прогресс-карточки: чат занимает всю высоту, верх
   не режется. ЧИСТО CSS по классу глобального детектора (фокус не роняет). */
body.gs-kb-open .deal-info-card,
body.gs-kb-open .deal-state-card {
    display: none;
}
/* Чистый верх чата при печати: отступ от края экрана — видны верхние закругления
   белой карточки ленты (.chat-messages скруглена --radius-md), не впритык к статус-бару. */
body.gs-kb-open.page--deal-detail-active .deal-chat-container {
    margin-top: 8px;
}


/* Базовый пузырь */

.chat-message {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;

    max-width: 80%;
    padding: 8px 10px;
    border-radius: var(--radius-md);
    font-size: 14px;
    line-height: 1.35;

    word-wrap: break-word;
    word-break: break-word;
}

/* мои сообщения — справа, контент внутри тоже вправо */

.chat-message--me {
    align-self: flex-end;
    align-items: flex-end;

    background: var(--accent-dark);
    color: var(--on-accent);
}

/* чужие сообщения — слева */

.chat-message--other {
    align-self: flex-start;
    background: var(--tint-neutral);
    color: var(--tg-text);
}

/* системное сообщение о переходе статуса */

.chat-system-msg {
    align-self: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    background: rgba(var(--accent-rgb), 0.08);
    border-radius: var(--radius-sm);
    padding: 5px 14px;
    margin: 6px 0 2px;
    flex-shrink: 0;
    text-align: center;
    max-width: 80%;
}

.chat-system-msg__text {
    font-size: 12px;
    color: var(--tg-hint);
}

.chat-system-msg__time {
    font-size: 11px;
    color: var(--tg-hint);
    opacity: 0.7;
}

/* разделитель даты */

.chat-date-sep {
    align-self: center;
    font-size: 12px;
    color: var(--tg-hint);
    background: var(--tint-neutral-weak);
    border-radius: var(--radius-pill);
    padding: 3px 10px;
    margin: 4px 0;
    flex-shrink: 0;
}

/* время внутри пузыря */

.chat-message__time {
    font-size: 11px;
    opacity: 0.7;
    margin-top: 2px;
    align-self: flex-end;
}

/* Инпут */

.chat-input-row {
    display: flex;
    align-items: stretch;
    gap: 8px;
}

.chat-input {
    flex: 1;
    padding: 10px 14px;
    font-size: 15px;
    line-height: 1.3;

    border-radius: var(--radius-pill);
    border: 1px solid var(--border-subtle);

    background: var(--surface-2);
    color: var(--tg-text);

    outline: none;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.chat-input::placeholder {
    color: var(--tg-hint);
}

.chat-input:focus {
    border-color: var(--accent);
    box-shadow: 0 2px 8px rgba(var(--accent-rgb), 0.25);
}

.chat-send-btn {
    width: 42px;
    flex: 0 0 auto;
    border: none;

    border-radius: var(--radius-pill);

    display: flex;
    align-items: center;
    justify-content: center;

    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);

    font-size: 20px;
    font-weight: 600;

    cursor: pointer;
    transition: transform 0.12s;
}

.chat-send-btn:active {
    transform: scale(0.95);
}

/* ====== TOPBAR ====== */

.topbar-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;

    display: flex;
    justify-content: center;
    align-items: flex-end;

    height: var(--app-header-height);
    z-index: 1000;

    background: var(--tg-bg);
    border-bottom: 1px solid var(--tg-secondary-bg);
}

.topbar {
    width: 100%;
    max-width: 480px;
    /* Отступ строки бренда/кнопок от верха — с учётом выреза (standalone-PWA) и в
       браузере. Было 16px → над брендом оставалось много воздуха; 8px делает шапку
       компактнее (высота ~94px), бренд не липнет к верху. env(safe-area-inset-top)
       сохраняем — под вырезом отступ остаётся. Низ 10→8 — симметрично. */
    padding: calc(env(safe-area-inset-top, 0px) + 8px) 12px 8px;
}

.topbar-brand {
    text-align: center;
    font-size: 24px;
    font-weight: 700;
    margin-bottom: 6px;
    color: var(--text-primary);
    position: relative;

    margin-top: 4px; /* можно 0–6, но НЕ 20 */
}

/* Вторая строка (если используется) — заголовок страницы, баланс и т.п. */
.topbar-line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    /* Подъём блока заголовка ближе к строке бренда: бренд (24px) центрируется в
       строке высотой 38px (кнопки ←/☰) → под ним ~7px leading; −4px убирает лишний
       зазор. Верхний край шапки и горизонтальный инсет 12px не трогаем. */
    margin-top: -4px;
    /* Без доп. инсета: заголовок/пилюля выровнены по контентной сетке 12px
       (padding .topbar) — в линию с карточками стола и краями кнопок ←/☰.
       Прежние 8px (выравнивание по центру глифа) уводили их на 20px, вразрез
       с контентом. */
}

.topbar-back-btn {
    flex-shrink: 0;
    /* Резервируем место под кнопку всегда — даже когда её не видно (visibility:hidden),
       чтобы заголовок не сдвигался при появлении/исчезновении «Назад». */
    min-width: 24px;
    background: none;
    border: none;
    padding: 0 4px 0 0;
    font-size: 28px;
    line-height: 1;
    color: var(--accent);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.topbar-title-wrapper {
    flex: 1 1 auto;
    min-width: 0;
    /* Лёгкое появление заголовка при смене экрана — скрывает момент перерисовки */
    animation: gsTitleFade 150ms ease;
}

@keyframes gsTitleFade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.topbar-page-title {
    font-size: 20px;
    font-weight: 700;
    /* Manrope даёт больший leading, чем системный шрифт: line-height:normal раздувал
       строчный бокс до 28px (у системного — 24px) → над «Стол» появлялся лишний
       зазор под строкой бренда. 1.2 = бокс 24px, компактность как на системном. */
    line-height: 1.2;
    margin: 0 0 2px;
    color: var(--text-primary);

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.topbar-page-subtitle {
    font-size: 13px;
    color: var(--tg-hint);

    /* Резерв под одну строку: подзаголовок, появляющийся во второй фазе рендера
       (роль сделки, статус растения), не сдвигает заголовок по вертикали. */
    min-height: 18px;

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.topbar-balance {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 3px;
    margin-left: 12px;

    background: var(--surface-2);
    border: 1px solid rgba(var(--accent-rgb), 0.35);
    border-radius: var(--radius-pill);
    padding: 4px 8px 4px 10px;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.12s ease;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.topbar-balance:active {
    background: rgba(var(--accent-rgb), 0.08);
    transform: scale(0.96);
}

.topbar-balance-icon {
    font-size: 16px;
    /* Центрируем svg внутри спана → vertical-align детей (у листа .gs-leaf -0.12em,
       у колокола .gs-icon middle) не влияет: лист и колокол на одном уровне.
       Только плашка баланса; инлайн-в-тексте суммы/цена не затронуты. */
    display: flex;
    align-items: center;
}

.topbar-balance-value {
    font-size: 15px;
    font-weight: 600;
    color: var(--tg-text);
}

.topbar-balance-arrow {
    font-size: 18px;
    line-height: 1;
    color: var(--accent, #5B7A39);
    font-weight: 400;
    margin-left: 1px;
}

/* Верхняя строка топбара: [← назад] | [🌿 GreenSwap 🌿] | [☰ меню].
   Grid auto|1fr|auto — бренд по центру независимо от видимости «Назад». */
.topbar-top {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 8px;
    /* Строка бренда/кнопок вплотную к заголовку: заголовок не двигаем (его отступы
       не трогаем) — сокращаем именно зазор между двумя строками шапки. */
    margin-bottom: 0;
}
.topbar-top .topbar-brand { margin: 0; }

/* Парные круглые кнопки ← и ☰ (одинаковые). */
.topbar-circle-btn {
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--accent);
    cursor: pointer;
    position: relative;
    box-shadow: none;
    transition: background 0.15s ease, transform 0.12s ease;
    padding: 0;
}
.topbar-circle-btn:active {
    /* Лёгкий фидбек нажатия — временный, не постоянная плашка. */
    background: rgba(var(--accent-rgb), 0.12);
    transform: scale(0.94);
}
/* Красная точка непрочитанных на ☰. */
.topbar-menu-dot {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--brand-red);
    border: 1.5px solid var(--on-accent);
    box-sizing: border-box;
}
.topbar-menu-dot[data-zero="true"] { display: none; }

/* ── Меню-drawer (☰) ─────────────────────────────────────────────── */
.gs-mainmenu-overlay {
    position: fixed;
    inset: 0;
    z-index: 10800;            /* выше топбара (1000) и контента; ниже лайтбокса (10500? см. ниже) */
    display: none;
}
.gs-mainmenu-overlay.visible { display: block; }
/* Во время закрытия (display ещё block, но класс снят) не перехватываем клики —
   иначе гаснущая шторка блокировала бы модалку подтверждения выхода. */
.gs-mainmenu-overlay:not(.visible) { pointer-events: none; }
.gs-mainmenu-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    opacity: 0;
    transition: opacity 0.25s ease;
}
.gs-mainmenu-overlay.visible .gs-mainmenu-backdrop { opacity: 1; }
.gs-mainmenu-panel {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 78%;
    max-width: 300px;
    background: var(--surface-3);
    box-shadow: -8px 0 28px rgba(0, 0, 0, 0.18);
    display: flex;
    flex-direction: column;
    padding: calc(env(safe-area-inset-top, 0px) + 16px) 8px calc(env(safe-area-inset-bottom, 0px) + 16px);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform 0.25s ease;
}
.gs-mainmenu-overlay.visible .gs-mainmenu-panel { transform: translateX(0); }

.gs-mainmenu-item {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    padding: 14px 12px;
    background: none;
    border: none;
    border-radius: var(--radius-md);
    text-align: left;
    cursor: pointer;
    color: var(--text-primary);
    transition: background 0.12s ease;
}
.gs-mainmenu-item:active { background: rgba(var(--accent-rgb), 0.08); }
.gs-mainmenu-item__icon {
    flex-shrink: 0;
    display: inline-flex;
    color: var(--accent);
}
.gs-mainmenu-item__label {
    flex: 1;
    min-width: 0;
    font-size: 16px;
    font-weight: 600;
}
.gs-mainmenu-item__right {
    flex-shrink: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--accent);
    display: inline-flex;
    align-items: center;
}
.gs-mainmenu-item__badge {
    flex-shrink: 0;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--danger);
    color: var(--on-accent);
    font-size: 12px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.gs-mainmenu-item__badge[data-zero="true"] { display: none; }
.gs-mainmenu-item--danger { color: var(--danger); }
.gs-mainmenu-item--danger .gs-mainmenu-item__icon { color: var(--danger); }

/* Тонкий inset-разделитель между группами пунктов (зеркалит .gs-menu__divider). */
.gs-mainmenu-divider {
    height: 0.5px;
    background: var(--border-subtle);
    margin: 6px 12px;
}
/* Толстый разделитель-полоса перед «Выйти» — отбивка фоном, как spacer в меню профиля. */
.gs-mainmenu-spacer {
    height: 8px;
    margin: 6px -8px;
    background: rgba(var(--tint-rgb), 0.045);
    border-top: 0.5px solid var(--border-subtle);
    border-bottom: 0.5px solid var(--border-subtle);
}
/* Футер меню — прижат к низу панели: лист + версия по центру. */
.gs-mainmenu-footer {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    padding-top: 20px;
    padding-bottom: 4px;
}
/* Фирменный лист — крупно, приглушённо-оливковый. */
.gs-mainmenu-footer__leaf {
    line-height: 0;
    color: var(--accent);
    opacity: 0.3;
}
/* Номер версии — приглушённый, по центру под листом. */
.gs-mainmenu-version {
    text-align: center;
    font-size: 12px;
    color: var(--tg-hint);
    font-family: var(--font-mono);   /* тех-подпись версии — моноширинный акцент */
}


/* =======================================================
   ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ
   ======================================================= */

.profile-page {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px var(--scroll-end-gap);   /* h-инсет 12 на контенте (скроллер — .tab--active — во всю ширину) */
}

.profile-user-card {
    display: flex;
    flex-direction: column;
    padding: 12px 14px;
    background: var(--surface-2);
    border-radius: var(--radius-lg);
    border: var(--card-border);
    box-shadow: var(--shadow-card);
    position: relative;
}

.profile-edit-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    background: none;
    border: none;
    font-size: 14px;
    cursor: pointer;
    padding: 4px;
    line-height: 1;
    opacity: 0.55;
    transition: opacity 0.15s;
}
.profile-edit-btn:active { opacity: 0.3; }

/* Кнопка меню (три точки) в шапке своего профиля */
.profile-settings-btn {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    line-height: 1;
    color: var(--text-primary);
    opacity: 0.6;
    transition: opacity 0.15s;
}
.profile-settings-btn svg { display: block; }
.profile-settings-btn:active { opacity: 0.3; }

/* Список действий в GsSheet (меню профиля) */
.profile-action-list {
    display: flex;
    flex-direction: column;
    margin: 0 -4px;
}

.profile-action-item {
    display: block;
    width: 100%;
    padding: 14px 4px;
    background: none;
    border: none;
    text-align: left;
    font-size: 16px;
    color: var(--text-primary);
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.06);
    transition: opacity 0.12s;
}
.profile-action-item:last-child { border-bottom: none; }
.profile-action-item:active { opacity: 0.45; }

.profile-action-item--danger { color: var(--brand-red); }

.profile-action-divider {
    height: 1px;
    background: var(--border-subtle);
    margin: 4px 0;
}

/* ===== Анкорное поповер-меню ⋮ (gsMenu, menu.js) ===== */
/* Замена нижнего шита для контекстных меню: открывается у кнопки, без затемнения. */
.gs-menu-backdrop {
    position: fixed;
    inset: 0;
    background: transparent;   /* ловушка внешнего тапа, экран НЕ темнеет */
    z-index: 999;
    /* Тап поглощается целиком: без 300мс-задержки клика и без подсветки backdrop. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
.gs-menu {
    position: fixed;
    min-width: 180px;
    max-width: 240px;
    background: var(--surface-3);
    border: 0.5px solid rgba(var(--tint-rgb), 0.1);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
    overflow: hidden;
    z-index: 1000;
    transform-origin: top right;   /* растёт из угла у ⋮ */
    animation: gsMenuIn 0.12s ease-out;
}
@keyframes gsMenuIn {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: scale(1); }
}
.gs-menu__item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    padding: 13px 14px;
    font-size: 15px;
    color: var(--text-primary);
    cursor: pointer;
    border-bottom: 0.5px solid rgba(var(--tint-rgb), 0.06);
    transition: opacity 0.12s;
}
.gs-menu__item:last-child { border-bottom: none; }
.gs-menu__item:active { opacity: 0.45; }
.gs-menu__item--danger { color: var(--danger); }
.gs-menu__item-label { flex: 1; min-width: 0; }
.gs-menu__item--active { font-weight: 600; }
.gs-menu__item-check { flex-shrink: 0; color: var(--accent); font-weight: 700; }
.gs-menu__divider {
    height: 0.5px;
    background: var(--border-subtle);
}

/* Режим «панель» (gsMenu.openPanel) — произвольный контент (фильтр Стола).
   Ширину/max-height ставит JS; снимаем list-ограничения базового .gs-menu. */
.gs-menu--panel {
    max-width: none;
    overflow: visible;   /* дропдаун города escape-ит клиппинг панели */
    transform-origin: top right;
}
.gs-menu-panel__content {
    padding: 12px;
}
/* Внутри панели: заголовки секций/город работают как в модале.
   Убираем нижний bleed последней секции. */
.gs-menu--panel .feed-filter-section:last-of-type { margin-bottom: 0; }

/* Шапка панели фильтра: заголовок + крестик закрытия (отмена). */
.gs-filter-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 10px;
}
.gs-filter-panel__title {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
}
.gs-filter-panel__close {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    margin: -6px -6px -6px 0;   /* tap-таргет крупнее, не раздувая шапку */
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--tg-hint);
    cursor: pointer;
    border-radius: var(--radius-pill);
    transition: opacity 0.15s;
}
.gs-filter-panel__close:active { opacity: 0.35; }
.gs-filter-panel__close svg { display: block; }

/* Крестик очистки поля города — абсолютом справа внутри .feed-city-wrap. */
#feedFilterPanel #cityInput { padding-right: 34px; }
.gs-city-clear {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--tg-hint);
    cursor: pointer;
    z-index: 2;
}
.gs-city-clear:active { opacity: 0.4; }
.gs-city-clear svg { display: block; }
/* Кнопки футера панели мельче, чем в полноэкранном модале (scoped — другие
   .feed-btn не задеты). Вид secondary/primary сохранён. */
#feedFilterPanel .feed-modal__footer .feed-btn {
    padding: 8px 14px;
    min-height: 0;
    font-size: 14px;
}

/* Generic-чип (Тип/Доставка в фильтре) — метрики .delivery-chip, но без
   #screen-plant-scope. Мультивыбор, active залит акцентом. */
.gs-chip {
    display: inline-block;
    /* Компактные метрики как у чипа формы растения (#screen-plant .delivery-chips--cell). */
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-1);
    color: var(--tg-text);
    font-size: 13px;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
    -webkit-appearance: none;
    appearance: none;
    transition: background 0.12s ease-out, border-color 0.12s ease-out, color 0.12s ease-out;
}
.gs-chip--active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
}
.gs-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
@media (prefers-reduced-motion: reduce) {
    .gs-menu { animation: none; }
}

/* Кнопки в топбаре экрана уведомлений (✓ и ⚙️) */
.notif-topbar-btn {
    background: none;
    border: none;
    font-size: 18px;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.55;
    cursor: pointer;
    transition: opacity 0.15s;
    line-height: 1;
    flex-shrink: 0;
}
.notif-topbar-btn:active { opacity: 0.3; }

.profile-user-top {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 14px;
}

.profile-user-params {
    display: grid;
    grid-template-columns: 1fr 1fr;
    margin: 12px -14px 0;     /* 12px над разделителем (как у статистики) */
    padding-top: 12px;        /* 12px под разделителем до участия/листочков */
    border-top: 1px solid var(--border-subtle);
}

.profile-user-param-cell {
    display: flex;
    flex-direction: column;
    align-items: center;   /* центрируем участие/листочки */
    gap: 3px;
    padding: 0 14px;       /* верт. отступы — у контейнера (12px) и карточки (12px) */
}

.profile-user-param-cell:first-child {
    border-right: 1px solid rgba(var(--tint-rgb), 0.07);
}

.profile-user-param-cell--tappable {
    cursor: pointer;
    transition: background 0.1s;
}

.profile-user-param-cell--tappable:active {
    background: rgba(var(--tint-rgb), 0.04);
}

.profile-user-param__label {
    font-size: 11px;
    font-weight: 500;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.profile-user-param__value {
    font-size: 14px;
    font-weight: 600;
    color: var(--tg-text);
}

.profile-user-param-cell--tappable .profile-user-param__value::after {
    content: " ›";
    color: var(--tg-hint);
    font-weight: 400;
}

.profile-avatar {
    width: 68px;
    height: 68px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--border-subtle);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    font-weight: 700;
    color: var(--on-accent);
    flex-shrink: 0;
    box-shadow: 0 2px 10px rgba(25,25,25,0.12);
}

.profile-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.profile-name {
    font-size: 17px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.profile-city {
    font-size: 14px;
    color: var(--tg-text);   /* обычный текст (проектный secondary), не приглушённо-серый */
    margin-bottom: 4px;
}
.profile-bio {
    font-size: 13px;
    color: var(--tg-hint);
    margin-bottom: 0;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.profile-user-info {
    flex: 1;
    min-width: 0;
}

.profile-stats-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    width: auto;
    gap: 0;
    /* Отдельный ряд во всю ширину карточки (разделитель + отступ, как в карточке сделки) */
    margin: 12px -14px 0;
    padding: 12px 14px 0;
    border-top: 1px solid var(--border-subtle);
}

.profile-stat-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding-right: 10px;
}

.profile-stat-cell:not(:first-child) {
    padding-left: 10px;
}

.profile-stat-cell:not(:last-child) {
    border-right: 1px solid rgba(var(--tint-rgb), 0.07);
}

.profile-stat-value {
    font-size: 14px;
    font-weight: 600;
    color: var(--tg-text);
    width: 100%;
    text-align: center;
}

.profile-stat-label {
    font-size: 11px;
    font-weight: 500;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.profile-section-title {
    margin: 4px 0 0;
    font-size: 19px;
    font-weight: 700;
    color: var(--tg-text);
}

.profile-empty-plants {
    margin: 8px 0 0;
    font-size: 14px;
    color: var(--tg-hint);
    text-align: center;
}

#profilePlantsSection .plants-grid {
    /* Верхний зазор под градиент .feed-toolbar::after даёт САМ .profile-page gap:8
       (тулбар и #profilePlantsSection — соседние flex-дети). Поэтому обнуляем базовый
       .plants-grid padding-top:8px — иначе 8(gap)+8(padding)=16px против 8px на Столе. */
    padding-top: 0;
    padding-bottom: 20px; /* profile-page добавляет ещё 20px → итого 40px как на столе */
}

/* =======================================================
   ФОРМА РАСТЕНИЯ (screen-plant, edit/create mode)
   ======================================================= */

.pf-container {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 8px 0 0;
    width: 100%;
    box-sizing: border-box;
}

/* Секция формы */

.pf-section {
    background: var(--surface-2);
    border-radius: var(--radius-lg);
    padding: 16px;
    border: var(--card-border);
    box-shadow: var(--shadow-card);
}

/* Метка «Фото» — та же типографика, что у подписей полей формы
   (#screen-plant label: 11px/700 uppercase, margin-bottom 6px). flex —
   ради inline-подсказки «до 5 штук» справа. */
.pf-section__label {
    font-size: 11px;
    font-weight: 700;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.pf-section__hint {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
}

/* Поля формы */

#screen-plant .form-field {
    margin-bottom: 12px;
}

#screen-plant .form-field:last-child {
    margin-bottom: 0;
}

#screen-plant label {
    display: block;
    margin-bottom: 6px;
    font-size: 11px;
    font-weight: 700;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

#screen-plant input,
#screen-plant textarea,
#screen-plant select {
    width: 100%;
    padding: 11px 12px;
    font-size: 15px;
    border-radius: var(--radius-sm);
    border: 1.5px solid rgba(var(--tint-rgb), 0.09);
    background: var(--surface-1);
    color: var(--tg-text);
    outline: none;
    box-sizing: border-box;
    transition: border-color 0.15s ease-out, box-shadow 0.15s ease-out;
    -webkit-appearance: none;
    appearance: none;
}

#screen-plant textarea {
    resize: none;
    min-height: 80px;
    line-height: 1.5;
}

#screen-plant input:focus,
#screen-plant textarea:focus,
#screen-plant select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.12);
}

#screen-plant select {
    background-image: url("data:image/svg+xml;utf8,<svg fill='%23666' height='18' viewBox='0 0 24 24' width='18' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 18px;
    padding-right: 36px;
}

#screen-plant .hint {
    margin-top: 6px;
    font-size: 12px;
    color: var(--tg-hint);
}

/* Чипы доставки */

#screen-plant .delivery-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

#screen-plant .delivery-chip {
    /* Три кнопки делят строку поровну и помещаются на узких экранах (БАГ 2) */
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    padding: 8px 6px;
    border-radius: var(--radius-pill);
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-1);
    color: var(--tg-text);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    /* Сброс нативной кнопки WebKit: без него <button> получает собственные
       внутренние отступы/метрики → плашка шире view-span (при просмотре 2 в ряд,
       при редактировании 1) → «перескок». С appearance:none ширина = как у view. */
    -webkit-appearance: none;
    appearance: none;
    transition: background 0.12s ease-out, border-color 0.12s ease-out, color 0.12s ease-out;
}

#screen-plant .delivery-chip--active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
}

/* Тип/Передача inline в ячейках инфо-сетки (этап 3a): компактные чипы по контенту
   с переносом (узкая ячейка Тип|Передача — пол-ширины), не растягивать на всю. */
#screen-plant .delivery-chips--cell {
    /* Отступы ТОЛЬКО через margin плашек: flex gap в этом WebView применяет
       column-gap (горизонталь), но НЕ row-gap (вертикаль при переносе) → вертикаль
       пропадала. margin работает в обе стороны. Такой же приём и во view (ps-view-chip). */
    gap: 0;
    align-items: center;   /* как во view-контейнере (не stretch) */
    margin-top: 1px;
    margin-bottom: -4px;   /* съедаем нижний margin последнего ряда */
}
#screen-plant .delivery-chips--cell .delivery-chip {
    flex: 0 0 auto;
    margin: 0 4px 4px 0;   /* право 4 (горизонталь) + низ 4 (вертикаль при переносе) */
    padding: 4px 10px;     /* как плашка просмотра .ps-view-chip */
    font-size: 12px;
    line-height: 1.2;      /* как .ps-view-chip (у <button> дефолт normal → выше) */
}

/* Город */

#screen-plant .city-field { position: relative; }

#screen-plant .city-input-wrapper { position: relative; }

#screen-plant .clear-city-btn {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    background: var(--border-subtle);
    border: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    font-size: 16px;
    line-height: 1;
    padding: 0;
    cursor: pointer;
    color: var(--tg-hint);
    display: none;
    align-items: center;
    justify-content: center;
}

#screen-plant .clear-city-btn:active {
    transform: translateY(-50%) scale(0.94);
}

#screen-plant .suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 4px;
    max-height: 220px;
    overflow-y: auto;
    background: var(--surface-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-subtle);
    box-shadow: 0 8px 24px rgba(25, 25, 25, 0.14);
    padding: 4px 0;
    z-index: 20;
    display: none;
}

#screen-plant .suggestion-item {
    padding: 10px 14px;
    font-size: 14px;
    cursor: pointer;
    color: var(--tg-text);
}

#screen-plant .suggestion-item:active {
    background: var(--surface-1);
}

/* Кнопка Сохранить */

#screen-plant .pf-container {
    flex: 1 0 auto; /* растягивается до полной высоты вкладки */
}

#screen-plant .form-actions {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px;
    position: sticky;
    bottom: 0;
    margin-top: auto; /* прижимает кнопки к низу при коротком контенте */
    background: linear-gradient(to bottom, transparent, var(--tg-bg) 40%);
    padding: 12px 0 4px;
    z-index: 10;
}

/* Primary — справа, вторичная — слева. .take-button слит сюда (единый primary). */
#screen-plant .primary-button,
#screen-plant .take-button {
    flex: 1;
    order: 1;
    min-width: 0;
    padding: 13px 16px;
    border-radius: var(--radius-pill);
    border: none;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: transform 0.12s ease-out;
}

#screen-plant .primary-button:active,
#screen-plant .take-button:active {
    transform: scale(0.97);
}

/* «Забронировать» (view чужого) — единственная кнопка бара: по контенту, по центру
   (не на всю ширину). Специфичность #screen-plant #psTakeBtn перебивает flex:1
   .take-button; раскладку [Сохранить][Отмена]/модератора не задевает. */
#screen-plant #psTakeBtn {
    flex: 0 0 auto;
    margin: 0 auto;
    padding: 13px 32px;
}

/* «К сделке» на забронированном растении — цвет брони (--status-purple, как «Бронь»
   в прогрессе сделки), НЕ зелёный «Забронировать». Единственная кнопка бара → по
   контенту, по центру. Специфичность #screen-plant #psGoToDealBtn перебивает
   .secondary-button. */
#screen-plant #psGoToDealBtn {
    flex: 0 0 auto;
    margin: 0 auto;
    padding: 13px 32px;
    border-color: var(--status-purple);
    background: var(--status-purple);
    color: var(--on-accent);
    font-weight: 600;
}

/* «Забронировано» (занято другим участником) — нейтральная disabled-кнопка бара. */
#screen-plant #psReservedBtn {
    flex: 0 0 auto;
    margin: 0 auto;
    padding: 13px 32px;
    opacity: 0.6;
    cursor: default;
}

/* Edit-бар растения: «Отмена» слева, «Сохранить» справа (save order:1). */
#screen-plant #psSaveDraftBtn { order: 1; }

#screen-plant .secondary-button {
    flex: 1;
    order: 0;
    min-width: 0;
    padding: 13px 16px;
    border-radius: var(--radius-pill);
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-2);
    color: var(--text-primary);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.12s ease-out, transform 0.12s ease-out;
}

#screen-plant .secondary-button:active {
    background: var(--border-subtle);
    transform: scale(0.97);
}

/* Danger — текстовая ссылка, компактная */
#screen-plant .danger-button {
    flex-basis: 100%;
    order: 2;
    padding: 6px 0;
    border: none;
    background: transparent;
    color: var(--danger);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    text-align: center;
    text-decoration: underline;
    text-decoration-color: rgba(227, 42, 32, 0.35);
    text-underline-offset: 2px;
}

#screen-plant .danger-button:active {
    opacity: 0.55;
}



/* Toast-уведомление */
.gs-toast {
    position: fixed;
    bottom: calc(64px + env(safe-area-inset-bottom) + 12px);
    /* Центрирование через left:0/right:0 + margin:auto, НЕ через left:50%.
       При left:50% у fixed-элемента без width доступная ширина для shrink-to-fit
       = только 50vw (от центра до правого края), и max-width до него не доходит —
       тост получался узким (≈половина экрана) и текст ломался на лишние строки.
       С left:0;right:0 доступна вся ширина: короткий текст обнимается пилюлей,
       длинный переносится у max-width. */
    left: 0;
    right: 0;
    margin-inline: auto;
    width: fit-content;
    max-width: min(94vw, 480px);
    transform: translateY(12px);
    background: var(--surface-inverse);
    color: var(--text-on-inverse);
    padding: 10px 20px;
    border-radius: var(--radius-pill);
    font-size: 14px;
    font-weight: 500;
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: center;
    line-height: 1.35;
    z-index: 9999;
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    pointer-events: none;
}

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

/* Тип тоста — цветной акцент слева. Именно inset box-shadow, а не border-left:
   у пилюли радиус 999px, и граница выгнулась бы дугой. Ещё border менял бы
   ширину, и текст прыгал бы между типами. Иконок нет — только акцент. */
.gs-toast--success {
    box-shadow: inset 3px 0 0 var(--accent);
}

.gs-toast--error {
    box-shadow: inset 3px 0 0 var(--danger);
}

/* info — нейтральный, без акцента */
.gs-toast--info {
    box-shadow: none;
}

/* Экран успеха после создания растения */

.pf-success {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 16px;
    padding: 60px 24px 40px;
    min-height: 60vh;
}

.pf-success__icon {
    font-size: 64px;
    line-height: 1;
}

.pf-success__title {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0;
}

.pf-success__text {
    font-size: 14px;
    color: var(--tg-hint);
    margin: 0;
    max-width: 280px;
    line-height: 1.5;
}

.pf-success__btn {
    margin-top: 8px;
    padding: 13px 16px;
    border-radius: var(--radius-pill);
    border: none;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.12s ease-out;
}

.pf-success__btn:active {
    transform: scale(0.97);
}

/* Информационный баннер в форме растения */

.pf-info-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;

    padding: 10px 14px;
    border-radius: var(--radius-md);
    font-size: 13px;
    line-height: 1.4;
    margin-bottom: 12px;
}

.pf-info-banner--warn {
    background: var(--banner-warn-bg);
    color: var(--banner-warn-text);
    border-left: 3px solid var(--banner-warn-accent);
}

.pf-info-banner--ok {
    background: var(--banner-ok-bg);
    color: var(--status-approved-text);
    border-left: 3px solid var(--accent);
}

.pf-info-banner--error {
    background: var(--banner-error-bg);
    color: var(--status-rejected-text);
    border-left: 3px solid var(--danger);
}

/* Подсветка незаполненного обязательного поля (БАГ 4) — только рамка, без текста */
.ps-field--error,
.ps-field--error input,
.ps-field--error textarea {
    border: 2px solid var(--brand-red) !important;
    /* !important — иначе у полей с собственным радиусом/боксом углы красной рамки
       остаются острыми (напр. inline-поля, контейнеры чипов/фото). */
    border-radius: var(--radius-sm) !important;
}

/* Выравнивание красной рамки по типам полей (у них разный box-model):
   инлайн-поля почти без padding (рамка липнет к тексту, плейсхолдер не по центру),
   контейнер чипов имеет margin-bottom у плашек (низ с отступом, верх впритык). */

/* Название (инлайн-поле): внутренний отступ — рамка не касается текста, плейсхолдер
   по центру. Право 24px — резерв под крестик очистки (в ошибке поле пустое, крестика
   нет, но держим единый бокс). */
#screen-plant .ps-inline-field.ps-field--error {
    padding: 5px 24px 5px 8px !important;
}
/* Город (инлайн .lp-loc-input): то же; право 30px — резерв под гео/крестик. */
#screen-plant #psLocationPicker .lp-loc-input.ps-field--error {
    padding: 5px 30px 5px 8px !important;
}
/* Доставка/Тип (контейнер чипов): симметрия 4px со всех сторон. Плашки уже дают
   низ (margin-bottom 4) и право (margin-right 4) → добавляем только верх+лево 4. */
#screen-plant .delivery-chips--cell.ps-field--error {
    padding: 4px 0 0 4px !important;
}

/* ── Единое семейство инлайновых ошибок форм ───────────────────
   Два уровня, разная роль в лейауте (см. webapp/form_error.js):
   .gs-form-error  — ошибка всей формы, по центру, резервирует строку;
   .gs-field-error — ошибка конкретного поля, под инпутом (место резервирует
                     контейнер поля, напр. .bl-field-group).
   Единый цвет --brand-red: раньше leaves/subscription были на --danger. */

.gs-form-error {
    font-size: 13px;
    color: var(--brand-red);
    text-align: center;
    margin: 8px 0 0;
    min-height: 18px;   /* резерв: появление ошибки не двигает кнопку */
}

.gs-field-error {
    margin-top: 4px;
    font-size: 12px;
    color: var(--brand-red);
}

.pf-info-banner--neutral {
    background: var(--tg-secondary-bg);
    color: var(--tg-hint);
    border-left: 3px solid var(--border-subtle);
}

.pf-info-banner--purple {
    background: var(--banner-purple-bg);   /* подложка в тон --banner-purple */
    color: var(--banner-purple-text);
    border-left: 3px solid var(--banner-purple);
}

/* =======================================================
   ПОДПИСКА
   ======================================================= */

.subscription-block {
    padding: 16px;
    background: var(--tg-bg);
    border-radius: var(--radius-lg);
    border: var(--card-border);
    box-shadow: var(--shadow-card);
    margin-bottom: 12px;
}

.subscription-description {
    font-size: 14px;
    color: var(--tg-hint);
    margin: 0 0 14px;
    text-align: center;
}

.subscription-tariffs {
    display: flex;
    gap: 10px;
    margin-top: 8px;   /* место под бейдж «Выгодно», сидящий на верхней грани popular */
}

.subscription-tariff {
    position: relative;  /* якорь для оверлей-бейджа «Выгодно» */
    flex: 1 1 0;         /* строго равная ширина трёх плашек, независимо от контента */
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;

    padding: 14px 6px 12px;
    border-radius: var(--radius-md);
    border: 1.5px solid rgba(184, 184, 184, 0.4);
    background: var(--tg-secondary-bg);
    color: var(--tg-text);

    cursor: pointer;
    text-align: center;
    transition: border-color 0.12s, background 0.12s, transform 0.12s, box-shadow 0.12s;
}

.subscription-tariff:active {
    transform: scale(0.97);
}

/* Подсветка ВЫБРАННОЙ плашки (не popular — выбор отдельный; popular лишь несёт бейдж). */
.subscription-tariff.is-selected {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb), 0.07);
    box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.18);
}

.sub-tariff-months {
    font-size: 13px;
    font-weight: 700;   /* пожирнее (1 месяц / 3 / 6) */
    color: var(--tg-text);
}

.subscription-tariff.is-selected .sub-tariff-months {
    color: var(--accent-dark);
}

/* Пакет листочков: количество крупнее периода (это «лицо» плашки). */
.sub-tariff-count {
    font-size: 18px;
    font-weight: 800;
    line-height: 1.1;
}

/* Бейдж «Выгодно» — оверлей на верхней грани popular-плашки (страддлит границу). */
.sub-tariff-badge {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
    color: var(--on-accent);
    background: var(--accent);
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    box-shadow: 0 2px 6px rgba(var(--accent-rgb), 0.3);
}

.sub-tariff-price {
    font-size: 20px;
    font-weight: 700;
    color: var(--tg-text);
    line-height: 1.1;
    margin-top: 2px;
}

.subscription-tariff.is-selected .sub-tariff-price {
    color: var(--accent-dark);
}

.sub-tariff-per {
    font-size: 11px;
    color: var(--tg-hint);
    margin-top: 1px;
}

/* Чип бонуса «+N 🌿» — под периодом; слот зарезервирован и на плашках без бонуса. */
.sub-tariff-bonus {
    font-size: 11px;
    font-weight: 600;
    color: var(--accent-dark);
    background: rgba(var(--accent-rgb), 0.12);
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    line-height: 1.2;
    margin-top: 2px;
}
/* Пустой слот бейджа/бонуса — резервирует ту же высоту (строки выровнены), но невидим. */
.sub-tariff-slot-reserved {
    visibility: hidden;
}

/* Единый блок тарифов: плашки + кнопка оплаты + подпись «Оплата через ЮKassa» */
.subscription-tariffs-block {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
}
.subscription-pay-btn {
    align-self: center;      /* по контенту, по центру — не на всю ширину */
    padding: 13px 44px;      /* комфортные боковые паддинги */
    border: none;
    border-radius: var(--radius-pill);
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.12s;
}
.subscription-pay-btn:active { transform: scale(0.98); }
.subscription-pay-note {
    font-size: 12px;
    color: var(--tg-hint);
    text-align: center;
    margin-top: -4px;
}
/* Строка со ссылками на оферту/возврат под кнопкой оплаты. */
.subscription-pay-legal {
    font-size: 12px;
    color: var(--tg-hint);
    text-align: center;
    line-height: 1.4;
    margin-top: 4px;
}
.subscription-pay-legal a { color: var(--accent); }

/* Единый баннер состояния участия (4 варианта) — заменил прежние .subscription-state.
   Слева цветная точка + заголовок(700)/подпись; справа круглая «?» в цвет статуса. */
.subscription-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    min-height: 81px;                   /* = высота .leaves-balance-card (замер) — равные блоки */
    box-sizing: border-box;
    border-radius: var(--radius-md);
    color: var(--on-accent);          /* залитый блок — белый текст на цветном фоне */
}
.subscription-banner__icon {
    flex: 0 0 auto;
    display: flex;                        /* слот слева; иконка по центру баннера (align-items:center) */
    /* .gs-icon внутри — stroke:currentColor → белая (баннер color:brand-white), как «?» */
}
.subscription-banner__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.subscription-banner__title { font-size: 15px; font-weight: 800; line-height: 1.2; }
.subscription-banner__sub   { font-size: 13px; line-height: 1.3; opacity: 0.9; }
.subscription-banner__help {
    flex: 0 0 auto;
    width: 26px; height: 26px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.6);
    background: rgba(255,255,255,0.15);
    font-size: 15px; font-weight: 700; line-height: 1;
    cursor: pointer;
    color: var(--on-accent);
}
/* Варианты: залитый градиент своего цвета + тень-подъём в тон (образец — .leaves-balance-card) */
.subscription-banner--active  { background: linear-gradient(135deg, #5B7A39, #46602b); box-shadow: 0 6px 18px rgba(91,122,57,0.32); }
.subscription-banner--trial   { background: linear-gradient(135deg, #3f76c9, #315ea0); box-shadow: 0 6px 18px rgba(63,118,201,0.32); }
.subscription-banner--expired { background: linear-gradient(135deg, #C0862E, #a06e22); box-shadow: 0 6px 18px rgba(192,134,46,0.32); }
.subscription-banner--none    { background: linear-gradient(135deg, #8f8f88, #6f6f69); box-shadow: 0 6px 18px rgba(120,120,112,0.30); }

/* Инлайн-кнопки тарифов (в профиле) */

.profile-subscription-inline {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 14px;
    color: var(--tg-hint);
    padding: 12px 14px;
    background: var(--tg-bg);
    border-radius: var(--radius-lg);
    border: var(--card-border);
    box-shadow: var(--shadow-card);
}

.subscription-actions-inline {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.subscription-btn-inline {
    padding: 6px 12px;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(184, 184, 184, 0.6);
    background: var(--tg-secondary-bg);
    color: var(--tg-text);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.12s, border-color 0.12s, transform 0.12s;
}

.subscription-btn-inline:active {
    transform: scale(0.97);
}

.subscription-btn--popular {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb), 0.08);
    color: var(--accent-dark);
    font-weight: 600;
}

/* ============================================================
   Feed FAB — кнопка + добавить растение
   ============================================================ */

.feed-fab {
    position: fixed;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 72px);
    right: max(16px, calc((100vw - 480px) / 2 + 16px));
    z-index: 200;

    width: 52px;
    height: 52px;
    border-radius: 50%;
    border: none;

    background: var(--accent);
    color: var(--on-accent);   /* цвет глифа: .gs-icon рисуется stroke: currentColor */

    box-shadow: var(--shadow-soft);
    cursor: pointer;
    transition: transform 0.12s ease-out;

    display: flex;
    align-items: center;
    justify-content: center;
}

.feed-fab:active {
    transform: scale(0.93);
}

/* ============================================================
   Feed paywall (полноэкранный, вместо растений при locked=true)
   ============================================================ */

.feed-paywall {
    grid-column: 1 / -1; /* растягивается на всю ширину грида */
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 48px 24px;
}

.feed-paywall__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 16px;
}

.feed-paywall__title {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 12px;
}

.feed-paywall__desc {
    font-size: 15px;
    color: var(--tg-hint);
    line-height: 1.5;
    margin-bottom: 28px;
    max-width: 280px;
}

.feed-paywall__plans {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
}

.feed-paywall__plan {
    width: 100%;
    padding: 14px 16px;
    background: var(--surface-2);
    border: 1.5px solid var(--accent);
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 600;
    color: var(--accent);
    cursor: pointer;
    transition: background 0.15s ease-out, color 0.15s ease-out;
}

.feed-paywall__plan:active {
    background: var(--accent);
    color: var(--on-accent);
}


/* ============================================================
   Subscription screen (dedicated tab)
   ============================================================ */

.subscription-page {
    display: flex;
    flex-direction: column;
    align-items: stretch;   /* дети во всю ширину (не сжатые по центру): плашка состояния,
                               тарифы, кнопка — edge-to-edge в пределах бокового инсета */
    gap: 16px;
    padding: 12px 12px var(--scroll-end-gap);   /* верхний отступ как у экрана листочков */
}

/* Маркетинговая шапка участия (состояния never/trial) */
.subscription-hero {
    text-align: center;
    padding: 4px 0 4px;
}

.subscription-hero__title {
    font-size: 22px;
    font-weight: 800;
    line-height: 1.2;
    color: var(--tg-text);
    margin: 0;
}

.subscription-hero__subtitle {
    font-size: 14px;
    color: var(--tg-hint);
    margin: 8px 0 0;
}

/* Блок выгод участия — компактный список на фоне страницы (состояния never/trial) */
.subscription-benefits {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.subscription-benefit {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 0;
}

.subscription-benefit__check {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #5B7A39;
    color: var(--on-accent);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

.subscription-benefit__text {
    font-size: 15px;
    font-weight: 500;
    color: var(--tg-text);
}

/* ===== Экран «Пригласить друга» (referral_screen.js) ===== */
.referral-page {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 16px;   /* как у .subscription-page/.leaves-page (единый ритм страниц-секций) */
    padding: 12px 12px var(--scroll-end-gap);   /* инсет как у subscription/leaves */
}
/* Секция: подпись (.leaves-section-title) сверху + содержимое; сама подпись имеет
   margin-bottom, поэтому секции — простой контейнер. */
.referral-section { display: flex; flex-direction: column; }
/* Вводная community-строка над карточкой награды — фирменная оливковая. */
.referral-intro {
    margin: 0 0 4px;
    font-size: 15px;
    line-height: 1.4;
    font-weight: 600;
    color: var(--accent);
}
/* Плоская карточка «Бонус за друга» — светлая подложка, без заливки. */
.referral-how {
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: var(--radius-lg);
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.referral-how__item {
    display: flex;
    align-items: center;   /* «+N 🌿» по центру по вертикали, даже когда текст в 2 строки */
    gap: 10px;
}
.referral-how__leaf {
    flex-shrink: 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--accent);
    white-space: nowrap;
}
.referral-how__text { font-size: 14px; color: var(--tg-text); line-height: 1.35; }
.referral-how__lead { font-size: 13px; color: var(--tg-text); line-height: 1.4; margin: 0; }
.referral-how__note { font-size: 12px; color: var(--tg-hint); margin: 0; }
/* Ссылка на статью — текстовая кнопка, не соревнуется с кнопками «Ваша ссылка». */
.referral-how__link {
    align-self: flex-start;
    margin-top: 2px;
    padding: 4px 0;
    border: none;
    background: none;
    color: var(--accent);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
}
.referral-how__link:active { opacity: 0.6; }

.referral-link__input {
    width: 100%;
    box-sizing: border-box;
    padding: 11px 14px;
    margin-bottom: 8px;
    font-size: 14px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-subtle);
    background: var(--tg-secondary-bg);
    color: var(--tg-text);
    outline: none;
    font-family: var(--font-mono);   /* реф-ссылка — технический текст, моноширинный */
}
.referral-link__actions {
    display: flex;
    gap: 8px;
}

/* Статистика: карточка «Начислено» + ряд из трёх карточек (метрики .subscription-tariff). */
.referral-earned {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 14px 16px;
    margin-bottom: 8px;
    background: var(--tg-secondary-bg);
    border: var(--card-border);
    border-radius: var(--radius-lg);
}
.referral-earned__label { font-size: 14px; color: var(--tg-text); }
.referral-earned__value { font-size: 20px; font-weight: 800; color: var(--accent); white-space: nowrap; }
.referral-stats-row {
    display: flex;
    gap: 8px;
}
.referral-stat-card {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 14px 6px 12px;
    border-radius: var(--radius-md);
    border: 1.5px solid rgba(184, 184, 184, 0.4);
    background: var(--tg-secondary-bg);
    text-align: center;
}
.referral-stat-card__num { font-size: 20px; font-weight: 800; color: var(--tg-text); line-height: 1.1; }
.referral-stat-card__label { font-size: 12px; color: var(--tg-hint); }
.referral-stats-note { font-size: 12px; color: var(--tg-hint); line-height: 1.35; margin: 8px 2px 0; text-align: center; }
/* Кнопки экрана реферала: размер основной кнопки приложения (глобального
   .primary/.secondary-button стиля нет — задаём здесь, scoped). В ряд, равной ширины;
   одна «Скопировать» без шэра → на всю ширину (flex:1 + единственный ребёнок). */
.referral-btn {
    flex: 1;
    min-width: 0;
    padding: 13px 16px;
    min-height: 46px;
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    -webkit-appearance: none;
    appearance: none;
    transition: transform 0.12s ease-out, background 0.12s ease-out;
}
.referral-btn.primary-button {
    border: none;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
    font-weight: 600;
}
.referral-btn.secondary-button {
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-2);
    color: var(--text-primary);
}
.referral-btn:active { transform: scale(0.98); }

/* Блок «Как это работает» (неактивное состояние участия) */
/* ============================================================
   Profile subscription status strip
   ============================================================ */

.profile-sub-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px;
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-sm);
    width: 100%;
    box-sizing: border-box;
}

.profile-sub-status__label {
    font-size: 14px;
    color: var(--tg-text);
    flex: 1;
}

.profile-sub-status__btn {
    padding: 8px 16px;
    border-radius: var(--radius-pill);
    border: none;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    transition: opacity 0.12s ease-out, transform 0.12s ease-out;
}

.profile-sub-status__btn:active {
    opacity: 0.85;
    transform: scale(0.97);
}

.profile-sub-status__btn--secondary {
    background: transparent;
    color: var(--accent);
    border: 1.5px solid var(--accent);
}

.profile-leaves-shortcut {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-sm);
    border: none;
    width: 100%;
    box-sizing: border-box;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    color: var(--tg-text);
    text-align: left;
    transition: opacity 0.12s ease;
}

.profile-leaves-shortcut:active {
    opacity: 0.7;
}

.profile-leaves-shortcut__chevron {
    font-size: 18px;
    color: var(--tg-hint);
}

/* =======================================================
   ЛИСТОЧКИ
   ======================================================= */

.leaves-page {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 12px 12px var(--scroll-end-gap);
}

/* Баланс */
.leaves-balance-card {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 20px;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    border-radius: var(--radius-md);
    box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.3);
    color: var(--on-accent);
}

.leaves-balance-icon {
    font-size: 36px;
    line-height: 1;
}

.leaves-balance-value {
    font-size: 32px;
    font-weight: 800;
    line-height: 1;
}

.leaves-balance-label {
    font-size: 13px;
    opacity: 0.85;
    margin-top: 2px;
}

.leaves-balance-sub {
    font-size: 12px;
    opacity: 0.75;
    margin-top: 5px;
}

/* «?»-help в карточке баланса — прижат вправо (body не flex:1); стиль-копия
   .subscription-banner__help: белый кружок на зелёном градиенте. → статья «leaves». */
.leaves-balance-help {
    flex: 0 0 auto;
    margin-left: auto;
    width: 26px; height: 26px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.6);
    background: rgba(255,255,255,0.15);
    font-size: 15px; font-weight: 700; line-height: 1;
    cursor: pointer;
    color: var(--on-accent);
}

/* Блок «Бонус за публикацию» — заголовок вынесен секцией над карточкой. */
.leaves-progress-section { margin-top: 14px; }
.leaves-progress-card {
    padding: 14px 16px;
    background: var(--surface-2);
    border: var(--card-border);
    border-radius: var(--radius-md);
}
/* Шкала сверху: деления 0/5/10 (серые) + текущее значение зелёным. */
.leaves-progress__scale {
    position: relative;
    height: 18px;
    margin-bottom: 6px;
}
.leaves-progress__scale-mark {
    position: absolute;
    transform: translateX(-50%);
    top: 2px;
    font-size: 12px;
    font-weight: 600;
    color: var(--tg-hint);
}
/* pos совпал с делением → само число зелёным (без отдельного пузырька). */
.leaves-progress__scale-mark--cur {
    color: var(--accent);
    font-weight: 800;
}
/* Текущее значение (pos не на делении) — зелёный пузырёк над полосой. */
.leaves-progress__scale-cur {
    position: absolute;
    transform: translateX(-50%);
    top: 0;
    padding: 1px 7px;
    font-size: 12px;
    font-weight: 800;
    color: var(--on-accent);
    background: var(--accent);
    border-radius: 999px;
    white-space: nowrap;
}
.leaves-progress__track {
    position: relative;
    height: 8px;
    margin: 0;
    background: var(--surface-1);
    border-radius: 999px;
    /* overflow видимый — узлы-вехи и маркер выходят за высоту дорожки (8px). */
}
/* Маркер текущей позиции на полосе — белый круг с зелёной обводкой, поверх узлов. */
.leaves-progress__curdot {
    position: absolute;
    top: 50%;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 3px solid var(--accent);
    transform: translate(-50%, -50%);
    box-sizing: border-box;
    z-index: 2;
}
.leaves-progress__fill {
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
    transition: width 0.35s ease;
}
/* Узлы-вехи (5 и 10): будущий — обведён, пройденный (--done) — залит. */
.leaves-progress__node {
    position: absolute;
    top: 50%;
    width: 12px; height: 12px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 2px solid var(--border-subtle);
    transform: translate(-50%, -50%);
    box-sizing: border-box;
}
.leaves-progress__node--done {
    background: var(--accent);
    border-color: var(--accent);
}
.leaves-progress__marks {
    position: relative;
    height: 16px;
    margin-top: 10px;
}
.leaves-progress__mark {
    position: absolute;
    transform: translateX(-50%);
    font-size: 12px;
    font-weight: 600;
    color: var(--tg-hint);
    white-space: nowrap;
}
.leaves-progress__hint {
    margin-top: 8px;
    font-size: 13px;
    line-height: 1.4;
    color: var(--tg-hint);
}

/* Заголовок секции */
.leaves-section-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--tg-text);
    margin: 0 0 10px;
}

/* Карточки пакетов */
.leaves-packs {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}

.leaves-pack {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 14px 8px 12px;
    background: var(--tg-secondary-bg);
    border: 1.5px solid rgba(var(--border-field-rgb), 0.3);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}

.leaves-pack:active {
    transform: scale(0.96);
}

.leaves-pack--featured {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb), 0.06);
    box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.18);
}

.leaves-pack__badge {
    position: absolute;
    top: -10px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--accent);
    color: var(--on-accent);
    font-size: 10px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

.leaves-pack__icon {
    font-size: 22px;
    line-height: 1;
}

.leaves-pack__count {
    font-size: 20px;
    font-weight: 800;
    color: var(--tg-text);
}

.leaves-pack__price {
    font-size: 13px;
    color: var(--tg-hint);
    font-weight: 500;
}

.leaves-buy-hint {
    margin: 8px 0 0;
    font-size: 12px;
    color: var(--tg-hint);
    text-align: center;
}

/* История транзакций */
.leaves-history-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.leaves-tx {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 4px;
    border-bottom: 1px solid rgba(var(--border-field-rgb), 0.12);
}

.leaves-tx:last-child {
    border-bottom: none;
}

.leaves-tx__icon {
    font-size: 20px;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-xs);
    flex-shrink: 0;
}

.leaves-tx__body {
    flex: 1;
    min-width: 0;
}

.leaves-tx__label {
    font-size: 14px;
    font-weight: 500;
    color: var(--tg-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.leaves-tx__date {
    font-size: 12px;
    color: var(--tg-hint);
    margin-top: 1px;
}

.leaves-tx__amount {
    font-size: 15px;
    font-weight: 700;
    white-space: nowrap;
    flex-shrink: 0;
}

.leaves-tx__amount--plus  { color: var(--accent); }
.leaves-tx__amount--minus { color: var(--danger); }

.leaves-notice {
    padding: 12px 16px;
    background: var(--tg-secondary-bg);
    border-radius: var(--radius-sm);
    font-size: 14px;
    color: var(--tg-text);
    text-align: center;
}

/* .leaves-empty унифицирован в .gs-empty-state--inline */


/* Нижняя навигация */

.bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;

    /* Клиренс под home-indicator — по режиму, из единой --nav-clearance (core.css).
       Тем же значением считается нижний резерв .page-inner под нав → высота бара и
       резерв контента совпадают, зазора нет. Браузер: 0; standalone: max(4px, env−22). */
    padding-bottom: var(--nav-clearance);

    background: var(--tg-bg);
    border-top: 1px solid var(--tg-secondary-bg);
    z-index: 1000;
}

.bottom-nav__inner {
    width: 100%;
    max-width: 480px;
    margin: 0 auto;

    padding: 4px 12px;

    display: flex;
    justify-content: space-around;
}

/* Унификация ширины блоков сделок */

.deal-page,
.deals-list,
.deal-header-card,
.deal-chat-container {
    width: 100%;
}

/* ===== Кнопка действия в топбаре (✏️) ===== */

.topbar-action-btn {
    flex-shrink: 0;
    background: none;
    border: none;
    font-size: 20px;
    padding: 0 2px;
    margin-right: 4px;
    cursor: pointer;
    color: var(--accent, #5B7A39);
    display: flex;
    align-items: center;
    line-height: 1;
    opacity: 0.85;
    transition: opacity 0.15s;
}
.topbar-action-btn:active {
    opacity: 0.5;
}

/* ===== Шит редактирования профиля ===== */

.profile-edit-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.5);
    z-index: 500;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.25s ease;
}
.profile-edit-overlay--visible {
    opacity: 1;
}
.profile-edit-sheet {
    width: 100%;
    max-width: 480px;
    background: var(--surface-3);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    padding: 12px 16px 0;
    box-shadow: var(--shadow-up);
    transform: translateY(40px);
    transition: transform 0.25s ease;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.profile-edit-sheet__body {
    overflow-y: auto;
    flex: 1;
    min-height: 0;
    padding-bottom: 8px;
}

.profile-edit-sheet__save-wrap {
    flex-shrink: 0;
    padding: 12px 0 calc(72px + env(safe-area-inset-bottom, 0px));
    background: var(--surface-3);
}
.profile-edit-overlay--visible .profile-edit-sheet {
    transform: translateY(0);
}
.profile-edit-sheet__drag {
    width: 40px;
    height: 4px;
    background: rgba(var(--tint-rgb), 0.12);
    border-radius: 2px;
    margin: 0 auto 14px;
}
.profile-edit-sheet__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}
.profile-edit-sheet__title {
    font-size: 17px;
    font-weight: 700;
    color: var(--tg-text);
}
.profile-edit-sheet__close {
    background: none;
    border: none;
    font-size: 18px;
    color: var(--tg-hint);
    cursor: pointer;
    padding: 4px;
    line-height: 1;
    transition: opacity 0.15s;
}
.profile-edit-sheet__close:active { opacity: 0.5; }

/* Аватар первым блоком, по центру шита */
.profile-edit-avatar-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    margin: 0 auto 16px;
}

.profile-edit-avatar-col .profile-avatar {
    width: 68px;
    height: 68px;
    font-size: 26px;
}

/* Кликабельный аватар в форме редактирования.
   overflow:visible — иначе круглый clip от .profile-avatar обрезает карандаш/крестик
   в правом нижнем/верхнем углу. */
.profile-edit-avatar {
    position: relative;
    cursor: pointer;
    overflow: visible;
}

/* =========================
   ЭКРАН РЕДАКТИРОВАНИЯ ПРОФИЛЯ (отдельный экран, не шит)
   ========================= */
#profileEditContainer {
    padding: 8px 12px calc(var(--scroll-end-gap) + 20px);
}
.pe-card {
    background: var(--surface-2);
    border-radius: var(--radius-lg);
    border: var(--card-border);
    box-shadow: var(--shadow-card);
    margin-top: 8px;
    padding: 16px 14px 18px;
}
/* position:relative + fit-content — карандаш (absolute) держится в углу аватара */
.pe-avatar-wrap {
    position: relative;
    width: fit-content;
    margin: 0 auto 24px;
}
.pe-avatar-wrap .profile-avatar {
    width: 80px;
    height: 80px;
}
.pe-field-group {
    margin-bottom: 16px;
}
/* Локация внутри группы имеет свой margin-bottom — убираем, чтобы между городом
   и «О себе» был тот же отступ (16px от .pe-field-group), что и между именем и городом. */
.pe-field-group .lp-field {
    margin-bottom: 0;
}
.pe-label {
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--tg-hint);
    margin-bottom: 6px;
}
.pe-required { color: var(--brand-red); }
.pe-field {
    width: 100%;
    padding: 12px 14px;
    font-size: 16px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    color: var(--text-primary);
    box-sizing: border-box;
    outline: none;
    font-family: inherit;
    transition: border-color 0.15s;
}
.pe-field:focus { border-color: var(--accent); }
/* Ошибка обязательного поля — единый класс .ps-field--error (как в форме растения):
   2px solid var(--brand-red). Имя и город профиля подсвечиваются одинаково. */
.pe-textarea {
    resize: none;
    min-height: 84px;
    line-height: 1.45;
}
/* Локация в форме профиля: внутренний лейбл пикера скрыт — над ним свой «ГОРОД».
   Само поле пикера уже в рамке (.lp-loc-input), убираем лишний нижний отступ. */
#peLocation .lp-label { display: none; }
#peLocation .lp-field { margin-bottom: 0; }
/* Резервный блок ошибки геолокации не нужен в форме профиля — он создавал лишний
   вертикальный воздух между городом и «О себе». Схлопываем (при ошибке покажется текст). */
#peLocation .lp-geo-hint { min-height: 0; margin: 0; }
.pe-save {
    width: 100%;
    padding: 13px 16px;
    margin-top: 8px;
    border: none;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: opacity 0.12s;
}
.pe-save:active { opacity: 0.85; }
.pe-save:disabled { opacity: 0.6; cursor: not-allowed; }
.pe-delete-link {
    display: block;
    text-align: center;
    margin-top: 16px;
    font-size: 13px;
    color: var(--tg-hint);
    cursor: pointer;
    text-decoration: none;
}

/* ===== Экран «Вход через браузер» (browser_login.js) ===== */
.bl-intro {
    font-size: 14px;
    line-height: 1.45;
    color: var(--text-primary);
    margin-bottom: 16px;
}
.bl-intro--muted { color: var(--tg-hint); }

/* Поле пароля + кнопка-глаз */
.bl-pass-wrap { position: relative; }
.bl-pass-input { padding-right: 44px; }
.bl-eye {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    border: none;
    background: transparent;
    cursor: pointer;
    line-height: 1;
    opacity: 0.5;
    border-radius: var(--radius-sm);
    /* SVG-иконка (i-eye/i-eye-off) по центру; цвет — от текста поля (currentColor). */
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-primary);
}
.bl-eye svg { width: 20px; height: 20px; }
.bl-eye--on { opacity: 0.9; }

/* Резерв места под ошибку — на КОНТЕЙНЕРЕ поля, не на самом узле ошибки.
   Узел позиционируется абсолютно в зарезервированную полосу, поэтому его
   появление не толкает следующее поле. min-height на .gs-field-error дал бы
   тот же эффект, но раздул бы форму на высоту строки под КАЖДЫМ полем. */
.bl-field-group {
    position: relative;
    padding-bottom: 18px;
}

.bl-field-group > .gs-field-error {
    position: absolute;
    left: 0;
    bottom: 0;
}

/* Состояние «задан» — маскированный email */
.bl-status-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.bl-status-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--tg-hint);
}
.bl-status-value {
    font-size: 15px;
    color: var(--text-primary);
    font-weight: 500;
}
.bl-check { color: var(--accent); }

.bl-btn-secondary {
    background: var(--border-subtle);
    color: var(--text-primary);
}

.bl-skeleton {
    padding: 24px 0;
    text-align: center;
    color: var(--tg-hint);
    font-size: 14px;
}

/* Заглушка под будущую инструкцию — пустая, места не занимает */
.bl-instruction:empty { display: none; }

.profile-edit-avatar__pencil {
    position: absolute;
    right: -2px;
    bottom: -2px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 1.5px solid var(--border-subtle);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    line-height: 1;
    box-shadow: 0 1px 4px rgba(25, 25, 25, 0.18);
}

.profile-edit-name-fields {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}
/* Локация — компонент initLocationPicker имеет свой margin-bottom; убираем,
   чтобы между городом и «О себе» был тот же 8px, что и между именем и городом. */
.profile-edit-name-fields .lp-field {
    margin-bottom: 0;
}

.profile-edit-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-bottom: 20px;
}
.profile-edit-field__label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--tg-hint);
    letter-spacing: 0;
    margin-bottom: 6px;
}
.profile-edit-field__input,
.profile-edit-field__textarea {
    width: 100%;
    padding: 11px 12px;
    background: var(--tg-secondary-bg);
    border: 1.5px solid transparent;
    border-radius: var(--radius-sm);
    font-size: 15px;
    color: var(--tg-text);
    box-sizing: border-box;
    outline: none;
    font-family: inherit;
    transition: border-color 0.15s;
}
.profile-edit-field__input:focus,
.profile-edit-field__textarea:focus {
    border-color: var(--accent, #5B7A39);
}
.profile-edit-field__textarea {
    resize: none;
    min-height: 80px;
    line-height: 1.45;
}
.profile-edit-sheet__save {
    width: 100%;
    padding: 13px 16px;
    border-radius: var(--radius-pill);
    border: none;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s, transform 0.12s;
}
.profile-edit-sheet__save:active {
    opacity: 0.9;
    transform: scale(0.97);
}
.profile-edit-sheet__save:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.profile-edit-city-wrap {
    position: relative;
}
.profile-edit-city-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--tg-bg);
    border: 1.5px solid rgba(var(--tint-rgb), 0.1);
    border-radius: var(--radius-sm);
    z-index: 10;
    max-height: 180px;
    overflow-y: auto;
    box-shadow: var(--shadow-popover);
    margin-top: 4px;
}
.profile-edit-city-suggestions.hidden { display: none; }
.profile-edit-city-item {
    padding: 10px 14px;
    font-size: 14px;
    color: var(--tg-text);
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.05);
}
.profile-edit-city-item:last-child { border-bottom: none; }
.profile-edit-city-item:active { background: rgba(var(--tint-rgb), 0.04); }

/* Автодополнение города в фильтре стола (тот же вид, что в профиле) */
.feed-city-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--tg-bg);
    border: 1.5px solid rgba(var(--tint-rgb), 0.1);
    border-radius: var(--radius-sm);
    z-index: 10;
    max-height: 180px;
    overflow-y: auto;
    box-shadow: var(--shadow-popover);
    margin-top: 4px;
}
.feed-city-suggestions.hidden { display: none; }
.feed-city-item {
    padding: 10px 14px;
    font-size: 14px;
    color: var(--tg-text);
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.05);
}
.feed-city-item:last-child { border-bottom: none; }
.feed-city-item:active { background: rgba(var(--tint-rgb), 0.04); }

/* ============================
   КОМПОНЕНТ ЛОКАЦИИ (location_picker.js)
   ============================ */
.lp-field { margin-bottom: 12px; }
.lp-field.hidden { display: none; }
.lp-label {
    display: block;
    font-size: 13px;
    color: var(--tg-hint);
    margin-bottom: 6px;
}
.lp-wrap { position: relative; }
.lp-city-input,
.lp-district-input,
.lp-loc-input {
    width: 100%;
    box-sizing: border-box;
    padding: 11px 14px;
    font-size: 15px;
    border: 1.5px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    color: var(--text-primary);
    outline: none;
}
.lp-city-input:focus,
.lp-district-input:focus,
.lp-loc-input:focus { border-color: var(--accent); }
/* disabled на время «Определяем город...» — сохраняем обычный вид (UA/iOS иначе серит) */
.lp-city-input:disabled,
.lp-district-input:disabled,
.lp-loc-input:disabled {
    background: var(--surface-2);
    color: var(--text-primary);
    -webkit-text-fill-color: var(--text-primary);
    opacity: 1;
    cursor: default;
}
.lp-city-suggestions,
.lp-district-suggestions,
.lp-loc-suggestions {
    position: absolute;
    top: 100%;            /* раскрывается ВНИЗ от поля */
    left: 0;
    right: 0;
    /* Непрозрачный белый фон: раньше был --tg-bg (ivory, как у страницы) —
       панель «сливалась» и просвечивала контент под собой. */
    background: var(--surface-3);
    border: 1.5px solid rgba(var(--tint-rgb), 0.1);
    border-radius: var(--radius-sm);
    /* Выше соседних элементов формы (галка/кнопка), но в пределах стека
       карточки онбординга — карточка не имеет overflow:hidden, dropdown не клипается. */
    z-index: 50;
    max-height: 240px;
    overflow-y: auto;
    /* iOS: инерционный скролл списка + жест не проваливается в родительский скроллер;
       pan-y — вертикальный скролл разрешён (тап/скролл различает JS по порогу движения). */
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    touch-action: pan-y;
    box-shadow: var(--shadow-popover);
    margin-top: 4px;
}
/* Видимая полоса прокрутки справа (десктоп/Android; iOS Safari её игнорирует —
   там системный overlay-скролл при жесте, что ожидаемо). */
.lp-loc-suggestions::-webkit-scrollbar { width: 8px; }
.lp-loc-suggestions::-webkit-scrollbar-track { background: transparent; }
.lp-loc-suggestions::-webkit-scrollbar-thumb { background: rgba(var(--tint-rgb), 0.2); border-radius: 4px; }

.lp-city-suggestions.hidden,
.lp-district-suggestions.hidden,
.lp-loc-suggestions.hidden { display: none; }
.lp-sug-item {
    padding: 10px 14px;
    font-size: 14px;
    color: var(--tg-text);
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.05);
}
.lp-sug-item:last-child { border-bottom: none; }
.lp-sug-item:active { background: rgba(var(--tint-rgb), 0.04); }

/* Элемент единого поиска локации: иконка + название + подзаголовок */
.lp-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.05);
}
.lp-item:last-child { border-bottom: none; }
.lp-item:active { background: rgba(var(--tint-rgb), 0.04); }
/* .lp-item--empty унифицирован в .gs-empty-state--inline */
.lp-item__icon {
    flex-shrink: 0;
    /* Фиксированная колонка иконки → левый край текста совпадает во ВСЕХ строках
       (эмодзи 🚇/📍 и «—» у «Не указывать» имеют разную глиф-ширину). */
    width: 20px;
    text-align: center;
    font-size: 18px;
    line-height: 1;
}
/* «Не указывать…» — та же строка/высота, что у районов; подпись приглушена. */
.lp-item--none .lp-item__name { color: var(--tg-hint); }
.lp-item__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.lp-item__name {
    font-size: 14px;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lp-item__sub {
    font-size: 12px;
    color: var(--tg-hint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Локация инлайн в ячейке «Город» инфо-сетки (этап 3b): view = текст #psCityView,
   edit = пикер #psLocationPicker на месте. Геолокация — иконка внутри поля города. */
.ps-location-picker { width: 100%; }

/* БАГ 4 + этап 3b: убираем отступы поля города в ячейке — input сидит заподлицо
   под лейблом «Город». Дубль-лейбл самого пикера скрыт (как в #peLocation профиля):
   остаётся только «Город» из ячейки. */
#psLocationPicker .lp-label { display: none; }
#psLocationPicker .lp-field { margin-bottom: 0; }
#psLocationPicker .lp-geo-hint { min-height: 0; margin: 0; }

/* Поле города в edit/create — инлайн-стиль как у названия (подчёркивание,
   прозрачный фон). id-scope перебивает боксовый .lp-loc-input. Подсказки/гео/
   крестик (.gs-loc-btn) и логика _updateLocBtn/_clear — как есть. */
#screen-plant[data-mode="edit"]   #psLocationPicker .lp-loc-input,
#screen-plant[data-mode="create"] #psLocationPicker .lp-loc-input {
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border-subtle);
    border-radius: 0;
    padding: 0 30px 4px 0;
    font-size: 14px;         /* совпадает с городом-текстом view (#psCityView) */
    font-weight: 400;        /* обычный вес — НЕ жирный как название */
    color: var(--tg-text);
}
#screen-plant[data-mode="edit"]   #psLocationPicker .lp-loc-input:focus,
#screen-plant[data-mode="create"] #psLocationPicker .lp-loc-input:focus {
    border-bottom-color: var(--accent);
    box-shadow: inset 0 -1px 0 0 var(--accent);
}
#psLocationPicker .gs-has-loc .lp-loc-input { padding-right: 30px; }
#psLocationPicker .gs-loc-btn { width: 28px; height: 28px; min-width: 0; min-height: 0; padding: 0; right: 0; }
#psLocationPicker .gs-loc-btn svg { width: 20px; height: 20px; }
#psLocationPicker .gs-loc-btn[data-mode="clear"] svg { width: 16px; height: 16px; }   /* единый крестик 16×16 (как название/auth) */

/* Дропдаун подсказок раскрывается ВНИЗ (position:absolute) — поднимаем пикер над
   соседними ячейками грида, чтобы список не клипался/не уходил под ряд Тип|Передача. */
#screen-plant[data-mode="edit"]   #psLocationPicker,
#screen-plant[data-mode="create"] #psLocationPicker { position: relative; z-index: 3; }
#psLocationPicker .lp-loc-suggestions { z-index: 4; }

/* БАГ 1: заголовок формы создания/редактирования растения */
/* B1: подзаголовок формы растения (вторичный текст) */

/* Пустой стейт «фильтр не дал результатов» — унифицирован
   в .gs-empty-state--compact (см. выше). */

/* ============================
   АДМИНКА
   ============================ */

.admin-page {
    /* Горизонтальный отступ задаёт .page-inner (12px) — здесь только вертикальный,
       чтобы все экраны админки имели единый отступ от краёв, как основные экраны. */
    padding: 16px 0;
    padding-bottom: var(--scroll-end-gap);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.admin-home {
    /* Обёртка главного экрана */
}

.admin-section-list {
    display: flex;
    flex-direction: column;
    gap: 1px;
    background: var(--divider-color, var(--border-subtle));
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.admin-section-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    background: var(--surface-2);
    cursor: pointer;
    transition: background 0.12s;
}

.admin-section-item:active {
    background: var(--surface-1);
}

.admin-section-icon {
    font-size: 20px;
    width: 28px;
    text-align: center;
    flex-shrink: 0;
}

.admin-section-title {
    flex: 1;
    font-size: 16px;
    font-weight: 500;
    color: var(--text-primary);
}

.admin-section-badge {
    background: var(--danger);
    color: var(--on-accent);
    font-size: 12px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    min-width: 20px;
    text-align: center;
    flex-shrink: 0;
}

.admin-section-arrow {
    color: var(--tg-hint);
    font-size: 18px;
    flex-shrink: 0;
}

/* Кнопка «Управление» в профиле */
.profile-admin-btn {
    display: block;
    width: 100%;
    padding: 14px;
    /* Единый зелёный акцент (как primary-кнопки) */
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    margin-top: 12px;
    transition: opacity 0.12s;
}

.profile-admin-btn:active {
    opacity: 0.75;
}

/* ============================
   МОДЕРАЦИЯ РАСТЕНИЙ
   ============================ */

/* Список карточек на модерации */
.admin-plant-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Карточка в списке */
.admin-plant-card {
    display: flex;
    gap: 12px;
    padding: 12px;
    background: var(--surface-2);
    border-radius: var(--radius-md);
    border: var(--card-border);
    cursor: pointer;
    transition: background 0.1s;
}

.admin-plant-card:active {
    background: var(--surface-1);
}

.admin-plant-card__photo {
    width: 64px;
    height: 64px;
    border-radius: var(--radius-sm);
    flex-shrink: 0;
    /* фон/фолбэк «нет фото» — от .gs-photo-slot (обёртка), img внутри cover */
}

.admin-plant-card__info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
}

.admin-plant-card__title {
    font-weight: 600;
    font-size: 15px;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.admin-plant-card__meta {
    font-size: 13px;
    color: var(--tg-hint);
}

/* Галерея фото в детальной карточке */
.admin-plant-gallery {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin: 0 -16px;
    padding: 0 16px;
}

.admin-plant-gallery::-webkit-scrollbar {
    display: none;
}

.admin-plant-gallery__img {
    width: 240px;
    height: 240px;
    object-fit: cover;
    border-radius: var(--radius-md);
    flex-shrink: 0;
    border: var(--card-border);
}

.admin-plant-gallery--empty {
    height: 180px;
    background: var(--surface-1);
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 100%;
}

/* Поля детальной карточки */
.admin-plant-detail__title {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 16px 0 12px;
    padding: 0;
}

.admin-plant-detail__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 9px 0;
    border-bottom: 1px solid var(--surface-1);
    font-size: 14px;
    color: var(--text-primary);
    gap: 8px;
}

.admin-plant-detail__label {
    color: var(--tg-hint);
    flex-shrink: 0;
}

.admin-plant-detail__desc {
    margin-top: 14px;
    font-size: 15px;
    color: var(--tg-text);
    line-height: 1.55;
}

/* Ссылка на профиль владельца */
.admin-owner-link {
    color: var(--accent);
    cursor: pointer;
    font-weight: 500;
    text-decoration: underline;
    text-decoration-style: dotted;
    text-underline-offset: 2px;
}

/* Плашка кнопок одобрить/отклонить */
.admin-moderation-actions {
    display: flex;
    gap: 8px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--surface-1);
    border-top: 1px solid var(--border-subtle);
    z-index: 10;
}

.admin-btn-reject {
    flex: 1;
    padding: 14px;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    cursor: pointer;
    transition: background 0.1s;
}

.admin-btn-reject:active {
    background: var(--surface-1);
}

.admin-btn-approve {
    flex: 1;
    padding: 14px;
    background: var(--accent);
    border: none;
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 600;
    color: var(--on-accent);
    cursor: pointer;
    transition: opacity 0.1s;
}

.admin-btn-approve:active {
    opacity: 0.8;
}

/* ============================
   РАЗДЕЛ ПОЛЬЗОВАТЕЛЕЙ В АДМИНКЕ
   ============================ */

/* Поле поиска */
.admin-search-wrap {
    margin-bottom: 12px;
}

/* Обёртка списка */
.admin-list-wrap {
    display: flex;
    flex-direction: column;
}

.admin-list-loading,
.admin-list-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--tg-hint);
    font-size: 14px;
}

/* Карточка пользователя */
.admin-user-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--surface-2);
    border-radius: var(--radius-md);
    border: var(--card-border);
    cursor: pointer;
    margin-bottom: 8px;
    transition: background 0.12s;
}

.admin-user-card:active {
    background: var(--surface-1);
}

.admin-user-card__info {
    flex: 1;
    min-width: 0;
}

.admin-user-card__name {
    font-weight: 600;
    font-size: 15px;
    color: var(--text-primary);
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
}

.admin-user-card__city {
    font-size: 13px;
    color: var(--tg-hint);
    font-weight: 400;
    flex-shrink: 0;
}

.admin-user-card__stats {
    font-size: 13px;
    color: var(--tg-hint);
    margin-top: 4px;
}

.admin-user-card__subscription {
    font-size: 12px;
    margin-top: 4px;
}

.admin-user-card__subscription.active  { color: var(--accent); }
.admin-user-card__subscription.inactive { color: var(--tg-hint); }

/* Кнопка ⚙️ */
.admin-edit-btn {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    background: var(--surface-1);
    border: none;
    font-size: 16px;
    cursor: pointer;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s;
}

.admin-edit-btn:active {
    background: var(--border-subtle);
}

/* ============================
   ЭКРАН УПРАВЛЕНИЯ ПОЛЬЗОВАТЕЛЕМ
   ============================ */

.admin-user-edit {
    /* Контейнер экрана управления */
}

.admin-user-info-card {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    border: var(--card-border);
    padding: 16px;
    margin-bottom: 16px;
}

.admin-user-info-card__name {
    font-size: 17px;
    font-weight: 700;
    color: var(--text-primary);
}

.admin-user-info-card__city {
    font-size: 13px;
    color: var(--tg-hint);
    margin-top: 2px;
}

.admin-user-info-card__stats {
    font-size: 13px;
    color: var(--tg-hint);
    margin-top: 8px;
}

.admin-user-info-card__row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 14px;
    color: var(--text-primary);
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--surface-1);
}

/* Статусы */
.admin-status-ok     { color: var(--accent); font-weight: 500; }
.admin-status-none   { color: var(--tg-hint); }
.admin-status-danger { color: var(--danger); font-weight: 500; }

/* Список кнопок действий */
.admin-action-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.admin-action-btn {
    width: 100%;
    padding: 14px 16px;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    cursor: pointer;
    text-align: left;
    transition: background 0.12s;
}

.admin-action-btn:active {
    background: var(--surface-1);
}

.admin-action-btn.danger {
    color: var(--danger);
    border-color: var(--danger);
}

.admin-action-btn.superadmin {
    color: var(--accent);
    border-color: var(--accent);
}

/* ============================
   TOAST-УВЕДОМЛЕНИЕ
   ============================ */

.admin-toast {
    position: fixed;
    bottom: 90px;
    left: 50%;
    transform: translateX(-50%) translateY(16px);
    background: var(--surface-inverse);
    color: var(--text-on-inverse);
    padding: 10px 20px;
    border-radius: var(--radius-pill);
    font-size: 14px;
    font-weight: 500;
    opacity: 0;
    transition: opacity 0.2s, transform 0.2s;
    z-index: 9999;
    white-space: nowrap;
    pointer-events: none;
    max-width: calc(100vw - 32px);
    text-overflow: ellipsis;
    overflow: hidden;
}

.admin-toast--show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.admin-toast--error {
    background: var(--danger);
}

/* ============================
   АДМИНКА — СДЕЛКИ
   ============================ */

.admin-reservation-card {
    display: flex;
    gap: 12px;
    padding: 12px;
    background: var(--surface-2);
    border-radius: var(--radius-md);
    border: var(--card-border);
    cursor: pointer;
    margin-bottom: 8px;
    transition: background 0.1s;
}

.admin-reservation-card:active {
    background: var(--surface-1);
}

.admin-reservation-card__photo {
    width: 64px;
    height: 64px;
    border-radius: var(--radius-sm);
    object-fit: cover;
    background: var(--surface-1);
    flex-shrink: 0;
}

.admin-reservation-card__info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.admin-reservation-card__title {
    font-weight: 600;
    font-size: 15px;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.admin-reservation-card__meta {
    font-size: 13px;
    color: var(--tg-hint);
}

/* Плашка «Изменено модератором» */
.admin-moderation-note {
    padding: 10px 14px;
    background: var(--surface-1);
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--tg-hint);
    margin: 8px 0;
}

/* Статус-опции в шите */
.admin-status-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 12px 0;
}

.admin-status-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: 15px;
    transition: border-color 0.12s, background 0.12s;
}

.admin-status-option.selected {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb), 0.06);
}

.admin-status-option:active:not(.selected) {
    background: var(--surface-1);
}

.admin-status-option__dot {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid var(--border-subtle);
    flex-shrink: 0;
    transition: border-color 0.12s, background 0.12s;
}

.admin-status-option.selected .admin-status-option__dot {
    border-color: var(--accent);
    background: var(--accent);
}

/* Кнопка «Изменить статус» */
.admin-change-status-btn {
    width: 100%;
    padding: 14px;
    background: var(--surface-inverse);
    color: var(--text-on-inverse);
    border: none;
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    transition: opacity 0.1s;
}

.admin-change-status-btn:active {
    opacity: 0.75;
}

/* Textarea комментария в шите изменения статуса */
.admin-comment-input {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-size: 14px;
    font-family: inherit;
    box-sizing: border-box;
    margin-top: 8px;
    resize: none;
    min-height: 72px;
    color: var(--text-primary);
    background: var(--surface-2);
    outline: none;
    transition: border-color 0.15s;
}

.admin-comment-input:focus {
    border-color: var(--accent);
}

/* ============================
   РАЗДЕЛ СТАТИСТИКИ В АДМИНКЕ
   ============================ */

.admin-stats-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 8px;
}

.admin-stat-card {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    border: var(--card-border);
    padding: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.admin-stat-card__value {
    font-size: 28px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1;
}

.admin-stat-card__label {
    font-size: 12px;
    color: var(--tg-hint);
    margin-top: 6px;
}

/* Выделение: «На модерации» и «Участники» если значение > 0 */
.admin-stat-card.highlight {
    border-color: var(--accent);
}

.admin-stat-card.highlight .admin-stat-card__value {
    color: var(--accent);
}

.admin-stats-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 16px;
    padding: 0 4px;
}

.admin-stats-updated {
    font-size: 12px;
    color: var(--tg-hint);
}

.admin-stats-refresh {
    background: none;
    border: none;
    font-size: 18px;
    cursor: pointer;
    color: var(--tg-hint);
    padding: 4px 8px;
    transition: transform 0.2s, color 0.15s;
}

.admin-stats-refresh:active {
    transform: rotate(180deg);
    color: var(--accent);
}

/* ───────── Admin: Economy section ───────── */
.admin-economy-group {
    margin-bottom: 20px;
}

.admin-economy-group__title {
    font-size: 12px;
    font-weight: 600;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 0 4px;
    margin-bottom: 6px;
}

.admin-economy-list {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    border: var(--card-border);
    overflow: hidden;
}

.admin-economy-item {
    display: flex;
    align-items: center;
    padding: 12px 16px;
    cursor: pointer;
    border-bottom: 1px solid var(--divider-color);
    gap: 12px;
}

.admin-economy-item:last-child {
    border-bottom: none;
}

.admin-economy-item:active {
    background: var(--surface-1);
}

.admin-economy-item__info {
    flex: 1;
    min-width: 0;
}

.admin-economy-item__desc {
    font-size: 14px;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.admin-economy-item__key {
    font-size: 11px;
    color: var(--tg-hint);
    margin-top: 2px;
    font-family: monospace;
}

.admin-economy-item__value {
    font-size: 15px;
    font-weight: 600;
    color: var(--accent);
    flex-shrink: 0;
}

.admin-economy-item__arrow {
    color: var(--tg-hint);
    font-size: 16px;
    flex-shrink: 0;
}

/* ───────── Browser dev login screen ───────── */
/* =========================
   ЭКРАН АВТОРИЗАЦИИ (auth_screen.js)
   ========================= */

.auth-overlay {
    position: fixed;
    inset: 0;
    background: var(--surface-1);
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px;
    box-sizing: border-box;
    overflow-y: auto;
}

/* Показ юр-документа в оверлее регистрации — полноэкранно сверху вниз (а не узкой
   центрированной карточкой). Класс вешается на #authOverlay на время документа
   (auth_screen.js:_showLegalDoc) и снимается при возврате к форме. */
.auth-overlay--doc { justify-content: flex-start; padding: 0; background: var(--surface-2); }
.auth-overlay--doc .auth-card {
    max-width: none; width: 100%; min-height: 100%;
    border-radius: 0; box-shadow: none; padding: 16px 12px;
    background: var(--surface-2);
}
.auth-overlay--doc .auth-brand { display: none; }
/* «← Назад» — компактная ссылка в левом углу, прижата к верху; фон белый (в тон
   документа → без видимой подложки), только чтобы прятать текст под sticky при скролле. */
.auth-overlay--doc .auth-resend {
    position: sticky; top: 0; z-index: 2;
    background: var(--surface-2); margin: 0 -12px; padding: 8px 12px;
    text-align: left;
}

/* Версия под карточкой, на сером фоне; ширина по карточке → текст у левого края */
.auth-version {
    width: 100%;
    max-width: 380px;
    text-align: left;
    margin-top: 8px;
    padding-left: 4px;
    font-family: var(--font-mono);   /* тех-подпись версии — моноширинный акцент */
}

.auth-card {
    background: var(--surface-2);
    border-radius: var(--radius-xl);
    padding: 32px 24px;
    width: 100%;
    max-width: 380px;
    box-shadow: var(--shadow-card);
}

.auth-logo {
    font-size: 48px;
    text-align: center;
    margin-bottom: 4px;
}

.auth-title {
    font-size: 24px;
    font-weight: 700;
    color: var(--text-primary);
    text-align: center;
    margin-bottom: 24px;
}

/* Бренд экрана входа — как .ob-header__brand онбординга: 🌿 GreenSwap 🌿, 28px/700 */
.auth-brand {
    font-size: 28px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--text-primary);
    text-align: center;
    margin: 0 0 6px 0;
}
/* Листья бренда входа — из gsLeaf: своя посадка + симметрия (без валютного margin),
   левый лист зеркалим (как топбар/онбординг/сторис). */
.auth-brand .gs-leaf { margin-left: 0; vertical-align: -0.1em; }
.auth-brand .gs-leaf:first-child { transform: scaleX(-1); }
/* Тёплый подзаголовок входа (не сухой --tg-hint), как .ob-header__subtitle */
.auth-brand-sub {
    font-size: 15px;
    font-weight: 400;
    line-height: 1.4;
    color: var(--text-primary);
    text-align: center;
    margin: 0 0 20px 0;
}
@media (max-width: 360px) {
    .auth-brand { font-size: 24px; }
}

/* Кружок «О проекте» на экране входа — вход в гостевые сторис. */
.auth-stories {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    margin: 0 0 22px;
}
.auth-stories__circle-wrap {
    position: relative;
    width: 96px;
    height: 96px;
}
/* Сегментированное кольцо — старт сегментов сверху (12 ч). */
.auth-stories__ring {
    position: absolute;
    inset: 0;
    transform: rotate(-90deg);
}
/* Внутренний круг: фон-стиль как у about + значок по центру (белый). */
.auth-stories__circle {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 84px;
    height: 84px;
    border: none;
    padding: 0;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--brand-white);
    background-color: var(--brand-olive);   /* фолбэк, если about-картинка не задана */
    background-size: cover;
    background-position: center;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
    transition: transform 0.12s ease;
}
.auth-stories__circle:active { transform: translate(-50%, -50%) scale(0.95); }
.auth-stories__circle svg {
    width: 30px;
    height: 30px;
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
}
.auth-stories__label {
    font-size: 13px;
    font-weight: 600;
    color: var(--tg-hint);
}

.auth-subtitle {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 20px;
}

.auth-label {
    font-size: 13px;
    color: var(--tg-hint);
    margin-bottom: 6px;
    margin-top: 14px;
}

.auth-input {
    width: 100%;
    padding: 13px 14px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-size: 15px;
    font-family: inherit;
    box-sizing: border-box;
    /* Лёгкая заливка — поле читается на белой карточке, но остаётся вторичным
       относительно оливковой Telegram-кнопки. Обводка сохранена. Покрывает и
       поле пароля входа (у него класс .auth-input .bl-pass-input). */
    background: var(--input-bg);
    color: var(--text-primary);
    transition: border-color 0.15s;
}

.auth-input:focus {
    outline: none;
    border-color: var(--accent);
}

.auth-btn-primary {
    width: 100%;
    padding: 14px;
    background: var(--accent);
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    margin-top: 20px;
    font-family: inherit;
    transition: opacity 0.12s;
}

.auth-btn-primary:active  { opacity: 0.85; }
.auth-btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }

/* Первичная кнопка входа через Telegram — крупнее и ярче email-формы (визуальный приоритет) */
.auth-btn-tg {
    width: 100%;
    padding: 16px;
    background: var(--accent);
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius-pill);
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    transition: opacity 0.12s;
}
.auth-btn-tg:active { opacity: 0.85; }

.auth-btn-secondary {
    width: 100%;
    padding: 14px;
    background: var(--surface-2);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    margin-top: 10px;
    font-family: inherit;
    transition: border-color 0.12s;
}

.auth-btn-secondary:active { border-color: var(--accent); }

.auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 20px 0;
    color: var(--tg-hint);
    font-size: 13px;
}

.auth-divider::before,
.auth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-subtle);
}

/* ── Экран ввода кода ── */

.auth-code-hint {
    font-size: 14px;
    color: var(--tg-hint);
    text-align: center;
    line-height: 1.5;
    margin-bottom: 20px;
}

.auth-code-email {
    font-weight: 600;
    color: var(--text-primary);
}

.auth-code-inputs {
    display: flex;
    gap: 8px;
    justify-content: center;
    margin-bottom: 4px;
}

.auth-code-input {
    width: 44px;
    height: 52px;
    text-align: center;
    font-size: 20px;
    font-weight: 600;
    border: 2px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    color: var(--text-primary);
    caret-color: transparent;
    font-family: inherit;
    transition: border-color 0.12s, background 0.12s;
}

.auth-code-input:focus {
    outline: none;
    border-color: var(--accent);
}

.auth-code-input.filled {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb), 0.06);
}

.auth-code-input:disabled {
    opacity: 0.5;
}

.auth-resend {
    font-size: 13px;
    color: var(--tg-hint);
    text-align: center;
    margin-top: 16px;
    line-height: 1.8;
}

.auth-resend-btn {
    background: none;
    border: none;
    color: var(--accent);
    font-size: 13px;
    cursor: pointer;
    padding: 0;
    font-family: inherit;
    font-weight: 500;
    text-decoration: underline;
    text-decoration-color: transparent;
    transition: text-decoration-color 0.12s;
}

.auth-resend-btn:hover:not(:disabled) {
    text-decoration-color: var(--accent);
}

.auth-resend-btn:disabled {
    color: var(--tg-hint);
    cursor: default;
    text-decoration: none;
}

/* ============================
   КНОПКИ МОДЕРАТОРА (plant_screen, внутри #psActions)
   ============================ */

#psModRejectBtn {
    flex: 1;
    padding: 14px;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    cursor: pointer;
    transition: background 0.1s;
}

#psModRejectBtn:active {
    background: var(--surface-1);
}

#psModApproveBtn {
    flex: 1;
    padding: 14px;
    background: var(--accent);
    border: none;
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 600;
    color: var(--on-accent);
    cursor: pointer;
    transition: opacity 0.1s;
}

#psModApproveBtn:active {
    opacity: 0.8;
}

/* ==============================
   ОНБОРДИНГ — поля формы (auth-overlay, auth-card и базовые
   классы уже объявлены выше в секции auth_screen.js)
   ============================== */

/* Поле формы */
.auth-field {
    text-align: left;
    margin-bottom: 16px;
}

.auth-field__label {
    display: block;
    font-size: 13px;
    font-weight: 500;
    color: var(--tg-hint);
    margin-bottom: 6px;
}

.auth-required {
    color: var(--danger);
    font-size: 12px;
}

.auth-field__input {
    width: 100%;
    padding: 13px 14px;
    border: 1.5px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-size: 16px;
    font-family: inherit;
    box-sizing: border-box;
    background: var(--surface-2);
    color: var(--text-primary);
    transition: border-color 0.15s;
}

.auth-field__input:focus {
    outline: none;
    border-color: var(--accent);
}

/* Обёртка поля под крестик очистки (email, имя онбординга/профиля, название растения).
   Крестик — внутри поля справа через absolute (тот же паттерн, что .gs-loc-btn). */
.auth-field__wrap { position: relative; }
.auth-field__wrap > input,
.auth-field__wrap > textarea {
    width: 100%;
    box-sizing: border-box;
    padding-right: 36px;   /* место под крестик */
}

.auth-field__clear {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    color: var(--tg-hint);
}
.auth-field__clear svg { width: 16px; height: 16px; }
.auth-field__clear.hidden { display: none; }

/* Валидация поля имени */
.auth-field__input--error { border: 2px solid var(--danger); }
.auth-field__error {
    margin: 6px 2px 0;
    font-size: 12px;
    color: var(--danger);
    line-height: 1.4;
}
.auth-field__error.hidden { display: none; }

/* Город с автодополнением */
.auth-city-wrap {
    position: relative;
}

.auth-city-suggestions {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--surface-3);
    border: 1.5px solid rgba(var(--tint-rgb), 0.1);
    border-radius: var(--radius-sm);
    z-index: 10;
    max-height: 180px;
    overflow-y: auto;
    box-shadow: var(--shadow-popover);
}

.auth-city-suggestions.hidden {
    display: none;
}

.auth-city-item {
    padding: 10px 14px;
    font-size: 14px;
    color: var(--tg-text);
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.05);
    text-align: left;
}

.auth-city-item:last-child {
    border-bottom: none;
}

.auth-city-item:active {
    background: rgba(var(--tint-rgb), 0.04);
}

/* Кнопка */
.auth-btn {
    display: block;
    width: 100%;
    padding: 13px 16px;
    background: var(--accent);
    color: var(--on-accent);
    border: none;
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    margin-top: 8px;
    transition: opacity 0.12s;
}

.auth-btn:active {
    opacity: 0.85;
}

.auth-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}


/* =========================
   АВАТАР: СПИННЕР ЗАГРУЗКИ
   ========================= */
.av-spinner {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 28px; height: 28px;
    border: 3px solid rgba(255, 255, 255, 0.4);
    border-top-color: var(--on-accent);
    border-radius: 50%;
    animation: avSpin 0.8s linear infinite;
}
@keyframes avSpin {
    to { transform: translate(-50%, -50%) rotate(360deg); }
}


/* =========================
   PULL-TO-REFRESH (pull_refresh.js)
   Индикатор — первый ребёнок секции, растущий in-flow зазор: при тяге контент
   сдвигается вниз, спиннер виден в открывшемся сверху зазоре (не поверх списка).
   ========================= */
.gs-ptr {
    flex: 0 0 auto;
    height: 0;                      /* зазор растёт из 0 по мере тяги (JS) */
    overflow: hidden;              /* спиннер проявляется по мере роста зазора */
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.gs-ptr--anim {
    transition: height .3s ease;    /* плавный возврат контента наверх */
}
.gs-ptr__spinner {
    width: 26px; height: 26px;
    border: 3px solid rgba(var(--tint-rgb), 0.14);
    border-top-color: var(--accent);
    border-radius: 50%;
    transition: opacity 0.2s ease;   /* синхронное гашение при коллапсе зазора */
}
/* Сворачивание зазора → гасим спиннер, чтобы overflow:hidden не резал его кромкой. */
.gs-ptr--collapsing .gs-ptr__spinner { opacity: 0; }
/* Крутим, когда порог взят (ready) и во время обновления (active). */
.gs-ptr--ready .gs-ptr__spinner,
.gs-ptr--active .gs-ptr__spinner {
    animation: gsPtrSpin .7s linear infinite;
}
@keyframes gsPtrSpin { to { transform: rotate(360deg); } }

/* Лёгкий спиннер поиска стола — справа в поле .search-box, пока идёт сетевой запрос
   поиска (мягкая перезагрузка без скелетона). Переиспользует @keyframes gsPtrSpin. */
.feed-search-spinner {
    flex: 0 0 auto;
    width: 16px; height: 16px;
    margin-left: 8px;
    border: 2px solid rgba(var(--tint-rgb), 0.14);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: gsPtrSpin 0.7s linear infinite;
}
.feed-search-spinner[hidden] { display: none; }

/* Скролл-секции PTR: overscroll-behavior:contain — жест не проваливается в
   системный bounce (индикатор теперь in-flow, position:relative не нужен). */
#tab-feed, #tab-deals, #tab-profile {
    overscroll-behavior-y: contain;
}
@media (prefers-reduced-motion: reduce) {
    .gs-ptr__spinner { animation: none; }
}


/* =========================
   ЗАГОЛОВОК ОНБОРДИНГА
   ========================= */
.ob-header {
    text-align: center;
    margin-bottom: 8px;
}
.ob-header__welcome {
    font-size: 15px;
    font-weight: 400;
    color: var(--text-primary);
    margin: 0 0 4px 0;
}
.ob-header__brand {
    font-size: 28px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 6px 0;
    line-height: 1.1;
}
.ob-header__subtitle {
    font-size: 15px;
    font-weight: 400;
    color: var(--text-primary);
    margin: 0 0 16px 0;
    line-height: 1.4;
}
.ob-header__intro {
    font-size: 15px;
    font-weight: 400;
    color: var(--text-primary);
    text-align: center;
    margin: 0 0 12px 0;
}
@media (max-width: 360px) {
    .ob-header__brand { font-size: 24px; }
}


/* =========================
   ГАЛКА СОГЛАСИЯ (онбординг)
   ========================= */
/* ── Поле города на онбординге: внутренний лейбл пикера скрыт — над ним свой с звёздочкой.
   Подавляем lp-geo-hint и margin поля — так же, как в #peLocation профиля. ── */
#obLocation .lp-label { display: none; }
#obLocation .lp-field { margin-bottom: 0; }
#obLocation .lp-geo-hint { min-height: 0; margin: 0; }

/* Пустой блок ошибки не должен резервировать место — иначе создаёт лишний зазор
   перед спойлером «О себе». Схлопываем когда пустой. */
#obError:empty { min-height: 0; margin: 0; }

/* ── Спойлер «О себе» на онбординге ── */
.ob-bio-spoiler {
    margin: 0 0 12px;
}

.ob-bio-spoiler__toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    width: 100%;
    text-align: left;
    margin-bottom: 6px;
}

/* Текст «О СЕБЕ» — тот же стиль, что pe-label (заголовки «ИМЯ», «ГОРОД…») */
.ob-bio-spoiler__toggle span {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--tg-hint);
}

.ob-bio-spoiler__chevron {
    transition: transform 0.2s ease;
    flex-shrink: 0;
}

.ob-bio-spoiler__body {
    padding-top: 0;
}

.ob-bio-textarea {
    width: 100%;
    resize: none;
    min-height: 80px;
    box-sizing: border-box;
}

.ob-consent {
    margin: 4px 0 16px;
}

.ob-consent__label {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
}

/* Нативный input скрыт, но остаётся доступным */
.ob-consent__checkbox {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.ob-consent__box {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    margin-top: 1px;
    border: 2px solid var(--border-subtle);
    border-radius: 6px;
    background: transparent;
    transition: border-color 0.15s, background 0.15s;
    position: relative;
}

/* Белая галочка через SVG-маску при отметке */
.ob-consent__checkbox:checked + .ob-consent__box {
    border-color: var(--accent);
    background: var(--accent);
}

.ob-consent__checkbox:checked + .ob-consent__box::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px 14px;
}

.ob-consent__text {
    font-size: 13px;
    line-height: 1.4;
    color: var(--tg-hint);
}

.ob-consent__link {
    color: var(--tg-hint);
    text-decoration: underline;
}
.ob-consent__link:hover {
    color: var(--accent);
    text-decoration: none;
}

@keyframes obConsentShake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
}

.ob-consent__box--error {
    border-color: var(--danger);
    animation: obConsentShake 0.3s ease;
}


/* =========================
   УВЕДОМЛЕНИЯ
   ========================= */

/* Контейнер экрана */
.notifications-container {
    /* Горизонтальный отступ как у .page-inner (12px) — карточки на всю ширину контента.
       Верхний отступ 0: sticky-тулбар прижат к шапке (как на Столе), свой 6px даёт .feed-toolbar. */
    padding: 0 12px var(--scroll-end-gap);
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* ── Управление под шапкой ────────────────────────────────── */
.notif-actions-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 0 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid rgba(var(--tint-rgb), 0.06);
}

.notif-action-link {
    background: none;
    border: none;
    font-size: 13px;
    color: var(--tg-hint);
    cursor: pointer;
    padding: 4px 0;
    line-height: 1;
    transition: opacity 0.15s;
}
/* Подчёркивание при наведении — только на устройствах с курсором (на тач не залипает после тапа) */
@media (hover: hover) {
    .notif-action-link:hover { text-decoration: underline; text-underline-offset: 2px; }
}
/* Короткий отклик при тапе на телефоне — без залипания */
.notif-action-link:active { opacity: 0.55; }

/* Список */
.notif-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;   /* воздух между sticky-тулбаром и первой карточкой */
    padding-bottom: var(--scroll-end-gap);
}

/* Иконка-кнопка в тулбаре («Прочитать все») — квадратная, тот же стиль .feed-btn. */
.feed-btn--icon {
    padding: 7px 9px;
    line-height: 0;   /* svg по центру без лишней высоты строки */
}

/* Карточка уведомления */
/* Плитка уведомления: эмодзи | контент(2 строки) | шеврон — компактная высота. */
.notif-item {
    display: flex;
    align-items: center;         /* эмодзи и шеврон по вертикальному центру */
    gap: 10px;
    padding: 10px 12px;
    background: var(--surface-2);
    border: var(--card-border);
    border-radius: var(--radius-md);
    cursor: default;
    transition: transform 0.1s ease-out;
}

.notif-item--unread {
    cursor: pointer;
}

.notif-item--unread:active {
    transform: scale(0.98);
}

/* Эмодзи категории — колонка слева. */
.notif-item__icon {
    flex-shrink: 0;
    width: 24px;
    font-size: 19px;
    line-height: 1;
    text-align: center;
}

.notif-item__body {
    flex: 1;
    min-width: 0;
}

/* Верхняя строка: заголовок (растёт) + точка непрочитанного + дата в углу. */
.notif-item__top {
    display: flex;
    align-items: center;
    gap: 6px;
}

.notif-item__title {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Точка непрочитанного — рядом с датой, только у .notif-item--unread. */
.notif-item__dot {
    flex-shrink: 0;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    display: none;
}
.notif-item--unread .notif-item__dot {
    display: block;
}

.notif-item__time {
    flex-shrink: 0;
    font-size: 11px;
    color: var(--tg-hint);
    opacity: 0.8;
    white-space: nowrap;
}

/* Нижняя строка: текст в ОДНУ строку с обрезкой. */
.notif-item__text {
    font-size: 13px;
    color: var(--tg-hint);
    line-height: 1.35;
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Шеврон справа — приглушённый, по вертикальному центру. */
.notif-item__chevron {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    color: var(--tg-hint);
    opacity: 0.6;
}

/* Пустой стейт и лоадер */
/* .notif-empty унифицирован в .gs-empty-state--inline */
/* Спиннер догрузки: постоянная высота, JS переключает visibility (не display),
   иначе появление блока толкает низ списка при infinite-scroll. */
.notif-spinner {
    text-align: center;
    color: var(--tg-hint);
    font-size: 14px;
    height: 40px;
    line-height: 40px;
    margin: 0;
}

/* Индикатор догрузки истории листочков (infinite-scroll).
   Постоянная высота + visibility — см. .notif-spinner. */
.leaves-spinner {
    text-align: center;
    color: var(--tg-hint);
    font-size: 14px;
    height: 40px;
    line-height: 40px;
}

/* ── Центральная модалка gsModal (общий компонент) ──────────────────────────
   Каркас вынесен из прежней .notif-modal/.notif-detail (детали уведомления теперь
   рендерятся через gsModal.show). z-index 10001 — ВЫШЕ нижнего шита GsSheet (10000):
   confirm поверх открытого шита не прячется. safe-area снизу — крестик/кнопки не
   уходят под «чёлку» при max-height:85vh на маленьких экранах. */
.gs-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    z-index: 10001;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px));
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
}
.gs-modal-overlay.visible { opacity: 1; pointer-events: auto; }

.gs-modal {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    max-width: 400px;
    max-height: 85vh;
    overflow-y: auto;
    background: var(--tg-bg);
    border-radius: var(--radius-lg);
    padding: 26px 20px 20px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    transform: scale(0.96);
    transition: transform 0.18s ease;
}
.gs-modal-overlay.visible .gs-modal { transform: scale(1); }

.gs-modal__close {
    position: absolute;
    top: 6px;
    right: 8px;
    background: none;
    border: none;
    font-size: 26px;
    line-height: 1;
    color: var(--tg-hint);
    cursor: pointer;
    padding: 4px 10px;
}

.gs-modal__title {
    font-size: 18px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 10px;
    line-height: 1.3;
    text-align: center;
}

/* Черта под заголовком — короткая линия В ЦВЕТ кнопки действия. */
.gs-modal__divider {
    width: 44px;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
    margin: 0 auto 12px;
}
.gs-modal__divider--primary { background: var(--accent); }
.gs-modal__divider--danger  { background: var(--danger); }
.gs-modal__divider--neutral { background: var(--border-subtle); }

/* Описание confirm/alert — по центру, приглушённое. */
.gs-modal__desc {
    font-size: 14px;
    color: var(--tg-hint);
    line-height: 1.5;
    text-align: center;
    width: 100%;
    margin-bottom: 18px;
}

/* Дата (модалка уведомления, через gsModal.show). */
.gs-modal__date {
    font-size: 12px;
    color: var(--tg-hint);
    margin-bottom: 14px;
}

/* Тело с выравниванием по ЛЕВОМУ краю (модалка уведомления). */
.gs-modal__text {
    font-size: 15px;
    color: var(--text-primary);
    line-height: 1.5;
    white-space: pre-line;
    text-align: left;
    width: 100%;
    margin-bottom: 18px;
}
/* welcome — тело по центру (только этот тип; прочие остаются слева) */
.gs-modal__text--center { text-align: center; }

/* Кнопки В РЯД, равной ширины; одна кнопка → на всю ширину (единственный flex:1). */
.gs-modal__actions {
    display: flex;
    flex-direction: row;
    gap: 10px;
    width: 100%;
}

.gs-modal__btn {
    flex: 1 1 0;   /* равная ширина в ряду; одна кнопка → на всю ширину */
    min-width: 0;
    padding: 13px 16px;
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 600;
    border: none;
    cursor: pointer;
    box-shadow: none;
    transition: opacity 0.15s, transform 0.12s;
    white-space: nowrap;
}

.gs-modal__btn:active { transform: scale(0.98); }

.gs-modal__btn--primary {
    background: var(--accent);
    color: var(--on-accent);
}
.gs-modal__btn--danger {
    background: var(--danger);
    color: var(--on-accent);
}
.gs-modal__btn--neutral,
.gs-modal__btn--secondary {
    background: var(--border-subtle);
    color: var(--text-primary);
}

/* topbar-right — обёртка для пилюль (уведомления + листочки) */
.topbar-right {
    display: flex;
    align-items: center;
    gap: 0;
}

/* Скрываем нулевое значение счётчика в обеих пилюлях шапки */
#notifCount[data-zero="true"],
#leafBalance[data-zero="true"] {
    display: none;
}

/* =========================
   НАСТРОЙКИ УВЕДОМЛЕНИЙ (редактирование профиля)
   ========================= */

/* ── Полноэкранный экран «Настройки» (#tab-settings) ──────────────── */
/* Секционный каркас: белые карточки-секции на ивори-фоне, готов к росту. */
.settings-screen {
    padding: 12px 16px calc(var(--scroll-end-gap) + 20px);
}
.settings-section {
    background: var(--surface-2);
    border: var(--card-border);
    border-radius: var(--radius-lg);
    padding: 4px 16px 16px;
    margin-bottom: 12px;
}
.settings-section__title {
    font-size: 13px;
    font-weight: 700;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 14px 0 2px;
}
/* Переключатель темы: три равных сегмента (Светлая / Тёмная / Системная).
   Активный — заливка акцентом, остальные — поверхность 2 с мягкой рамкой. */
.theme-switch {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-top: 10px;
}
.theme-switch__opt {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;

    padding: 12px 4px;
    border-radius: var(--radius-md);
    border: 1.5px solid var(--border-subtle);
    background: var(--surface-2);
    color: var(--text-primary);

    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.12s;
}
.theme-switch__opt:active { transform: scale(0.97); }
.theme-switch__opt.is-active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);   /* .gs-icon внутри — stroke:currentColor, красится сам */
}

/* Внутри секции первая .profile-notif-section без верхней линии/отступа. */
.settings-section .profile-notif-section:first-of-type {
    margin-top: 8px;
    padding-top: 0;
    border-top: none;
}

/* ── Помощь (список статей + статья) ── */
.help-page {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 0 calc(var(--scroll-end-gap) + 20px);
}
.help-card {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 14px 16px;
    background: var(--surface-2);
    border: var(--card-border);
    border-radius: var(--radius-lg);
    text-align: left;
    cursor: pointer;
    transition: transform 0.12s ease;
}
.help-card:active { transform: scale(0.98); }
.help-card__icon {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
}
.help-card__title {
    flex: 1;
    min-width: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary);
}
.help-card__chevron {
    color: var(--tg-hint);
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* Карточка-ссылка (раздел «Документы») — тот же вид, без подчёркивания <a>. */
a.help-card { text-decoration: none; color: inherit; }
/* Подзаголовок группы в «Помощи» (напр. «Документы»). */
.help-section-title { font-size: 14px; font-weight: 700; color: var(--tg-text); margin: 10px 0 0; }

/* Правовой документ, показанный in-app (тело фетчится из публичного HTML, инжектится
   в .legal-doc). Scoped-оформление — НЕ глобальные h1/h2/p (инлайн-стили страниц не
   тащим). Применяется и в SPA-экране #tab-legal-doc, и в оверлее регистрации. */
/* Белый фон экрана документа из «Помощи» (как у оверлея регистрации и standalone). */
#tab-legal-doc { background: var(--surface-2); }
.legal-doc { color: var(--text-primary); line-height: 1.6; padding: 8px 0 12px; }
.legal-doc h1 { font-size: 22px; margin: 0 0 4px; line-height: 1.25; text-align: center; }
.legal-doc h2 { font-size: 18px; margin: 22px 0 8px; }
.legal-doc h3 { font-size: 16px; margin: 18px 0 6px; }
.legal-doc p  { color: var(--tg-text); margin: 8px 0; }
.legal-doc ul,
.legal-doc ol { color: var(--tg-text); margin: 8px 0; padding-left: 22px; }
.legal-doc li { margin: 4px 0; }
.legal-doc a  { color: var(--accent); }
.legal-doc .doc-meta { color: var(--tg-hint); font-size: 14px; margin: 0 0 8px; text-align: center; }
.legal-doc table { border-collapse: collapse; width: 100%; margin: 10px 0; font-size: 14px; }
.legal-doc th,
.legal-doc td { border: 1px solid rgba(var(--tint-rgb), 0.12); padding: 6px 8px; text-align: left; }

.help-article__body {
    background: var(--surface-2);
    border: var(--card-border);
    border-radius: var(--radius-lg);
    padding: 16px;
    font-size: 15px;
    line-height: 1.5;
    color: var(--text-primary);
}
/* Блоки тела статьи (строятся узлами в _renderArticleBody). */
.help-article__p  { margin: 0 0 10px; }
.help-article__p:last-child { margin-bottom: 0; }
.help-article__sub {
    margin: 18px 0 8px;
    color: var(--text-accent);
    font-weight: 500;
}
.help-article__sub:first-child { margin-top: 0; }
.help-article__li {
    display: flex;
    gap: 9px;
    margin: 0 0 6px;
}
.help-article__li-dot { color: var(--accent); flex-shrink: 0; }
.help-article__lead { font-weight: 500; }
/* Внутристатейная ссылка (токен [текст](тип:арг)). */
.help-article__link {
    color: var(--accent);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.profile-notif-section {
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid var(--border-subtle);
}

.profile-notif-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 12px;
}

.profile-notif-section-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--tg-hint);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 12px;
}

.profile-notif-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 0;
    border-bottom: 1px solid var(--divider-color, rgba(var(--tint-rgb), 0.06));
}

/* Вложенная подгруппа (звук/вибрация под «В приложении») — отступ + левая линия иерархии */
.profile-notif-subgroup {
    margin-left: 14px;
    padding-left: 12px;
    border-left: 2px solid var(--border-subtle);
}
/* Приглушение, когда «В приложении» выключено — звук/вибрация ни на что не влияют */
.profile-notif-subgroup.is-disabled {
    opacity: 0.45;
    pointer-events: none;
}

.profile-notif-row:last-child {
    border-bottom: none;
}

.profile-notif-label {
    font-size: 15px;
    color: var(--text-primary);
}

/* ── Web push (блок настроек) ─────────────────────────────────────── */
/* Подсказка/статус под тумблером (denied / не поддерживается / iPhone Safari). */
.push-hint {
    font-size: 13px;
    color: var(--tg-hint);
    line-height: 1.4;
    margin-top: 4px;
}

/* Адаптивная инструкция включения push (нумерованные шаги + «Подробнее») */
.push-instruction {
    margin-top: 10px;
    background: rgba(91, 122, 57, 0.08);
    border-radius: var(--radius-md);
    padding: 12px 14px;
}
.push-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.push-steps__item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 13px;
    line-height: 1.4;
    color: var(--text-primary);
}
.push-steps__num {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 12px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
.push-steps__icon {
    flex-shrink: 0;
    width: 19px;
    height: 19px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.push-steps__icon svg { width: 19px; height: 19px; display: block; }
.push-steps__text { flex: 1; min-width: 0; }

/* Выполненный шаг: галочка (акцент) вместо иконки + приглушённый текст */
.push-steps__item--done .push-steps__icon {
    color: var(--accent);
    font-size: 15px;
    font-weight: 700;
}
.push-steps__item--done .push-steps__text { color: var(--tg-hint); }
.push-more {
    display: inline-block;
    margin-top: 10px;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent);
    text-decoration: underline;
    cursor: pointer;
}

/* Тогл — label-обёртка с hidden input + slider */
.profile-notif-toggle {
    position: relative;
    width: 44px;
    height: 26px;
    flex-shrink: 0;
}

.profile-notif-toggle input {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}

.profile-notif-slider {
    position: absolute;
    inset: 0;
    background: var(--border-subtle);
    border-radius: var(--radius-pill);
    transition: background 0.2s;
    cursor: pointer;
}

.profile-notif-slider::before {
    content: '';
    position: absolute;
    width: 20px;
    height: 20px;
    left: 3px;
    top: 3px;
    background: white;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
    transition: transform 0.2s;
}

.profile-notif-toggle input:checked + .profile-notif-slider {
    background: var(--accent);
}

.profile-notif-toggle input:checked + .profile-notif-slider::before {
    transform: translateX(18px);
}

.profile-notif-toggle input:disabled + .profile-notif-slider {
    cursor: not-allowed;
    opacity: 0.45;
}

/* =========================
   ОПАСНАЯ ЗОНА (удаление аккаунта)
   ========================= */

.profile-danger-zone {
    margin-top: 8px;
    text-align: center;
}

.profile-delete-link {
    font-size: 13px;
    color: var(--tg-hint);
    cursor: pointer;
    text-decoration: none;
}

/* =========================
   АДМИНКА: УПРАВЛЕНИЕ СТОЛАМИ
   ========================= */

.admin-table-list {
    padding: 16px 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-bottom: var(--scroll-end-gap);
}

.admin-table-card {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    padding: 14px 16px;
    border: var(--card-border);
    cursor: pointer;
    transition: background 0.12s;
}

.admin-table-card:active {
    background: var(--surface-1);
}

.admin-table-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
}

.admin-table-card__name {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary);
}

.admin-table-card__meta {
    font-size: 12px;
    color: var(--tg-hint);
    margin-bottom: 4px;
}

.admin-table-card__count {
    font-size: 13px;
    color: var(--tg-hint);
}

/* Форма редактирования стола */

.admin-form-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.admin-form-label {
    font-size: 13px;
    font-weight: 500;
    color: var(--tg-hint);
}

.admin-form-input {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    border: 1.5px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    font-size: 15px;
    color: var(--text-primary);
    background: var(--surface-2);
    outline: none;
    transition: border-color 0.15s;
}

.admin-form-input:focus {
    border-color: var(--accent);
}

.admin-form-input:disabled {
    background: var(--surface-1);
    color: var(--tg-hint);
    cursor: not-allowed;
}

.admin-form-divider {
    height: 1px;
    background: var(--border-subtle);
    margin: 4px 0;
}

.admin-form-readonly {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.admin-form-readonly__row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 14px;
}

.admin-form-readonly__label {
    color: var(--tg-hint);
}

.admin-form-readonly__value {
    color: var(--text-primary);
    font-weight: 500;
    font-family: monospace;
    font-size: 13px;
}

/* Тогл (переключатель) */

.admin-toggle {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 26px;
    flex-shrink: 0;
}

.admin-toggle input {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}

.admin-toggle__slider {
    position: absolute;
    inset: 0;
    background: var(--border-subtle);
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: background 0.2s;
}

.admin-toggle__slider::before {
    content: "";
    position: absolute;
    width: 20px;
    height: 20px;
    left: 3px;
    top: 3px;
    background: white;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
    transition: transform 0.2s;
}

.admin-toggle input:checked + .admin-toggle__slider {
    background: var(--accent);
}

.admin-toggle input:checked + .admin-toggle__slider::before {
    transform: translateX(18px);
}

.admin-toggle input:disabled + .admin-toggle__slider {
    cursor: not-allowed;
    opacity: 0.45;
}


/* =========================
   ОБЩИЙ ERROR STATE
   ========================= */

.gs-error-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 48px 24px;
}

.gs-error-state__icon {
    font-size: 40px;
    margin-bottom: 12px;
}

.gs-error-state__title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 8px;
}

.gs-error-state__desc {
    font-size: 14px;
    color: var(--tg-hint);
    margin-bottom: 20px;
    line-height: 1.4;
}

.gs-error-state__btn {
    padding: 11px 24px;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
}

/* ===== Справочники ===== */

.admin-dict-list {
    padding: 16px 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-bottom: var(--scroll-end-gap);
}

.admin-dict-card {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    padding: 14px 16px;
    border: var(--card-border);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.admin-dict-card__name {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary);
}

.admin-dict-card__source {
    font-size: 12px;
    color: var(--tg-hint);
}

.admin-dict-card__stats {
    font-size: 13px;
    color: var(--tg-hint);
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 6px;
}

.admin-dict-card__footer {
    margin-top: 10px;
}

.admin-dict-card__btn {
    width: 100%;
}



/* ==== bottom_nav.css ==== */
.bottom-nav {
    /* Позиционирование, фон, бордер — в ui.css */
}

.bottom-nav__item {
    flex: 1;

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    padding-top: 2px;
    border: none;
    background: none;
    color: var(--tg-hint);
    font-size: 13px;

    cursor: pointer;
}

.bottom-nav__pill {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    border-radius: 12px;
    padding: 2px 14px 2px;
    transition: background 0.15s ease;
}

.bottom-nav__icon {
    font-size: 20px;
    line-height: 22px;
    display: block;
    text-align: center;
}

.bottom-nav__label {
    font-size: 11px;
    line-height: 1.2;
}

.bottom-nav__item--active .bottom-nav__pill {
    background: rgba(91, 122, 57, 0.14);
}

.bottom-nav__item--active {
    color: var(--accent, #5B7A39);
    font-weight: 600;
}

/* Открытая клавиатура → скрыть нижнюю панель на ВСЕХ экранах (поиск/фильтр Стола,
   чат сделки, поля растения edit/create, профиль-поля). Класс gs-kb-open ставит
   глобальный visualViewport-детектор (_gsInitKeyboardDetector, app.js). Плавающие
   бары (композер сделки, #psActions растения) позиционируются сами. */
body.gs-kb-open .bottom-nav {
    display: none !important;
}

/* Экран растения нав НЕ скрывает: .bottom-nav — position:fixed; bottom:0, при
   открытой клавиатуре (overlay-режим) остаётся у layout-низа ЗА клавиатурой, над
   ней не всплывает → скрывать незачем. #psActions стоит НАД навом (резерв под нав
   в .page-inner). Прежнее скрытие (body.plant-editing / :has(tab--active)) убрано:
   давало мелькание (live-toggle по режиму/анимации) и путаницу с кнопками. */