/* Минимализм и скорость: одна маленькая таблица стилей, ноль библиотек.
   Цвета — из темы Telegram, поэтому светлая и тёмная работают сами. */

:root {
  --bg: var(--tg-theme-bg-color, #fff);
  --fg: var(--tg-theme-text-color, #111);
  --hint: var(--tg-theme-hint-color, #8a8a8e);
  --link: var(--tg-theme-link-color, #2481cc);
  --card: var(--tg-theme-secondary-bg-color, #f2f2f7);
  --accent: var(--tg-theme-button-color, #2481cc);
  --accent-fg: var(--tg-theme-button-text-color, #fff);
  --ok: #34a06e;
  /* Второй акцент — только для линии лидера на общем графике */
  --warn: #d99a2b;
  /* fallback первым: старые WebView не знают color-mix и пропустят вторую строку */
  --track: rgba(128, 128, 128, 0.25);
  --track: color-mix(in srgb, var(--hint) 25%, transparent);
}

/* Вне Telegram переменных темы нет — уважаем системную тёмную тему */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: var(--tg-theme-bg-color, #1c1c1e);
    --fg: var(--tg-theme-text-color, #f2f2f7);
    --hint: var(--tg-theme-hint-color, #98989e);
    --card: var(--tg-theme-secondary-bg-color, #2c2c2e);
  }
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
body {
  font: 16px/1.45 -apple-system, system-ui, Roboto, sans-serif;
  background: var(--bg); color: var(--fg);
  display: flex; flex-direction: column;
}

#screen { flex: 1; overflow-y: auto; padding: 14px 16px calc(70px + env(safe-area-inset-bottom)); }
.center { text-align: center; padding: 40px 0; }
.muted { color: var(--hint); }
.small { font-size: 13px; }

/* gap обязателен с тех пор, как ник на «Сегодня» обрезается (.clip): без
   зазора многоточие упиралось прямо в пилюлю стрика, и две разные вещи
   читались одной строкой. */
.head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 10px; }
/* Однострочная обрезка для текста, длину которого мы не контролируем (ник
   из Telegram приходит без лимита). Родителю в flex нужен min-width: 0,
   иначе строка не сжимается, а растягивает экран горизонтальным скроллом. */
.clip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Кнопка «← Все» в шапке комнаты. Адресуемся к ней через .head > .chip, а не
   заводим отдельный класс: прямой сосед блока метаданных в шапке во всём
   приложении один, а остальные чипы лежат внутри .periods и .chips, где
   сжатие и перенос по строкам — как раз то, что нужно. Без flex:none длинное
   название комнаты выдавливало пилюлю до кружка с текстом в две строки;
   align-self держит её у первой строки, иначе она висит посреди шапки,
   которая теперь занимает четыре-пять строк («создал X», общий счёт). */
.head > .chip { flex: none; align-self: flex-start; }
/* flex: none по той же причине, что у .head > .chip: длинный ник теперь
   сжимается сам, а пилюля без запрета сжималась вместе с ним и ломала
   «2 дн. подряд» на две строки. */
.streak { background: var(--card); border-radius: 999px; padding: 4px 12px; font-size: 13px; flex: none; }

.weight { text-align: center; margin: 6px 0 4px; }
.weight b { font-size: 44px; font-weight: 600; line-height: 1.1; }
.weight .unit { font-size: 18px; color: var(--hint); font-weight: 400; }
/* Строки под весом (когда взвешен, среднее за неделю) — обычные
   .small.muted: зелёный .trend, стоявший у среднего, обещал хорошее и в те
   недели, когда среднее росло, а своего размера или отступа этим строкам
   не нужно — их держит line-height. */

.bar { height: 8px; background: var(--track); border-radius: 999px; overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.bar.thin { height: 6px; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 14px 0; }
.card { background: var(--card); border-radius: 14px; padding: 12px; }
/* У .card нет своего margin, и карточки, идущие подряд без обёртки с gap,
   стояли вплотную — плашка приглашённых упиралась в график, график в
   таблицу мест, а на «Профиле» слипались все три карточки. Отступ только
   прямым детям #screen: внутри .grid2 и других обёрток расстояние уже
   держит их gap, и второй слой отступов там всё бы разъехался. */
#screen > .card { margin-bottom: 10px; }
.card h3 { font-size: 13px; font-weight: 500; color: var(--hint); margin-bottom: 6px; }
.card .big { font-size: 20px; font-weight: 600; }

.quick { display: flex; gap: 8px; margin: 10px 0; }
.quick input {
  flex: 1; min-width: 0; font-size: 16px; padding: 10px 12px;
  border: 1px solid var(--track); border-radius: 12px;
  background: var(--bg); color: var(--fg);
}
.quick button, .btn {
  border: 0; border-radius: 12px; padding: 10px 16px; font-size: 15px;
  background: var(--accent); color: var(--accent-fg); cursor: pointer;
}
/* Рамка обязательна: фон у ghost — тот же var(--card), что и у карточки,
   и внутри .card (лента фото, настройки комнаты) кнопка без неё читается
   как обычная строка текста, а не как то, что можно нажать. */
.btn.ghost { background: var(--card); color: var(--fg); border: 1px solid var(--track); }

.meals { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.meal {
  text-align: left; border: 0; border-radius: 12px; padding: 10px 12px;
  background: var(--card); color: var(--fg); cursor: pointer; font-size: 13px;
}
.meal b { display: block; font-size: 14px; }
.meal span { color: var(--hint); font-size: 12px; }

#tabs {
  position: fixed; bottom: 0; left: 0; right: 0;
  display: grid; grid-template-columns: repeat(4, 1fr);
  background: var(--bg); border-top: 1px solid var(--track);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
}
.tab {
  border: 0; background: none; color: var(--hint); font-size: 11px;
  display: flex; flex-direction: column; align-items: center; gap: 2px; cursor: pointer;
}
.tab.active { color: var(--accent); }
.tab svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* Тост живёт в body, а не в #screen: перерисовка экрана стирала бы его в
   том же кадре, в котором он появился. */
.toast {
  /* Выше просмотрщика (z-index 30): неудачное удаление показывает тост, и
     под чёрным оверлеем он был бы невидим — на экране не менялось бы
     ничего, а кнопка выглядела бы сломанной. */
  position: fixed; left: 12px; right: 12px; bottom: 76px; z-index: 40;
  background: var(--card); border-radius: 12px; box-shadow: 0 4px 16px rgba(0,0,0,.18);
  padding: 10px 14px; font-size: 14px; text-align: center;
}

/* Карточка-сигнал: то, ради чего создатель открыл комнату. */
.card.note {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  flex-wrap: wrap; border-left: 3px solid var(--accent);
}

/* Общий счёт комнаты и недельный лидер. Обе строки стоят одна под другой,
   а не рядом с кнопкой «Все»: на 375 px в шапке и так тесно от даты,
   лимита участников и имени создателя — новая колонка её бы переломила. */
.room-total { margin-top: 4px; font-weight: 500; }
.week-leader {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-bottom: 10px; color: var(--hint);
}
.wl-badge {
  flex: none; background: var(--card); color: var(--fg);
  border-radius: 999px; padding: 2px 9px; font-weight: 600;
}

/* --- график --- */

.periods { display: flex; gap: 8px; margin: 4px 0 12px; }
/* Рамка по той же причине, что у .btn.ghost: фон чипа — var(--card), и
   внутри карточки (переключатель графика, «Напомнить», выбор срока в форме
   комнаты) невыбранные варианты выглядели обычным текстом. Человек видел
   только выбранный и не догадывался, что там вообще есть выбор. */
.chip {
  border: 1px solid var(--track); border-radius: 999px; padding: 7px 14px; font-size: 13px;
  background: var(--card); color: var(--fg); cursor: pointer;
}
.chip.on { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }

/* relative — опора для абсолютной плашки курсора (.chart-tip): HTML-элемент
   внутрь svg не положить, поэтому плашка живёт в карточке и позиционируется
   от неё. */
.chart-card { position: relative; padding: 14px 10px 8px; }
/* pan-y: горизонтальная протяжка пальцем — наш курсор по дням, а
   вертикальный свайп остаётся странице; без этого график глушил бы скролл. */
.chart-card svg { display: block; overflow: visible; touch-action: pan-y; }
.c-grid { stroke: var(--track); stroke-width: 1; }
/* 11px, не 9: на узких экранах svg сжимается до ~0.84 масштаба, и 9px
   превращались в ~7.5 — даты и проценты становились нечитаемы. */
.c-axis { fill: var(--hint); font-size: 11px; }
.c-line {
  fill: none; stroke: var(--accent); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
}
/* Не цвет сетки: дневная линия красилась в var(--track) и на тёмной теме
   исчезала в сетке целиком — та же болезнь, что была у .c-other.
   Полупрозрачный hint виден на обеих темах, но тише сглаженной линии. */
.c-raw { fill: none; stroke: var(--hint); stroke-opacity: .55; stroke-width: 1.2; }
.c-plan { fill: none; stroke: var(--hint); stroke-width: 1.4; stroke-dasharray: 4 3; }
.c-area { fill: var(--accent); opacity: 0.14; stroke: none; }
.c-dot { fill: var(--accent); opacity: 0.6; }
.c-last { fill: var(--accent); stroke: var(--card); stroke-width: 2; }
/* Линия цели: зелёная и тоньше основной — это ориентир, а не данные.
   Рисуется только когда цель попала в видимый коридор шкалы (goal_y). */
.c-goal { stroke: var(--ok); stroke-width: 1.2; stroke-dasharray: 6 4; }
.c-goal-text { fill: var(--ok); font-size: 11px; }
/* Бейдж последнего веса у точки: фон страницы, а не карточки — на фоне
   chart-card плашка без контраста сливалась бы с ней. */
.c-badge { fill: var(--bg); stroke: var(--track); }
.c-badge-text { font-size: 11px; font-weight: 600; fill: var(--fg); }
/* Вертикаль тап-курсора. Прозрачность анимируется как у плашки (.chart-tip):
   таять они должны одновременно, порознь это выглядит поломкой. */
.c-cursor { stroke: var(--hint); stroke-width: 1; stroke-dasharray: 2 3; transition: opacity .2s; }

.legend { display: flex; gap: 14px; justify-content: center; margin-top: 8px; }
.legend span { display: inline-flex; align-items: center; gap: 5px; }
.legend i { width: 14px; height: 0; border-top-width: 2px; border-top-style: solid; }
.k-line { border-color: var(--accent); }
/* Как сама линия (см. .c-raw): ключ легенды цвета сетки на тёмной теме
   был так же невидим. */
.k-raw { border-color: var(--hint); opacity: .55; }
.k-plan { border-color: var(--hint); border-top-style: dashed; }

/* Плитки статистики 2×2 вместо одной карточки «За период» (макет В2). */
.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 10px; }
.tile { background: var(--card); border-radius: 12px; padding: 10px 12px; }
.tile b { display: block; font-size: 17px; }
.tile span { font-size: 12px; color: var(--hint); }
/* Подсказка «взвешивайся ещё» — на всю ширину: это не показатель,
   а объяснение, почему плиток темпа и прогноза сейчас нет. */
.tile.wide { grid-column: 1 / -1; }
/* Оценка темпа рядом с числом: «норма», «быстрее обычного». Цвет — акцент
   успеха, но только у самой пометки, а не у числа: число нейтрально, и
   «вес растёт» зелёным выглядело бы издёвкой. */
.tile .note-ok { font-size: 12px; font-weight: 500; color: var(--ok); }

/* Плашка тап-курсора. pointer-events: none — палец под ней продолжает
   вести курсор, а не «нажимает» плашку; появляется и тает через opacity.
   Живёт в .chart-card (ей дан position: relative). */
.chart-tip {
  position: absolute; opacity: 0; pointer-events: none;
  background: var(--bg); border: 1px solid var(--track); border-radius: 10px;
  padding: 8px 10px; font-size: 12px; line-height: 1.5;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
  transition: opacity .2s;
}
.chart-tip .m { color: var(--hint); }

/* Лестница контрольных точек (checkpoints-mockups, В1 «Лента»): все точки
   до финиша, листается вбок. Ширина плитки фиксирована — ряд из чисел
   одной породы должен идти ровным шагом, а не плясать от длины подписи.
   Живёт под графиком, внутри .chart-card (goalplace-mockups, вариант А),
   поэтому и правила стоят здесь, а не в профильной части файла: свой
   margin-top отделяет полосу от легенды, у карточки снизу всего 8px. */
.cp-strip { display: flex; gap: 8px; margin-top: 10px; overflow-x: auto; padding-bottom: 2px; }
/* cursor: pointer — точка не подпись, а кнопка: тап ставит курсор графика
   на её дату. Без курсора-руки нажимаемость ничем не выдавала себя. */
.pt {
  flex: none; width: 84px; text-align: center; background: var(--bg);
  border-radius: 10px; padding: 8px 4px; border: 1px solid transparent;
  cursor: pointer;
}
.pt b { display: block; font-size: 15px; font-variant-numeric: tabular-nums; }
.pt span { display: block; font-size: 11.5px; color: var(--hint); }
.pt .mark { margin-top: 3px; font-size: 11px; }
.pt.done .mark { color: var(--ok); }
/* «выше на X» — цветом подсказки, не красным: личный экран не наказывает,
   это факт, а не оценка. */
.pt.miss .mark { color: var(--hint); }
.pt.next { border-color: var(--accent); }
.pt.finish b { color: var(--ok); }
.pt.dim { opacity: .75; }

/* --- профиль --- */

.row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; padding: 9px 0; border-top: 1px solid var(--track);
}
.row:first-of-type { border-top: 0; }
.row em { display: block; font-style: normal; }
.row input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent); }

/* Настройки рассылки (notifysettings-mockups, В1): текст строки — кнопка
   раскрытия, шрифт и цвет наследуются, чтобы строка не отличалась от
   прежней label. Выключенная рассылка гаснет вместе с кнопкой. */
.pref-edit {
  background: none; border: 0; padding: 0; text-align: left;
  font: inherit; color: var(--fg); cursor: pointer; flex: 1; min-width: 0;
}
.pref-edit:disabled { cursor: default; opacity: .6; }
.pref-panel { padding: 2px 0 8px; }
.pref-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* --- комнаты --- */

.field {
  width: 100%; font-size: 16px; padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--track); border-radius: 12px;
  background: var(--bg); color: var(--fg);
}
.field.short { width: 110px; margin: 0; text-align: right; }
.field.wide-field { width: 160px; text-align: left; }
.btn.wide { width: 100%; margin-top: 12px; }

.periods { flex-wrap: wrap; }
/* Заголовок списка комнат на «Сегодня». Список лежит на фоне экрана, а не
   в карточке (иначе .room сливается с .card — у обоих var(--card)), поэтому
   подпись к нему нужна своя: правило .card h3 сюда не достаёт. */
.rooms-title { font-size: 13px; font-weight: 500; color: var(--hint); margin: 14px 0 6px; }
.rooms { display: flex; flex-direction: column; gap: 8px; }
/* Отступ снизу — только когда список лежит прямо на экране («Сегодня»):
   переехав из карточки на фон, он потерял её margin и упирался в плитки
   итогов. Внутри .card («Челлендж») лишний отступ был бы дырой в карточке. */
#screen > .rooms { margin-bottom: 10px; }
/* Ссылка «ещё N комнат» под усечённым списком. */
.rooms-more {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  color: var(--link); font-size: 13px; padding: 6px 2px; cursor: pointer;
}
/* Карточка комнаты — строка: название с мета слева, место справа, стрелка
   в конце. Без display:flex внутренние блоки вставали друг под другом, и
   все четыре списка («Мои», «Открытые», «Архив», «Тебя зовут») рассыпались
   лесенкой — это первое, что видит любой, кто открыл вкладку. */
.room {
  display: flex; align-items: center; gap: 10px; width: 100%;
  text-align: left; border: 0; border-radius: 12px; padding: 10px 12px;
  /* var(--card), а не var(--bg): строки списка лежат прямо на фоне
     страницы, и с фоном страницы же они не читались как нажимаемые —
     весь каталог комнат выглядел текстом с интервалами. */
  background: var(--card); color: var(--fg); cursor: pointer;
}
.room b { display: block; font-size: 15px; }
.room span { color: var(--hint); font-size: 12px; }

.r-main { flex: 1; min-width: 0; }
.r-main b { display: block; font-size: 15px; }
.r-main span { display: block; font-size: 12px; color: var(--hint); }
.r-pct { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.r-pct em { display: block; font-style: normal; font-weight: 400; font-size: 11px; color: var(--hint); }
.r-go { color: var(--hint); }
.r-meta i.act { font-style: normal; color: var(--ok); }
.r-meta i.act.dead { color: var(--hint); }
/* Рамка: бейдж лежит и в карточке участника, и в строке списка комнат —
   у обеих фон var(--card), тот же, что у самого бейджа. */
.own {
  font-style: normal; font-size: 11px; color: var(--hint);
  background: var(--card); border: 1px solid var(--track);
  border-radius: 999px; padding: 1px 7px; vertical-align: 2px;
}

/* Переключатель разделов */
.seg { display: flex; background: var(--card); border-radius: 10px; padding: 3px; margin-bottom: 12px; }
.seg button {
  flex: 1; border: 0; background: none; color: var(--hint);
  padding: 8px; border-radius: 8px; font-size: 14px; cursor: pointer;
}
.seg button.on { background: var(--bg); color: var(--fg); font-weight: 600; }
.chips { display: flex; gap: 7px; margin-bottom: 10px; }
.chips.wrap { flex-wrap: wrap; }

/* Карточки участников */
.cards { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.pcard { background: var(--card); border-radius: 12px; padding: 10px 12px; }
.pcard.me { outline: 1.5px solid var(--accent); }
.pc-top { display: flex; align-items: center; gap: 8px; }
.pc-top .place { width: 22px; text-align: center; color: var(--hint); font-size: 13px; }
.pc-top b { flex: 1; min-width: 0; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Бейдж — сосед ника по строке, а не его часть: внутри <b> с ellipsis он
   исчезал целиком, стоило нику дорасти до ширины экрана, и создатель
   комнаты переставал быть подписан ровно там, где длинное имя. */
.pc-top .own { flex: none; }
.pc-top .pct { font-weight: 600; font-variant-numeric: tabular-nums; }
.pc-mid { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.pc-facts { margin-top: 6px; }
/* Размеры здесь, а не только в атрибутах svg: когда точек меньше трёх, линии
   нет и шаблон ставит на её место пустой <span class="spark">. Распорка
   обязана занять ту же клетку, иначе факты в карточках без линии съезжают
   влево и соседние строки перестают стоять по одной вертикали. Самому svg
   эти 62×20 ничего не меняют — те же числа стоят у него в атрибутах. */
.spark { flex: none; width: 62px; height: 20px; }
.spark path { fill: none; stroke: var(--accent); stroke-width: 1.4; stroke-linejoin: round; }

/* Линии общего графика: жирных всегда две, остальные — серый коридор */
/* linecap нужен всем ролям, а не только своей линии: одна точка рисуется
   отрезком нулевой длины, и без круглого конца её просто не видно. */
.c-me { fill: none; stroke: var(--accent); stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
.c-leader { fill: none; stroke: var(--warn); stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
/* Не цвет сетки: серым коридором линии красились в var(--track) и на
   тёмной теме исчезали в ней целиком — участник, который не ты и не
   лидер, на графике отсутствовал. Полупрозрачный hint виден на обеих
   темах, но по-прежнему тише жирных линий. */
.c-other { fill: none; stroke: var(--hint); stroke-opacity: .55; stroke-width: 1.2; stroke-linecap: round; }
.k-me { border-color: var(--accent); }
.k-leader { border-color: var(--warn); }
.k-other { border-color: var(--hint); opacity: .55; }
/* Подсветка по тапу в табло: выбранная линия выходит вперёд, остальные
   гаснут — иначе в комнате на десятерых график нечитаем. */
svg.dim .c-me, svg.dim .c-leader, svg.dim .c-other { opacity: .18; }
svg.dim path.lit { opacity: 1; stroke-width: 2.8; stroke: var(--accent); }
.pcard.lit { outline: 1.5px dashed var(--accent); }

/* Настройки комнаты: открывают раз в жизни, поэтому свёрнуты */
.room-title { font-weight: 600; font-size: 17px; }
/* Селектор по details.card, а не по .settings: такая же свёртка «Архив» есть
   на экране списка комнат, и помечена она должна быть так же — иначе один
   экран показывает, что блок открывается, а соседний нет. */
details.card > summary {
  cursor: pointer; list-style: none;
  /* Место справа — под шеврон. Он ставится абсолютно, а НЕ через flex:
     смена display у <summary> в старых WebView (Safari примерно до 14)
     ломала само раскрытие <details>, то есть под удар попадала бы работа
     свёртки, а не её вид. Ради значка так рисковать нечем. */
  position: relative; padding: 2px 22px 2px 0;
}
details.card > summary::-webkit-details-marker { display: none; }
.settings[open] summary { margin-bottom: 10px; }
/* Системный треугольник убран правилом выше, и замены ему не было: серая
   строка в карточке читалась обычной подписью, а не тем, что можно открыть.
   Поворот вешаем на [open] — состояние свёртки остаётся в одном месте. */
.chev { position: absolute; right: 0; top: 2px; color: var(--hint); transition: transform .15s; }
details[open] .chev { transform: rotate(180deg); }
.hr { height: 1px; background: var(--track); margin: 14px 0; }
.settings .btn.ghost { background: var(--bg); }

/* Реакции: единственный способ общения внутри комнаты */
.reacts { display: flex; gap: 6px; align-items: center; margin-top: 9px; flex-wrap: wrap; }
/* 7px по вертикали вместо 3px — это 34 px высоты вместо 26: по кнопке
   перестают промахиваться. До рекомендованных 44 не поднимаем осознанно:
   при border-radius 999px высота тянет за собой и горизонтальный запас,
   иначе пилюля превращается в кругляш, а четыре реакции с подписью
   «за сегодня» должны остаться одной строкой на 375 px — с переносом
   карточка участника вырастает на целую строку. */
.react {
  border: 1px solid var(--track); border-radius: 999px; padding: 7px 10px;
  font-size: 14px; line-height: 1.3; background: var(--bg); color: var(--fg); cursor: pointer;
}
.react.on { border-color: var(--accent); background: var(--card); }
.react span { font-size: 12px; color: var(--hint); margin-left: 2px; }
.react.on span { color: var(--accent); }
.react-got {
  font-size: 13px; background: var(--bg); border-radius: 999px; padding: 3px 10px;
}

.consent {
  background: var(--bg); border-radius: 10px; padding: 10px 12px;
  margin: 10px 0 2px; color: var(--hint); line-height: 1.4;
}
.consent b { color: var(--fg); }

/* --- фото и видео комнаты (docs/media-mockups.html, вариант В3) --- */

.media-card h3 { margin-bottom: 8px; }
.dayrow { margin-bottom: 10px; }
.dayrow:last-child { margin-bottom: 0; }
/* Капслок и разрядка, а не просто размер: рядом стоит заголовок карточки
   «Фото комнаты» (.card h3 — 13px тем же цветом), и без разницы в наборе
   «Сегодня» читалось вторым подзаголовком, а не меткой дня. */
.dayrow .cap {
  font-size: 11px; color: var(--hint); margin-bottom: 5px;
  text-transform: uppercase; letter-spacing: .05em;
}
/* overflow-x на строке дня, а не на всей карточке: иначе горизонтальный
   скролл одного дня утаскивал бы за собой соседние дни и заголовки. */
.dayrow .line { display: flex; gap: 7px; overflow-x: auto; padding-bottom: 2px; }
/* Класс вешает app.js, когда строка правда шире экрана и прокручена не до
   конца. Растворённый правый край — единственный признак, что справа есть
   ещё фото: полосы прокрутки в мобильном WebView не видно, а миниатюры
   ровно 72 px и почти всегда обрываются целым числом клеток, поэтому
   «обрезанная половинка» сама собой не появляется. */
.dayrow .line.has-more,
.cp-strip.has-more {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
}

.mthumb {
  position: relative; flex: none; border-radius: 10px; overflow: hidden;
  cursor: pointer; background: var(--track);
  display: flex; align-items: center; justify-content: center;
}
.dayrow .mthumb { width: 72px; height: 72px; }
/* Полоска в карточке участника — те же миниатюры, что и в общей ленте
   (см. room.html: row.photos отдаёт item той же формы), только мельче и
   без подписи автора — он и так назван в шапке карточки. */
.pc-strip { display: flex; gap: 6px; margin-top: 8px; }
.pc-strip .mthumb { width: 56px; height: 56px; border-radius: 8px; }

.mthumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Обводка отдельным слоем, а не border или box-shadow самой клетки: и фон,
   и inset-тень рисуются ПОД содержимым, а картинка лежит поверх на всю
   клетку и съела бы их. Без обводки тёмное фото на тёмной карточке теряет
   края и выглядит дырой в вёрстке. Серый нейтрален: на светлом снимке он
   темнее, на тёмном светлее, поэтому одна строка держит обе темы. */
.mthumb::before {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  border-radius: inherit; box-shadow: inset 0 0 0 1px rgba(128, 128, 128, .45);
}

/* has_thumb=false — у части видео Telegram не прислал превью вовсе;
   подделывать его на сервере нечем (см. /media/{id}/thumb), поэтому здесь
   всегда одна и та же полосатая заглушка с ▶. */
.mthumb:not([data-thumb="1"]) {
  background: repeating-linear-gradient(
    45deg, var(--track), var(--track) 6px, var(--card) 6px, var(--card) 12px
  );
}
.mthumb:not([data-thumb="1"])::after { content: "▶"; color: var(--hint); font-size: 20px; }

/* Бейдж сверху, а не снизу: внизу клетки уже лежит подпись автора
   (.day-author растянут от края до края), и в общей ленте длительность
   ложилась ровно поверх ника — на светлой теме читались оба текста
   вперемешку. */
.vbadge {
  position: absolute; left: 5px; top: 5px; z-index: 1;
  background: rgba(0, 0, 0, .62); color: #fff; border-radius: 999px;
  font-size: 10.5px; line-height: 1.5; padding: 1px 7px;
}
.day-author {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  background: linear-gradient(transparent, rgba(0, 0, 0, .65)); color: #fff;
  font-size: 11px; padding: 9px 5px 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Просмотрщик собирается и убирается кодом (app.js: openMediaViewer/
   closeMediaViewer), поэтому живёт в body, а не в #screen — тот же приём,
   что и у .toast: перерисовка экрана не должна утаскивать его за собой. */
.viewer-overlay {
  position: fixed; inset: 0; z-index: 30; background: #000;
  display: flex; flex-direction: column;
}
.v-top { display: flex; justify-content: space-between; align-items: center; padding: 12px 14px; color: #fff; }
.v-close {
  background: rgba(255, 255, 255, .15); border: 0; color: #fff; border-radius: 999px;
  width: 32px; height: 32px; font-size: 16px; cursor: pointer;
}
.v-media { position: relative; flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.v-img, .v-video { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Зоны листания создаются только для фото (app.js): у видео полоса
   перемотки оказывается посреди сцены, а не внизу — кадр 16:9 в
   вертикальном экране обрамлён чёрным, и никакой отступ снизу её не
   освободит. Отступ всё равно оставлен: он бережёт подпись от случайного
   тапа при листании. */
.v-nav { position: absolute; top: 0; bottom: 44px; width: 30%; cursor: pointer; }
.v-prev { left: 0; }
.v-next { right: 0; }
.v-spinner {
  width: 32px; height: 32px; border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, .25); border-top-color: #fff;
  animation: v-spin .8s linear infinite;
}
@keyframes v-spin { to { transform: rotate(360deg); } }
/* Отступ снизу с запасом под системную полосу: страница объявлена
   `viewport-fit=cover`, и без него кнопка «Удалить» упирается в
   home-indicator — нижняя часть тапа уходит системному жесту, а не нам. */
.v-bottom {
  padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  color: #fff; background: linear-gradient(transparent, rgba(0, 0, 0, .8));
}
.v-author { font-size: 13px; color: rgba(255, 255, 255, .75); }
.v-caption { font-size: 15px; margin-top: 4px; white-space: pre-wrap; word-break: break-word; }
.v-del {
  margin-top: 12px; background: rgba(255, 255, 255, .14); border: 0; color: #ff9c9c;
  border-radius: 12px; padding: 9px 14px; font-size: 14px; cursor: pointer; width: 100%;
}
