@font-face {
    font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
    src: url(/fonts/inter-cyrillic.woff2) format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  }
  @font-face {
    font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
    src: url(/fonts/inter-latin.woff2) format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }
  @font-face {
    font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 100 900; font-display: swap;
    src: url(/fonts/cormorant-cyrillic.woff2) format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  }
  @font-face {
    font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 100 900; font-display: swap;
    src: url(/fonts/cormorant-latin.woff2) format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

/* Golos и Manrope раньше лежали одним файлом на каждый шрифт. Теперь они
   разрезаны на русский и латиницу, как Inter выше: так браузер не тянет
   полкилобайта латинских знаков, которые в русском окне не нужны. */
@font-face {
    font-family: 'Golos Text'; font-style: normal; font-weight: 400 700; font-display: swap;
    src: url(/fonts/golos-cyrillic.woff2) format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  }
  @font-face {
    font-family: 'Golos Text'; font-style: normal; font-weight: 400 700; font-display: swap;
    src: url(/fonts/golos-latin.woff2) format('woff2');
  }
  @font-face {
    font-family: 'Manrope'; font-style: normal; font-weight: 400 800; font-display: swap;
    src: url(/fonts/manrope-cyrillic.woff2) format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  }
  @font-face {
    font-family: 'Manrope'; font-style: normal; font-weight: 400 800; font-display: swap;
    src: url(/fonts/manrope-latin.woff2) format('woff2');
  }

:root {
    /* Стрелка выпадающего списка: рисуем сами, потому что системную вместе
       с appearance приходится гасить целиком. Цвет свой на каждую тему. */
    --chevron: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2380899c' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6'/%3E%3C/svg%3E");
    --bg: hsl(230 25% 7%);
    --panel: hsl(230 22% 10%);
    --panel-2: hsl(230 20% 12.5%);
    --panel-3: hsl(230 20% 14%);
    --panel-4: hsl(230 18% 16%);
    --sunken: hsl(230 24% 8.5%);
    --border: hsl(230 16% 20%);
    --border-2: hsl(230 16% 25%);
    --line: hsl(230 16% 18%);
    --text: hsl(240 20% 92%);
    --text-2: hsl(240 14% 84%);
    --muted: hsl(233 12% 55%);
    --muted-2: hsl(233 14% 62%);
    --faint: hsl(233 10% 46%);
    /* Тот же фиолетовый, но поднятый по светлоте: на тёмном фоне
       исходный тон выглядит грязным пятном. */
    --gold-hsl: 245 78% 68%;
    --gold: hsl(245 78% 68%);
    --gold-deep: hsl(245 62% 56%);
    --gold-soft: hsl(245 85% 76%);
    --gold-bright: hsl(245 90% 82%);
    --gold-tint: hsl(245 45% 22% / .55);
    --gold-wash: hsl(245 40% 20% / .45);
    --gold-wash-2: hsl(245 42% 22% / .6);
    /* Заливка акцентом там, где поверх неё идёт текст. Чуть глубже --gold:
       сам акцент поднят по светлоте, чтобы читаться буквами на тёмном фоне,
       и белая надпись на нём была бы на грани различимости. Отдельный токен,
       а не правка --gold, — иначе вместе с заливкой потускнели бы ссылки и
       значки, которые этим же цветом написаны. */
    --gold-fill: hsl(245 72% 62%);
    /* Текст на фиолетовой заливке — белый, как в светлой теме: тёмная буква
       на ярком пятне выглядела вырезанной дыркой. */
    --on-accent: hsl(0 0% 100%);
    --on-accent-hsl: 0 0% 100%;
    /* Красная плашка светлая в обеих темах наоборот: на ней текст тёмный. */
    --on-danger: hsl(230 30% 8%);
    /* Тревога поверх фиолетовой заливки. Одна на обе темы: заливка в обеих
       фиолетовая, а --danger и --warn считаются от фона окна и на ней либо
       тонут, либо режут глаз. */
    --warn-on-accent-hsl: 45 100% 82%;
    /* Занавес поверх переписки, когда на неё тащат файл: цвет фона окна,
       а не «цвет текста на акценте» — они больше не совпадают. */
    --drop-veil: hsl(230 25% 7% / .82);
    --danger: hsl(4 72% 68%);
    --danger-line: hsl(4 60% 50%);
    --danger-line-hsl: 4 60% 50%;
    --warn: hsl(38 88% 66%);
    --warn-line-hsl: 38 80% 50%;
    --ok: hsl(164 58% 55%);
    --ok-line: hsl(164 62% 42%);
    --ok-line-hsl: 164 62% 42%;
    --tg-color: hsl(199 68% 66%);
    --tg-line-hsl: 199 60% 48%;
    --chart-in: hsl(245 55% 58%);
    --bubble-out: hsl(245 40% 22% / .85);
    --quote-bg: hsl(230 20% 16% / .7);
    --overlay-soft: hsl(230 28% 5% / .78);
    --skeleton-shine: hsl(230 18% 20%);
    --wave-off: hsl(245 40% 46% / .55);
    --wave-on: hsl(245 60% 62%);
    --scroll-track: hsl(230 20% 12%);
    --scroll-thumb-hover: hsl(245 35% 32%);
    --shadow: 0 2px 16px -2px hsl(230 30% 3% / .6);
    --shadow-lg: 0 26px 54px -26px rgba(0, 0, 0, 1);
    /* Чернильный блок разбора умной модели. В тёмной теме он темнее фона —
       иначе разбор сливался бы с карточкой, а это её главный текст. */
    --ink: hsl(230 30% 4%);
    --ink-text: hsl(240 16% 86%);
    --ink-line: hsl(230 18% 17%);
    --ink-accent: hsl(245 85% 78%);

    /*
     * Цифры и ключи набираются тем же шрифтом, что и текст: машинописный
     * рядом с Inter выглядел чужим. Ровные колонки держит tabular-nums —
     * для этого моноширинный не нужен.
     */
    --num: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --serif: 'Manrope', 'Golos Text', Georgia, serif;
  }
  @media (prefers-color-scheme: light) {
    :root:not([data-theme='dark']) {
    --chevron: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%235c6373' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6'/%3E%3C/svg%3E");
    /* Поверхности: фон — светлая бумага, панели — белые. Главная правка:
       раньше --bg и --panel были одинаково белыми, поэтому карточки, шапка и
       список сливались в одно полотно. Оттенок холодный, от фиолетового
       акцента продукта: тёплая бумага рядом с ним читалась бы как грязь. */
    --bg: hsl(248 30% 95%);
    --panel: hsl(0 0% 100%);
    --panel-2: hsl(250 45% 98%);
    --panel-3: hsl(248 40% 96.5%);
    --panel-4: hsl(248 30% 92%);
    /* Впадины (композер, полоса задачи, сводная строка) теперь темнее панели,
       а не белее белого. */
    --sunken: hsl(248 32% 93.5%);
    /* Границы: было 91% — на белом их не видно. */
    --border: hsl(246 24% 84%);
    --border-2: hsl(244 22% 74%);
    --line: hsl(246 26% 89%);
    --text: hsl(222 32% 10%);
    --text-2: hsl(222 18% 25%);
    --muted: hsl(222 12% 40%);
    --muted-2: hsl(222 14% 32%);
    /* Времена сообщений 11px были почти нечитаемы. */
    --faint: hsl(222 10% 48%);
    /* Фиолетовый — акцент продукта. Заливка светлее, акцентный текст темнее:
       одним тоном не обойтись, он либо не читается на белом, либо слишком
       глухой под белым текстом. gold-hsl идёт в полупрозрачные обводки
       hsl(var(--gold-hsl) / .4) — на белом они должны быть видны. */
    --gold-hsl: 246 62% 50%;
    --gold: hsl(244 68% 54%);
    --gold-deep: hsl(246 62% 46%);
    --gold-soft: hsl(246 64% 44%);
    --gold-bright: hsl(248 66% 36%);
    --gold-tint: hsl(246 80% 93%);
    --gold-wash: hsl(246 85% 96.5%);
    --gold-wash-2: hsl(246 80% 93.5%);
    /* Заливка акцентом здесь и так глубокая — белый текст на ней читается. */
    --gold-fill: hsl(244 68% 54%);
    /* На фиолетовой заливке текст белый, а не тёмный. */
    --on-accent: hsl(0 0% 100%);
    --on-accent-hsl: 0 0% 100%;
    --on-danger: hsl(0 0% 100%);
    /* Тревога поверх фиолетовой заливки. Одна на обе темы: заливка в обеих
       фиолетовая, а --danger и --warn считаются от фона окна и на ней либо
       тонут, либо режут глаз. */
    --warn-on-accent-hsl: 45 100% 82%;
    --drop-veil: hsl(0 0% 100% / .82);
    /* Смысловые цвета: текст насыщённый и тёмный, плашки светлые, но с
       настоящей насыщенностью, а не тремя оттенками серого. */
    --danger: hsl(2 70% 42%);
    --danger-line: hsl(2 66% 48%);
    --danger-line-hsl: 2 66% 48%;
    --warn: hsl(26 82% 34%);
    --warn-line-hsl: 30 80% 44%;
    --ok: hsl(150 62% 25%);
    --ok-line: hsl(150 52% 32%);
    --ok-line-hsl: 150 52% 34%;
    --tg-color: hsl(202 74% 32%);
    --tg-line-hsl: 202 66% 40%;
    /* Столбики клиентов в графике по часам — синие: рядом с фиолетовыми
       столбиками наших ответов оттенок того же тона не различить. */
    --chart-in: hsl(200 72% 38%);
    --bubble-out: hsl(246 85% 95%);
    --quote-bg: hsl(248 35% 94% / .95);
    --overlay-soft: hsl(225 28% 12% / .72);
    --skeleton-shine: hsl(248 35% 91%);
    --wave-off: hsl(246 30% 76%);
    --wave-on: hsl(245 65% 50%);
    --scroll-track: hsl(248 30% 94%);
    --scroll-thumb-hover: hsl(246 26% 66%);
    /* Тень в два слоя: контактная и мягкая. Одна слабая тень на белом не
       читается, из-за неё карточки и выглядели плоскими. */
    --shadow: 0 1px 2px hsl(246 30% 30% / .08), 0 8px 20px -10px hsl(246 34% 28% / .22);
    --shadow-lg: 0 24px 50px -22px hsl(246 34% 22% / .4);
    /* Чернильный блок разбора инвертирован, поэтому ему нужна своя граница:
       раньше ink-line был прозрачным и блок «висел» в воздухе. */
    --ink: hsl(225 32% 11%);
    --ink-text: hsl(240 16% 90%);
    --ink-line: hsl(226 28% 22%);
    --ink-accent: hsl(246 92% 78%);
    }
  }
  :root[data-theme='light'] {
    --chevron: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%235c6373' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6'/%3E%3C/svg%3E");
    /* Поверхности: фон — светлая бумага, панели — белые. Главная правка:
       раньше --bg и --panel были одинаково белыми, поэтому карточки, шапка и
       список сливались в одно полотно. Оттенок холодный, от фиолетового
       акцента продукта: тёплая бумага рядом с ним читалась бы как грязь. */
    --bg: hsl(248 30% 95%);
    --panel: hsl(0 0% 100%);
    --panel-2: hsl(250 45% 98%);
    --panel-3: hsl(248 40% 96.5%);
    --panel-4: hsl(248 30% 92%);
    /* Впадины (композер, полоса задачи, сводная строка) теперь темнее панели,
       а не белее белого. */
    --sunken: hsl(248 32% 93.5%);
    /* Границы: было 91% — на белом их не видно. */
    --border: hsl(246 24% 84%);
    --border-2: hsl(244 22% 74%);
    --line: hsl(246 26% 89%);
    --text: hsl(222 32% 10%);
    --text-2: hsl(222 18% 25%);
    --muted: hsl(222 12% 40%);
    --muted-2: hsl(222 14% 32%);
    /* Времена сообщений 11px были почти нечитаемы. */
    --faint: hsl(222 10% 48%);
    /* Фиолетовый — акцент продукта. Заливка светлее, акцентный текст темнее:
       одним тоном не обойтись, он либо не читается на белом, либо слишком
       глухой под белым текстом. gold-hsl идёт в полупрозрачные обводки
       hsl(var(--gold-hsl) / .4) — на белом они должны быть видны. */
    --gold-hsl: 246 62% 50%;
    --gold: hsl(244 68% 54%);
    --gold-deep: hsl(246 62% 46%);
    --gold-soft: hsl(246 64% 44%);
    --gold-bright: hsl(248 66% 36%);
    --gold-tint: hsl(246 80% 93%);
    --gold-wash: hsl(246 85% 96.5%);
    --gold-wash-2: hsl(246 80% 93.5%);
    /* Заливка акцентом здесь и так глубокая — белый текст на ней читается. */
    --gold-fill: hsl(244 68% 54%);
    /* На фиолетовой заливке текст белый, а не тёмный. */
    --on-accent: hsl(0 0% 100%);
    --on-accent-hsl: 0 0% 100%;
    --on-danger: hsl(0 0% 100%);
    /* Тревога поверх фиолетовой заливки. Одна на обе темы: заливка в обеих
       фиолетовая, а --danger и --warn считаются от фона окна и на ней либо
       тонут, либо режут глаз. */
    --warn-on-accent-hsl: 45 100% 82%;
    --drop-veil: hsl(0 0% 100% / .82);
    /* Смысловые цвета: текст насыщённый и тёмный, плашки светлые, но с
       настоящей насыщенностью, а не тремя оттенками серого. */
    --danger: hsl(2 70% 42%);
    --danger-line: hsl(2 66% 48%);
    --danger-line-hsl: 2 66% 48%;
    --warn: hsl(26 82% 34%);
    --warn-line-hsl: 30 80% 44%;
    --ok: hsl(150 62% 25%);
    --ok-line: hsl(150 52% 32%);
    --ok-line-hsl: 150 52% 34%;
    --tg-color: hsl(202 74% 32%);
    --tg-line-hsl: 202 66% 40%;
    /* Столбики клиентов в графике по часам — синие: рядом с фиолетовыми
       столбиками наших ответов оттенок того же тона не различить. */
    --chart-in: hsl(200 72% 38%);
    --bubble-out: hsl(246 85% 95%);
    --quote-bg: hsl(248 35% 94% / .95);
    --overlay-soft: hsl(225 28% 12% / .72);
    --skeleton-shine: hsl(248 35% 91%);
    --wave-off: hsl(246 30% 76%);
    --wave-on: hsl(245 65% 50%);
    --scroll-track: hsl(248 30% 94%);
    --scroll-thumb-hover: hsl(246 26% 66%);
    /* Тень в два слоя: контактная и мягкая. Одна слабая тень на белом не
       читается, из-за неё карточки и выглядели плоскими. */
    --shadow: 0 1px 2px hsl(246 30% 30% / .08), 0 8px 20px -10px hsl(246 34% 28% / .22);
    --shadow-lg: 0 24px 50px -22px hsl(246 34% 22% / .4);
    /* Чернильный блок разбора инвертирован, поэтому ему нужна своя граница:
       раньше ink-line был прозрачным и блок «висел» в воздухе. */
    --ink: hsl(225 32% 11%);
    --ink-text: hsl(240 16% 90%);
    --ink-line: hsl(226 28% 22%);
    --ink-accent: hsl(246 92% 78%);
  }
  :root[data-theme='dark'] {
    /* Стрелка выпадающего списка: рисуем сами, потому что системную вместе
       с appearance приходится гасить целиком. Цвет свой на каждую тему. */
    --chevron: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2380899c' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6'/%3E%3C/svg%3E");
    --bg: hsl(230 25% 7%);
    --panel: hsl(230 22% 10%);
    --panel-2: hsl(230 20% 12.5%);
    --panel-3: hsl(230 20% 14%);
    --panel-4: hsl(230 18% 16%);
    --sunken: hsl(230 24% 8.5%);
    --border: hsl(230 16% 20%);
    --border-2: hsl(230 16% 25%);
    --line: hsl(230 16% 18%);
    --text: hsl(240 20% 92%);
    --text-2: hsl(240 14% 84%);
    --muted: hsl(233 12% 55%);
    --muted-2: hsl(233 14% 62%);
    --faint: hsl(233 10% 46%);
    /* Тот же фиолетовый, но поднятый по светлоте: на тёмном фоне
       исходный тон выглядит грязным пятном. */
    --gold-hsl: 245 78% 68%;
    --gold: hsl(245 78% 68%);
    --gold-deep: hsl(245 62% 56%);
    --gold-soft: hsl(245 85% 76%);
    --gold-bright: hsl(245 90% 82%);
    --gold-tint: hsl(245 45% 22% / .55);
    --gold-wash: hsl(245 40% 20% / .45);
    --gold-wash-2: hsl(245 42% 22% / .6);
    /* Заливка акцентом там, где поверх неё идёт текст. Чуть глубже --gold:
       сам акцент поднят по светлоте, чтобы читаться буквами на тёмном фоне,
       и белая надпись на нём была бы на грани различимости. Отдельный токен,
       а не правка --gold, — иначе вместе с заливкой потускнели бы ссылки и
       значки, которые этим же цветом написаны. */
    --gold-fill: hsl(245 72% 62%);
    /* Текст на фиолетовой заливке — белый, как в светлой теме: тёмная буква
       на ярком пятне выглядела вырезанной дыркой. */
    --on-accent: hsl(0 0% 100%);
    --on-accent-hsl: 0 0% 100%;
    /* Красная плашка светлая в обеих темах наоборот: на ней текст тёмный. */
    --on-danger: hsl(230 30% 8%);
    /* Тревога поверх фиолетовой заливки. Одна на обе темы: заливка в обеих
       фиолетовая, а --danger и --warn считаются от фона окна и на ней либо
       тонут, либо режут глаз. */
    --warn-on-accent-hsl: 45 100% 82%;
    /* Занавес поверх переписки, когда на неё тащат файл: цвет фона окна,
       а не «цвет текста на акценте» — они больше не совпадают. */
    --drop-veil: hsl(230 25% 7% / .82);
    --danger: hsl(4 72% 68%);
    --danger-line: hsl(4 60% 50%);
    --danger-line-hsl: 4 60% 50%;
    --warn: hsl(38 88% 66%);
    --warn-line-hsl: 38 80% 50%;
    --ok: hsl(164 58% 55%);
    --ok-line: hsl(164 62% 42%);
    --ok-line-hsl: 164 62% 42%;
    --tg-color: hsl(199 68% 66%);
    --tg-line-hsl: 199 60% 48%;
    --chart-in: hsl(245 55% 58%);
    --bubble-out: hsl(245 40% 22% / .85);
    --quote-bg: hsl(230 20% 16% / .7);
    --overlay-soft: hsl(230 28% 5% / .78);
    --skeleton-shine: hsl(230 18% 20%);
    --wave-off: hsl(245 40% 46% / .55);
    --wave-on: hsl(245 60% 62%);
    --scroll-track: hsl(230 20% 12%);
    --scroll-thumb-hover: hsl(245 35% 32%);
    --shadow: 0 2px 16px -2px hsl(230 30% 3% / .6);
    --shadow-lg: 0 26px 54px -26px rgba(0, 0, 0, 1);
    /* Чернильный блок разбора умной модели. В тёмной теме он темнее фона —
       иначе разбор сливался бы с карточкой, а это её главный текст. */
    --ink: hsl(230 30% 4%);
    --ink-text: hsl(240 16% 86%);
    --ink-line: hsl(230 18% 17%);
    --ink-accent: hsl(245 85% 78%);
  }
  /* Браузер красит свои поля ввода и полосы прокрутки под тему страницы. */
  :root { color-scheme: dark; }
  @media (prefers-color-scheme: light) { :root:not([data-theme='dark']) { color-scheme: light; } }
  :root[data-theme='light'] { color-scheme: light; }
  :root[data-theme='dark'] { color-scheme: dark; }


  * { box-sizing: border-box; }
  /* Safari: класс с display:flex перебивает атрибут hidden, и закрытая
     шторка остаётся на весь экран — цветной фон поверх текста. */
  [hidden] { display: none !important; }
  dialog:not([open]) { display: none !important; }
  /* Серую вспышку по тапу рисует сам iOS, и рисует с задержкой — палец уже
     ушёл, а квадрат ещё горит. Убираем её, но взамен обязаны дать свой
     отклик: нажатие без ответа читается как «не сработало». Отклик — ниже,
     у каждого нажимаемого места. */
  * { -webkit-tap-highlight-color: transparent; }
  /* Долгое нажатие на строке списка предлагает «скопировать» и выделяет
     текст — в приложении так не бывает. Поля ввода и переписку не трогаем:
     там выделение нужно. */
  .item, .task, .rrow, button { -webkit-user-select: none; user-select: none; }
  /* Отклик на нажатие там, где его не было: строка списка, задача, строка
     очереди. Кнопки свой уже имеют. */
  @media (hover: none) {
    .item:active { background: var(--panel-2); }
    .task:active, .rrow:active { transform: scale(.995); }
  }
  .task, .rrow { transition: transform .12s ease; }
  /* Переключение темы — плавное, но только для цвета: анимировать всё
     подряд на таком количестве узлов телефон не потянет. */
  body, .panel, aside, header, .bubble, .card, .review, .item {
    transition: background-color .25s ease, border-color .25s ease, color .25s ease;
  }
  html, body {
    margin: 0; height: 100%; background: var(--bg); color: var(--text);
    font-family: 'Golos Text', Inter, system-ui, sans-serif; font-size: 15px; line-height: 1.5;
    -webkit-font-smoothing: antialiased;
  }
  a { color: var(--gold-soft); text-decoration: none; }
  a:hover { color: var(--gold-bright); }
  input, button, select, textarea { font-family: 'Golos Text', Inter, system-ui, sans-serif; }
  input[type=number] { -moz-appearance: textfield; }
  input[type=number]::-webkit-outer-spin-button,
  input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  ::selection { background: hsl(var(--gold-hsl) / .3); }
  /* Обводка фокуса — золотая, а не системная белая: она тут повсюду вылезает. */
  :focus-visible { outline: 2px solid hsl(var(--gold-hsl) / .55); outline-offset: 2px; }
  :focus:not(:focus-visible) { outline: none; }
  ::-webkit-scrollbar { width: 6px; height: 6px; }
  ::-webkit-scrollbar-track { background: var(--scroll-track); }
  ::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 3px; }
  ::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); }

  @keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
  @keyframes viewIn { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }
  @keyframes rowIn { from { opacity: 0; transform: translateY(-8px) } to { opacity: 1; transform: none } }
  @keyframes msgIn { from { opacity: 0; transform: translateY(14px) scale(.96) } to { opacity: 1; transform: none } }
  @keyframes panelIn { from { opacity: 0; transform: translateX(22px) } to { opacity: 1; transform: none } }
  @keyframes dlgIn { from { opacity: 0; transform: translateY(16px) scale(.96) } to { opacity: 1; transform: none } }
  @keyframes sheetIn { from { opacity: 0; transform: translateY(28px) scale(.97) } to { opacity: 1; transform: none } }
  @keyframes sheetOut { from { opacity: 1; transform: none } to { opacity: 0; transform: translateY(18px) scale(.98) } }
  @keyframes stackIn { from { opacity: 0; transform: translateY(12px) } to { opacity: 1; transform: none } }
  @keyframes lbIn { from { opacity: 0; transform: scale(.9) } to { opacity: 1; transform: scale(1) } }
  @keyframes toastIn { from { opacity: 0; transform: translate(-50%, 16px) scale(.96) } to { opacity: 1; transform: translate(-50%, 0) scale(1) } }
  @keyframes noteIn { from { opacity: 0; transform: translateX(24px) scale(.96) } to { opacity: 1; transform: translateX(0) scale(1) } }
  @keyframes noteOut { to { opacity: 0; transform: translateX(24px) scale(.96) } }
  @keyframes spin { to { transform: rotate(360deg) } }
  @keyframes pulseDot { 0%, 100% { opacity: 1 } 50% { opacity: .3 } }
  @keyframes unreadOut { 0% { transform: scale(1); opacity: 1 } 45% { transform: scale(1.35) } 100% { transform: scale(.2); opacity: 0 } }
  @keyframes shimmer { 0% { background-position: -200% 0 } 100% { background-position: 200% 0 } }
  @keyframes glowPulse { 0%, 100% { box-shadow: 0 0 0 0 hsl(var(--gold-hsl) / .35) } 50% { box-shadow: 0 0 0 6px hsl(var(--gold-hsl) / 0) } }
  @media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  }

  /*
   * Переписка — окно в три колонки, каждая со своей прокруткой: ей нужна
   * жёсткая высота во весь экран. dvh вместо vh потому, что vh у части
   * браузеров не совпадает с видимой частью окна, и тогда низ содержимого
   * оказывается за краем без возможности доскроллить.
   */
  body { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; padding: 0; }

  /*
   * Дашборд и настройки — обычные длинные страницы. Прокручиваем их самой
   * страницей, а не коробкой внутри: коробка держится на высоте окна, и
   * стоит ей разойтись с настоящей — часть содержимого просто не достать.
   * Шапку при этом прибиваем к верху, иначе вкладки уезжают при прокрутке.
   */
  body.v-board, body.v-settings, body.v-tasks, body.v-cabinet, body.v-admin, body.v-site,
  body.v-analytics {
    height: auto; min-height: 100vh; min-height: 100dvh; overflow-y: auto;
  }
  body.v-analytics .view, body.v-analytics header,
  body.v-board .view, body.v-settings .view, body.v-tasks .view,
  body.v-cabinet .view, body.v-admin .view, body.v-site .view { overflow: visible; }
  body.v-board header, body.v-settings header, body.v-tasks header,
  body.v-cabinet header, body.v-admin header, body.v-site header,
  body.v-analytics header { position: sticky; top: 0; z-index: 30; }

  /* ---------- шапка ---------- */
  header {
    flex: none; display: flex; align-items: center; gap: 10px;
    height: calc(56px + env(safe-area-inset-top, 0px));
    min-height: calc(56px + env(safe-area-inset-top, 0px));
    padding: env(safe-area-inset-top, 0px) 14px 0;
    box-sizing: border-box;
    border-bottom: 1px solid var(--line); background: var(--panel); position: relative; z-index: 20;
  }
  .brand { display: flex; align-items: center; min-width: 0; color: var(--text); }
  .brand b {
    margin-left: 0; font-family: var(--serif); font-size: 16px; font-weight: 800;
    letter-spacing: -.01em; color: var(--text); white-space: nowrap;
  }
  .brand-sep { margin: 0 12px; color: var(--faint); }
  .brand-sub { font-size: 14px; color: var(--muted); white-space: nowrap; }
  .spacer { flex: 1; }
  .chip {
    flex: none; display: inline-flex; align-items: center; gap: 8px; padding: 5px 11px;
    border-radius: 999px; border: 1px solid var(--border); background: var(--panel-2);
    font: 400 11.5px Inter, sans-serif; color: var(--muted); white-space: nowrap;
    cursor: pointer; transition: border-color .2s ease;
  }
  .chip:hover { border-color: var(--border-2); }
  .chip .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); }
  .chip .dot.ok { background: var(--ok-line); }
  .chip .dot.bad { background: var(--danger); animation: pulseDot 1.8s ease-in-out infinite; }
  .chip .lab { font-size: 11.5px; font-weight: 600; letter-spacing: .04em; }
  .chip .lab.ok { color: var(--ok); }
  .chip .lab.bad { color: var(--danger); }
  /* Список каналов под плашкой: в шапке помещается только счёт, а знать
     хочется, какой именно мессенджер отвалился. */
  .chip-wrap { position: relative; flex: none; }
  .chan-pop {
    position: absolute; left: 0; top: 34px; z-index: 60; width: 288px; padding: 7px;
    border-radius: 14px; border: 1px solid var(--border-2); background: var(--panel-2);
    box-shadow: var(--shadow-lg); animation: dlgIn .18s cubic-bezier(.2, .8, .3, 1);
  }
  .chan-pop[hidden] { display: none; }
  .chan-pop .row {
    display: flex; align-items: flex-start; gap: 9px; width: 100%; padding: 8px 9px;
    border: 0; border-radius: 9px; background: none; text-align: left;
    font: 500 13px Inter, sans-serif; color: var(--text-2);
  }
  .chan-pop button.row { cursor: pointer; transition: background .15s ease; }
  .chan-pop button.row:hover { background: var(--panel-4); }
  .chan-pop .row .dot { flex: none; width: 7px; height: 7px; margin-top: 5px; border-radius: 50%; }
  .chan-pop .row .dot.ok { background: var(--ok-line); }
  .chan-pop .row .dot.bad { background: var(--danger); }
  .chan-pop .row .nm { min-width: 0; }
  .chan-pop .row .nm b { display: block; font-weight: 600; color: var(--text); }
  .chan-pop .row .nm span {
    display: block; margin-top: 2px; font-size: 11.5px; font-weight: 400;
    line-height: 1.4; color: var(--muted); overflow-wrap: anywhere;
  }
  .chan-pop .row .nm span.bad { color: var(--danger); }
  .chan-pop .empty { padding: 10px 9px; font-size: 12.5px; color: var(--muted); }
  .chan-pop .hint {
    margin: 5px 9px 3px; padding-top: 7px; border-top: 1px solid var(--line);
    font-size: 11.5px; color: var(--faint);
  }
  .views { display: flex; gap: 2px; padding: 3px; border-radius: 10px; background: var(--panel-2); }
  .views button {
    flex: none; padding: 6px 13px; border-radius: 8px; border: 0; background: transparent;
    color: var(--muted); font: 500 13px Inter, sans-serif; cursor: pointer; white-space: nowrap;
    transition: background .2s ease, color .2s ease;
  }
  .views button:hover { color: var(--text-2); }
  .views button.on { background: var(--gold-fill); color: var(--on-accent); font-weight: 600; }
  .ghost {
    flex: none; height: 32px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--border);
    background: var(--panel-2); color: var(--text-2); font: 500 12.5px Inter, sans-serif;
    cursor: pointer; white-space: nowrap;
    transition: border-color .2s ease, color .2s ease, transform .2s ease;
  }
  .ghost:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }
  .ghost.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); font-weight: 600; }
  .ghost:active { transform: translateY(1px); }
  .ghost:disabled { opacity: .45; cursor: not-allowed; }
  .ghost.warn { border-color: hsl(0 70% 60% / .35); color: var(--danger); }
  #btn-bell {
    display: inline-flex; align-items: center; gap: 6px; max-width: 240px;
  }
  #btn-bell[hidden] { display: none !important; }
  #btn-bell .bell-ok { font-weight: 700; color: var(--ok); }
  .linkish {
    border: 0; background: none; padding: 0; font: inherit; color: var(--gold-soft);
    text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
  }
  .linkish:hover { color: var(--gold); }
  .ghost.warn:hover { border-color: hsl(0 70% 60% / .6); color: var(--danger); }
  .icon-btn {
    flex: none; display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border-radius: 8px;
    border: 1px solid var(--border); background: var(--panel-2); color: var(--muted);
    font: 600 13px Inter, sans-serif; cursor: pointer;
    transition: border-color .2s ease, color .2s ease;
  }
  .icon-btn:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }
  /* Менеджер клиента в карточке: имя заметное, предложение перевести — тихое. */
  .panel-man { font-weight: 600; color: var(--text); }
  .panel-offer { margin-top: 8px; display: grid; gap: 6px; justify-items: start; }
  .pick-list { display: grid; gap: 6px; max-height: 320px; overflow-y: auto; padding: 12px 20px 4px; }
  .pick-row {
    text-align: left; min-height: 40px; padding: 9px 12px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
    font: 500 14px Inter, sans-serif; cursor: pointer;
  }
  .pick-row:hover { border-color: hsl(var(--gold-hsl) / .45); }
  /* Кто ведёт сейчас — отмечен, чтобы не назначать того же самого. */
  .pick-row.on { border-color: hsl(var(--gold-hsl) / .5); color: var(--gold); cursor: default; }
  .ghost.small { height: 30px; padding: 0 11px; font-size: 12px; }
  /* Разбор — главное, что окно умеет сверх переписки, поэтому кнопка не серая. */
  .btn-rc {
    display: inline-flex; align-items: center; gap: 7px;
    border-color: hsl(var(--gold-hsl) / .4); background: var(--gold-wash);
    color: var(--gold-soft); font-weight: 600;
  }
  .btn-rc:hover { border-color: hsl(var(--gold-hsl) / .75); color: var(--gold-bright); }
  .btn-rc[hidden] { display: none; }
  .btn-rc .spark { font-size: 12px; line-height: 1; }

  /* ---------- общий каркас видов ---------- */
  main { flex: 1; display: grid; min-height: 0; grid-template-columns: 340px minmax(0, 1fr); }
  main.with-panel { grid-template-columns: 340px minmax(0, 1fr) 296px; }
  .view { flex: 1; min-height: 0; overflow-y: auto; animation: viewIn .28s cubic-bezier(.2, .8, .3, 1); }
  body.v-chats main { display: grid; }
  body:not(.v-chats) main { display: none; }
  body.v-board #board { display: block; }
  body:not(.v-board) #board { display: none; }
  body.v-analytics #analytics { display: block; }
  body:not(.v-analytics) #analytics { display: none; }
  body.v-tasks #tasks { display: block; }
  body:not(.v-tasks) #tasks { display: none; }
  body.v-settings #settings { display: block; }
  body:not(.v-settings) #settings { display: none; }
  body.v-cabinet #cabinet { display: block; }
  body:not(.v-cabinet) #cabinet { display: none; }
  body.v-admin #admin { display: block; }
  body:not(.v-admin) #admin { display: none; }
  body.v-site #site { display: block; }
  body:not(.v-site) #site { display: none; }

  /* ---------- задачи ---------- */
  .views button .badge {
    display: inline-block; margin-left: 7px; min-width: 18px; padding: 0 5px;
    border-radius: 999px; background: var(--gold-fill); color: var(--on-accent);
    font-size: 11px; font-weight: 700; line-height: 17px; text-align: center;
  }
  .views button.on .badge { background: var(--on-accent); color: var(--gold-fill); }
  .views button .badge[hidden] { display: none; }

  .tasks-inner { max-width: 860px; margin: 0 auto; padding: 26px 16px 60px; }
  .tasks-head { margin-bottom: 20px; }
  /* Ряд «все / мои» под подписью: тот же вид, что и над списком диалогов. */
  #tasks-filters { margin-top: 12px; }
  .tasks-head .h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
  .tasks-head h2 {
    margin: 0; font-family: var(--serif); font-size: 22px; font-weight: 700;
    letter-spacing: -.01em; color: var(--text);
  }
  .tasks-head .count { font-family: var(--num); font-size: 13px; color: var(--muted); }
  .tasks-sub { margin: 0; font-size: 13px; color: var(--muted); max-width: 62ch; line-height: 1.55; }

  /* Дела разложены по срочности: просроченное сверху и подробно, остальное —
     строкой. Общий список одинаковых карточек этого не показывает. */
  .tgroup { display: flex; align-items: center; gap: 9px; margin: 0 0 10px; }
  .tgroup span { font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
  .tgroup i { flex: 1; height: 1px; background: var(--line); }
  .tgroup.bad span { color: var(--danger); }
  .tgroup.bad i { background: hsl(var(--danger-line-hsl) / .25); }
  .tgroup.warn span { color: var(--warn); }
  .tgroup.warn i { background: hsl(var(--warn-line-hsl) / .22); }
  .tgroup.calm span { color: var(--muted); }
  .tasks-group { display: flex; flex-direction: column; gap: 8px; margin-bottom: 22px; }
  .tasks-list { display: flex; flex-direction: column; }

  .task {
    display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 12px; align-items: start;
    padding: 13px 15px; border-radius: 14px; border: 1px solid var(--border); background: var(--panel);
    animation: viewIn .25s cubic-bezier(.2, .8, .3, 1) both;
  }
  .task.slim { align-items: center; padding: 12px 15px; }
  /* Подсветка карточки, к которой пришли с дашборда. Именно переходом, а не
     анимацией: у .task уже есть анимация появления, и подмена имени в
     animation перезапускала её при снятии класса — карточка моргала. */
  .task { transition: border-color .5s ease, box-shadow .5s ease; }
  .task.flash {
    border-color: hsl(var(--gold-hsl) / .75);
    box-shadow: 0 0 0 3px hsl(var(--gold-hsl) / .2);
  }
  .task.sev2 {
    border-color: hsl(var(--danger-line-hsl) / .3);
    background: linear-gradient(160deg, hsl(var(--danger-line-hsl) / .07), var(--panel));
  }
  .task.closing { opacity: .35; transform: translateX(10px); transition: opacity .25s ease, transform .25s ease; }
  /* Выполненные: без галочки и приглушённые — это уже не дело, а возможность
     передумать. Единственная кнопка справа возвращает задачу в работу. */
  .task.done { grid-template-columns: minmax(0, 1fr) auto; }
  .task.done .what { color: var(--text-2); }
  .task .meta .w.ok { color: var(--ok); }
  .tasks-sub.warn { color: var(--warn); }

  /* Галочка вместо кнопки «Готово»: дело закрывают одним движением, и место
     справа остаётся под то, ради чего задачу открыли. Рисуем сами — в наших
     подмножествах шрифтов знака ✓ нет, вместо него получился бы квадрат. */
  .tcheck {
    /* padding: 0 обязателен: у кнопки свой отступ от браузера (1px 6px), и
       галочка центрировалась не в квадратике, а в том, что от него осталось
       внутри отступов, — то есть вставала правее середины. */
    display: grid; place-items: center; width: 24px; height: 24px; padding: 0; border-radius: 8px;
    border: 1.5px solid var(--border-2); background: transparent; color: var(--muted); cursor: pointer;
    transition: border-color .2s ease, background .2s ease, color .2s ease;
  }
  .task:not(.slim) .tcheck { margin-top: 2px; }
  .task.sev2 .tcheck { border-color: hsl(var(--ok-line-hsl) / .5); color: var(--ok); }
  .tcheck:hover { border-color: hsl(var(--ok-line-hsl) / .6); background: hsl(var(--ok-line-hsl) / .2); color: var(--ok); }
  .tcheck:disabled { opacity: .5; cursor: default; }
  .tcheck svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

  .task .body { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
  .task.slim .body { gap: 4px; }
  .task .what { font-size: 14.5px; color: var(--text); line-height: 1.45; }
  .task .why { font-size: 13px; color: var(--text-2); line-height: 1.55; }
  .task.slim .what { font-size: 14px; }
  .task .meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); }
  .task .meta .name { font-weight: 600; color: var(--text-2); }
  .task .meta .phone { font-variant-numeric: tabular-nums; }
  .task .meta .w { font-weight: 600; }
  .task .meta .w.bad { color: var(--danger); }
  .task .meta .w.warn { color: var(--warn); }
  .task .tips { display: flex; flex-direction: column; gap: 6px; }
  .task .tip {
    text-align: left; padding: 9px 11px; border-radius: 9px; font: 400 13px Inter, sans-serif;
    border: 1px solid hsl(var(--gold-hsl) / .35); background: var(--gold-wash);
    color: var(--text); cursor: pointer; line-height: 1.5;
    transition: border-color .2s ease, background .2s ease;
  }
  .task .tip:hover { border-color: hsl(var(--gold-hsl) / .6); background: var(--gold-wash-2); }
  .task .acts { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
  .task .acts button {
    height: 28px; padding: 0 11px; border-radius: 8px; border: 1px solid var(--border-2);
    background: var(--panel-2); color: var(--text-2);
    font: 500 12px 'Golos Text', Inter, sans-serif; cursor: pointer; white-space: nowrap;
    transition: border-color .2s ease, background .2s ease, color .2s ease;
  }
  .task .acts button:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--text); }
  .task .acts button.primary {
    border-color: transparent; background: var(--gold-fill); color: var(--on-accent); font-weight: 600;
  }
  .task .acts button.primary:hover { filter: brightness(1.06); color: var(--on-accent); }
  .task .acts button:disabled { opacity: .55; cursor: default; }

  .tasks-empty {
    padding: 42px 20px; text-align: center; color: var(--muted); font-size: 14px;
    border: 1px dashed var(--border); border-radius: 12px;
  }
  .tasks-empty b { display: block; margin-bottom: 6px; color: var(--text-2); font-size: 15px; }
  @media (max-width: 720px) {
    .tasks-inner { padding: 18px 12px 48px; }
    /* Кнопки — под текстом и одной ширины: сбоку они сжимают заголовок
       задачи до двух слов в строке. */
    .task { grid-template-columns: 26px minmax(0, 1fr); }
    .task.slim { align-items: start; }
    .task .acts { grid-column: 2; display: grid; grid-template-columns: 1fr 1fr; }
    /* У выполненной нет колонки под галочку: кнопки встают под текст, иначе
       они отжимали бы его в узкий столбик рядом с собой. */
    .task.done { grid-template-columns: minmax(0, 1fr); }
    .task.done .acts { grid-column: 1; }
  }

  /* ---------- список диалогов ---------- */
  aside { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); background: var(--panel); }
  .search { flex: none; padding: 12px 13px 10px; border-bottom: 1px solid var(--line); }
  .search .field { position: relative; }
  .search input {
    width: 100%; height: 36px; padding: 0 28px; border-radius: 9px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text); font-size: 13.5px; outline: none;
    transition: border-color .2s ease;
  }
  .search input:focus { border-color: hsl(var(--gold-hsl) / .45); }
  /* У type=search браузер рисует свой крестик — рядом с нашим их получается два */
  .search input::-webkit-search-cancel-button,
  .search input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
  /* Автозаполнение красит поле в свой синий — возвращаем тему окна */
  input:-webkit-autofill, input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--text);
    -webkit-box-shadow: 0 0 0 1000px var(--panel-3) inset;
    caret-color: var(--text);
  }
  .search .lens { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 12px; }
  #email-trap {
    position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0;
    pointer-events: none;
  }
  .search .clear {
    position: absolute; right: 9px; top: 50%; transform: translateY(-50%); border: 0; padding: 2px 4px;
    background: none; color: var(--muted); font-size: 13px; cursor: pointer;
  }
  .search .clear:hover { color: var(--gold-soft); }
  .search-row { display: flex; align-items: center; gap: 8px; margin-top: 9px; }
  .search-row .filters { margin-top: 0; flex: 1; min-width: 0; }
  .write-mail { display: none !important; }
  .ptr {
    flex: none; display: flex; align-items: center; justify-content: center; gap: 8px;
    height: 0; overflow: hidden; font-size: 12px; color: var(--muted); background: var(--bg);
  }
  .ptr[hidden] { display: none !important; }
  .ptr.busy::before {
    content: ''; width: 14px; height: 14px;
    border: 2px solid var(--border-2); border-top-color: var(--gold);
    border-radius: 50%; animation: spin .7s linear infinite;
  }
  .mail-compose { padding: 0 20px 18px; display: grid; gap: 11px; }
  .mail-compose label { font-size: 12.5px; color: var(--muted-2); }
  .mail-compose input, .mail-compose textarea {
    display: block; width: 100%; box-sizing: border-box; margin-top: 5px;
    padding: 8px 11px; border-radius: 9px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text); font: 400 14px/1.45 Inter, sans-serif;
    outline: none;
  }
  .mail-compose textarea { resize: vertical; min-height: 110px; }
  .mail-compose input:focus, .mail-compose textarea:focus { border-color: hsl(var(--gold-hsl) / .6); }
  .mail-compose-error { font-size: 13px; color: var(--danger); }
  .mail-compose-error[hidden] { display: none; }
  .bubble .text a { color: inherit; text-decoration: underline; overflow-wrap: anywhere; }
  .bubble .mail-subj {
    margin: 0 0 6px; font-size: 12px; font-weight: 650; opacity: .78;
    padding-bottom: 5px; border-bottom: 1px solid currentColor;
  }
  /* Чипы фильтров не делят ширину поровну: на телефоне в такую долю
     «★ Избранные» с числом не влезал и переносился на вторую строку внутри
     28-пиксельной кнопки. Ширина — по содержимому, а если чипов больше, чем
     помещается, ряд листается вбок, как вкладки в шапке. */
  .filters {
    display: flex; gap: 6px; margin-top: 9px;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .filters::-webkit-scrollbar { display: none; }
  .filters button {
    flex: 0 0 auto; height: 28px; padding: 0 12px; white-space: nowrap;
    border-radius: 8px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--muted); font: 500 12px Inter, sans-serif; cursor: pointer;
    transition: border-color .2s ease, color .2s ease, background .2s ease;
  }
  .filters button .n {
    margin-left: 5px; font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums;
  }
  .filters button.on .n { color: inherit; opacity: .8; }
  .filters button.on {
    border-color: hsl(var(--gold-hsl) / .45); background: var(--gold-tint);
    color: var(--gold-soft); font-weight: 600;
  }
  .list { flex: 1; min-height: 0; overflow-y: auto; }
  .item {
    display: grid; grid-template-columns: 40px 1fr auto; gap: 11px; align-items: center;
    width: 100%; padding: 11px 13px; text-align: left; cursor: pointer; font: inherit; color: inherit;
    border: 0; border-bottom: 1px solid var(--line); border-left: 3px solid transparent;
    background: transparent; transition: background .2s ease, border-color .2s ease;
    animation: rowIn .3s cubic-bezier(.2, .8, .3, 1) both;
  }
  .item:hover { background: var(--sunken); }
  .item.on { border-left-color: var(--gold); background: var(--panel-2); }
  .item .col { min-width: 0; }
  .item .name { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; min-width: 0; }
  .item .preview { font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .item .right { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
  .item .time { font-size: 11px; color: var(--faint); white-space: nowrap; }
  .item .row { display: flex; align-items: center; gap: 6px; min-width: 0; }
  .deal {
    flex: 0 1 auto; min-width: 40px; max-width: 58%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 11px; font-weight: 500; line-height: 1.35;
    color: var(--gold-soft); background: var(--gold-tint);
    border: 1px solid hsl(var(--gold-hsl) / .28); border-radius: 999px;
    padding: 1px 8px;
  }
  .deal-link { cursor: pointer; }
  /* Отметка избранного: видно, что диалог помечен, но нажимать нечего —
     строка сама кнопка, и клик по звёздочке просто откроет переписку. */
  .item .star { font-size: 13px; line-height: 1; color: var(--gold); pointer-events: none; }
  /* Пометка рабочего чата приглушена: это не выделение диалога, как звезда,
     а признак того, что разбор его не касается. */
  .item .work-mark { font-size: 11px; line-height: 1; filter: grayscale(1); opacity: .75; pointer-events: none; }
  /* Звёздочка в шапке чата — крупнее прочих значков: 13px рядом с «✦» и
     карточкой клиента читались как один ряд украшений, и её не находили. */
  .chat-head .icon-btn.star { font-size: 16px; }
  .chat-head .icon-btn.star.on { color: var(--gold); }
  #btn-hide { flex: none; white-space: nowrap; }
  #btn-hide.on { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }
  .avatar {
    position: relative; flex: none; display: grid; place-items: center; width: 40px; height: 40px;
    border-radius: 50%; border: 1px solid var(--border-2); background: var(--panel-4);
  }
  .avatar .fill { position: absolute; inset: 0; border-radius: 50%; overflow: hidden; }
  .avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
  .avatar b { position: relative; font-size: 15px; font-weight: 600; }
  .mark { border-radius: 3px; padding: 0 2px; background: hsl(var(--gold-hsl) / .28); color: var(--gold-bright); }
  .chan {
    flex: none; padding: 1px 5px; border-radius: 5px; font-size: 10px; font-weight: 700;
    letter-spacing: .05em; border: 1px solid; background: transparent;
  }
  .chan.big { padding: 2px 7px; font-size: 10.5px; }
  .chan.whatsapp { border-color: hsl(var(--ok-line-hsl) / .4); background: hsl(var(--ok-line-hsl) / .16); color: var(--ok); }
  .chan.telegram { border-color: hsl(var(--tg-line-hsl) / .4); background: hsl(var(--tg-line-hsl) / .16); color: var(--tg-color); }
  .chan.max { border-color: hsl(var(--gold-hsl) / .4); background: hsl(var(--gold-hsl) / .14); color: var(--gold-soft); }
  .chan.email { border-color: hsl(var(--tg-line-hsl) / .3); background: var(--panel-4); color: var(--muted-2); }
  .badge-group { flex: none; padding: 1px 6px; border-radius: 5px; border: 1px solid var(--border-2); font-size: 10px; color: var(--muted-2); }
  /* Кружок непрочитанного — один и тот же с цифрой и без неё: разный размер
     читался бы как два разных значка, а значение у них одно. */
  .unread, .dot-unread {
    min-width: 19px; height: 19px; border-radius: 999px; background: var(--gold-fill);
    display: grid; place-items: center;
    animation: glowPulse 2.2s ease-in-out infinite;
  }
  .unread { padding: 0 6px; color: var(--on-accent); font-size: 11.5px; font-weight: 700; }
  /* Отмечен непрочитанным руками: тот же кружок, но пустой. Цифра значила бы,
     что пришли новые сообщения, а их не приходило. */
  .dot-unread { flex: none; width: 19px; }
  /* Меню диалога открыто: список уходит на второй план, выбранная строка — нет. */
  .list .item { transition: filter .26s ease, opacity .26s ease; }
  /* Спам бледный: он остаётся в списке, потому что переписку не выкидываем,
     но глаз должен проходить мимо него, а не цепляться как за клиента. */
  .list .item.spam { opacity: .45; }
  .list .item.spam:hover, .list .item.spam.on { opacity: .8; }
  .list.menu-open .item:not(.picked) { filter: blur(2.5px); opacity: .5; }
  .list .item.picked { position: relative; z-index: 1; }
  .list .item.holding { transform: scale(.985); }
  /* Плашка неподтверждённой почты. Во всю ширину над окном и без крестика:
     закрываемое предупреждение закрывают не читая, а тут от прочтения зависит,
     дойдёт ли до человека письмо о счёте. Цвет предупреждения, не ошибки:
     сервис работает, просто мы пока не можем до него достучаться. */
  .confirm-bar {
    display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px;
    padding: 9px 16px; border-bottom: 1px solid hsl(var(--warn-line-hsl) / .45);
    background: hsl(var(--warn-line-hsl) / .12);
    font-size: 13px; line-height: 1.45; color: var(--text-2);
  }
  .confirm-bar .ico { flex: none; font-size: 15px; color: var(--warn); }
  .confirm-bar .say { flex: 1; min-width: 200px; }
  .confirm-bar b { color: var(--text); font-weight: 600; }
  .confirm-bar button {
    flex: none; height: 30px; padding: 0 14px; border-radius: 9px;
    border: 1px solid hsl(var(--warn-line-hsl) / .6); background: transparent;
    color: var(--warn); font: 600 12.5px Inter, sans-serif; cursor: pointer;
    transition: background .2s ease, color .2s ease;
  }
  .confirm-bar button:hover { background: hsl(var(--warn-line-hsl) / .18); }
  .confirm-bar button:disabled { opacity: .55; cursor: default; }
  /* Полоса перевода живёт над лентой и не уезжает с ней: решение про язык
     принимают, глядя на переписку, а не пролистав её до конца. */
  .tr-bar {
    display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
    padding: 10px 16px; border-bottom: 1px solid var(--line); background: var(--sunken);
    font-size: 13px; color: var(--text-2);
  }
  .tr-bar[hidden] { display: none; }
  .tr-bar .ico { flex: none; color: var(--gold-soft); }
  .tr-bar .say { flex: 1; min-width: 160px; line-height: 1.45; }
  .tr-bar select { height: 32px; padding: 0 28px 0 10px; border-radius: 9px; font-size: 13px; }
  .tr-bar button {
    width: auto; margin: 0; height: 32px; padding: 0 14px; border-radius: 9px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 12.5px Inter, sans-serif; cursor: pointer; box-shadow: none;
  }
  .tr-bar button.ghost {
    background: transparent; border: 1px solid var(--border); color: var(--text-2); font-weight: 500;
  }
  .tr-bar button.x {
    padding: 0; width: 30px; border: 0; background: none; color: var(--faint); font-size: 15px;
  }
  .tr-bar button.x:hover { color: var(--text-2); }
  .tr-bar .wait { font-size: 12.5px; color: var(--muted); }
  /* Переведённое сообщение помечено: подменять слова клиента молча нельзя. */
  .msg .text .tr-mark {
    display: block; margin-bottom: 3px; font-size: 11px; letter-spacing: .02em; color: var(--faint);
  }
  .empty { display: grid; place-items: center; height: 100%; padding: 30px; text-align: center; color: var(--muted); }
  .empty h2 { margin: 0 0 6px; font-family: var(--serif); font-size: 20px; font-weight: 600; color: var(--text-2); }
  .empty p { margin: 0; font-size: 13px; line-height: 1.55; }

  /* ---------- переписка ---------- */
  section.chat {
    position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0;
    background: var(--bg);
  }
  .chat-head {
    flex: none; display: flex; align-items: center; gap: 12px; padding: 11px 16px;
    border-bottom: 1px solid var(--line); background: var(--panel);
  }
  .chat-head .title {
    display: flex; align-items: center; gap: 8px; min-width: 0;
    font-size: 15px; font-weight: 600; cursor: pointer;
  }
  .chat-head .title .who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .chat-head .title:hover { color: var(--gold-soft); }
  .chat-head .title .deal { color: var(--gold-soft); }
  #btn-hide, #btn-star, #btn-panel { display: none !important; }
  .chat-head .sub { display: flex; align-items: center; gap: 8px; margin-top: 3px; font-size: 12px; color: var(--muted); }
  .lead-link { font-weight: 600; color: var(--gold-soft); }
  .ball {
    flex: none; padding: 2px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 600; border: 1px solid;
  }
  .ball.us { border-color: hsl(var(--danger-line-hsl) / .35); background: hsl(var(--danger-line-hsl) / .14); color: var(--danger); }
  .ball.client { border-color: hsl(var(--ok-line-hsl) / .3); background: hsl(var(--ok-line-hsl) / .1); color: var(--ok); }
  .ball.mood { cursor: help; position: relative; }
  .ball.mood.bad { border-color: hsl(var(--gold-hsl) / .3); background: hsl(var(--gold-hsl) / .1); color: var(--gold-bright); }
  .ball.mood.good { border-color: hsl(var(--ok-line-hsl) / .3); background: hsl(var(--ok-line-hsl) / .1); color: var(--ok); }
  /* Обёртка нужна только затем, чтобы кнопке «вниз» было к чему прижаться:
     у самой ленты своя прокрутка, и кнопка внутри неё уезжала бы вместе
     с сообщениями. */
  .feed-wrap { position: relative; flex: 1; min-height: 0; display: flex; }
  .feed { flex: 1; min-height: 0; overflow-y: auto; padding: 18px 16px 8px; }
  /* Стрелка к последнему сообщению. Появляется, только когда лента отлистана
     вверх: у самого низа ей нечего делать. */
  /* Демо-переписка живёт в окне до первого настоящего канала, и убрать её
     нужно ровно один раз. Кнопка поверх всего: искать её в настройках —
     значит не найти, а красный цвет честно говорит, что действие
     необратимое. */
  .demo-fab {
    position: fixed; right: 18px; bottom: 18px; z-index: 30;
    height: 40px; padding: 0 16px; border-radius: 20px;
    border: 1px solid hsl(var(--danger-line-hsl) / .55);
    background: hsl(var(--danger-line-hsl) / .1);
    color: var(--danger); font: 600 13px/1 Inter, sans-serif; cursor: pointer;
    box-shadow: var(--shadow-lg);
    transition: transform .18s ease, background-color .2s ease, border-color .2s ease;
  }
  .demo-fab[hidden] { display: none; }
  .demo-fab:hover {
    background: hsl(var(--danger-line-hsl) / .18);
    border-color: hsl(var(--danger-line-hsl) / .8); transform: translateY(-1px);
  }
  .demo-fab:active { transform: translateY(1px); }
  /* Прятать кнопку в открытом диалоге можно только на телефоне: там переписка
     занимает экран целиком, и свободного угла внизу нет. На широком экране
     диалог открыт почти всегда — и кнопка, спрятанная заодно с ним, просто
     не существовала для нового клиента. */
  .to-bottom {
    position: absolute; right: 16px; bottom: 14px; z-index: 4;
    display: grid; place-items: center; width: 40px; height: 40px; padding: 0;
    border-radius: 50%; border: 1px solid var(--border-2); background: var(--panel);
    color: var(--text-2); box-shadow: var(--shadow-lg); cursor: pointer;
    animation: toBottomIn .18s ease both;
    transition: color .2s ease, border-color .2s ease, transform .2s ease;
  }
  /* Своя анимация: у общей pillIn сдвиг на -50% по горизонтали — она для
     плашки по центру экрана, и кнопку она бы уводила влево. */
  @keyframes toBottomIn { from { opacity: 0; transform: translateY(6px) } to { opacity: 1; transform: none } }
  .to-bottom[hidden] { display: none; }
  .to-bottom:hover { color: var(--gold-soft); border-color: hsl(var(--gold-hsl) / .45); }
  .to-bottom:active { transform: translateY(1px); }
  .to-bottom .arr { font-size: 17px; line-height: 1; }
  /* Сколько сообщений пришло, пока читали историю: без числа непонятно,
     ждёт там что-то новое или кнопка просто возвращает вниз. */
  .to-bottom .n {
    position: absolute; top: -5px; right: -4px; min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 999px; background: var(--gold-fill); color: var(--on-accent);
    font: 600 11px Inter, sans-serif; line-height: 18px; text-align: center;
  }
  .to-bottom .n[hidden] { display: none; }
  .day { display: flex; justify-content: center; margin: 12px 0; }
  .day span {
    padding: 3px 12px; border-radius: 999px; border: 1px solid var(--border);
    background: var(--panel-2); font-size: 11.5px; color: var(--muted);
  }
  .history-more { display: flex; justify-content: center; margin: 4px 0 14px; }
  .history-more button {
    height: 32px; padding: 0 14px; border-radius: 999px;
    font-size: 12.5px;
  }
  /* touch-action: горизонтальный жест разбираем сами. Без этого палец, ведя
     пузырь вбок, заодно тащил за собой всю страницу. */
  .msg {
    display: flex; margin-bottom: 9px; touch-action: pan-y pinch-zoom;
    animation: msgIn .3s cubic-bezier(.2, .8, .3, 1) both;
  }
  /* Зажатое сообщение — это наш жест: открыть меню. iOS в тот же момент
     начинал выделять текст и показывал свою панель «Скопировать · Найти»,
     и вместо меню человек получал выделение. Выделять там нечего: текст
     копируется пунктом меню. На компьютере выделение мышью остаётся — им
     пользуются, и никакого долгого нажатия там нет. */
  @media (pointer: coarse) {
    .msg {
      -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
    }
  }
  /* Стрелка ответа: рисунок, а не символ — «↩» телефон подменяет цветным
     эмодзи. Ширины она не занимает (отрицательное поле) и лежит под
     пузырём справа: свайп уводит пузырь влево и открывает её. */
  .msg::after {
    content: ''; flex: none; align-self: center; width: 19px; height: 19px;
    margin-left: -19px; background-color: var(--muted); opacity: 0;
    transform: scale(.55);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.5 15 4 9.5 9.5 4'/%3E%3Cpath d='M4 9.5h8.5a7 7 0 0 1 7 7V20'/%3E%3C/svg%3E") center / 19px 19px no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.5 15 4 9.5 9.5 4'/%3E%3Cpath d='M4 9.5h8.5a7 7 0 0 1 7 7V20'/%3E%3C/svg%3E") center / 19px 19px no-repeat;
    transition: opacity .16s ease, transform .16s ease, background-color .16s ease;
  }
  /* Пока переписка едет с сервера, на её месте стоят пустые пузыри: без них
     открытый на телефоне диалог выглядел мёртвым тёмным экраном, и менеджер
     не понимал, работает окно или зависло. */
  .feed-skel .msg { animation: none; }
  .feed-skel .bubble { box-shadow: none; }
  .feed-skel .skel { height: 10px; margin: 5px 0; max-width: 100%; }
  .msg.out { justify-content: flex-end; }
  .bubble {
    max-width: min(680px, 78%); padding: 11px 14px 8px; border-radius: 18px;
    border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow);
  }
  .msg.in .bubble { border-bottom-left-radius: 7px; }
  /* Наша реплика — заливкой акцентом, как в макете: в длинной переписке
     сразу видно, где отвечал менеджер, а где писал клиент. */
  .msg.out .bubble {
    border-color: transparent; background: var(--gold-fill); color: var(--on-accent);
    border-bottom-right-radius: 7px;
  }
  .bubble { transition: transform .26s cubic-bezier(.22, .9, .3, 1); }
  .bubble .text { font-size: 14.5px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
  .edit-dlg { width: min(520px, calc(100vw - 32px)); }
  .edit-text {
    width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
    font: 400 14px/1.5 Inter, sans-serif; resize: vertical;
  }
  .edit-text:focus { outline: none; border-color: hsl(var(--gold-hsl) / .45); }
  .bubble .meta { display: flex; gap: 8px; justify-content: flex-end; margin-top: 5px; font-size: 11px; color: var(--faint); }
  .bubble .meta .author { color: var(--gold-soft); font-weight: 600; }
  /* Своё сообщение, пока сервер его не подтвердил: то же место в ленте,
     но приглушённое, и часики вместо галочки. */
  .bubble.sending { opacity: .72; }
  /* Галочки «ушло / дошло / прочитано» — как в телефонных мессенджерах. */
  .bubble .ticks { display: inline-flex; align-items: center; opacity: .55; }
  .bubble .ticks.read { opacity: 1; color: var(--ink-accent); }
  .msg.out .bubble .ticks.read { color: var(--on-accent); opacity: 1; }
  .bubble.sending .clock { display: inline-flex; align-items: center; opacity: .8; }
  .bubble.sending .clock svg { width: 12px; height: 12px; }
  /* Не дошло. Красным — и с двумя выходами: повторить или убрать из ленты,
     чтобы неотправленное не висело вечно и не путалось с отправленным. */
  .bubble.undelivered { border-color: hsl(var(--danger-line-hsl) / .6); }
  .bubble.undelivered .meta { flex-wrap: wrap; align-items: center; }
  /* Причина занимает свою строку целиком: иначе длинная фраза расталкивает
     кнопки по разным строкам, и они выглядят как две разные мысли. */
  .bubble.undelivered .why { flex-basis: 100%; margin: 2px 0 7px; color: var(--danger); }
  .bubble.undelivered .again {
    height: 22px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--border-2);
    background: transparent; color: var(--text-2); font: 500 11px Inter, sans-serif; cursor: pointer;
  }
  .bubble.undelivered .again:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }
  /* Не дошедшее — в нашем же пузыре, а он залит акцентом. Красный на
     фиолетовом не читается совсем, поэтому здесь цвет тревоги другой:
     светло-янтарный, он виден на заливке в обеих темах. Рамка и кнопки —
     от заливки, а не от фона окна: серые на фиолетовом еле различимы. */
  .msg.out .bubble.undelivered { border-color: hsl(var(--warn-on-accent-hsl) / .6); }
  .msg.out .bubble.undelivered .why { color: hsl(var(--warn-on-accent-hsl)); }
  .msg.out .bubble.undelivered .again {
    border-color: hsl(var(--on-accent-hsl) / .45); color: var(--on-accent);
  }
  .msg.out .bubble.undelivered .again:hover {
    border-color: hsl(var(--on-accent-hsl) / .75);
    background: hsl(var(--on-accent-hsl) / .14); color: var(--on-accent);
  }
  .bubble.undelivered .again:active { transform: translateY(1px); }
  /* Всё, что внутри залитого пузыря, считает цвет от заливки, а не от фона окна. */
  .msg.out .bubble .meta { color: hsl(var(--on-accent-hsl) / .72); }
  .msg.out .bubble .meta .author { color: hsl(var(--on-accent-hsl) / .9); }
  .msg.out .bubble a { color: inherit; text-decoration: underline; }
  /* В нашем пузыре заливка акцентная — цитата берёт цвета от неё. */
  .msg.out .quoted {
    border-left-color: hsl(var(--on-accent-hsl) / .5); color: hsl(var(--on-accent-hsl) / .8);
    background: hsl(var(--on-accent-hsl) / .12);
  }
  .msg.out .quoted .who { color: hsl(var(--on-accent-hsl) / .95); }
  .msg.out .quoted:hover { color: var(--on-accent); background: hsl(var(--on-accent-hsl) / .18); }
  .msg.out .transcript { background: hsl(var(--on-accent-hsl) / .12); }
  .msg.out .transcript.note, .msg.out .pending, .msg.out .undecrypted { color: hsl(var(--on-accent-hsl) / .78); }
  .msg.out .file {
    border-color: hsl(var(--on-accent-hsl) / .35); background: hsl(var(--on-accent-hsl) / .12);
    color: inherit;
  }
  .msg.out .voice .play {
    border-color: hsl(var(--on-accent-hsl) / .45); background: hsl(var(--on-accent-hsl) / .16); color: inherit;
  }
  .msg.out .voice .wave i { background: hsl(var(--on-accent-hsl) / .38); }
  .msg.out .voice.playing .wave i, .msg.out .voice .wave i.done { background: hsl(var(--on-accent-hsl) / .85); }
  .msg.out .voice .clock, .msg.out .reaction .label { color: hsl(var(--on-accent-hsl) / .75); }
  /* Цитата ответа. «↩ ответ на сообщение» ничего не говорило: в переписке из
     сотни реплик это загадка, а не подсказка. Показываем, кого цитируют и что
     он сказал, и по клику отматываем к самому сообщению. */
  .quoted {
    display: block; width: 100%; margin-bottom: 6px; padding: 5px 9px; text-align: left;
    border: 0; border-left: 3px solid var(--gold); border-radius: 0 7px 7px 0;
    background: var(--quote-bg); color: var(--muted);
    font: 400 12px Inter, sans-serif; cursor: pointer;
    transition: color .18s ease, background .18s ease;
  }
  .quoted:hover { color: var(--text-2); }
  .quoted.plain { cursor: default; }
  .quoted .who { display: block; margin-bottom: 1px; font-size: 11.5px; font-weight: 600; color: var(--gold-soft); }
  .quoted .txt {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; line-height: 1.4;
  }
  /* Нашли цитируемое сообщение — подсвечиваем, иначе взгляд его теряет. */
  .msg.flash .bubble { animation: glowPulse 1.1s ease 2; }
  .bubble img, .bubble video { display: block; max-width: 100%; max-height: 320px; border-radius: 9px; object-fit: contain; }
  .shot { position: relative; display: inline-block; margin-bottom: 5px; cursor: zoom-in; line-height: 0; }
  .shot .zoom {
    position: absolute; right: 8px; bottom: 8px; padding: 3px 8px; border-radius: 999px;
    background: var(--overlay-soft); color: var(--text-2); font-size: 11px; line-height: 1.5;
    opacity: 0; transition: opacity .2s ease; pointer-events: none;
  }
  .shot:hover .zoom { opacity: 1; }
  /* Имя файла придумывает не сервис, а тот, кто его прислал: «Григорян_А_П,_
     Счет_на_оплату_№1043_pdf.pdf» — одно слово без пробелов, и разорвать его
     браузеру негде. Без ограничения по ширине и переноса карточка распирала
     сообщение изнутри и вылезала за его край. */
  .file {
    display: inline-flex; align-items: flex-start; gap: 9px; max-width: 100%;
    margin-bottom: 5px; padding: 9px 11px;
    border-radius: 9px; border: 1px solid var(--border-2); background: var(--panel-3);
    color: var(--text-2); font-size: 13.5px; line-height: 1.45; text-decoration: none;
  }
  .file .clip { flex: none; }
  .file .name { min-width: 0; overflow-wrap: anywhere; }
  .file:hover { border-color: hsl(var(--gold-hsl) / .45); }
  .voice { display: flex; align-items: center; gap: 10px; width: 280px; max-width: 100%; margin-bottom: 5px; }
  .voice audio { display: none; }
  .voice .play {
    flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
    border: 1px solid hsl(var(--gold-hsl) / .45); background: var(--gold-wash-2); color: var(--gold-soft);
    cursor: pointer; transition: background .2s ease, color .2s ease, transform .2s ease;
  }
  .voice .play:hover { transform: scale(1.06); }
  .voice.playing .play { background: var(--gold-fill); color: var(--on-accent); }
  .voice .ico {
    width: 0; height: 0; margin-left: 2px; border-left: 7px solid currentColor;
    border-top: 4.5px solid transparent; border-bottom: 4.5px solid transparent;
  }
  .voice.playing .ico {
    width: 8px; height: 10px; margin-left: 0; border: 0;
    border-left: 3px solid currentColor; border-right: 3px solid currentColor;
  }
  .voice .wave { display: flex; align-items: center; gap: 2px; flex: 1; min-width: 0; height: 26px; cursor: pointer; }
  .voice .wave i { flex: 1; min-width: 0; border-radius: 2px; background: var(--wave-off); transition: background .12s linear; }
  .voice.playing .wave i { background: var(--wave-on); }
  .voice .wave i.done { background: var(--gold-soft); }
  .voice .clock {
    flex: none; font-family: var(--num); font-size: 11.5px; color: var(--muted-2);
    font-variant-numeric: tabular-nums;
  }
  .transcript {
    display: flex; gap: 7px; margin: 2px 0 5px; padding: 7px 9px; border-radius: 9px;
    background: var(--quote-bg); font-size: 13.5px; line-height: 1.45;
  }
  .transcript .mic { flex: none; opacity: .65; }
  .transcript .said { white-space: pre-wrap; overflow-wrap: anywhere; }
  .transcript.note { color: var(--muted); font-size: 12px; }
  .undecrypted {
    display: flex; align-items: flex-start; gap: 8px; font-size: 13px; line-height: 1.45;
    color: var(--muted-2); cursor: help;
  }
  .undecrypted .sign { flex: none; color: var(--warn); }
  /* Реакция на своём сообщении: маленькая плашка у нижнего края пузыря,
     как в мессенджерах. Отдельный пузырь остаётся только для реакции на
     сообщение, которого нет в загруженной переписке. */
  .bubble .reacts { display: flex; gap: 4px; margin-top: 6px; }
  .react-chip {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 26px; height: 22px; padding: 0 6px; border-radius: 11px;
    border: 1px solid var(--border); background: var(--panel);
    font-size: 13px; line-height: 1;
  }
  .msg.out .react-chip { border-color: hsl(var(--gold-hsl) / .35); background: var(--panel-2); }
  /* Наша фишка — с золотой рамкой: сразу видно, чья реакция. Счётчик — когда
     смайлик один на двоих. */
  .react-chip.mine { border-color: hsl(var(--gold-hsl) / .55); }
  .react-chip .n { margin-left: 4px; font-size: 11px; color: var(--muted); }
  .reaction { display: flex; align-items: center; gap: 9px; }
  .reaction .emoji { font-size: 26px; line-height: 1; }
  .reaction .label { font-size: 12.5px; color: var(--muted); }
  .pending, .failed { font-size: 12.5px; }
  .shot-wait { width: 240px; max-width: 100%; margin-bottom: 5px; }
  .shot-wait .skel { display: block; width: 100%; height: 150px; border-radius: 9px; }
  .shot-wait .pending { display: block; margin-top: 6px; }
  .pending { color: var(--muted); }
  .failed { color: var(--danger); }

  /* ---------- подсказки и ввод ---------- */
  .quick {
    flex: none; padding: 10px 16px 4px; background: var(--sunken); border-top: 1px solid var(--line);
  }
  .quick[hidden] { display: none; }
  .quick .hint { display: block; font-size: 12px; color: var(--muted); }
  .sg-ask {
    padding: 7px 14px; border-radius: 999px; border: 1px dashed hsl(var(--gold-hsl) / .4);
    background: var(--gold-wash); color: var(--gold-soft); font: 500 12.5px 'Golos Text', Inter, sans-serif;
    cursor: pointer; transition: background .2s ease, border-color .2s ease, transform .2s ease;
  }
  .sg-ask:hover { background: var(--gold-tint); border-color: hsl(var(--gold-hsl) / .65); }
  .sg-ask:active { transform: translateY(1px); }
  .sg-ask:disabled { opacity: .6; cursor: default; }
  /* Подсказка и правка ошибок стоят рядом над строкой ввода. В самой строке
     для второй кнопки места не осталось: поле сжималось до двух слов. */
  .quick-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
  .sg + .quick-row { margin-top: 9px; }
  .sg-fix { display: inline-flex; align-items: center; gap: 7px; }
  .sg-fix .ico-fix { width: 15px; height: 14px; }
  /* Перевод черновика — соседняя кнопка того же вида: обе про то, что сервис
     делает с уже набранным текстом. Появляется вместе с переводом диалога и
     не возникает рывком — раздвигает соседей ростом от нуля. */
  .sg-tr { display: inline-flex; align-items: center; gap: 7px; }
  .sg-tr .ico-tr { width: 15px; height: 15px; }
  @keyframes sgTrIn {
    from { max-width: 0; padding-left: 0; padding-right: 0; opacity: 0; transform: scale(.85); }
    to { max-width: 260px; padding-left: 14px; padding-right: 14px; opacity: 1; transform: none; }
  }
  .sg-tr.grow { animation: sgTrIn .3s cubic-bezier(.2, .8, .3, 1); overflow: hidden; white-space: nowrap; }
  @media (prefers-reduced-motion: reduce) { .sg-tr.grow { animation: none; } }
  /* На телефоне от кнопки остаётся значок: с подписью ряд не влезал в строку
     и уезжал на вторую, съедая ленту. Соседки без своих слов непонятны,
     а перевод — картинка, которую видно и так. */
  @media (max-width: 720px) {
    .sg-tr { padding: 7px 9px; gap: 0; }
    .sg-tr .lbl { display: none; }
    .sg-tr .ico-tr { width: 16px; height: 16px; }
    /* Три кнопки в строку помещаются только вместе: значок вместо подписи
       экономит половину нужного, остальное отдают отступы соседок. */
    .quick-row { gap: 6px; }
    .sg-ask { padding: 7px 11px; font-size: 12px; }
  }
  /* Подсказка — это карточка, а не строка: у реплики есть приём и объяснение,
     иначе менеджер вставляет чужие слова, не понимая зачем. */
  .sg {
    padding: 14px 16px 13px; border-radius: 18px; border: 1px solid var(--border);
    background: var(--panel); box-shadow: var(--shadow);
    animation: stackIn .3s cubic-bezier(.2, .8, .3, 1) both;
  }
  .sg-top { display: flex; align-items: center; gap: 9px; margin-bottom: 9px; }
  .sg-badge {
    flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 9px;
    background: var(--gold-fill); color: var(--on-accent); font: 700 11.5px/1 'Golos Text', Inter, sans-serif;
  }
  .sg-method { font-size: 13.5px; font-weight: 700; color: var(--gold); }
  .sg-x {
    margin-left: auto; flex: none; width: 26px; height: 26px; border-radius: 8px;
    border: 1px solid var(--border); background: transparent; color: var(--muted);
    font-size: 12px; cursor: pointer; transition: border-color .2s ease, color .2s ease;
  }
  .sg-x:hover { border-color: hsl(var(--gold-hsl) / .5); color: var(--gold-soft); }
  .sg-text { font-size: 15px; line-height: 1.55; }
  .sg-why { margin-top: 8px; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
  .sg-acts { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
  .sg-btn {
    height: 34px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--border-2);
    background: var(--panel-2); color: var(--text-2); font: 600 13px 'Golos Text', Inter, sans-serif;
    cursor: pointer; transition: border-color .2s ease, color .2s ease, transform .2s ease;
  }
  .sg-btn:hover { border-color: hsl(var(--gold-hsl) / .5); color: var(--gold-soft); }
  .sg-btn:active { transform: translateY(1px); }
  .sg-btn.primary { border-color: transparent; background: var(--gold-fill); color: var(--on-accent); }
  .sg-btn.primary:hover { filter: brightness(1.06); color: var(--on-accent); }
  .sg-btn:disabled { opacity: .5; cursor: default; transform: none; }
  .sg-count { font-size: 12px; color: var(--muted); }

  /* ---------- задача по диалогу ---------- */
  /* Задачу ставит разбор, а видеть её надо там, где по ней работают. */
  .ctask { flex: none; padding: 8px 16px 0; background: var(--sunken); }
  .ctask[hidden] { display: none; }
  .ctask .box {
    display: flex; align-items: flex-start; gap: 10px; padding: 10px 13px; border-radius: 14px;
    border: 1px solid hsl(var(--ok-line-hsl) / .3); background: hsl(var(--ok-line-hsl) / .1);
    font-size: 13.5px; line-height: 1.5;
    animation: stackIn .3s cubic-bezier(.2, .8, .3, 1) both;
    transition: opacity .25s ease, transform .25s ease;
  }
  .ctask .box.closing { opacity: 0; transform: translateY(-6px); }
  .ctask .tick {
    flex: none; display: grid; place-items: center; width: 26px; height: 26px; padding: 0; border-radius: 9px;
    border: 1px solid hsl(var(--ok-line-hsl) / .45); background: hsl(var(--ok-line-hsl) / .16);
    color: var(--ok); font-size: 12px; cursor: pointer; transition: background .2s ease, color .2s ease;
  }
  .ctask .tick:hover { background: hsl(var(--ok-line-hsl) / .85); color: hsl(0 0% 100%); }
  .ctask b { color: var(--ok); font-weight: 700; }
  .ctask .aside { color: var(--muted); }
  .composer {
    flex: none; display: flex; gap: 10px; padding: 10px 16px 14px; background: var(--sunken);
  }
  .composer[hidden] { display: none; }
  .composer textarea {
    flex: 1; min-width: 0; min-height: 42px; max-height: 150px; padding: 10px 13px; resize: none;
    border-radius: 10px; border: 1px solid var(--border); background: var(--panel-3);
    color: var(--text); font-size: 14px; line-height: 1.4; outline: none; transition: border-color .2s ease;
  }
  .composer textarea:focus { border-color: hsl(var(--gold-hsl) / .45); }
  .composer button {
    flex: none; align-self: flex-end; height: 42px; padding: 0 18px; border-radius: 10px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 13.5px Inter, sans-serif; cursor: pointer;
    transition: filter .2s ease, transform .2s ease;
  }
  .composer button:hover { filter: brightness(1.06); }
  .composer button:active { transform: translateY(1px); }
  .composer button:disabled { filter: grayscale(.5); cursor: default; }
  /* Кнопка отправки появляется, только когда есть что отправлять: набранный
     текст, записанное голосовое или вложение. Пустая, она занимала место в
     строке и обещала действие, которого нет. Схлопываем её по ширине, а не
     прячем: поле ввода тогда плавно забирает освободившееся место, а не
     прыгает на него рывком. */
  #composer-send {
    overflow: hidden; white-space: nowrap;
    max-width: 0; padding-left: 0; padding-right: 0; margin-left: -10px;
    opacity: 0; transform: scale(.55); pointer-events: none;
    transition: max-width .34s cubic-bezier(.22, .9, .28, 1),
                padding .34s cubic-bezier(.22, .9, .28, 1),
                margin-left .34s cubic-bezier(.22, .9, .28, 1),
                opacity .2s ease, filter .2s ease,
                transform .34s cubic-bezier(.24, 1.24, .38, 1);
  }
  #composer-send.ready {
    /* 124px — с запасом над реальными 108: max-width задаёт скорость роста,
       и чем он ближе к настоящей ширине, тем меньше кнопка «доезжает» уже
       невидимой частью. */
    max-width: 124px; padding-left: 18px; padding-right: 18px; margin-left: 0;
    opacity: 1; transform: scale(1); pointer-events: auto;
  }
  #composer-send.ready:active { transform: scale(.955); }
  .composer .tool {
    flex: none; align-self: flex-end; display: grid; place-items: center; width: 42px; height: 42px;
    padding: 0; border-radius: 10px; border: 1px solid var(--border); background: var(--panel-3);
    color: var(--muted-2); cursor: pointer;
    transition: border-color .2s ease, color .2s ease, background .2s ease;
  }
  .composer .tool:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); filter: none; }
  .composer .tool[hidden] { display: none; }
  .composer .tool.recording {
    border-color: hsl(var(--danger-line-hsl) / .55); background: hsl(var(--danger-line-hsl) / .16); color: var(--danger);
    animation: glowPulse 1.6s ease-in-out infinite;
  }
  /* Скрепка и микрофон нарисованы, а не набраны символами: эмодзи в разных
     системах выглядят по-разному, а нужного знака в шрифте окна нет. */
  .ico-mic { display: block; width: 17px; height: 17px; }
  /* Скрепка — рисунком, а не рамкой: скруглённый прямоугольник под наклоном
     читался как капсула, и кнопку принимали за что угодно, кроме вложения. */
  .ico-clip {
    display: block; width: 18px; height: 18px; fill: none; stroke: currentColor;
    stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
  }
  /* Проверка ошибок: буква со знаком проверки. Слово на кнопку не влезает,
     а «галочка» без буквы читалась бы как «отправить». */
  .ico-fix {
    display: block; width: 19px; height: 18px; fill: none; stroke: currentColor;
    stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  }
  /* Стрелка отправки — для телефона, где слову «Отправить» не хватает места. */
  .ico-send {
    display: none; width: 0; height: 0; margin-left: 2px;
    border-top: 8px solid transparent; border-bottom: 8px solid transparent;
    border-left: 13px solid var(--on-accent);
  }
  .ico-mic {
    position: relative; box-sizing: border-box; width: 8px; height: 12px;
    border: 1.6px solid currentColor; border-radius: 5px; margin-bottom: 5px;
  }
  .ico-mic::after {
    content: ''; position: absolute; left: 50%; bottom: -6px; width: 14px; height: 7px;
    border: 1.6px solid currentColor; border-top: 0; border-radius: 0 0 9px 9px;
    transform: translateX(-50%);
  }

  /* На что отвечаем — прямо над строкой ввода, как в мессенджерах. Полоска
     слева и крестик справа: видно и куда уйдёт цитата, и как передумать. */
  .reply-bar {
    flex: none; display: flex; align-items: center; gap: 10px;
    padding: 8px 16px 0; background: var(--sunken);
  }
  .reply-bar[hidden] { display: none; }
  .reply-bar .box {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px;
    padding: 7px 10px; border-radius: 10px; border: 1px solid var(--border-2);
    border-left: 3px solid var(--gold); background: var(--panel-2);
  }
  .reply-bar .who { flex: none; font-size: 12px; font-weight: 600; color: var(--gold-soft); }
  .reply-bar .txt {
    flex: 1; min-width: 0; font-size: 12.5px; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .reply-bar .drop {
    flex: none; width: 26px; height: 26px; padding: 0; border-radius: 8px;
    border: 1px solid var(--border-2); background: var(--panel-2); color: var(--muted);
    font-size: 13px; cursor: pointer;
  }
  .reply-bar .drop:hover { border-color: hsl(var(--danger-line-hsl) / .5); color: var(--danger); }
  /* Меню сообщения: ряд реакций сверху, действия под ним. Открывается правой
     кнопкой и долгим нажатием — как в обычном мессенджере, где на самой
     реплике не висит ни одной кнопки. */
  .msg-menu {
    position: fixed; z-index: 70; min-width: 208px; padding: 6px;
    border-radius: 14px; border: 1px solid var(--border-2); background: var(--panel-2);
    box-shadow: var(--shadow-lg); animation: menuIn .22s cubic-bezier(.18, .92, .26, 1);
  }
  .msg-menu .row {
    display: flex; gap: 2px; padding: 2px 2px 6px; margin-bottom: 4px;
    border-bottom: 1px solid var(--line);
  }
  .msg-menu .row button {
    flex: 1; height: 34px; padding: 0; border: 0; border-radius: 9px; background: none;
    font-size: 19px; line-height: 1; cursor: pointer; transition: background .15s ease;
  }
  .msg-menu .row button:hover { background: var(--panel-4); }
  .msg-menu .row button.on { background: var(--gold-wash); }
  .msg-menu .act {
    display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px;
    border: 0; border-radius: 9px; background: none; color: var(--text-2);
    font: 500 13.5px Inter, sans-serif; text-align: left; cursor: pointer;
  }
  .msg-menu .act:hover { background: var(--panel-4); color: var(--text); }
  .msg-menu .act .lbl { flex: 1; min-width: 0; }
  .msg-menu .act .hint { flex: none; font-size: 15px; }
  @keyframes menuIn {
    from { opacity: 0; transform: scale(.9); }
    to { opacity: 1; transform: scale(1); }
  }
  /* Пока меню открыто, остальная переписка уходит на второй план, а выбранное
     сообщение чуть подрастает: видно, о какой именно реплике речь. */
  /* Переход держим на самих сообщениях, а не на .menu-open: иначе размытие
     наводилось плавно, а снималось рывком — правило исчезало вместе с классом. */
  .feed .msg, .feed .day { transition: filter .26s ease, opacity .26s ease; }
  .feed.menu-open .msg:not(.picked), .feed.menu-open .day {
    filter: blur(2.5px); opacity: .5;
  }
  /* Палец лёг на сообщение — пузырь чуть проседает и держится так всё
     нажатие; открылось меню — распрямляется с лёгким перелётом. */
  .msg.holding .bubble {
    transform: scale(.975); transition: transform .34s cubic-bezier(.25, .8, .3, 1);
  }
  .msg.picked .bubble {
    transform: scale(1.045); box-shadow: var(--shadow-lg);
    transition: transform .28s cubic-bezier(.22, 1.12, .36, 1);
  }
  /* Свайп вправо — ответ. Стрелка проявляется по мере сдвига, а на пороге
     ответа загорается акцентом: видно, отпускать уже можно или ещё рано. */
  .msg.swiping .bubble { transition: none; }
  .msg.swiping::after { opacity: .5; transform: scale(1); }
  .msg.will-reply::after { background-color: var(--gold-soft); opacity: 1; }
  .attach-bar {
    flex: none; display: flex; gap: 8px; padding: 9px 16px 0; overflow-x: auto; background: var(--sunken);
  }
  .attach-bar[hidden] { display: none; }
  .attach-card {
    position: relative; flex: none; display: flex; align-items: center; gap: 9px; max-width: 260px;
    padding: 7px 30px 7px 8px; border-radius: 10px; border: 1px solid var(--border-2);
    background: var(--panel-2); animation: rowIn .24s cubic-bezier(.2, .8, .3, 1) both;
  }
  .attach-card img { width: 38px; height: 38px; border-radius: 7px; object-fit: cover; }
  .attach-card .doc {
    display: grid; place-items: center; width: 38px; height: 38px; border-radius: 7px;
    background: var(--panel-4); color: var(--gold-soft); font: 600 10px var(--num);
  }
  .attach-card .who { min-width: 0; }
  .attach-card .name {
    font-size: 12.5px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .attach-card .size { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  .attach-card .drop {
    position: absolute; top: 6px; right: 7px; width: 18px; height: 18px; padding: 0; border-radius: 50%;
    border: 0; background: transparent; color: var(--muted); font-size: 13px; line-height: 1; cursor: pointer;
  }
  .attach-card .drop:hover { color: var(--danger); }
  .attach-card.busy { opacity: .6; }
  .attach-card .bar {
    position: absolute; left: 8px; right: 8px; bottom: 3px; height: 2px; border-radius: 2px;
    background: linear-gradient(90deg, var(--gold), hsl(var(--gold-hsl) / 0));
    background-size: 200% 100%; animation: shimmer 1.2s linear infinite;
  }
  .rec-status { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--danger); }
  .rec-status .dot {
    width: 8px; height: 8px; border-radius: 50%; background: var(--danger);
    animation: pulseDot 1.2s ease-in-out infinite;
  }
  .rec-status .clock { font-family: var(--num); font-variant-numeric: tabular-nums; }
  .rec-status button {
    height: 26px; padding: 0 10px; border-radius: 7px; border: 1px solid var(--border-2);
    background: transparent; color: var(--text-2); font: 500 12px Inter, sans-serif; cursor: pointer;
  }
  .rec-status button:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }

  .drop-hint {
    position: absolute; inset: 0; z-index: 40; display: grid; place-items: center;
    background: var(--drop-veil); border: 2px dashed hsl(var(--gold-hsl) / .5); border-radius: 12px;
    color: var(--gold-soft); font-size: 15px; animation: fadeIn .15s ease; pointer-events: none;
  }
  .drop-hint[hidden] { display: none; }

  .send-error { flex: none; padding: 0 16px 9px; background: var(--sunken); font-size: 12.5px; color: var(--danger); }
  .send-error[hidden] { display: none; }

  /* ---------- панель клиента ---------- */
  .panel[hidden], .chat-head[hidden], .filters[hidden], .ball[hidden], .nav[hidden],
  .send-error[hidden], .conn-missing[hidden], .chart[hidden] { display: none !important; }
  .panel:empty { display: none !important; }
  .panel {
    position: relative; display: flex; flex-direction: column; min-height: 0; overflow-y: auto;
    border-left: 1px solid var(--line); background: var(--panel);
    animation: panelIn .3s cubic-bezier(.2, .8, .3, 1);
  }
  /* Крестик нужен только шторке на узких экранах — на широких панель живёт
     своей колонкой и закрывается кнопкой в шапке чата. */
  .panel-close {
    display: none; position: absolute; top: 10px; right: 10px; z-index: 2;
    place-items: center; width: 34px; height: 34px; border-radius: 9px;
    border: 1px solid var(--border-2); background: var(--panel-2); color: var(--text-2);
    font-size: 18px; line-height: 1; cursor: pointer;
  }
  .panel-close:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }
  .panel-head { padding: 20px 18px 16px; text-align: center; border-bottom: 1px solid var(--line); }
  .panel-head .avatar { width: 62px; height: 62px; margin: 0 auto 12px; }
  .panel-head .avatar b { font-size: 22px; }
  .panel-head .name {
    font-size: 15.5px; font-weight: 600;
    display: flex; align-items: center; justify-content: center; gap: 6px;
  }
  .panel-head .name-edit {
    flex: none; padding: 0 4px; border: 0; background: none; color: var(--muted);
    font-size: 13px; cursor: pointer; opacity: 0; transition: opacity .15s ease, color .15s ease;
  }
  .panel-head:hover .name-edit, .panel-head .name-edit:focus { opacity: 1; }
  .panel-head .name-edit:hover { color: var(--gold-soft); }
  .panel-head .name-field {
    width: 100%; max-width: 240px; padding: 4px 8px; border-radius: 7px;
    border: 1px solid var(--border-2); background: var(--panel-2); color: var(--text);
    font: 600 15px Inter, sans-serif; text-align: center;
  }
  .panel-head .row { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 7px; font-size: 12.5px; color: var(--muted); }
  .panel-head .deal-line { margin-top: 8px; }
  .panel-head .deal { max-width: 100%; display: inline-block; text-decoration: none; }
  .panel-head a { display: inline-block; margin-top: 10px; font-size: 12.5px; font-weight: 500; }
  /* Действия под именем. Избранное и «рабочий» — короткие пометки одного
     веса, они стоят парой в одной строке. Перевод под ними: он не пометка,
     а вход в отдельный разговор про язык, и в общем ряду читался бы третьей
     галочкой. Столбиком по центру — чтобы под именем клиента не было
     лесенки из разноширинных строк. */
  .panel-acts {
    display: flex; flex-direction: column; align-items: center; gap: 9px; margin-top: 14px;
  }
  .panel-acts .top {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
    gap: 8px 16px; max-width: 100%;
  }
  .panel-acts .top > * { flex: none; white-space: nowrap; }
  /* Значку отведено ровно 15 px в каждой из трёх кнопок: надписи набраны нашим
     Inter и везде одинаковы, а эмодзи рисует система, и на маке они шире.
     С фиксированной коробкой ширина строки перестаёт зависеть от машины. */
  .panel-star .s, .panel-work .s, .panel-tr .s { flex: none; width: 15px; text-align: center; }
  .panel-acts a { margin-top: 0; }
  /* Избранное словами. В шапке чата это значок среди значков — на телефоне
     его не ищут, а карточку клиента открывают руками и читают.
     Не плашка, а такая же надпись, как ссылка на лид рядом: две кнопки
     с рамками в шапке карточки спорили друг с другом и с именем клиента. */
  .panel-star {
    display: inline-flex; align-items: center; gap: 6px; min-height: 26px;
    padding: 0; border: 0; background: none; color: var(--muted);
    font: 500 12.5px Inter, sans-serif; cursor: pointer;
    transition: color .2s ease;
  }
  .panel-star:hover { color: var(--gold-soft); }
  .panel-star .s { font-size: 14px; line-height: 1; color: var(--faint); transition: color .2s ease; }
  .panel-star:hover .s { color: var(--gold-soft); }
  .panel-star.on { color: var(--gold-soft); }
  .panel-star.on .s { color: var(--gold); }
  /* Пометка «рабочий» — надпись того же роста, что и избранное, но не золотая:
     это не выделение диалога, а отказ от его разбора. */
  .panel-work {
    display: inline-flex; align-items: center; gap: 6px; min-height: 26px;
    padding: 0; border: 0; background: none; color: var(--muted);
    font: 500 12.5px Inter, sans-serif; cursor: pointer;
    transition: color .2s ease;
  }
  .panel-work:hover { color: var(--text); }
  .panel-work .s { font-size: 13px; line-height: 1; filter: grayscale(1); opacity: .7; }
  .panel-work.on { color: var(--text); }
  .panel-work.on .s { filter: none; opacity: 1; }
  .panel-work[disabled] { opacity: .5; cursor: default; }
  /* Перевод переписки — такая же надпись, как избранное и «рабочий». */
  .panel-tr {
    display: inline-flex; align-items: center; gap: 6px; min-height: 26px;
    padding: 0; border: 0; background: none; color: var(--muted);
    font: 500 12.5px Inter, sans-serif; cursor: pointer;
    transition: color .2s ease;
  }
  .panel-tr:hover { color: var(--text); }
  .panel-tr .s { font-size: 13px; line-height: 1; filter: grayscale(1); opacity: .7; }
  .panel-tr.on { color: var(--text); }
  .panel-tr.on .s { filter: none; opacity: 1; }
  /* Четыре цифры в один ряд: в сетке 2×2 каждая клетка была наполовину пустой,
     и справка о клиенте занимала четверть карточки, оттесняя вниз то, ради чего
     её открывают. */
  .panel-stats { display: grid; grid-template-columns: repeat(3, 1fr); border-bottom: 1px solid var(--line); }
  /* Без разделителей между плитками: цифры и так стоят колонками,
     а полоски дробили карточку на клетки. */
  .panel-stats div { min-width: 0; padding: 9px 4px; text-align: center; }
  .panel-stats .v { font-family: var(--num); font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
  .panel-stats .v.bad { color: var(--danger); }
  .panel-stats .l { margin-top: 1px; font-size: 10.5px; line-height: 1.3; color: var(--muted); }
  .panel-sec { padding: 15px 18px; border-bottom: 1px solid var(--line); }
  .panel-sec h4 { margin: 0 0 10px; font-size: 10.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
  .panel-sec p { margin: 0; font-size: 13px; line-height: 1.55; color: var(--text-2); }
  .tags { display: flex; flex-wrap: wrap; gap: 6px; }
  .tag { padding: 2px 9px; border-radius: 999px; border: 1px solid var(--border-2); background: var(--panel-2); color: var(--muted-2); font-size: 11.5px; }
  /* Заметка о клиенте: что помнить именно про этого человека. */
  .note-box { display: flex; flex-direction: column; gap: 8px; }
  .note-box textarea {
    width: 100%; min-height: 76px; padding: 9px 11px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font: 400 13px Inter, sans-serif; line-height: 1.5; resize: vertical; outline: none;
  }
  .note-box textarea:focus { border-color: hsl(var(--gold-hsl) / .45); }
  .note-row { display: flex; align-items: center; gap: 10px; }
  /* Сохранённая заметка — текст, а не поле: её читают чаще, чем правят. */
  .note-text { font-size: 13.5px; line-height: 1.55; color: var(--text); white-space: pre-wrap; word-break: break-word; }
  .note-row .when { flex: 1; min-width: 0; font-size: 11px; color: var(--faint); }
  .note-save {
    height: 32px; padding: 0 14px; border-radius: 9px; border: 1px solid hsl(var(--gold-hsl) / .4);
    background: hsl(var(--gold-hsl) / .12); color: var(--gold-soft);
    font: 600 12.5px Inter, sans-serif; cursor: pointer;
  }
  .note-save:disabled { opacity: .5; cursor: default; }
  .media { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .media a {
    position: relative; display: block; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
    border: 1px solid var(--border-2); background: var(--bg); cursor: zoom-in;
    transition: border-color .2s ease, transform .2s ease;
  }
  .media a:hover { border-color: hsl(var(--gold-hsl) / .5); transform: translateY(-1px); }
  .media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
  .media .doc { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--num); font-size: 11px; color: var(--muted-2); }

  /* ---------- дашборд ---------- */
  .board-inner { max-width: 1180px; margin: 0 auto; padding: 22px 18px 70px; }
  .period { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
  .pill {
    padding: 7px 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel);
    color: var(--muted); font: 500 13px Inter, sans-serif; cursor: pointer; white-space: nowrap;
    transition: border-color .2s ease, background .2s ease, color .2s ease, transform .2s ease;
  }
  .pill:hover { border-color: var(--border-2); color: var(--text-2); }
  .pill.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-fill); color: var(--on-accent); font-weight: 600; }
  .pill-sep { width: 1px; height: 20px; margin: 0 3px; background: var(--border-2); }
  .pill.mood-pill.on { border-color: hsl(var(--danger-line-hsl) / .5); background: var(--danger); color: var(--on-danger); }
  .custom { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 16px; font-size: 13px; color: var(--muted); }
  .custom[hidden] { display: none; }
  .custom input {
    height: 32px; padding: 0 10px; border-radius: 8px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text); font-size: 13px; outline: none;
  }
  /* Три плитки вместо девяти. Руководителю нужны три вопроса: что горит,
     как быстро отвечаем, сколько пришло. Остальные цифры ушли в полосу ниже —
     они справочные, ради них не стоит дробить экран на десяток одинаковых
     прямоугольников, среди которых главное не видно. */
  .heroes { display: grid; grid-template-columns: 1.15fr 1fr 1fr; gap: 12px; }
  .hero {
    padding: 18px 20px 16px; border-radius: 14px; border: 1px solid var(--border);
    background: var(--panel); box-shadow: var(--shadow);
    animation: rowIn .32s cubic-bezier(.2, .8, .3, 1) both;
    transition: border-color .24s ease;
  }
  .hero .cap {
    font-size: 11.5px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--muted);
  }
  .hero .top { display: flex; align-items: flex-end; gap: 12px; margin-top: 10px; }
  .hero .big {
    font-family: var(--num); font-size: 46px; font-weight: 700; line-height: .95;
    font-variant-numeric: tabular-nums;
  }
  .hero .big small { font-size: 20px; font-weight: 600; }
  .hero .aside { font-size: 13px; line-height: 1.4; color: var(--text-2); padding-bottom: 5px; }
  .hero .delta { font-size: 12.5px; line-height: 1.4; font-weight: 600; padding-bottom: 7px; }
  .hero .delta.up { color: var(--ok); }
  .hero .delta.down { color: var(--danger); }
  .hero .delta span { display: block; color: var(--muted); font-weight: 400; }
  .hero .lines { margin-top: 12px; display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; color: var(--muted); }
  .hero .lines b { color: var(--text-2); font-weight: 600; }
  .hero .lines b.warn { color: var(--warn); }
  .hero .rows { margin-top: 14px; display: flex; flex-direction: column; gap: 7px; font-size: 12.5px; color: var(--muted); }
  .hero .rows div { display: flex; justify-content: space-between; gap: 12px; }
  .hero .rows .n { font-family: var(--num); color: var(--text-2); font-variant-numeric: tabular-nums; }
  .hero .rows .n.bad { color: var(--danger); }
  /* Столбики по дням — не график, а форма кривой: падает медиана или растёт. */
  .hero .spark { margin-top: 14px; display: flex; align-items: flex-end; gap: 3px; height: 38px; }
  .hero .spark i {
    flex: 1; min-width: 0; background: hsl(var(--gold-hsl) / .35); border-radius: 2px 2px 0 0;
    transition: height .5s cubic-bezier(.2, .8, .3, 1);
  }
  .hero .spark i.last { background: var(--gold-fill); }
  .hero .foot { margin-top: 8px; font-size: 12.5px; line-height: 1.4; color: var(--muted); }
  .hero .go {
    margin-top: 14px; height: 32px; padding: 0 14px; border-radius: 999px;
    border: 1px solid hsl(var(--danger-line-hsl) / .5); background: hsl(var(--danger-line-hsl) / .18);
    color: var(--danger); font: 600 12.5px 'Golos Text', Inter, sans-serif; cursor: pointer;
    transition: background .2s ease;
  }
  .hero .go:hover { background: hsl(var(--danger-line-hsl) / .3); }
  .hero.bad { border-color: hsl(var(--danger-line-hsl) / .34); background: linear-gradient(150deg, hsl(var(--danger-line-hsl) / .12), var(--panel)); }
  .hero.bad .cap, .hero.bad .big { color: var(--danger); }
  .hero.gold { border-color: hsl(var(--gold-hsl) / .3); background: linear-gradient(150deg, var(--gold-tint), var(--panel)); }
  .hero.gold .cap, .hero.gold .big { color: var(--gold-soft); }
  .hero .skel { display: block; }
  .strip {
    display: flex; align-items: center; flex-wrap: wrap; gap: 6px 22px; margin-top: 12px;
    padding: 11px 18px; border-radius: 12px; border: 1px solid var(--border);
    background: var(--sunken); font-size: 12.5px; color: var(--muted);
  }
  .strip b { font-family: var(--num); color: var(--text-2); font-weight: 600; font-variant-numeric: tabular-nums; }
  .strip .up { color: var(--ok); }
  .strip .down { color: var(--danger); }
  .strip .sep { width: 1px; height: 14px; background: var(--border-2); }
  .strip .spacer { flex: 1; }
  .strip button {
    border: 0; background: none; padding: 0; font: 400 12.5px 'Golos Text', Inter, sans-serif;
    color: var(--gold-soft); cursor: pointer;
  }
  .strip button:hover { color: var(--gold-bright); }
  .stamp { font-size: 12.5px; color: var(--faint); }
  .period-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
  .period-row .period, .board-h .period, .filter-row .period { margin: 0; }
  .chart {
    margin-top: 14px; padding: 16px 18px 12px; border-radius: 12px; border: 1px solid var(--border);
    background: var(--panel); box-shadow: var(--shadow);
  }
  .chart .head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
  .chart h3 { margin: 0; font-family: var(--serif); font-size: 17px; font-weight: 600; }
  .chart .legend { display: flex; gap: 14px; font-size: 11.5px; color: var(--muted); }
  .chart .legend i { display: inline-block; width: 9px; height: 9px; margin-right: 6px; border-radius: 2px; }
  .chart .bars { display: flex; align-items: flex-end; gap: 6px; height: 132px; }
  .chart .slot { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; }
  .chart .pair { display: flex; align-items: flex-end; justify-content: center; gap: 2px; width: 100%; height: 110px; }
  .chart .bar { flex: 1; min-width: 0; max-width: 9px; border-radius: 3px 3px 0 0; transition: height .5s cubic-bezier(.2, .8, .3, 1), filter .16s ease; }
  .chart .bar:hover { filter: brightness(1.25); }
  .chart .bar.in { background: var(--chart-in); }
  .chart .bar.out { background: var(--gold-fill); }
  .chart .hour { font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
  /* Вкладки в одну строку и по одной высоте. Длинные названия — «Платежи и
     касса», «Настройки сервиса» — переносились на два ряда, и соседние
     короткие вставали по центру относительно них: ряд получался рваный.
     Перенос запрещён, а если вкладки не влезают по ширине, ряд прокручивается
     вбок — прятать вкладки из-за длинного слова нельзя. */
  /* ---------- аналитика ---------- */
  .an-note { color: var(--muted); font-size: 12.5px; margin: 2px 0 12px; line-height: 1.5; }
  .an-cards { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
  /* Цифры в карточке: крупно значение, под ним словами что это. Читают
     карточку по одному человеку, и подпись важнее компактности. */
  .an-nums {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
    gap: 10px; margin: 0 0 14px;
  }
  .an-num {
    padding: 10px 12px; border-radius: 11px; background: var(--panel-2);
    border: 1px solid var(--line);
  }
  .an-num b {
    display: block; font-size: 19px; font-weight: 600; line-height: 1.2;
    font-variant-numeric: tabular-nums;
  }
  .an-num b.bad { color: var(--danger); }
  .an-num b.good { color: var(--ok); }
  .an-num span { display: block; margin-top: 3px; font-size: 11.5px; color: var(--muted); }
  .an-card .who { margin: 3px 0 0; font-size: 12px; color: var(--muted); }
  .an-card { border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px; background: var(--panel); }
  .an-card h3 { margin: 0; font-size: 15px; }
  .an-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
  .an-head .avatar { flex: none; width: 40px; height: 40px; font-size: 14px; }
  .an-card p { margin: 0 0 10px; line-height: 1.55; }
  .an-card ul { margin: 0 0 10px; padding-left: 18px; line-height: 1.55; }
  .an-card .lab { color: var(--muted); font-size: 12px; margin-bottom: 4px; }
  .an-advice { border-left: 2px solid hsl(var(--gold-hsl) / .6); padding-left: 10px; }
  .board-tabs {
    display: flex; gap: 8px; margin: 26px 0 14px; border-bottom: 1px solid var(--line);
    align-items: flex-end; overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  }
  .board-tabs::-webkit-scrollbar { display: none; }
  .board-tabs button {
    position: relative; flex: 0 0 auto; padding: 10px 16px; white-space: nowrap;
    border: 0; background: none; color: var(--muted);
    font: 600 15px Inter, sans-serif; cursor: pointer; transition: color .22s ease;
  }
  .board-tabs button:hover { color: var(--text-2); }
  .board-tabs button.on { color: var(--text); }
  .board-tabs button i {
    position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px;
    background: var(--gold-fill); transform: scaleX(0); opacity: 0;
    transition: transform .28s cubic-bezier(.2, .8, .3, 1), opacity .22s ease;
  }
  .board-tabs button.on i { transform: scaleX(1); opacity: 1; }
  .filter-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
  /* Заголовок раздела: название, счётчик и фильтры в одной строке. */
  .board-h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 26px 0 10px; }
  .board-h h3 { margin: 0; font-family: var(--serif); font-size: 19px; font-weight: 700; letter-spacing: -.01em; }
  .board-h .cnt { font-size: 12.5px; color: var(--muted); }
  .board-h .spacer { flex: 1; }

  /* Очередь вмешательств — строками, а не карточками. Пятнадцать полных
     карточек в столбик не окинуть взглядом, а решение здесь принимается по
     трём словам: кто, что сделать, сколько ждёт. Разбор целиком открывается
     по кнопке — той же карточкой, что и поверх переписки. */
  /* Каждый диалог — своя карточка с воздухом вокруг. Сплошным полотном с
     волосяными разделителями список читался как таблица: глаз не находил,
     где кончается один клиент и начинается следующий. */
  .reviews { display: flex; flex-direction: column; gap: 10px; }
  .rrow {
    border-radius: 14px; overflow: hidden; border: 1px solid var(--border);
    background: var(--panel); animation: rowIn .3s cubic-bezier(.2, .8, .3, 1) both;
  }
  .rrow .line {
    /* Колонка действий закреплена по ширине самой длинной пары кнопок
       («Свернуть» + «Открыть чат»): иначе срок ожидания в соседних строках
       стоял бы на разном расстоянии от края. */
    display: grid; grid-template-columns: 4px 232px minmax(0, 1fr) 132px 180px;
    align-items: center; gap: 14px; padding: 0 16px 0 0; min-height: 56px;
  }
  .rrow .sev { align-self: stretch; background: var(--border-2); }
  .rrow.sev1 .sev { background: var(--warn); }
  .rrow.sev2 .sev { background: var(--danger); }
  /* Кто — слева одним блоком: имя с каналом и под ним лид с датой. Справа
     остаётся только срок ожидания — ради него в строку и смотрят. */
  .rrow .who { grid-column: 2; display: flex; flex-direction: column; justify-content: center; gap: 2px; padding-left: 2px; min-width: 0; }
  .rrow .who .top { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .rrow .who .nm {
    font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .rrow .who .sub {
    font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .rrow .mid { grid-column: 3; min-width: 0; display: flex; flex-direction: column; gap: 2px; padding: 9px 0; }
  /* Разбор открыт — суть и жалоба уже стоят в карточке ниже: строка
     повторяла бы их слово в слово. Колонки поэтому закреплены номерами:
     иначе срок и кнопки съезжают в освободившееся место. */
  .rrow.open .mid { display: none; }
  /* Суть — до двух строк: обрыв в середине первой читался как недописанная
     мысль, а три строки растягивают список так, что за экран влезает пять
     диалогов вместо десяти. */
  .rrow .todo {
    font-size: 13.5px; color: var(--text); line-height: 1.4;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  /* Зачем сюда смотреть — под сутью, со своим заголовком: цветная полоса
     слева говорит то же самое, но её надо расшифровывать по памяти. */
  .rrow .why { margin-top: 4px; }
  .rrow .why .cap {
    font-size: 10px; font-weight: 600; letter-spacing: .08em;
    text-transform: uppercase; color: var(--faint);
  }
  .rrow .why .txt {
    margin-top: 1px; font-size: 12.5px; font-weight: 500; color: var(--muted-2); line-height: 1.4;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .rrow .why.bad .txt { color: var(--danger); }
  .rrow .why.warn .txt { color: var(--warn); }
  .rrow .when { grid-column: 4; display: flex; flex-direction: column; gap: 3px; }
  .rrow .when .w { font-size: 12.5px; font-weight: 600; color: var(--muted); }
  .rrow .when .w.bad { color: var(--danger); }
  .rrow .when .w.warn { color: var(--warn); }
  .rrow .when .w.good { color: var(--ok); }
  .rrow .when .sub { font-size: 11.5px; color: var(--muted); }
  .rrow .acts { grid-column: 5; display: flex; gap: 6px; justify-content: flex-end; }
  .rrow .acts button {
    height: 28px; padding: 0 10px; border-radius: 8px; border: 1px solid var(--border-2);
    background: var(--panel-2); color: var(--text-2);
    font: 500 12px 'Golos Text', Inter, sans-serif; cursor: pointer; white-space: nowrap;
    transition: border-color .2s ease, background .2s ease, color .2s ease;
  }
  .rrow .acts button:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--text); }
  .rrow .acts button.gold {
    border-color: hsl(var(--gold-hsl) / .45); background: var(--gold-wash); color: var(--gold-soft); font-weight: 600;
  }
  .rrow .acts button.gold:hover { background: var(--gold-wash-2); }
  .rrow .acts button:disabled { opacity: .5; cursor: default; }
  /* Крестик скрытия — слева от имени и тише всего остального: это уборка,
     а не действие по клиенту. Площадь побольше, чем сам знак: в него
     попадают пальцем. */
  .rrow .row-hide {
    flex: none; width: 22px; height: 22px; padding: 0; border-radius: 7px;
    border: 1px solid transparent; background: none; color: var(--faint);
    font-size: 12px; line-height: 1; cursor: pointer;
    transition: color .2s ease, border-color .2s ease, background .2s ease;
  }
  .rrow .row-hide:hover { border-color: var(--border-2); background: var(--panel-2); color: var(--danger); }
  .rrow .body { padding: 0 16px 16px 18px; }
  /* Пусто — такая же карточка, как строки списка. */
  .reviews .empty-board {
    border-radius: 14px; border: 1px solid var(--border); background: var(--panel);
  }
  .review { padding: 14px 16px 15px; background: var(--panel); }
  .pager { display: flex; align-items: center; gap: 12px; margin-top: 16px; }
  .pager .range { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
  /* Слова клиента — крупно и дословно. Это единственное место в окне, где
     говорит не сервис и не модель, а сам человек, поэтому шрифт крупный. */
  .quotes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 20px; }
  .vq {
    display: flex; flex-direction: column; gap: 14px; padding: 20px; border-radius: 16px;
    border: 1px solid var(--border); background: var(--panel-2);
    animation: rowIn .3s cubic-bezier(.2, .8, .3, 1) both;
  }
  .vq.bad { border-color: hsl(var(--danger-line-hsl) / .3); }
  .vq.good { border-color: hsl(var(--ok-line-hsl) / .28); }
  .vq .said {
    font-family: var(--serif); font-size: 20px; font-weight: 600; line-height: 1.35;
    letter-spacing: -.01em; text-wrap: pretty;
  }
  .vq .by { margin-top: auto; display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
  .vq .by i { flex: none; width: 6px; height: 6px; transform: rotate(45deg); }
  .vq.bad .by i { background: var(--danger); }
  .vq.good .by i { background: var(--ok); }
  .vq a { font-size: 12.5px; }
  .voices { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .voice-card { padding: 15px 17px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow); }
  .voice-card h4 { margin: 0 0 11px; font-size: 13.5px; }
  .voice-card.bad h4 { color: var(--danger); }
  .voice-card.good h4 { color: var(--ok); }
  .voice-card ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
  .voice-card li {
    display: flex; gap: 9px; align-items: flex-start; font-size: 13.5px; line-height: 1.5;
    animation: rowIn .3s cubic-bezier(.2, .8, .3, 1) both;
  }
  .voice-card li::before {
    content: ''; flex: none; margin-top: 7px; width: 5px; height: 5px; transform: rotate(45deg);
  }
  .voice-card.bad li::before { background: var(--danger); }
  .voice-card.good li::before { background: var(--ok); }
  .voice-card a { font-size: 12px; color: var(--muted); margin-left: 6px; }
  .voice-card .none { font-size: 13px; color: var(--muted); }
  .voices-count { font-size: 12.5px; color: var(--muted); }
  .cards-hint { font-size: 12.5px; color: var(--muted); }
  .empty-board { padding: 34px; text-align: center; color: var(--muted); line-height: 1.6; }
  .skel {
    display: block; border-radius: 6px;
    background: linear-gradient(90deg, var(--panel-3) 25%, var(--skeleton-shine) 50%, var(--panel-3) 75%);
    background-size: 200% 100%; animation: shimmer 1.4s infinite;
  }

  /* ---------- подсказки «!» ---------- */
  .help {
    position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
    width: 18px; height: 18px; margin-left: 6px; border-radius: 50%; background: var(--gold-fill);
    color: var(--on-accent); font-size: 11.5px; font-weight: 700; cursor: help; vertical-align: 2px;
  }
  .help-box {
    display: none; position: absolute; top: 26px; left: -10px; z-index: 30; width: min(440px, 74vw);
    padding: 13px 15px; border-radius: 11px; border: 1px solid var(--border-2); background: var(--panel-2);
    box-shadow: var(--shadow-lg); font: 400 12.5px/1.55 Inter, sans-serif; color: var(--text-2);
    text-align: left; cursor: auto; animation: rowIn .2s cubic-bezier(.2, .8, .3, 1);
  }
  .help:hover .help-box, .help:focus .help-box, .help:focus-within .help-box,
  .ball.mood:hover .help-box, .ball.mood:focus .help-box { display: block; }
  .help-box b { display: block; margin-top: 9px; color: var(--text); }
  .help-box b:first-child { margin-top: 0; }
  .help-box .quote { display: block; margin: 2px 0 8px; }

  /* ---------- настройки ---------- */
  .set-title { margin: 26px 0 12px; font-family: var(--serif); font-size: 20px; font-weight: 600; }
  .set-title:first-child { margin-top: 0; }
  /* Установка приложения из магазина amoCRM: заметный, но не кричащий блок. */
  .crm-store {
    margin-top: 14px; padding: 14px 16px; border-radius: 12px;
    background: var(--gold-wash); border: 1px solid hsl(var(--gold-hsl) / .35);
  }
  .crm-store .nm { font-weight: 600; font-size: 14px; }
  .crm-store .cap { margin-top: 5px; font-size: 12.5px; line-height: 1.45; color: var(--text-2); }
  .crm-store .go {
    display: inline-block; margin-top: 11px; padding: 9px 16px; border-radius: 9px;
    background: var(--gold-fill); color: var(--on-accent);
    font-size: 13px; font-weight: 600; text-decoration: none;
  }
  .set-card { padding: 17px 18px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow); }
  .set-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 14px; }

  /* Поля живут не только в настройках: те же подписи и рамки нужны карточкам
     админки и кабинета, иначе там торчат серые поля браузера. */
  .set-card label, .acct .more label, .grant label, .pay .card label {
    display: block; font-size: 12.5px; color: var(--muted); line-height: 1.4;
  }
  .set-card label.full { margin-bottom: 14px; }
  .set-card label.full:last-child { margin-bottom: 0; }
  /* Поля в ряду стоят на одной линии, даже когда подписи разной длины:
     «Пароль №2 — проверка оплаты» переносился на вторую строку и утаскивал
     своё поле вниз, а соседние оставались на месте. Правило идёт после
     общего display:block выше — иначе оно его не перебьёт. */
  .set-grid > label { display: flex; flex-direction: column; }
  /* Отступ снизу в сетке лишний — строки разводит gap, — и он же всё портил:
     последнему полю в ряду отступа не доставалось, из-за чего у него было на
     14 px больше высоты, и прижатое к низу поле уезжало ниже соседей. */
  .set-grid > label.full { margin-bottom: 0; }
  .set-grid > label > input, .set-grid > label > select, .set-grid > label > textarea {
    margin-top: auto;
  }
  /* Строка под полями: кнопка и подпись рядом, а не одна над другой. */
  .set-row { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
  .set-hint { font-size: 12.5px; color: var(--muted); }
  /* Выпадающие списки. Системный select рисуется браузером и в тёмной теме
     выглядел светлой заплаткой посреди окна. Рисуем сам список сами, вместе
     со стрелкой: из-за неё appearance приходится гасить целиком.
     Раскрытый перечень всё равно рисует система — ему помогает color-scheme
     на корне и цвет пунктов ниже. */
  select {
    appearance: none; -webkit-appearance: none;
    height: 36px; padding: 0 32px 0 12px; border-radius: 10px;
    border: 1px solid var(--border); background-color: var(--panel-3); color: var(--text);
    font: inherit; font-size: 13.5px; line-height: 1.2; cursor: pointer; outline: none;
    background-image: var(--chevron);
    background-repeat: no-repeat;
    background-position: right 11px center;
    background-size: 11px 7px;
    transition: border-color .2s ease, background-color .2s ease;
  }
  select:hover { border-color: var(--border-2); }
  select:focus-visible {
    border-color: hsl(var(--gold-hsl) / .55);
    box-shadow: 0 0 0 3px hsl(var(--gold-hsl) / .16);
  }
  select:disabled { opacity: .55; cursor: default; }
  select option { background: var(--panel-2); color: var(--text); }

  .set-hint.warn { color: var(--warn); }
  .set-card input[type=text], .set-card input[type=password], .set-card input[type=number],
  .set-card textarea,
  .acct .more input, .grant input,
  .plan-card input {
    display: block; width: 100%; margin-top: 7px; padding: 9px 12px; border-radius: 9px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font-size: 13.5px; font-family: inherit; outline: none; transition: border-color .2s ease;
  }
  .set-card input:focus, .set-card textarea:focus,
  .acct .more input:focus { border-color: hsl(var(--gold-hsl) / .45); }
  /* Там, где список стоит под подписью, он тянется на всю ширину поля. */
  .set-card select, .acct .more select, .grant select, .plan-card select {
    display: block; width: 100%; margin-top: 7px; height: 38px;
  }
  .set-card input.ident, .set-card textarea.ident { font-family: var(--num); }
  .set-card textarea { resize: vertical; line-height: 1.55; }
  /* Подписи в блоке разной длины: одна встаёт в строку, другая в две — и поля
     одного ряда оказывались на разной высоте. Ячейка сетки и так тянется на
     высоту ряда: раскладываем её сверху вниз и разводим по краям — подпись
     остаётся наверху, поле опускается к низу, и поля ряда стоят на одной
     линии. */
  .set-grid > label { display: flex; flex-direction: column; justify-content: space-between; }
  .switch { display: flex; align-items: center; gap: 11px; margin-bottom: 15px; font-size: 14.5px; color: var(--text); cursor: pointer; }
  .switch input { position: absolute; opacity: 0; width: 0; height: 0; }
  /* Размеры сходятся ровно: при border-box дорожке 38x22 с рамкой в пиксель
     и отступом в два остаётся 32x16 внутри — кружок ровно этой высоты и
     проезжает ровно 16 пикселей до правого края. Раньше кружок был 17 при
     внутренней высоте 15 и торчал из дорожки сверху и снизу. */
  .track {
    flex: none; display: inline-flex; align-items: center; width: 38px; height: 22px;
    padding: 2px; border-radius: 999px;
    border: 1px solid var(--border-2); background: var(--panel-4);
    transition: background .22s ease, border-color .22s ease;
  }
  .thumb {
    flex: none; width: 16px; height: 16px; border-radius: 50%; background: var(--faint);
    transition: transform .26s cubic-bezier(.2, .8, .3, 1), background .22s ease;
  }
  .switch input:checked + .track { border-color: hsl(var(--gold-hsl) / .5); background: hsl(var(--gold-hsl) / .35); }
  .switch input:checked + .track .thumb { background: var(--gold-soft); transform: translateX(16px); }
  /* Пояснение рядом с переключателем: что именно случится, когда его
     включат. Тем же размером, но приглушённое — это не второе название. */
  .switch .sub { color: var(--muted); font-weight: 400; }
  .switch input:focus-visible + .track { border-color: hsl(var(--gold-hsl) / .7); box-shadow: 0 0 0 3px hsl(var(--gold-hsl) / .18); }
  .ico-tpl {
    display: block; box-sizing: border-box; width: 15px; height: 15px;
    border: 1.6px solid currentColor; border-radius: 3px; border-top-width: 5px;
  }
  .tpl-pop {
    position: absolute; left: 16px; right: 16px; bottom: 62px; z-index: 35; max-height: 320px;
    overflow-y: auto; padding: 7px; border-radius: 12px; border: 1px solid var(--border-2);
    background: var(--panel-2); box-shadow: var(--shadow-lg);
    animation: dlgIn .22s cubic-bezier(.2, .8, .3, 1);
  }
  .tpl-pop[hidden] { display: none; }
  /* Попап смайлов устроен как попап шаблонов: то же место над строкой ввода,
     та же подложка. Сетка фиксированной высоты — иначе «Улыбки» и «Жесты»
     прыгали бы по высоте при переключении. */
  .emo-pop {
    position: absolute; left: 16px; right: 16px; bottom: 62px; z-index: 35;
    padding: 9px; border-radius: 12px; border: 1px solid var(--border-2);
    background: var(--panel-2); box-shadow: var(--shadow-lg);
    animation: dlgIn .22s cubic-bezier(.2, .8, .3, 1);
  }
  .emo-pop[hidden] { display: none; }
  .emo-find input {
    width: 100%; height: 34px; padding: 0 11px; border-radius: 9px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font-size: 13px; font-family: inherit; outline: none;
  }
  .emo-find input:focus { border-color: hsl(var(--gold-hsl) / .45); }
  .emo-tabs { display: flex; flex-wrap: wrap; gap: 5px; margin: 8px 0; }
  .emo-tabs button {
    padding: 4px 10px; border-radius: 999px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--muted); font: 500 12px Inter, sans-serif;
    cursor: pointer; transition: all .18s ease;
  }
  .emo-tabs button.on {
    border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint);
    color: var(--gold-soft); font-weight: 600;
  }
  .emo-body { height: 196px; overflow-y: auto; }
  .emo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(38px, 1fr)); gap: 2px; }
  .emo-grid .emo {
    height: 38px; padding: 0; border: 0; border-radius: 9px; background: none;
    font-size: 21px; line-height: 1; cursor: pointer; transition: background .15s ease;
  }
  .emo-grid .emo:hover { background: var(--panel-4); }
  .emo-none { padding: 24px 8px; text-align: center; font-size: 12.5px; color: var(--muted); }
  /* Строка = вставить + править + удалить. Кнопки действий рядом, а не по
     наведению: на телефоне наведения нет, а править надо и с него. */
  .tpl-pop .item { display: flex; align-items: center; gap: 2px; border-radius: 9px; }
  .tpl-pop .item:hover { background: var(--panel-4); }
  .tpl-pop .pick {
    flex: 1; min-width: 0; display: block; padding: 8px 10px; border: 0; border-radius: 9px;
    background: none; color: var(--text-2); text-align: left; cursor: pointer;
  }
  .tpl-pop .act {
    flex: none; width: 28px; height: 28px; margin-right: 4px; padding: 0; border: 0;
    border-radius: 8px; background: none; color: var(--muted); font-size: 13px;
    cursor: pointer; transition: background .15s ease, color .15s ease;
  }
  .tpl-pop .act:hover { background: var(--panel-2); color: var(--text); }
  .tpl-pop .act.del { font-size: 15px; }
  .tpl-pop .act.del:hover { color: var(--danger); }
  .tpl-pop .act:disabled { opacity: .3; cursor: default; }
  /* Карандаш рисуем сами: в подмножествах шрифта есть только латиница,
     кириллица и стрелки, а ✎ на чужой машине станет пустым квадратом. */
  .ico-edit { display: block; position: relative; width: 13px; height: 13px; margin: 0 auto; }
  .ico-edit::before {
    content: ''; position: absolute; left: 0; top: 4.5px; width: 11px; height: 4px;
    box-sizing: border-box; border: 1.4px solid currentColor; border-radius: 1px;
    border-right-width: 2.6px; transform: rotate(-45deg);
  }
  .tpl-pop .name { font-size: 13px; font-weight: 600; color: var(--text); }
  .tpl-pop .tag {
    margin-left: 6px; padding: 1px 6px; border-radius: 20px; font-size: 10.5px;
    font-weight: 500; color: var(--muted); background: var(--panel-4); vertical-align: 1px;
  }
  .tpl-pop .text {
    margin-top: 2px; font-size: 12px; color: var(--muted); overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap;
  }
  .tpl-pop .none { padding: 10px 10px 4px; font-size: 12.5px; color: var(--muted); }
  .tpl-pop .add {
    display: block; width: 100%; margin-top: 4px; padding: 9px 10px; border: 0;
    border-top: 1px solid var(--border); border-radius: 0 0 9px 9px; background: none;
    color: var(--gold-soft); font-size: 12.5px; text-align: left; cursor: pointer;
  }
  .tpl-pop .add:hover { background: var(--panel-4); }
  .tpl-pop .form { padding: 8px; display: flex; flex-direction: column; gap: 7px; }
  .tpl-pop .form input, .tpl-pop .form textarea {
    width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 9px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font: inherit; font-size: 13px; outline: none; resize: vertical;
  }
  .tpl-pop .form input:focus, .tpl-pop .form textarea:focus {
    border-color: hsl(var(--gold-hsl) / .55);
  }
  .tpl-pop .form .row { display: flex; gap: 7px; }
  .tpl-pop .form .row button {
    flex: 1; padding: 8px; border-radius: 9px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text-2); font-size: 12.5px; cursor: pointer;
  }
  .tpl-pop .form .row button.ok {
    border-color: hsl(var(--gold-hsl) / .5); background: hsl(var(--gold-hsl) / .12); color: var(--gold-soft);
  }
  .tpl-pop .form .row button:hover { background: var(--panel-4); }


  .set-run { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
  .set-run .run-status { font-size: 12.5px; color: var(--muted); }
  .set-run .run-status.ok { color: var(--ok); }
  .set-run .run-status.bad { color: var(--danger); }
  .set-note { margin-top: 15px; padding-top: 15px; border-top: 1px solid var(--line); font-size: 12.5px; line-height: 1.55; color: var(--muted); }
  /* Черта отделяет пояснение от полей выше. Если пояснение в карточке одно,
     отделять нечего — черта висит над пустотой. */
  .set-note:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
  .set-note div + div { margin-top: 7px; }
  /* Кто чем занят: работа, модель, пояснение — тремя столбцами, чтобы взгляд
     шёл по одной колонке, а не разбирал каждую строку заново. */
  .set-models { display: flex; flex-direction: column; gap: 9px; margin-bottom: 12px; }
  .set-models > div {
    display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 3px 14px;
    align-items: baseline;
  }
  .set-models b { font-size: 13px; font-weight: 600; color: var(--text-2); }
  .set-models .ident { font-family: var(--num); font-size: 13px; color: var(--text); overflow-wrap: anywhere; }
  .set-models .ident.off { color: var(--muted); }
  .set-models i { grid-column: 2; font-style: normal; font-size: 12px; color: var(--muted); }
  /* Подключения: у каждого своё состояние, адрес и объяснение — без этого
     список читался как набор технических слов без смысла. */
  .set-conns { display: flex; flex-direction: column; gap: 1px; border-radius: 12px; overflow: hidden; background: var(--line); }
  .set-conns .conn { padding: 11px 14px; background: var(--panel-3); }
  .set-conns .head { display: flex; align-items: center; gap: 9px; }
  .set-conns .head b { font-size: 13.5px; font-weight: 600; }
  .set-conns .pill {
    padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
    border: 1px solid var(--border-2); background: var(--panel-4); color: var(--muted);
  }
  .set-conns .conn.on .pill {
    border-color: hsl(var(--ok-line-hsl) / .4); background: hsl(var(--ok-line-hsl) / .16); color: var(--ok);
  }
  .set-conns .val { margin-top: 3px; font-family: var(--num); font-size: 12.5px; color: var(--text-2); overflow-wrap: anywhere; }
  .set-conns .note { margin-top: 3px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
  .kb { margin-top: 16px; padding-top: 15px; border-top: 1px solid var(--line); }
  /* Документы — плитками: список из шестнадцати строк читается как свалка,
     а по значку типа файла человек находит нужный, не вчитываясь в название. */
  .kb-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 8px; }
  .kb-list:not(:empty) { margin-bottom: 10px; }
  /* Обёртка секции: полка наших материалов, подпись и сетка плиток идут
     друг под другом, а не колонками. */
  .kb-files { display: block; }
  .kb-row {
    position: relative; display: flex; align-items: flex-start; gap: 10px; padding: 10px 11px;
    border-radius: 12px; border: 1px solid var(--border); background: var(--panel-3);
    transition: border-color .18s ease, transform .18s ease;
  }
  .kb-row:hover { border-color: var(--border-2); transform: translateY(-1px); }
  .kb-row.bad { border-color: hsl(var(--danger-line-hsl) / .45); }
  .kb-row .doc { flex: none; width: 30px; height: 36px; }
  .kb-row .who { flex: 1; min-width: 0; }
  .kb-row .name {
    font-size: 12.5px; font-weight: 600; line-height: 1.3;
    /* Заголовок в две строки: третья строка ломает высоту всей полки плиток. */
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .kb-row .meta { margin-top: 3px; font-size: 11.5px; color: var(--muted); }
  .kb-row .meta.bad { color: var(--danger); }
  .kb-row .drop {
    position: absolute; top: 5px; right: 5px; width: 24px; height: 24px; padding: 0;
    border: 0; border-radius: 7px; background: none; color: var(--faint); font-size: 14px;
    cursor: pointer; opacity: 0; transition: opacity .15s ease, background .15s ease, color .15s ease;
  }
  .kb-row:hover .drop, .kb-row .drop:focus-visible { opacity: 1; }
  .kb-row .drop:hover { background: var(--panel-2); color: var(--danger); }

  /* Наши материалы — отдельной полкой над своими: человек должен сразу
     понимать, что это не он загружал, и что убрать их можно одной кнопкой. */
  .kb-ours-box {
    margin-bottom: 12px; padding: 13px 14px 14px; border-radius: 14px;
    border: 1px solid hsl(var(--gold-hsl) / .32); background: var(--gold-tint);
  }
  .kb-ours-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
  .kb-ours-head h4 { margin: 0; font-size: 13.5px; font-weight: 700; }
  .kb-ours-head .cnt { font-size: 12px; color: var(--muted); }
  .kb-ours-head .spacer { flex: 1; }
  .kb-ours-box .txt {
    margin: 5px 0 11px; font-size: 12.5px; line-height: 1.5; color: var(--text-2); max-width: 74ch;
  }
  .kb-ours-box .kb-list { margin-bottom: 0; }
  .kb-ours-box .kb-row { background: var(--panel); border-color: hsl(var(--gold-hsl) / .22); }
  /* Пусто — рассказываем, что можно вернуть, и не рисуем пустую полку. */
  .kb-ours-row {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    margin-bottom: 12px; padding: 11px 12px; border-radius: 12px;
    border: 1px dashed var(--border-2); background: var(--panel-3);
  }
  .kb-ours-row .txt { flex: 1; min-width: 220px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
  .kb-mine { margin: 4px 0 8px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
  /* Плашка «наш» и «сам»: её носят и наши документы, и самошлющие правила. */
  .kb-ours {
    margin-left: 7px; padding: 1px 6px; border-radius: 999px;
    border: 1px solid var(--border-2); background: var(--panel-3);
    color: var(--muted); font-size: 10.5px; font-weight: 600; vertical-align: 1px;
  }
  .kb-add { display: inline-flex; }
  .kb-add input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
  .kb-add span {
    display: inline-block; padding: 8px 13px; border-radius: 9px;
    border: 1px dashed var(--border-2); color: var(--gold-soft); font-size: 12.5px;
    cursor: pointer; transition: border-color .18s ease, background .18s ease;
  }
  .kb-add span:hover { border-color: hsl(var(--gold-hsl) / .5); background: var(--panel-4); }
  .kb-add input:focus-visible + span { outline: 2px solid var(--gold); outline-offset: 2px; }
  .set-actions { display: flex; align-items: center; gap: 14px; margin: 24px 0 40px; }
  /* display у класса сильнее браузерного [hidden] — иначе скрытая кнопка
     «Сохранить» продолжает висеть внизу вкладки, где ей делать нечего. */
  .set-actions[hidden] { display: none; }
  .set-actions button {
    padding: 11px 24px; border-radius: 10px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 14px Inter, sans-serif; cursor: pointer; transition: filter .2s ease, transform .2s ease;
  }
  .set-actions button:hover { filter: brightness(1.06); }
  .set-actions button:disabled { filter: grayscale(.5); cursor: default; }
  .set-status { font-size: 13.5px; color: var(--muted); }
  .set-status.ok { color: var(--gold-soft); }
  .set-status.bad { color: var(--danger); }

  /* ---------- кабинет и админка ---------- */
  /* Подпись и значение — две колонки: во flex длинная подпись сдвигала
     значение, и столбец цифр шёл лесенкой. */
  .cab-row {
    display: grid; grid-template-columns: minmax(120px, 168px) minmax(0, 1fr);
    gap: 6px 14px; align-items: baseline; font-size: 13.5px;
  }
  .cab-row + .cab-row { margin-top: 9px; }
  .cab-row b {
    font-size: 11px; font-weight: 500; letter-spacing: .04em; line-height: 1.35;
    text-transform: uppercase; color: var(--muted);
  }
  .cab-row > span { min-width: 0; overflow-wrap: anywhere; }
  @media (max-width: 560px) {
    .cab-row { grid-template-columns: 1fr; gap: 2px; }
  }
  /* Счета: пять колонок с общей сеткой у шапки и строк — иначе суммы, метки
     и даты идут лесенкой, у каждой строки своя. */
  .pay-rows { display: flex; flex-direction: column; }
  .pay-row {
    display: grid;
    grid-template-columns: 108px minmax(0, 1fr) 110px 150px 132px;
    gap: 4px 16px; align-items: center; padding: 11px 0; font-size: 13.5px;
  }
  .pay-row + .pay-row { border-top: 1px solid var(--line); }
  .pay-row.head {
    padding: 0 0 9px; border-bottom: 1px solid var(--line);
    font-size: 11px; font-weight: 500; letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted);
  }
  .pay-row.head + .pay-row { border-top: 0; }
  .pay-row .no { font-variant-numeric: tabular-nums; color: var(--muted); }
  .pay-row .what { min-width: 0; overflow-wrap: anywhere; }
  .pay-row .sum { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
  .pay-row .when { color: var(--muted); font-variant-numeric: tabular-nums; }
  .pay-row .badge-st { justify-self: start; }
  @media (max-width: 720px) {
    .pay-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; padding: 12px 0; }
    .pay-row.head { display: none; }
    .pay-row .no { grid-column: 1; }
    .pay-row .sum { grid-column: 2; grid-row: 1; }
    .pay-row .what { grid-column: 1 / -1; }
    .pay-row .badge-st { grid-column: 1; }
    .pay-row .when { grid-column: 2; text-align: right; }
  }
  /* Строка подписки: между плитками состояния и списком тарифов. Не карточка
     и не предупреждение — просто факт про деньги и кнопка рядом с ним. */
  .sub-bar {
    display: flex; align-items: flex-start; gap: 12px 14px; flex-wrap: wrap;
    margin: 14px 0 0; padding: 13px 16px; border-radius: 12px;
    border: 1px solid hsl(var(--ok-line-hsl) / .4); background: hsl(var(--ok-line-hsl) / .09);
    font-size: 13.5px; color: var(--text-2);
  }
  .sub-bar.off { border-color: hsl(var(--warn-line-hsl) / .45); background: hsl(var(--warn-line-hsl) / .1); }
  .sub-bar[hidden] { display: none; }
  .sub-bar .ico { flex: none; font-size: 15px; line-height: 1.5; color: var(--ok); }
  .sub-bar.off .ico { color: var(--warn); }
  .sub-bar .say { flex: 1; min-width: 220px; line-height: 1.5; }
  .sub-bar .say b { color: var(--text); }
  .sub-bar .note { margin-top: 3px; font-size: 12.5px; color: var(--muted); }
  .sub-bar button { flex: none; align-self: center; }
  .cab-plan { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
  .cab-plan .name { font-family: var(--serif); font-size: 21px; font-weight: 700; letter-spacing: -.01em; }
  .cab-plan .until { font-size: 13px; color: var(--muted); }
  .cab-plan .pill {
    padding: 2px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
    border: 1px solid hsl(var(--ok-line-hsl) / .4); background: hsl(var(--ok-line-hsl) / .16); color: var(--ok);
  }
  .cab-plan .pill.off {
    border-color: hsl(var(--danger-line-hsl) / .4); background: hsl(var(--danger-line-hsl) / .14); color: var(--danger);
  }
  /* Что открыто и что нет — одним взглядом, без чтения таблицы тарифов. */
  .feat { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 13px; }
  .feat span {
    padding: 2px 10px; border-radius: 999px; font-size: 12px;
    border: 1px solid var(--border); color: var(--muted);
  }
  .feat span.on { border-color: hsl(var(--ok-line-hsl) / .4); background: hsl(var(--ok-line-hsl) / .12); color: var(--ok); }
  .money { font-family: var(--num); font-variant-numeric: tabular-nums; }
  .ref-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 10px; margin: 14px 0; }
  .ref-grid > div { padding: 12px 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel-3); }
  .ref-grid .v { font-family: var(--num); font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
  .ref-grid .v.gold { color: var(--gold-soft); }
  .ref-grid .l { margin-top: 2px; font-size: 12px; color: var(--muted); }
  .link-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 4px; }
  .link-row input {
    flex: 1; min-width: 240px; height: 34px; padding: 0 10px; border-radius: 9px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font-family: var(--num); font-size: 12.5px; outline: none;
  }
  /* Таблицы админки: их читают глазами по столбцу, поэтому цифры моноширинные. */
  .tbl-wrap { overflow-x: auto; }
  .tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
  .tbl th {
    text-align: left; padding: 7px 10px; white-space: nowrap;
    font-size: 11px; font-weight: 500; letter-spacing: .04em; text-transform: uppercase;
    color: var(--muted); border-bottom: 1px solid var(--line);
  }
  .tbl td { padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
  .tbl tr:last-child td { border-bottom: 0; }
  .tbl .num { font-family: var(--num); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .tbl .muted { color: var(--muted); }
  .tbl .bad { color: var(--danger); }
  .tbl .ok { color: var(--ok); }
  .tbl input {
    height: 30px; padding: 0 8px; border-radius: 8px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text); font-size: 12.5px; outline: none;
  }
  .tbl select { height: 30px; padding: 0 26px 0 8px; border-radius: 8px; font-size: 12.5px; }
  .tbl input { width: 70px; }
  .plan-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
  .plan-card { padding: 16px 18px; border-radius: 14px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow); }
  .plan-card h4 { margin: 0; font-family: var(--serif); font-size: 19px; font-weight: 700; }
  .plan-card .tagline { margin-top: 2px; font-size: 12.5px; color: var(--muted); }
  .plan-card .set-grid { margin-top: 12px; }
  .plan-card .feat span { cursor: pointer; user-select: none; }
  .adm-empty { padding: 22px; text-align: center; color: var(--muted); font-size: 13.5px; }
  .finder { position: relative; }
  .finder-pop {
    position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 40; max-height: 260px;
    overflow-y: auto; padding: 6px; border-radius: 11px; border: 1px solid var(--border-2);
    background: var(--panel-2); box-shadow: var(--shadow-lg);
  }
  .finder-pop[hidden] { display: none; }
  .finder-pop button {
    display: block; width: 100%; padding: 7px 9px; border: 0; border-radius: 8px; background: none;
    text-align: left; cursor: pointer;
  }
  .finder-pop button:hover { background: var(--panel-4); }
  .finder-pop .nm { display: block; font-size: 13px; color: var(--text); }
  .finder-pop .em { display: block; margin-top: 1px; font-size: 11.5px; color: var(--muted); }
  .finder-pop .none { padding: 10px; font-size: 12.5px; color: var(--muted); text-align: center; }

  /* ---------- справка ---------- */
  /* Не .help-box: это имя занято подсказкой «!», а у неё display:none. */
  .help-sheet { width: min(860px, 100%); }
  .help-top { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
  .help-top h2 { margin: 0; font-family: var(--serif); font-size: 24px; font-weight: 700; letter-spacing: -.01em; }
  .help-top p { margin: 4px 0 0; font-size: 13px; color: var(--muted); }
  .help-top .spacer { flex: 1; }
  .help-find { position: relative; }
  .help-find input {
    width: 100%; height: 44px; padding: 0 14px 0 40px; border-radius: 12px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font-size: 14px; font-family: inherit; outline: none; transition: border-color .2s ease;
  }
  .help-find input:focus { border-color: hsl(var(--gold-hsl) / .5); }
  .help-find .lens {
    position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
    color: var(--gold-soft); font-size: 13px; pointer-events: none;
  }
  .help-cats { display: flex; flex-wrap: wrap; gap: 7px; margin: 13px 0 4px; }
  .help-cats button {
    padding: 6px 13px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel-3);
    color: var(--muted); font: 500 12.5px Inter, sans-serif; cursor: pointer; transition: all .18s ease;
  }
  .help-cats button.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); font-weight: 600; }
  .help-art { border-radius: 14px; border: 1px solid var(--border); background: var(--panel); }
  .help-art + .help-art { margin-top: 9px; }
  .help-art > .head {
    display: flex; align-items: center; gap: 11px; padding: 13px 15px; cursor: pointer;
    border-radius: 14px;
  }
  .help-art > .head:hover { background: var(--panel-2); }
  .help-art .num {
    flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 8px;
    background: var(--gold-tint); color: var(--gold-soft); font: 600 12px var(--num);
  }
  .help-art .ttl { flex: 1; min-width: 0; font-size: 14.5px; font-weight: 600; }
  .help-art .cat { flex: none; font-size: 11px; color: var(--faint); }
  .help-art .body { padding: 0 15px 16px 52px; }
  .help-art .body[hidden] { display: none; }
  .help-art .why { margin: 0 0 11px; font-size: 13px; line-height: 1.55; color: var(--muted); }
  .help-art ol { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 9px; }
  .help-art li { font-size: 13.5px; line-height: 1.6; color: var(--text-2); }
  .help-art .note {
    margin-top: 12px; padding: 10px 12px; border-radius: 10px; background: var(--panel-3);
    font-size: 12.5px; line-height: 1.5; color: var(--muted);
  }
  .help-art .go {
    margin-top: 13px; height: 34px; padding: 0 14px; border-radius: 10px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 12.5px Inter, sans-serif; cursor: pointer;
  }
  /* Кнопка из окна прямо в тексте: человек ищет глазами такую же. */
  .ui-chip {
    display: inline-flex; align-items: center; gap: 5px; margin: 0 2px; padding: 2px 9px;
    border-radius: 7px; border: 1px solid var(--border-2); background: var(--panel-2);
    color: var(--text-2); font-size: 12px; font-weight: 500; vertical-align: baseline;
  }
  .ui-chip.gold { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); }
  .ui-chip.key { font-family: var(--num); font-size: 11.5px; }
  .help-keys { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 8px 16px; }
  .help-keys div { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--text-2); }
  .help-none { padding: 26px; text-align: center; color: var(--muted); font-size: 13.5px; }

  .welcome { width: min(520px, 100%); text-align: center; padding: 30px 30px 26px; }
  .welcome .ico { font-size: 26px; color: var(--gold-soft); }
  .welcome h2 { margin: 10px 0 0; font-family: var(--serif); font-size: 26px; font-weight: 700; }
  .welcome p { margin: 10px 0 0; font-size: 14px; line-height: 1.6; color: var(--muted); }
  .welcome-list { margin: 18px 0 0; padding: 0; list-style: none; text-align: left; display: flex; flex-direction: column; gap: 9px; }
  .welcome-list li {
    position: relative; padding-left: 24px; font-size: 13.5px; line-height: 1.5; color: var(--text-2);
  }
  .welcome-list li::before {
    content: '✓'; position: absolute; left: 0; top: 0; color: var(--ok); font-size: 12px;
  }
  .welcome-run { display: flex; gap: 10px; justify-content: center; margin-top: 22px; }
  .welcome-run .go {
    height: 40px; padding: 0 20px; border: 0; border-radius: 11px;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 700 13.5px Inter, sans-serif; cursor: pointer;
  }
  .welcome-run .ghost { height: 40px; }

  /* ---------- замок тарифа ---------- */
  /* Вкладку видно всегда — иначе непонятно, за что платить, — но содержимое
     под замком: размытое, некликабельное и с одной понятной кнопкой. */
  .locked { position: relative; }
  .locked > *:not(.lock) { filter: blur(6px); pointer-events: none; user-select: none; }
  .lock {
    position: absolute; inset: 0; z-index: 30; display: grid; place-items: center;
    padding: 24px; background: var(--overlay-soft);
  }
  .lock-card {
    max-width: 420px; padding: 26px 28px; border-radius: 18px; border: 1px solid var(--border-2);
    background: var(--panel); box-shadow: var(--shadow-lg); text-align: center;
  }
  .lock-card .ico { font-size: 26px; }
  .lock-card h3 { margin: 10px 0 0; font-family: var(--serif); font-size: 21px; font-weight: 700; }
  .lock-card p { margin: 8px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
  .lock-card p.why { font-size: 12.5px; }
  .lock-card .go {
    margin-top: 16px; height: 40px; padding: 0 20px; border: 0; border-radius: 11px;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 700 13.5px Inter, sans-serif; cursor: pointer;
  }
  .lock-card .go:hover { filter: brightness(1.06); }

  /* ---------- аватар и меню кабинета ---------- */
  /* Кабинет — личное, а не рабочая вкладка: он живёт под аватаром справа,
     как в любом сервисе, и не отнимает место у переписки. */
  .me { position: relative; flex: none; }
  .avatar {
    display: grid; place-items: center; width: 34px; height: 34px; padding: 0;
    border-radius: 50%; border: 1px solid hsl(var(--gold-hsl) / .38);
    background: linear-gradient(150deg, var(--gold-tint), var(--panel-3));
    color: var(--gold-soft); font: 600 12.5px Inter, sans-serif; letter-spacing: .02em;
    cursor: pointer; transition: border-color .2s ease, transform .2s ease;
  }
  .avatar:hover { border-color: hsl(var(--gold-hsl) / .7); transform: translateY(-1px); }
  .avatar.lg { width: 44px; height: 44px; font-size: 15px; }
  .avatar { overflow: hidden; padding: 0; }
  .avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .me-pop {
    position: absolute; right: 0; top: 42px; z-index: 60; width: 246px; padding: 8px;
    border-radius: 14px; border: 1px solid var(--border-2); background: var(--panel-2);
    box-shadow: var(--shadow-lg); animation: dlgIn .18s cubic-bezier(.2, .8, .3, 1);
  }
  .me-pop[hidden] { display: none; }
  .me-pop .who { display: flex; gap: 11px; align-items: center; padding: 8px 9px 12px; }
  .me-pop .who .nm { font-size: 13.5px; font-weight: 600; color: var(--text); }
  .me-pop .who .em { margin-top: 2px; font-size: 11.5px; color: var(--muted); word-break: break-all; }
  .me-pop .who .rl { margin-top: 5px; display: inline-block; padding: 2px 8px; border-radius: 999px;
    border: 1px solid var(--border-2); font-size: 10.5px; color: var(--muted); }
  .me-pop hr { margin: 0 0 6px; border: 0; border-top: 1px solid var(--line); }
  .me-pop button {
    display: block; width: 100%; padding: 9px 10px; border: 0; border-radius: 9px;
    background: none; color: var(--text-2); font: 500 13px Inter, sans-serif;
    text-align: left; cursor: pointer; transition: background .15s ease, color .15s ease;
  }
  .me-pop button:hover { background: var(--panel-4); color: var(--text); }
  .me-pop button.out { color: var(--muted); }
  #me-theme, #me-bell { display: none; }


  /* ---------- кабинет клиента ---------- */
  .cab-head {
    display: flex; align-items: center; gap: 14px; padding: 16px 18px; margin-bottom: 4px;
    border-radius: 14px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow);
  }
  .cab-head .nm { font-family: var(--serif); font-size: 21px; font-weight: 700; letter-spacing: -.01em; }
  .cab-head .sub { margin-top: 3px; font-size: 12.5px; color: var(--muted); }
  .cab-head .spacer { flex: 1; }
  /* Метка состояния. Отдельный класс, а не .pill: тот уже занят кнопками
     периода на дашборде, и общий стиль испортил бы их. */
  .badge-st {
    flex: none; white-space: nowrap;
    display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
    border: 1px solid hsl(var(--ok-line-hsl) / .45); background: hsl(var(--ok-line-hsl) / .14); color: var(--ok);
  }
  .badge-st.off { border-color: hsl(var(--danger-line-hsl) / .4); background: hsl(var(--danger-line-hsl) / .12); color: var(--danger); }
  .badge-st.neutral { border-color: var(--border-2); background: var(--panel-3); color: var(--muted); }
  .badge-st.gold { border-color: hsl(var(--gold-hsl) / .45); background: var(--gold-tint); color: var(--gold-soft); }

  /* Полоса состояния тарифа: главное — что открыто и до какого числа. */
  .prof-head { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
  .prof-head .nm { font-size: 16px; font-weight: 600; }
  .prof-head .em { margin-top: 2px; font-size: 12.5px; color: var(--muted); }
  .prof-head .kb-add { display: inline-block; margin-top: 8px; }
  .avatar.xl { width: 72px; height: 72px; font-size: 24px; }
  .cab-state { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 6px; }
  .cab-state > div { padding: 13px 15px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel-3); }
  .cab-state .v { font-family: var(--num); font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums; }
  .cab-state .v.gold { color: var(--gold-soft); }
  .cab-state .v.bad { color: var(--danger); }
  .cab-state .l { margin-top: 3px; font-size: 12px; color: var(--muted); line-height: 1.35; }

  .tariffs { display: grid; grid-template-columns: repeat(auto-fit, minmax(262px, 1fr)); gap: 12px; align-items: start; }
  .tariff {
    position: relative; display: flex; flex-direction: column; padding: 18px; border-radius: 16px;
    border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow);
    transition: border-color .2s ease, transform .2s ease;
  }
  .tariff:hover { border-color: var(--border-2); transform: translateY(-2px); }
  .tariff.on { border-color: hsl(var(--gold-hsl) / .55); background: linear-gradient(160deg, var(--gold-tint), var(--panel)); }
  .tariff .mark {
    position: absolute; top: 14px; right: 14px; padding: 3px 9px; border-radius: 999px;
    border: 1px solid hsl(var(--gold-hsl) / .45); background: var(--panel); font-size: 10.5px;
    font-weight: 600; color: var(--gold-soft);
  }
  .tariff h4 { margin: 0; font-family: var(--serif); font-size: 20px; font-weight: 700; }
  .tariff .sub { margin-top: 4px; min-height: 32px; font-size: 12.5px; line-height: 1.4; color: var(--muted); }
  .tariff .price { margin: 12px 0 2px; display: flex; align-items: baseline; gap: 7px; }
  .tariff .price b { font-family: var(--num); font-size: 27px; font-weight: 700; letter-spacing: -.02em; }
  .tariff .price span { font-size: 12px; color: var(--muted); }
  .tariff .seats { font-size: 12.5px; color: var(--text-2); }
  .tariff ul { margin: 13px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
  .tariff li { display: flex; gap: 8px; font-size: 12.5px; line-height: 1.35; color: var(--text-2); }
  .tariff li i {
    flex: none; width: 15px; height: 15px; margin-top: 1px; border-radius: 50%; display: grid;
    place-items: center; font-size: 9px; font-style: normal;
    background: hsl(var(--ok-line-hsl) / .16); color: var(--ok);
  }
  .tariff li.no { color: var(--faint); }
  .tariff li.no i { background: var(--panel-4); color: var(--faint); }
  .tariff .pick {
    margin-top: 15px; height: 36px; border-radius: 10px; border: 1px solid var(--border-2);
    background: transparent; color: var(--text-2); font: 600 12.5px Inter, sans-serif; cursor: pointer;
    transition: border-color .2s ease, color .2s ease, background .2s ease;
  }
  .tariff .pick:hover { border-color: hsl(var(--gold-hsl) / .55); color: var(--gold-soft); }
  .tariff .pick.now { border: 0; background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent); }

  /* Показ функции по наведению. Название в списке тарифа ничего не говорит
     тому, кто сервиса не видел: «разметка диалогов ИИ» — это про что? Рядом
     со строкой всплывает петля из двух кадров настоящего окна.
     Слева, а не справа: тарифы стоят колонками, и окошко справа накрыло бы
     соседний тариф — тот самый, с которым человек сейчас сравнивает. */
  .tariff li.clip { cursor: help; }
  .tariff li.clip span { border-bottom: 1px dashed var(--border-2); }
  .tariff li.clip:hover span { border-bottom-color: var(--gold-soft); color: var(--text); }
  .clip-pop {
    position: fixed; z-index: 72; padding: 9px; border-radius: 16px;
    border: 1px solid var(--border-2); background: var(--panel-2); box-shadow: var(--shadow-lg);
    opacity: 0; transform: translateX(8px); pointer-events: none;
    transition: opacity .16s ease, transform .16s ease;
  }
  .clip-pop.on { opacity: 1; transform: none; }
  /* Место под кадр держим заранее: иначе окошко дёргалось бы, пока ролик
     едет по сети. Соотношение сторон задаёт сам ролик — оно у всех одно. */
  /* Своё имя, а не .shot: так уже называется картинка во вложениях чата, и её
     display: inline-block схлопывал кадр в ноль — окошко открывалось пустым. */
  .clip-pop .clip-film {
    display: block; position: relative; overflow: hidden;
    border-radius: 10px; background: var(--panel-3);
  }
  /* Записано окно целиком, а показываем нужный кусок: ролик больше рамки и
     сдвинут — так рамку можно поправить, не переснимая. */
  .clip-pop .clip-film video, .clip-pop .clip-film img {
    position: absolute; display: block; border: 0;
  }
  .clip-pop .cap { margin: 8px 3px 2px; font-size: 12px; line-height: 1.4; color: var(--muted); }
  /* На телефоне наводить нечем: строка остаётся строкой. */
  @media (hover: none) { .tariff li.clip span { border-bottom: 0 } .clip-pop { display: none } }

  /* Оплата: слева объём, справа счёт. Числа считаются на глазах — человек
     платит ту сумму, которую видел, а не ту, что покажет касса. */
  .pay { display: grid; grid-template-columns: 1.35fr 1fr; gap: 14px; align-items: start; }
  .pay .card { padding: 17px 18px; border-radius: 14px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow); }
  .pay .lbl, .set-card > .lbl, .plan-card .lbl, .set-grid .lbl { font-size: 12.5px; color: var(--muted); }
  /* Подпись под сеткой полей: без отступа она липнет к строкам ввода и
     читается как их продолжение, а это уже другой вопрос. */
  .set-card > .lbl.gap { margin-top: 18px; }
  .set-grid .nm { margin-top: 3px; font-size: 14px; font-weight: 600; }
  .plan-card .lbl { margin: 14px 0 -4px; }
  .pay .blk + .blk { margin-top: 17px; }
  .seg { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
  .seg button {
    padding: 7px 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel-3);
    color: var(--muted); font: 500 12.5px Inter, sans-serif; cursor: pointer; transition: all .18s ease;
  }
  .seg button:hover { color: var(--text-2); }
  .seg button.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); font-weight: 600; }
  .seg button small { display: block; font-size: 10px; opacity: .8; }
  .step { display: flex; align-items: center; gap: 10px; margin-top: 9px; }
  .step button {
    width: 32px; height: 32px; border-radius: 9px; border: 1px solid var(--border-2); background: var(--panel-3);
    color: var(--text-2); font-size: 16px; line-height: 1; cursor: pointer; transition: all .18s ease;
  }
  .step button:hover:not(:disabled) { border-color: hsl(var(--gold-hsl) / .5); color: var(--gold-soft); }
  .step button:disabled { opacity: .35; cursor: default; }
  .step .val { min-width: 42px; text-align: center; font-family: var(--num); font-size: 18px; font-weight: 700; }
  .step .hint { font-size: 12px; color: var(--muted); line-height: 1.4; }
  .bill { display: flex; flex-direction: column; gap: 8px; }
  .bill .ln { display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px; color: var(--muted); }
  .bill .ln b { font-family: var(--num); font-weight: 500; color: var(--text-2); font-variant-numeric: tabular-nums; }
  .bill .ln.off b { color: var(--ok); }
  .bill .total { margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
  .bill .total span { font-size: 13px; color: var(--muted); }
  .bill .total b { font-family: var(--num); font-size: 27px; font-weight: 700; letter-spacing: -.02em; }
  .bill .total .sum { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; justify-content: flex-end; }
  .bill .total .sum s { font-family: var(--num); font-size: 15px; color: var(--muted); text-decoration-thickness: 1px; }
  .bill .saved { font-size: 12px; color: var(--ok); }
  /* ---------- экран «Сайт» ---------- */
  .site-top { display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap; margin-bottom: 18px; }
  .site-top h2 { margin: 0; font-family: var(--serif); font-size: 25px; font-weight: 600; }
  .site-top p { margin: 6px 0 0; max-width: 620px; font-size: 13px; line-height: 1.55; color: var(--muted); }
  .site-top .site-period { margin-left: auto; }
  .site-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-bottom: 18px; }

  .block-card {
    margin-bottom: 20px; border-radius: 14px; border: 1px solid var(--border);
    background: var(--panel); box-shadow: var(--shadow); overflow: hidden;
  }
  .block-head { display: flex; align-items: center; gap: 10px; padding: 15px 18px; border-bottom: 1px solid var(--line); }
  .block-head b { font-size: 14.5px; }
  .block-head .key { font-size: 11.5px; color: var(--faint); }
  .block-head .n {
    display: grid; place-items: center; width: 22px; height: 22px; border-radius: 7px;
    background: var(--panel-4); color: var(--muted); font-size: 11.5px; font-weight: 700;
  }
  .pill {
    flex: none; padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 600;
    border: 1px solid var(--border-2); background: var(--panel-4); color: var(--muted);
  }
  .pill.win { border-color: hsl(var(--ok-line-hsl) / .45); background: hsl(var(--ok-line-hsl) / .12); color: var(--ok); }
  .pill.off { opacity: .8; }

  /* Место страницы: свёрнутое — одна строка, развёрнутое — карточки вариантов. */
  .slot { border-bottom: 1px solid var(--line); }
  .slot:last-child { border-bottom: 0; }
  .slot-head {
    display: flex; align-items: center; gap: 12px; width: 100%; padding: 14px 18px;
    border: 0; background: transparent; color: inherit; font: inherit; text-align: left;
    cursor: pointer; transition: background .18s ease;
  }
  .slot-head:hover { background: var(--sunken); }
  .slot-head .nm { flex: none; font-size: 13.5px; font-weight: 600; }
  .slot-head .nm .key { margin-left: 7px; font-size: 11px; font-weight: 400; color: var(--faint); }
  .slot-head .sub {
    flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 12.5px; color: var(--muted);
  }
  .slot-head .sub b { font-weight: 600; color: var(--gold-soft); }
  .slot-head .cnt { flex: none; font-size: 11.5px; color: var(--faint); }
  .slot-head .caret { flex: none; color: var(--faint); transition: transform .2s ease; }
  .slot.open .slot-head { background: var(--sunken); }
  .slot.open .slot-head .caret { transform: rotate(180deg); }
  .slot-body { padding: 6px 18px 20px; }

  /* Карточки вариантов стоят подряд: между ними нужен воздух, иначе экран
     читается как одна сплошная простыня из полей и кнопок. */
  .variant {
    margin-top: 14px; padding: 16px 16px 15px; border-radius: 13px;
    border: 1px solid var(--line); background: var(--panel-2);
  }
  .variant.off { opacity: .6; }
  .variant.win { border-color: hsl(var(--ok-line-hsl) / .45); }
  .variant.new { border-style: dashed; margin-top: 18px; }
  .variant .top { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; margin-bottom: 10px; }
  .variant .num { font-size: 12px; font-weight: 700; color: var(--text-2); font-variant-numeric: tabular-nums; }
  .variant .stat { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
  .variant .stat b { font-weight: 600; color: var(--text-2); }
  .variant .cap {
    display: block; margin-bottom: 7px; font-size: 11.5px; font-weight: 600;
    letter-spacing: .02em; text-transform: uppercase; color: var(--faint);
  }
  .variant textarea {
    display: block; width: 100%; margin: 0; padding: 11px 13px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font: inherit; font-size: 13.5px; line-height: 1.55; resize: vertical; outline: none;
    transition: border-color .2s ease;
  }
  .variant textarea:focus { border-color: hsl(var(--gold-hsl) / .45); }
  .variant textarea:disabled { opacity: .75; cursor: default; }
  /* Подсказка про звёздочки всплывает, когда в поле пишут: висеть над каждым
     из пяти вариантов ей незачем, а узнать про выделение больше неоткуда. */
  .variant .tip { margin-top: 7px; font-size: 12px; line-height: 1.5; color: var(--faint); }
  .variant .tip[hidden] { display: none; }
  .variant .tip b { font-weight: 600; color: var(--gold-soft); }
  /* Предпросмотр показываем, только когда он не повторяет набранное: без
     выделения это была вторая такая же строка под полем — и вопрос «зачем». */
  .variant .preview {
    margin-top: 11px; padding: 10px 12px; border-radius: 10px; background: var(--sunken);
    font-size: 13px; line-height: 1.5; color: var(--text-2);
  }
  .variant .preview .cap { margin-bottom: 5px; }
  .variant .preview b { font-weight: 600; color: var(--gold-soft); }
  /* «Удалить» уезжает от созидательных кнопок: рядом с «Сохранить» они
     выглядят одинаково опасными. */
  .variant .set-run .spacer { flex: 1; min-width: 12px; }
  /* Главное действие карточки видно сразу: остальные — ghost, опасное — warn. */
  .variant .set-run button:not(.ghost) {
    width: auto; margin: 0; height: 36px; padding: 0 18px; border-radius: 10px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 13px Inter, sans-serif; cursor: pointer; box-shadow: none;
    transition: filter .2s ease;
  }
  .variant .set-run button:not(.ghost):hover:not(:disabled) { filter: brightness(1.06); }
  .variant .set-run button:not(.ghost):disabled { filter: grayscale(.55); opacity: .6; cursor: default; }

  /* Полоса конверсии: две длины рядом сравниваются быстрее двух процентов. */
  .bar { height: 6px; margin: 2px 0 8px; border-radius: 999px; background: var(--panel-4); overflow: hidden; }
  .bar i { display: block; height: 100%; border-radius: 999px; background: var(--gold-fill); }
  /* Мало данных — полоса бледнее, но всё-таки видна: серый в серый читался
     как пустая дорожка, и длина переставала о чём-либо говорить. */
  .bar.thin i { background: hsl(var(--gold-hsl) / .4); }
  .win .bar i { background: var(--ok-line); }

  .stat-row { display: flex; align-items: center; gap: 12px; padding: 11px 16px; border-bottom: 1px solid var(--line); }
  .stat-row:last-child { border-bottom: 0; }
  .stat-row.off { opacity: .55; }
  .stat-row .num { flex: none; width: 28px; font-size: 12px; font-weight: 700; color: var(--muted); }
  .stat-row .body { flex: 1; min-width: 0; }
  .stat-row .txt {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 13px; color: var(--text-2); margin-bottom: 6px;
  }
  .stat-row .txt b { font-weight: 600; color: var(--gold-soft); }
  .stat-row .nums { flex: none; text-align: right; }
  .stat-row .nums b { display: block; font-size: 14px; font-variant-numeric: tabular-nums; }
  .stat-row .nums span { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  .stat-row.win .nums b { color: var(--ok); }

  .mail-preview {
    margin-top: 7px; padding: 14px 16px; border-radius: 12px;
    border: 1px solid var(--line); background: var(--sunken);
  }
  .mail-preview .to { font-size: 12px; color: var(--muted); }
  .mail-preview .subj { margin-top: 6px; font-size: 14.5px; font-weight: 600; }
  .mail-preview .text { margin-top: 9px; font-size: 13px; line-height: 1.55; white-space: pre-wrap; }
  .check { display: flex; align-items: center; gap: 9px; margin-top: 14px; font-size: 13px; color: var(--text-2); }
  .check input { width: 16px; height: 16px; margin: 0; accent-color: var(--gold); }
  .seg button .off {
    margin-left: 5px; font-size: 10.5px; font-weight: 700; color: var(--ok);
    font-variant-numeric: tabular-nums;
  }
  .seg button.on .off { color: inherit; opacity: .85; }
  .bill .go {
    margin-top: 14px; height: 42px; border: 0; border-radius: 11px;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 700 14px Inter, sans-serif; cursor: pointer; transition: filter .2s ease;
  }
  .bill .go:hover { filter: brightness(1.06); }
  .bill .go:disabled { opacity: .5; cursor: default; }
  .bill .foot { margin-top: 9px; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
  /* Согласие на автосписания. Стоит над кнопкой, а не под ней: человек
     должен прочитать его до оплаты, а не узнать после. Галочка не
     проставлена — согласие даётся действием, иначе это не согласие. */
  /* label.agree, а не .agree: правило «.pay .card label { display: block }»
     выше стоит из двух классов и элемента, и без элемента здесь галочка с
     текстом слипались в одну строку — текст наезжал на квадратик. */
  /* Поддержка: точка, когда есть ответ, которого человек не видел. Она нужна
     в двух местах — на самом пункте меню и на аватаре: меню обычно закрыто,
     и точка внутри него никого бы не позвала. */
  #btn-me { position: relative; }
  #btn-me .dot {
    position: absolute; top: -1px; right: -1px; width: 9px; height: 9px; border-radius: 50%;
    background: var(--gold); box-shadow: 0 0 0 2px var(--bg);
  }
  .me-pop #btn-support { position: relative; }
  .me-pop #btn-support .dot {
    position: absolute; top: 50%; right: 10px; margin-top: -3.5px;
    width: 7px; height: 7px; border-radius: 50%; background: var(--gold);
  }
  .me-pop .dot[hidden], #btn-me .dot[hidden] { display: none; }
  .sup-wrap { display: flex; flex-direction: column; gap: 12px; }
  .sup-list { display: flex; flex-direction: column; gap: 8px; max-height: 210px; overflow-y: auto; }
  .sup-item {
    display: flex; align-items: center; gap: 10px; padding: 10px 12px; text-align: left;
    border-radius: 11px; border: 1px solid var(--border); background: var(--panel-3);
    color: var(--text); font: 400 13px Inter, sans-serif; cursor: pointer;
  }
  .sup-item:hover { border-color: hsl(var(--gold-hsl) / .45); }
  .sup-item .s { flex: 1; min-width: 0; }
  .sup-item .nm { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sup-item .ls { margin-top: 2px; font-size: 12px; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sup-thread { display: flex; flex-direction: column; gap: 9px; max-height: 320px; overflow-y: auto; }
  .sup-msg { max-width: 86%; padding: 9px 12px; border-radius: 13px; font-size: 13.5px; line-height: 1.5; }
  .sup-msg.client { align-self: flex-end; background: var(--gold-fill); color: var(--on-accent); }
  .sup-msg.support { align-self: flex-start; background: var(--panel-3); border: 1px solid var(--border); }
  .sup-msg .who { margin-bottom: 3px; font-size: 11.5px; opacity: .75; }
  .sup-note { font-size: 12.5px; line-height: 1.6; color: var(--muted); }
  /* Поля обращения — как везде в окне: своя рамка, свой фон и кольцо в
     фокусе. Браузерные по умолчанию выглядят чужими именно там, где человек
     и так расстроен: он пишет в поддержку. */
  .sup-wrap input, .sup-wrap textarea {
    width: 100%; padding: 11px 13px; border-radius: 12px;
    border: 1px solid var(--border-2); background: var(--panel-3); color: var(--text);
    font: 400 13.5px Inter, sans-serif; line-height: 1.6; outline: none;
    transition: border-color .2s ease, box-shadow .2s ease;
  }
  .sup-wrap input::placeholder, .sup-wrap textarea::placeholder { color: var(--faint); }
  .sup-wrap input:focus, .sup-wrap textarea:focus {
    border-color: hsl(var(--gold-hsl) / .55);
    box-shadow: 0 0 0 3px hsl(var(--gold-hsl) / .14);
  }
  /* Тянуть только вниз: вбок текстовое поле вылезает за края окна. */
  .sup-wrap textarea { min-height: 132px; resize: vertical; }
  .sup-wrap .lbl { margin-bottom: -6px; font-size: 12px; color: var(--muted); }

  /* Системные письма: список карточек, каждая раскрывается в правку. */
  .letter-card {
    margin-bottom: 10px; border-radius: 14px; border: 1px solid var(--border);
    background: var(--panel); box-shadow: var(--shadow); overflow: hidden;
  }
  /* Счётчики письма: сколько ждёт отправки и сколько ушло. */
  .letter-nums { display: flex; align-items: center; gap: 14px; font-size: 12.5px; color: var(--muted); white-space: nowrap; }
  .letter-nums .n b { font-family: var(--num); font-variant-numeric: tabular-nums; color: var(--text-2); font-weight: 600; }
  .letter-nums .n.hot b { color: var(--gold); }
  .letter-nums .n.bad b { color: var(--danger); }
  @media (max-width: 640px) { .letter-nums { display: none; } }
  .letter-card > .top {
    display: flex; align-items: center; gap: 12px; padding: 14px 16px; cursor: pointer;
  }
  .letter-card > .top:hover { background: var(--panel-3); }
  .letter-card .nm { font-size: 14px; font-weight: 600; }
  .letter-card .wh { margin-top: 2px; font-size: 12px; color: var(--muted); }
  .letter-card .sp { flex: 1; }
  .letter-card .more { padding: 4px 16px 16px; border-top: 1px solid var(--line); }
  .letter-card .more[hidden] { display: none; }
  .letter-card label { display: block; margin-top: 13px; font-size: 12.5px; color: var(--muted); }
  .letter-card input, .letter-card textarea {
    width: 100%; margin-top: 6px; padding: 9px 12px; border-radius: 10px;
    border: 1px solid var(--border-2); background: var(--panel-3); color: var(--text);
    font: 400 13px Inter, sans-serif; outline: none;
  }
  .letter-card textarea { min-height: 190px; line-height: 1.55; resize: vertical; }
  .letter-card input:focus, .letter-card textarea:focus { border-color: hsl(var(--gold-hsl) / .5); }
  .letter-card .fields { margin-top: 8px; font-size: 12px; color: var(--muted); line-height: 1.6; }
  .letter-card .fields code {
    padding: 1px 5px; border-radius: 5px; background: var(--panel-3);
    font-family: var(--num); font-size: 11.5px; color: var(--gold-soft); cursor: pointer;
  }
  .letter-card .acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
  .letter-frame {
    width: 100%; height: 520px; margin-top: 12px; border: 1px solid var(--border);
    border-radius: 12px; background: #fff;
  }
  .bill label.agree {
    margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
    display: flex; gap: 9px; align-items: flex-start;
    font-size: 12px; line-height: 1.5; color: var(--text-2); cursor: pointer;
  }
  .bill .agree input { flex: none; width: 16px; height: 16px; margin: 2px 0 0; accent-color: var(--gold); }
  .bill .agree a { color: var(--gold-soft); text-decoration: underline; }
  .bill .agree .when { display: block; margin-top: 4px; font-size: 11.5px; color: var(--muted); }

  /* ---------- админка ---------- */
  .adm-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 22px 0 12px; }
  .adm-head:first-child { margin-top: 0; }
  .adm-head h3 { margin: 0; font-family: var(--serif); font-size: 20px; font-weight: 600; }
  .adm-head p { margin: 0; font-size: 12.5px; color: var(--muted); }
  .adm-head .spacer { flex: 1; }
  .subtabs { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 12px; }
  .subtabs button {
    padding: 6px 13px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel-2);
    color: var(--muted); font: 500 12.5px Inter, sans-serif; cursor: pointer; transition: all .18s ease;
  }
  .subtabs button.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); font-weight: 600; }
  .subtabs button .n { margin-left: 6px; font-family: var(--num); font-size: 11px; opacity: .75; }

  /* Клиент — карточка, а не строка таблицы: в строку не помещается ни почта,
     ни то, чем он пользуется. */
  .acct { border-radius: 14px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow); }
  .acct + .acct { margin-top: 10px; }
  .acct.dead { opacity: .82; }
  .acct .top { display: flex; align-items: center; gap: 13px; padding: 14px 16px; cursor: pointer; }
  .acct .top:hover { background: var(--panel-2); border-radius: 14px; }
  .acct .who { min-width: 0; flex: 1; }
  .acct .who .nm { font-size: 14.5px; font-weight: 600; }
  .acct .who .em { margin-top: 2px; font-size: 12px; color: var(--muted); }
  .acct .facts { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
  .acct .facts > div { text-align: right; }
  .acct .facts .v { font-family: var(--num); font-size: 14.5px; font-variant-numeric: tabular-nums; }
  .acct .facts .v.gold { color: var(--gold-soft); }
  .acct .facts .l { margin-top: 1px; font-size: 11px; color: var(--muted); }
  .acct .caret { flex: none; color: var(--faint); font-size: 11px; transition: transform .2s ease; }
  .acct.open .caret { transform: rotate(180deg); }
  .acct .more { padding: 4px 16px 16px; border-top: 1px solid var(--line); }
  .acct .more[hidden] { display: none; }
  .acct .cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-top: 13px; }
  .acct .cols h5 { margin: 0 0 8px; font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
  /* Колонки карточки клиента не сжимаются сами: без min-width длинная почта
     распирает свою колонку, и плашки ролей наезжают на поля соседней. */
  .acct .cols > * { min-width: 0; }
  .people-row {
    display: flex; align-items: center; flex-wrap: wrap; gap: 6px 9px;
    padding: 6px 0; font-size: 12.5px;
  }
  .people-row .who { flex: 1 1 130px; min-width: 0; }
  .people-row .em { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .people-row .spacer { flex: 1 1 0; }

  /* Выдача прав: человек и вкладки, которые ему открыты. */
  .grant { padding: 14px 16px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel-3); }
  .grant + .grant { margin-top: 10px; }
  .grant .top { display: flex; align-items: center; gap: 11px; }
  .grant .top .nm { font-size: 13.5px; font-weight: 600; }
  .grant .top .em { font-size: 12px; color: var(--muted); }
  .grant .top .spacer { flex: 1; }
  /* Куда слать и что приложить — две строки под текстом правила: их
     меняют реже текста, но искать в другом месте не должны. */
  .rule-pick { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
  .rule-pick .lbl { font-size: 12.5px; color: var(--muted); }
  /* В строке «Куда слать» список стоит рядом с подписью, а не тянется под
     неё на всю ширину, как поля в карточке настроек. */
  .rule-pick select { display: inline-block; width: auto; margin-top: 0; height: 34px; }
  .rule-file { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; font-size: 13px; }
  .rule-file .ico { opacity: .7; }
  .rule-file .nm { overflow-wrap: anywhere; }
  .rule-file .sz, .rule-file .hint { font-size: 12px; color: var(--muted); }
  .tabsel { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
  .tabsel button {
    padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border-2); background: var(--panel);
    color: var(--muted); font: 500 12px Inter, sans-serif; cursor: pointer; transition: all .18s ease;
  }
  .tabsel button.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); font-weight: 600; }
  .tabsel button:disabled { opacity: .55; cursor: default; }
  /* Чипы роли в кабинете — картинка доступа, а не кнопки. Выбранные не
     бледнеют: иначе «открыто» и «закрыто» читались бы одинаково серыми. */
  .tabsel.locked button.on:disabled { opacity: 1; }
  .grant textarea {
    display: block; width: 100%; margin-top: 11px; padding: 10px 12px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--panel); color: var(--text);
    font: 400 13.5px/1.55 Inter, sans-serif; resize: vertical; outline: none;
  }
  .grant textarea:focus { border-color: hsl(var(--gold-hsl) / .45); }

  @media (max-width: 900px) {
    .pay { grid-template-columns: 1fr; }
    .acct .facts { gap: 12px; }
  }

  /* ---------- модалка, лайтбокс, тост ---------- */
  dialog {
    width: min(420px, calc(100vw - 32px)); padding: 0; border: 1px solid var(--border-2);
    border-radius: 16px; background: var(--panel); color: var(--text); box-shadow: var(--shadow-lg);
  }
  #mail-dialog { width: min(520px, calc(100vw - 32px)); }
  dialog::backdrop { background: rgba(4, 6, 10, .7); backdrop-filter: blur(3px); }
  dialog[open] { animation: dlgIn .3s cubic-bezier(.2, .8, .3, 1); }
  .modal-head {
    display: flex; align-items: center; gap: 12px;
    padding: 18px 20px 14px; border-bottom: 1px solid var(--line);
  }
  .modal-head h2 {
    flex: 1 1 auto; min-width: 0;
    margin: 0; font-family: var(--serif); font-size: 20px; font-weight: 600;
  }
  /* Крестик справа в заголовке вместо кнопки внизу: до нижней приходилось
     листать всё окно, а закрыть хочется сразу. Он выше строки заголовка,
     поэтому шапке с крестиком отступы ужимаем — иначе она раздувается. */
  #modal .modal-head { padding: 14px 14px 13px 20px; }
  .modal-body { padding: 18px 20px; }
  /* Окно чтения материала: широкое, со своей прокруткой и книжной вёрсткой. */
  /* display задаём ТОЛЬКО открытому окну: правило на самом dialog перебивает
     браузерное «закрытый не показывается», и пустая карточка висит поверх
     страницы, уехав за верхний край. */
  dialog.doc { width: min(760px, calc(100vw - 32px)); max-height: 86vh; margin: auto; padding: 0; }
  dialog.doc[open] { display: flex; flex-direction: column; }
  .doc-head {
    display: flex; align-items: flex-start; gap: 14px; flex: none;
    padding: 20px 24px 16px; border-bottom: 1px solid var(--line);
  }
  .doc-head h2 { margin: 0; font-family: var(--serif); font-size: 22px; font-weight: 600; line-height: 1.25; }
  .doc-meta { margin-top: 5px; font-size: 12.5px; color: var(--muted); }
  .doc-body { flex: 1; min-height: 0; overflow-y: auto; padding: 20px 24px 26px; }
  .doc-body h3 {
    margin: 26px 0 10px; font-family: var(--serif); font-size: 18px; font-weight: 600; line-height: 1.3;
  }
  .doc-body h3:first-child { margin-top: 0; }
  .doc-body h4 { margin: 20px 0 8px; font-size: 14.5px; font-weight: 700; color: var(--text-2); }
  .doc-body p { margin: 0 0 12px; font-size: 14.5px; line-height: 1.7; color: var(--text-2); }
  .doc-body ul, .doc-body ol { margin: 0 0 14px; padding-left: 22px; }
  .doc-body li { margin: 0 0 6px; font-size: 14.5px; line-height: 1.65; color: var(--text-2); }
  .doc-body b { font-weight: 600; color: var(--text); }
  .doc-body code {
    padding: 1px 5px; border-radius: 5px; background: var(--panel-3);
    font-family: var(--num); font-size: 13px;
  }
  .doc-body blockquote {
    margin: 0 0 14px; padding: 2px 0 2px 14px; border-left: 2px solid hsl(var(--gold-hsl) / .5);
    color: var(--muted); font-style: italic;
  }
  .doc-body .doc-bad { color: var(--danger); }
  /* Таблица шире окна — прокручивается внутри своей рамки, а не тянет страницу. */
  .doc-table { margin: 0 0 16px; overflow-x: auto; border-radius: 10px; border: 1px solid var(--line); }
  .doc-table table { width: 100%; border-collapse: collapse; font-size: 14px; }
  .doc-table th, .doc-table td {
    padding: 9px 13px; text-align: left; vertical-align: top; line-height: 1.55;
    border-bottom: 1px solid var(--line); color: var(--text-2);
  }
  .doc-table th { background: var(--sunken); font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; }
  .doc-table tr:last-child td { border-bottom: 0; }
  /* Карточка документа кликается целиком, кроме крестика. */
  .kb-row { cursor: pointer; }
  .kb-row .drop { cursor: pointer; }

  .conn-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
  .conn-row {
    display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 11px;
    border: 1px solid var(--border); background: var(--panel-3); cursor: pointer;
    transition: border-color .18s ease;
  }
  .conn-row:hover { border-color: var(--border-2); }
  .conn-row.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); }
  .conn-row .nm { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600; }
  .conn-row .nm span { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 400; color: var(--muted); }
  .conn-row .x {
    flex: none; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 8px;
    background: none; color: var(--faint); font-size: 14px; cursor: pointer;
  }
  .conn-row .x:hover { background: var(--panel-2); color: var(--danger); }
  .conn-add { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
  .conn-add button {
    flex: 1; min-width: 140px; height: 38px; border-radius: 10px; border: 1px dashed var(--border-2);
    background: transparent; color: var(--text-2); font: 500 12.5px Inter, sans-serif; cursor: pointer;
    transition: border-color .18s ease, color .18s ease;
  }
  .conn-add button:hover:not(:disabled) { border-color: hsl(var(--gold-hsl) / .55); color: var(--gold-soft); }
  .conn-add button:disabled { opacity: .5; cursor: default; }
  .conn-add .note { flex: 1 0 100%; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
  .conn-tabs { display: flex; gap: 8px; justify-content: center; margin-bottom: 14px; }
  .conn-tabs button {
    padding: 6px 16px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel-2);
    color: var(--muted); font: 500 13px Inter, sans-serif; cursor: pointer; transition: all .2s ease;
  }
  .conn-tabs button.on { border-color: hsl(var(--gold-hsl) / .5); background: var(--gold-tint); color: var(--gold-soft); font-weight: 600; }
  #conn-state { display: block; text-align: center; margin-bottom: 16px; cursor: default; }
  #conn-state.ok { border-color: hsl(var(--ok-line-hsl) / .4); color: var(--ok); }
  #conn-state.bad { border-color: hsl(var(--danger-line-hsl) / .4); color: var(--danger); }
  .qr-slot { display: grid; place-items: center; min-height: 240px; text-align: center; }
  /* Явный display перебивает [hidden] браузера: пока код не пришёл, место под
     него не должно зиять пустотой. */
  .qr-slot[hidden] { display: none; }
  .qr-slot img { width: 232px; height: 232px; border-radius: 10px; background: #fff; padding: 8px; }
  .qr-slot h2 { margin: 0; font-family: var(--serif); font-size: 22px; }
  .qr-slot .hint { margin-top: 8px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
  .qr-slot .reset { margin-top: 14px; }
  .pass-form { display: flex; gap: 8px; width: 100%; margin-top: 14px; }
  .pass-form input {
    flex: 1; min-width: 0; height: 40px; padding: 0 12px; border-radius: 10px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text); font-size: 14px; outline: none;
  }
  .pass-form button {
    height: 40px; padding: 0 16px; border-radius: 10px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 13px Inter, sans-serif; cursor: pointer;
  }
  .pass-error { margin-top: 9px; font-size: 12.5px; color: var(--danger); }
  /* Форма почтового ящика: полей много, поэтому в два столбца — иначе она
     вытягивается за высоту окна и кнопку приходится искать прокруткой. */
  .mailbox-form { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 100%; margin-top: 14px; text-align: left; }
  .mailbox-form label { font-size: 12px; color: var(--muted-2); }
  .mailbox-form label.wide { grid-column: 1 / -1; }
  .mailbox-form input {
    display: block; width: 100%; box-sizing: border-box; margin-top: 4px; height: 38px;
    padding: 0 11px; border-radius: 9px; border: 1px solid var(--border);
    background: var(--panel-3); color: var(--text); font-size: 14px; outline: none;
  }
  .mailbox-form input:focus { border-color: hsl(var(--gold-hsl) / .6); }
  .mailbox-form button {
    grid-column: 1 / -1; height: 40px; border-radius: 10px; border: 0;
    background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill)); color: var(--on-accent);
    font: 600 13px Inter, sans-serif; cursor: pointer;
  }
  .steps { margin: 16px 0 0; padding-left: 20px; font-size: 12.5px; line-height: 1.7; color: var(--muted); }
  .steps[hidden] { display: none; }
  .conn-missing { margin-top: 12px; padding: 10px 12px; border-radius: 9px; background: var(--panel-2); font-size: 12px; line-height: 1.5; color: var(--muted); }
  .modal-foot { padding: 0 20px 18px; }
  /* Своё окно вопроса вместо системного confirm: тот приходит с чужими
     шрифтами и чужими кнопками и выглядит как ошибка браузера, а не как
     часть окна. Здесь всё то же самое, но в нашем оформлении. */
  dialog.ask { width: min(400px, calc(100vw - 32px)); }
  .ask-text { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--muted); }
  .ask-text + .ask-text { margin-top: 10px; }
  .ask-foot { display: flex; gap: 9px; justify-content: flex-end; padding: 4px 20px 18px; }
  .ask-foot button {
    height: 36px; padding: 0 16px; border-radius: 9px; border: 1px solid var(--border);
    background: var(--panel-2); color: var(--text-2); font: 500 13px Inter, sans-serif;
    cursor: pointer; transition: border-color .2s ease, color .2s ease, filter .2s ease;
  }
  .ask-foot button:hover { border-color: var(--border-2); color: var(--text); }
  .ask-foot button.go {
    border: 0; background: linear-gradient(135deg, var(--gold-deep), var(--gold-fill));
    color: var(--on-accent); font-weight: 600;
  }
  .ask-foot button.go:hover { filter: brightness(1.06); }
  .ask-foot button.go.danger { background: var(--danger); color: #fff; }
  @media (max-width: 640px) {
    .ask-foot { flex-direction: column-reverse; }
    .ask-foot button { width: 100%; height: 42px; font-size: 14px; }
  }
  .linked-row {
    display: flex; align-items: center; gap: 8px; padding: 7px 9px; margin-bottom: 6px;
    border-radius: 9px; border: 1px solid var(--border); background: var(--panel-3);
    font-size: 12.5px; color: var(--text-2); text-decoration: none;
  }
  .linked-row:hover { border-color: hsl(var(--gold-hsl) / .45); }
  .linked-row .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .linked-row .count { flex: none; font-size: 11px; color: var(--faint); }
  .muted-note { font-size: 12.5px; line-height: 1.5; color: var(--muted); }
  .link-btn {
    margin-top: 8px; height: 28px; padding: 0 11px; border-radius: 8px;
    border: 1px solid var(--border-2); background: transparent; color: var(--gold-soft);
    font: 500 12px Inter, sans-serif; cursor: pointer; transition: border-color .2s ease;
  }
  .link-btn:hover { border-color: hsl(var(--gold-hsl) / .5); }
  .link-body { padding: 16px 20px; }
  .link-body p { margin: 0 0 12px; font-size: 13px; line-height: 1.55; color: var(--muted); }
  .link-body input {
    width: 100%; box-sizing: border-box; height: 40px; padding: 0 13px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--panel-3); color: var(--text);
    font-size: 13.5px; outline: none;
  }
  .link-body input:focus { border-color: hsl(var(--gold-hsl) / .45); }
  .link-results { max-height: 260px; overflow-y: auto; margin-top: 11px; }
  .link-results .none { padding: 10px 2px; font-size: 12.5px; color: var(--muted); }
  .link-results .pick {
    display: flex; align-items: center; gap: 9px; width: 100%; padding: 9px 10px; margin-bottom: 6px;
    border-radius: 9px; border: 1px solid var(--border); background: var(--panel-3);
    color: var(--text-2); font-size: 13px; text-align: left; cursor: pointer;
    transition: border-color .18s ease;
  }
  .link-results .pick:hover { border-color: hsl(var(--gold-hsl) / .5); }
  .link-results .pick .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .link-results .pick .count { flex: none; font-size: 11px; color: var(--faint); }

  .keys-body { display: flex; flex-direction: column; gap: 10px; padding: 18px 20px; }
  .keys-body div { display: flex; align-items: center; gap: 12px; }
  .keys-body kbd {
    flex: none; min-width: 58px; padding: 3px 9px; border-radius: 7px; border: 1px solid var(--border-2);
    background: var(--panel-4); font-family: var(--num); font-size: 12px; text-align: center;
    color: var(--gold-soft);
  }
  .keys-body span { font-size: 13.5px; color: var(--text-2); }
  .lightbox {
    position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column;
    background: rgba(4, 6, 10, .94); animation: fadeIn .2s ease;
  }
  .lightbox[hidden] { display: none !important; }
  .lb-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex: none; padding: 14px 18px; }
  .lb-who { min-width: 0; }
  .lb-who .cap { font-size: 14px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lb-who .meta { font-size: 12px; color: var(--muted); }
  /* Солнце и месяц — рисунком, а не кругом с вырезом: вырез закрашивался
     цветом кнопки, и на тёмной теме месяц читался обломком кольца. */
  .ico-theme { display: block; }
  .ico-theme .sun { display: none; }
  .theme-light .ico-theme .moon { display: none; }
  .theme-light .ico-theme .sun { display: block; }

  /* Значок «страница с боковой панелью» рисуем рамкой, а не символом:
     ▤ в шрифте окна нет и вместо него получается пустой квадрат. */
  .ico-panel {
    display: block; width: 11px; height: 13px; border: 1.4px solid currentColor;
    border-right-width: 4px; border-radius: 2px;
  }
  .lb-tools { display: flex; align-items: center; gap: 8px; flex: none; }
  .lb-tools .counter { font-family: var(--num); font-size: 12px; color: var(--muted-2); font-variant-numeric: tabular-nums; }
  .lightbox .close {
    display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px;
    border: 1px solid var(--border-2); background: rgba(20, 24, 32, .7); color: var(--text-2);
    font-size: 14px; cursor: pointer; transition: border-color .2s ease, color .2s ease;
  }
  .lightbox .close:hover { border-color: hsl(var(--gold-hsl) / .45); color: var(--gold-soft); }
  .lb-stage { flex: 1; display: flex; align-items: center; justify-content: center; gap: 14px; min-height: 0; padding: 0 14px 22px; }
  .lightbox img { max-width: min(1000px, 92vw); max-height: 100%; border-radius: 14px; animation: lbIn .3s cubic-bezier(.2, .8, .3, 1); }
  .lightbox .nav {
    flex: none; width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border-2);
    background: rgba(20, 24, 32, .6); color: var(--text-2); font-size: 26px; line-height: 1;
    cursor: pointer; transition: background .2s ease, transform .2s ease;
  }
  .lightbox .nav:hover { background: rgba(32, 38, 50, .8); transform: scale(1.06); }
  .lightbox .nav[hidden] { display: none; }
  .toast {
    /* transform обязателен и вне анимации: без него после её конца плашку
       отбрасывает вправо на половину своей ширины */
    position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
    z-index: 70; padding: 10px 18px; border-radius: 999px;
    border: 1px solid hsl(var(--gold-hsl) / .4); background: var(--panel-2); color: var(--gold-soft);
    font-size: 13px; box-shadow: var(--shadow-lg); animation: toastIn .28s cubic-bezier(.2, .8, .3, 1);
  }
  .toast[hidden] { display: none; }

  .ios-install {
    flex: none; display: flex; align-items: center; gap: 12px;
    padding: 8px 14px; border-bottom: 1px solid hsl(var(--gold-hsl) / .35);
    background: var(--gold-wash); color: var(--text); font-size: 13px; line-height: 1.4;
  }
  .ios-install[hidden] { display: none !important; }
  .ios-install span { min-width: 0; flex: 1; }
  .ios-install .ghost { flex: none; }

  #note-stack {
    position: fixed; top: 64px; right: 16px; z-index: 80;
    display: flex; flex-direction: column; gap: 8px;
    width: min(360px, calc(100vw - 24px)); pointer-events: none;
  }
  .note-card {
    pointer-events: auto; display: block; width: 100%; text-align: left;
    padding: 12px 14px; border-radius: 14px; border: 1px solid var(--border);
    background: var(--panel); color: inherit; box-shadow: var(--shadow-lg);
    cursor: pointer; animation: noteIn .25s cubic-bezier(.2, .8, .3, 1);
  }
  .note-card.out { animation: noteOut .2s ease forwards; }
  .note-card .who { font-weight: 700; font-size: 13.5px; }
  .note-card .txt {
    margin-top: 4px; font-size: 13px; color: var(--muted-2); line-height: 1.35;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
  }

  /* ---------- карточка разбора ---------- */
  /* Один и тот же вид у разбора в дашборде и поверх переписки: руководитель
     и менеджер обсуждают одну карточку, а не две разные. */
  .rc { display: flex; flex-direction: column; gap: 11px; }
  .rc > * { animation: stackIn .3s cubic-bezier(.2, .8, .3, 1) both; }
  .rc-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
  .rc-name { font-family: var(--serif); font-size: 17.5px; font-weight: 700; letter-spacing: -.01em; }
  .rc-when {
    margin-left: auto; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border);
    background: var(--panel-2); font-size: 11.5px; color: var(--muted); white-space: nowrap;
  }
  .rc-tags { display: flex; flex-wrap: wrap; gap: 7px; }
  .rc-tag {
    padding: 5px 12px; border-radius: 999px; border: 1px solid transparent;
    font-size: 12.5px; font-weight: 600; line-height: 1.35;
  }
  .rc-tag.bad { border-color: hsl(var(--danger-line-hsl) / .32); background: hsl(var(--danger-line-hsl) / .13); color: var(--danger); }
  .rc-tag.warn { border-color: hsl(38 80% 50% / .34); background: hsl(38 85% 52% / .13); color: var(--warn); }
  .rc-tag.good { border-color: hsl(var(--ok-line-hsl) / .3); background: hsl(var(--ok-line-hsl) / .11); color: var(--ok); }
  .rc-tag.plain { border-color: var(--border-2); background: var(--panel-2); color: var(--muted-2); }
  .rc-tag.lead { border-color: hsl(var(--gold-hsl) / .4); background: var(--gold-wash); color: var(--gold-soft); }
  a.rc-tag.lead:hover { border-color: hsl(var(--gold-hsl) / .7); }
  .rc-block {
    display: flex; flex-direction: column; gap: 8px; padding: 15px 17px; border-radius: 16px;
    border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow);
  }
  .rc-block .cap {
    font-size: 10.5px; font-weight: 600; letter-spacing: .09em;
    text-transform: uppercase; color: var(--muted);
  }
  .rc-line { font-size: 14.5px; line-height: 1.55; }
  .rc-line.was, .rc-line.was b { color: var(--muted-2); }
  .rc-line b { font-weight: 700; }
  .rc-line.next, .rc-line.next b { color: var(--gold); }
  .rc-quote {
    padding: 13px 16px; border-radius: 5px 16px 16px 5px; border-left: 4px solid var(--gold);
    background: var(--panel-2);
  }
  .rc-quote .cap {
    margin-bottom: 5px; font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--muted);
  }
  .rc-quote .said { font-size: 14.5px; line-height: 1.55; }
  .rc-quote.good { border-left-color: var(--ok-line); }
  .rc-deep .cap-when { margin-left: 8px; font-weight: 500; letter-spacing: 0; text-transform: none; opacity: .65; }
  /* Разбор умной модели — чернильная плашка: это вывод, а не ещё одна строка. */
  .rc-deep {
    position: relative; padding: 15px 17px; border-radius: 16px;
    border: 1px solid var(--ink-line); background: var(--ink); color: var(--ink-text);
  }
  .rc-deep .cap {
    margin-bottom: 7px; font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--ink-accent);
  }
  .rc-deep .txt {
    font-size: 14px; line-height: 1.62; white-space: pre-wrap;
    /* Потолок вместо none: с ним раскрытие едет плавно, а не прыгает. */
    overflow: hidden; max-height: 1200px; transition: max-height .34s cubic-bezier(.2, .8, .3, 1);
  }
  .rc-deep .txt.clamp { max-height: 78px; }
  .rc-deep .fade {
    position: absolute; left: 1px; right: 1px; bottom: 1px; height: 46px; border-radius: 0 0 15px 15px;
    background: linear-gradient(180deg, transparent, var(--ink)); pointer-events: none;
  }
  .rc-more {
    margin-top: 9px; height: 27px; padding: 0 11px; border-radius: 8px;
    border: 1px solid hsl(var(--gold-hsl) / .45); background: transparent; color: var(--ink-accent);
    font: 500 11.5px 'Golos Text', Inter, sans-serif; cursor: pointer; transition: background .2s ease;
  }
  .rc-more:hover { background: hsl(var(--gold-hsl) / .16); }
  .rc-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 13px; }
  .rc-note { font-size: 12.5px; line-height: 1.5; color: var(--muted); }
  .rc-empty { padding: 22px 18px; border-radius: 16px; border: 1px dashed var(--border-2); background: var(--panel); text-align: center; color: var(--muted); line-height: 1.6; }

  /* ---------- разбор поверх переписки ---------- */
  .sheet {
    position: fixed; inset: 0; z-index: 64; display: flex; align-items: center; justify-content: center;
    padding: 26px; background: var(--overlay-soft); backdrop-filter: blur(7px);
    animation: fadeIn .22s ease; opacity: 1; transition: opacity .18s ease;
  }
  .sheet[hidden], .lightbox[hidden] { display: none !important; }
  .sheet.closing { opacity: 0; }
  .sheet-box {
    width: min(720px, 100%); max-height: min(88vh, 940px); overflow-y: auto;
    padding: 20px 22px 22px; border-radius: 24px; border: 1px solid var(--border);
    background: var(--panel-2); box-shadow: var(--shadow-lg);
    animation: sheetIn .36s cubic-bezier(.2, .84, .28, 1);
  }
  .sheet.closing .sheet-box { animation: sheetOut .18s ease forwards; }
  .sheet-top { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
  .sheet-top h3 { margin: 0; font-family: var(--serif); font-size: 21px; font-weight: 700; letter-spacing: -.015em; }
  .sheet-top .who { margin-top: 3px; font-size: 12.5px; color: var(--muted); }
  .sheet-x {
    margin-left: auto; flex: none; display: grid; place-items: center; width: 32px; height: 32px;
    border-radius: 10px; border: 1px solid var(--border); background: var(--panel); color: var(--muted);
    font-size: 14px; cursor: pointer; transition: border-color .2s ease, color .2s ease;
  }
  .sheet-x:hover { border-color: hsl(var(--gold-hsl) / .5); color: var(--gold-soft); }

  .back { display: none; }
  @media (max-width: 1200px) {
    main.with-panel { grid-template-columns: 320px minmax(0, 1fr); }
    /* Третьей колонке места нет — карточка клиента выезжает шторкой поверх
       чата. Кнопка в шапке открывает, крестик или она же закрывают. */
    .panel {
      position: fixed; top: 0; right: 0; bottom: 0; width: min(420px, 100%);
      z-index: 46; box-shadow: var(--shadow-lg);
      padding-top: env(safe-area-inset-top, 0px);
    }
    .panel-close {
      display: grid;
      top: calc(10px + env(safe-area-inset-top, 0px));
    }
  }
  @media (max-width: 900px) {
    .btn-rc .lbl { display: none; }
    /* Подписи нет — значит это такой же значок, как звёздочка и карточка
       клиента. Разные размеры в одном ряду читались как случайность. */
    .chat-head .btn-rc { width: 36px; height: 36px; padding: 0; justify-content: center; }
    .chat-head .icon-btn { width: 36px; height: 36px; }
    .brand-sep, .brand-sub { display: none; }
    .voices, .quotes { grid-template-columns: 1fr; }
    .heroes { grid-template-columns: 1fr; }
    /* Справочная полоса в колонку: на узком экране она переносилась как
       придётся — разделитель повисал в конце строки, а «График по часам»
       уезжал вправо от долей каналов. */
    .strip { flex-direction: column; align-items: flex-start; gap: 8px; }
    .strip .sep, .strip .spacer { display: none; }
    /* Строка очереди в колонку: пять столбцов на телефоне превращаются в
       пять узких полос, где не читается ни имя, ни дело. */
    .rrow .line { grid-template-columns: 4px minmax(0, 1fr); align-items: start; padding: 10px 14px 12px 0; }
    .rrow .sev { grid-row: 1 / span 4; }
    .rrow .who, .rrow .mid, .rrow .when, .rrow .acts { grid-column: 2; }
    .rrow .mid { padding: 6px 0 0; }
    /* На телефоне строка вдвое уже: в две строки суть режется на полуслове. */
    .rrow .mid .todo { -webkit-line-clamp: 3; }
    .rrow .why .txt { -webkit-line-clamp: 3; }
    .rrow .when { flex-direction: row; gap: 8px; align-items: baseline; margin-top: 4px; }
    /* Кнопки к правому краю и «В задачи» первой: большой палец на телефоне
       достаёт до правого нижнего угла, а не до левого. row-reverse кладёт
       первую в разметке кнопку справа, поэтому пакуем от начала оси. */
    .rrow .acts { flex-direction: row-reverse; justify-content: flex-start; margin-top: 10px; }
    .rrow .body { padding: 0 14px 14px 18px; }
  }
  @media (max-width: 720px) {
    .sheet { padding: 0; align-items: flex-end; }
    .sheet-box {
      max-height: 92vh; border-radius: 22px 22px 0 0;
      padding-bottom: calc(22px + env(safe-area-inset-bottom));
    }
    html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
    header {
      flex-wrap: nowrap; gap: 6px;
      height: calc(48px + env(safe-area-inset-top, 0px));
      min-height: calc(48px + env(safe-area-inset-top, 0px));
      padding: env(safe-area-inset-top, 0px) 8px 0;
    }
    .brand, .chip-wrap, header > .spacer, #btn-theme, #btn-help, #btn-connect, #btn-bell {
      display: none !important;
    }
    #me-theme, #me-bell:not([hidden]) { display: block; }
    /* Полоска вкладок занимает всё, кроме кружка профиля: сама ездит
       пальцем, аватар остаётся на месте справа. */
    .views {
      flex: 1 1 0; width: 0; min-width: 0; overflow-x: auto; scrollbar-width: none;
      padding: 2px; gap: 1px;
    }
    .views::-webkit-scrollbar { display: none; }
    .views button { padding: 5px 7px; font-size: 12px; }
    .me { flex: none; margin-left: 4px; }
    .avatar { width: 32px; height: 32px; font-size: 12px; }
    .ghost { padding: 0 9px; font-size: 12px; }
    #note-stack { top: 58px; right: 10px; }
    .ios-install { flex-wrap: wrap; font-size: 12.5px; padding: 8px 10px; }
    main, main.with-panel {
      display: flex; flex-direction: column;
      grid-template-columns: minmax(0, 1fr);
      flex: 1 1 0; min-height: 0;
    }
    main { position: relative; }
    aside, section.chat { flex: 1 1 0; min-height: 0; width: 100%; }
    body { padding-bottom: 0; }
    body.v-chats {
      position: fixed; left: 0; right: 0; top: 0; width: 100%;
      height: 100dvh; max-height: 100%; overflow: hidden;
    }
    html, aside, .list, main { background: var(--bg); }
    .list { padding-bottom: 0; }
    .chat-head .spacer { display: block !important; flex: 1; min-width: 4px; }
    #chat-ball, #btn-review { flex: none; }
    .composer {
      gap: 6px;
      align-items: flex-end;
      padding: 6px 8px;
      padding-left: calc(8px + env(safe-area-inset-left, 0px));
      padding-right: calc(8px + env(safe-area-inset-right, 0px));
    }
    .composer .tool {
      width: 38px; height: 38px; border-radius: 50%;
    }
    #composer-send {
      display: grid; place-items: center;
      height: 38px; padding: 0; margin-left: 0; border-radius: 50%;
    }
    #composer-send.ready {
      width: 38px; max-width: 38px; padding: 0; margin-left: 0; border-radius: 50%;
    }
    #composer-send span { display: none; }
    #composer-send .ico-send { display: block; }
    .composer textarea {
      margin-left: 10px; margin-right: 8px;
      min-height: 38px; border-radius: 19px; padding: 8px 14px;
      transition: margin .18s ease, border-radius .18s ease;
    }
    body.composer-focus .composer {
      padding: 8px 10px;
      padding-left: calc(10px + env(safe-area-inset-left, 0px));
      padding-right: calc(10px + env(safe-area-inset-right, 0px));
    }
    body.composer-focus .composer textarea {
      margin-left: 0; margin-right: 0; border-radius: 10px;
    }
    body.chat-open aside { display: none; }
    body:not(.chat-open) section.chat { display: none; }
    /* Низ занят строкой ввода и быстрыми кнопками — кнопка села бы поверх. */
    body.chat-open .demo-fab { display: none; }
    .back { display: inline-block; }
    /* Возврат к списку свайпом от левого края: пока палец ведёт диалог
       вправо, под ним виден список — так видно, куда жест приведёт. */
    body.chat-open.chat-sliding aside { display: flex; }
    body.chat-open.chat-sliding section.chat {
      position: absolute; inset: 0; z-index: 6; box-shadow: -18px 0 40px rgb(0 0 0 / .5);
    }
    /* Смайлы — только на компьютере: на телефоне своя клавиатура эмодзи
       под рукой, а место в строке ввода дороже лишней кнопки. */
    #btn-emoji, #emoji-pop { display: none; }
    /* Полоса перевода на телефоне съедает высоту ленты: жмём отступы и
       пускаем язык с кнопкой в одну строку. */
    .tr-bar { gap: 8px; padding: 8px 12px; font-size: 12.5px; }
    .tr-bar .say { flex: 1 1 200px; min-width: 0; }
    .tr-bar select { flex: 1 1 120px; min-width: 0; }
    /* Safari увеличивает страницу, если в поле меньше 16px. */
    .composer textarea,
    .search input,
    input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    select, textarea { font-size: 16px !important; }
  }
  /* На телефоне шапка не влезает целиком: оставляем то, без чего не обойтись. */
  @media (max-width: 560px) {
    /* Шапка чата в одну строку: имя, срок ожидания и две кнопки. Телефон и
       счётчик сообщений есть в карточке клиента, здесь они только ломают
       строку и сдвигают всё остальное. */
    .chat-head { gap: 8px; padding: 9px 10px; }
    .chat-head .title { min-width: 0; overflow: hidden; }
    .chat-head .sub { display: none; }
    /* Палец крупнее курсора: звёздочке нужна и площадь, и размер. */
    .chat-head .icon-btn.star { font-size: 19px; }
    header {
      gap: 8px;
      height: calc(48px + env(safe-area-inset-top, 0px));
      min-height: calc(48px + env(safe-area-inset-top, 0px));
      padding: env(safe-area-inset-top, 0px) 8px 0;
      flex-wrap: nowrap;
    }
    /* Между значком сервиса и полоской вкладок нужен воздух: вплотную
       яркая «Переписки» читалась как наехавшая на логотип. Ужиматься значку
       нельзя: от него оставался огрызок. */
    .brand, .chip-wrap, #btn-help, #btn-connect { display: none !important; }
    /* Четыре вкладки руководителя в 390 пикселей не помещаются, и шапка
       вылезала за край экрана — страница уезжала вбок целиком. Теперь
       листается сама полоска; двум вкладкам менеджера листаться не
       приходится, место под них есть. */
    .views { min-width: 0; overflow-x: auto; scrollbar-width: none; padding: 2px; }
    .views::-webkit-scrollbar { display: none; }
    .views button { padding: 6px 7px; }
    .board-inner { padding: 16px 10px 56px; }
    .hero { padding: 15px 16px 14px; }
    .hero .big { font-size: 38px; }
    .chart { padding: 12px 10px 10px; }
    .chart .bars { gap: 3px; }
    .set-grid { grid-template-columns: 1fr; }
    .composer .tool { width: 38px; height: 38px; }
  }
  /* Совсем узкий экран: значок сервиса уступает место вкладкам. Приложение
     открывают со своей иконки — узнавать его ещё и в шапке незачем. */
  @media (max-width: 370px) {
    .brand { display: none; }
  }
