/* ============================================================================
   ПЕРЕПИСКА С КЛИЕНТОМ — ОФОРМЛЕНИЕ
   ============================================================================

   ВАЖНО. Это рабочая зона: здесь клиенты пишут менеджеру. Поведение низа экрана
   выверено на живом айфоне в телеграме и легко ломается со стороны. Прежде чем
   менять что-либо ниже, прочитайте «Чего нельзя трогать».

   ---------------------------------------------------------------------------
   ЧТО ГДЕ
   ---------------------------------------------------------------------------
   Экран и подложки .................. .tab-screen--page[data-screen="chat"]
   Числа низа (полоса, строка, табы) . body { --chat-safe, --chat-field, --chat-tabs }
   Столбец ........................... .chat
   Лента сообщений ................... .chat__log
   Пузыри и время .................... .chat-line, .chat-line__at
   Фото и файлы ...................... .chat-line--photo, .chat-photo, .chat-file
   Снимок во весь экран .............. .chat-viewer
   Строка ввода ...................... .chat__form, .chat__field, .chat__send
   Подложка под строкой .............. .chat__foot
   Клавиатура ........................ высота .chat__foot, считает chat.js

   ---------------------------------------------------------------------------
   КАК УСТРОЕНО
   ---------------------------------------------------------------------------
   Столбец ровно в видимую часть окна (100dvh). Сверху лента, она тянется и
   прокручивается внутри себя. Снизу строка ввода. Под строкой — пустая
   подложка в высоту панели вкладок: панель стоит на этом месте.

   Клавиатура сжимает окно, а значит и столбец: лента становится короче, строка
   оказывается над клавиатурой. Подложка при этом складывается, чтобы строка
   легла на клавиатуру вплотную.

   ---------------------------------------------------------------------------
   ЕСЛИ НИЗ ПЕРЕПИСКИ ПОЕХАЛ — ВЕРНУТЬСЯ СЮДА
   ---------------------------------------------------------------------------
   В истории стоит метка `chat-ok-20260820`: состояние, проверенное владельцем
   20.08.2026, когда строка, панель и клавиатура работают верно во всех
   положениях. Откат одной командой:

       git checkout chat-ok-20260820 -- webapp/js/chat.js webapp/js/app.js \
                                        webapp/css/chat.css webapp/css/base.css

   В тот день низ переписки перестраивали трижды, и все три раза пришлось
   откатывать. Правка здесь допустима только точечная, по одному месту за раз.
   Прочитать этот список — до правки, а не после отката.

   ---------------------------------------------------------------------------
   ЧЕГО НЕЛЬЗЯ ТРОГАТЬ (каждое куплено дорого)
   ---------------------------------------------------------------------------
   1. О клавиатуре судит один источник — размер окна, и считает его chat.js. Ни
      пометок приложения, ни своих меток здесь быть не должно: их было три, они
      расходились между собой, и строка ввода оказывалась посреди экрана, а
      панель вкладок пропадала.

      Этой же меркой chat.js ставит `keyboard-open`, по которой base.css прячет
      панель вкладок. Приложение своего измерения не имеет и иметь не должно:
      20.08.2026 их было два, они расходились, и панель вставала поверх строки.

   2. Высота столбца — только `100dvh`. `svh` и высота от телеграма клавиатуру
      нарочно не замечают. Полная высота окна тоже не годится: страница станет
      выше видимой части, её можно будет прокрутить, и айфон прокрутит её сам —
      экран уедет на высоту клавиатуры.

   3. Оболочка приложения на этом экране не растянута — по той же причине.

   4. Строка ввода не меняет ни размера, ни положения. Место панели вкладок
      держит подложка: есть клавиатура — подложки нет, нет клавиатуры — есть.
      Отсюда у строки ровно два положения и никакого третьего.

   5. Подсветку касания глушим у ленты, панели и подложки: именно она вспыхивала
      над строкой ввода.

   Смежное правило вне этого файла: в app.js любое касание вне поля гасит
   клавиатуру, и экран переписки из него исключён. Иначе тап по ленте сворачивает
   клавиатуру и экран мигает.
   ============================================================================ */

.tab-screen--page[data-screen="chat"] {
  --ink: 20, 22, 26;
  --text: #14161a;
  --panel: #ffffff;
  background: #ffffff;
  color: #14161a;
  /* колодец приложения переписке не нужен: она идёт от края до края */
  margin: 0 -18px;
  padding: 0;
  /* У экранов приложения минимальная высота «во весь экран», а в телеграме это
     больше видимой области: страница вышла бы длиннее окна и тянулась. Высоту
     переписке задаёт её столбец, и ровно по окну. */
  min-height: 0;
}

/* Белый идёт сплошным на весь экран, до системной шапки и до низа: иначе при
   потягивании из-под переписки выглядывает серая подложка приложения. */
body[data-screen="chat"] {
  background: #ffffff;
}

/* Оболочка: тот же белый и не растянута на всю высоту окна. Растянутая делает
   страницу выше видимой части, её можно прокрутить, и айфон прокручивает её
   сам, чтобы показать поле ввода, — экран уезжает на высоту клавиатуры. */
body[data-screen="chat"] .app-shell {
  background: #ffffff;
  min-height: 0;
}

/* Числа, из которых сложен низ переписки. Лежат на body, потому что панель
   вкладок живёт вне экрана переписки, а встать должна по ним же. */
body {
  /* Системная полоса внизу телефона. Замер кладёт сюда chat.js один раз: айфон
     обнуляет её, когда выезжает клавиатура — полоса уходит под клавиатуру, и о
     ней сообщают ноль. Значение из `env` остаётся на первый кадр. */
  --chat-safe: env(safe-area-inset-bottom);
  /* Высота строки ввода: со второй строки текста её меняет chat.js. */
  --chat-field: 40px;
  /* Место панели вкладок: её высота с отступами и системная полоса. */
  --chat-tabs: calc(67px + var(--chat-safe));
}

/* Столбец от верха окна до панели вкладок. Обе его части — лента и строка
   ввода — лежат в обычном потоке: прибитое к окну айфон переставляет отдельным
   рывком уже после клавиатуры, а страницу везёт вместе с ней.

   Высота окна — от телеграма, он её сообщает сам и обновляет. `100svh` тут не
   годится: это высота экрана телефона, а приложение живёт в своём окне, ниже
   шапки телеграма, и оно короче. Остался запасным, если телеграм молчит.

   Столбец занимает окно целиком: низ строки ввода — это низ страницы. Айфон
   под клавиатуру равняет именно по низу страницы, поэтому строка и встаёт на
   клавиатуру. Всё, что оказалось бы ниже строки, встало бы полосой между ней и
   клавиатурой. */
.chat {
  /* Ровно видимая часть окна: `dvh` уменьшается вместе с клавиатурой. Полная
     высота окна тут не годится — страница оказывалась выше видимой части, её
     можно было прокрутить, и айфон прокручивал. */
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Лента занимает всё, что осталось от строки ввода, и прокручивается внутри
   себя. Своей высоты не знает и знать не должна — её задаёт столбец. */
.chat__log {
  flex: 1 1 auto;
  /* Никакой подсветки под пальцем: именно она вспыхивала над строкой ввода —
     её зона оставалась там, где строка была до складывания подложки. */
  -webkit-tap-highlight-color: transparent;
  /* без этого столбец не даст ленте стать короче содержимого, и прокрутки не
     будет: она уедет под строку ввода */
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Снизу — только зазор до строки ввода. Место под саму строку держит столбец:
     она стоит в нём обычным нижним краем. Пока строка была вынута из потока,
     ленте приходилось держать это место числом в отступе, и число это менялось
     в свой момент, отдельно от высоты, — при уходе клавиатуры оно менялось
     последним, и его уже никто не догонял: текст оказывался под строкой. */
  padding: 12px 14px 14px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #ffffff;
}

/* Дата разговора. Стоит между сообщениями по центру и разделяет дни: без неё
   вчерашняя переписка неотличима от сегодняшней. Слов «вчера» и «сегодня» нет
   нарочно — они устаревают прямо на экране, а число не устаревает.

   Простым текстом, без плашки: пузырей в ленте и так хватает. */
.chat-day {
  align-self: center;
  margin: 6px 0 2px;
  color: #9aa0a8;
  font-size: 12.5px;
  line-height: 1.2;
}

.chat__empty {
  margin: auto;
  padding: 0 24px;
  text-align: center;
  color: #9aa0a8;
  /* Четырнадцать — ступень из таблицы почерка. Здесь стояло 14.5: размера с
     половиной в лестнице нет. */
  font-size: 14px;
  line-height: 1.4;
}

/* Пузыри лёгкие: свой — серый, наш — голубоватый. Время стоит внутри,
   в конце последней строки, и обтекается текстом. */
.chat-line {
  position: relative;
  max-width: 80%;
  padding: 9px 13px 9px;
  border-radius: var(--radius-soft);
  font-size: 15.5px;
  line-height: 1.3;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Пузырь клиента — белый, отделён только тенью (выбор владельца 26.08.2026).
   Серым он совпадал с панелью вкладок, и переписка выглядела собранной из
   чужих кусков. Линию вместо тени не берём: рамки из приложения выводили, и
   заводить их обратно ради одного места незачем.

   Это единственная тень в приложении. Она тут не для объёма, а вместо линии:
   белое на белом иначе не отделить, а цветом отделять нельзя — цвет у нас
   значит «нажимается». */
.chat-line--client {
  align-self: flex-end;
  background: #ffffff;
  color: #14161a;
  box-shadow: 0 1px 3px rgba(20, 22, 26, 0.12),
              0 0 0 0.5px rgba(20, 22, 26, 0.05);
}

/* Пузырь менеджера — залит синим, буквы белые (выбор владельца 26.08.2026).
   Цвет берётся из палитры: своего числа здесь нет и быть не должно.

   Белым по нему 4,0:1 — для 15,5 пикселя это чуть ниже порога 4,5. Владелец
   выбрал, зная это: ему важнее, чтобы ответ менеджера был виден сразу. Глубокий
   --accent-deep дал бы 5,4:1, если однажды покажется бледным.

   В мессенджерах синим красят свои сообщения, а не чужие. Здесь наоборот, и это
   не ошибка: клиент смотрит переписку ради ответов менеджера, они и главные. */
.chat-line--operator {
  align-self: flex-start;
  background: var(--accent);
  color: var(--on-accent);
  /* Та же тень, что у белого пузыря. Синему она не нужна, чтобы отделиться, —
     он и так виден; она нужна, чтобы оба пузыря лежали на одной поверхности.
     Без неё синий выглядит наклейкой поверх, а белый — вложенным в лист. */
  box-shadow: 0 1px 3px rgba(20, 22, 26, 0.12);
}

.chat-line__at {
  float: right;
  margin: 6px 0 0 10px;
  font-size: 11px;
  color: #9aa0a8;
}

/* Мелочь внутри синего пузыря: время и подпись файла. Серым по синему их не
   видно вовсе — 1,9:1. Белым в три четверти силы: подпись остаётся подписью,
   но читается. */
.chat-line--operator .chat-line__at,
.chat-line--operator .chat-file__note {
  color: rgba(255, 255, 255, 0.75);
}

/* Фото и файлы. Снимок занимает пузырь целиком — поля вокруг него делают из
   сообщения наклейку. Высоту пузыря задаёт соотношение сторон, пришедшее от
   телеграма: место занято до загрузки, и лента не подпрыгивает. */
.chat-line--photo {
  padding: 4px;
}

.chat-photo {
  display: block;
  width: 210px;
  max-width: 100%;
  max-height: 320px;
  overflow: hidden;
  border-radius: 14px;
  background: #e3e5e9;
}

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

.chat-photo--lost {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  color: #9aa0a8;
  font-size: 13px;
}

.chat-line--photo .chat-line__text {
  display: block;
  padding: 7px 9px 0;
}

.chat-line--photo .chat-line__at {
  margin: 5px 9px 3px 10px;
}

.chat-file__name {
  display: block;
  word-break: break-word;
}

.chat-file__note {
  display: block;
  margin-top: 5px;
  color: #9aa0a8;
  font-size: 12px;
  line-height: 1.3;
}


/* Снимок во весь экран. Лежит поверх всего, включая панель вкладок: фото
   смотрят целиком, а не в окошке между чужими краями. Закрывает любое
   касание — ни увеличения, ни кнопок здесь нет и не должно быть: всё это
   есть в боте, и там оно родное. */
.chat-viewer {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: #000000;
  -webkit-tap-highlight-color: transparent;
}

.chat-viewer.is-open {
  display: flex;
}

.chat-viewer img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.chat-viewer__close {
  position: absolute;
  top: calc(12px + env(safe-area-inset-top));
  right: 14px;
  width: 34px;
  height: 34px;
  /* Сетка с центрированием, а не текстовое выравнивание: у кнопки свои поля,
     и знак в них садится мимо середины кружка. Так же устроена скрепка. */
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  -webkit-tap-highlight-color: transparent;
}

.chat-viewer__close svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: #ffffff;
  stroke-width: 1.9;
  stroke-linecap: round;
}

/* Строка ввода лежит поверх ленты, у нижнего края страницы, и в столбце места
   не занимает.

   Это и есть то, ради чего всё: строка при наборе худеет и встаёт на
   клавиатуру, а лента от этого не меняет высоты ни на точку. Пока строка была
   частью столбца, каждое её изменение меняло и высоту ленты — а у прокрутки,
   меняющей высоту, сафари сбивает положение на кадр, и на экране мелькали
   сообщения, давно ушедшие за верхний край.

   Из потока она вынута, но к окну не прибита: страницу под клавиатуру айфон
   поднимает целиком, и строка едет вместе с ней. */
.chat__form {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) 34px;
  /* По середине: в одну строку — а это почти всегда — плюс и стрелка стоят
     ровно посередине поля (замечание владельца 18.08.2026). */
  align-items: center;
  gap: 8px;
  /* Снизу — место панели вкладок: она стоит на этом поле, и лента под ней не
     просвечивает. Пока идёт набор, табов нет, и поле сжимается до зазора над
     клавиатурой — правило ниже. */
  /* Размер строки постоянный: место панели вкладок держит подложка под ней.
     Пока это место было полем самой строки, строка меняла размер при каждом
     появлении клавиатуры — а меняющая размер строка с фоном и линией оставляет
     на айфоне след прежней отрисовки выше по экрану. */
  /* Снизу столько же, сколько сверху. Безопасную полосу телефона держит
     подложка под строкой (--chat-tabs), и добавлять её здесь второй раз
     значит поднять строку на пустое место (замечание владельца 19.08.2026). */
  padding: 5px 10px 6px;
  background: #ffffff;
  border-top: 1px solid var(--hair);
  -webkit-tap-highlight-color: transparent;
}

/* Место панели вкладок. Пустая подложка без фона и границ: её изменение следов
   не оставляет, потому что рисовать в ней нечего. */
.chat__foot {
  flex: 0 0 auto;
  height: var(--chat-tabs);
  -webkit-tap-highlight-color: transparent;
}

/* Высоту подложки ставит chat.js по самому размеру окна: окно сжато
   клавиатурой — подложки нет. Пометки тут быть не должно: она расходится с
   действительностью, и тогда строка ввода оказывается выше клавиатуры — там,
   где её быть не может ни при каком раскладе. */
/* Скрепка открывает выбор файла. Сам выбор скрыт: показывать системное поле
   «Файл не выбран» посреди строки ввода незачем. */
/* Нажимается сам плюс — он подпись поля выбора. Само поле размером в точку
   лежит в углу кнопки: у него свой наименьший размер, и растянутое на кнопку
   оно заходило на строку ввода — палец попадал в него, нажимая первую букву
   «Сообщения» (замечание владельца 19.08.2026). */
.chat__clip {
  position: relative;
  /* Кнопка ровно по значку с небольшим полем — и ни точкой больше. Раздутая до
     48, она заходила в сторону строки ввода: касания у левого края строки
     попадали в невидимое поле выбора, строка не бралась, а клавиатура
     выскакивала и гасла (замечание владельца 19.08.2026). */
  width: 34px;
  padding: 0;
  height: 34px;
  border: 0;
  background: none;
  display: grid;
  place-items: center;
  outline: none;
  -webkit-tap-highlight-color: transparent;
}

/* Значок не ловит касание: касание должно приходить на саму подпись, иначе
   попадание в неё зависит от того, как движок пробрасывает клик с вложенного
   рисунка — отсюда и было «нажимается через раз». */
.chat__clip svg {
  pointer-events: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: #b0b6bd;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Поле само по себе, плюс и стрелка снаружи по бокам и на одном уровне с ним
   (решение владельца 18.08.2026). Рамка и угол — те же, что у строки поиска. */
.chat__field {
  width: 100%;
  height: var(--chat-field);
  padding: 10px 12px;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: #ffffff;
  color: #14161a;
  /* Цвет курсора называем прямо, а не оставляем на `auto`: при нём цвет
     выбирает система, и на белом поле он однажды уже вышел белым. */
  caret-color: #14161a;
  font: inherit;
  font-size: 16px;
  line-height: 1.2;
  resize: none;
  /* Ни обводки при вводе, ни вспышки под пальцем: строка выглядит одинаково
     до касания и после. Курсор при этом на месте — он не отсюда. */
  outline: none;
  -webkit-tap-highlight-color: transparent;
}

.chat__field:focus,
.chat__field:focus-visible {
  outline: none;
}

.chat__field::placeholder {
  color: #9aa0a8;
}

.chat__send {
  /* Свои поля у кнопки надо снять: с ними место под значок уже самой кнопки,
     значок в него не влезает, и браузер прижимает его к краю вместо центра.
     Размер тот же, что у плюса напротив, и та же норма попадания. */
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  padding: 0;
  border: 0;
  background: none;
  display: grid;
  place-items: center;
  outline: none;
  -webkit-tap-highlight-color: transparent;
}

/* Пока писать нечего — кнопка приглушена, но своего цвета не теряет: это тот
   же системный цвет, только вполсилы. Появился текст — загорается в полную.
   Прозрачностью, а не другим цветом: системный цвет у каждого свой, и
   подбирать к нему бледный оттенок наугад нельзя. */
/* Пока писать нечего — стрелка серая. Появился текст — синеет; ни строка, ни
   стрелка при этом не двигаются. */
.chat__send:disabled svg {
  stroke: #c2c7ce;
}

/* Стрелка занимает почти весь кружок, как в образце. Мало увеличить значок —
   сам рисунок должен идти на всю сетку: раньше он занимал чуть больше её
   половины, и стрелка терялась в кнопке, сколько значок ни расти. */
.chat__send svg {
  pointer-events: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.tab-icon-mask--chat {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M22%2017a2%202%200%200%201-2%202H6.828a2%202%200%200%200-1.414.586l-2.202%202.202A.71.71%200%200%201%202%2021.286V5a2%202%200%200%201%202-2h16a2%202%200%200%201%202%202z%22%20%2F%3E%3C%2Fsvg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M22%2017a2%202%200%200%201-2%202H6.828a2%202%200%200%200-1.414.586l-2.202%202.202A.71.71%200%200%201%202%2021.286V5a2%202%200%200%201%202-2h16a2%202%200%200%201%202%202z%22%20%2F%3E%3C%2Fsvg%3E");
}


/* Поле выбора стоит на своём месте, но размером в точку: чужой зоны не
   занимает и на строку не лезет.

   За экран его уводить нельзя: получив фокус, браузер прокручивает страницу к
   полю — а оно за краем. Экран дёргается, и клавиатура схлопывается сама
   (найдено 19.08.2026 после жалобы владельца). */
.chat__pick {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
