/* ─────────────────────────────────────────────────────────────────────────
   Layout & components
   ───────────────────────────────────────────────────────────────────────── */

/* ── Shell ─────────────────────────────────────────────────────────────── */
.app {
  min-height: 100dvh;
  display: grid;
  /* minmax(0, …) lets the column shrink below its content's max-content width,
     which is what keeps a wide table from stretching the whole page. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
}
.main {
  width: 100%;
  min-width: 0;
  max-width: 1240px;
  margin-inline: auto;
  padding: 4px var(--pad) calc(var(--nav-h) + 34px + env(safe-area-inset-bottom));
}

/* ── Top bar ───────────────────────────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 40;
  padding-top: env(safe-area-inset-top);
  background: color-mix(in srgb, var(--bg) 68%, transparent);
  backdrop-filter: blur(var(--blur)) saturate(1.5);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(1.5);
  border-bottom: 1px solid var(--line);
}
@supports not (backdrop-filter: blur(2px)) { .topbar { background: var(--bg); } }
.topbar-in {
  max-width: 1240px; margin-inline: auto; min-width: 0;
  min-height: 56px; padding: 8px var(--pad);
  display: flex; align-items: center; gap: 10px;
}
.brand { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1; }
.brand-logo {
  width: 34px; height: 34px; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center; font-size: var(--fs-icon-sm);
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 45%, #a855f7));
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 40%, transparent);
  overflow: hidden;
}
.brand-logo img { width: 100%; height: 100%; object-fit: cover; }
/* A drawn ball is its own shape — it needs no tile behind it. */
.brand-logo.plain { background: none; box-shadow: none; border-radius: 0; color: var(--accent); }
.brand-logo.plain svg, .logo-svg svg { width: 100%; height: 100%; display: block; }
.logo-svg { width: 100%; height: 100%; }
.brand { text-align: left; }
.brand-txt { min-width: 0; }
.brand-name { font-weight: 680; font-size: var(--fs-md); line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand-sub { font-size: var(--fs-2xs); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.iconbtn {
  position: relative;
  width: 38px; height: 38px; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center; font-size: var(--fs-icon-sm); color: var(--text-2);
  border: 1px solid transparent;
  transition: background var(--t-fast), color var(--t-fast), transform var(--t-fast) var(--spring), border-color var(--t-fast);
}
.iconbtn:hover { background: var(--surface-2); color: var(--text); }
.iconbtn:active { transform: scale(.9); }
.iconbtn.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
.iconbtn .dot {
  position: absolute; transform: translate(13px, -11px);
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: var(--r-full);
  background: var(--bad); color: #fff; font-size: var(--fs-3xs); font-weight: 700;
  display: grid; place-items: center;
  box-shadow: 0 0 0 2px var(--bg), 0 2px 8px color-mix(in srgb, var(--bad) 55%, transparent);
  animation: dotPop .34s var(--spring);
}
.iconbtn.unread { color: var(--bad); }
@keyframes dotPop { 0% { transform: translate(13px, -11px) scale(0); } 100% { transform: translate(13px, -11px) scale(1); } }

/* ── Navigation ────────────────────────────────────────────────────────── */
.nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
  padding: 6px max(8px, env(safe-area-inset-left)) calc(6px + env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-right));
  background: color-mix(in srgb, var(--bg) 74%, transparent);
  backdrop-filter: blur(var(--blur)) saturate(1.6);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(1.6);
  border-top: 1px solid var(--line);
}
@supports not (backdrop-filter: blur(2px)) { .nav { background: var(--bg); } }
.nav-in { display: flex; gap: 2px; max-width: 620px; margin-inline: auto; }
.nav-item {
  flex: 1; min-width: 0; padding: 7px 2px 5px; border-radius: var(--r-sm);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  color: var(--text-3); font-size: var(--fs-3xs); font-weight: 600; letter-spacing: .01em;
  transition: color var(--t-fast), background var(--t-fast), transform var(--t-fast) var(--spring);
  position: relative;
}
.nav-item i { font-style: normal; font-size: var(--fs-icon); line-height: 1; transition: transform var(--t) var(--spring); }
/* Подпись переносится на вторую строку, а не обрезается многоточием.
   «Навантаження» по-украински короче не становится, а «Навант…» — это уже не
   слово. Две строки нижнее меню выдерживает: под контент отведено на 34 px
   больше его высоты. Третьей строки не бывает — обрезаем на второй. */
.nav-item span {
  max-width: 100%; text-align: center;
  line-height: 1.06; overflow-wrap: anywhere; hyphens: auto;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.nav-item:active { transform: scale(.93); }
.nav-item.on { color: var(--accent-text); }
.nav-item.on i { transform: translateY(-1px) scale(1.08); }
.nav-item.on::before {
  content: ""; position: absolute; inset: 2px 6px;
  background: var(--accent-soft); border-radius: var(--r-sm); z-index: -1;
  animation: pop .34s var(--spring);
}

@media (min-width: 960px) {
  .app { grid-template-columns: var(--rail-w) minmax(0, 1fr); grid-template-rows: auto 1fr; }
  .topbar { grid-column: 1 / -1; }
  .nav {
    position: sticky; top: 0; align-self: start; height: calc(100dvh - 66px);
    border-top: 0; border-right: 1px solid var(--line);
    padding: 14px 12px; background: transparent; backdrop-filter: none;
  }
  .nav-in { flex-direction: column; gap: 4px; max-width: none; }
  .nav-item {
    flex-direction: row; justify-content: flex-start; gap: 12px;
    padding: 11px 14px; font-size: var(--fs-sm); border-radius: var(--r-sm);
  }
  .nav-item i { font-size: var(--fs-icon-sm); }
  .main { padding-bottom: 60px; max-width: 1100px; margin-inline: 0; }
}

/* ── Cards & panels ────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  backdrop-filter: blur(var(--blur)) saturate(1.35);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(1.35);
  box-shadow: var(--shadow-1);
}
@supports not (backdrop-filter: blur(2px)) { .card { background: var(--surface-sol); } }
.card.pad { padding: 16px; }
.card.tight { padding: 12px; border-radius: var(--r-md); }

.section { margin-top: 18px; }
.section-head {
  display: flex; align-items: center; gap: 10px; margin: 0 4px 10px;
}
.section-head h2, .section-head h3 { flex: 1; min-width: 0; }
.eyebrow {
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-3);
}
.muted { color: var(--text-3); }
.dim   { color: var(--text-2); }
.hint  { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.45; }
.row { display: flex; align-items: center; gap: 10px; }
.row.wrap { flex-wrap: wrap; }
.spacer { flex: 1; }
.stack { display: grid; gap: 10px; }
/* Single-column grids default to an `auto` track, which sizes to max-content and
   quietly stretches the page. Pin them to a shrinkable column. */
.stack, .dayrow, .list, .field, .tile, .pcard, .squad ul, .chart-wrap, .acc-body > .stack {
  grid-template-columns: minmax(0, 1fr);
}
.stack > *, .dayrow > *, .list > *, .pcard > * { min-width: 0; }
.stack.lg { gap: 16px; }

/* ── Buttons ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 16px; border-radius: var(--r-sm);
  font-weight: 620; font-size: var(--fs-md);
  background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text);
  transition: transform var(--t-fast) var(--spring), background var(--t-fast), border-color var(--t-fast), opacity var(--t-fast);
}
.btn:hover { border-color: var(--line-strong); }
.btn:active { transform: scale(.965); }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn.primary {
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 72%, #6366f1));
  border-color: transparent; color: var(--on-accent);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 36%, transparent);
}
.btn.ghost { background: transparent; border-color: var(--line); }
.btn.quiet { background: transparent; border-color: transparent; color: var(--text-2); padding-inline: 10px; }
.btn.danger { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 34%, transparent); background: color-mix(in srgb, var(--bad) 10%, transparent); }
.btn.wide { width: 100%; }
.btn.sm { padding: 7px 12px; font-size: var(--fs-sm); border-radius: var(--r-xs); }
.btn.lg { padding: 14px 20px; font-size: var(--fs-lg); border-radius: var(--r-md); }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: var(--r-full);
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-2);
  transition: all var(--t-fast) var(--ease);
}
.chip:active { transform: scale(.94); }
.chip.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
/* Кегль и отступы прежние, но по высоте палец должен попадать в 32 px. */
.chip.sm { padding: 5px 10px; font-size: var(--fs-xs); min-height: 32px; }

/* ── Segmented control with a sliding indicator ────────────────────────── */
.seg {
  position: relative; display: inline-flex; padding: 4px; gap: 2px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md);
  overflow: hidden; max-width: 100%;
}
.seg-ind {
  position: absolute; top: 4px; bottom: 4px; left: 0; width: 0;
  background: var(--accent); border-radius: var(--r-sm);
  box-shadow: 0 3px 12px color-mix(in srgb, var(--accent) 44%, transparent);
  transition: transform var(--t) var(--ease-out), width var(--t) var(--ease-out);
  z-index: 0;
}
.seg button {
  position: relative; z-index: 1; min-width: 0;
  padding: 8px 14px; border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-weight: 620; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color var(--t-fast);
}
@media (max-width: 380px) { .seg button { padding-inline: 10px; font-size: var(--fs-xs); } }
.seg button.on {
  color: var(--on-accent);
  background: var(--accent);
  box-shadow: 0 3px 12px color-mix(in srgb, var(--accent) 40%, transparent);
}
.seg.slide button.on { background: none; box-shadow: none; }
.seg:not(.slide) .seg-ind { display: none; }
/* Подписи целиком, в две строки, ширина поровну. Обрезанный вариант выбора
   бесполезен: человек должен прочитать все три, прежде чем нажать. */
.seg.wrap { display: flex; width: 100%; flex-wrap: wrap; }
/* Переносящийся сегмент подсвечивает выбранное фоном самой кнопки, а не
   ползунком: ползунок ездит по одной строке и на втором ряду встал бы мимо. */
.seg.wrap .seg-ind { display: none; }
.seg.wrap button.on {
  background: var(--accent); color: var(--on-accent);
  box-shadow: 0 3px 12px color-mix(in srgb, var(--accent) 40%, transparent);
}
.seg.wrap button {
  /* auto, а не 0: колонки берут по своей длине и делят остаток, поэтому
     «с ограничениями» не оказывается уже «готов». Перенос — только по
     пробелам: разорванное посередине «ограничениям/и» читается хуже
     обрезанного. */
  flex: 1 1 auto; min-width: max-content; padding-inline: 10px;
  white-space: normal; text-overflow: clip; text-align: center;
  line-height: 1.14; overflow-wrap: normal; word-break: normal;
}

.seg.scroll { display: flex; overflow-x: auto; scrollbar-width: none; }
/* A scrolling control keeps full labels — it scrolls instead of truncating.
   flex-shrink: 0 — обязателен: иначе текст кнопки печатается поверх соседней. */
.seg.scroll button { flex: 1 0 auto; }
.seg.scroll::-webkit-scrollbar { display: none; }

/* ── Fields ────────────────────────────────────────────────────────────── */
/* min-width:0 здесь — не украшение, а условие работы.
   Поле почти всегда лежит в flex-строке рядом с соседом, а flex-элемент по
   умолчанию не сжимается уже своего содержимого. У `input[type=date]` на iOS
   содержимое широкое («27 авг. 2026 г.» плюс отступы), поэтому две даты в
   одной строке переставали помещаться и налезали друг на друга. */
.field { display: grid; gap: 6px; min-width: 0; }
.field > label { font-size: var(--fs-xs); font-weight: 620; color: var(--text-2); padding-left: 2px; }
.input, select.input, textarea.input {
  width: 100%; padding: 12px 14px; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--surface-sol) 82%, transparent);
  border: 1px solid var(--line); color: var(--text);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.input:focus { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft); }
.input::placeholder { color: var(--text-3); }
textarea.input { min-height: 92px; resize: vertical; }
/* Нативные поля даты и времени на iOS живут по своим правилам: центрируют
   текст и держат собственную ширину. Приводим их к остальным полям. */
.input[type="date"], .input[type="time"] {
  min-width: 0; text-align: left;
  -webkit-appearance: none; appearance: none;
}
select.input { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--text-3) 50%), linear-gradient(135deg, var(--text-3) 50%, transparent 50%); background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%; background-size: 5px 5px; background-repeat: no-repeat; padding-right: 34px; }
/* Две колонки формы. Сеткой, а не flex-строкой: minmax(0, 1fr) делит ширину
   поровну независимо от содержимого, а align-items: start держит подписи на
   одной линии, когда одна колонка выше другой. */
.frow { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; align-items: start; }
.frow.wide-first { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.frow.narrow-first { grid-template-columns: 110px minmax(0, 1fr); }

.field-err { font-size: var(--fs-xs); color: var(--bad); }
/* Компактный вариант поля. Кегль трогать нельзя: Safari на iOS зумит
   страницу на любом input/select мельче 16px и обратно не отъезжает. */
.input.sm { width: auto; padding: 6px 10px; min-height: 34px; font-size: 16px; }
select.input.sm { padding-right: 30px; background-position: calc(100% - 15px) 50%, calc(100% - 10px) 50%; }

.switch {
  position: relative; width: 46px; height: 27px; border-radius: var(--r-full); flex: none;
  background: var(--line-strong); transition: background var(--t) var(--ease);
}
/* Прозрачное расширение зоны нажатия до 33 px без роста самого тумблера. */
.switch::before { content: ""; position: absolute; inset: -3px -2px; border-radius: var(--r-full); }
[role="switch"] { min-height: 32px; }
.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 21px; height: 21px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,.35);
  transition: transform var(--t) var(--spring);
}
.switch.on { background: var(--accent); }
.switch.on::after { transform: translateX(19px); }

/* ── Avatars ───────────────────────────────────────────────────────────── */
.av {
  border-radius: 50%; flex: none; overflow: hidden;
  display: grid; place-items: center;
  background: linear-gradient(140deg, color-mix(in srgb, var(--accent) 55%, transparent), color-mix(in srgb, var(--accent) 18%, transparent));
  color: var(--text); font-weight: 700; letter-spacing: -.02em;
  border: 1px solid var(--line);
}
.av img { width: 100%; height: 100%; object-fit: cover; }
.av.s28 { width: 28px; height: 28px; font-size: var(--fs-3xs); }
.av.s36 { width: 36px; height: 36px; font-size: var(--fs-xs); }
.av.s44 { width: 44px; height: 44px; font-size: var(--fs-md); }
.av.s84 { width: 84px; height: 84px; font-size: var(--fs-3xl); border-width: 2px; }

/* ── Stat tiles ────────────────────────────────────────────────────────── */
/* Ряды плиток заполняются целиком. Сетка из 6 колонок: плитка занимает 3 (два
   в ряд) или 2 (три в ряд), а «хвост», который иначе остался бы один, тянется
   на весь остаток ряда. Замерено: раньше 7-я плитка висела одна. */
.tiles { display: grid; gap: 10px; grid-template-columns: repeat(6, minmax(0, 1fr)); }
.tiles > * { grid-column: span 3; }
.tiles > :last-child:nth-child(odd) { grid-column: span 6; }
@media (min-width: 420px) {
  .tiles > * { grid-column: span 2; }
  .tiles > :last-child:nth-child(odd) { grid-column: span 2; }
  .tiles > :nth-child(3n+1):nth-last-child(2),
  .tiles > :nth-child(3n+2):last-child { grid-column: span 3; }
  .tiles > :nth-child(3n+1):last-child { grid-column: span 6; }
}
@media (min-width: 760px) {
  .tiles { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .tiles > *,
  .tiles > :last-child:nth-child(odd),
  .tiles > :nth-child(3n+1):nth-last-child(2),
  .tiles > :nth-child(3n+2):last-child,
  .tiles > :nth-child(3n+1):last-child { grid-column: span 3; }
  .tiles > :nth-child(4n+1):nth-last-child(3),
  .tiles > :nth-child(4n+2):nth-last-child(2),
  .tiles > :nth-child(4n+3):last-child { grid-column: span 4; }
  .tiles > :nth-child(4n+1):nth-last-child(2),
  .tiles > :nth-child(4n+2):last-child { grid-column: span 6; }
  .tiles > :nth-child(4n+1):last-child { grid-column: span 12; }
}
.tile {
  padding: 13px 14px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line);
  display: grid; gap: 3px; position: relative; overflow: hidden;
  backdrop-filter: blur(var(--blur));
  -webkit-backdrop-filter: blur(var(--blur));
}
.tile::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--tile-accent, var(--accent)); opacity: .85;
}
/* Блок, а не flex: анонимный flex-элемент не умеет уходить ниже ширины
   самого длинного слова, и «⚠️ Предупреждения» вылезало за плитку. */
.tile-lbl { font-size: var(--fs-2xs); font-weight: 640; color: var(--text-3); min-width: 0; overflow-wrap: break-word; }
.tile-val { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -.03em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.tile-val small { font-size: var(--fs-md); font-weight: 600; color: var(--text-3); margin-left: 1px; }
.tile-note { font-size: var(--fs-2xs); color: var(--text-3); }
/* An empty value should read as "nothing yet", not as a giant rule. */
.nodata { font-size: .58em; color: var(--text-3); vertical-align: .18em; letter-spacing: -.04em; }
.trio .nodata, table.grid .nodata { font-size: inherit; vertical-align: baseline; }

/* ── Accordion blocks (the daily check-in) ─────────────────────────────── */
.acc { border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface); overflow: hidden; }
.acc + .acc { margin-top: 10px; }
.acc-head {
  width: 100%; display: flex; align-items: center; gap: 11px;
  padding: 13px 14px; text-align: left;
  transition: background var(--t-fast);
}
.acc-head:hover { background: var(--surface-2); }
.acc-head .ico { font-size: var(--fs-icon); width: 26px; text-align: center; flex: none; }
/* Ужимается заголовок, а не пилюля справа: иначе текст печатался поверх неё
   (замерено 89,2 px наложения на ширине 320). */
/* Две строки вместо многоточия: «TQR — восстановление» в одну не помещается
   на 320 px ни при каком кегле, а «TQR — восстано…» не читается. Пилюля
   справа держит свою ширину, поэтому наезда по-прежнему нет. */
.acc-head .ttl {
  flex: 1; min-width: 0; font-weight: 620; line-height: 1.16;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.acc-head .ttl small { display: block; font-weight: 500; color: var(--text-3); font-size: var(--fs-2xs); overflow: hidden; text-overflow: ellipsis; }
.acc-head .chev { color: var(--text-3); transition: transform var(--t) var(--ease); font-size: var(--fs-xs); }
.acc.open .acc-head .chev { transform: rotate(90deg); }
.acc.locked .acc-head { cursor: default; }
.acc.locked .acc-head:hover { background: none; }
.pill {
  padding: 5px 11px; border-radius: var(--r-full); font-size: var(--fs-xs); font-weight: 660;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text-2); white-space: nowrap;
  flex: none;
}
.pill.todo { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
.pill.done { background: color-mix(in srgb, var(--good) 16%, transparent); border-color: color-mix(in srgb, var(--good) 36%, transparent); color: color-mix(in srgb, var(--good) 86%, white); }
.pill.warn { background: color-mix(in srgb, var(--warn) 16%, transparent); border-color: color-mix(in srgb, var(--warn) 40%, transparent); color: color-mix(in srgb, var(--warn) 88%, white); }
.pill.bad  { background: color-mix(in srgb, var(--bad) 16%, transparent); border-color: color-mix(in srgb, var(--bad) 38%, transparent); color: color-mix(in srgb, var(--bad) 88%, white); }
.acc-body { padding: 4px 14px 15px; animation: slideDown .26s var(--ease-out); }

/* Строка процедуры: значок, имя, кнопки порядка. Имени отдаём всё, что
   осталось, и не меньше 140 px — иначе подсказка «Ледяная ванна» обрезается на
   «Ледяная ван». Не хватило места — кнопки уезжают под строку, а не имя. */
.proc-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.proc-row > .proc-name { flex: 1 1 140px; min-width: 0; }
.proc-acts { display: flex; gap: 6px; margin-left: auto; flex: none; }

/* ── Level pickers ─────────────────────────────────────────────────────── */
.levels { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px; }
.levels.tqr { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.levels button {
  aspect-ratio: 1.35; border-radius: var(--r-sm); font-weight: 730; font-size: var(--fs-lg);
  border: 1px solid transparent; position: relative; overflow: hidden;
  font-variant-numeric: tabular-nums;
  transition: transform var(--t-fast) var(--spring), filter var(--t-fast), box-shadow var(--t-fast);
}
.levels button:hover { filter: brightness(1.14); box-shadow: 0 4px 14px rgba(0,0,0,.3); }
.levels button:active { transform: scale(.9); }
.scale-legend { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 11px; }
.legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-2xs); color: var(--text-3); }
.legend-dot { width: 11px; height: 11px; border-radius: var(--r-2xs); flex: none; }

.mrow { display: flex; flex-wrap: wrap; gap: 8px; }
.mrow button {
  padding: 9px 14px; border-radius: var(--r-sm); font-weight: 600; font-size: var(--fs-sm);
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text-2);
  transition: all var(--t-fast) var(--ease);
}
.mrow button:active { transform: scale(.94); }
.mrow button.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
.mrow button.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 30%, transparent); }

/* ── Player cards (summary view) ───────────────────────────────────────── */
.cards { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); }
.pcard {
  padding: 13px; border-radius: var(--r-md); background: var(--surface);
  border: 1px solid var(--line); display: grid; gap: 10px; position: relative;
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast), box-shadow var(--t-fast);
  backdrop-filter: blur(var(--blur)); -webkit-backdrop-filter: blur(var(--blur));
}
.pcard:hover { border-color: var(--line-strong); }
.pcard.sel { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.pcard-top { display: flex; align-items: center; gap: 9px; }
.pcard-name { flex: 1; min-width: 0; }
.pcard-name b { display: block; font-size: var(--fs-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcard-name small { color: var(--text-3); font-size: var(--fs-2xs); }
.jersey {
  min-width: 27px; height: 27px; padding: 0 6px; border-radius: var(--r-xs); flex: none;
  display: grid; place-items: center; font-size: var(--fs-xs); font-weight: 750;
  background: var(--surface-2); border: 1px solid var(--line); font-variant-numeric: tabular-nums;
}
.trio { display: grid; gap: 6px; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
.trio .cell {
  padding: 8px 4px; border-radius: var(--r-xs); text-align: center;
  background: var(--surface-2); border: 1px solid var(--line);
}
.trio .cell b { display: block; font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }
.trio .cell small { font-size: var(--fs-3xs); color: var(--text-3); }
/* Все клетки одной высоты: значение несёт цвет, высота его только дублировала
   и заодно делала выходной «выше» болезни. См. spark() в views/stats.js. */
.spark { display: flex; gap: 2px; height: 26px; align-items: stretch; }
.spark i {
  flex: 1; min-width: 2px; height: 100%; border-radius: var(--r-2xs); font-style: normal;
  display: grid; place-items: center; font-size: var(--fs-3xs);
  transition: background var(--t) var(--ease-out);
}

/* ── Calendar grid ─────────────────────────────────────────────────────── */
.gridwrap {
  overflow: auto; border-radius: var(--r-md); border: 1px solid var(--line);
  background: var(--surface); max-height: 74dvh;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}
table.grid { border-collapse: separate; border-spacing: 0; width: max-content; min-width: 100%; }
table.grid th, table.grid td {
  padding: 0; text-align: center; font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
  border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  height: var(--row-h); min-width: var(--cell); width: var(--cell);
}
table.grid thead th {
  position: sticky; top: 0; z-index: 3; background: var(--surface-sol);
  font-weight: 640; font-size: var(--fs-2xs); padding: 5px 2px; height: auto; line-height: 1.15;
}
table.grid thead th small { display: block; font-size: var(--fs-3xs); color: var(--text-3); font-weight: 500; }
table.grid th.we, table.grid td.we { background: color-mix(in srgb, var(--text) 4%, transparent); }
table.grid th.off, table.grid td.off { background: color-mix(in srgb, var(--rest) 24%, transparent); }
table.grid th.today { box-shadow: inset 0 0 0 2px var(--accent); border-radius: var(--r-xs); }
table.grid .stick {
  position: sticky; left: 0; z-index: 2; text-align: left;
  min-width: var(--name-w); width: var(--name-w); max-width: var(--name-w);
  padding: 0 9px; background: var(--surface-sol); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.grid thead .stick { z-index: 4; }
table.grid .sum { min-width: var(--sum-w); width: var(--sum-w); font-weight: 700; background: color-mix(in srgb, var(--text) 5%, transparent); }
table.grid tr.team td { font-weight: 750; background: color-mix(in srgb, var(--accent) 9%, transparent); }
table.grid tr.me .stick { color: var(--accent-text); }
table.grid tr.sel .stick { background: var(--accent-soft); }
.cellv { display: grid; place-items: center; height: 100%; border-radius: var(--r-2xs); margin: 2px; font-weight: 650; }
.split { display: grid; grid-template-rows: 1fr 1fr; height: 100%; gap: 1px; padding: 1px; }
.split > span { display: grid; place-items: center; border-radius: var(--r-2xs); font-size: var(--fs-2xs); font-weight: 650; position: relative; }
.split > span.am::after { content: "☀"; position: absolute; left: 1px; top: 0; font-size: 7px; opacity: .85; }
.split > span.mt::after { content: "🏆"; position: absolute; left: 1px; top: 0; font-size: 7px; }
table.grid.dbl td { height: 46px; }

/* ── Bottom sheet & modal ──────────────────────────────────────────────── */
.backdrop {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(3, 6, 14, .58);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  animation: fade var(--t) var(--ease);
}
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 91;
  max-height: 88dvh; overflow: auto;
  padding: 8px var(--pad) calc(20px + env(safe-area-inset-bottom));
  background: var(--elevated); border-radius: var(--r-xl) var(--r-xl) 0 0;
  border-top: 1px solid var(--line-strong);
  box-shadow: var(--shadow-pop);
  animation: sheetUp .32s var(--ease-out);
  backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
}
.sheet-grip { width: 40px; height: 4px; border-radius: var(--r-full); background: var(--line-strong); margin: 6px auto 12px; }
.sheet-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.sheet-head h3 { flex: 1; }
@media (min-width: 720px) {
  .sheet {
    left: 50%; right: auto; bottom: auto; top: 50%;
    transform: translate(-50%, -50%);
    width: min(560px, calc(100vw - 40px));
    border-radius: var(--r-xl); border: 1px solid var(--line-strong);
    animation: popIn .28s var(--ease-out);
    padding: 18px 20px 22px;
  }
  .sheet-grip { display: none; }
  /* Широкая шторка — только на большом экране. На телефоне у .sheet заданы и
     left, и right: добавленная сюда же ширина делает блок переопределённым,
     браузер отбрасывает right — и справа остаётся мёртвая полоса в 40 px. */
  .sheet.wide { width: min(880px, calc(100vw - 40px)); }
}

/* ── Toast ─────────────────────────────────────────────────────────────── */
.toasts {
  position: fixed; z-index: 120; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--nav-h) + 22px + env(safe-area-inset-bottom));
  display: grid; gap: 8px; width: min(440px, calc(100vw - 28px));
  pointer-events: none;
}
@media (min-width: 960px) { .toasts { bottom: 24px; } }
.toast {
  padding: 12px 15px; border-radius: var(--r-md);
  background: var(--elevated); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-2); font-size: var(--fs-sm); font-weight: 550;
  display: flex; align-items: center; gap: 10px;
  animation: toastIn .3s var(--ease-out);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
}
.toast.out { animation: toastOut .22s var(--ease) forwards; }
.toast.ok  { border-color: color-mix(in srgb, var(--good) 45%, transparent); }
.toast.err { border-color: color-mix(in srgb, var(--bad) 50%, transparent); }

/* ── Misc ──────────────────────────────────────────────────────────────── */
.empty { text-align: center; padding: 40px 20px; color: var(--text-3); }
.empty .big { font-size: 44px; margin-bottom: 10px; opacity: .55; }

.skel { background: linear-gradient(100deg, var(--surface-2) 30%, color-mix(in srgb, var(--text) 8%, var(--surface-2)) 50%, var(--surface-2) 70%); background-size: 220% 100%; animation: shimmer 1.3s infinite linear; border-radius: var(--r-sm); }

.list { display: grid; gap: 1px; background: var(--line); border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--line); }
.list > * { background: var(--surface-sol); padding: 12px 14px; display: flex; align-items: center; gap: 11px; }
.list > *:hover { background: var(--surface-2); }

.badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: var(--r-xs); font-size: var(--fs-3xs); font-weight: 700; background: var(--surface-2); border: 1px solid var(--line); color: var(--text-3); }
.badge.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.badge.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.badge.good { color: var(--good); border-color: color-mix(in srgb, var(--good) 40%, transparent); }

.pos { padding: 2px 6px; border-radius: var(--r-xs); font-size: var(--fs-3xs); font-weight: 750; }
.pos.p-s  { background: #a855f733; color: #d8b4fe; }
.pos.p-op { background: #f43f5e33; color: #fda4af; }
.pos.p-oh { background: #3b82f633; color: #93c5fd; }
.pos.p-mb { background: #22c55e33; color: #86efac; }
.pos.p-l  { background: #eab30833; color: #fde047; }
:root[data-theme="light"] .pos.p-s  { background: #a855f722; color: #7e22ce; }
:root[data-theme="light"] .pos.p-op { background: #f43f5e22; color: #be123c; }
:root[data-theme="light"] .pos.p-oh { background: #3b82f622; color: #1d4ed8; }
:root[data-theme="light"] .pos.p-mb { background: #22c55e22; color: #15803d; }
:root[data-theme="light"] .pos.p-l  { background: #eab30833; color: #a16207; }

.squad { border-radius: var(--r-md); border: 1px solid var(--line); overflow: hidden; background: var(--surface); }
.squad-head { padding: 11px 14px; display: flex; align-items: center; gap: 9px; font-weight: 680; border-bottom: 1px solid var(--line); }
.squad-head .dotc { width: 11px; height: 11px; border-radius: var(--r-2xs); flex: none; }
.squad ul { list-style: none; padding: 6px; display: grid; gap: 3px; }
.squad li { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: var(--r-xs); transition: background var(--t-fast); }
.squad li:hover { background: var(--surface-2); }
.squad li.picked { background: var(--accent-soft); outline: 1px dashed var(--accent-line); }

.dayrow { display: grid; gap: 10px; }
.day {
  border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface);
  padding: 11px 13px; display: grid; gap: 7px;
  transition: border-color var(--t-fast), transform var(--t-fast);
}
.day.today { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.day.off { opacity: .62; }
.day-top { display: flex; align-items: baseline; gap: 9px; }
.day-num { font-size: var(--fs-xl); font-weight: 730; font-variant-numeric: tabular-nums; }
.day-wd { font-size: var(--fs-2xs); color: var(--text-3); text-transform: uppercase; letter-spacing: .06em; font-weight: 650; }
/* Sessions read as a list, one per line — a run-on string is unreadable on a phone. */
.sessions { display: grid; gap: 3px; font-size: var(--fs-xs); color: var(--text-2); }
.sessions > span { display: flex; gap: 8px; align-items: baseline; }
.sessions time { font-variant-numeric: tabular-nums; color: var(--text-3); min-width: 42px; }
@media (min-width: 620px) { .day-top .sessions { text-align: right; } }
.dchip {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px;
  border-radius: var(--r-full); font-size: var(--fs-xs); font-weight: 620;
  background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--accent-text);
}
.dchip.preview { background: transparent; border-style: dashed; color: var(--text-3); }
.dchip.manual { background: var(--accent); color: var(--on-accent); border-color: transparent; }

.codebox {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--fs-xl); font-weight: 700; letter-spacing: .22em;
  padding: 14px 16px; border-radius: var(--r-md); text-align: center;
  background: var(--surface-2); border: 1px dashed var(--line-strong);
}

/* 8 образцов ложатся ровно: 4×2 на телефоне, 8×1 когда хватает ширины.
   На flex-wrap восьмой переносился на отдельную строку один. */
.swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 9px; justify-items: center; }
@media (min-width: 420px) { .swatches { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
.swatch { width: 34px; height: 34px; border-radius: var(--r-sm); border: 2px solid transparent; position: relative; transition: transform var(--t-fast) var(--spring); }
.swatch:active { transform: scale(.9); }
.swatch.on { border-color: var(--text); box-shadow: 0 0 0 3px color-mix(in srgb, var(--text) 14%, transparent); }
/* 8 пресетов логотипа — ровно 4×2 на телефоне (auto-fill давал ряды 5+3). */
.logopick { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 520px) { .logopick { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
.logoopt {
  aspect-ratio: 1; padding: 7px; border-radius: var(--r-sm);
  border: 2px solid transparent; background: var(--surface-2);
  color: var(--accent); overflow: hidden;
  transition: transform var(--t-fast) var(--spring), border-color var(--t-fast), background var(--t-fast);
}
.logoopt:hover { background: var(--surface-3, var(--surface-2)); }
.logoopt:active { transform: scale(.92); }
.logoopt.on { border-color: var(--accent); background: var(--accent-soft); }
.logoopt img { width: 100%; height: 100%; object-fit: contain; border-radius: var(--r-xs); }

/* Фиксированное число колонок вместо auto-fill: размер превью больше не
   скачет от ширины экрана, 8 пресетов всегда дают целые ряды (4×2 / 2×4). */
.walls { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
@media (min-width: 400px) { .walls { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.wallopt {
  aspect-ratio: 16/10; border-radius: var(--r-sm); border: 2px solid transparent;
  position: relative; overflow: hidden; background-size: cover; background-position: center;
  transition: transform var(--t-fast) var(--spring);
}
.wallopt:active { transform: scale(.95); }
.wallopt.on { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.wallopt span { position: absolute; left: 0; right: 0; bottom: 0; padding: 3px 6px; font-size: var(--fs-3xs); font-weight: 650; background: rgba(0,0,0,.45); color: #fff; }
/* «Своя картинка» — отдельная широкая полоса под сеткой: в ячейке пресета
   подпись не помещалась и ломалась на две строки. */
.wallopt.custom { grid-column: 1 / -1; aspect-ratio: auto; min-height: 46px; display: grid; place-items: center; border-style: dashed; border-color: var(--line-strong); }
.wallopt.custom span { position: static; left: auto; right: auto; padding: 4px 11px; border-radius: var(--r-full); white-space: nowrap; }
.wallopt.custom.on { border-color: var(--accent); }

.progress { height: 6px; border-radius: var(--r-full); background: var(--line-strong); overflow: hidden; }
.progress i { display: block; height: 100%; border-radius: var(--r-full); background: var(--accent); transition: width var(--t-slow) var(--ease-out); }

.chart { width: 100%; height: 132px; display: block; }
.chart-wrap { position: relative; }

/* ── Animations ────────────────────────────────────────────────────────── */
@keyframes fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes pop { 0% { transform: scale(.6); opacity: 0 } 100% { transform: scale(1); opacity: 1 } }
@keyframes popIn { from { opacity: 0; transform: translate(-50%, -46%) scale(.96) } to { opacity: 1; transform: translate(-50%, -50%) scale(1) } }
@keyframes sheetUp { from { transform: translateY(26px); opacity: .4 } to { transform: none; opacity: 1 } }
@keyframes slideDown { from { opacity: 0; transform: translateY(-6px) } to { opacity: 1; transform: none } }
@keyframes toastIn { from { opacity: 0; transform: translateY(14px) scale(.97) } to { opacity: 1; transform: none } }
@keyframes toastOut { to { opacity: 0; transform: translateY(8px) scale(.98) } }
@keyframes shimmer { from { background-position: 140% 0 } to { background-position: -40% 0 } }
@keyframes riseIn { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }

.rise { animation: riseIn .34s var(--ease-out) both; }
.rise:nth-child(1) { animation-delay: .01s }
.rise:nth-child(2) { animation-delay: .04s }
.rise:nth-child(3) { animation-delay: .07s }
.rise:nth-child(4) { animation-delay: .10s }
.rise:nth-child(5) { animation-delay: .13s }
.rise:nth-child(6) { animation-delay: .16s }
.rise:nth-child(7) { animation-delay: .19s }
.rise:nth-child(8) { animation-delay: .22s }
.rise:nth-child(n+9) { animation-delay: .25s }

::view-transition-old(root) { animation: fade .16s var(--ease) reverse; }
::view-transition-new(root) { animation: fade .22s var(--ease); }

/* ── Density ───────────────────────────────────────────────────────────── */
:root[data-density="compact"] {
  --pad: 12px; --cell: 34px; --row-h: 34px; --name-w: 112px; --sum-w: 54px;
  font-size: 14px;
}
@media (min-width: 860px) {
  :root { --cell: 38px; --name-w: 150px; }
}

/* ── Auth screen ───────────────────────────────────────────────────────── */
.authwrap { min-height: 100dvh; display: grid; place-items: center; padding: 22px 18px calc(30px + env(safe-area-inset-bottom)); }
.card.authcard { width: min(430px, 100%); padding: 26px 22px; border-radius: var(--r-xl); animation: riseIn .4s var(--ease-out) both; }
.authlogo {
  width: 62px; height: 62px; border-radius: var(--r-lg); margin: 0 auto 14px;
  display: grid; place-items: center; font-size: 32px;
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 40%, #a855f7));
  box-shadow: 0 10px 30px color-mix(in srgb, var(--accent) 42%, transparent);
}
/* A drawn ball carries its own shape — no plate, no glow behind it. */
.authlogo.plain { background: none; box-shadow: none; padding: 0; }
.authlogo.plain .logo-svg { width: 62px; height: 62px; }

/* ── Дежурные: фамилия белая, контур по амплуа ─────────────────────────────
   Сплошная заливка амплуа превращала строку дежурных в светофор, а цветные
   фамилии читались хуже белых. Цвет ушёл в контур: расстановка видна с одного
   взгляда, а текст остаётся текстом. */
.dchip.p-s  { border-color: #a855f7; }
.dchip.p-op { border-color: #f43f5e; }
.dchip.p-oh { border-color: #3b82f6; }
.dchip.p-mb { border-color: #22c55e; }
.dchip.p-l  { border-color: #eab308; }
.dchip.p-s, .dchip.p-op, .dchip.p-oh, .dchip.p-mb, .dchip.p-l { color: var(--text); }
.dchip.manual.p-s, .dchip.manual.p-op, .dchip.manual.p-oh,
.dchip.manual.p-mb, .dchip.manual.p-l { color: var(--on-accent); border-width: 2px; }

/* Крестики: итог за период говорит числом, а не красным прямоугольником. */
.trio .cell.bad b { color: var(--bad); }
.trio .cell.bad { border-color: color-mix(in srgb, var(--bad) 42%, transparent); }

/* На узких экранах (iPhone SE, 320 px) на кнопку раздела приходится 62 px, и
   «Календарь» в базовом кегле не помещается — обрезается многоточием. Замерено
   в браузере: при 0,58rem слово укладывается целиком. */
@media (max-width: 360px) {
  .nav-item { font-size: .58rem; letter-spacing: -.01em; padding-left: 1px; padding-right: 1px; }
  .nav-item i { font-size: var(--fs-icon-sm); }
}

/* ==== install ==== */
/* Подвал карточки входа. Раньше кнопка «Скачать на устройство» приклеивалась к
   ряду языков вплотную — ровно 0,00 px: отступы стояли у соседей, а у неё не
   было. Расстояния держит колонка, поэтому забыть их негде. */
.authfoot { display: flex; flex-direction: column; gap: 14px; margin-top: 18px; }
.authfoot > * { margin: 0; }
.authlocs { display: flex; justify-content: center; flex-wrap: wrap; gap: 6px; }

/* Кнопки в подвале должны читаться одной семьёй: главная крупнее, остальные
   одной высоты. 44 px — минимальная цель нажатия по рекомендациям Apple. */
.authfoot .btn { min-height: 46px; }
.authfoot .btn.quiet { font-size: var(--fs-sm); }

/* Эмодзи вынесен в отдельный элемент: пока он лежал в одном текстовом узле с
   подписью, gap кнопки на него не действовал, и значок оптически прижимался к
   верхнему краю (0,25 px сверху против 4,36 px снизу). */
.inst-btn { align-items: center; }
.inst-ico { display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-icon-sm); line-height: 1; flex: none; }
.inst-label { min-width: 0; }

/* Лист с шагами установки. */
.inst-body { gap: 14px; }
.inst-steps { display: grid; gap: 12px; }
.inst-step { display: grid; grid-template-columns: 26px 1fr; gap: 10px; align-items: start; }

/* Второй способ установки отделён чертой: это не продолжение инструкции,
   а другая дорога к тому же значку. */
.inst-alt {
  display: grid; gap: 12px;
  margin-top: 4px; padding-top: 16px;
  border-top: 1px solid var(--line);
}
.inst-alt-title { font-weight: 650; font-size: var(--fs-sm); }
.inst-num {
  width: 26px; height: 26px; border-radius: var(--r-full);
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  color: var(--text); font-weight: 700; font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}
.inst-txt { min-width: 0; }
.inst-txt > div { overflow-wrap: break-word; }
.inst-txt .hint { margin-top: 4px; }
.inst-actions { gap: 8px; flex-wrap: wrap; }
.inst-actions > * { flex: 1 1 auto; justify-content: center; text-align: center; }

/* Схема нижней панели Safari: показать пальцем, где искать «⋯». Слова
   «нажмите ⋯ справа в адресной строке» сами по себе не помогают, если человек
   впервые смотрит на новую панель iOS 26. */
.inst-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: var(--fs-sm); color: var(--text-2);
}
.inst-bar-ico { flex: none; font-size: var(--fs-xs); }
.inst-bar-url { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; }
.inst-bar-hit {
  flex: none; width: 30px; height: 30px; border-radius: var(--r-full);
  display: grid; place-items: center; color: var(--text);
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent);
  animation: instPulse 1.8s var(--ease) infinite;
}
@keyframes instPulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 10px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .inst-bar-hit { animation: none; } }

/* ── Demo-account ─────────────────────────────────────────────────────────
   Кнопка стоит выше формы входа и должна читаться как «главное действие для
   тех, кто зашёл посмотреть», не перебивая при этом настоящий вход. Отсюда
   заливка акцентом с прозрачностью, а не сплошная: сплошная спорила бы с
   «Войти» и человек с аккаунтом путался бы, куда ему. */
.demo-cta { gap: 8px; margin-top: 18px; }
.btn.demo {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent) 26%, transparent),
    color-mix(in srgb, var(--accent) 12%, transparent));
  border: 1px solid var(--accent-line);
  color: var(--accent-text);
  font-weight: 700;
}
.btn.demo:active { transform: scale(.985); }
.btn.demo[disabled] { opacity: .7; }

/* Разделитель «или»: линия, разорванная словом. */
.authsep {
  display: flex; align-items: center; gap: 12px;
  margin: 18px 0 4px; color: var(--text-3); font-size: var(--fs-xs);
}
.authsep::before, .authsep::after {
  content: ''; flex: 1; height: 1px; background: var(--line);
}

.demo-chip {
  flex: none; min-height: 30px; padding: 4px 10px;
  font-size: var(--fs-2xs); font-weight: 700;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-color: var(--accent-line); color: var(--accent-text);
}

/* ── Коды ─────────────────────────────────────────────────────────────────
   Поле принимает и восьмизначное приглашение, и длинный код основателя,
   поэтому разрядка меньше, чем в .codebox: иначе VT-XXXX-XXXX-XXXX-XXXX не
   помещается на телефоне и переносится посреди группы. */
.codeinput {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .08em; text-transform: uppercase;
}
.codebox.big { font-size: var(--fs-lg); letter-spacing: .12em; word-break: break-all; }

.founder-hit { border-color: var(--accent-line); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }

.notice {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 14px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--accent) 9%, var(--surface-2));
  border: 1px solid var(--accent-line);
  color: var(--text-2); line-height: 1.5;
}

/* Список кодов основателя. */
.fcode {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line);
}
.fcode.dead { opacity: .55; }
.fcode-main { flex: 1; min-width: 0; display: grid; gap: 5px; }
.fcode-str {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--fs-sm); font-weight: 700; letter-spacing: .04em;
  text-align: left; color: var(--text); word-break: break-all;
  background: none; border: 0; padding: 0; cursor: pointer;
}
.fcode-str:active { opacity: .6; }
.fcode-sub { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: var(--fs-2xs); }

.flog-box > summary { cursor: pointer; color: var(--text-3); font-size: var(--fs-xs); padding: 6px 0; }
.flog { display: flex; gap: 8px; align-items: center; font-size: var(--fs-2xs); }

.tips { margin: 0; padding-left: 20px; display: grid; gap: 8px; color: var(--text-2); line-height: 1.5; }
.tips li::marker { color: var(--accent); }

/* Компактная строка Safari в iOS 26: адрес и «⋯» в одной плавающей пилюле. */
.inst-bar.compact { border-radius: var(--r-full); padding: 6px 8px 6px 14px; }
.inst-actions { gap: 8px; flex-wrap: wrap; }
.inst-actions > * { flex: 1; min-width: 140px; }

/* Переключатель языков внутри окна установки: оно выскакивает само, до входа,
   и переключатель на карточке под ним человеку не виден. */
.inst-locs { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; margin-top: 4px; }

/* Панель массовых действий. Раньше она висела на inline `bottom: 10px` — то
   есть ровно под нижним меню, которое её и накрывало: на телефоне из панели
   была видна только строка «Выбрано: N», а кнопки уходили под меню. */
.actionbar {
  position: sticky;
  bottom: calc(var(--nav-h) + 10px + env(safe-area-inset-bottom));
  z-index: 20;
}
@media (min-width: 960px) { .actionbar { bottom: 14px; } }

/* Быстрые действия на карточке игрока. */
.pcard-more {
  flex: none; width: 30px; height: 30px; font-size: var(--fs-sm); line-height: 1;
  color: var(--text-2); background: var(--surface-2); border: 1px solid var(--line);
}
.pcard-more:hover, .pcard-more:focus-visible { color: var(--text); border-color: var(--line-strong); }

/* Выходной и пропуск в полоске: значок мелкий, чтобы не спорить с цифрами. */
.spark i.off, .spark i.abs { display: grid; place-items: center; font-size: 9px; line-height: 1; }

/* ── Админ-панель владельца сайта ─────────────────────────────────────────
   Строка команды и строка человека устроены одинаково: слева имя и мелочи
   под ним, справа кнопки. Одинаково — не из лени, а чтобы взгляд не
   перестраивался при переключении вкладок. */
.adm-head { display: grid; gap: 2px; }
.adm-head h2 { font-size: var(--fs-lg); }
/* Плиток бывает три, а бывает пять — считаем демо-песочницы и заблокированных
   только когда они есть. Колонка фиксированной ширины при пяти плитках рвёт
   подписи пополам, поэтому сетка переносит их сама. */
.adm-sum {
  margin-top: 2px;
  grid-auto-flow: row; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
}
.adm-sum .cell.warn { border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); }
.adm-sum .cell.warn b { color: var(--bad); }

.adm-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line);
}
.adm-row.dead { opacity: .6; }
.adm-main { flex: 1; min-width: 0; display: grid; gap: 4px; }
.adm-name {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-weight: 650; font-size: var(--fs-sm); color: var(--text);
}
.adm-sub { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; font-size: var(--fs-2xs); }

/* Название клуба открывает карточку. Подчёркивание появляется только под
   пальцем и курсором: постоянное превратило бы список в частокол ссылок. */
.adm-name.adm-open { cursor: pointer; }
.adm-name.adm-open:hover, .adm-name.adm-open:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.adm-name.adm-open:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 3px; border-radius: 4px; }

/* Строка «подпись — значение» в карточке клуба: подпись слева, число справа,
   разной длины подписи не должны двигать колонку с числами. */
.adm-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: var(--fs-xs); min-height: 22px;
}
.adm-line > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-line > b { flex: none; font-weight: 650; }
.bad-text { color: var(--bad); }
.adm-acts { display: flex; align-items: center; gap: 6px; flex: none; }
.adm-note { font-size: var(--fs-2xs); color: var(--muted); font-style: italic; }

/* На телефоне кнопки уезжают под строку: иначе на них остаётся половина
   ширины, и название клуба ломается на три строки ради трёх кнопок. */
@media (max-width: 560px) {
  .adm-row.adm-wrap { flex-wrap: wrap; }
  .adm-row.adm-wrap .adm-main { flex: 1 1 100%; }
  .adm-row.adm-wrap .adm-acts { margin-left: auto; }
}

/* Полоса и метка «вы в чужой команде». Красная и на всех экранах: спутать
   чужую команду со своей — самый дорогой промах в этой панели. */
.adm-inside {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--bad) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--bad) 42%, var(--line));
  font-size: var(--fs-2xs); color: var(--text);
}
.adm-inside span { flex: 1; min-width: 140px; }
.chip.inside-chip {
  flex: none; white-space: nowrap; max-width: 40%;
  background: color-mix(in srgb, var(--bad) 16%, var(--surface-2));
  border-color: color-mix(in srgb, var(--bad) 45%, var(--line));
  color: var(--text);
}

/* Шестой пункт появляется только у владельца сайта — на узком экране
   подписи иначе не помещаются и обрезаются многоточием. */
.nav-in:has(> :nth-child(6)) .nav-item { font-size: .6rem; padding-inline: 1px; }
.nav-in:has(> :nth-child(6)) .nav-item i { font-size: 19px; }

/* ── Полоса о подписке ───────────────────────────────────────────────────
   Под шапкой, на всех экранах. Не всплывашка: человек должен понимать,
   почему приложение перестало записывать, ДО того как ткнёт в кнопку. */
/* Не sticky намеренно: шапка приклеена и сама сдвигается на вырез экрана,
   и полоса, приклеенная под ней «на 56 пикселей», разъезжалась бы на каждом
   втором телефоне. Здесь достаточно, что она первая, что видит человек. */
.planbar-slot:empty { display: none; }
.planbar {
  padding: 8px var(--pad); font-size: var(--fs-2xs); line-height: 1.35;
  background: color-mix(in srgb, var(--bad) 16%, var(--surface));
  border-bottom: 1px solid color-mix(in srgb, var(--bad) 40%, var(--line));
  color: var(--text); text-align: center;
}
.planbar.soon {
  background: color-mix(in srgb, #f59e0b 16%, var(--surface));
  border-bottom-color: color-mix(in srgb, #f59e0b 40%, var(--line));
}
