/*
  components.css — общие примитивы интерфейса (FE-02: ни одного литерала цвета).

  ЗАЧЕМ ОТДЕЛЬНЫЙ ФАЙЛ. До сих пор каждый фрагмент рисовал себя сам, и «карточка»
  на одной странице выглядела не так, как на другой. Здесь — единые `.card`, `.btn`,
  `.chip`, `.badge`, `.icon`, `.field`, `.state`, `.sheet`, `.tabbar`, `.skeleton`,
  `.switch`, `.segmented`, `.avatar`; страницы только собирают их.

  ОТКУДА ЗНАЧЕНИЯ. Цвета — только `var(--c-…)` из `themes.css`; форма, плотность и
  типографика — `var(--radius-…)`, `var(--space-…)`, `var(--fs-…)` из
  `theme-tokens.css` (масштаб ОДИН на все темы: палитра его не переопределяет, t148).
  Литералов цвета здесь нет и быть не может — это проверяет `test_frontend_themes.py`.

  СОСТОЯНИЯ. У каждой страницы/панели три исхода, и все — текстом, а не пустым
  экраном: `data-state="loading"` (скелет), `"empty"` (объяснение + действие),
  `"error"` (человеческий текст отказа). Имя состояния — атрибут, поэтому опыт
  может его проверить.

  МОБИЛЬНЫЙ ПЕРВЫМ: тап-зоны ≥ `--tap-min`, safe-area снизу, `clamp()` для
  типографики, `prefers-reduced-motion` гасит анимации.
*/

/* ── фокус и базовые тексты ──────────────────────────────────────────────── */

:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

/* `hidden` сильнее любого display у компонента: иначе `.card{display:flex}` /
   `.btn{display:inline-flex}` перебивают атрибут, и «скрытая» карточка события
   остаётся видимой (найдено на живом стенде). */
[hidden] {
    display: none !important;
}

::selection {
    background: var(--c-selection);
}

.subtitle {
    display: block;
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
}

.title-text {
    display: block;
    color: var(--c-text);
    font-family: var(--font-display);
    font-size: clamp(var(--fs-lg), 4.6vw, var(--fs-2xl));
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
}

.base-text {
    display: block;
    color: var(--c-text-2);
    font-size: var(--fs-base);
    line-height: var(--lh-normal);
}

.section-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
}

/* ── карточка ────────────────────────────────────────────────────────────── */

.card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--card-pad);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-card);
    background: var(--c-surface);
    box-shadow: var(--shadow-card);
}

.card--flush {
    padding: 0;
    overflow: hidden;
}

.card--tinted {
    background: var(--c-tip-bg);
    border-color: var(--c-tip-border);
    box-shadow: none;
}

.card--accent {
    background: var(--c-accent-soft);
    border-color: var(--c-border-focus);
}

/* ── кнопка ──────────────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: var(--tap-min);
    padding: var(--space-2) var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-btn);
    background: var(--c-surface-2);
    color: var(--c-text);
    font: inherit;
    font-weight: var(--fw-semibold);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: transform var(--dur-fast) var(--ease), background var(--dur) var(--ease),
        opacity var(--dur) var(--ease);
}

.btn:active {
    transform: scale(0.98);
}

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: default;
    transform: none;
}

.btn--primary {
    border-color: transparent;
    background: var(--c-gradient-cta);
    color: var(--c-text-on-gradient);
    box-shadow: var(--shadow-glow);
}

.btn--secondary {
    border-color: var(--c-border);
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
}

.btn--ghost {
    border-color: var(--c-border);
    background: transparent;
    color: var(--c-text-2);
}

.btn--danger {
    border-color: var(--c-danger-border);
    background: var(--c-danger-bg);
    color: var(--c-text-danger);
}

.btn--block {
    width: 100%;
}

.btn--sm {
    min-height: auto;
    padding: var(--space-1) var(--space-3);
    font-size: var(--fs-sm);
}

/* ── чип, бейдж, иконка ──────────────────────────────────────────────────── */

.chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: var(--tap-min);
    padding: var(--space-1) var(--space-4);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-chip);
    background: var(--c-surface);
    color: var(--c-text-2);
    font: inherit;
    font-size: var(--fs-base);
    text-align: center;
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.chip[aria-pressed="true"],
.chip--active {
    border-color: transparent;
    background: var(--c-accent);
    color: var(--c-text-on-accent);
    font-weight: var(--fw-semibold);
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    border-radius: var(--radius-chip);
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
}

.badge--dot::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--c-success);
}

.badge--muted {
    background: var(--c-surface-2);
    color: var(--c-text-muted);
}

.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-pill);
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
    flex: none;
}

.icon svg {
    width: var(--icon-sm);
    height: var(--icon-sm);
}

.icon--bubble {
    border: 1px solid var(--c-border);
    background: var(--c-surface-2);
}

.avatar {
    width: 48px;
    height: 48px;
    border-radius: var(--radius-pill);
    object-fit: cover;
    background: var(--c-surface-2);
    flex: none;
}

.avatar--lg {
    width: 72px;
    height: 72px;
}

.avatar--placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--c-text-accent);
    font-weight: var(--fw-bold);
    text-transform: uppercase;
}

/* ── поле ввода и переключатель ──────────────────────────────────────────── */

.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.field__label {
    color: var(--c-text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
}

.field__input,
.input-like,
.insta-input {
    width: 100%;
    min-height: var(--tap-min);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-field);
    background: var(--c-bg-elev);
    color: var(--c-text);
    font: inherit;
}

.field__input::placeholder {
    color: var(--c-text-muted);
}

.field__input:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 1px;
}

/* ── мягкая проверка города (t164) ───────────────────────────────────────────
   «Возможно, вы имели в виду: <Москва>?» + «Всё равно сохранить». Это ПОДСКАЗКА, а не
   отказ: опечатка не запирает анкету. Кнопки вариантов — не меньше тап-зоны, чтобы
   человек не промахивался по ним пальцем. */

.city-suggest {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-surface-2);
}

.city-suggest__title {
    margin: 0;
    color: var(--c-text-2);
    font-size: var(--fs-sm);
    line-height: var(--lh-normal);
}

.city-suggest__options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.city-suggest__option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tap-min);
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--c-border-focus);
    border-radius: var(--radius-chip);
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    cursor: pointer;
}

.city-suggest__option:hover {
    background: var(--c-surface-3);
}

.city-suggest__option:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

.city-suggest__keep {
    align-self: flex-start;
}

/* ── карусель готовых обложек (t157) ─────────────────────────────────────────
   Расположение — как в legacy: горизонтальная лента миниатюр, выбранная обведена
   рамкой. Скролл живёт ВНУТРИ ленты (страница не «уезжает»), снимок прилипает к краю.
   Размер миниатюры — 16:9, 104×72: обложка узнаётся, а лента не занимает пол-экрана. */

.cover-picker {
    display: flex;
    gap: var(--space-2);
    padding: var(--space-1) 2px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
}

.cover-picker::-webkit-scrollbar {
    display: none;
}

.cover-option {
    position: relative;
    flex: 0 0 auto;
    width: 104px;
    height: 72px;
    padding: 0;
    border: 2px solid var(--c-border);
    border-radius: var(--radius-sm);
    background: var(--c-surface-2);
    overflow: hidden;
    cursor: pointer;
    scroll-snap-align: start;
    transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.cover-option img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cover-option:hover {
    border-color: var(--c-text-muted);
}

/* Выбор виден не только рамкой: подпись и галочка читаются и без цвета. */
.cover-option[aria-checked="true"] {
    border-color: var(--c-border-focus);
    box-shadow: 0 0 0 2px var(--c-accent-soft);
}

.cover-option[aria-checked="true"]::after {
    content: "✓";
    position: absolute;
    top: 4px;
    right: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: var(--radius-pill);
    background: var(--c-accent);
    color: var(--c-text-on-accent);
    font-size: var(--fs-caption);
    font-weight: var(--fw-bold);
    line-height: 1;
}

.cover-option:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

.cover-option__caption {
    position: absolute;
    inset: auto 0 0 0;
    padding: 2px var(--space-1);
    background: var(--c-bg-elev);
    color: var(--c-text-2);
    font-size: var(--fs-caption);
    line-height: var(--lh-tight);
    text-align: center;
}

.switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 48px;
    height: 28px;
    flex: none;
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-pill);
    background: var(--c-surface-3);
    cursor: pointer;
    transition: background var(--dur) var(--ease);
}

.switch::after {
    content: "";
    width: 22px;
    height: 22px;
    margin-left: 2px;
    border-radius: var(--radius-pill);
    background: var(--c-bg-elev);
    box-shadow: var(--shadow-card);
    transition: transform var(--dur) var(--ease-spring);
}

.switch:checked {
    border-color: transparent;
    background: var(--c-accent);
}

.switch:checked::after {
    transform: translateX(20px);
}

.segmented {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-chip);
    background: var(--c-surface-2);
}

.segmented__item {
    min-height: 36px;
    padding: var(--space-1) var(--space-3);
    border: 0;
    border-radius: var(--radius-chip);
    background: transparent;
    color: var(--c-text-2);
    font: inherit;
    font-size: var(--fs-sm);
    cursor: pointer;
}

.segmented__item[aria-pressed="true"] {
    background: var(--c-accent);
    color: var(--c-text-on-accent);
    font-weight: var(--fw-semibold);
}

/* ── список, полоса, разделитель ─────────────────────────────────────────── */

.list-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--tap-min);
    padding: var(--space-2) 0;
    color: var(--c-text);
    text-decoration: none;
}

.list-row + .list-row {
    border-top: 1px solid var(--c-border);
}

.list-row__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1;
}

.list-row__title {
    font-size: var(--fs-base);
    font-weight: var(--fw-semibold);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.list-row__meta {
    color: var(--c-text-muted);
    font-size: var(--fs-sm);
}

.divider {
    width: 100%;
    height: 1px;
    border: 0;
    background: var(--c-border);
}

.progress {
    width: 100%;
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--c-surface-3);
    overflow: hidden;
}

.progress__fill {
    height: 100%;
    border-radius: inherit;
    background: var(--c-gradient-cta);
    transition: width var(--dur-slow) var(--ease);
}

/* ── состояния страницы/панели ───────────────────────────────────────────── */

.state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-6) var(--space-4);
    color: var(--c-text-2);
    font-size: var(--fs-base);
    line-height: var(--lh-normal);
    text-align: center;
}

.state[hidden] {
    display: none;
}

.state__title {
    color: var(--c-text);
    font-size: var(--fs-md);
    font-weight: var(--fw-semibold);
}

.state__action {
    margin-top: var(--space-1);
}

.state[data-state="error"] {
    color: var(--c-text-danger);
}

.state[data-state="error"] .state__title {
    color: var(--c-text-danger);
}

.state[data-state="empty"] {
    color: var(--c-text-muted);
}

.skeleton {
    position: relative;
    overflow: hidden;
    min-height: 14px;
    border-radius: var(--radius-sm);
    background: var(--c-skeleton);
}

.skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, var(--c-skeleton-shine), transparent);
    transform: translateX(-100%);
    animation: skeleton-slide 1.2s infinite;
}

.skeleton--card {
    height: 96px;
    border-radius: var(--radius-card);
}

@keyframes skeleton-slide {
    to {
        transform: translateX(100%);
    }
}

/* ── нижняя навигация ────────────────────────────────────────────────────── */

.tabbar {
    position: fixed;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    width: min(100%, var(--content-max));
    z-index: var(--z-nav);
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    padding-bottom: calc(var(--space-1) + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--c-nav-border);
    background: var(--c-nav-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

.tab {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: var(--tap-min);
    min-height: var(--tap-min);
    padding: var(--space-1);
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--c-nav-item);
    font: inherit;
    font-size: var(--fs-caption);
    cursor: pointer;
    transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.tab__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--icon);
    height: var(--icon);
    border-radius: var(--radius-sm);
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.tab[aria-current="page"] {
    color: var(--c-nav-item-active);
    font-weight: var(--fw-semibold);
}

.tab[aria-current="page"] .tab__icon {
    background: var(--c-nav-active-bg);
}

/* Форма активного состояния: индикатор, а не только цвет (DESIGN_BRIEF §5.1). */
.tab[aria-current="page"]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 28%;
    right: 28%;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: var(--c-gradient-cta);
}

/* ── полноэкранная панель (общение/участники/настройки) ──────────────────── */

.sheet {
    position: fixed;
    inset: 0;
    z-index: var(--z-sheet);
    display: flex;
    flex-direction: column;
    background: var(--c-bg);
}

.sheet[hidden] {
    display: none;
}

.sheet__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--gutter);
    border-bottom: 1px solid var(--c-border);
    background: var(--c-bg-elev);
}

.sheet__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(var(--fs-lg), 4.6vw, var(--fs-xl));
    font-weight: var(--fw-bold);
}

.sheet__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    flex: 1;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: var(--gutter);
    padding-bottom: calc(var(--space-8) + env(safe-area-inset-bottom, 0px));
}

.sheet__section {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    min-height: var(--tap-min);
}

.chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* ── виджет оформления по наброску `new/wiget_colors_example.html` (21.10.2026) ──
   Кружки палитр в шесть колонок, переключатель схемы из трёх иконок в шапке,
   карточка деталей с живым превью чата. Цвет кружка задаёт `themes.css` по
   `data-palette` (единственный файл с литералами), здесь только геометрия. */
.theme-widget {
    gap: var(--space-4);
}

.theme-widget__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
}

.theme-modes {
    display: flex;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-pill);
    background: var(--c-bg);
}

.theme-mode {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--c-text-muted);
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

/* Видимая кнопка 32 px, но зона нажатия — 44 px (правило `--tap-min`): */
.theme-mode::before {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: 50%;
}

.theme-mode svg {
    width: 16px;
    height: 16px;
    fill: currentColor;
}

.theme-mode:hover {
    color: var(--c-text);
}

.theme-mode[aria-pressed="true"] {
    background: var(--c-surface-3);
    color: var(--c-text);
    box-shadow: 0 2px 5px var(--c-shadow-color);
}

.theme-mode:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

.theme-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--space-3);
    justify-items: center;
}

.palette-swatch {
    position: relative;
    width: min(44px, 100%);
    aspect-ratio: 1 / 1;
    padding: 0;
    border: 0;
    border-radius: 50%;
    cursor: pointer;
    transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.palette-swatch:hover {
    transform: scale(1.1);
}

.palette-swatch[aria-pressed="true"] {
    box-shadow: 0 0 0 3px var(--c-surface), 0 0 0 5px var(--c-text);
}

/* Галочка активной палитры — двумя границами, без картинки и лишнего цвета. */
.palette-swatch[aria-pressed="true"]::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 14px;
    margin: -9px 0 0 -4px;
    border-right: 2px solid var(--c-text);
    border-bottom: 2px solid var(--c-text);
    transform: rotate(45deg);
    filter: drop-shadow(0 1px 2px var(--c-shadow-color));
}

.palette-swatch:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 3px;
}

/* t113: закрытая тема — видна, но не выбирается; открытая для покупки — рамка-подсказка. */
.palette-swatch--locked {
    opacity: 0.45;
    cursor: not-allowed;
}

.palette-swatch--locked:hover {
    transform: none;
}

.palette-swatch--locked::before {
    content: "🔒";
    position: absolute;
    right: -2px;
    bottom: -2px;
    font-size: 11px;
    line-height: 1;
}

.palette-swatch--buy {
    opacity: 0.85;
}

.theme-details {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-bg);
}

.theme-details__name {
    margin: 0;
    color: var(--c-text);
    font-size: var(--fs-md);
    font-weight: var(--fw-semibold);
}

.theme-details__mood {
    margin: 0;
    color: var(--c-text-muted);
    font-size: var(--fs-sm);
    line-height: var(--lh-normal);
}

/* t115: действие выбранной темы — установить или купить. */
.theme-details__actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.theme-details__note {
    margin: 0;
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
    text-align: center;
}

.theme-preview {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3);
    overflow: hidden;
    border-radius: var(--radius-sm);
    background: var(--c-surface);
}

/* Декоративное свечение в углу — акцентом выбранной (примеряемой) темы. */
.theme-preview::before {
    content: "";
    position: absolute;
    top: -20px;
    right: -20px;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: var(--c-accent);
    filter: blur(30px);
    opacity: 0.35;
    pointer-events: none;
}

/* В превью — настоящие компоненты приложения (.btn/.card), а не отдельные муляжи.
   Палитра выбранной темы приходит на этот контейнер инлайн-токенами из panels.js. */
.theme-showcase {
    position: relative;
    z-index: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
}

.theme-showcase .btn {
    flex: 1 1 auto;
    min-width: 0;
}

.theme-showcase__card {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    box-shadow: none;
}

.theme-showcase__title {
    color: var(--c-text);
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
}

.theme-showcase__text {
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
}

/* ── виджеты участников (20.10.2026, по расположению legacy) ──────────────────
   Два виджета В РЯД: «Участники — 209 / +3 в этом месяце» и «Средний возраст —
   26 / от 18 до 33». Сетка 1fr 1fr держит их одинаковой ширины на любом телефоне
   (360…430 px), `min-height` — одинаковой высоты; числа приходят из `/api/get_users`
   (`total_count`, `joint_last_month`, `average_age`, `min_age`, `max_age`). */

.users-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2);
}

/* Пояснение к числам, когда включён фильтр: источник считает статистику по всем (t156). */
.users-stats__note {
    grid-column: 1 / -1;
    margin: 0;
}

.stat {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-height: 88px;
    padding: var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-surface);
    box-shadow: var(--shadow-card);
}

.stat__label {
    color: var(--c-text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
}

.stat__value {
    color: var(--c-text);
    font-size: var(--fs-2xl);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
}

.stat__note {
    overflow: hidden;
    color: var(--c-text-2);
    font-size: var(--fs-caption);
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── «Общение»: категории и карточки чатов ───────────────────────────────────
   Запрос владельца 20.10.2026: «мой город / другие города» + крупная обложка.
   Геометрия — только из токенов (--radius-*, --space-*, --fs-*): одна и та же у
   всех тем (инвариант шкалы, t148), поэтому переключение темы не двигает карточки.
   Карточка одноколоночная: горизонтальной прокрутки нет, на 360…430 px она
   занимает всю ширину листа. */

.chat-tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-chip);
    background: var(--c-surface-2);
}

.chat-tabs__item {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    min-width: 0;
    min-height: var(--tap-min);
    padding: var(--space-1) var(--space-2);
    border: 0;
    border-radius: var(--radius-chip);
    background: transparent;
    color: var(--c-text-2);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.chat-tabs__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chat-tabs__count {
    flex: none;
    font-size: var(--fs-caption);
    font-weight: var(--fw-regular);
    opacity: 0.85;
}

.chat-tabs__item[aria-selected="true"] {
    background: var(--c-accent);
    color: var(--c-text-on-accent);
    font-weight: var(--fw-semibold);
}

.chats-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.chat-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
}

.chat-group + .chat-group {
    margin-top: var(--space-3);
}

.chat-group__title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2);
    margin: 0;
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
}

.chat-group__city {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chat-group__count {
    flex: none;
    color: var(--c-text-2);
    font-weight: var(--fw-medium);
    letter-spacing: normal;
    text-transform: none;
}

/* ── карусель карточек чата (t158) ───────────────────────────────────────────
   Расположение и размеры взяты из шаблона владельца `new/chat_list.html`:
   лента с `scroll-snap` и скрытым скроллбаром, карточка 80 % ширины ленты,
   квадратная обложка (1:1) с градиентом в тело карточки, бейдж активности в правом
   верхнем углу, кнопка входа во всю ширину (padding 12 px, радиус 14 px, кегль 14,
   вес 700), точки-индикаторы (8 px, активная — 24 px). ЦВЕТА, радиусы и отступы —
   наши токены: палитра шаблона не копируется. Тап-зоны не меньше --tap-min (44 px):
   кнопка входа 44, точки 36×44 (сама точка 8 px внутри). */

.chat-carousel {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}

.chat-rail {
    display: flex;
    gap: var(--space-4);
    /* Поля ленты — по шаблону (10/16/20), но без двойных: лист уже даёт --gutter. */
    padding: var(--space-2) var(--space-1) var(--space-2);
    overflow-x: auto;
    /* Горизонтальный свайп остаётся в ленте: страница не «уезжает» вместе с ней. */
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.chat-rail::-webkit-scrollbar {
    display: none;
}

.chat-rail:focus-visible {
    border-radius: var(--radius-md);
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

.chat-rail > .chat-card {
    /* Шаблон: карточка занимает 80 % ленты — виден край следующей. */
    flex: 0 0 80%;
    scroll-snap-align: center;
}

.chat-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--c-border);
    /* Шаблон: радиус 24 px; ближайший токен — --radius-lg (22). */
    border-radius: var(--radius-lg);
    background: var(--c-surface);
    box-shadow: var(--shadow-card);
}

.chat-card__cover {
    position: relative;
    display: block;
    width: 100%;
    /* Шаблон: идеальный квадрат. */
    aspect-ratio: 1 / 1;
    background: var(--c-surface-2);
}

.chat-card__cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Градиент снизу обложки: картинка «перетекает» в тело карточки (шаблон). */
.chat-card__cover::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 50%;
    background: linear-gradient(to top, var(--c-surface) 0%, transparent 100%);
    pointer-events: none;
}

.chat-card__activity {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-chip);
    background: var(--c-bg-elev);
    color: var(--c-text-2);
    font-size: var(--fs-caption);
    font-weight: var(--fw-bold);
    white-space: nowrap;
}

.chat-card__activity[data-hot="true"] {
    border-color: transparent;
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
}

.chat-card__body {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
    /* Шаблон: тело поднимается на градиент и прижимает кнопку к низу. */
    margin-top: calc(-1 * var(--space-3));
    padding: 0 var(--space-4) var(--space-4);
}

.chat-card__name {
    margin: 0 0 var(--space-1);
    color: var(--c-text);
    font-size: var(--fs-lg);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
    overflow-wrap: anywhere;
}

.chat-card__about {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    margin: 0 0 var(--space-3);
    color: var(--c-text-muted);
    font-size: var(--fs-sm);
    line-height: var(--lh-normal);
    overflow-wrap: anywhere;
}

.chat-card__foot {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: auto;
}

.chat-card__foot > * {
    flex: 1;
    min-width: 0;
}

/* Кнопка входа: размеры из шаблона (100 %, padding 12, радиус 14→--radius-btn,
   кегль 14, вес 700), тап-зона — --tap-min. Цвета — токены (btn--primary). */
.chat-card__cta {
    width: 100%;
    min-height: var(--tap-min);
    margin-top: auto;
    padding: var(--space-3);
    border-radius: var(--radius-btn);
    font-size: var(--fs-base);
    font-weight: var(--fw-bold);
}

/* ── лоадер «Общения» (t219) ─────────────────────────────────────────────────
   Пока справочник чатов едет, на месте ленты показываем скелетон карточки:
   обложку 1:1 и строки текста той же ширины/высоты, что у настоящей карточки.
   Это не отдельное «серое пятно», а форма будущего списка — перерисовка после
   ответа не двигает ни одну карточку. Слой декоративный: имя состояния и текст
   «Загружаем чаты…» живут в `#chats-state` (role=status ставит `setState`).
   Анимация блика — общий `.skeleton`; `prefers-reduced-motion` её уже выключает. */
.chat-loader {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.chat-loader[hidden] {
    display: none;
}

.chat-loader__rail {
    padding: var(--space-2) var(--space-1) 0;
}

.chat-card--skeleton {
    pointer-events: none;
}

.chat-loader__cover {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: 0;
}

/* Тело скелетона повторяет ритм `.chat-card__body`, но без «подъезда» на обложку:
   у заглушки нет картинки, поэтому отрицательный margin только срезал бы строки. */
.chat-loader__body {
    margin-top: 0;
    padding: var(--space-3) var(--space-4) var(--space-4);
    gap: var(--space-2);
}

.chat-loader__line {
    width: 100%;
    height: 12px;
    border-radius: var(--radius-xs);
}

.chat-loader__line--name {
    width: 62%;
    height: 18px;
}

.chat-loader__line--short {
    width: 38%;
}

.chat-loader__cta {
    width: 100%;
    height: var(--tap-min);
    margin-top: var(--space-2);
    border-radius: var(--radius-btn);
}

/* ── точки-индикаторы карусели ────────────────────────────────────────────────
   Сама точка 8 px (активная 24 px), кнопка вокруг неё — 36×44: попасть пальцем
   можно, а ряд остаётся низким. Для чтения программы точка — кнопка с названием
   чата; текущая помечена `aria-current`. */

.chat-dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
}

.chat-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: var(--tap-min);
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    cursor: pointer;
}

.chat-dot::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--c-surface-3);
    transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}

.chat-dot[aria-current="true"]::before {
    width: 24px;
    border-radius: var(--radius-xs);
    background: var(--c-accent);
}

.chat-dot:hover::before {
    background: var(--c-text-muted);
}

.chat-dot[aria-current="true"]:hover::before {
    background: var(--c-accent);
}

.chat-dot:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: -2px;
}

/* ── мобильная адаптация и движение ──────────────────────────────────────── */

@media (min-width: 560px) {
    .sheet__body,
    .sheet__bar {
        max-width: var(--content-max);
        margin: 0 auto;
        width: 100%;
    }
}

@media (max-width: 360px) {
    .tab {
        font-size: 10px;
    }

    /* Шесть кружков остаются в ряд: уменьшаем промежутки, а не прячем палитры. */
    .theme-grid {
        gap: var(--space-2);
    }
}

@media (prefers-reduced-motion: reduce) {
    .skeleton::after {
        animation: none;
    }

    .btn,
    .tab,
    .tab__icon,
    .progress__fill,
    .switch::after,
    .chip {
        transition: none;
    }

    .btn:active {
        transform: none;
    }
}


/* ── карточка участника (t147, расположение legacy) ──────────────────────────
   Фото владельца: аватар слева, справа ник и @тэг, под ними «пол · возраст»,
   иконка верификации — в правом верхнем углу аватара, сердечко-любимка — справа по
   центру. Высота карточки — 82 px при телефоне 390 px (ориентир legacy 76–84) и
   ОДНА у всех: `min-height` плюс строки в одну линию с многоточием, поэтому длинное
   имя не растягивает карточку. Разделитель — `gap` списка, а не border-bottom.
   Стили legacy не копируются: цвета, радиусы и отступы — наши токены, поэтому
   переключение темы не двигает ни одну карточку. */

.users-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* ── фильтры списка участников (t156, возраст — поповер с t163) ───────────────
   Расположение — из обновлённого шаблона владельца `new/member_list.html`: чипы и в том
   же ряду кнопка «Возраст», раскрывающая поповер. На узком экране (360 px) ряд
   ПЕРЕНОСИТСЯ, а не прячется за горизонтальной прокруткой: фильтр, уехавший за край,
   человек не находит. Размеры — наши: чип и кнопка опираются на примитив `.chip`
   (тап-зона 44), поля возраста тоже 44. */

.member-filters {
    /* Точка отсчёта для поповера: он раскрывается под рядом чипов, а не «где-то». */
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.member-chips {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    scrollbar-width: none;
}

.member-chips::-webkit-scrollbar {
    display: none;
}

.member-chip {
    flex: none;
    min-height: var(--tap-min);
    padding: var(--space-1) var(--space-3);
    font-size: var(--fs-sm);
    white-space: nowrap;
}

.chip__count {
    color: inherit;
    font-weight: var(--fw-regular);
    opacity: 0.7;
}

/* Кнопка возраста: иконка-воронка + подпись («Возраст» / «18–30»). Активный фильтр
   виден и цветом (как у выбранного чипа), и текстом диапазона — не только цветом. */
.member-chip--age {
    gap: var(--space-1);
}

.member-chip--age[data-active="true"] {
    border-color: var(--c-border-focus);
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
}

.member-chip__icon {
    flex: none;
    width: 12px;
    height: 12px;
    opacity: 0.85;
}

/* ── поповер возраста ───────────────────────────────────────────────────────
   Абсолютный, но с `max-width: 100%` и левым краем по контейнеру: на 360 px он не
   вылезает за экран и не обрезается (проверено замером). `z-index` — выше списка,
   но ниже листов/панелей. */

.member-age-popover {
    position: absolute;
    top: calc(100% + var(--space-1));
    left: 0;
    z-index: 5;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    width: min(264px, 100%);
    max-width: 100%;
    padding: var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-surface-2);
    box-shadow: var(--shadow-card);
}

.member-age-popover[hidden] {
    display: none;
}

.member-age-popover__title {
    margin: 0;
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
}

.member-age-popover__range {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
}

.member-age-popover__field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    flex: 1;
    min-width: 0;
}

.member-age-popover__label {
    color: var(--c-text-muted);
    font-size: var(--fs-caption);
}

.member-age-popover__input {
    width: 100%;
    min-height: var(--tap-min);
    padding: 0 var(--space-2);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-sm);
    background: var(--c-surface);
    color: var(--c-text);
    font: inherit;
    font-size: var(--fs-base);
}

.member-age-popover__input:focus-visible {
    border-color: var(--c-border-focus);
    outline: 2px solid var(--c-border-focus);
    outline-offset: -2px;
}

.member-age-popover__dash {
    padding-bottom: var(--space-3);
    color: var(--c-text-muted);
}

.member-age-popover__actions {
    display: flex;
    gap: var(--space-2);
}

.member-age-popover__actions > * {
    flex: 1;
    min-width: 0;
}

/* ── строка участника ────────────────────────────────────────────────────────
   `82 px` — ВЫСОТА ОБЫЧНОЙ строки, а не потолок: длинный ник или тэг переносится и
   карточка становится выше. Многоточия здесь нет намеренно (t156): «Temnodush /
   👾Чивапчич» должен читаться целиком, а не угадываться. */

.person {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 82px;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-surface);
    transition: border-color var(--dur) var(--ease);
}

.person:hover {
    border-color: var(--c-border-focus);
}

/* Ссылка на профиль — левая часть карточки; сердечко остаётся соседней кнопкой. */
.person__link {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex: 1 1 auto;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}

.person__link:focus-visible {
    border-radius: var(--radius-sm);
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

/* Обёртка нужна ради угла: значок верификации лежит ПОВЕРХ аватара. */
.person__avatar-wrap {
    position: relative;
    flex: none;
    width: 48px;
    height: 48px;
}

.person__avatar {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--c-surface-2);
    object-fit: cover;
}

/* Кружок верификации по краю аватара (t156) — на месте онлайн-точки из шаблона.
   У «нет верификации» кружка нет вовсе: пустой круг читался бы как «офлайн». */
.person__verify {
    position: absolute;
    right: -3px;
    bottom: -3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border: 2px solid var(--c-surface);
    border-radius: var(--radius-pill);
    background: var(--c-bg-elev);
    line-height: 0;
}

.person__verify img {
    display: block;
    width: 12px;
    height: 12px;
}

.person__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 auto;
}

.person__line {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-2);
    min-width: 0;
}

.person__name {
    color: var(--c-text);
    /* Владелец 21.10.2026: ник — крупнее и ЖИРНЫЙ, остальные факты — обычным
       начертанием. 18 px — ближайший токен к просьбе «сделай больше»; было 16. */
    font-size: var(--fs-lg);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
    overflow-wrap: anywhere;
}

/* Тэг — не логин: без `@`, пилюлей рядом с ником (t156). Переносится, не обрезается. */
.person__tag {
    max-width: 100%;
    padding: 1px var(--space-2);
    border: 1px solid var(--c-border-focus);
    border-radius: var(--radius-chip);
    background: var(--c-accent-soft);
    color: var(--c-text-accent);
    font-size: var(--fs-sm);
    line-height: var(--lh-normal);
    overflow-wrap: anywhere;
}

.person__self {
    flex: none;
    color: var(--c-text-accent);
    font-size: var(--fs-caption);
}

.person__facts {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 3px;
    color: var(--c-text-muted);
    /* 14 px и нормальное начертание: строка «мужской · 27 лет» больше не мелкая;
       ник остаётся единственным жирным элементом карточки. */
    font-family: var(--font-sans);
    font-size: var(--fs-base);
    font-weight: var(--fw-regular);
    line-height: var(--lh-normal);
    overflow-wrap: anywhere;
}

/* Знак пола идёт первым в строке фактов и не должен отрываться от слова «мужской»:
   поэтому иконка и слово живут в одной строке, а переносится уже весь блок целиком
   (строка короткая). Размер значка поднят вместе с текстом — 16 px вместо 14. */
.person__sex {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 16px;
    height: 16px;
}

.person__sex svg {
    display: block;
    width: 16px;
    height: 16px;
}

.person__sex--male {
    color: var(--c-gender-male);
}

.person__sex--female {
    color: var(--c-gender-female);
}

/* ── любимки: сердце без внешней обводки и heart-pop (t179 → t219) ─────────────
   Владелец 21.10.2026: сердечко «не нажато» выглядело квадратом — фигура занимала
   весь свой 19×16 viewBox, и stroke срезался краями бокса. Теперь:
   * фигура 24×24 с полями (2…22 px) — у обводки есть место со всех сторон;
   * у кнопки НЕТ рамки и подложки: рисуется только само сердце — внутренняя
     обводка в покое и заливка в избранном, без «внешнего» контура;
   * иконка 20 px в тап-зоне 44×44: значку не тесно, палец не промахивается.
   Состояние читается по `aria-pressed` и меняется CSS, второй картинки нет.
   Нажатие — `is-pop`: 1 → 1.22 → 0.96 → 1 за 0.36 s; reduced-motion отключает. */
.person__heart {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--tap-min);
    height: var(--tap-min);
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--c-text-muted);
    line-height: 1;
    cursor: pointer;
    transition: color var(--dur) var(--ease);
}

.person__heart:hover {
    color: var(--c-text-accent);
}

.person__heart svg {
    display: block;
    width: 20px;
    height: 20px;
    overflow: visible;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: fill var(--dur) var(--ease), stroke var(--dur) var(--ease);
}

.person__heart[aria-pressed="true"] {
    color: var(--c-text-accent);
}

.person__heart[aria-pressed="true"] svg {
    fill: currentColor;
    stroke: none;
}

.person__heart:focus-visible {
    outline: 2px solid var(--c-border-focus);
    outline-offset: 2px;
}

.person__heart:disabled {
    opacity: 0.5;
    cursor: progress;
}

/* Кнопка «В любимки» на чужом профиле ведёт себя так же: обводка → заливка + «поп». */
.profile-action[aria-pressed="false"] svg.profile-action__icon {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.4;
}

.profile-action[aria-pressed="true"] svg.profile-action__icon {
    fill: currentColor;
    stroke: none;
}

@keyframes heart-pop {
    0% {
        transform: scale(1);
    }
    40% {
        transform: scale(1.22);
    }
    70% {
        transform: scale(0.96);
    }
    100% {
        transform: scale(1);
    }
}

.person__heart.is-pop,
.profile-action.is-pop {
    animation: heart-pop 0.36s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .person__heart.is-pop,
    .profile-action.is-pop {
        animation: none;
    }
}

/* «О себе» переехало в app.css (t149): там же спойлер и виджет уровня. */
