/* AMS — дизайн-токены из хендоффа. Сетка 8 px, Inter + JetBrains Mono. */
:root{
  --bg-app:#F4F6F9; --bg-surface:#FFFFFF; --bg-subtle:#FAFCFE; --bg-muted:#F8FAFC;
  --bg-calc:#FAFBFC; --bg-row-alt:#FCFDFE; --bg-header:#EEF2F6;
  --bd-strong:#D8DDE3; --bd-medium:#E3E8EE; --bd-subtle:#EEF2F6; --bd-faint:#F2F5F8;
  --tx-primary:#1F2D3D; --tx-secondary:#37475A; --tx-muted:#6B7480; --tx-faint:#96A0AC;
  --blue:#1D8CF0; --blue-hover:#1670C4; --blue-bg:#EAF4FE; --blue-bd:#BFDDFA;
  --green:#1E7E34; --green-hover:#19692C; --green-bg:#E7F3EA; --green-corridor:#D6EBD9;
  --amber:#8A5A00; --amber-bg:#FDF8EC; --amber-bg-tag:#FDF0D9; --amber-bd:#F0DDB4;
  --red:#C0392B; --red-bg:#FBEDEB; --red-bd:#F2C4BD;
  --grey:#CBD3DC;
  /* Цвета серий на графиках: восемь слотов в неизменном порядке. Оттенки не
     подбираются на лету — порядок проверен на различимость, в том числе при
     дальтонизме; девятой серии не бывает, она уходит в «прочие». */
  --s1:#2A78D6; --s2:#EB6834; --s3:#1BAF7A; --s4:#EDA100;
  --s5:#E87BA4; --s6:#008300; --s7:#4A3AA7; --s8:#E34948;
  /* тёмный ряд той же палитры: им рисуют план рядом с фактом своего цвета —
     связь с сезоном видна, а спутать столбик с линией уже нельзя */
  --d1:#0F3F7E; --d2:#9B3A11; --d3:#0C6B49; --d4:#8C5F00;
  --d5:#9A3F60; --d6:#004B00; --d7:#2A2064; --d8:#8A2320;
  /* Девятый и дальше: средств в направлении бывает больше десятка, и на
     восьми цветах они начинали повторяться — два синих слоя в одном
     столбике различить нельзя */
  --s9:#0FA3B1; --s10:#B07AA1; --s11:#7F8C2A; --s12:#C46A00;
  --d9:#08636C; --d10:#6E4865; --d11:#4E5619; --d12:#7A4100;
  --s-other:#96A0AC;
  --p-prep:#DCE9F7; --p-pre:#E5E1F5; --p-comp:#F7E2DC; --p-trans:#E6EDE7;
  --ev-camp:#37475A; --ev-exam:#7A5EA8;
  --row-h:32px;
}
html,body{margin:0;padding:0}
*{box-sizing:border-box}
body{background:var(--bg-app);color:var(--tx-primary);font-family:Inter,"Helvetica Neue",Arial,sans-serif;font-size:15px;-webkit-font-smoothing:antialiased}
a{color:var(--blue);text-decoration:none}
a:hover{color:var(--blue-hover);text-decoration:underline}
input,select,textarea,button{font-family:inherit;font-size:inherit;color:inherit}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--grey);border-radius:6px;border:2px solid var(--bg-app)}
::-webkit-scrollbar-track{background:transparent}
.amsx::-webkit-scrollbar-thumb{border-color:#fff}
.mono{font-family:"JetBrains Mono",ui-monospace,Consolas,monospace}
.tnum{font-variant-numeric:tabular-nums}

/* ---------- каркас ---------- */
.shell{display:flex;height:100vh;width:100%;overflow:hidden;background:var(--bg-app)}
nav.side{width:260px;flex:0 0 auto;background:#fff;border-right:1px solid var(--bd-strong);
  display:flex;flex-direction:column;box-shadow:0 1px 3px rgba(16,24,40,.08);transition:width .16s ease;overflow:hidden}
nav.side.collapsed{width:64px}
.side-logo{height:56px;display:flex;align-items:center;gap:10px;padding:0 14px;border-bottom:1px solid var(--bd-medium);flex:0 0 auto;overflow:hidden}
.side-mark{width:26px;height:26px;border-radius:6px;background:var(--blue);flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:13px;letter-spacing:-.5px}
.side-name{font-weight:600;font-size:15px;letter-spacing:-.2px;white-space:nowrap;line-height:1.15}
/* название по-русски — второй строкой под латинским (закон о русском языке) */
.side-name-ru{display:block;font-size:11px;font-weight:400;letter-spacing:0;color:var(--tx-muted)}
.side-scroll{flex:1 1 auto;overflow-y:auto;overflow-x:hidden;padding:8px 0 16px}
.nav-group{padding:10px 0 2px}
.nav-title{padding:4px 16px 6px;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--tx-faint);white-space:nowrap}
.nav-rule{height:1px;background:var(--bd-medium);margin:6px 14px 8px}
.nav-item{position:relative;display:flex;align-items:center;gap:10px;height:34px;padding:0 16px;font-size:13.5px;color:var(--tx-secondary);cursor:pointer;text-decoration:none}
.nav-item:hover{background:#F1F5F9;text-decoration:none;color:var(--tx-secondary)}
.nav-item.active{background:var(--blue-bg);color:var(--blue);font-weight:600;box-shadow:inset 3px 0 0 var(--blue)}
.nav-item .ico{width:16px;height:16px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:var(--tx-muted)}
.nav-item.active .ico{color:var(--blue)}
.nav-item .lbl{flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nav-badge{flex:0 0 auto;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--blue);color:#fff;font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center}
.nav-dot{position:absolute;top:6px;right:14px;width:7px;height:7px;border-radius:4px;background:var(--blue);border:1.5px solid #fff}
.side-toggle{height:40px;display:flex;align-items:center;gap:10px;padding:0 16px;border-top:1px solid var(--bd-medium);font-size:12.5px;color:var(--tx-muted);cursor:pointer;flex:0 0 auto}
.side-toggle:hover{background:#F1F5F9;color:var(--tx-primary);text-decoration:none}
.side-toggle .ico{width:16px;height:16px;display:flex;align-items:center;justify-content:center}
/* Свёрнутое меню — один класс на nav: оба вида уже в разметке, поэтому свернуть и
   раскрыть можно без перезагрузки. На телефоне меню выезжает всегда полным. */
.nav-rule,.nav-dot,.side-toggle .t-open{display:none}
@media (min-width:821px){
  nav.side.collapsed .side-name,nav.side.collapsed .nav-title,nav.side.collapsed .nav-item .lbl,
  nav.side.collapsed .nav-badge,nav.side.collapsed .side-toggle .t-close{display:none}
  nav.side.collapsed .nav-rule,nav.side.collapsed .nav-dot{display:block}
  nav.side.collapsed .side-toggle .t-open{display:flex}
  /* Человек и выход внизу меню — только для телефона: на компьютере они есть
     в шапке, а внизу меню «Выход» путали со «Свернуть меню» */
  nav.side .side-me,nav.side .side-exit{display:none}
}

.main-col{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
header.top{height:56px;flex:0 0 auto;background:#fff;border-bottom:1px solid var(--bd-strong);display:flex;align-items:center;gap:14px;padding:0 20px}
header.top .lb{font-size:13px;color:var(--tx-muted)}
header.top select{height:30px;min-width:0;border:1px solid var(--bd-strong);border-radius:4px;background:#fff;padding:0 8px;font-size:13px;font-weight:500}
header.top input.q{width:100%;height:30px;border:1px solid var(--bd-strong);border-radius:4px;padding:0 10px;font-size:13px;background:var(--bg-muted)}
.top-user{display:flex;align-items:center;gap:10px;padding-left:14px;border-left:1px solid var(--bd-medium);flex:0 0 auto}
.avatar{width:30px;height:30px;border-radius:15px;background:var(--bg-header);color:var(--tx-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex:0 0 auto}
/* Место под полосу прокрутки держим всегда. Иначе на коротком экране полосы нет,
   а на длинном она появляется, рабочая область становится уже на её ширину — и
   кнопки в шапке, стоявшие в строке заголовка, перескакивают на строку ниже.
   При переходе по вкладкам это выглядит как прыгающая вёрстка. */
main.work{flex:1 1 auto;overflow:auto;padding:20px 24px 48px;scrollbar-gutter:stable}

/* ---------- типографика ---------- */
h1.scr{margin:0 0 4px;font-size:28px;font-weight:600;letter-spacing:-.4px}
.crumb{font-size:12px;color:var(--tx-muted);margin-bottom:4px}
/* возврат в строке пути: заметнее остального пути, но тише заголовка */
.crumb a.back{color:var(--blue);text-decoration:none;font-weight:500}
.crumb a.back:hover{text-decoration:underline}
.sub{font-size:13px;color:var(--tx-muted)}
.sec-title{font-size:15px;font-weight:600}
/* Подзаголовок внутри карточки: делит список на части и должен читаться как
   заголовок, а не как пояснение под полем. */
.sub-title{font-size:13.5px;font-weight:600;color:var(--tx-primary);letter-spacing:.01em;
  padding-bottom:4px;border-bottom:1px solid var(--bd-subtle);margin-bottom:10px}
.card-title{font-size:14px;font-weight:600}
.caption{font-size:12px;color:var(--tx-muted)}
.faint{font-size:10.5px;color:var(--tx-faint)}
.kpi-num{font-size:26px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.4px}

/* ---------- элементы ---------- */
.card{background:#fff;border:1px solid var(--bd-strong);border-radius:8px}
.card.pad{padding:14px}
.page-head{display:flex;align-items:flex-start;gap:16px;margin-bottom:14px;flex-wrap:nowrap}
/* Кнопки шапки стоят справа и не прыгают: при переносе строк flex раскладывает
   по «желаемой» ширине, а не по сжатой, и длинный подзаголовок уводил их под
   заголовок — на соседней вкладке с подзаголовком покороче они возвращались
   назад, и кнопка оказывалась то там, то тут. Поэтому шапка идёт одной строкой:
   переносится подзаголовок, а не кнопки. На узком экране перенос возвращается —
   там кнопкам рядом с заголовком уже не поместиться. */
.page-head > .grow{min-width:0}
@media (max-width:1100px){.page-head{flex-wrap:wrap}}
.page-head .acts{display:flex;align-items:center;gap:8px;flex:0 0 auto;padding-top:22px;flex-wrap:wrap}

.btn{height:32px;padding:0 12px;border:1px solid var(--bd-strong);border-radius:4px;background:#fff;
  display:inline-flex;align-items:center;gap:6px;font-size:13px;cursor:pointer;color:var(--tx-primary);white-space:nowrap}
.btn:hover{border-color:var(--blue);color:var(--blue);text-decoration:none}
.btn.primary{background:var(--green);border-color:var(--green);color:#fff;font-weight:500}
.btn.primary:hover{background:var(--green-hover);border-color:var(--green-hover);color:#fff}
.btn.blue{background:var(--blue);border-color:var(--blue);color:#fff;font-weight:500}
.btn.blue:hover{background:var(--blue-hover);border-color:var(--blue-hover);color:#fff}
.btn.danger{color:var(--red)}
.btn.danger:hover{border-color:var(--red);background:var(--red-bg);color:var(--red)}
.btn.sm{height:28px;padding:0 10px;font-size:12px}
/* Часы лентой: один столбик — один час. Прокручивается вбок, потому что суток
   трое, а не один экран; разделитель дня не даёт потерять, где кончился четверг. */
.wxhours{display:flex;align-items:stretch;gap:2px;min-width:max-content;padding-bottom:4px}
.wxh{flex:0 0 58px;text-align:center;padding:6px 2px;border-radius:4px;
  border:1px solid transparent}
.wxh:hover{background:var(--bg-muted)}
.wxh .t{font-size:11px;color:var(--tx-muted)}
.wxh .v{font-size:15px;font-weight:600;margin-top:2px}
.wxh .w{font-size:11px;color:var(--tx-muted)}
.wxh .p{font-size:11px;color:var(--blue);min-height:14px}
/* влажность: при сухом воздухе снег абразивный, при влажном липнет */
.wxh .hm{font-size:11px;color:var(--tx-muted);min-height:14px}
.wxh .hm.hi{color:var(--blue);font-weight:600}
/* служба сказала «осадков не будет»: это не то же, что «числа нет» */
.wxh .p.zero{color:var(--tx-faint)}
.wxh .pp{font-size:10px;color:var(--tx-faint)}
.wxh .pp.hi{color:var(--blue);font-weight:600}
/* снегопад — отдельной строкой: «2 мм» и «2 см снега» на склоне разные вещи */
.wxh .sn{font-size:11px;color:var(--tx-muted);min-height:14px}
.wxh .sn.hi{color:var(--violet, #6a3fb5);font-weight:600}
/* час ниже нуля: по нему и выбирают, когда ехать */
.wxh.cold{background:var(--blue-bg)}
.wxhday{flex:0 0 auto;align-self:stretch;display:flex;flex-direction:column;
  justify-content:center;padding:0 10px;margin-right:2px;
  border-left:2px solid var(--blue-bd)}
.wxhday .d{font-size:12px;font-weight:600}
.wxhday .n{font-size:11px;color:var(--tx-muted)}
/* Итоговая строка таблицы: она не одна из перечисленных, а вывод из них —
   в списке служб это сводка, которой и пользуются. */
.t tbody tr.sumrow>td{background:var(--blue-bg);border-top:1px solid var(--blue-bd)}
/* Кнопка ведёт туда, где пока пусто: нажать можно, но видно, что данных там
   нет. Нужна дням прогноза, которые ещё не спрашивали. */
.btn.dim{color:var(--tx-faint);border-color:var(--bd-subtle)}
.btn.dim:hover{color:var(--blue);border-color:var(--blue)}
.btn.wz{height:34px;padding:0 16px}
.btn[disabled],.btn.off{background:var(--grey);border-color:var(--grey);color:#fff;cursor:not-allowed}
.btn.off:hover{background:var(--grey);border-color:var(--grey);color:#fff}

.inp{height:30px;border:1px solid var(--bd-strong);border-radius:4px;padding:0 8px;font-size:13px;background:#fff;width:100%}
.inp:focus{outline:none;border-color:var(--blue)}
textarea.inp{height:auto;padding:6px 8px;line-height:1.45}
.field{margin-bottom:12px}
/* Строка «поле + кнопка»: у поля снизу свои 12px, и кнопка,
   выровненная по нижнему краю, съезжает под список. */
.crewrow .field{margin-bottom:0}
.field .lb{font-size:11px;color:var(--tx-muted);margin-bottom:3px}

.tabs{display:flex;border:1px solid var(--bd-strong);border-radius:4px;overflow:hidden}
.tabs a,.tabs button{padding:0 12px;height:28px;display:flex;align-items:center;font-size:13.5px;color:var(--tx-secondary);
  background:#fff;border:none;border-right:1px solid var(--bd-strong);white-space:nowrap;cursor:pointer}
.tabs a:last-child,.tabs button:last-child{border-right:none}
.tabs a:hover,.tabs button:hover{background:var(--bg-muted);text-decoration:none}
.tabs a.on,.tabs button.on{background:var(--blue-bg);color:var(--blue);font-weight:600}

.tag{display:inline-flex;align-items:center;height:18px;padding:0 7px;border-radius:9px;font-size:11px;font-weight:600;white-space:nowrap}
.tag.ok{background:var(--green-bg);color:var(--green)}
.tag.warn{background:var(--amber-bg-tag);color:var(--amber)}
.tag.bad{background:var(--red-bg);color:var(--red)}
.tag.info{background:var(--blue-bg);color:var(--blue)}
.tag.mute{background:var(--bg-header);color:var(--tx-muted)}
.tag.spec{background:var(--red-bg);color:var(--red);border:1px solid var(--red-bd)}

/* Справка-плашка: та же геометрия, что у свёрнутой справки (details.infobox),
   чтобы рядом они читались как одно семейство, а не как разные по важности */
.banner{border-radius:6px;padding:8px 12px;font-size:13px;margin-bottom:12px;line-height:1.45}
.banner.info{background:var(--blue-bg);border:1px solid var(--blue-bd)}
/* ссылка-плашка ведёт себя как плашка, а не как ссылка */
a.banner{display:block;text-decoration:none;color:inherit}
.banner.warn{background:var(--amber-bg);border:1px solid var(--amber-bd)}
.banner.bad{background:var(--red-bg);border:1px solid var(--red-bd)}
.banner b{font-weight:600}

.grid-kpi{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}
.grid-sum{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:8px}
.two-col{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:16px}
/* содержимое колонки прокручивается внутри себя, а не растягивает страницу */
.two-col > *{min-width:0}
/* Схема и карточка: ширину карточке задают её поля, а не ширина экрана —
   в долях она разрасталась, и половина её оставалась пустой. Остальное
   место уходит схеме, которой его всегда мало. */
.two-col.orgtwo{grid-template-columns:minmax(0,1fr) minmax(0,560px)}
/* Часть карточки: отчёркнута от предыдущей одинаково во всех карточках */
.cardsec{border-top:1px solid var(--bd-subtle);margin-top:14px;padding-top:14px}
.grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px}
.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}
/* Форма в узкой карточке: сколько полей встанет в ряд, решает ширина, а не
   число полей. Тремя столбцами в боковой карточке подпись «ответственный за
   дисциплину» сжимается до полутора слов. */
.formgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(0,240px));gap:10px 14px}
/* display в правиле класса сильнее браузерного [hidden]: скрытый блок остался бы
   на экране, и форма показывала бы места всех команд разом */
.formgrid[hidden]{display:none}
.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 16px}
/* Форма, поля которой заполняют по порядку бланка: каждое занимает свою
   ячейку целиком. Пока ширину задавали полю поимённо, в колонке по 240
   точек оставались пустые хвосты, и строка читалась рвано. Поле, которому
   нужна вся строка — перечень галочек, длинное название, — берёт её
   классом wide. */
/* Свёрнутый бланк: заголовок кликается, стрелка слева, развёрнутый
   отделяется от содержимого отступом. Иначе он читается как служебная
   «деталька», а это главная форма экрана. */
.foldform > summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px}
.foldform > summary::-webkit-details-marker{display:none}
.foldform > summary::before{content:'▸';color:var(--tx-muted);font-size:12px}
.foldform[open] > summary::before{content:'▾'}
.foldform[open] > summary{margin-bottom:4px}
/* min-width:0 обязателен: длинные варианты списка иначе раздвигают
   ячейку, и ряд перестаёт быть ровным */
.formgrid.even .inp{width:100%;max-width:100%;min-width:0}
.formgrid.even .field.wide{grid-column:1/-1}
@media(max-width:1100px){.two-col,.grid3,.grid4{grid-template-columns:1fr}}

/* ---------- таблицы ---------- */
.tw{background:#fff;border:1px solid var(--bd-strong);border-radius:8px;overflow:auto}
table.t{border-collapse:separate;border-spacing:0;width:100%;font-size:13px}
table.t.dense{font-size:12.5px}
table.t thead th{position:sticky;top:0;z-index:2;background:var(--bg-header);border-bottom:1px solid var(--bd-strong);
  padding:8px 10px;text-align:left;font-size:11px;font-weight:600;color:var(--tx-muted);
  text-transform:uppercase;letter-spacing:.03em;white-space:nowrap}
table.t tbody td{border-bottom:1px solid var(--bd-subtle);padding:0 10px;height:var(--row-h);vertical-align:middle}
table.t tbody tr:nth-child(even){background:var(--bg-row-alt)}
table.t tbody tr:hover{background:var(--bg-muted)}
/* строка, которую сейчас смотрят: списки прохождений открывают данные ниже на
   той же странице, и без отметки непонятно, чья это таблица */
table.t tbody tr.sel,table.t tbody tr.sel:nth-child(even){background:var(--blue-bg);box-shadow:inset 3px 0 0 var(--blue)}
table.t tbody tr.sel td.sticky{background:var(--blue-bg)}
table.t td.calc,table.t td.num{text-align:right;font-variant-numeric:tabular-nums}
table.t th.num{text-align:right}
table.t td.calc{background:var(--bg-calc);color:var(--tx-secondary)}
/* граница между группами колонок: соседние одинаковые числа иначе читаются
   как одно продолжающееся, особенно когда оба отклонения красные */
table.t th.colsep,table.t td.colsep{border-left:1px solid var(--bd-medium);padding-left:16px}
/* Две шкалы подряд — целевой коридор и выполнение плана — тонкой чертой не
   разделяются: обе светло-серые, на одной высоте, и читаются как одна
   длинная полоса. Здесь граница заметная, а сами шкалы обведены — две
   обведённые фигуры рядом уже не сливаются. */
table.t th.colsep.hard,table.t td.colsep.hard{border-left:2px solid var(--bd-strong)}
table.t td.colsep.hard .scale,table.t td.colsep.hard .bar{border:1px solid var(--bd-strong)}
/* План — факт: подписи колонок длиннее своих чисел, и в одну строку они
   растягивали таблицу за край окна. Здесь подпись переносится, число —
   никогда, а подпись под шкалой держится одной строкой: разорванная
   пополам, она ломала и без того тесные шкалы. */
table.t.mpfd thead th{white-space:normal;line-height:1.25}
table.t.mpfd tbody td.num,table.t.mpfd tbody td.calc{white-space:nowrap}
table.t.mpfd td.colsep.hard .faint{white-space:nowrap}
table.t tr.err td{background:var(--red-bg)}
/* Заголовок части в разборе плана дня: это не строка данных, а граница между
   разнородными частями — средствами, итогами по ним и работой сверх плана.
   Складывать строки разных частей нельзя, и граница должна быть видна. */
/* Предложение занести упражнение: подсказка под клеткой, а не окно поверх —
   её читают краем глаза и чаще всего проходят мимо, и это нормально. */
.exnew{font-size:11.5px;color:var(--amber);line-height:1.3}
.exnew a{color:var(--blue);text-decoration:underline}
table.t tr.grouprow > td{background:var(--bg-header);border-top:2px solid var(--bd-strong);
  padding-top:10px;padding-bottom:7px;font-size:11.5px;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;color:var(--tx-muted)}
table.t tr.grouprow.first > td{border-top:0}
/* пояснение при заголовке — фраза, а не ярлык: обычным шрифтом */
table.t tr.grouprow > td .gnote{font-weight:400;text-transform:none;letter-spacing:0}
table.t tr.grouprow.gm > td{border-top-color:var(--blue-bd);color:var(--blue)}
table.t tr.grouprow.over > td{border-top-color:var(--amber-bd);color:var(--amber);
  background:var(--amber-bg)}
/* Раскрытый старт: продолжение своей строки, а не вставка поверх таблицы.
   Отбивка слева показывает, что это её часть, а не следующая запись. */
table.t tr.rowopen > td{background:var(--bg-muted);padding:0}
/* Ширину ей ставит скрипт по видимой части списка: в разметке этой величины
   нет — ячейка шириной во всю таблицу, а таблица шире экрана. */
/* Поля сроков поездки: одинаковой ширины, переносятся по одному. Ряд из полей
   разной ширины на узком списке рвал форму пополам. */
.racegrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:10px 12px;align-items:flex-end;max-width:1020px}
.rowbox{position:sticky;left:0;box-sizing:border-box;
  border-left:3px solid var(--blue);padding:12px 14px}
table.t tr.wrn td{background:var(--amber-bg)}
table.t td.ov{background:#FEF9EE;color:var(--amber);font-weight:600}
table.t td.sticky,table.t th.sticky{position:sticky;left:0;background:#fff;border-right:1px solid var(--bd-strong);z-index:1}
table.t thead th.sticky{background:var(--bg-header);z-index:3}
table.t tbody tr:nth-child(even) td.sticky{background:var(--bg-row-alt)}
table.t tbody tr:hover td.sticky{background:var(--bg-muted)}
/* вторая закреплённая колонка: у динамики ЭКО рядом с названием показателя стоит
   модель — без неё числа в прокрученной таблице не с чем сравнить */
table.t td.sticky2,table.t th.sticky2{position:sticky;left:260px;background:#fff;
  border-right:1px solid var(--bd-strong);z-index:1}
table.t thead th.sticky2{background:var(--bg-header);z-index:3}
table.t tbody tr:nth-child(even) td.sticky2{background:var(--bg-row-alt)}
table.t tbody tr:hover td.sticky2{background:var(--bg-muted)}
table.t tbody tr.keyrow td.sticky,table.t tbody tr.keyrow td.sticky2{background:var(--amber-bg,#FFF6E5)}
/* Несколько закреплённых колонок подряд: в конструкторе моделей слева стоят
   показатель, единица и пол — без них прокрученные вправо сезоны читаются
   вслепую. Ширины колонок зависят от названий, поэтому смещения расставляет
   скрипт: жёсткие пиксели врут, как только показатель длиннее обычного. */
.tw.stickcols table.t td.stickx,.tw.stickcols table.t th.stickx{
  position:sticky;left:0;background:#fff;z-index:1}
.tw.stickcols table.t .stickx[data-col="1"]{left:var(--sx1,280px)}
.tw.stickcols table.t .stickx[data-col="2"]{left:var(--sx2,430px)}
.tw.stickcols table.t .stickx.edge{border-right:1px solid var(--bd-strong)}
.tw.stickcols table.t thead th.stickx{background:var(--bg-header);z-index:3}
.tw.stickcols table.t tbody tr:nth-child(even) td.stickx{background:var(--bg-row-alt)}
.tw.stickcols table.t tbody tr:hover td.stickx{background:var(--bg-muted)}
.tw.stickcols table.t tbody tr.sumrow td.stickx{background:var(--bg-muted)}
/* Панель отрезка и среза в ЦКП: слева подпись, справа выбор недель, ниже
   срезы. Сетка жёсткая, а кнопка «Весь сезон» стоит всегда (погашенная на
   полном сезоне) — иначе при выборе отрезка строка перестраивалась и всё
   уезжало вбок. */
.cpbar{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:start}
.cpbar-info{min-height:44px}
.cpbar-form{display:flex;gap:8px;align-items:flex-end;justify-content:flex-end;flex-wrap:nowrap}
.cpbar-scopes{display:flex;gap:8px;align-items:center;margin-top:12px;flex-wrap:wrap}
@media (max-width:1100px){.cpbar{grid-template-columns:1fr}.cpbar-form{justify-content:flex-start;flex-wrap:wrap}}
/* итоговая строка обследования: интегральный показатель читают первым, поэтому
   он выделен полосой и жирным, а не теряется среди сорока строк */
table.t tbody tr.keyrow td{background:var(--amber-bg,#FFF6E5);font-weight:600}
table.t tbody tr.keyrow:hover td{background:var(--amber-bg,#FFF6E5)}
table.t tbody tr.keyrow td:first-child{box-shadow:inset 3px 0 0 var(--amber,#B26A00)}
/* тот же смысл колонкой: в срезе команды интегральный показатель — итог всего
   обследования, и его ищут глазами первым, а строки там спортсмены */
table.t th.keycol,table.t td.keycol{background:var(--amber-bg,#FFF6E5)}
table.t td.keycol{font-weight:600}
table.t tbody tr:hover td.keycol{background:var(--amber-bg,#FFF6E5)}
table.t thead th.keycol{box-shadow:inset 0 3px 0 var(--amber,#B26A00)}
/* год над колонками дат обследований: держит взгляд в нужном столбце */
table.t thead th.yhead{background:var(--bg-header);font-size:11px;letter-spacing:.03em;
  color:var(--tx-muted);border-left:1px solid var(--bd-medium);text-align:center}
/* шапка длинного списка не уезжает вверх при его прокрутке */
table.t thead.stick th{position:sticky;top:0;z-index:4;background:var(--bg-header)}
/* название раздела в широкой таблице: сама строка тянется во всю ширину, а подпись
   держится у левого края — при прокрутке вправо видно, к какому разделу строки */
/* Длинная таблица показателей: шапка держится сверху, а строка раздела —
   сразу под ней, пока идут его показатели. Прокрутив к «Аэробным способностям»,
   тренер видит, в каком разделе находится, а не гадает по названиям строк.
   Высоту шапки подставляет скрипт: у таблиц ЭКО она в две строки. */
.tw.stickgrp table.t thead th{position:sticky;top:0;z-index:5;background:var(--bg-header)}
.tw.stickgrp table.t thead th.sticky,.tw.stickgrp table.t thead th.sticky2{z-index:6}
.tw.stickgrp table.t tbody td.grpcell{position:sticky;top:var(--theadh,34px);z-index:4;
  background:var(--bg-muted)}
.tw.stickgrp table.t tbody tr.grp td{position:sticky;top:var(--theadh,34px);z-index:4}
/* Подпись раздела стоит там же, где названия показателей, и не сдвигается ни на
   пиксель при прокрутке: собственный отступ вместо отступа ячейки, иначе на нулевой
   прокрутке она смещена на ширину этого отступа, а потом «доезжает» к краю. */
table.t td.grpcell{padding-left:0}
table.t .grpname{position:sticky;left:0;z-index:2;display:inline-block;
  padding:0 10px;background:var(--bg-muted)}
table.t tr.grp .grpname{background:var(--bg-header)}
table.t tr.grp td{background:var(--bg-header);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.03em;color:var(--tx-muted)}
/* Название блока не уезжает при прокрутке вправо: строка блока растянута на
   всю таблицу, и прижимать её некуда — закрепляем текст внутри неё. Тогда
   подпись едет по своей строке и остаётся над колонкой показателей. */
.stickname{position:sticky;left:10px;display:inline-block;max-width:100%}
.cellinp{width:100%;height:calc(var(--row-h) - 10px);border:1px solid transparent;border-radius:3px;background:transparent;padding:0 4px;font-size:inherit}
.cellinp:hover{border-color:var(--bd-medium)}
.cellinp:focus{outline:none;border-color:var(--blue);background:#fff}
.cellinp.num{text-align:right;font-variant-numeric:tabular-nums}
/* клетка, которая по умолчанию пуста: без рамки её не видно, и блок ввода
   читается как пустая таблица */
.cellinp.box{border-color:var(--bd-subtle);background:#fff}
.cellinp.box:hover{border-color:var(--bd-medium)}
.cellinp.box::placeholder{color:var(--tx-faint);font-size:11px}
/* ячейка, которую документ не дал: обведена, чтобы её нашли и вписали руками */
/* клетка, значение которой уже лежит в базе: видно, что дата закрыта */
.cellinp.hasval{color:var(--green);font-weight:600}
table.t td.isdb{background:var(--green-bg)}
.cellinp.needval{border-color:var(--amber-bd);background:var(--amber-bg)}
/* число не ушло в базу: поле остаётся заполненным, но видно, что оно не сохранено */
.cellinp.cellbad{border-color:var(--red);background:var(--red-bg,#FDECEC)}
/* вспышка после сохранения работает и в клетке таблицы */
table.t td.saved{animation:amsSaved .9s ease-out}
.cellinp.needval:focus{border-color:var(--blue);background:#fff}
.cellsel{width:100%;height:calc(var(--row-h) - 10px);border:1px solid transparent;border-radius:3px;background:transparent;font-size:inherit;padding:0 2px}
.cellsel:hover{border-color:var(--bd-medium)}
.cellsel:focus{outline:none;border-color:var(--blue);background:#fff}
.rowact{display:flex;align-items:center;gap:4px;justify-content:flex-end}
.rowact span{width:22px;height:22px;border-radius:3px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--tx-muted);font-size:13px}
.rowact span:hover{background:#F1F5F9;color:var(--blue)}
.rowact span.del{color:var(--red)}
.rowact span.del:hover{background:var(--red-bg)}
.empty{padding:56px 24px;text-align:center}
.empty .t{font-size:15px;font-weight:600;margin-bottom:6px}
.empty .d{font-size:13px;color:var(--tx-muted);margin-bottom:16px}
.histmark{display:inline-block;width:0;height:0;border-left:6px solid transparent;border-top:6px solid var(--amber);
  position:absolute;top:0;right:0}
.hascell{position:relative}

/* ---------- шкалы ---------- */
.bar{height:8px;border-radius:4px;background:var(--bg-header);position:relative;overflow:hidden}
.bar > i{position:absolute;left:0;top:0;bottom:0;background:var(--blue);border-radius:4px}
.scale{position:relative;height:14px;background:var(--bg-header);border-radius:3px}
.scale .cor{position:absolute;top:0;bottom:0;background:var(--green-corridor)}
.scale .mk{position:absolute;top:-2px;width:2px;height:18px;background:var(--tx-primary)}
.scale .m100{position:absolute;top:-2px;width:1px;height:18px;background:var(--tx-faint)}

/* ---------- сетка недель ---------- */
.weeks{border-collapse:separate;border-spacing:0;font-size:11px}
.weeks th,.weeks td{border-bottom:1px solid var(--bd-subtle);border-right:1px solid var(--bd-faint);padding:0 2px;height:26px;text-align:center;white-space:nowrap}
.weeks td.head,.weeks th.head{position:sticky;left:0;background:#fff;z-index:2;text-align:left;padding:0 10px;width:var(--yhead,250px);min-width:var(--yhead,250px);border-right:1px solid var(--bd-strong);font-size:12px}
.weeks tr.auto td{background:var(--bg-calc);color:var(--tx-faint)}
.weeks tr.auto td.head{background:#fff}
.wk{width:40px;min-width:40px}
.resize{cursor:col-resize}

/* ---------- тост ---------- */
#toast{position:fixed;right:24px;bottom:24px;z-index:80;background:var(--tx-primary);color:#fff;padding:12px 16px;
  border-radius:6px;font-size:13px;box-shadow:0 6px 20px rgba(16,24,40,.24);max-width:420px;display:none}
#toast.on{display:block}

/* ---------- модальное окно и правая панель ---------- */
.ovwrap{position:fixed;inset:0;background:rgba(31,45,61,.28);z-index:70;display:flex;justify-content:flex-end}
.ovpanel{width:420px;background:#fff;height:100%;display:flex;flex-direction:column}
.ovpanel .h{padding:16px 20px;border-bottom:1px solid var(--bd-strong)}
.ovpanel .b{flex:1 1 auto;overflow:auto;padding:12px 20px}
.modalwrap{position:fixed;inset:0;background:rgba(31,45,61,.28);z-index:70;display:flex;align-items:center;justify-content:center;padding:24px}
.modal{width:720px;max-width:100%;max-height:86vh;background:#fff;border-radius:8px;display:flex;flex-direction:column;box-shadow:0 6px 20px rgba(16,24,40,.24)}
.modal .h{padding:16px 20px;border-bottom:1px solid var(--bd-strong);display:flex;align-items:center;gap:10px}
.modal .b{flex:1 1 auto;overflow:auto;padding:16px 20px}
.modal .f{padding:12px 20px;border-top:1px solid var(--bd-strong);display:flex;gap:8px;align-items:center}

/* ---------- вход ---------- */
.login-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;background:var(--bg-app);padding:24px}
.login{width:400px;max-width:100%;background:#fff;border:1px solid var(--bd-strong);border-radius:8px;padding:28px}
.login input{width:100%;height:38px;border:1px solid var(--bd-strong);border-radius:6px;padding:0 10px;font-size:13.5px}
.login .go{height:42px;border-radius:6px;background:var(--green);color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:500;cursor:pointer;width:100%;border:none}
.login .go:hover{background:var(--green-hover)}
/* Демонстрационные записи: разложены по службам, в строке человек и его
   должность. Два десятка строк «почта — роль» подряд читаются плохо, и войти
   «за старшего тренера» получалось наугад. Окно входа под такой список шире. */
.login{width:400px}
.login:has(.lgrow){width:560px}
.lgdesk{font-size:11px;font-weight:600;color:var(--tx-muted);text-transform:uppercase;
  letter-spacing:.4px;margin:10px 0 4px}
.lgdesk:first-of-type{margin-top:0}
.lgrow{display:grid;grid-template-columns:1fr auto;gap:2px 10px;padding:4px 6px;
  border-radius:4px;cursor:pointer;line-height:1.35}
.lgrow:hover{background:var(--blue-bg)}
.lgname{font-size:12.5px;font-weight:500}
.lgduty{font-size:11px;color:var(--tx-muted);grid-column:1;grid-row:2}
.lgmail{font-size:11.5px;color:var(--tx-muted);grid-column:2;grid-row:1/3;align-self:center}

/* ---------- согласия ---------- */
.consent{border:1px solid var(--bd-medium);border-radius:6px;padding:12px 14px;margin-bottom:10px;background:#fff}
.consent .row{display:flex;gap:10px;align-items:flex-start}
.consent input[type=checkbox]{width:18px;height:18px;margin-top:1px;flex:0 0 auto}

/* ---------- мобильная рамка ---------- */
.mobframe{width:390px;max-width:100%;border:1px solid var(--bd-strong);border-radius:22px;background:#fff;box-shadow:0 2px 10px rgba(16,24,40,.08);overflow:hidden}
.mobstatus{height:34px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;font-size:11px;color:var(--tx-muted);border-bottom:1px solid var(--bd-subtle)}
.mobbody{padding:14px 16px 20px}
.tapzone{min-height:48px}

/* ---------- степпер ---------- */
/* Полоса шагов мастера: восемь шагов должны укладываться в строку, поэтому
   и кружок, и подпись мельче обычных, а соединители — тонкие */
.stepper{display:flex;align-items:center;justify-content:flex-start;gap:0;margin-bottom:14px;
  flex-wrap:wrap;row-gap:6px}
.stepper .step{display:flex;align-items:center;gap:6px;cursor:pointer;text-decoration:none;
  padding:3px 6px;border-radius:6px}
.stepper .step:hover{background:var(--bg-muted);text-decoration:none}
.step:hover{text-decoration:none}
.stepper .step .n{width:20px;height:20px;border-radius:10px;background:var(--bg-header);color:var(--tx-muted);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex:0 0 auto}
.stepper .step.on .n{background:var(--blue);color:#fff}
.stepper .step.done .n{background:var(--green);color:#fff}
.stepper .step .s{font-size:11.5px;color:var(--tx-muted);white-space:nowrap}
.stepper .step.on .s{color:var(--tx-primary);font-weight:600}
.stepline{height:1px;background:var(--bd-medium);flex:0 0 16px;width:16px;margin:0 2px}

/* ---------- состояния: загрузка, ошибка ---------- */
.skel{background:linear-gradient(90deg,var(--bg-header) 25%,var(--bd-faint) 37%,var(--bg-header) 63%);
  background-size:400% 100%;animation:sk 1.4s ease infinite;border-radius:4px;height:12px}
@keyframes sk{0%{background-position:100% 50%}100%{background-position:0 50%}}
.state{padding:40px 24px;text-align:center}
.state .t{font-size:15px;font-weight:600;margin-bottom:6px}
.state .d{font-size:13px;color:var(--tx-muted);margin-bottom:16px}

/* ---------- служебное ---------- */
.flex{display:flex;align-items:center}
.gap6{gap:6px}.gap8{gap:8px}.gap10{gap:10px}.gap12{gap:12px}.gap14{gap:14px}.gap16{gap:16px}.gap24{gap:24px}
.grow{flex:1 1 auto}
.mb8{margin-bottom:8px}.mb12{margin-bottom:12px}.mb16{margin-bottom:16px}.mb20{margin-bottom:20px}
/* подсказка к полю: значок у подписи и всплывающий текст под полем */
.field{position:relative}
.hinti{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;margin-left:5px;
  padding:0;border:1px solid var(--bd-strong);border-radius:50%;background:var(--bg-surface);
  color:var(--tx-muted);font-size:10px;font-style:italic;font-weight:600;line-height:1;cursor:pointer;vertical-align:middle}
.hinti:hover{color:var(--blue);border-color:var(--blue)}
.hinti[aria-expanded="true"]{color:#fff;background:var(--blue);border-color:var(--blue)}
.hintbox{position:absolute;z-index:30;left:0;top:100%;margin-top:2px;width:340px;max-width:92vw;
  padding:9px 11px;border:1px solid var(--bd-strong);border-radius:6px;background:var(--bg-surface);
  box-shadow:0 8px 20px rgba(16,24,40,.16);font-size:12px;line-height:1.45;color:var(--tx-secondary)}
/* полоса вкладок спортсменов: переносится по ширине карточки, а не уезжает за край */
/* отметка даты отчёта: видно, какие прохождения уйдут в базу и что уже загружено */
.datechip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1px solid var(--bd-medium);
  border-radius:14px;font-size:12.5px;background:var(--bg-surface);cursor:pointer}
.datechip.on{border-color:var(--green);background:var(--green-bg)}
.datechip input{margin:0}
.ecotabs{display:flex;flex-wrap:wrap;gap:4px}
.ecotabs a{display:inline-flex;align-items:center;gap:4px;padding:5px 10px;border:1px solid var(--bd-medium);
  border-radius:6px;background:var(--bg-surface);color:var(--tx-secondary);font-size:12.5px;text-decoration:none}
.ecotabs a:hover{border-color:var(--blue);color:var(--blue)}
.ecotabs a.on{background:var(--blue-bg);border-color:var(--blue-bd);color:var(--blue);font-weight:600}
.ecotabs a.saved{border-color:var(--green);background:var(--green-bg)}
.ecook{color:var(--green);font-weight:600}
.mt4{margin-top:4px}
.mt8{margin-top:8px}.mt12{margin-top:12px}.mt16{margin-top:16px}
.wrap{flex-wrap:wrap}
.right{text-align:right}
.nowrap{white-space:nowrap}
.ok{color:var(--green)}.warn{color:var(--amber)}.bad{color:var(--red)}.muted{color:var(--tx-muted)}
.toolbar{background:#fff;border:1px solid var(--bd-strong);border-radius:8px 8px 0 0;border-bottom:none;padding:10px 12px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.toolbar + .tw{border-radius:0}
.foot{background:#fff;border:1px solid var(--bd-strong);border-top:none;border-radius:0 0 8px 8px;padding:14px}

/* ---------- глобальный поиск (правки, п. 1) ---------- */
.gs-trigger{flex:1 1 180px;max-width:340px;min-width:100px;height:30px;border:1px solid var(--bd-strong);
  border-radius:4px;padding:0 10px;background:var(--bg-muted);display:flex;align-items:center;gap:8px;
  cursor:pointer;color:var(--tx-faint);font-size:13px}
.gs-trigger:hover{border-color:var(--blue)}
.kbd{flex:0 0 auto;font-size:10.5px;border:1px solid var(--bd-medium);border-radius:3px;padding:1px 5px;background:#fff;color:var(--tx-muted)}
.gs-group{margin-bottom:14px}
.gs-group .t{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--tx-faint);margin-bottom:6px}
.gs-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:4px;text-decoration:none;color:var(--tx-primary)}
.gs-item:hover,.gs-item.sel{background:var(--blue-bg);text-decoration:none}
.gs-item .n{font-size:13px;font-weight:500}
.gs-item .s{font-size:11.5px;color:var(--tx-muted)}

/* ---------- дневник ---------- */
table.diary{border-collapse:separate;border-spacing:0;font-size:12.5px}
table.diary th,table.diary td{border-bottom:1px solid var(--bd-subtle);border-right:1px solid var(--bd-faint);
  padding:0 8px;height:28px;white-space:nowrap}
table.diary th{background:var(--bg-header);position:sticky;top:0;z-index:2;font-size:10.5px;font-weight:600;
  color:var(--tx-muted);text-transform:uppercase;letter-spacing:.03em;text-align:center}
table.diary td.metric,table.diary th.metric{position:sticky;left:0;z-index:3;background:#fff;text-align:left;
  min-width:280px;max-width:280px;border-right:1px solid var(--bd-strong);overflow:hidden;text-overflow:ellipsis}
table.diary th.metric{z-index:4}
table.diary td.unit,table.diary th.unit{position:sticky;left:280px;z-index:3;background:#fff;text-align:left;
  min-width:70px;color:var(--tx-muted);border-right:1px solid var(--bd-strong)}
table.diary th.unit{z-index:4;background:var(--bg-header)}
table.diary td.v{text-align:right;font-variant-numeric:tabular-nums}
table.diary td.total,table.diary th.total{background:var(--bg-header);font-weight:600}
table.diary tr.blk td{background:var(--bg-header);font-size:11px;font-weight:600;text-transform:uppercase;
  letter-spacing:.03em;color:var(--tx-muted);cursor:pointer;position:sticky;left:0}
/* Свёрнутое — одним видом на всё приложение.
 *
 * Свёрнутых блоков на экране бывает три подряд: спрятанная форма, длинная
 * таблица и справка. Пока каждый оформлялся по-своему — карточкой в полный
 * рост, голым <details> без рамки, синей плашкой вдвое выше строки, — разнобой
 * читался как разная важность, хотя смысл один: «здесь свёрнуто, разверните».
 * Поэтому у всех одна высота строки, одна рамка и один значок.
 *
 * Собрано на <details>: разворот нативный, без скрипта — страница не
 * перерисовывается и не уезжает наверх.
 *
 * .fold — свёрнутая часть работы (форма, таблица, список).
 * .infobox — справка: то же самое, но голубым, потому что читать необязательно.
 */
details.fold,details.infobox{border:1px solid var(--bd-subtle);border-radius:6px;background:#fff;
  padding:0 12px;margin-bottom:12px}
details.fold > summary,details.infobox > summary{cursor:pointer;list-style:none;display:flex;
  align-items:center;gap:8px;min-height:32px;padding:5px 0;font-size:13px;font-weight:600;
  color:var(--tx-primary);line-height:1.35}
details.fold > summary::-webkit-details-marker,
details.infobox > summary::-webkit-details-marker{display:none}
details.fold > summary::before,details.infobox > summary::before{content:'▸';flex:0 0 auto;
  color:var(--tx-muted);font-size:11px}
details.fold[open] > summary::before,details.infobox[open] > summary::before{content:'▾'}
details.fold > summary:hover,details.infobox > summary:hover{color:var(--blue)}
/* заголовок свёрнутого — строка, а не раздел: крупный шрифт тут спорит с соседями */
details.fold > summary.sec-title,details.infobox > summary.sec-title{font-size:13px}
details.fold > summary .caption,details.fold > summary .faint,
details.infobox > summary .caption,details.infobox > summary .faint{font-weight:400}
details.fold[open],details.infobox[open]{padding-bottom:12px}
details.fold[open] > summary,details.infobox[open] > summary{margin-bottom:10px;
  border-bottom:1px solid var(--bd-subtle)}
/* справка читается как подсказка, а не как предупреждение */
details.infobox{border-color:var(--blue-bd);background:var(--blue-bg)}
details.infobox > summary{color:var(--blue-hover)}
details.infobox > summary::before{color:var(--blue)}
details.infobox[open] > summary{border-bottom-color:var(--blue-bd)}
.ibi{flex:0 0 auto;width:16px;height:16px;border-radius:8px;background:var(--blue);color:#fff;
  font-size:11px;font-weight:700;font-style:italic;display:flex;align-items:center;justify-content:center}
details.infobox .ibhint{font-weight:400;color:var(--tx-muted);font-size:12px}

/* Меню из трёх точек: действия, которых немного и которые не стоят кнопки
   в шапке. Стрелки у него нет — точки сами говорят «здесь ещё что-то» */
.dotsmenu{position:relative;display:inline-block}
.dotsmenu>summary{list-style:none;cursor:pointer;width:32px;height:32px;display:inline-flex;
  align-items:center;justify-content:center;border:1px solid var(--bd-strong);border-radius:4px;
  background:#fff;color:var(--tx-secondary);font-size:16px;line-height:1}
.dotsmenu>summary::-webkit-details-marker{display:none}
.dotsmenu>summary:hover{border-color:var(--blue);color:var(--blue)}
.dotsmenu[open]>summary{border-color:var(--blue);color:var(--blue)}
/* в строке разговора кнопки соседствуют с названием: там нужен размер
   поменьше, иначе строка становится выше самой переписки */
.dotsmenu.sm>summary{width:26px;height:26px;font-size:14px}
/* панель, выставленная скриптом по окну: её не режет прокрутка таблицы */
.dotsbox.fx{position:fixed;top:0;left:0;right:auto;margin:0;width:max-content;
  max-width:calc(100vw - 16px);max-height:calc(100vh - 16px);overflow:auto}
.dotsbox{position:absolute;z-index:40;top:36px;right:0;min-width:320px;max-height:60vh;overflow:auto;
  padding:6px;background:#fff;border:1px solid var(--bd-strong);border-radius:6px;
  box-shadow:0 8px 24px rgba(31,45,61,.14)}
.dotsbox .cmphead{padding:6px 8px 2px}
.dotsrow{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px;border:none;
  background:none;border-radius:4px;font-size:13px;color:var(--tx-primary);text-align:left;
  cursor:pointer;text-decoration:none}
.dotsrow:hover{background:var(--bg-muted);text-decoration:none;color:var(--tx-primary)}
.dotsrow .faint{margin-left:auto}

/* Сообщение: по нему нажимают, чтобы ответить, поэтому это ссылка, а не
   просто пузырь. Цвет и рамка прежние — щелчок не должен выглядеть как
   переход на другой экран */
.msgbox{display:block;background:var(--bg-muted);border:1px solid var(--bd-medium);
  border-radius:10px;padding:8px 12px;font-size:13px;line-height:1.45;color:inherit;text-decoration:none}
.msgbox.mine{background:var(--blue-bg);border-color:var(--blue-bd)}
.msgbox:hover{border-color:var(--blue);text-decoration:none;color:inherit}
/* цитата: узкая полоса слева, как в переписке на бумаге — «вот на это отвечаю» */
.msgq{display:block;border-left:3px solid var(--blue);padding:2px 0 2px 8px;margin-bottom:6px;
  font-size:12px;color:var(--tx-secondary);background:transparent}

/* Чат: слева разговоры, справа переписка. На телефоне рядом они не встают —
   список уезжает наверх и укорачивается, а переписка занимает всю ширину.
   Высоты в vh: на узком экране переписка должна помещаться в экран целиком,
   иначе поле ввода оказывается за нижним краем. */
.chatwrap{display:flex;gap:12px;align-items:flex-start}
.chatlist{flex:0 0 300px;max-width:300px;overflow:hidden}
.chatrows{max-height:62vh;overflow:auto}
.chatmain{min-width:420px;display:flex;flex-direction:column;height:66vh;min-height:440px}
.chathead{display:flex;gap:8px;align-items:center;padding:8px 14px;
  border-bottom:1px solid var(--bd-subtle)}
.chatacts{flex:0 0 auto}
@media (max-width:820px){
  .chatwrap{flex-direction:column}
  .chatlist{flex:1 1 auto;max-width:none;width:100%}
  .chatrows{max-height:34vh}
  .chatmain{min-width:0;width:100%;height:auto;min-height:0;max-height:none}
  .chathead{flex-wrap:wrap;row-gap:6px}
  .chathead .grow{display:none}
  .chatacts{margin-left:auto}
  .dotsbox{min-width:0;width:max-content;max-width:calc(100vw - 32px)}
}
/* Строка списка разговоров: выбранный виден сразу — в чате переключаются
   часто, и «где я сейчас» должно читаться без чтения заголовка */
.chatrow{display:block;padding:9px 12px;border-bottom:1px solid var(--bd-subtle);
  color:inherit;text-decoration:none}
.chatrow:hover{background:var(--bg-subtle);text-decoration:none;color:inherit}
.chatrow.on{background:var(--blue-bg);box-shadow:inset 3px 0 0 var(--blue)}
.chatrow .nav-badge{position:static}

/* короткая подсветка после сохранения: подтверждение без всплывающего текста */
@keyframes amsSaved{from{background:var(--green-bg,#E7F3EA)}to{background:transparent}}
.saved{animation:amsSaved .9s ease-out}

/* плановые объёмы: расчётная ячейка отличается от введённой руками,
   а колонки переездов и выходных закрыты для ввода */
table.diary td span.calc{background:none;color:var(--tx-secondary);font-variant-numeric:tabular-nums}
table.diary td.v.pv-off{background:var(--bg-muted)}

/* итоговая строка блока: «— общее время», общий объём по зонам и по всей работе.
   Жирный здесь несёт смысл — это сумма, а не ещё один показатель наравне с прочими */
table.diary tr.sumrow td{font-weight:600}
table.diary tr.sumrow td.metric{color:var(--tx-primary)}
/* итог в шапке блока показывается только когда блок свёрнут */
table.diary tr.blk td.blksum{text-align:right;font-variant-numeric:tabular-nums;
  text-transform:none;letter-spacing:0;font-weight:600;display:none}
table.diary tr.blk[data-open="0"] td.blksum{display:table-cell}
.src-device{box-shadow:inset 0 -2px 0 var(--green)}
.src-manual{box-shadow:inset 0 -2px 0 var(--amber)}
.src-none{color:var(--tx-faint)}
.zone-1{background:#EAF4FE;color:#1670C4}
.zone-2{background:#E7F3EA;color:#1E7E34}
.zone-3{background:#FDF0D9;color:#8A5A00}
.zone-4{background:#FBEDEB;color:#C0392B}
.zone-5{background:#EDE7F6;color:#5B3FA8}
.zonebox{flex:1 1 0;border:1px solid var(--bd-medium);border-radius:4px;padding:6px 8px;text-align:center}

/* выбор пульсовой зоны в конспекте: цвет тот же, что в отчётах и у спортсмена,
   поэтому зона узнаётся без чтения подписи */
.zonepick{display:flex;align-items:center;gap:6px}
.zdot{width:11px;height:11px;border-radius:50%;flex:0 0 auto;border:1px solid var(--bd-medium);background:transparent}
.zdot.zone-1{background:#1670C4;border-color:#1670C4}
.zdot.zone-2{background:#1E7E34;border-color:#1E7E34}
.zdot.zone-3{background:#8A5A00;border-color:#8A5A00}
.zdot.zone-4{background:#C0392B;border-color:#C0392B}
.zdot.zone-5{background:#5B3FA8;border-color:#5B3FA8}
.zonesel{min-width:96px;font-weight:500}
.zonesel.zone-1,.zonesel.zone-2,.zonesel.zone-3,.zonesel.zone-4,.zonesel.zone-5{border-color:var(--bd-medium)}
.zonelegend{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-top:6px}
.zonelegend span{display:flex;align-items:center;gap:5px}

/* ---------- раскрывающийся отчёт ---------- */
.rep-card{background:#fff;border:1px solid var(--bd-strong);border-radius:8px;overflow:hidden;margin-bottom:8px}
.rep-head{display:flex;align-items:center;gap:12px;padding:11px 14px;cursor:pointer;text-decoration:none;color:inherit}
.rep-head:hover{background:var(--bg-muted);text-decoration:none;color:inherit}
.subrow td{background:var(--bg-subtle)}

/* ---------- выбор варианта в опроснике ---------- */
/* прячем сам переключатель, но оставляем его в потоке: иначе он недоступен с клавиатуры */
.scaleopt { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.scaleopt + .btn { cursor: pointer; user-select: none; }
.scaleopt:checked + .btn {
  background: var(--blue-bg); border-color: var(--blue); color: var(--blue); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--blue);
}
.scaleopt:focus-visible + .btn { outline: 2px solid var(--blue); outline-offset: 1px; }

/* ---------- шапка годового плана ----------
   Девять верхних строк — это и есть план: месяц, неделя, период, этап, задача,
   мероприятие. Раньше они были помечены как служебные и уходили в бледно-серое,
   потому что рассчитываются сами. Но «рассчитано» не значит «второстепенно»:
   цифры объёмов ниже читают уже после того, как поняли, какая это неделя. */
.weeks tr.yh td{height:30px;background:#fff;color:var(--tx-primary);font-size:12px}
.weeks tr.yh td.head{font-weight:600;color:var(--tx-primary)}
.weeks tr.yh td.head .faint{font-weight:400}
.weeks tr.yh td.txt{text-align:left;padding:0 6px}
.weeks tr.yh td.txt span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}

.weeks tr.ymonth td{font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--tx-secondary);border-right:1px solid var(--bd-strong)}
.weeks tr.ynum td{font-weight:700;font-variant-numeric:tabular-nums;font-size:12px}

/* Даты недели: начало и конец в одной колонке шириной 40 пикселей —
   двумя строками, иначе диапазон в неё просто не помещается. */
.weeks tr.ydates td.wk{padding:0;line-height:1.08}
.weeks tr.ydates b{display:block;font-size:10px;font-weight:600;font-variant-numeric:tabular-nums}
.weeks tr.ydates i{display:block;font-size:10px;font-style:normal;color:var(--tx-muted);
  font-variant-numeric:tabular-nums}

/* Текущая неделя сезона: она нужна взгляду раньше всех остальных */
.weeks tr.ynum td.now,.weeks tr.ydates td.now{background:var(--blue-bg);box-shadow:inset 0 0 0 1px var(--blue-bd)}
.weeks tr.ynum td.now{color:var(--blue)}

.weeks tr.yper td{font-weight:700;font-size:12px;border-right:1px solid var(--bd-strong)}
.weeks tr.ystage td{font-weight:600;background:var(--bg-subtle);border-right:1px solid var(--bd-medium)}
.weeks tr.ytask td.txt span{color:var(--tx-secondary)}
.weeks tr.yev td.ev{color:#fff;border-right:1px solid #fff}
.weeks tr.yev td.ev span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:11px;font-weight:600;padding:0 6px;text-align:left}
.weeks tr.yevd td{border-bottom:2px solid var(--bd-strong)}

/* Равные недели: без фиксированной раскладки колонка растягивалась под самое
   длинное название периода, и год переставал делиться на 52 одинаковых доли. */
.weeks.fixed{table-layout:fixed}
.weeks.fixed td{overflow:hidden}
.weeks tr.ymonth td:not(.head) span,.weeks tr.yper td:not(.head) span,
.weeks tr.ystage td:not(.head) span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.weeks td.vol span{display:block;overflow:hidden;font-size:11px}
.weeks.fixed td{text-overflow:ellipsis}

/* ---------- шапка годового плана держится на экране ----------
   Сетка прокручивается внутри себя по обеим осям, а девять верхних строк и колонка
   названий закреплены. Иначе при уходе вниз к показателям цифра теряет свою неделю,
   а при уходе вправо — своё название: сопоставлять становится нечего. */
.ygrid{max-height:calc(100vh - 230px);min-height:360px}
.weeks tr.yh td{position:sticky;z-index:3}
.weeks tr.ymonth td{top:0}
.weeks tr.ynum   td{top:30px}
.weeks tr.ydates td{top:60px}
.weeks tr.yper   td{top:90px}
.weeks tr.ystage td{top:120px}
.weeks tr.ytask  td{top:150px}
.weeks tr.yev    td{top:180px}
.weeks tr.yplace td{top:210px}
.weeks tr.yevd   td{top:240px}
.weeks tr.yh td.head{left:0;z-index:6}

/* Названия строк переносятся: обрезать «Средства циклической направленности —
   общее время» до многоточия значит превратить показатель в загадку.
   Закреплённую шапку это не касается — её строки держат ровно 30 пикселей,
   от которых отсчитывается прилипание. */
.weeks tr:not(.yh) td.head{white-space:normal;line-height:1.2;padding-top:3px;padding-bottom:3px}
.weeks tr:not(.yh) td.head span{font-size:11px}

/* Сводные строки: общий объём работы, общий объём циклических нагрузок и итоги блоков */
.weeks tr.tot td{background:var(--bg-header);font-weight:700}
.weeks tr.tot td.head{background:var(--bg-header);color:var(--tx-primary)}
.weeks tr.tot td.head span{font-weight:700;font-size:11.5px}
.weeks tr.tot td.vol span{font-weight:700}

/* ---------- сетка под ширину окна ----------
   На узком экране колонка названий съедает половину видимых недель, а вместе
   с ними и смысл сетки: она нужна, чтобы видеть год, а не одну подпись.
   Поэтому подпись ужимается, а служебное «· авто» уходит первым — оно и так
   повторяется в каждой строке шапки. */
.ygrid{--yhead:250px}
@media(max-width:1280px){
  .ygrid{--yhead:200px}
  .weeks tr.yh td.head .faint{display:none}
}
@media(max-width:980px){
  .ygrid{--yhead:150px}
  .weeks tr.yh td.head{font-size:11px}
  .weeks tr:not(.yh) td.head span{font-size:10.5px}
}

/* Длинное значение набирается мельче, а не обрезается: «14 40» вместо «14 400» —
   это не сокращение, а потерянный разряд. */
.weeks td.vol.s1 span{font-size:9.5px;letter-spacing:-.02em}
.weeks td.vol.s2 span{font-size:9px;letter-spacing:-.03em}
.weeks td.vol.s3 span{font-size:8px;letter-spacing:-.04em}

/* Подпись строки сетки не переносится: «Месяц» и пометка «· авто» — одно целое,
   а разорванная надвое подпись в закреплённой шапке ещё и не помещается в свои
   тридцать пикселей. Длинным названиям показателей перенос по-прежнему разрешён. */
.weeks tr.yh td.head,#y-band td.head{white-space:nowrap}
.weeks td.head .faint{white-space:nowrap}

/* Значение из книги: план недельный, своей раскладки по дням у него нет,
   и путать его с посчитанным по мероприятию нельзя. */
.weeks td.vol.book span{border-bottom:1px dotted var(--tx-faint)}
.bookmark{border-bottom:1px dotted var(--tx-faint)}

/* Поэтапные задачи — не подпись, а формулировка на несколько недель вперёд:
   одной обрезанной строкой она не читается. Три строки мелким кеглем показывают
   задачу целиком там, где диапазон широкий, и её начало там, где он узкий. */
.weeks tr.ytask td{height:44px}
.weeks tr.ytask td.txt{padding:3px 6px;vertical-align:top}
.weeks tr.ytask td.txt span{white-space:normal;font-size:9px;line-height:1.2;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}

/* строка задач выше прочих — прилипание нижних строк шапки сдвигается на её высоту */
.weeks tr.yev   td{top:194px}
.weeks tr.yplace td{top:224px}
.weeks tr.yevd  td{top:254px}

/* Текущая неделя — полосой через всю сетку: номер и даты пометить мало,
   взгляд идёт вниз по показателям и теряет колонку среди пятидесяти двух.
   Полоса лежит поверх ячеек полупрозрачно, поэтому проходит и через
   объединённые ячейки периода, этапа и мероприятия. */
.wkwrap{position:relative;display:inline-block;min-width:100%}
.nowcol{position:absolute;top:0;bottom:0;width:40px;z-index:4;pointer-events:none;
  background:rgba(29,140,240,.10);border-left:1px solid var(--blue-bd);border-right:1px solid var(--blue-bd)}

/* Длинная таблица прокручивается внутри себя, иначе закреплённая шапка
   не срабатывает: sticky держится за ближайший прокручиваемый бок, а им
   оказывается страница целиком. */
.tw.tall{max-height:calc(100vh - 300px);min-height:320px}
/* таблица по ширине страницы без своей прокрутки: одна прокрутка — страницы,
   шапка держится у её верха (список мероприятий) */
.tw.flow{overflow:visible}
table.t.evlist{table-layout:fixed;width:100%}
table.t.evlist td{vertical-align:top;overflow-wrap:anywhere;padding-top:7px;padding-bottom:7px}
table.t.evlist .evhead{display:flex;flex-direction:column;align-items:flex-start;gap:5px}
table.t.evlist .evname{min-width:0}
/* правка — один карандаш: квадратная кнопка в той же группе */
table.t.evlist .tabs.evacts a.ico{width:28px;padding:0;justify-content:center}
/* «Пересмотреть» — заметная, но не тревожная: янтарная, как метки «требует внимания» */
table.t.evlist .evreview{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 10px;
  border:1px solid var(--amber-bd, #E8C77A);border-radius:4px;background:var(--amber-bg);color:var(--amber);
  font-size:12px;font-weight:600;cursor:pointer;font-family:inherit}
table.t.evlist .evreview svg{width:14px;height:14px}
table.t.evlist .evreview:hover{filter:brightness(.96)}
/* План загрузки объектов: то, что сейчас правится, — рамкой в плане и у карточки */
.opcur{outline:2px solid var(--blue);outline-offset:-2px;box-shadow:0 0 0 3px var(--blue-bg);z-index:2}
table.t td > a.opcur{padding:2px 4px}
.card.opedit{border-color:var(--blue);box-shadow:0 0 0 3px var(--blue-bg)}
/* пустая клетка дня в плане объектов: щелчок — новая запись в этот слот; «+» виден при наведении */
a.opadd{display:block;min-height:26px;text-align:center;color:var(--tx-faint);text-decoration:none;border-radius:4px;line-height:26px}
a.opadd::after{content:'+';opacity:0;font-weight:600}
a.opadd:hover{background:var(--bg-muted)}
a.opadd:hover::after,a.opadd:focus::after{opacity:1}
table.t.evlist td .btn.sm{height:24px;padding:0 9px;font-size:12px}
/* Действия строки — одной полосой под названием (датой) в первой клетке, как у
   мероприятий: в широкой таблице к ним не листать вбок, и они на одном месте у
   каждой строки. Значок без подписи — квадратная кнопка .ico, удаление — .danger */
.tabs.evacts{display:flex;width:max-content;margin-top:6px;border-color:var(--bd-strong);background:var(--bg-surface);
  box-shadow:0 1px 2px rgba(16,24,40,.08)}
table.t.evlist .evhead .tabs.evacts{display:inline-flex;margin-top:0}
/* у клеток таблиц нет отступа сверху и снизу — полоса ложилась прямо на линию
   строки и сливалась с ней: клетке с полосой — воздух снизу и сверху */
table.t tbody td:has(> .tabs.evacts),table.t tbody td:has(> div > .tabs.evacts),
table.t tbody td:has(.evhead){padding-top:7px;padding-bottom:9px}
/* у строки нет ни одного действия (смотрит не тот, кто правит) — пустой рамки не рисуем */
.tabs.evacts:not(:has(a,button,label,span,form)){display:none}
.tabs.evacts a,.tabs.evacts button{height:26px;padding:0 10px;font-size:12px;font-weight:400;gap:5px;color:var(--tx-secondary);
  background:var(--bg-surface);font-family:inherit;white-space:nowrap}
.tabs.evacts svg{width:14px;height:14px;color:var(--blue);flex:0 0 auto}
.tabs.evacts a.ico,.tabs.evacts button.ico{width:28px;padding:0;justify-content:center}
.tabs.evacts a:hover,.tabs.evacts button:hover{background:var(--blue-bg);color:var(--blue)}
.tabs.evacts .danger svg{color:var(--tx-muted)}
.tabs.evacts .danger:hover{background:var(--red-bg);color:var(--red)}
.tabs.evacts .danger:hover svg{color:var(--red)}
.tabs.evacts .ok:hover{background:var(--green-bg);color:var(--green)}
.tabs.evacts .ok:hover svg{color:var(--green)}
.tabs.evacts .on{background:var(--blue-bg);color:var(--blue)}
.tabs.evacts > span{display:flex;align-items:center;height:26px;padding:0 10px;font-size:12px;color:var(--tx-faint);
  border-right:1px solid var(--bd-strong)}
.tabs.evacts > span:last-child{border-right:none}
.tabs.evacts > label{display:flex;align-items:center;gap:5px;height:26px;padding:0 10px;margin:0;font-size:12px;
  color:var(--tx-secondary);border-right:1px solid var(--bd-strong);cursor:pointer;white-space:nowrap}
.tabs.evacts > label:last-child{border-right:none}
.tabs.evacts > label input{margin:0}
.tabs.evacts > form{display:flex;margin:0}
.tabs.evacts > form:not(:last-child) > button{border-right:1px solid var(--bd-strong)}
/* строка таблицы, где под главной клеткой стоят действия: клетки — по верху */
table.t tr.racts > td,table.t tbody tr:has(.tabs.evacts) > td{vertical-align:top;padding-top:7px;padding-bottom:9px}
/* календарь соревнований по ширине страницы: колонки долями, отметки на всю клетку */
/* сведения об операторе: строки в несколько строчек текста — с воздухом */
table.t.pubinfo tbody td{padding:8px 10px;height:auto;vertical-align:top}
/* сверка: решение по строке — под её названием в закреплённой первой клетке */
.recdecide{margin-top:6px;font-weight:400}
table.t.complist{table-layout:fixed;width:100%}
table.t.complist td{vertical-align:top;overflow-wrap:anywhere;padding-top:7px;padding-bottom:9px}
table.t.complist td select.inp{width:100% !important;max-width:100%}
table.t.complist tr.rowopen > td{overflow-x:auto}

/* кнопка-ссылка: действие, которое по смыслу ссылка, но требует POST —
   «Создать конспект» в строке задачи создаёт запись, а не открывает страницу */
.lnk{background:none;border:0;padding:0;margin:0;font:inherit;color:var(--blue);cursor:pointer}
.lnk:hover{color:var(--blue-hover);text-decoration:underline}
.lnk.danger{color:var(--red)}

/* Календарь сезона: месяц — блок, колонка — день.
   Цвет здесь несёт смысл, поэтому у каждого рода записи он свой и не повторяется:
   выезд синий, дом почти белый, переезд янтарный, контрольная зелёная,
   обследование фиолетовое. Старты идут своей лестницей — залитый целевой,
   обведённый контрольный, пунктирный проходной, — чтобы приоритет читался
   даже там, где соседняя строка занята. */
.cal{table-layout:fixed;width:100%;border-collapse:collapse;font-size:11px}
.cal td{border:1px solid var(--bd-subtle);height:26px;padding:0 2px;text-align:center;
        white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:var(--bg-surface)}
.cal td.h{text-align:left;padding-left:8px;background:var(--bg-header);color:var(--tx-muted);
          font-weight:500;border-right:2px solid var(--bd-strong)}
.cal td.we{background:var(--bg-muted);color:var(--tx-muted)}
.cal td.now{box-shadow:inset 0 0 0 2px var(--blue);font-weight:600}

/* где команда */
.cal td.pl{background:var(--blue-bg);border-color:var(--blue-bd)}
.cal td.pl a{color:var(--blue);font-weight:600}
.cal td.pl.home{background:var(--bg-surface);border-color:var(--bd-medium);
                box-shadow:inset 0 -2px 0 var(--grey)}
.cal td.pl.home a{color:var(--tx-secondary);font-weight:600}
.cal td.tr{background:var(--amber-bg-tag);border-color:var(--amber-bd);
           color:var(--amber);font-weight:700}

/* что за день: старт, контрольная, обследование */
.cal td.ev a{font-weight:600}
.cal td.pA{background:var(--red-bg);border-color:var(--red-bd)}
.cal td.pA a{color:var(--red)}
.cal td.pB{background:var(--bg-surface);box-shadow:inset 0 0 0 2px var(--red-bd)}
.cal td.pB a{color:var(--red)}
.cal td.pC{background:var(--bg-surface);box-shadow:inset 0 0 0 1px var(--grey)}
.cal td.pC a{color:var(--tx-muted)}
/* дни старта заняты ещё чем-то: рамка видна на любой заливке приоритета */
.cal td.clash{box-shadow:inset 0 0 0 2px var(--red);position:relative}
.cal td.kt{background:var(--green-bg);border-color:var(--green-corridor)}
.cal td.kt a{color:var(--green)}
.cal td.eco{background:var(--p-pre);border-color:#CFC7EA}
.cal td.eco a{color:var(--ev-exam)}

/* Отчёт спортсмена: «Повт. · Подх. · Вес / дист» — это одно целое, факт тренировки.
   Общая шапка и боковые линии показывают границы группы, чтобы колонки не читались
   как три независимых показателя рядом с планом */
.t th.grp-fact{text-align:center;background:var(--blue-bg);color:var(--blue);
               border-left:2px solid var(--blue-bd);border-right:2px solid var(--blue-bd)}
.t th.sub-fact:first-of-type{border-left:2px solid var(--blue-bd)}
.t th.sub-fact:last-of-type{border-right:2px solid var(--blue-bd)}
.t td.fact-l{border-left:2px solid var(--blue-bd)}
.t td.fact-r{border-right:2px solid var(--blue-bd)}

/* Плитка-ссылка на панелях: число ведёт туда, где его можно разобрать.
   Плитка без прав остаётся обычной карточкой — приглашать на «нет доступа» незачем */
a.card.kpi-a{display:block;text-decoration:none;color:inherit;transition:border-color .12s,box-shadow .12s}
a.card.kpi-a:hover{border-color:var(--blue);box-shadow:0 1px 6px rgba(29,140,240,.14);text-decoration:none}
a.card.kpi-a:hover .kpi-num{color:var(--blue)}
a.card.kpi-a.on{border-color:var(--blue);box-shadow:inset 0 0 0 1px var(--blue-bd)}

/* ===== Списки людей: команда, спортсмены, тренеры, специалисты =====
   Один вид на все четыре вкладки: карточка с панелью поиска, строки с портретом,
   счётчики кружком, статус плашкой и действия иконками. Разное содержание
   в одинаковой форме читается быстрее, чем четыре разные таблицы. */
.pcard{background:var(--bg-surface);border:1px solid var(--bd-strong);border-radius:10px;overflow:hidden}
.ptools{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:14px}
.ptools .inp{height:34px}
.ptbl{width:100%;border-collapse:collapse}
.ptbl th{font-size:11px;letter-spacing:.03em;text-transform:uppercase;color:var(--tx-muted);
         font-weight:600;text-align:left;padding:11px 14px;background:var(--bg-header);
         border-top:1px solid var(--bd-subtle);border-bottom:1px solid var(--bd-subtle);white-space:nowrap}
.ptbl td{padding:11px 14px;border-bottom:1px solid var(--bd-subtle);vertical-align:middle;font-size:13px}
.ptbl tr:last-child td{border-bottom:0}
.ptbl tbody tr:hover td{background:var(--bg-muted)}
.ptbl tr.off td{background:var(--bg-muted);color:var(--tx-muted)}
.pperson{display:flex;gap:10px;align-items:center}
.pav{width:34px;height:34px;border-radius:17px;background:var(--blue-bg);color:var(--blue);
     display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex:0 0 auto}
.pav.grey{background:var(--bg-header);color:var(--tx-muted)}
.pnm{font-weight:500}
.psub{font-size:11.5px;color:var(--tx-faint)}
.pbadge{min-width:22px;height:22px;padding:0 7px;border-radius:11px;background:var(--grey);color:#fff;
        font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}
.pbadge.red{background:var(--red)} .pbadge.blue{background:var(--blue)} .pbadge.green{background:var(--green)}
.ppill{display:inline-block;padding:4px 9px;border-radius:6px;font-size:11.5px;font-weight:500;white-space:nowrap;
       background:var(--blue-bg);color:var(--blue)}
.ppill.ok{background:var(--green-bg);color:var(--green)}
.ppill.warn{background:var(--amber-bg-tag);color:var(--amber)}
.ppill.bad{background:var(--red-bg);color:var(--red)}
.ppill.mute{background:var(--bg-header);color:var(--tx-muted)}
.pacts{display:flex;gap:6px;justify-content:flex-end;align-items:center}
/* строка, чья карточка раскрыта ниже: иначе в длинной таблице теряешь,
   что именно открыл */
.t tbody tr.on{background:var(--blue-bg)}
.iconbtn{width:30px;height:30px;border-radius:6px;border:1px solid var(--bd-medium);background:var(--bg-surface);
         color:var(--tx-muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;padding:0}
.iconbtn:hover{border-color:var(--blue);color:var(--blue);text-decoration:none}
.iconbtn.danger:hover{border-color:var(--red);color:var(--red)}
.iconbtn.ok:hover{border-color:var(--green);color:var(--green)}
/* открытая форма повтора: видно, какая строка сейчас в работе — форма
   стоит под таблицей, и связь с ней иначе теряется */
.iconbtn.on{border-color:var(--blue);color:var(--blue);background:var(--blue-bg)}
.pfoot{padding:12px 14px;color:var(--tx-muted);font-size:12px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}

/* ===== Структура вида спорта =====
   Карточка уровня: сверху вид спорта с общими должностями, ниже дисциплины.
   Пустая должность показывается так же заметно, как занятая: вакансия — это
   управленческий вопрос, а не пропуск в таблице. */
.orgtop{display:flex;justify-content:center;margin-bottom:0}
.orgline{width:2px;height:22px;background:var(--bd-strong);margin:0 auto}
.orggrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:16px}
.orgcard{background:var(--bg-surface);border:1px solid var(--bd-strong);border-radius:10px;overflow:hidden;position:relative}
.orgcard.head{max-width:520px;width:100%;border-color:var(--blue-bd);box-shadow:0 1px 6px rgba(29,140,240,.10)}
.orgtitle{padding:12px 14px;background:var(--bg-header);border-bottom:1px solid var(--bd-subtle);
          font-weight:600;font-size:14px;text-align:center}
.orgcard.head .orgtitle{background:var(--blue-bg);color:var(--blue);font-size:15px}
.orgnote{font-weight:400;font-size:11.5px;color:var(--tx-muted);margin-top:3px}
.orgbody{padding:6px 14px}
.orgrow{display:flex;gap:10px;align-items:center;padding:6px 0;border-bottom:1px dashed var(--bd-subtle);font-size:12.5px}
.orgrow:last-child{border-bottom:0}
.orglabel{color:var(--tx-muted);flex:0 0 42%;font-size:11.5px}
.sperson{display:flex;gap:7px;align-items:center;min-width:0}
.sperson span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sperson.vac{color:var(--amber);font-weight:600}
.pav.sm{width:22px;height:22px;border-radius:11px;font-size:10px}
.orgfoot{padding:10px 14px;border-top:1px solid var(--bd-subtle);background:var(--bg-muted);font-size:12px}
.orgacts{position:absolute;top:8px;right:8px;display:flex;gap:6px;opacity:0;transition:opacity .12s}
.orgcard:hover .orgacts{opacity:1}
/* Широкие списки людей прокручиваются внутри карточки, а не обрезаются её краем:
   после добавления выбора состава и трёх действий строка перестала помещаться */
.ptw{overflow-x:auto;max-width:100%}
/* внутри обёртки таблица живёт своей шириной: колонки не сжимаются до
   переноса по букве, а строка целиком уезжает под прокрутку */
.ptw > table{width:100%}
/* Лента дней: дни идут колонками, показатели строками. Первый столбец с
   названиями строк остаётся на месте, пока ленту листают вбок, — иначе,
   долистав до пятницы, уже не помнишь, что в строке ветер, а что осадки. */
.wxband{min-width:760px}
.wxband td:first-child,.wxband th:first-child{
  position:sticky;left:0;z-index:1;background:var(--bg-card,#fff)}
.wxband th a.on{font-weight:700;color:var(--blue)}
.wxband svg{display:block;margin:0 auto}
.ptbl.wide{min-width:1120px}
.ptbl td .inp{max-width:100%}
.ptbl.wide td,.ptbl.wide th{padding:11px 10px}

/* Строка бланка с вписанной фамилией: человека такого в составе нет, и это видно
   сразу — иначе легко принять её за обычную строку и ждать, что числа уйдут в базу. */
select.biowho.typed{border-color:var(--amber);color:var(--amber);font-weight:600}

/* Один человек в двух строках бланка: числа одной затрут числа другой, поэтому
   видно сразу — до того, как обе строки заполнят. */
select.biowho.dup{border-color:var(--red);color:var(--red);font-weight:600}

/* Лактатная кривая: наведение выделяет одну линию из пучка */
.lacline{transition:stroke-width .12s}
.lacline:hover{stroke-width:3.5}
.lacdot{transition:r .12s}
.lacwrap:hover .lacline:not(:hover){opacity:.35}
.lacser[hidden]{display:none}
.laclg{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 8px 0 6px;border:1px solid var(--bd-medium);
  border-radius:11px;background:#fff;font:inherit;font-size:11.5px;color:var(--tx-secondary);cursor:pointer}
.laclg:hover{border-color:var(--bd-strong);background:var(--bg-muted)}
.laclg[aria-pressed="false"]{color:var(--tx-faint);text-decoration:line-through;background:var(--bg-muted)}
.laclg[aria-pressed="false"] .laclgdot{opacity:.3}
.laclgdot{width:10px;height:10px;border-radius:2px;flex:0 0 auto}
.laclgall{height:22px;padding:0 8px;border:0;border-radius:11px;background:none;font:inherit;font-size:11.5px;
  color:var(--blue);cursor:pointer;text-decoration:underline}
/* Расчёты под значением: раньше они были набраны бледно-серым 10,5 px и терялись
   на белом. Теперь размер как у подписей, начертание среднее, а цвета — из палитры
   состояний: изменение по ступеням нейтральное, разница с наложением зелёная
   (лактата меньше) или красная (больше). */
.lacdelta{display:flex;gap:5px;justify-content:flex-end;align-items:baseline;
  font-size:11.5px;font-weight:500;line-height:1.35;white-space:nowrap;margin-top:1px}
.lacdelta .dstep{color:var(--tx-secondary)}
.lacdelta .dbetter{color:var(--green)}
.lacdelta .dworse{color:var(--red)}
.lacdelta .dsep{color:var(--bd-strong)}
/* «Наложить» — выпадающий список прошедших тестирований. Отметок может быть
   несколько, поэтому это не <select>, а список с галочками; штрих в строке тот же,
   что у линии на графике. */
.cmpdrop{position:relative;display:inline-block}
.cmpdrop>summary{list-style:none;cursor:pointer;height:30px;display:inline-flex;align-items:center;gap:6px;
  padding:0 26px 0 10px;border:1px solid var(--bd-strong);border-radius:4px;background:#fff;
  font-size:13px;color:var(--tx-secondary);white-space:nowrap;
  background-image:linear-gradient(45deg,transparent 50%,var(--tx-muted) 50%),linear-gradient(135deg,var(--tx-muted) 50%,transparent 50%);
  background-position:calc(100% - 14px) 13px,calc(100% - 9px) 13px;background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.cmpdrop>summary::-webkit-details-marker{display:none}
.cmpdrop>summary:hover{border-color:var(--tx-faint)}
.cmpdrop .cmpval{font-weight:500;color:var(--tx-primary)}
.cmpmenu{position:absolute;z-index:40;top:34px;left:0;min-width:330px;padding:6px;background:#fff;
  border:1px solid var(--bd-strong);border-radius:6px;box-shadow:0 8px 24px rgba(31,45,61,.14)}
.cmpitem{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:4px;font-size:12.5px;
  color:var(--tx-secondary);text-decoration:none;white-space:nowrap}
.cmpitem:hover{background:var(--bg-muted);color:var(--tx-primary)}
.cmpitem.on{color:var(--tx-primary);font-weight:500}
.cmpbox{width:14px;height:14px;flex:0 0 auto;border:1px solid var(--bd-strong);border-radius:3px;
  display:inline-flex;align-items:center;justify-content:center;font-size:10px;color:var(--blue);line-height:1}
.cmpitem.on .cmpbox{border-color:var(--blue);background:var(--blue-bg)}
.cmphead{padding:6px 8px 2px;font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--tx-faint)}
.cmpnote{padding:8px;font-size:12.5px;color:var(--tx-muted)}
.cmpsep{height:1px;background:var(--bd-subtle);margin:5px 2px}
/* «Было → стало · норма» под названием показателя: главное здесь — что изменилось,
   поэтому «стало» набрано крупнее, а выход за коридор подчёркнут цветом и рамкой */
.wsn{display:flex;flex-wrap:wrap;align-items:baseline;gap:5px;font-size:12px;color:var(--tx-secondary);margin-top:3px}
.wsn-l{font-size:10.5px;text-transform:uppercase;letter-spacing:.3px;color:var(--tx-faint)}
.wsn-ar{color:var(--tx-faint)}
.wsn-now{font-size:14px;font-weight:600;color:var(--tx-primary)}
.wsn-out{color:var(--red);border-bottom:1.5px solid var(--red-bd)}
.wsn-good{color:var(--green);font-weight:500}
.wsn-bad{color:var(--red);font-weight:500}
.wsn-mute{color:var(--tx-muted)}

/* Список дисциплин при загрузке календаря: отметок бывает больше десятка,
   поэтому в несколько колонок и с прокруткой — форма не должна растягиваться
   на весь экран */
.discbox{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:2px 12px;
  align-content:start;height:120px;overflow:auto;border:1px solid var(--bd-strong);
  border-radius:8px;padding:6px 8px;background:#fff}
.discitem{display:flex;align-items:center;gap:6px;font-size:13px;white-space:nowrap;
  padding:1px 0;cursor:pointer}
.discitem .faint{margin-left:auto}

/* Дерево подразделений: отступ показывает подчинение, выбранный узел выделен.
   Строка узла — ссылка целиком: попадать в неё нужно легко, читают её быстро. */
.orgtree{max-height:60vh;overflow:auto}
.orgnode{margin-bottom:2px}
.orgnode > a{display:block;padding:6px 10px;border:1px solid transparent;border-radius:8px;
  text-decoration:none;color:inherit}
.orgnode > a:hover{background:var(--bg-muted);border-color:var(--bd-subtle)}
.orgnode.on > a{background:var(--blue-bg);border-color:var(--blue-bd)}
.orgname{display:block;font-size:13px;font-weight:600}
.orgnode.on .orgname{color:var(--blue)}
.orgmeta{display:block;font-size:11.5px;color:var(--tx-muted);margin-top:1px}
.vacword{color:var(--amber)}
/* себя в структуре видно сразу — иначе её приходится перечитывать глазами */
.sperson.me{font-weight:600;color:var(--blue)}

/* Два шага работы со структурой: сначала схема, потом люди в ней. Цифра слева
   держит порядок — без неё две одинаковые кнопки читаются как вкладки, между
   которыми всё равно, с какой начинать. */
.steps{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media(max-width:900px){.steps{grid-template-columns:1fr}}
.steps .step{display:flex;gap:10px;align-items:center;padding:10px 12px;background:#fff;
  border:1px solid var(--bd-medium);border-radius:10px;text-decoration:none;color:inherit}
.step:hover{border-color:var(--blue-bd);text-decoration:none}
.steps .step.on{border-color:var(--blue);background:var(--blue-bg)}
.stepno{flex:0 0 auto;width:24px;height:24px;border-radius:12px;background:var(--bg-header);
  color:var(--tx-muted);font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center}
.steps .step.on .stepno{background:var(--blue);color:#fff}
.steps .step b{display:block;font-size:13.5px;font-weight:600}
.steps .step i{display:block;font-style:normal;font-size:11.5px;color:var(--tx-muted);margin-top:1px}

/* Схема подразделений: выбранное крупной карточкой, под ним рамкой — то, что в
   него входит. Ломаные линии оргсхемы намеренно заменены рамкой: они держатся,
   только пока дети умещаются в одну строку, а рамка не рассыпается никогда и не
   заставляет листать вбок. */
/* Окно схемы: узкое, прокручивается. Внутри — полотно во всю ширину схемы,
   в нём всё и центрируется; иначе вершина уезжает за край прокрутки. */
.orgchart{position:relative;overflow-x:auto}
.ocinner{position:relative;display:flex;flex-direction:column;align-items:center;width:100%}
.ocpath{font-size:12px;color:var(--tx-muted);margin-bottom:10px;text-align:center;line-height:1.6}
/* Объединение над видом спорта: не карточка подразделения — внутрь него не
   заходят и управляют не им. Пунктир и приглушённый цвет говорят, что это
   рамка вокруг, а не следующий уровень, по которому ходят. */
.octop{position:relative;display:block;max-width:320px;padding:6px 22px 6px 12px;text-align:center;
  border:1px dashed var(--bd-strong);border-radius:9px;background:var(--bg-muted);
  color:var(--tx-muted)}
.octop .ocname{font-size:12.5px;font-weight:600;color:var(--tx-primary)}
/* промежуток между родителем и рамкой: линию в нём рисует слой */
.ocstem{width:1px;height:16px}
/* Ряд подчинённых не переносится: схема разворачивается вширь и прокручивается,
   а перенос давал ступеньки в линиях. Отступы одинаковы слева и справа —
   иначе ряд съезжает вбок от родителя. */
.ockids{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;width:100%;
  border:1px solid var(--bd-subtle);border-radius:10px;padding:10px 16px 12px;
  background:var(--bg-muted)}
.ocbox{position:relative;z-index:1;display:block;min-width:150px;max-width:210px;padding:8px 10px;background:#fff;
  border:1px solid var(--bd-strong);border-radius:9px;text-decoration:none;color:inherit}
.ocbox:hover{border-color:var(--blue-bd);text-decoration:none;color:inherit}
.ocbox.big{min-width:240px;max-width:none;border-width:2px;border-color:var(--blue);background:var(--blue-bg)}
.ocbox.on{border-color:var(--blue-bd);background:var(--blue-bg)}
/* Крестик блока: стоит на месте всегда, бледно. Пока он появлялся только под
   курсором, о нём не знал тот, кто его не искал, — и лишнее оставалось в
   схеме. Под курсором наливается, чтобы не нажать его мимоходом. */
.ocx{position:absolute;top:2px;right:3px;z-index:2;width:16px;height:16px;line-height:15px;
  text-align:center;font-size:14px;border-radius:50%;color:var(--tx-faint);
  opacity:.4;transition:opacity .12s,background .12s;cursor:pointer}
.ocbox:hover .ocx,.octop:hover .ocx,.ocx:focus{opacity:1}
.ocx:hover{background:var(--red-bg,#fdecec);color:var(--red,#c0392b)}
.ocname{display:block;font-size:13px;font-weight:600;padding-right:14px}
.ocbox.big .ocname{font-size:15px}
.ocsub{display:block;font-size:11.5px;color:var(--tx-muted);margin-top:2px}
.ocbar{display:block;height:4px;border-radius:3px;background:var(--bd-subtle);margin-top:6px;overflow:hidden}
.ocbar > i{display:block;height:100%;background:var(--green)}
.ocempty{font-size:12px;color:var(--tx-muted);padding:6px 4px;text-align:center}
/* Состав — конечный уровень схемы: карточка не проваливается глубже, а уводит
   в сам состав. Подпись об этом стоит на карточке, чтобы переход не оказался
   неожиданностью. */
.ocgo{display:block;font-size:11px;color:var(--blue);margin-top:4px}
/* Место под линии: сверху для отвода, слева для ствола. Сами линии рисует
   слой amsOrgWires() — по измеренным координатам карточек, иначе отрезки
   не сходятся: размеры карточек зависят от текста и ширины окна. */
/* Карточка — посередине над своим поддеревом: колонка шире её, и у левого
   края начальник оказывался сбоку от собственных подчинённых. */
.occol{position:relative;display:flex;flex-direction:column;align-items:center;gap:4px;padding-top:18px}
.ocwire{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;
  overflow:visible;z-index:0}
/* Линии рисуются отдельными отрезками — ветвление иначе не нарисовать. Чтобы
   на стыках не появлялись волосяные разрывы, концы у отрезков квадратные:
   каждый заходит за угол на половину толщины. Округление crispEdges убрано —
   оно двигало каждый отрезок к своему пикселю, и углы расходились. */
.ocwire path{fill:none;stroke:var(--tx-muted);stroke-width:1.25;
  stroke-linecap:square;stroke-linejoin:miter}
/* Вложенное стоит под своим родителем столбиком; связь рисует слой линий —
   отчёркивание слева ни к чему не примыкало, и связь приходилось додумывать.
   Отступ слева — место под эту линию. */
/* Подчинённые стоят в ряд под своим начальником: это оргсхема, а не список.
   Столбиком они читались лесенкой и растягивали полотно вниз. */
.ocgroup{display:flex;flex-direction:row;flex-wrap:wrap;column-gap:10px;row-gap:30px;
  justify-content:center;padding-top:22px;align-items:flex-start}
/* вложенная ветвь уже отбита самой рамкой: второй отступ сверху только рвёт линию */
.ocgroup > .occol{padding-top:0}
/* разрыв строки в ряду подчинённых: то, что за ним, начинается с новой */
.ocbreak{flex-basis:100%;height:0;margin:0;padding:0}
/* Должность при начальнике: стоит сбоку от его карточки, связана короткой
   перемычкой. Зазор держит место для неё. */
.ocrow{display:flex;align-items:center;gap:26px}
/* Вширь схема не помещается в карточку — прокручивается она, а не страница */
.orgchart{overflow-x:auto}
/* подпись ответвления: штаб команды — не первый её состав */
/* Имя уровня строкой над рядом: ряд читается как «составы», «штаб команды»,
   «дисциплины», а не как список одинаковых прямоугольников. Слева подпись
   отнимала у ряда ширину, и ряд переносился — объясняя уровень, она его и
   ломала. Нижний отступ оставляет место планке, которая идёт над рядом. */
.ocaside{flex-basis:100%;width:0;min-width:100%;font-size:11px;line-height:1.2;
  color:var(--tx-muted);padding-left:4px;margin:0 0 13px;overflow:hidden}
/* Что получится из выбранного — списком, а не строчкой мелким шрифтом: при
   «мужчины и женщины в одной команде» выбранное разворачивается по полу, и
   увидеть это надо сразу, до того как схема собрана. */
.rosterout{margin-top:8px;border:1px solid var(--bd-medium);border-radius:8px;
  background:var(--bg-muted);padding:8px 10px}
.rosterout-h{font-size:12px;font-weight:600;color:var(--tx-secondary);margin-bottom:4px}
.rosterout-i{font-size:12.5px;color:var(--tx-primary);padding:2px 0 2px 12px;position:relative}
.rosterout-i::before{content:"";position:absolute;left:2px;top:9px;width:4px;height:4px;
  border-radius:2px;background:var(--blue)}
/* Группа внутри состава — с отступом и без маркера-точки: она часть состава над
   ней, а не следующий состав в списке. */
.rosterout-i.sub{padding-left:26px;color:var(--tx-secondary)}
.rosterout-i.sub::before{left:16px;background:var(--grey)}

/* Карточка подразделения уезжает вбок целиком, и схема занимает освободившееся
   место. Прятать одно содержимое мало: пустая рамка в полэкрана остаётся
   стоять и занимает то самое место, ради которого её сворачивали. */
.two-col > .card{transition:opacity .16s ease,transform .2s ease}
.two-col.off{grid-template-columns:1fr}
.two-col.off > .card + .card{display:none}
/* Должность в схеме — не подразделение: у неё нет людей внутри, на неё ставят
   человека. Пунктир отличает её от карточек подразделений, не выводя из ряда. */
.ocbox.role{border-style:dashed}
/* Сотрудник под своим руководителем: не должность и не подразделение — человек.
   От места он отличается сплошной рамкой против пунктира, а не бледностью:
   выцветшая карточка сливалась с панелью под ней. */
.ocbox.man{border-color:var(--bd-strong);background:#fff}
/* Объединение над видом спорта и виды спорта рядом — по кнопке: работа идёт
   внутри вида спорта, и вершина нужна, когда смотрят на место в федерации.
   Пока скрыто, на схеме ничего лишнего. */
.ocunion,.ocsib{display:none}
.ocinner.union-on .ocunion{display:flex;flex-direction:column;align-items:center}
.ocinner.union-on .ocsib{display:block}
.ocsibs{display:flex;align-items:flex-start;justify-content:center;gap:12px}
/* Вид спорта федерации, которого ещё нет в приложении: место, а не подразделение */
.ocbox.ghost{border-style:dashed;background:var(--bg-muted);color:var(--tx-muted)}
.ocbox.ghost .ocname{color:var(--tx-muted);font-weight:500}

/* Набор галочек, который сохраняется одним полем: специализация тренера — не
   один пункт из списка, отмечают в ней столько, сколько названо в функционале
   рядом. Плотно: ячейка таблицы и так узкая, а строк в наборе четыре. */
.chk{display:flex;align-items:center;gap:6px;font-size:12px;line-height:1.6;
  color:var(--tx-secondary);cursor:pointer;white-space:nowrap}
.chk input{margin:0;flex:0 0 auto}

/* Выбор из справочника подготовки: закрыт, пока в него не полезли. В строке
   таблицы важнее видеть, что выбрано, чем сорок строк справочника. */
.specpick summary{cursor:pointer;font-size:12px;color:var(--tx-secondary);line-height:1.5}
.specpick summary::marker{color:var(--tx-faint)}
.specpick .specbox{max-height:240px;overflow:auto;margin-top:6px;padding:6px 8px;
  border:1px solid var(--bd-subtle);border-radius:4px;background:var(--bg-subtle);min-width:250px}
.specpick .chk.b{font-weight:500;color:var(--tx-primary);margin-top:4px}
.specpick .chk.sub{padding-left:18px;color:var(--tx-muted)}

/* Выбор отрезков в сетке отклонений: кнопка со списком, который раскрывается
   поверх таблицы. В сезоне бывает двести дней — в строку шапки они не влезут,
   а выбирают из них по одному-два. */
.devpick{position:relative}
.devpick summary{list-style:none;cursor:pointer;height:28px;padding:0 10px;
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  border:1px solid var(--bd-strong);border-radius:4px;background:#fff;
  font-size:12px;color:var(--tx-primary)}
.devpick summary::-webkit-details-marker{display:none}
.devpick summary::after{content:'▾';color:var(--tx-faint)}
.devpick details[open] summary{border-color:var(--blue);color:var(--blue)}
.devpick .pickpop{position:absolute;z-index:30;top:34px;left:0;padding:8px;
  background:#fff;border:1px solid var(--bd-strong);border-radius:4px;
  box-shadow:0 8px 24px rgba(31,45,61,.12)}
.devpick .specbox{max-height:320px;min-width:260px;margin:0;padding:0;border:0;background:#fff}
.devpick .chk{display:block;padding:2px 0}
.devpick .pickwk{margin:6px 0 2px;font-size:11px;text-transform:uppercase;letter-spacing:.03em}
.devpick .pickwk a{color:var(--tx-muted)}
.devpick .pickwk a:hover{color:var(--blue)}

/* Клетка другого разреза ведёт в свой день: вносят руками там, где видно
   занятия. Ссылкой не подчёркиваем — в таблице это шум, — но курсор говорит,
   что по клетке можно нажать. */
.diary a.dcell{display:block;color:inherit;text-decoration:none;cursor:pointer}
.diary a.dcell:hover{color:var(--blue);text-decoration:underline}

/* Итог за год в сетке плана: стоит последней колонкой и не уезжает при
   прокрутке — год смотрят, не отпуская названия строки слева. */
.weeks td.yt{position:sticky;right:0;z-index:2;background:var(--bg-muted);width:62px;min-width:62px;
  border-left:1px solid var(--bd-strong);font-weight:600}
.weeks tr.yh td.yt{background:var(--bg-header)}
.weeks td.yt.tot{background:var(--blue-bg)}
.weeks td.yt span,.weeks td.yt b{display:block;width:100%;text-align:center;overflow:hidden;text-overflow:ellipsis}

/* «ГОД» и «ИТОГО» — одна надпись, разнесённая по двум строкам шапки, и
   выглядеть должна одинаково: строки шапки задают свои размеры каждая, и без
   этого «год» выходил мелким прописным, а «ИТОГО» — крупнее и другим шрифтом.
   Заодно ставим по середине клетки и по высоте, а не только по ширине. */
.weeks tr.yh td.yt{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  vertical-align:middle;padding:0}
/* подпись на всю шапку: одна клетка, надпись ровно в её середине */
.weeks td.yt.ytitle{vertical-align:middle}
.weeks td.yt.ytitle span{display:block;line-height:1.3;text-align:center}

/* Разрезы отклонения: четыре взгляда на один разрыв, свёрнутые до нужного.
   Список дней длинный по делу — держим его в своей рамке с прокруткой, чтобы
   он не отодвигал выводы под ним на экран вниз. */
.devslice{border-top:1px solid var(--bd-subtle);padding:8px 0}
.devslice summary{cursor:pointer;font-size:13px}
.devslice summary .faint{font-size:12px}
.devslice .devbox{max-height:420px;overflow:auto;margin-top:8px}

/* Сопоставление в клетке: план, факт и отклонение друг под другом. Три числа
   в одной клетке читаются только если различаются весом и цветом — иначе это
   столбик одинаковых цифр, в котором ничего не найти. */
.diary td.cmpcell{padding:2px 4px;line-height:1.15;vertical-align:middle}
.diary .cmp{display:block;white-space:nowrap}
.diary .cmp.p{font-size:10px;color:var(--tx-faint)}
.diary .cmp.f{font-size:12px;font-weight:600;color:var(--tx-primary)}
.diary .cmp.d{font-size:10px;font-weight:600;color:var(--tx-muted)}
.diary .cmp.d.ok{color:var(--green)}
.diary .cmp.d.warn{color:var(--amber)}
.diary .cmp.d.bad{color:var(--red)}

/* Тренерские строки индивидуального плана: две одинаковые карточки —
   подпись строки, сам тренер и список штаба, из которого его берут. */
.coachgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px}
.coachbox{border:1px solid var(--bd-medium);border-radius:8px;padding:10px 12px;background:var(--bg-muted)}
.coachbox .inp{background:#fff}
.coachtitle{font-size:12.5px;font-weight:600}
.stafflist{max-height:210px;overflow:auto;margin-top:6px;padding-right:4px}
.staffrow{display:flex;gap:8px;align-items:flex-start;padding:5px 2px;border-bottom:1px solid var(--bd-faint);font-size:12px;line-height:1.45;cursor:pointer}
.staffrow:last-child{border-bottom:none}
.staffrow:hover{background:var(--bg-header)}
.staffrow .tag{margin-left:6px;vertical-align:middle}
.staffname{font-weight:600}
.staffnote{display:block;font-size:10.5px;color:var(--tx-faint)}

/* Состояние автосохранения карточки плана: оно стоит на месте кнопки,
   поэтому и выглядит надписью, а не ещё одним органом управления. */
.savemark{font-size:12px;color:var(--tx-muted)}
.savemark.busy{color:var(--amber)}
.savemark.ok{color:var(--green)}
.savemark.bad{color:var(--red);font-weight:600}

/* График динамики в карточке плана: рисуется по тем же полям, что и
   таблица над ним, поэтому стоит сразу под ней и во всю её ширину. */
.chartbox{border:1px solid var(--bd-medium);border-radius:8px;background:#fff;padding:8px 10px}
.chartbox svg{display:block;width:100%;height:220px}
.chartrow{padding:6px 0}
.chartrow + .chartrow{border-top:1px solid var(--bd-faint)}
.chartname{font-size:12px;font-weight:600;color:var(--tx-secondary);margin:2px 0 2px 34px}
.chartrow svg{display:block;width:100%;height:160px}

/* Полоса шагов первичной настройки: видно, где стоишь, что уже собрано
   (число рядом с названием) и куда можно вернуться. */
.wizbar{display:flex;flex-wrap:wrap;gap:6px}
.wizstep{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--bd-medium);
  border-radius:16px;background:#fff;font-size:12px;color:var(--tx-secondary);white-space:nowrap}
.wizstep:hover{border-color:var(--bd-strong)}
.wizstep.on{background:var(--blue-bg);border-color:var(--blue);color:var(--blue);font-weight:600}
.wizstep.ok .wizno{background:var(--green);color:#fff}
.wizno{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;
  background:var(--bg-header);color:var(--tx-muted);font-size:11px;font-weight:600}
.wizcnt{font-size:11px;color:var(--tx-faint)}

/* Дерево собранной схемы на последнем шаге мастера: отступ показывает
   вложенность — вид спорта, дисциплина, команда, состав. */
.wiztree{border:1px solid var(--bd-medium);border-radius:8px;padding:10px 12px;background:var(--bg-muted)}
.wiznode{font-size:12.5px;line-height:1.7}
.wizsport{font-size:14px}
.wizdisc{margin-left:14px}
.wizteam{margin-left:28px}
.wizroster{margin-left:42px;color:var(--tx-secondary)}

/* ---------- шапка профиля спортсмена ----------
   Сделана по образцу карточек FIS и ФФР: портрет, имя, под ним — то, чем
   спортсмена называют в документах и протоколах (код FIS, год рождения,
   дисциплина, состав, тренер). Раньше в шапке стояли три слова, и ради кода
   или тренера приходилось лезть в другие разделы. */
.athero{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap;
        background:linear-gradient(135deg,var(--blue) 0%,#1d4f91 100%);color:#fff;
        border-radius:12px;padding:18px 20px}
.athero .avat{width:76px;height:76px;border-radius:38px;background:rgba(255,255,255,.16);
        display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;flex:0 0 auto}
.athero .who{min-width:220px;flex:1 1 260px}
.athero .nm{font-size:26px;font-weight:700;line-height:1.15}
.athero .en{font-size:13px;opacity:.75;margin-top:2px;letter-spacing:.02em}
.athero .tagline{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.athero .tagline .tag{background:rgba(255,255,255,.18);color:#fff;border:0}
.athero .facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
        gap:10px 18px;flex:2 1 420px}
.athero .fact .k{font-size:11px;text-transform:uppercase;letter-spacing:.04em;opacity:.7}
.athero .fact .v{font-size:14px;font-weight:600;margin-top:1px}
.athero a{color:#fff;text-decoration:underline}
@media(max-width:700px){.athero .nm{font-size:22px}}

/* Расписание списков очков FIS: таблица с периодами, где строка раскрывается
   календарём окна. Сделана сеткой, а не <table>: раскрытие держится на
   нативном <details>, значит работает без скрипта и не дёргает страницу. */
.plan{border:1px solid var(--bd-medium);border-radius:8px;overflow:hidden}
.plan .row{display:grid;grid-template-columns:minmax(230px,2.4fr) repeat(5,minmax(86px,.9fr)) minmax(150px,1.4fr);
  gap:10px;padding:8px 12px;align-items:baseline;font-size:12px}
.plan .head{background:var(--bg-header);font-size:11px;text-transform:uppercase;
  letter-spacing:.03em;color:var(--tx-muted)}
.plan details{border-top:1px solid var(--bd-subtle)}
.plan details>summary{cursor:pointer;list-style:none}
.plan details>summary::-webkit-details-marker{display:none}
.plan details>summary:hover{background:var(--bg-subtle)}
.plan details>summary .nm::before{content:'\25B8';color:var(--tx-muted);margin-right:6px}
.plan details[open]>summary .nm::before{content:'\25BE'}
.plan details[open]>summary{background:var(--bg-muted)}
.plan .body{padding:0 12px 12px}
.plan .tnum{font-variant-numeric:tabular-nums;white-space:nowrap}
@media(max-width:1000px){.plan .head{display:none}
  .plan .row{grid-template-columns:1fr 1fr;gap:4px 10px}}

/* Подсказка у точки графика: дата, старт, дисциплина и число — карточкой,
   как на сайте FIS. Показывается наведением, без скрипта: точка со своей
   площадью захвата и карточка лежат в одной группе, поэтому достаточно
   :hover. Карточка не перехватывает мышь, чтобы не мешать соседям. */
/* Конспект против плана дня с двумя планами: столбцов на два больше, и в
   обычном наборе строка перестаёт помещаться. Мельче только этот вид —
   остальные таблицы приложения набираются как были. */
table.t.pdsplit{font-size:12px}
table.t.pdsplit th{font-size:10px;line-height:1.25}
table.t.pdsplit td{padding-top:4px;padding-bottom:4px}
/* мужская и женская мерки — одна пара: слева у пары отбивка, между
   столбцами пары её нет, и четыре числа подряд читаются как два блока */
table.t.pdsplit .pdgap{border-left:1px solid var(--bd-medium)}
table.t.pdsplit .pdsub{font-weight:400;text-transform:none;letter-spacing:0;color:var(--tx-muted)}
table.t.pdsplit th .pdsub{display:block}
svg.chart .ctip{opacity:0;pointer-events:none;transition:opacity .08s ease}
svg.chart .cpt:hover .ctip,svg.chart .cpt:focus .ctip{opacity:1}
svg.chart .cpt{cursor:pointer}
svg.chart a{text-decoration:none}

/* ===================== узкий экран (телефон) =====================
   Меню перестаёт делить строку с работой и выезжает поверх неё. Полоса сверху
   отдаёт место: подписи «Сезон» и «Команда» и поиск на телефоне не нужны —
   списки и так подписаны, а поиск открывается с клавиатуры, которой там нет. */
.navbtn{display:none}
.navveil{display:none}
@media (max-width:820px){
  .navbtn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
    flex:0 0 auto;border:1px solid var(--bd-strong);border-radius:6px;background:#fff;
    font-size:17px;line-height:1;color:var(--tx-secondary);cursor:pointer}
  nav.side,nav.side.collapsed{position:fixed;top:0;left:0;height:100%;width:270px;z-index:70;
    transform:translateX(-100%);transition:transform .18s ease}
  .shell.navopen nav.side{transform:none}
  .shell.navopen .navveil{display:block;position:fixed;inset:0;z-index:60;background:rgba(16,24,40,.38)}
  header.top{gap:8px;padding:0 10px}
  header.top .lb{display:none}
  header.top select{flex:0 0 auto !important;width:auto !important;max-width:132px}
  .gs-trigger{display:none}
  .top-user{padding-left:8px;gap:8px}
  .top-user>div:nth-child(2){display:none}
  main.work{padding:12px 12px 40px}
  .page-head{flex-wrap:wrap;row-gap:8px}
  .card{max-width:none}
}

/* Раскладка диска: слева дерево, справа содержимое папки. В отличие от чата
   высота здесь не задаётся: список файлов должен занимать столько, сколько
   ему нужно, а не прокручиваться в полоске на треть экрана. */
.dkwrap{display:flex;gap:12px;align-items:flex-start}
.dktree{flex:0 0 260px;max-width:260px;overflow:hidden}
.dkrows{max-height:70vh;overflow:auto}
/* пустой список папок — с теми же отступами, что у строк дерева, а не впритык к рамке */
.dkrows .dkempty{padding:8px 12px 12px;line-height:1.45}
.dkmain{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.dkhead{display:flex;gap:8px;align-items:center;padding:8px 14px;
  border-bottom:1px solid var(--bd-subtle)}
.dkbody{padding:12px 14px}
@media (max-width:820px){
  .dkwrap{flex-direction:column}
  .dktree{flex:1 1 auto;max-width:none;width:100%}
  .dkrows{max-height:34vh}
  .dkmain{width:100%}
  .dkhead{flex-wrap:wrap;row-gap:6px}
  .dkbody{padding:10px 10px 12px}
}
/* ===================== Диск =====================
   Дерево папок слева повторяет список разговоров в чате: одинаковые вещи
   должны выглядеть одинаково. Подсветка «over» — единственный способ понять,
   куда упадёт файл, который тащат. */
.dfrow{display:flex;align-items:center;gap:8px;padding:7px 10px;font-size:13px;
  color:var(--tx-primary);text-decoration:none;border-bottom:1px solid var(--bd-subtle)}
.dfrow:hover{background:var(--bg-muted);text-decoration:none;color:var(--tx-primary)}
.dfrow.on{background:var(--blue-bg);box-shadow:inset 3px 0 0 var(--blue)}
.dfrow.over{background:var(--blue-bg);outline:2px dashed var(--blue);outline-offset:-2px}
.dfi{width:14px;text-align:center;color:var(--tx-muted);flex:0 0 auto}
/* Плитка папки: с иконкой — её находят глазами быстрее, чем строку списка.
   Меню в углу, как у документа: открыть, права, переименовать, удалить. */
.dfcard{position:relative;min-width:230px;max-width:280px;padding:10px 12px;border:1px solid var(--bd-medium);
  border-radius:10px;background:#fff;color:var(--tx-primary)}
.dfcard:hover{border-color:var(--blue)}
.dfcard.over{border-color:var(--blue);background:var(--blue-bg);outline:2px dashed var(--blue);outline-offset:-4px}
.dfcard .dfopen{display:flex;gap:10px;align-items:flex-start;color:inherit;text-decoration:none;padding-right:22px}
.dfcard .dfopen:hover{text-decoration:none;color:inherit}
.dfcard .dftext{min-width:0}
.dfcard .dfn{display:block;font-weight:600;font-size:13px;margin-bottom:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dfcard .faint{display:block;font-size:11.5px}
.dfcard .dfmenu{position:absolute;top:6px;right:6px}
.dfcard .dfmenu>summary{width:22px;height:22px;border-color:transparent;background:none}
.dfcard:hover .dfmenu>summary{border-color:var(--bd-medium);background:#fff}
/* сама иконка: скруглённая папка с «язычком», нарисована рамками, без картинок */
.dficon{position:relative;flex:0 0 auto;width:30px;height:24px;border-radius:3px 6px 6px 6px;
  background:#DCEBFF;border:1px solid #9BC4F5}
.dficon::before{content:'';position:absolute;top:-5px;left:-1px;width:13px;height:5px;
  border-radius:3px 3px 0 0;background:#DCEBFF;border:1px solid #9BC4F5;border-bottom:none}
.dficon.med{background:#FFE6EA;border-color:#F2A6B3}
.dficon.med::before{background:#FFE6EA;border-color:#F2A6B3}.dropzone{display:block;padding:14px;border:1px dashed var(--bd-strong);border-radius:8px;
  background:var(--bg-muted);font-size:13px;text-align:center}
.dropzone.over{border-color:var(--blue);background:var(--blue-bg)}
tr.dfile{cursor:grab}
tr.dfile.sel{background:var(--blue-bg)}

/* Просмотр документа: читаемая колонка, а не копия страницы Word */
.docview{max-width:820px;font-size:13.5px;line-height:1.55}
.docview p{margin:0 0 8px}
.docview .dochead{font-weight:700;font-size:15px;margin:12px 0 8px}
.docview .docsp{height:8px}

/* Штамп подписи: так его печатают в кадровых системах — рамкой и заголовком,
   чтобы на распечатке было видно, что документ подписан не от руки */
.signstamp{border:1px solid var(--blue);}
.signstamp .signhead{color:var(--blue);font-weight:700;letter-spacing:.02em;margin-bottom:4px}
.signstamp .signsub{color:var(--tx-secondary);font-size:12.5px;margin-bottom:10px}

/* ===================== Документ в приложении =====================
   Книга выглядит книгой: буквы колонок, номера строк, ввод прямо в клетку.
   Документ Word — страницей с полями. Слайд — карточкой. Это не копия Word,
   но работать с содержимым можно не выходя из приложения. */
.xlsheet{border:1px solid var(--bd-strong);border-radius:8px;overflow:hidden;background:#fff}
.xltabs{display:flex;gap:2px;padding:6px 6px 0;background:var(--bg-muted);border-bottom:1px solid var(--bd-medium);overflow:auto}
.xltab{border:1px solid var(--bd-medium);border-bottom:none;border-radius:6px 6px 0 0;background:#fff;
  padding:5px 12px;font-size:12.5px;cursor:pointer;white-space:nowrap;color:var(--tx-secondary)}
.xltab.on{color:var(--tx-primary);font-weight:600;box-shadow:inset 0 -2px 0 var(--blue)}
.xlbox{display:none;max-height:62vh;overflow:auto}
.xlbox.on{display:block}
table.xlgrid{border-collapse:separate;border-spacing:0;font-size:12.5px;table-layout:fixed}
table.xlgrid th{position:sticky;top:0;z-index:2;background:var(--bg-muted);border-right:1px solid var(--bd-medium);
  border-bottom:1px solid var(--bd-strong);font-weight:600;color:var(--tx-secondary);height:24px;min-width:110px}
table.xlgrid th.xlrn{left:0;z-index:3;min-width:44px;width:44px;text-align:center}
table.xlgrid tbody th.xlrn{position:sticky;top:auto;background:var(--bg-muted)}
table.xlgrid td{border-right:1px solid var(--bd-subtle);border-bottom:1px solid var(--bd-subtle);
  padding:0;height:24px;min-width:110px;max-width:260px;overflow:hidden}
table.xlgrid td.xlnum{text-align:right}
table.xlgrid td.xlf{background:#FFFDF2}
.xlc{width:100%;height:23px;border:1px solid transparent;background:none;padding:0 6px;font:inherit;
  color:inherit;outline:none;text-align:inherit}
.xlc:hover{border-color:var(--bd-medium)}
.xlc:focus{border-color:var(--blue);background:#fff;box-shadow:0 0 0 2px var(--blue-bg)}
.xlc.dirty{background:#F2FBF4}
.xlv{display:block;padding:3px 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.docpage{background:#fff;border:1px solid var(--bd-strong);border-radius:8px;padding:38px 46px;
  max-width:900px;font-size:14px;line-height:1.6;box-shadow:0 1px 3px rgba(16,24,40,.06)}
.docpage .docp{margin:0 0 8px;outline:none;border-radius:3px}
.docpage.edit .docp:hover{background:var(--bg-muted)}
.docpage.edit .docp:focus{background:#fff;box-shadow:0 0 0 2px var(--blue-bg)}
.docpage .dochead{font-weight:700;font-size:17px;margin:16px 0 10px}
.docpage .docsp{height:10px}
table.doctable{border-collapse:collapse;width:100%;margin:10px 0 14px;font-size:13px}
table.doctable td{border:1px solid var(--bd-medium);padding:6px 8px;vertical-align:top;outline:none}
.docpage.edit table.doctable td:focus{box-shadow:inset 0 0 0 2px var(--blue-bg)}

.slide{background:#fff;border:1px solid var(--bd-strong);border-radius:8px;padding:18px 22px;margin-bottom:10px;
  max-width:760px}
.slide .slideno{font-size:11px;color:var(--tx-muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px}
.slide .slideline{font-size:14px;line-height:1.5;outline:none;border-radius:3px;padding:2px 4px}
.slide .slideline.first{font-size:18px;font-weight:700;margin-bottom:6px}
.slide .slideline:focus{box-shadow:0 0 0 2px var(--blue-bg)}
@media (max-width:820px){
  .docpage{padding:20px 16px}
  .xlbox{max-height:52vh}
}

/* Шапка документа закреплена: при правке длинного отчёта кнопка «сохранить» и
   состояние правки не должны уезжать вверх вместе с текстом. Прокручивается
   сам документ, а не страница целиком. */
.docbar{position:sticky;top:0;z-index:20;display:flex;gap:8px;align-items:center;flex-wrap:wrap;
  padding:8px 0 10px;margin-bottom:8px;background:#fff;border-bottom:1px solid var(--bd-medium)}
/* Ширина закреплена: надпись меняется по ходу правки, и без этого
   соседние кнопки прыгали бы при каждом слове */
.savest{display:inline-block;min-width:168px;text-align:right;font-size:12px;
  color:var(--tx-muted);white-space:nowrap;transition:color .15s ease}
/* кнопка со значком: квадратная, под размер остальных мелких кнопок */
.btn.iconbtn{padding:0;width:30px;min-width:30px;display:inline-flex;align-items:center;justify-content:center}
.btn.iconbtn svg{width:15px;height:15px}
.docscroll{max-height:calc(100vh - 260px);min-height:280px;overflow:auto;padding-right:4px}
.docp.dirty,.slideline.dirty,table.doctable td.dirty{background:#F2FBF4}
@media (max-width:820px){
  .docbar{position:static}
  .docscroll{max-height:none}
}

/* Окно редактора документов: высоту задаём мы, иначе он схлопывается в
   ноль — своей высоты у встроенного редактора нет */
.ooframe{height:calc(100vh - 230px);min-height:420px;border:1px solid var(--bd-strong);
  border-radius:8px;overflow:hidden;background:#fff}
@media (max-width:820px){.ooframe{height:70vh;min-height:320px}}

/* Списки выбора в правах: видно сразу несколько строк, и отметить можно
   нескольких — права выдают обычно не одному человеку */
.pickbox{height:auto;min-height:132px;padding:4px;line-height:1.5}
.pickbox option{padding:3px 6px;border-radius:3px}
/* отмеченную строку видно и когда список не в фокусе: иначе после
   перехода к соседнему полю кажется, что выбор слетел */
.pickbox option{cursor:pointer}
.pickbox option:checked{background:var(--blue-bg);box-shadow:inset 2px 0 0 var(--blue);font-weight:500}
.pickbox optgroup{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--tx-muted)}

/* Строка выдачи прав: списки тянутся по ширине карточки, кнопка стоит в
   одном ряду с ними, пояснение — отдельной строкой под ними */
.aclrow{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end}
.aclrow .field{margin:0;min-width:0}
.aclrow .field.wide{flex:1 1 260px}
.aclrow .field.narrow{flex:0 1 190px}
.aclrow>.btn{flex:0 0 auto}

/* Включённая правка видна по нажатому карандашу: иначе непонятно, почему
   текст то меняется, то нет */
.btn.iconbtn.on{background:var(--blue-bg);border-color:var(--blue);color:var(--blue)}
.docpage:not(.edit) .docp,.docpage:not(.edit) td{cursor:default}

/* Выделенный прямоугольник в книге: рамка по краю выделения, как в Excel,
   и заметная заливка — иначе не видно, что именно сейчас очистится */
table.xlgrid td.sel{background:var(--blue-bg)}
table.xlgrid td.sel .xlc{background:transparent}
table.xlgrid td.anchor .xlc{box-shadow:0 0 0 2px var(--blue) inset}
table.xlgrid th[data-col],table.xlgrid th[data-row]{cursor:pointer;user-select:none}
table.xlgrid th.selhead{background:var(--blue-bg);color:var(--blue)}

/* Пустой абзац: в него ставят курсор и дописывают — значит у него должна
   быть высота строки и видимое место, иначе попасть туда нечем */
.docpage.edit .docp.docempty{min-height:1.5em}
.docpage.edit .docp.docempty:empty::before{content:'пустая строка — можно писать';
  color:var(--tx-faint);font-size:12px}
/* строка для нового абзаца: отделена от документа, чтобы её не путали с
   его собственным текстом */
/* поле под новые абзацы сразу в несколько строк: чаще дописывают не одну
   строку, а кусок текста, и место под него должно быть видно */
.docpage.edit .docp.docnew{border-top:1px dashed var(--bd-medium);margin-top:10px;
  padding-top:8px;min-height:4.5em}
.docpage.edit .docp.docnew:empty::before{content:'новые абзацы — пишите здесь; Enter начинает следующий, пустая строка даёт отступ'}
.docpage:not(.edit) .docp.docnew{display:none}
.docpage.edit .docp.docempty:focus::before{content:''}

/* узкий экран: шаги переносятся, но остаются в одну колонку подписей */
@media (max-width:1100px){.stepper .step .s{font-size:11px}.stepline{flex-basis:10px;width:10px}}
@media (max-width:820px){.stepper .step .s{display:none}.stepper .step.on .s{display:inline}}

/* Пометки в PDF.

   Страницы рисуем сами, поверх каждой лежит холст для пометок. Полоса с
   орудиями закреплена сверху: до неё не нужно возвращаться прокруткой. */
.pdfbox{border:1px solid var(--bd-medium);border-radius:8px;overflow:hidden;background:var(--bg-soft)}
.pdfbar{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:8px;
  border-bottom:1px solid var(--bd-subtle);background:#fff}
.pdfbar .grow{flex:1 1 auto}
.pdfpages{max-height:72vh;overflow:auto;padding:12px;display:flex;flex-direction:column;
  align-items:center;gap:14px}
.pdfpage{position:relative;width:100%;max-width:900px;background:#fff;
  box-shadow:0 1px 6px rgba(0,0,0,.18)}
.pdfpage canvas{display:block;width:100%;height:auto}
.pdfpage canvas.pdfink{position:absolute;left:0;top:0;touch-action:none}
/* орудие видно по курсору: рисовать и смотреть — разные занятия */
.pdfbox.tool-hand .pdfink{pointer-events:none}
.pdfbox.tool-mark .pdfink,.pdfbox.tool-pen .pdfink{cursor:crosshair}
.pdfbox.tool-note .pdfink{cursor:copy}
.pdfnote{position:absolute;z-index:5;width:260px;max-width:80%;background:#fff;
  border:1px solid var(--bd-strong);border-radius:8px;padding:8px;
  box-shadow:0 6px 18px rgba(0,0,0,.18)}
.pdfnote textarea{width:100%;min-height:64px;resize:vertical}
.pdfnote .row{display:flex;gap:6px;justify-content:flex-end;margin-top:6px}
@media (max-width:820px){.pdfpages{max-height:60vh;padding:8px}}

/* карточка только на просмотр: fieldset не должен приносить свою рамку и
   мешать сеткам внутри — у него своя минимальная ширина по умолчанию */
.roview{border:0;padding:0;margin:0;min-width:0}
.roview .inp,.roview input,.roview select,.roview textarea{
  background:var(--bg-muted);border-color:transparent;color:var(--tx-primary);
  opacity:1;cursor:default;-webkit-text-fill-color:var(--tx-primary)}
.roview .btn,.roview button{display:none}
.roview .savemark{color:var(--tx-muted)}

/* Диаграмма Ганта на экране проектов. Полоса лежит в дорожке шириной в
   колонку: её место и длина считаются в процентах от отрезка дат, и
   таблица остаётся таблицей — ни холста, ни картинки. */
/* Ширину граф задаём сами: при вольной раскладке место уходит полосе, а
   название задачи ужимается до переноса по буквам. Не поместилось —
   таблица едет вбок в своей обёртке, как прочие. */
.gantt{min-width:920px;table-layout:fixed}
.gantt th:nth-child(1){width:260px}
.gantt th:nth-child(2){width:170px}
.gantt th:nth-child(3){width:90px}
.gantt .gscale{position:relative;height:16px}
.gantt .gtick{position:absolute;top:0;font-size:10px;color:var(--tx-faint);
  text-transform:none;letter-spacing:0;white-space:nowrap;transform:translateX(-2px)}
.gantt .gtrack{position:relative;height:18px;background:var(--bg-muted);border-radius:4px}
.gantt .gbar{position:absolute;top:3px;height:12px;border-radius:6px;min-width:3px}
.gantt .g-done{background:var(--green)}
.gantt .g-run{background:var(--blue)}
.gantt .g-open{background:var(--grey)}
.gantt .g-late{background:var(--red)}
.gantt .gnow{position:absolute;top:0;bottom:0;width:1px;background:var(--tx-faint)}
.gantt td.sec{background:#FFF;border:0;padding:10px 0 4px;font-weight:600;font-size:11px}

/* спрятанное атрибутом hidden прячется всегда: у кнопок и ячеек свой
   display, и без этого правила они его переспорят */
[hidden]{display:none !important}

/* ---------- антидопинговое обучение: карточки теста и разделы курса ---------- */
/* карточка показывается по одной: список вопросов целиком читают наискось */
.adcard{display:none;border:1px solid var(--bd-strong);border-radius:8px;padding:18px 20px;
  background:#fff;box-shadow:0 1px 3px rgba(16,24,40,.08);margin-bottom:12px}
.adcard.on{display:block}
/* заголовок темы — то, что ищут глазами первым */
.adcard .sec-title{font-size:16px}
/* полоса и счётчик стоят над карточкой, а не внутри: они про весь путь */
.adcard .adbody{max-width:760px}
.adq{font-size:15px;line-height:1.45}
.adopts{display:flex;flex-direction:column;gap:6px}
/* вариант — строка во всю ширину: попасть по ней проще, чем по кружку */
.adopt{display:flex;gap:8px;align-items:flex-start;padding:8px 10px;border:1px solid var(--bd);
  border-radius:4px;cursor:pointer;background:var(--bg)}
.adopt:hover{background:var(--bg-muted)}
.adopt input{margin-top:2px}
/* после ответа: верное зелёным, ошибочно выбранное красным */
.adopt.ok{border-color:var(--green);background:var(--green-bg)}
.adopt.bad{border-color:var(--red);background:var(--red-bg)}
.adnote{padding:10px 12px;border-radius:4px;border:1px solid var(--bd);font-size:13.5px}
.adnote.ok{border-color:var(--green);background:var(--green-bg)}
.adnote.bad{border-color:var(--red);background:var(--red-bg)}
/* полоса продвижения по тесту */
.adbar{height:6px;border-radius:3px;background:var(--bg-muted);overflow:hidden}
.adbar-in{height:100%;background:var(--blue);transition:width .2s}
/* раздел курса: заголовок кликабелен, текст читается колонкой */
.adlesson{border:1px solid var(--bd);border-radius:6px;padding:10px 12px}
.adlesson summary{cursor:pointer}
.adbody{max-width:760px;line-height:1.5}
.adbody p{margin:0 0 10px}

/* ---------- конструктор курсов: программа шагами ---------- */
/* шаг программы — карточка в ленте: видно порядок и что это за шаг */
.adstep{border:1px solid var(--bd);border-radius:6px;padding:10px 12px;margin-bottom:8px;background:var(--bg)}
.adstep.on{border-color:var(--blue);background:var(--blue-bg)}
.adstep-n{font-size:11.5px;color:var(--tx-secondary);text-transform:uppercase;letter-spacing:.3px}
/* форма правки открывается внутри шага, а не уводит на другую страницу */
.adform{border-top:1px solid var(--bd);padding-top:12px}
/* список готовности: отметка слева, пояснение под строкой */
.adcheck-row{display:flex;gap:8px;align-items:flex-start;padding:5px 0;font-size:13.5px;
  color:var(--tx-secondary)}
.adcheck-row.ok{color:var(--tx)}
.adcheck-mark{width:14px;text-align:center;color:var(--tx-secondary)}
.adcheck-row.ok .adcheck-mark{color:var(--green)}

/* ---------- набор учебного текста: панель и поле ---------- */
.adtools{display:flex;gap:6px;align-items:center;flex-wrap:wrap;padding:6px 8px;
  border:1px solid var(--bd);border-bottom:none;border-radius:4px 4px 0 0;background:var(--bg-muted)}
.adtools-sep{width:1px;height:20px;background:var(--bd-strong);margin:0 2px}
.adtools .inp.sm{height:26px;padding:0 6px;font-size:12.5px}
/* поле набора: та же ширина строки, что у читателя, — видно, как ляжет текст */
.adeditor{border:1px solid var(--bd-strong);border-radius:0 0 4px 4px;padding:12px 14px;
  min-height:220px;max-height:460px;overflow-y:auto;background:#fff;line-height:1.5;font-size:14px}
.adeditor:focus{outline:2px solid var(--blue);outline-offset:-2px}
.adeditor p{margin:0 0 10px}
.adeditor ul,.adeditor ol{margin:0 0 10px;padding-left:22px}
.adeditor img,.adbody img{max-width:100%;height:auto;border-radius:4px;margin:6px 0}
.adbody ul,.adbody ol{margin:0 0 10px;padding-left:22px}
.adbody blockquote{margin:0 0 10px;padding:8px 12px;border-left:3px solid var(--bd-strong);
  background:var(--bg-muted);border-radius:0 4px 4px 0}

/* ---------- вопрос: варианты строками и картинка ---------- */
/* строка варианта: отметка «верный», поле и кнопка убрать — в одну линию */
.adopt-row{display:flex;gap:8px;align-items:center;margin-bottom:6px}
.adopt-row .inp{flex:1}
.adopt-row .chk{margin:0;padding:0 2px}
/* картинка вопроса: показывается над вариантами, шире колонки не растёт */
.adqimg{border:1px solid var(--bd);border-radius:4px;padding:6px;background:var(--bg);max-width:520px}
.adqimg img{display:block;max-width:100%;height:auto;border-radius:3px}

/* ---------- прохождение курса: карточка темы и проверка по ходу ---------- */
/* блок самопроверки отделён от текста: это уже не чтение, а действие */
.adselfcheck{border-top:1px solid var(--bd);padding-top:12px;margin-top:4px}
.adselfq{border:1px solid var(--bd);border-radius:6px;padding:12px;background:var(--bg)}
.adselfq .adopts{gap:4px}


/* ---------- сетка плана НМО: вид бланка федерации ---------- */
/* Бланк узкий по горизонтали и высокий по вертикали: колонок под сорок, и
   текст в шапке стоит стоймя. Повторяем его вид набором приложения — но
   линии здесь заметнее обычной таблицы: в сетке из тысячи клеток глаз ведут
   именно они, а не отступы.
   Слева две колонки держатся на месте при прокрутке вправо: без них через
   десять колонок непонятно, чей это крестик. */
.nmowrap{max-height:76vh}
table.t.nmogrid{border-collapse:separate;border-spacing:0;table-layout:fixed}
table.t.nmogrid td{border-right:1px solid var(--bd-medium);border-bottom:1px solid var(--bd-medium);
  padding:3px 4px;font-size:12px;vertical-align:middle;background:#fff}
table.t.nmogrid td.c1{position:sticky;left:0;z-index:2}
table.t.nmogrid td.c2{position:sticky;left:var(--nmo1,250px);z-index:2;
  border-right:2px solid var(--bd-strong)}
/* строка с наименованием держится сверху: уехав вниз по методам, видно,
   над каким мероприятием стоишь */
table.t.nmogrid tr.nmosticktop td{position:sticky;top:0;z-index:3;
  border-top:1px solid var(--bd-strong);border-bottom:1px solid var(--bd-strong)}
table.t.nmogrid tr.nmosticktop td.c1,table.t.nmogrid tr.nmosticktop td.c2{z-index:4}

/* строки шапки мероприятия: подпись слева, значения по колонкам */
table.t.nmogrid tr.nmohead td{background:var(--bg-muted);text-align:center;color:var(--tx-secondary)}
table.t.nmogrid tr td.nmolb{text-align:left;font-weight:600;color:var(--tx-primary);
  background:var(--bg-header);white-space:normal;line-height:1.25;vertical-align:middle}
table.t.nmogrid tr td.nmosub{text-align:center;font-size:11px;font-weight:500;
  color:var(--tx-secondary);background:var(--bg-header);white-space:nowrap}
/* период, этап и месяц пишутся целиком: сокращения вроде «сент…» в
   согласуемом документе читаются как опечатка */
table.t.nmogrid tr.nmoband-row td{white-space:normal;word-break:break-word;
  line-height:1.15;padding:4px 3px}
table.t.nmogrid tr td.nmoband{font-weight:600;color:var(--tx-primary);
  background:var(--bg-header);font-size:11px;
  border-right:1px solid var(--bd-strong)}
table.t.nmogrid tr td.nmoband.alt{background:var(--bg-muted)}
table.t.nmogrid tr td.nmodate{font-size:11px;white-space:nowrap;font-variant-numeric:tabular-nums}
table.t.nmogrid tr td.nmokind{font-weight:600;color:var(--tx-primary);background:var(--bg-header)}
table.t.nmogrid tr td.nmokind a{color:inherit;text-decoration:none}
table.t.nmogrid tr td.nmokind a:hover{color:var(--blue)}

/* место и состав в бланке написаны стоймя: иначе колонка в сантиметр шириной
   не вмещает «Кисловодск, УТЦ «Юг Спорт»» */
table.t.nmogrid tr td.nmovert{height:126px;padding:4px 0}
table.t.nmogrid tr td.nmovert.sm{height:88px}
table.t.nmogrid tr td.nmovert span{display:block;writing-mode:vertical-rl;transform:rotate(180deg);
  white-space:nowrap;overflow:hidden;max-height:100%;margin:0 auto;
  font-size:11px;line-height:1.1;color:var(--tx-primary)}

/* количество обследуемых правится прямо в клетке */
table.t.nmogrid tr td.nmocnt{padding:1px 2px;background:#fff}
.nmoqty{width:100%;height:22px;padding:0 2px;border:1px solid transparent;border-radius:3px;
  background:transparent;text-align:center;font-size:12px;font-variant-numeric:tabular-nums;
  -moz-appearance:textfield}
.nmoqty::-webkit-outer-spin-button,.nmoqty::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.nmoqty:hover{border-color:var(--bd-strong)}
.nmoqty:focus{border-color:var(--blue);background:#fff;outline:none}
.nmoqty.busy{opacity:.55}
.nmoqty.bad{border-color:var(--red,#E5484D);background:var(--red-bg,#FFF0F0)}

/* граница между шапкой и телом — как двойная линейка бланка */
table.t.nmogrid tr.nmosplit td{border-bottom:2px solid var(--bd-strong);height:26px}

/* карточка задачи слева: номер, виды обследования, текст и кружки колонок */
table.t.nmogrid tr td.nmotask{text-align:left;vertical-align:top;padding:8px;background:#fff;
  border-bottom:1px solid var(--bd-strong)}
.nmotasknum{float:left;width:22px;height:22px;margin:0 8px 4px 0;border-radius:11px;
  background:var(--bg-header);color:var(--tx-primary);font-weight:700;font-size:12px;
  line-height:22px;text-align:center}
.nmotasktext{color:var(--tx-primary);line-height:1.3}
.nmotaskall{clear:both;display:flex;flex-wrap:wrap;gap:3px;align-items:center;margin-top:6px}
.nmotaskall .faint{margin-right:2px;font-size:11px}
.nmodot{width:11px;height:11px;padding:0;border:1px solid var(--bd-strong);border-radius:6px;
  background:#fff;cursor:pointer}
.nmodot:hover{border-color:var(--blue)}
.nmodot.on{background:var(--blue);border-color:var(--blue)}

/* метод: номер и короткий текст — полный показывает подсказка и вкладка
   «Программа», иначе левая колонка разрастается на весь абзац методики */
table.t.nmogrid tr td.nmometh{text-align:left;vertical-align:top;padding:6px;background:#fff;
  font-size:11px;line-height:1.25;color:var(--tx-secondary)}
.nmomnum{display:inline-block;min-width:18px;margin-right:4px;font-weight:700;
  color:var(--tx-primary);font-variant-numeric:tabular-nums}

/* клетка пересечения: кликается целиком — в сетке на сорок колонок промах
   по мелкому значку ставит отметку соседнему методу */
table.t.nmogrid tr td.nmocell{text-align:center;cursor:pointer;color:var(--blue);
  font-weight:600;height:26px;user-select:none}
table.t.nmogrid tr td.nmocell:hover{background:var(--bg-muted);box-shadow:inset 0 0 0 1px var(--blue-bd)}
table.t.nmogrid tr td.nmocell.on{background:var(--blue-bg)}

/* ---------- подсказка по наведению ---------- */
/* Та же карточка, что на графиках (svg.chart .ctip): заголовок жирным,
   пояснения ниже. Родная подсказка браузера показывает одну серую строку и
   через секунду — в сетке этого мало. */
.amstip{position:fixed;z-index:60;display:none;max-width:340px;padding:8px 10px;
  background:var(--bg-surface);border:1px solid var(--bd-strong);border-radius:5px;
  box-shadow:0 6px 18px rgba(16,24,40,.12);pointer-events:none;font-size:11px;line-height:1.35}
.amstip-h{font-weight:600;color:var(--tx-primary);margin-bottom:3px}
.amstip-l{color:var(--tx-secondary);margin-top:2px}

/* действия в строке таблицы: одной полосой, кнопки не растягиваются и не
   переносятся — иначе строка вырастает вдвое, а «удалить» уезжает под
   соседнюю запись */
.nmoacts{flex-wrap:nowrap;align-items:center}
.nmoacts .btn{white-space:nowrap}
.nmoacts form{display:inline-flex}

/* название документа НМО: длинное, но правят его редко — набор помельче,
   чтобы оно не перевешивало остальную форму */
.nmotitle{font-size:12px}

/* Панель отмеченного в плане закупки: партию принимают целиком, и поля для
   неё держатся отдельным блоком над таблицей — чтобы не путать их с правкой
   одного пункта. Отключённые кнопки говорят, что отмечать пока нечего. */
.buybulk{border:1px solid var(--bd-medium);border-radius:6px;padding:12px;background:var(--bg-muted)}
.buybulk .inp{background:var(--bg-surface)}
.buybulk button[disabled]{opacity:.5;cursor:default}

/* Раскрытый склад: он живёт строкой в таблице мест хранения, под своим
   складом. Поэтому не карточка в карточке, а вложенный блок — с полем по
   краям и своим фоном, чтобы было видно, где кончается строка списка. */
.placeopen > td{background:var(--bg-muted);padding:12px 16px}
.placebox{background:var(--bg-surface);border:1px solid var(--bd-medium);
  border-radius:6px;padding:12px}
.placeact{background:var(--bg-surface);border:1px solid var(--bd-medium);
  border-radius:6px;padding:12px;margin-top:12px}
.placeopen table.t thead th{position:static}

/* Строка рейтинга и полосы выполнения — это ссылка: нажатие на направление
   сужает к нему весь разрез нагрузок. Подсветка нужна затем же, зачем она в
   таблице: показать, что строка живая, до нажатия, а не после. */
a.rankrow{cursor:pointer}
a.rankrow:hover rect:first-child{fill:var(--bg-muted)}
a.rankrow:hover text{fill:var(--blue)}

/* Подпись строки отбора, за которой стоит пояснение: без пунктира человек не
   догадается навести мышь, а именно там сказано, что означает выбор. */
.caption.hintlab{border-bottom:1px dotted var(--bd-strong);cursor:help}

/* Живая область, пока грузится новый вид: содержимое бледнеет и не принимает
   нажатий. Без этого человек щёлкает второй раз, не поняв, что первое уже
   считается, — а на разрезах нагрузки расчёт идёт полсекунды. */
#livezone.live-wait{opacity:.55;pointer-events:none;transition:opacity .12s ease}

/* Метка в легенде — переключатель: нажатие снимает свой ряд с картинки и
   возвращает обратно. Подчёркивания не даём: легенда читается как подпись,
   а не как ссылка, и лишняя черта спорит с чёрточкой снятого ряда */
.legitem{cursor:pointer;text-decoration:none;color:inherit;border-radius:4px;padding:1px 4px}
.legitem:hover{background:var(--bg-muted);color:inherit}

/* Свой человек и выход в нижней части меню: в шапке на телефоне для них
   нет места, а нужны они везде. На широком экране дублируют шапку —
   это дешевле, чем прятать и показывать одно и то же по ширине. */
.side-me,.side-exit{display:flex;align-items:center;gap:10px;padding:8px 14px;
  color:var(--tx-secondary);text-decoration:none;font-size:13px}
.side-me:hover,.side-exit:hover{background:var(--bg-subtle);text-decoration:none}
.side-me .nm{display:block;font-weight:600;color:var(--tx-primary);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-me .rl{display:block;font-size:11px;color:var(--tx-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-exit .ico{display:flex;width:16px;height:16px;align-items:center;justify-content:center}
.side-me{border-top:1px solid var(--bd-subtle);margin-top:4px}
/* свёрнутое меню — одни значки; подпись остаётся в разметке, чтобы на
   телефоне, где меню выезжает полным, её не пришлось дорисовывать */
nav.side.collapsed .side-me .lbl,nav.side.collapsed .side-exit .lbl{display:none}

/* ===== телефон: ничто не шире экрана =====
   На узком экране страницу разъезжает не текст, а то, чему задали ширину:
   поля в три колонки, карточки с max-width в разметке, полоса вкладок из
   восьми слов. Пользоваться этим нельзя — приходится возить страницу вбок,
   и половина содержимого оказывается за краем.

   Поэтому здесь снимаем заданные в разметке ширины (inline-стиль уступает
   только !important), а горизонтальную прокрутку оставляем ровно там, где
   она уместна: внутри таблиц и полосы вкладок. */
@media (max-width:820px){
  /* бланк в одну колонку: на телефоне поле в 240 точек оставляет пустой
     край, а два рядом не помещаются */
  .formgrid.even{grid-template-columns:1fr}

  /* полоса вкладок прокручивается сама, а не тянет за собой страницу */
  .tabs{overflow-x:auto;max-width:100%;-webkit-overflow-scrolling:touch;
    scrollbar-width:thin}
  .tabs a,.tabs button{flex:0 0 auto;white-space:nowrap}

  /* ширины из разметки на телефоне не работают: поле в 300px оставляет
     за краем и себя, и кнопку рядом */
  .card[style]{max-width:none !important}
  .field[style]{width:auto !important;max-width:none !important;
    grid-column:span 1 !important}
  form[style]{max-width:none !important}
  details.fold[style]{max-width:none !important}

  /* строка «поле + кнопка» переносится, а не сжимает поле до нечитаемого */
  .flex{flex-wrap:wrap}
  .crewrow .field{width:100% !important}

  /* в один столбец: две и три колонки на 360 точках нечитаемы */
  .grid2,.grid3,.grid4{grid-template-columns:1fr}

  /* таблицы возят вбок внутри своей рамки */
  .ptw,.tw{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tw.flow{overflow-x:auto}
  table.t.evlist,table.t.complist{min-width:820px}

  /* картинки и коды не распирают карточку */
  img,svg{max-width:100%;height:auto}

  /* заголовок экрана и кнопки рядом с ним */
  .page-head .sec-title,.page-head h1{min-width:0;word-break:break-word}

  /* Метка с фамилией и должностью длиннее экрана: на телефоне она
     переносится и становится выше, а не уезжает за край. Высоту
     отпускаем — иначе второй строке негде встать. */
  .tag{white-space:normal;height:auto;min-height:18px;max-width:100%;
    padding-top:2px;padding-bottom:2px;align-items:flex-start;line-height:1.3}
  .nowrap{white-space:normal}
  /* подписи в карточках тоже рвём по словам, а не растягиваем строку */
  .card,.caption,.psub{overflow-wrap:anywhere}

  /* Список моделей шире экрана: у select ширина по самому длинному
     пункту, а flex не жмёт элемент ниже его содержимого, пока ему это
     не разрешат. */
  select.inp,input.inp,textarea.inp{min-width:0;max-width:100%}
  .flex > select,.flex > input,.flex > .field,.flex > .inp{min-width:0}
  /* и заданная в разметке наименьшая ширина: на 360 точках она не
     помогает читать, а вытесняет содержимое за край */
  select[style],input[style],textarea[style]{min-width:0 !important;
    max-width:100% !important}

  /* Шапка экрана: на широком заголовок и кнопки стоят в строку нарочно,
     на телефоне строка не помещается — переносим. */
  .page-head{flex-wrap:wrap}
  .page-head > *{min-width:0}
  /* ряд кнопок шире экрана: на широком он держится одной строкой
     нарочно (flex:0 0 auto), здесь — переносится и прижимается влево */
  .page-head .acts{flex:1 1 100%;padding-top:4px;justify-content:flex-start;
    max-width:100%}
  .page-head .acts > *{flex:0 1 auto;min-width:0}

  /* Схема структуры шире любого телефона: её возят пальцем внутри
     рамки, а не растягивают страницу. */
  .orgwrap,.orgscroll,.steps{max-width:100%;overflow-x:auto;
    -webkit-overflow-scrolling:touch}

  /* Шапка: кнопка меню, два списка и человек. На 360 точках они встают
     впритык, поэтому списки делим по месту, а не держим по 132px —
     иначе второй уезжает за край вместе с колокольчиком. */
  header.top{gap:6px;padding:0 8px}
  header.top select{flex:1 1 0 !important;width:auto !important;
    min-width:84px !important;max-width:200px !important;font-size:12.5px;padding:0 4px}
  /* Делить ширину должны обёртки списков, а не всё подряд: колокольчик
     тоже «flex», и с общим правилом он забирал треть шапки, а распорка
     — ещё треть. */
  header.top > div.flex{flex:1 1 0;min-width:0}
  header.top > .grow{display:none}
  header.top > a.flex{flex:0 0 auto}
  .top-user{padding-left:6px;gap:6px}
  .avatar{width:26px;height:26px;border-radius:13px;font-size:11px}
  /* Шапку занимают списки сезона и команды: читать «2026-» и «Ски-крос»
     нельзя, а выбирают по ним каждый день. Человек и выход уезжают в
     меню — там они всегда на месте. */
  .top-user{display:none}
  /* меню выезжает полным даже когда на большом экране оно свёрнуто */
  nav.side.collapsed .side-me .lbl,nav.side.collapsed .side-exit .lbl{display:block}

  /* Дневник: липкие «показатель» и «единица» занимали 350 точек — на
     телефоне это весь экран, и дням места не оставалось. Сужаем их и
     разрешаем названию переноситься: лучше две строки, чем многоточие.
     Заголовок блока не липнет — его и так видно. */
  table.diary td.metric,table.diary th.metric{min-width:132px;max-width:132px;
    white-space:normal;overflow:visible;line-height:1.25}
  table.diary td.unit,table.diary th.unit{left:132px;min-width:42px}
  table.diary tr.blk td{position:static}
  table.diary th,table.diary td{padding:0 5px}
  .tw.amsx{max-height:62vh}

  /* Таблица, положенная прямо в карточку, без обёртки с прокруткой:
     таких мест много и переписывать их по одному незачем — пусть
     прокручивается сама карточка. */
  .card{overflow-x:auto}
  .blkbody{overflow-x:auto;max-width:100%}

  /* наименьшая ширина из разметки тоже лишняя: она держит строку шире
     экрана, хотя содержимое давно переносится */
  .card[style],.field[style],form[style],details[style],div[style],
  label[style],span[style],section[style],li[style]{min-width:0 !important}
  label[style],span[style]{max-width:100% !important}

  /* сетки, заданные в колонки: на телефоне — одна */
  .coachgrid{grid-template-columns:1fr}
  .coachbox{max-width:100%}

  /* подпись у галочки переносится, а не вылезает за рамку */
  label.chk{white-space:normal;align-items:flex-start}

  /* таблица внутри свёрнутого блока прокручивается в своей обёртке */
  .blkbody > div{overflow-x:auto;max-width:100%}
  /* карточка заявки: перечень позиций шире неё, и прокручиваться
     должен он, а не вся страница */
  .mtoord{overflow-x:auto}

  /* Обычные таблицы жмём: отступы по 12 точек с каждой стороны ячейки
     на телефоне съедают колонку целиком. Текст в ячейке переносится —
     лучше три строки, чем уехавший за край столбец. */
  table.t th,table.t td{padding:5px 6px}
  /* «ширина 170» у графы задумана для широкого экрана: на телефоне
     она растягивает таблицу вдвое, хотя текст давно переносится */
  table.t th[style],table.t td[style]{width:auto !important;
    min-width:0 !important}
  table.t td{white-space:normal;overflow-wrap:anywhere}
  /* даты и числа переносить нельзя: они читаются одним куском */
  table.t td.tnum,table.t td.num,table.t td.nowrap{white-space:nowrap;
    overflow-wrap:normal}

  /* длинное название отчёта рвём по словам: заголовок строки не должен
     вытеснять дату и значок справа */
  .rep-head .grow,.rep-head .grow > div{min-width:0;overflow-wrap:anywhere}
}

/* Совсем узкий экран: 320 точек — это старый телефон и половина
   раскладки в две колонки. Здесь уже не до красоты строки: поля и
   кнопки занимают всю ширину, числовые своды идут одной колонкой. */
@media (max-width:420px){
  .flex > .inp,.flex > select,.flex > input{flex:1 1 100%}
  /* флажок — не поле: растянутый на строку, он уезжал от своей подписи вверх */
  .flex > input[type=checkbox],.flex > input[type=radio]{flex:0 0 auto}
  .flex > input[type=checkbox] + span,.flex > input[type=radio] + span{flex:1 1 0;min-width:0}
  .grid-sum,.foot{grid-template-columns:1fr;flex-wrap:wrap}
  /* «Удалить значения мужского плана (2808)» в одну строку не влезает
     ни на каком телефоне: отпускаем высоту и переносим надпись */
  .btn{max-width:100%;white-space:normal;height:auto;min-height:32px;
    padding:5px 10px;line-height:1.25;text-align:center}
  /* «Фамилия · должность» в галочке шире 300 точек: строка списка
     отдаётся ей целиком, иначе она вылезает из карточки */
  label.chk{flex:1 1 100%;max-width:100%}
  /* Строка месяцев живёт в ячейке таблицы, а таблица и так возит вбок:
     пусть ячейка станет шире, чем рвать «апр» пополам. */
  .tw .flex.faint,.ptw .flex.faint{flex-wrap:nowrap}
  .tw .flex.faint > div,.ptw .flex.faint > div{min-width:18px}
  .card.pad,.card{padding-left:10px;padding-right:10px}
}

/* Только что заведённое: его ищут глазами сразу после действия, а пять
   одинаковых пустых строк различить нечем. Полоса слева и мягкий фон —
   «вот оно»; рамки нет нарочно, она читается как «тут ошибка». */
.justnew{background:var(--blue-bg);box-shadow:inset 3px 0 0 var(--blue);
  border-radius:6px;padding:8px 10px 10px;margin-left:-10px}

/* Списки приглашения: фамилию и должность не рвём по буквам. На узком
   экране мобильные правила снимают заданные ширины колонок, и ячейка
   схлопывалась до одной буквы — «Ози мо в Але ксе й» прочесть нельзя.
   Таблица вместо этого едет вбок в своей обёртке .ptw, как и прочие. */
table.t.invtbl th,table.t.invtbl td{white-space:nowrap;overflow-wrap:normal}
table.t.invtbl input[type="email"]{min-width:190px}

/* Проекты списком-таблицей: строка раскрывается прямо под собой, и
   раскрытая часть живёт в одной ячейке на всю ширину. Отступы ей нужны
   свои — иначе задачи и участники липнут к краям таблицы. */
/* На узком экране таблица ужималась до переноса по буквам: «Дизайн
   старто вого костюм а». Ширину держит сама таблица, а не графа, и
   лишнее уезжает вбок в своей обёртке .ptw — как у прочих таблиц. */
table.spprj{min-width:820px}
/* На телефоне 820 точек нет: строки раскладываются в список, и графа
   подписывается своим именем — без подписи «26.01.2027» ни о чём не
   говорит. Раскрытое к таблице не относится: оно под ней. */
@media (max-width:820px){
  table.spprj{min-width:0;display:block}
  table.spprj > thead{display:none}
  table.spprj > tbody,table.spprj > tbody > tr,table.spprj > tbody > tr > td{display:block;width:auto}
  table.spprj > tbody > tr{border-bottom:1px solid var(--bd-subtle);padding:6px 0}
  table.spprj > tbody > tr > td{border:0;padding:3px 12px}
  table.spprj > tbody > tr > td[data-lb]::before{content:attr(data-lb) ' · ';
    color:var(--tx-muted);font-size:11px}
  table.spprj > tbody > tr > td.right{text-align:left}
}
table.spprj > tbody > tr.on > td{background:var(--blue-bg)}
/* Раскрытое живёт под таблицей, по ширине экрана: внутри строки оно
   уезжало бы вбок вместе с ней. */
.spopen > table:first-child{margin-top:4px}
/* Ширину граф задаём сами: при вольной раскладке таблица отдаёт всё
   место кнопкам, а название задачи ужимает до переноса по буквам. */
table.sptasks{min-width:860px;table-layout:fixed}
table.sptasks th:nth-child(1){width:auto}
table.sptasks th:nth-child(2){width:120px}
table.sptasks th:nth-child(3){width:190px}
table.sptasks th:nth-child(4){width:140px}
table.sptasks th:nth-child(5){width:110px}

/* Исполнителей у задачи бывает несколько: список свёрнут и подписан тем,
   что в нём выбрано, — развёрнутым он занимал бы пол-экрана на каждой
   задаче. Устроен так же, как выбор разделов у отдела. Зовётся «whopick»,
   потому что «pickbox» в приложении уже занят списком на «Диске» — и его
   высота в 132 точки доставалась свёрнутому выбору как пустое место. */
.whopick{position:relative}
.whopick > summary{cursor:pointer;font-size:12.5px;padding:6px 8px;
  border:1px solid var(--bd-medium);border-radius:6px;background:var(--bg-surface);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Раскрытый список — слой поверх формы: своя ширина под должности,
   «Помошник руководителя отдела проведения соревноаний» в ячейку не
   умещается и рассыпается лесенкой. Форма при этом не раздвигается, и
   экран не прыгает на каждое раскрытие. */
.whopick-body{position:absolute;z-index:30;top:100%;left:0;margin-top:4px;
  width:max-content;min-width:100%;max-width:min(460px,86vw);
  max-height:260px;overflow:auto;border:1px solid var(--bd-medium);
  border-radius:6px;padding:6px 8px;background:var(--bg-surface);
  box-shadow:0 6px 20px rgba(31,45,61,.14)}
/* строка списка переносится: «Помошник руководителя отдела проведения
   соревноаний» в одну строку не встаёт ни при какой ширине */
.whopick-body .chk{align-items:flex-start;white-space:normal}
.whopick-body .chk > span{white-space:normal;line-height:1.35}
.whopick-body .chk > input{margin-top:3px}

/* Выбор разделов у отдела: список длинный, поэтому он свёрнут и
   прокручивается в своей рамке — иначе строка отдела уезжает на
   три экрана вниз. */
.menucell details > summary{cursor:pointer;font-size:12.5px;padding:6px 8px;
  border:1px solid var(--bd-medium);border-radius:6px;background:var(--bg-surface)}
.menubox{max-height:240px;overflow:auto;border:1px solid var(--bd-subtle);
  border-radius:6px;padding:6px 8px;margin-top:4px;background:var(--bg-surface)}
.menugrp{font-size:11px;color:var(--tx-muted);margin:6px 0 2px}
.menugrp:first-child{margin-top:0}
/* Подраздел стоит под своим разделом со сдвигом: отмечают его
   отдельно, но читается он как часть раздела, а не как сосед. */
.menubox .chk.deep{margin-left:16px}
.menubox .chk.deep > span{color:var(--tx-secondary)}
/* Задачи подготовки правят прямо в таблице, и поле должно занимать свою
   графу целиком: иначе таблица ужимает его до пары букв, и ни названия
   задачи, ни имени исполнителя не разобрать. */
table.taskedit td .inp{width:100%}
table.taskedit td{vertical-align:middle}
/* Ширину держит само поле: графа её не задаёт — таблица сжимает колонку
   по содержимому, а содержимое тянется за колонкой. Не хватило места —
   таблица прокручивается вбок, как и прочие здесь. */
table.taskedit td:nth-child(1) .inp{min-width:230px}
table.taskedit td:nth-child(2) .inp{min-width:190px}
table.taskedit td:nth-child(3) .inp{min-width:150px}
table.taskedit td:nth-child(4) .inp{min-width:140px}

/* Возрастные группы с выбором пола: название с возрастом слева, два
   флажка справа. Колонками, чтобы имена и флажки стояли друг под другом
   и строку было видно целиком. */
.sexgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(0,360px));gap:6px 18px}
.sexrow{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
/* Название — кнопка, но выглядит текстом: кликать по нему удобно, а
   кнопкой оно в ряду было бы лишним пятном */
.sexrow .sexname{flex:1 1 170px;min-width:0;text-align:left;font:inherit;
  font-size:13px;line-height:1.35;background:none;border:0;padding:0;cursor:pointer;
  color:var(--tx-primary)}
.sexrow .sexname:hover{color:var(--blue)}
.sexrow .chk{flex:0 0 auto}
/* На узком экране название с возрастом само занимает строку: рядом с
   ним флажки не помещаются и «Женщины» уезжали под «Мужчин» порознь. */
@media (max-width:820px){
  .sexgrid{grid-template-columns:1fr;gap:10px 0}
  .sexrow{gap:6px 16px}
  .sexrow .sexname{flex:1 1 100%}
}

/* Строка над списком: объясняет, что отметки и есть меню отдела */
.menunote{font-size:11.5px;line-height:1.45;color:var(--tx-muted);
  background:var(--bg-subtle);border-radius:6px;padding:6px 8px;margin-bottom:6px}

/* Список курсов: название и пояснение переносим по словам, а не по
   буквам. Мобильное правило разрешает разрыв где угодно, и «Анти-до-
   пинг» вставало столбиком в одну букву. */
table.t.adtbl th,table.t.adtbl td{overflow-wrap:normal}
table.t.adtbl td:first-child{min-width:260px}