/* pw-active — фирменный тёмный стиль клана Hurricane. Рабочая таблица, а не
   витрина: сетка и цифры читаются целиком, шапка примораживается, строка
   подсвечивается под курсором. Всё, что браузер рисует по-своему — select,
   date, file — переопределено, иначе посреди тёмной страницы появляются
   белые системные виджеты.

   Знак клана монохромный, поэтому цвет в интерфейсе несёт смысл, а не
   украшает: штормовой циан — навигация и действие, зелёный/жёлтый/красный —
   был/в очереди/пропустил. Тона разведены (циан 190°, зелёный 134°,
   жёлтый 42°, красный 5°), чтобы плашки не слипались на мелком кегле. */

:root {
  color-scheme: dark;

  /* --- полотна ------------------------------------------------------- */
  --bg: #0d0f12;
  --sheet: #14181c;          /* полотно таблицы */
  --band: #1c2127;           /* шапка таблицы, панели, карточки */
  --band-hi: #252b33;
  --field: #11151a;          /* поля ввода */
  --line: #2f363f;           /* линии сетки — разделитель, не элемент */
  --line-soft: #222830;
  --ctl-line: #606c7b;       /* рамки кнопок и полей: 3.4:1 к подложке */
  --row-alt: #181c21;        /* зебра */
  --row-hover: #202730;
  --row-sel: #10303a;

  /* --- текст: три уровня, нижний тоже проходит 4.5:1 ------------------ */
  --text: #e7ecf1;
  --muted: #9aa5b3;
  --faint: #838e9c;

  /* --- акцент: штормовой циан ---------------------------------------- */
  --accent: #4ccbe3;
  --accent-hi: #8ce0f0;
  --accent-lo: #2ba7c0;
  --accent-dim: #123742;     /* подложка активного пункта и плашки */
  --accent-edge: #2f7387;
  --accent-text: #bfeaf5;    /* текст на --accent-dim, 9.9:1 */
  --on-accent: #062028;      /* текст на заливке акцентом, 8.8:1 */
  --focus: rgba(76, 203, 227, .38);

  /* --- семафор -------------------------------------------------------- */
  --ok: #74d98b;
  --ok-dim: #12311f;
  --ok-edge: #36774c;
  --warn: #f0c256;
  --warn-dim: #352a10;
  --warn-edge: #7d6526;
  --err: #f28b82;
  --err-dim: #3a201e;
  --err-edge: #83403a;
  /* Пятый тон — только для карточки персонажа: характеристик там пять,
     а в семафоре цветов четыре. 7.4:1 к полотну карточки. */
  --violet: #b09bf0;

  /* --- размеры -------------------------------------------------------- */
  --radius: 10px;
  --radius-sm: 7px;
  --ctl-h: 34px;             /* одна высота у кнопок и полей */
  --shadow: 0 1px 2px rgba(0, 0, 0, .45);
  --shadow-pop: 0 2px 6px rgba(0, 0, 0, .5), 0 12px 28px rgba(0, 0, 0, .35);

  --ui: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
        "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas,
          "Liberation Mono", monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 var(--ui);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --- шапка сайта ----------------------------------------------------- */

header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 20px;
  background: rgba(15, 18, 22, .9);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-right: 16px;
  color: var(--text);
}
.brand:hover { text-decoration: none; }
.brand:hover .mark { color: var(--accent-hi); }

/* Знак — вихрь с клановой иконки: три сужающиеся полосы и хвост. */
.brand .mark {
  flex: none;
  width: 26px;
  height: 26px;
  color: var(--accent);
  transition: color .14s;
}
.brand .name {
  display: grid;
  line-height: 1.12;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.01em;
}
.brand .name small {
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .06em;
  color: var(--faint);
}

header nav { display: flex; gap: 2px; flex-wrap: wrap; }
header nav a {
  padding: 6px 12px;
  border-radius: 999px;
  color: var(--muted);
  font-weight: 500;
  white-space: nowrap;
}
header nav a:hover { background: var(--band); color: var(--text); text-decoration: none; }
/* Активный пункт держится не только цветом: заливка плюс обводка. */
header nav a.on {
  background: var(--accent-dim);
  box-shadow: inset 0 0 0 1px var(--accent-edge);
  color: var(--accent-text);
}
header nav a .badge {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--warn);
  color: #2a2205;
  font-size: 11px;
  font-weight: 700;
}

header .who { margin-left: auto; display: flex; align-items: center; gap: 10px; }
header .who span { color: var(--muted); font-size: 13px; }
header .who em { font-style: normal; color: var(--faint); }

main { max-width: 1180px; margin: 0 auto; padding: 22px 20px 72px; }

h1 {
  font-size: 21px;
  font-weight: 650;
  letter-spacing: -.015em;
  margin: 0 0 4px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
h2 { font-size: 14px; font-weight: 650; margin: 26px 0 9px; letter-spacing: .01em;
     color: var(--muted); text-transform: uppercase; }
.sub { color: var(--muted); margin: 0 0 16px; }

.muted { color: var(--muted); font-weight: 400; }
.faint { color: var(--faint); }
.err { color: var(--err); }
.flash { color: var(--ok); }
.warn { color: var(--warn); }
.warn a { color: inherit; }

/* Сообщение после htmx-свопа должно быть замечено: короткая подсветка. */
.flash, #queue > .err, #attendance > .err {
  display: block;
  margin: 0 0 10px;
  padding: 7px 11px;
  border-radius: var(--radius-sm);
  animation: rise .16s ease-out;
}
.flash { background: var(--ok-dim); box-shadow: inset 0 0 0 1px var(--ok-edge); }
#queue > .err, #attendance > .err {
  background: var(--err-dim);
  box-shadow: inset 0 0 0 1px var(--err-edge);
}

@keyframes rise { from { opacity: 0; transform: translateY(-3px); } }
@keyframes fade { from { opacity: 0; } }

/* --- таблица --------------------------------------------------------- */

.sheet {
  background: var(--sheet);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: auto;
  max-height: calc(100vh - 210px);
  overscroll-behavior: contain;
}

table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* Зебра вместо сетки: одно из двух, иначе плотная таблица рябит. */
th, td {
  text-align: left;
  padding: 6px 12px;
  line-height: 1.45;
  white-space: nowrap;
  border: 0;
}

thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--band);
  box-shadow: inset 0 -1px 0 var(--line);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding-top: 8px;
  padding-bottom: 8px;
  user-select: none;
}
thead th[data-sort] { cursor: pointer; }
thead th[data-sort]:hover { background: var(--band-hi); color: var(--text); }
/* Стрелка занимает своё место всегда — колонка не дёргается при сортировке. */
thead th[data-sort]::after {
  content: "▾";
  display: inline-block;
  width: 9px;
  margin-left: 5px;
  font-size: 9px;
  opacity: 0;
}
thead th[data-sort]:hover::after { opacity: .4; }
thead th.asc, thead th.desc {
  background: var(--accent-dim);
  color: var(--accent-text);
  box-shadow: inset 0 -2px 0 var(--accent), inset 0 -1px 0 var(--line);
}
thead th.asc::after { content: "▴"; opacity: 1; }
thead th.desc::after { content: "▾"; opacity: 1; }

tbody tr:nth-child(even) > td { background: var(--row-alt); }
tbody tr.me > td { background: var(--row-sel); }
tbody tr:hover > td { background: var(--row-hover); }
tbody tr { transition: none; }
tbody td { transition: background .1s; }

td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.rank { width: 46px; color: var(--faint); text-align: right; }
td.name { font-weight: 550; }
/* Выбывший приглушён, но остаётся читаемым: 4.5:1 держится. */
tr.off td { color: var(--faint); }
tr.off td.name { font-weight: 450; }
td.date { color: var(--muted); font-size: 13px; }
td.bad, td.num.bad { color: var(--warn); font-weight: 600; }

.empty td {
  color: var(--muted);
  text-align: center;
  padding: 30px 14px;
  white-space: normal;
  line-height: 1.7;
}
.empty td a { font-weight: 600; }

/* Цвет — как условное форматирование в таблице: цифра и так видна, цвет
   нужен, чтобы провал в явке бросался в глаза при прокрутке. Заливка только
   под долей: покрасить фоном и был, и пропустил — получить стену цвета,
   в которой уже ничего не выделяется. */
td.went { color: var(--ok); font-weight: 650; }
td.went.zero { color: var(--faint); font-weight: 400; }
td.missed { color: var(--err); }
td.missed.zero { color: var(--faint); }

.bar { min-width: 172px; }
.bar .wrap { display: flex; align-items: center; gap: 10px; }
.bar .track {
  position: relative;
  flex: 1;
  height: 8px;
  border-radius: 999px;
  background: #2a323b;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
  overflow: hidden;
}
.bar .fill { position: absolute; inset: 0 auto 0 0; border-radius: 999px; }
.bar .fill.hi  { background: var(--ok); }
.bar .fill.mid { background: var(--warn); }
.bar .fill.low { background: var(--err); }
.bar .pct {
  width: 36px;
  text-align: right;
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.bar .pct.hi { color: var(--ok); }
.bar .pct.mid { color: var(--warn); }
.bar .pct.low { color: var(--err); }
.bar .pct.zero { color: var(--faint); }

.pill {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--band-hi);
  box-shadow: inset 0 0 0 1px var(--line);
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
a.pill:hover { text-decoration: none; filter: brightness(1.18); }
.pill.ok { background: var(--ok-dim); box-shadow: inset 0 0 0 1px var(--ok-edge); color: var(--ok); }
.pill.warn { background: var(--warn-dim); box-shadow: inset 0 0 0 1px var(--warn-edge); color: var(--warn); }
.pill.err { background: var(--err-dim); box-shadow: inset 0 0 0 1px var(--err-edge); color: var(--err); }
.pill.accent { background: var(--accent-dim); box-shadow: inset 0 0 0 1px var(--accent-edge); color: var(--accent-text); }

/* --- поля ввода ------------------------------------------------------ */

input, button, select, textarea { font: inherit; }

input[type=text], input[type=password], input[type=number], input[type=date],
input[type=datetime-local], input:not([type]), select, textarea {
  height: var(--ctl-h);
  color: var(--text);
  background: var(--field);
  border: 1px solid var(--ctl-line);
  border-radius: var(--radius-sm);
  padding: 0 10px;
  transition: border-color .12s, box-shadow .12s, background .12s;
}
textarea { height: auto; padding: 8px 10px; }
input:hover:not(:disabled), select:hover { border-color: #7a8593; }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus);
  background: #131920;
}
input::placeholder { color: var(--faint); }
input:disabled { opacity: .55; }

select {
  appearance: none;
  padding-right: 34px;
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) 52%, calc(100% - 13px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
select option { background: #1b1d21; color: var(--text); }

/* Родной календарик и стрелки числового поля светлые сами по себе —
   инвертируем иконку, а не оставляем белое пятно. */
::-webkit-calendar-picker-indicator { filter: invert(.75); cursor: pointer; }

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--ctl-h);
  padding: 0 14px;
  border: 1px solid var(--ctl-line);
  border-radius: var(--radius-sm);
  background: var(--band);
  color: var(--text);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, border-color .12s, color .12s;
}
button:hover, .btn:hover { background: var(--band-hi); border-color: #7a8593; text-decoration: none; }
button:active, .btn:active { background: #2c333c; transform: translateY(1px); }
button:disabled, button[disabled] { opacity: .55; cursor: progress; transform: none; }

button.primary, .btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
button.primary:hover, .btn.primary:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
button.primary:active { background: var(--accent-lo); border-color: var(--accent-lo); }

button.ghost { background: transparent; }
button.ghost:hover { background: var(--band-hi); }

button.flat {
  height: 24px;
  border-color: transparent;
  background: none;
  color: var(--faint);
  padding: 0 7px;
}
button.flat:hover { background: var(--err-dim); color: var(--err); border-color: var(--err-edge); }
/* Переключатель «в клане» — не удаление, красным мигать ему незачем. */
button.flat.toggle { padding: 0; height: auto; }
button.flat.toggle:hover { background: none; border-color: transparent; filter: brightness(1.22); }

label.field { display: grid; gap: 5px; color: var(--muted); font-size: 11.5px;
              text-transform: uppercase; letter-spacing: .05em; font-weight: 700; }
label.field input, label.field select { width: 100%; }

.card {
  background: var(--band);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  box-shadow: var(--shadow);
}

.toolbar {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.toolbar .spacer { margin-left: auto; }

/* --- вход ------------------------------------------------------------ */

.login { max-width: 340px; margin: 8vh auto; display: grid; gap: 14px; padding: 24px 26px 26px; }
.login h1 { margin-bottom: 2px; }
.login input { width: 100%; }
.login button { width: 100%; }

/* --- загрузка -------------------------------------------------------- */

.upload { display: grid; gap: 16px; }
.upload .row { display: grid; grid-template-columns: minmax(260px, 1fr) auto;
               gap: 12px; align-items: end; }
.upload button { justify-self: start; }

.drop {
  display: grid;
  place-items: center;
  gap: 3px;
  padding: 24px 18px;
  border: 2px dashed #4b5562;
  border-radius: var(--radius);
  background: var(--field);
  text-align: center;
  cursor: pointer;
  transition: border-color .14s, background .14s;
}
.drop:hover { border-color: var(--accent-lo); background: #131b20; }
/* Перетаскивание над зоной: рамка сплошная, знак подпрыгивает — видно, что
   отпускать можно именно здесь. */
.drop.over { border-style: solid; border-color: var(--accent); background: var(--accent-dim); }
.drop input[type=file] { display: none; }
.drop .ico { width: 30px; height: 30px; color: var(--faint); transition: color .14s, transform .14s; }
.drop:hover .ico { color: var(--accent-lo); }
.drop.over .ico { color: var(--accent); transform: translateY(-3px); }
.drop .title { font-weight: 650; }
.drop .hint { color: var(--muted); font-size: 13px; }
.drop .picked:not(:empty) {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
  width: 100%;
  max-width: 420px;
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 650;
  text-align: left;
}
.drop .picked ul {
  margin: 5px 0 0;
  padding: 0;
  list-style: none;
  max-height: 132px;
  overflow-y: auto;
  color: var(--muted);
  font: 400 12px/1.65 var(--mono);
}
.drop .picked li { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.result { margin: 10px 0; padding: 13px 16px; animation: rise .16s ease-out; }
.result .head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.result .head b { font-size: 14px; }
.result p { margin: 9px 0 0; }
.result .names { color: var(--muted); font-size: 13px; line-height: 1.6; }
.checksum { color: var(--muted); }
.checksum b { color: var(--text); font-variant-numeric: tabular-nums; }
/* Недосчитанный кадр — единственное, ради чего разбор синхронный: он
   обязан бросаться в глаза, а не теряться среди плашек. */
.checksum.bad {
  margin-left: -16px;
  margin-right: -16px;
  padding: 7px 16px 7px 13px;
  border-left: 3px solid var(--warn);
  background: var(--warn-dim);
  color: var(--warn);
}
.checksum.bad b { color: var(--warn); }
.checksum.bad::before { content: "!"; margin-right: 8px; font-weight: 800; }

.busy-note { display: none; color: var(--muted); }
form.busy .busy-note { display: inline; }
form.busy .busy-note::after {
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  margin-left: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: pulse .9s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .25; } }

/* --- очередь --------------------------------------------------------- */

ol.queue { list-style: none; margin: 0; padding: 0; }
.qrow {
  display: grid;
  grid-template-columns: minmax(160px, 1fr) minmax(0, 2fr) 178px auto;
  gap: 12px;
  align-items: center;
  padding: 9px 14px 9px 11px;
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--line-soft);
}
.qrow:nth-child(even) { background: var(--row-alt); }
.qrow:last-child { border-bottom: 0; }
.qrow:hover { background: var(--row-hover); }
/* Разбирают табом: строка под фокусом должна быть видна через всю комнату. */
.qrow:focus-within { background: var(--row-sel); border-left-color: var(--accent); }

/* Сырое прочтение — моноширинным: так видно подменённую букву и лишний
   пробел, ради которых строка и попала в очередь. */
.qrow .raw { min-width: 0; }
.qrow .text {
  display: block;
  font: 650 14.5px/1.35 var(--mono);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
}
.qrow .meta { display: block; margin-top: 2px; color: var(--faint); font-size: 12px; }

.cands { display: flex; gap: 6px; flex-wrap: wrap; min-width: 0; }
.cand {
  height: 28px;
  padding: 0 8px;
  gap: 7px;
  max-width: 100%;
  overflow: hidden;
  font-weight: 550;
  background: var(--field);
}
.cand .n {
  display: inline-block;
  min-width: 15px;
  padding: 1px 0;
  border-radius: 4px;
  background: var(--band-hi);
  color: var(--faint);
  font: 700 10px/1.4 var(--mono);
  text-align: center;
}
.cand .sc { color: var(--faint); font: 600 11px/1 var(--mono); }
/* «Почти точно» — не только зелёным: галочка после счёта, чтобы решение
   читалось и на плохом мониторе. */
.cand.near {
  border-color: var(--ok-edge);
  background: var(--ok-dim);
  color: #d4f3dd;
}
.cand.near .n { background: #1b4a2d; color: var(--ok); }
.cand.near .sc { color: var(--ok); }
.cand.near::after { content: "✓"; color: var(--ok); font-size: 11px; font-weight: 800; }
.cand.near:hover { background: #1a4029; border-color: var(--ok); }

.qrow form.pick { margin: 0; }
.qrow form.pick input { width: 100%; font-family: var(--mono); font-size: 13px; }
.acts { display: flex; gap: 6px; }
.acts button { height: 28px; padding: 0 10px; font-size: 13px; }
.acts .dismiss:hover { background: var(--err-dim); border-color: var(--err-edge); color: var(--err); }
.acts .new-player:hover { background: var(--accent-dim); border-color: var(--accent-edge); color: var(--accent-text); }

/* --- ивенты ---------------------------------------------------------- */

.new-event {
  display: grid;
  grid-template-columns: 1.4fr 1fr .5fr auto;
  gap: 12px;
  align-items: end;
  margin-bottom: 18px;
}
.new-event label.wide { grid-column: 1 / -1; }
.new-event input { width: 100%; }

.meta-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             margin: 0 0 18px; color: var(--muted); }

form.add { display: flex; gap: 8px; margin-bottom: 12px; }

/* --- выдача ---------------------------------------------------------- */

.new-loot {
  display: grid;
  grid-template-columns: 1.4fr .45fr 1.2fr auto;
  gap: 12px;
  align-items: end;
  margin-bottom: 14px;
}
.new-loot input { width: 100%; }
.months { margin-bottom: 12px; }
td.qty { font-weight: 650; }

/* --- учётки ---------------------------------------------------------- */

.new-user {
  display: grid;
  grid-template-columns: 1.2fr .7fr 1fr auto;
  gap: 12px;
  align-items: end;
  margin-bottom: 12px;
}
.new-user input { width: 100%; }

/* Выданный пароль — крупно и моноширинно: его переписывают руками или
   копируют, и «l» с «1» тут путать нельзя. */
.issued {
  margin-bottom: 14px;
  border-color: var(--ok-edge);
  background: var(--ok-dim);
  animation: rise .16s ease-out;
}
.issued p { margin: 0 0 10px; }
.issued code {
  display: inline-block;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg);
  font: 600 17px/1.3 var(--mono);
  letter-spacing: .03em;
  user-select: all;
}

.err.boxed {
  margin: 0 0 12px;
  padding: 7px 11px;
  border-radius: var(--radius-sm);
  background: var(--err-dim);
  box-shadow: inset 0 0 0 1px var(--err-edge);
}

.switch {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 12px;
}
.switch > div { flex: 1; min-width: 0; }
.switch p { margin: 4px 0 0; font-size: 13px; }
.switch.on { border-color: var(--ok-edge); }

table.users select { min-width: 120px; }
table.users td { vertical-align: middle; }

/* Карандаш проявляется на строке под курсором: подчёркивать каждый ник
   пунктиром — рябить всю таблицу ради подсказки, нужной раз в месяц. */
/* Сам ник — ссылка на карточку персонажа, поэтому цвет у него обычный:
   подкрашивать акцентом каждую строку таблицы значило бы залить синим весь
   рейтинг. Подчёркивание под курсором говорит о ссылке ровно там, где на
   неё смотрят. */
.nick a { color: inherit; border-radius: 4px; }
.nick a:hover { color: var(--accent); }
.nick .pencil { margin-left: 7px; font-style: normal; font-size: 12px;
                color: var(--faint); opacity: 0; cursor: pointer;
                transition: opacity .12s, color .12s; }
tr:hover .nick .pencil, .qrow:hover .nick .pencil { opacity: 1; }
.nick .pencil:hover, .nick .pencil:focus-visible { color: var(--accent); opacity: 1; }
/* --- класс персонажа --- */

/* Только иконка, без подписи: название висит в title и в alt. Колонка узкая
   и фиксированной ширины — и с классом, и без него ячейка занимает те же
   22 пикселя, поэтому при сортировке ничего не дёргается. */
td.klass { width: 1%; padding-left: 14px; padding-right: 14px; }
/* Только значок, не ячейка: у <td> тот же класс klass, и inline-flex на нём
   выключал табличную раскладку — ячейка сжималась до ширины иконки, а
   остаток колонки оставался без фона строки. */
span.klass { display: inline-flex; align-items: center; border-radius: 5px; }
.klass img, .klass .none {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  /* Иконки вырезаны с плотным тёмным фоном — на полотне таблицы он читается
     как рамка, поэтому подложка своя, а не прозрачная дыра. */
  background: var(--band-hi);
  box-shadow: inset 0 0 0 1px var(--line);
  flex: none;
}
.klass .none {
  display: grid;
  place-items: center;
  color: var(--faint);
  font-style: normal;
  font-size: 12px;
}
tr.off .klass img { opacity: .55; }

/* Подписи нет, значит нет и места под карандаш: о том, что ячейка правится,
   говорит сама иконка — под курсором она подсвечивается рамкой акцента. */
.klass.edit { cursor: pointer; }
.klass.edit:hover img, .klass.edit:focus-visible img,
.klass.edit:hover .none, .klass.edit:focus-visible .none {
  box-shadow: inset 0 0 0 1px var(--accent-edge), 0 0 0 2px var(--accent-dim);
  color: var(--accent);
}

form.klass { margin: -3px 0; }
form.klass select { height: 28px; padding: 0 26px 0 8px; }

form.nick { display: flex; gap: 6px; align-items: center; margin: -3px 0; }
form.nick input { height: 28px; width: 100%; min-width: 120px; }
form.nick button { height: 28px; padding: 0 10px; }

/* --- карточка персонажа ---------------------------------------------- */

/* Шапка карточки: крупная иконка класса, ник и строчка приметных величин.
   Иконка тут в 64 пикселя, а не в 22, как в таблице, — на карточке смотрят
   на одного человека, и класс должен читаться с другого конца комнаты. */
.hero {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 18px;
}
.hero .face img, .hero .face .none {
  width: 64px;
  height: 64px;
  border-radius: 12px;
  background: var(--band-hi);
  box-shadow: inset 0 0 0 1px var(--line);
  display: grid;
  place-items: center;
  color: var(--faint);
  font-style: normal;
  font-size: 22px;
}
.hero .who { min-width: 0; }
.hero h1 { margin: 0 0 6px; }
.hero .meta-line { margin: 0; }
.hero > .hero-acts { margin-left: auto; display: flex; gap: 8px; align-items: center; }

.stats { max-width: 960px; }
/* Строки слева, пятиугольник справа; на узком экране — друг под другом. */
.stats .body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 8px 28px;
  align-items: center;
}
.stats .head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.stats .head h2 { margin: 0; }
.stats .head button { margin-left: auto; }
.stats .head button + button { margin-left: 0; }
.stats .err.line { margin: 6px 0 0; color: var(--err); }
.stats .foot { margin-top: 12px; }

/* Строка на характеристику, столбцы общие для всей карточки: название,
   число, полоска, доля. Числа стоят в одной колонке и выровнены по правому
   краю — так их сравнивают и между собой, и с чужой карточкой. */
.stats .grid { display: grid; margin: 0; }
.stats .stat {
  display: grid;
  grid-template-columns: 116px 104px minmax(80px, 1fr) 46px;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
}
/* Разделитель, а не рамка у каждой строки: линий должно быть на одну
   меньше, чем строк, иначе карточка становится решёткой. */
.stats .stat + .stat { border-top: 1px solid var(--line-soft); }

.stats dt {
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}
/* Цвет закреплён за характеристикой и красит число, полоску и поле ввода:
   на карточке он работает как подпись — строку находят, не читая названия.
   Тона взяты из семафора, кроме магической защиты: пятого значения там нет,
   и фиолетовый заведён отдельно. */
/* Одна раскладка цветов на карточку, пятиугольник и колонки ростера:
   ХП везде зелёный, атака везде красная. */
.stats .stat.level, .radar .axis.level { --c: var(--accent); }
.stats .stat.hp,    .radar .axis.hp,   .pts.hp   { --c: var(--ok); }
.stats .stat.atk,   .radar .axis.atk,  .pts.atk  { --c: var(--err); }
.stats .stat.pdef,  .radar .axis.pdef, .pts.pdef { --c: var(--warn); }
.stats .stat.mdef,  .radar .axis.mdef, .pts.mdef { --c: var(--violet); }

.stats dd {
  margin: 0;
  font-size: 20px;
  font-weight: 650;
  line-height: 1.2;
  text-align: right;
  color: var(--c, var(--text));
  font-variant-numeric: tabular-nums;
}
/* Незаполненное отличается от нуля и на вид: прочерк приглушён и бесцветен.
   Полоски нет и там, где сравнивать не с чем — пустое значение, класс не
   проставлен, в классе заполнил один. Место под неё остаётся: иначе строки
   разъедутся по высоте. */
.stats .stat.empty dd { color: var(--faint); font-weight: 400; }
.stats .track.none { visibility: hidden; }

.stats .track {
  position: relative;
  height: 8px;
  border-radius: 999px;
  background: #2a323b;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
  overflow: hidden;
}
/* Засечка посередине — ровно средний по классу, 5,0 балла (шкала идёт до
   двух средних, stats.BAR_CAP). Рисуется поверх заливки, иначе у того, кто выше среднего,
   она пропала бы под цветом — а это как раз тот случай, где её ищут. */
.stats .track::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: var(--band);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18);
}
.stats .fill {
  height: 100%;
  border-radius: 999px;
  background: var(--c, var(--accent));
  transition: width .18s ease-out;
}
.stats .pct {
  text-align: right;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--c, var(--text));
  font-variant-numeric: tabular-nums;
}
.stats .pct.off { color: var(--faint); font-weight: 400; cursor: help; }
/* Ниже среднего — балл приглушён, выше — в цвете характеристики. Красным
   не красим: красный здесь уже занят атакой. */
.stats .stat.below .pct { color: var(--muted); font-weight: 600; }
.stats .pct[title] { cursor: help; }

/* Правка идёт теми же строками: название на месте названия, поле на месте
   числа. Колонок две — полоске и доле в форме делать нечего. */
.stats.editing .stat { grid-template-columns: 116px minmax(120px, 210px); }
.stats.editing .lbl {
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.stats.editing input {
  width: 100%;
  height: 32px;
  text-align: right;
  color: var(--c, var(--text));
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.stats.editing input::placeholder { font-weight: 400; }

/* --- пятиугольник -------------------------------------------------- */

/* Как в доте, только с нашими характеристиками. Сетка — бледные кольца
   через каждые 2 балла, сам игрок — залитая акцентом фигура. Цвет вершин тот же, что у строк слева. */
.radar { margin: 0; text-align: center; }
.radar svg { width: 100%; max-width: 300px; height: auto; display: block; margin: 0 auto; }
.radar .ring  { fill: none; stroke: var(--line-soft); stroke-width: 1; }
.radar .spoke { stroke: var(--line); stroke-width: 1; }
.radar .shape {
  fill: rgba(76, 203, 227, .2);
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linejoin: round;
}
.radar .dot { fill: var(--c); stroke: var(--band); stroke-width: 2; }
.radar .lbl {
  fill: var(--muted);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.radar .val { fill: var(--c); font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.radar .missing .val { fill: var(--faint); font-weight: 400; }
.radar-empty { color: var(--faint); font-size: 13px; line-height: 1.6; margin: 0; padding: 20px 8px; }

/* Баллы в ростере — в цвете характеристики, ниже среднего приглушены, как
   на карточке. Колонки узкие: число здесь всегда в четыре знака, «6,1». */
td.pts { color: var(--c); font-weight: 650; width: 1%; }
td.pts.below { color: var(--muted); font-weight: 500; }

/* Телефон: название над числом, полоска во всю ширину под ними. Четыре
   колонки на 360 пикселях сжали бы число до двух цифр. */
@media (max-width: 820px) {
  .stats .body { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .stats .stat { grid-template-columns: 1fr auto; gap: 4px 12px; }
  .stats .track { grid-column: 1; align-self: center; }
  .stats .pct { grid-column: 2; }
  .stats.editing .stat { grid-template-columns: 1fr 120px; }
}

/* --- пресеты периода --- */

.presets { display: flex; gap: 6px; flex-wrap: wrap; padding-bottom: 7px; }
.presets a {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
}
.presets a:hover { background: var(--band); border-color: var(--ctl-line);
                   color: var(--text); text-decoration: none; }
.presets a.on {
  background: var(--accent-dim);
  border-color: var(--accent-edge);
  color: var(--accent-text);
}

/* --- селектор с поиском --- */

.picker { position: relative; }
/* Селектор живёт внутри label.field, а та заголовочная: капслок и разрядка
   не должны протекать в сам список. */
.picker, .picker-list, .picker input {
  text-transform: none;
  letter-spacing: normal;
  font-size: 14px;
  font-weight: 400;
  color: var(--text);
}
.picker input[type=text] { width: 100%; }
.picker.open input[type=text] {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus);
}
.picker-list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 280px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--band);
  border: 1px solid var(--ctl-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
}
.picker-list li {
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.picker-list li small { color: var(--muted); margin-left: 8px; font-variant-numeric: tabular-nums; }
.picker-list li:hover, .picker-list li.on {
  background: var(--accent-dim);
  box-shadow: inset 0 0 0 1px var(--accent-edge);
  color: var(--accent-text);
}
.picker-list li.on small, .picker-list li:hover small { color: var(--accent-text); opacity: .8; }
.picker-list li.none { color: var(--muted); cursor: default; }
.picker-list li.none:hover { background: none; box-shadow: none; color: var(--muted); }

.period { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }

.foot { margin-top: 14px; color: var(--muted); font-size: 13px; max-width: 780px; }

#queue, #attendance { animation: fade .14s ease-out; }

/* --- телефон: офицер догружает скрины с него ------------------------- */

@media (max-width: 860px) {
  .qrow { grid-template-columns: 1fr; padding: 11px 14px 11px 11px; }
  .new-event, .new-user, .new-loot { grid-template-columns: 1fr 1fr; }
  main { padding: 16px 12px 60px; }
  th, td { padding: 7px 10px; }
  .upload .row { grid-template-columns: 1fr; align-items: stretch; }
  .upload button { justify-self: stretch; }
  .sheet { max-height: none; }

  /* На телефоне меню уходит во вторую строку и прокручивается вбок:
     иначе пять пунктов встают столбиком и шапка занимает пол-экрана. */
  header { flex-wrap: wrap; padding: 7px 12px; gap: 6px; }
  .brand { margin-right: auto; gap: 8px; }
  .brand .mark { width: 22px; height: 22px; }
  .brand .name { font-size: 15px; }
  header .who { margin-left: 0; }
  header nav {
    order: 3;
    width: 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  header nav::-webkit-scrollbar { display: none; }
  header nav a { padding: 6px 11px; }
}

/* От 360px: палец требует 40px, таблица прокручивается внутри .sheet
   и не растягивает страницу. */
@media (max-width: 640px) {
  :root { --ctl-h: 40px; }
  .acts { display: grid; grid-template-columns: 1fr 1fr; }
  .acts button, .cand, form.nick button, form.nick input,
  .presets a { height: 40px; }
  .cand { padding: 0 11px; }
  .presets a { padding: 0 14px; }
  button.flat { height: 40px; min-width: 40px; }
  button.flat.toggle { height: auto; min-width: 0; }
  .login { margin: 4vh auto; }
  .new-event, .new-user, .new-loot { grid-template-columns: 1fr; }
  .switch { flex-direction: column; align-items: stretch; }
  h1 { font-size: 19px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
