/*
 * Gym Log v2 — стили по визуальному канону gym-concept.html:
 * тёмный ink-фон, лайм/пайн/эмбер акценты, «стекло»-карточки, radius 22,
 * свайп-пейджер, кольцо-таймер, bottom-sheets с grab-ручкой.
 * Логика и продуктовые правила — из прода; здесь только «одежда».
 */
:root{
  --ink:#0B0E0D;
  --ink2:#0F1514;
  --surface: rgba(255,255,255,.045);
  --surface-2: rgba(255,255,255,.07);
  --hair: rgba(255,255,255,.08);
  --hair-2: rgba(255,255,255,.14);
  --lime:#C8F84A;
  --lime-dim:#9ec93a;
  --pine:#4FE0A6;
  --ember:#FFA24C;
  /* R16: «спад» не выражается существующей палитрой — единственный новый токен */
  --rose:#FF6B6B;
  --text:#ECF1EE;
  --muted:#7E8A83;
  --muted-2:#525c56;
  --radius:22px;
  /* прод-алиасы: charts.js рисует stroke="var(--ink)" / fill="var(--card)" /
     var(--line) — в тёмной теме перекрашиваем их через те же имена */
  --card:#0B0E0D;
  --line:rgba(255,255,255,.09);
  --paper:#050707;
  --pop:#FFA24C;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html{-webkit-text-size-adjust:100%}
/* глушим браузерные жесты у краёв (переключение вкладок/назад на Android)
   и pull-to-refresh — листает только пейджер приложения */
html,body{height:100%;overscroll-behavior:none}
body{
  background:#050707;
  color:var(--text);
  font-family:'Space Grotesk','Inter',system-ui,-apple-system,sans-serif;
  line-height:1.4;
  display:flex;align-items:center;justify-content:center;
  min-height:100dvh;
  padding:24px 12px;
  overflow:hidden;
  -webkit-font-smoothing:antialiased;
}
@media (max-width:520px){ body{padding:0} }

/* ===== phone frame (десктоп — рамка, мобайл — full-bleed) ===== */
.phone{
  width:410px;max-width:100%;
  height:840px;max-height:100dvh;
  background:
    radial-gradient(120% 60% at 50% -8%, #14201b 0%, transparent 55%),
    linear-gradient(180deg, var(--ink) 0%, var(--ink2) 100%);
  border-radius:44px;
  /* clip (не hidden): запрещает и ПРОГРАММНЫЙ скролл — иначе focus()
     на элементе шторки за нижней гранью сдвигает всю рамку вверх */
  position:relative;overflow:hidden;overflow:clip;
  border:1px solid var(--hair);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.9), inset 0 1px 0 rgba(255,255,255,.05);
  display:flex;flex-direction:column;
  /* containing block для position:fixed потомков — всё живёт внутри рамки */
  transform:translateZ(0);
}
@media (max-width:520px){ .phone{border-radius:0;border:none;height:100dvh;box-shadow:none;width:100%} }

#app{flex:1;min-height:0;display:flex;flex-direction:column}
.appwrap{flex:1;min-height:0;display:flex;flex-direction:column}

/* ===== header ===== */
header{padding:calc(14px + env(safe-area-inset-top)) 20px 4px;flex:0 0 auto}
.h-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.h-title{font-size:24px;font-weight:700;letter-spacing:-.5px;display:flex;align-items:center;gap:9px}
/* Обёртка ради общей базовой линии «Gym» и номера: выравнивание живёт здесь,
   а ряд .h-title остаётся align-items:center и про базовые линии не знает.
   Замерено (e2e-app-version, сцена 1), чтобы не пересказывать домыслы:
   baseline на всём .h-title сдвинул бы иконку всего на 0.2px — синтезированная
   база grid-бокса .mark и так почти совпадает с центром ряда. То есть обёртка
   спасает не от съехавшей иконки, а от связывания двух независимых решений:
   «как выровнен ряд с иконкой и бейджем» и «как выровнена пара текстов». */
.h-brand{display:flex;align-items:baseline;gap:7px}
/* Моно-серый, приглушённый: лайм в этом приложении несёт смысл («сегодня»,
   «выбрано», «потолок взят») — номер сборки его размывал бы. */
.app-version{font-family:'Space Mono',monospace;font-size:10.5px;font-weight:400;letter-spacing:0;color:var(--muted-2)}
.mark{
  width:26px;height:26px;border-radius:8px;flex:0 0 auto;
  display:grid;place-items:center;
  background:radial-gradient(circle at 50% 30%, rgba(200,248,74,.25), transparent 70%), #10160f;
  border:1px solid rgba(200,248,74,.35);
}
.mark svg{filter:drop-shadow(0 0 5px rgba(200,248,74,.85))}
.progress-badge{
  font-family:'Space Mono',monospace;font-size:10.5px;color:var(--lime-dim);
  background:rgba(200,248,74,.08);border:1px solid rgba(200,248,74,.22);
  border-radius:10px;padding:5px 9px;white-space:nowrap;
  /* v2-19: бейдж стал <button> (тап → календарь). line-height задан ЯВНО:
     <span> наследовал 1.4 от body, а UA-стиль кнопки в части браузеров ставит
     normal — высота бейджа, а с ней и его место в ряду, поехали бы, и это
     ровно то, что пиннит e2e-app-version (сцена 1: verRight < badgeLeft).
     appearance:none снимает остатки нативной отделки iOS; всё видимое —
     шрифт, цвет, фон, рамка, радиус — объявлено здесь явно. */
  line-height:1.4;-webkit-appearance:none;appearance:none;cursor:pointer;
}
.days{display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none}
.days::-webkit-scrollbar{display:none}
.chip{
  flex:0 0 auto;padding:9px 15px;border-radius:14px;
  background:var(--surface);border:1px solid var(--hair);
  font-size:14px;font-weight:600;color:var(--muted);cursor:pointer;
  display:flex;flex-direction:column;align-items:flex-start;gap:1px;line-height:1.1;
  transition:all .25s cubic-bezier(.34,1.4,.5,1);
  position:relative;
}
/* маркер «сегодня по плану» — якорь дня из selectActiveDay. Намеренно тихий:
   не спорит с состоянием .on (это разные вопросы — «какой день сегодня» и
   «какой день открыт»), поэтому точка, а не заливка или рамка. */
.chip .today-dot{
  position:absolute;top:7px;right:9px;width:5px;height:5px;border-radius:50%;
  background:var(--lime);box-shadow:0 0 6px rgba(200,248,74,.55);
}
/* Ширину чипа задаёт подпись, поэтому точка садится к ней вплотную — зазор
   выходил 1px на всех днях и ширинах. Пересечения нет, но запаса тоже: чуть
   длиннее название группы мышц — и наедет. Резервируем место под точку
   только там, где она есть, чтобы остальные чипы не расширять. */
.chip:has(.today-dot) small{padding-right:10px}
.chip small{font-size:9.5px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;color:var(--muted-2)}
.chip.on{
  background:linear-gradient(180deg, rgba(200,248,74,.16), rgba(200,248,74,.06));
  border-color:rgba(200,248,74,.45);color:var(--lime);
  box-shadow:0 6px 18px -8px rgba(200,248,74,.5);
}
.chip.on small{color:var(--lime-dim)}
.warn{margin-top:10px;font-size:11.5px;color:#ffd0a8;background:rgba(255,162,76,.1);border:1px solid rgba(255,162,76,.35);border-radius:10px;padding:9px 11px;display:none}

/* ===== rest timer: кольцо ===== */
.timerbar{
  margin:10px 20px 0;flex:0 0 auto;
  background:linear-gradient(120deg, rgba(79,224,166,.07), rgba(200,248,74,.04));
  border:1px solid var(--hair-2);
  border-radius:18px;padding:10px 12px;
  display:flex;align-items:center;gap:12px;
}
.timerbar.running{border-color:rgba(79,224,166,.35);background:linear-gradient(120deg, rgba(79,224,166,.12), rgba(200,248,74,.05))}
.ring{position:relative;width:52px;height:52px;flex:0 0 auto}
.ring svg{transform:rotate(-90deg);display:block}
.ring .track{stroke:rgba(255,255,255,.1)}
.ring .prog{stroke:var(--pine);stroke-linecap:round;transition:stroke-dashoffset .95s linear}
.ring .t{position:absolute;inset:0;display:grid;place-items:center;font-family:'Space Mono',monospace;font-size:12.5px;font-weight:700;color:var(--pine)}
.timer-mid{flex:1;min-width:0}
.tpresets{display:flex;gap:5px;flex-wrap:wrap;min-width:0}
.tpresets button{
  font-family:'Space Mono',monospace;font-size:10.5px;padding:5px 8px;
  border:1px solid var(--hair);border-radius:9px;background:var(--surface);
  color:var(--muted);cursor:pointer;flex:1;
  min-height:44px;display:flex;align-items:center;justify-content:center;
}
.tpresets button.active{background:rgba(79,224,166,.14);color:var(--pine);border-color:rgba(79,224,166,.4)}
/* В отсчёте прячем ВЕСЬ средний блок, а не только чипы: его flex:1-распорка
   иначе не дала бы «Стопу» растянуться на ряд. */
.timerbar.running .timer-mid{display:none}
.timerbar.running .t-stop{display:block}
.t-stop{
  display:none;
  padding:9px 16px;border-radius:12px;background:var(--surface-2);
  border:1px solid var(--hair-2);color:var(--text);font-weight:600;font-size:13px;
  cursor:pointer;white-space:nowrap;flex:1;min-height:40px;
}
.t-stop:active{transform:scale(.94)}
@media (prefers-reduced-motion: no-preference){
  .timerbar.flash{animation:timerFlash .65s ease}
}
@keyframes timerFlash{0%{background:rgba(255,162,76,.25);border-color:rgba(255,162,76,.6)}100%{background:linear-gradient(120deg, rgba(79,224,166,.07), rgba(200,248,74,.04))}}

/* ===== pager ===== */
.stage{flex:1 1 auto;position:relative;overflow:hidden;margin-top:10px;min-height:0}
/* нативный scroll-snap: жест ведёт браузер (родная инерция/резинка iOS),
   overscroll-x:contain не даёт жесту уйти в навигацию браузера */
.pager{
  display:flex;height:100%;
  overflow-x:auto;overflow-y:hidden;
  scroll-snap-type:x mandatory;
  overscroll-behavior-x:contain;
  scrollbar-width:none;
}
.pager::-webkit-scrollbar{display:none}
.slide{
  flex:0 0 100%;min-width:100%;padding:2px 20px 14px;
  overflow-y:auto;scrollbar-width:none;overscroll-behavior-y:contain;
  scroll-snap-align:start;scroll-snap-stop:always;
}
.slide::-webkit-scrollbar{display:none}

.card{
  background:var(--surface);border:1px solid var(--hair);
  border-radius:var(--radius);padding:18px;
  box-shadow:0 20px 40px -30px rgba(0,0,0,.8), inset 0 1px 0 rgba(255,255,255,.04);
}

/* ===== плитка «+»: завершающий слайд карусели ===== */
/* Тот же .slide-контейнер, что у карточек (родной snap), но пустой по смыслу —
   поэтому тянется на всю высоту и центрирует мишень. Пунктир = «этого нет в
   программе дня», в отличие от сплошной рамки карточки. */
.plus-slide{display:flex}
.plus-tile{
  flex:1 1 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  background:none;border:1px dashed var(--hair-2);border-radius:var(--radius);
  color:var(--muted);cursor:pointer;padding:24px;
  font-family:inherit;font-size:15px;font-weight:600;letter-spacing:-.2px;
  transition:border-color .25s, color .25s, background .25s;
}
.plus-tile:hover,.plus-tile:focus-visible{border-color:rgba(200,248,74,.45);color:var(--ink);background:rgba(200,248,74,.03)}
.plus-glyph{
  width:60px;height:60px;border-radius:50%;display:grid;place-items:center;
  border:1px solid var(--hair-2);color:var(--lime);
  font-size:32px;font-weight:300;line-height:1;padding-bottom:4px;
  transition:border-color .25s;
}
.plus-tile:hover .plus-glyph,.plus-tile:focus-visible .plus-glyph{border-color:rgba(200,248,74,.45)}
.plus-cap{text-align:center;line-height:1.5}


/* строки шторки «+»: как .variant-row, плюс группа мышц под названием */
.extra-list{margin-top:4px}
.extra-row .variant-row-main{flex-direction:column;align-items:flex-start;gap:2px}
.extra-row-tr{color:var(--muted);font-size:11.5px;font-weight:500}

.ex-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:2px}
.ex-name{display:flex;align-items:center;gap:2px;min-width:0}
/* v2-29 (R3): пилюля «✓ Сделано» — второй ребёнок .ex-head, space-between
   сам ставит её к правому краю без пересчёта раскладки. Пайн, НЕ лайм: лайм
   в проекте занят смыслом «здесь и сейчас» (.chip.on, точка «сегодня»),
   пайн — «подтверждено» (то же .hint.hold, кольцо таймера). Цвета/альфа —
   ровно .tpresets button.active (строка 155), тот же язык «активно/пайн». */
.done-pill{
  flex:0 0 auto;font-family:'Space Mono',monospace;font-size:10.5px;font-weight:700;
  color:var(--pine);background:rgba(79,224,166,.14);border:1px solid rgba(79,224,166,.4);
  border-radius:10px;padding:5px 9px;white-space:nowrap;line-height:1.3;
}
.pname{
  font-size:19px;font-weight:600;letter-spacing:-.3px;line-height:1.15;
  display:inline-flex;align-items:center;gap:7px;cursor:pointer;min-height:32px;
}
.pname:active{opacity:.6}
.pname .stat-ic{color:var(--lime-dim);display:inline-grid;place-items:center;flex:0 0 auto}
.infobtn{
  width:34px;height:34px;flex:0 0 auto;border-radius:50%;
  border:none;background:none;color:var(--muted);cursor:pointer;
  font-family:'Space Mono',monospace;font-size:12px;font-weight:700;
  display:grid;place-items:center;padding:0;
}
.infobtn::after{
  content:'i';width:19px;height:19px;border-radius:50%;
  border:1px solid var(--hair-2);display:grid;place-items:center;line-height:1;
}
.infobtn:hover::after,.infobtn:focus-visible::after{color:var(--lime);border-color:rgba(200,248,74,.5)}
/* чип варианта — отдельной строкой на всю ширину, название тренажёра
   ВСЕГДА полностью (переносится, не обрезается) — правка владельца */
.variant-trigger{
  width:100%;padding:8px 11px;border-radius:11px;margin:0 0 10px;
  background:var(--surface-2);border:1px solid var(--hair);
  font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;
  display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:36px;
}
.variant-trigger:active{transform:scale(.98)}
.variant-trigger-text{flex:1;min-width:0;white-space:normal;text-align:left;line-height:1.3}
.variant-trigger-arrow{flex:0 0 auto;opacity:.6;font-size:9px}
.ex-sub{font-family:'Space Mono',monospace;font-size:10px;color:var(--muted-2);margin:0 0 8px}
.ex-sub .pnum{color:var(--lime-dim);font-weight:700;margin-right:6px}

.lasttime{
  font-size:12.5px;color:var(--muted);font-family:'Space Mono',monospace;
  margin:2px 0 12px;letter-spacing:-.3px;cursor:pointer;
  display:flex;align-items:center;min-height:36px;
}
.lasttime:hover,.lasttime:focus-visible{color:var(--pine)}

/* прогрессия — hint-бар в языке концепта */
.hint{
  display:block;background:linear-gradient(90deg, rgba(255,255,255,.05), transparent);
  border-left:2px solid var(--hair-2);
  padding:9px 12px;border-radius:10px;margin-bottom:12px;font-size:13px;line-height:1.45;
  color:var(--muted);
}
.hint.up{
  background:linear-gradient(90deg, rgba(200,248,74,.12), transparent);
  border-left-color:var(--lime);color:var(--lime);font-weight:600;
}
.hint.hold{
  background:linear-gradient(90deg, rgba(79,224,166,.1), transparent);
  border-left-color:var(--pine);color:var(--pine);
}
.hint.fresh{border-left-color:var(--hair-2);color:var(--muted)}
.hint.stall{
  background:linear-gradient(90deg, rgba(255,162,76,.13), transparent);
  border-left-color:var(--ember);color:#ffd0a8;margin-top:-6px;
}
@media (prefers-reduced-motion: no-preference){
  .hint.up{animation:hintFadeIn .3s ease}
}
@keyframes hintFadeIn{from{opacity:0}to{opacity:1}}

/* вес + повторы: степперы */
.wblock{margin-bottom:4px}
.wblock label,.repshead{
  display:block;font-size:10px;text-transform:uppercase;letter-spacing:.7px;
  color:var(--muted-2);font-weight:600;margin-bottom:5px;
}
.repshead{margin-top:12px}
.stepper{
  display:flex;align-items:center;gap:6px;background:var(--surface-2);
  border:1px solid var(--hair);border-radius:12px;padding:4px;
}
.stepper button{
  width:38px;height:38px;flex:0 0 auto;border-radius:9px;border:none;
  background:transparent;color:var(--text);font-size:19px;font-weight:400;line-height:1;
  display:grid;place-items:center;cursor:pointer;
}
.stepper button:active{background:var(--hair-2);transform:scale(.9)}
.stepper input{
  flex:1;min-width:0;width:100%;text-align:center;border:none;background:transparent;
  font-family:'Space Mono',monospace;font-size:16px;font-weight:700;color:var(--text);
  padding:6px 2px;
  transition:transform .18s cubic-bezier(.34,1.6,.5,1),color .2s;
}
.stepper input:focus{outline:none;color:var(--lime)}
.stepper input.bump{transform:scale(1.28);color:var(--lime)}
.stepper input::placeholder{color:var(--muted-2)}
.wlabel{font-family:'Space Mono',monospace;font-size:10px;color:var(--muted);text-transform:none;letter-spacing:0}

.set{display:flex;align-items:center;gap:10px;padding:6px 0}
.set + .set{border-top:1px solid var(--hair)}
.set .n{width:20px;font-family:'Space Mono',monospace;font-size:13px;color:var(--muted-2);font-weight:700;flex:0 0 auto}
.set .stepper{flex:1;min-width:0}
.set-x{
  width:30px;height:30px;flex:0 0 auto;border-radius:8px;border:1px solid var(--hair);
  background:transparent;color:var(--muted-2);font-size:16px;display:grid;place-items:center;cursor:pointer;
}
.set-x:active{transform:scale(.9);color:var(--ember)}
.set-add{
  width:100%;margin-top:10px;padding:11px;border-radius:12px;border:1px dashed var(--hair-2);
  background:transparent;color:var(--muted);font-weight:600;font-size:13.5px;cursor:pointer;
}
.set-add:active{background:var(--surface-2);color:var(--text)}
.set-add:disabled{opacity:.35;cursor:default}

/* точки-пейджер */
/* flex-wrap: число точек больше не фиксировано (6 программных + сколько угодно
   добавленных, §1). Без переноса ряд молча выезжал за экран: flex-shrink сжимал
   content-box до 0, а background-clip:content-box → точки просто переставали
   рисоваться (с ~8 экстр), и крайние уезжали за оба края — а точки это
   единственный способ прыгнуть по слайдам без свайпа. Тот же приём, что уже
   применён к .tpresets выше. */
.dots{display:flex;flex-wrap:wrap;justify-content:center;gap:1px;padding:4px 0 calc(8px + env(safe-area-inset-bottom));flex:0 0 auto}
/* хит-таргет точки больше её визуала: padding + background-clip */
.dot{width:6px;height:6px;padding:9px;box-sizing:content-box;flex-shrink:0;border-radius:12px;background:rgba(255,255,255,.34);background-clip:content-box;cursor:pointer;transition:all .3s cubic-bezier(.34,1.4,.5,1)}
.dot.on{width:22px;background:var(--lime);background-clip:content-box;box-shadow:none}


/* ===== toast (plain / ember «Потолок взят» / hold «Держишь» / drop «Спад») ===== */
.toast{
  position:absolute;left:20px;right:20px;bottom:calc(56px + env(safe-area-inset-bottom));z-index:80;
  background:rgba(20,26,23,.92);border:1px solid var(--hair-2);color:#fff;
  padding:13px 16px;border-radius:16px;font-weight:600;font-size:14px;line-height:1.4;
  display:flex;align-items:center;gap:10px;backdrop-filter:blur(12px);
  transform:translateY(28px) scale(.96);opacity:0;pointer-events:none;cursor:pointer;
  box-shadow:0 16px 40px -14px rgba(0,0,0,.8);
}
@media (prefers-reduced-motion: no-preference){
  .toast{transition:all .5s cubic-bezier(.34,1.5,.5,1)}
}
.toast.show{transform:translateY(0) scale(1);opacity:1;pointer-events:auto}
/* тихий индикатор («✓ сохранено») не перехватывает тапы по контенту */
.toast.quiet{pointer-events:none!important}
.toast.ember{
  background:linear-gradient(120deg, rgba(255,162,76,.22), rgba(255,162,76,.08));
  border-color:rgba(255,162,76,.5);
  box-shadow:0 16px 40px -12px rgba(255,162,76,.5);
}
.toast .flame{filter:drop-shadow(0 0 6px rgba(255,162,76,.9));flex:0 0 auto}
.toast.hold{
  background:linear-gradient(120deg, rgba(79,224,166,.20), rgba(79,224,166,.06));
  border-color:rgba(79,224,166,.5);
  box-shadow:0 16px 40px -12px rgba(79,224,166,.42);
}
.toast.drop{
  background:linear-gradient(120deg, rgba(255,107,107,.20), rgba(255,107,107,.06));
  border-color:rgba(255,107,107,.5);
  box-shadow:0 16px 40px -12px rgba(255,107,107,.42);
}
.toast .glyph{flex:0 0 auto;font-size:19px;line-height:1;font-weight:700}
.toast.hold .glyph{color:var(--pine)}
.toast.drop .glyph{color:var(--rose)}

/* ===== bottom sheets ===== */
.sheet-backdrop{
  position:absolute;inset:0;background:rgba(0,0,0,.55);backdrop-filter:blur(3px);
  opacity:0;pointer-events:none;z-index:50;
}
@media (prefers-reduced-motion: no-preference){
  .sheet-backdrop{transition:opacity .4s}
}
.sheet-backdrop.show{opacity:1;pointer-events:auto}
.sheet{
  position:absolute;left:0;right:0;bottom:0;z-index:60;
  background:linear-gradient(180deg,#141a17,#0d120f);
  border-top:1px solid var(--hair-2);
  border-radius:28px 28px 0 0;
  padding:8px 20px calc(24px + env(safe-area-inset-bottom));
  transform:translateY(102%);
  max-height:88%;overflow-y:auto;scrollbar-width:none;
  box-shadow:0 -20px 50px -12px rgba(0,0,0,.7);
  pointer-events:none;
}
@media (prefers-reduced-motion: no-preference){
  .sheet{transition:transform .5s cubic-bezier(.32,1.15,.4,1)}
}
.sheet::-webkit-scrollbar{display:none}
.sheet.show{transform:translateY(0);pointer-events:auto}
.grab{width:42px;height:5px;border-radius:3px;background:var(--hair-2);margin:6px auto 14px;cursor:grab;touch-action:none}
.sheet-close{
  position:absolute;top:10px;right:12px;font-family:'Space Mono',monospace;font-size:14px;
  background:none;border:none;color:var(--muted);cursor:pointer;padding:12px;margin:-8px;
}
.sheet-title{font-size:19px;font-weight:600;letter-spacing:-.3px;margin:0 30px 2px 0}
.sheet .sub{font-size:13px;color:var(--muted);margin:2px 0 14px}

/* команды тренера */
.sheet-variant{padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--hair)}
.sheet-variant:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0}
.sheet-variant.alt{opacity:.55}
.sheet-alt-label{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted-2);margin:4px 0}
.sheet-variant-name{font-weight:600;font-size:14.5px;margin:6px 0}
.sheet-tech{font-size:13.5px;line-height:1.5;margin-bottom:8px;color:var(--text)}
.sheet-cues{list-style:none;margin:0 0 6px;padding:0;font-size:14px;line-height:1.45}
.sheet-cues li{position:relative;padding:9px 0 9px 18px;border-top:1px solid var(--hair)}
.sheet-cues li:first-child{border-top:none}
.sheet-cues li::before{
  content:'';position:absolute;left:2px;top:15px;width:6px;height:6px;border-radius:50%;
  background:var(--lime);box-shadow:0 0 6px rgba(200,248,74,.7);
}
.sheet-warn{
  position:relative;font-size:14px;line-height:1.45;font-weight:500;color:#ffd0a8;
  padding:9px 0 9px 18px;border-top:1px solid var(--hair);margin:0 0 6px;
}
.sheet-warn::before{
  content:'';position:absolute;left:2px;top:15px;width:6px;height:6px;border-radius:50%;
  background:var(--ember);box-shadow:0 0 6px rgba(255,162,76,.7);
}
.sheet-video{
  margin-top:12px;display:flex;align-items:center;gap:10px;padding:12px;border-radius:14px;
  background:rgba(255,60,60,.08);border:1px solid rgba(255,80,80,.25);
  font-weight:600;font-size:14px;color:var(--text);text-decoration:none;
}
.sheet-video .play{width:34px;height:34px;border-radius:10px;background:#ff3b3b;display:grid;place-items:center;flex:0 0 auto}
.sheet-empty{font-size:12.5px;color:var(--muted)}

/* статистика: график сверху фиксирован, история скроллится */
#statsSheet{max-height:88%;overflow:hidden;display:flex;flex-direction:column}
#statsSheet .sheet-body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.stats-fixed{flex:0 0 auto}
.stats-history{flex:1 1 auto;min-height:0;overflow-y:auto;margin-top:4px;scrollbar-width:none}
.stats-history::-webkit-scrollbar{display:none}

/* вкладки вариантов шторки статистики: смотровые, не выбирающие — карточку
   под шторкой не трогают (см. onStatsSheetClick). Геометрия одолжена у
   .variant-row (min-height 44px, полное имя переносится, счётчик в моноспейсе
   не сжимается), но классы свои: сходство с пикером вариантов здесь как раз
   то, чего мы избегаем (см. §2d брифа v2-18) — поэтому ни радио-кружка, ни
   общих правил .variant-row*, только заливка лаймом как у активного чипа дня. */
.stats-tabs{display:flex;flex-direction:column;margin:6px 0 2px}
.stats-tab{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:11px 12px;min-height:44px;border-radius:12px;margin-bottom:5px;
  border:1px solid var(--hair);background:var(--surface);cursor:pointer;
  font-family:inherit;font-size:14.5px;font-weight:500;text-align:left;
}
.stats-tab:last-child{margin-bottom:0}
.stats-tab-name{color:var(--text);white-space:normal;line-height:1.3;flex:1;min-width:0}
.stats-tab-count{flex:0 0 auto;font-size:11px;color:var(--muted-2);font-family:'Space Mono',monospace;white-space:nowrap}
.stats-tab.is-active{
  background:linear-gradient(180deg, rgba(200,248,74,.16), rgba(200,248,74,.06));
  border-color:rgba(200,248,74,.45);
  box-shadow:0 6px 18px -8px rgba(200,248,74,.5);
}
.stats-tab.is-active .stats-tab-name{color:var(--lime);font-weight:600}
.stats-tab.is-active .stats-tab-count{color:var(--lime-dim)}

.stats-graph{
  background:var(--surface);border:1px solid var(--hair);border-radius:18px;
  padding:12px 10px 8px;margin:4px 0 6px;
}
.stats-graph .gtitle{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:0 0 2px 4px}
.stats-graph .glegend{font-family:'Space Mono',monospace;font-size:9.5px;color:var(--muted-2);margin:0 0 6px 4px}
.stats-graph svg{width:100%;height:auto;display:block;overflow:visible;cursor:pointer}
.gv2-grid{stroke:var(--hair);stroke-width:1}
.gv2-axis{fill:var(--muted-2);font-size:9px;font-family:'Space Mono',monospace}
.gv2-area{opacity:0}
@media (prefers-reduced-motion: no-preference){
  .gv2-area{transition:opacity .8s ease .3s}
}
.gv2-area.in{opacity:1}
.gv2-line{
  fill:none;stroke:var(--lime);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;
  filter:drop-shadow(0 3px 8px rgba(200,248,74,.35));
}
.pt-dot{opacity:0}
@media (prefers-reduced-motion: no-preference){
  .pt-dot{transition:opacity .3s}
}
.pt-dot.in{opacity:1}

/* тултип точки графика (механика прода: fixed, координаты из rect тапнутого круга) */
.chart-tooltip{
  position:fixed;left:0;top:0;transform:translate(-50%,calc(-100% - 14px));
  background:#0a0d0b;border:1px solid var(--hair-2);color:var(--text);
  font-family:'Space Mono',monospace;font-size:11px;font-weight:700;line-height:1.3;
  padding:6px 10px;border-radius:8px;pointer-events:none;opacity:0;z-index:90;
  white-space:nowrap;max-width:80vw;overflow:hidden;text-overflow:ellipsis;
}
@media (prefers-reduced-motion: no-preference){
  .chart-tooltip{transition:opacity .15s ease}
}
.chart-tooltip.show{opacity:1}

/* история: «12,07  8-10, 8-10» + месяцы + dim чужого варианта */
.hist-row{display:flex;align-items:center;gap:8px;padding:9px 2px;border-top:1px solid var(--hair);font-size:13px}
.hist-text{flex:1;font-family:'Space Mono',monospace;letter-spacing:-.3px;color:var(--text);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* недостижимо из UI с v2-18: historyRowHtml теперь всегда получает
   variantLabel===null в проде (история шторки статистики скоупится на
   активную вкладку), класс .foreign больше не навешивается. Часть комплекта
   с variantLabel-веткой в historyRowHtml (app.js) и .hist-variant ниже —
   единый триггер удаления всех четырёх сразу описан в комментарии на
   historyRowHtml. */
.hist-row.foreign .hist-text{opacity:.4}
/* тег чужого варианта: полное название (правка владельца) — короткий
   остаётся в строке, длинный переносится вниз отдельной строкой */
/* то же самое, что .hist-row.foreign .hist-text выше — недостижимо с v2-18,
   часть того же комплекта (см. комментарий на historyRowHtml в app.js). */
.hist-variant{
  font-size:9px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted-2);
  border:1px solid var(--hair);padding:2px 6px;border-radius:6px;
  white-space:normal;line-height:1.35;order:5;
  width:max-content;max-width:100%;
}
.hist-row{flex-wrap:wrap}
.hist-row button{
  font-family:'Space Mono',monospace;font-size:12px;width:32px;height:32px;flex:0 0 auto;
  border:1px solid var(--hair);border-radius:8px;background:transparent;color:var(--muted);cursor:pointer;
  display:grid;place-items:center;
}
.hist-row button.hist-del{color:var(--ember);border-color:rgba(255,162,76,.3)}
.hist-month{
  font-size:10px;text-transform:uppercase;letter-spacing:1.5px;color:var(--muted-2);
  font-family:'Space Mono',monospace;font-weight:700;padding:14px 2px 4px;
}
/* v2-40 (R13) — заголовок дня в шторке «Добавить упражнение», взамен
   переиспользованного .hist-month (заголовки МЕСЯЦЕВ шторки истории, не
   заголовки ДНЕЙ). Мокап docs/r13-mockup.html, утверждён владельцем
   08.08.2026. Типографика — язык .day-eyebrow (styles.css:715): Space Mono
   10px, letter-spacing .08em, uppercase, color var(--lime-dim); жирность
   700 оставлена от .hist-month (не унаследована от day-eyebrow — на
   фоне-плашке тонкий текст теряется, проверено рендером). Фон-плашка — ТОТ
   ЖЕ градиент, что у самой .sheet (styles.css:391), не новый цвет: sticky-
   элемент обязан быть непрозрачным, иначе строки, проезжающие под ним при
   скролле, просвечивали бы сквозь заголовок. Линия снизу — rgba(200,248,
   74,.3), тот же диапазон альфы --lime, что уже в приложении (.mark 35%,
   .chip.on 45%, .progress-badge 22%). margin:0 -20px компенсирует padding
   самой .sheet (20px, styles.css:394) и тянет плашку в край-в-край ширину
   шторки.
   top:-9px, НЕ top:0 — фикс щели прилипания, найден на мокапе. У .sheet
   padding-top:8px + border-top:1px = 9px (styles.css:390-394). При top:0
   плашка прилипает на 9px ниже самого верха шторки, и строка, шедшая в
   потоке НАД заголовком, при прокрутке проезжает ровно через этот зазор и
   узкой полоской просвечивает НАД плашкой (проверено покадрово через
   elementFromPoint). top:-9px сдвигает точку прилипания к САМОМУ верху
   (0px), padding-top увеличен на те же 9px (11→20), чтобы текст внутри не
   сдвинулся — у плашки просто раньше начинается фон, закрывающий зазор
   изнутри. Не «упрощать» обратно на top:0. */
.extra-day-header{
  position:sticky;top:-9px;z-index:2;
  margin:0 -20px;padding:20px 20px 9px;
  background:linear-gradient(180deg,#141a17,#0d120f);
  border-bottom:1px solid rgba(200,248,74,.3);
  font-family:'Space Mono',monospace;font-size:10px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--lime-dim);
}
.hist-edit-form{display:flex;gap:6px;align-items:center;padding:10px 0;border-top:1px solid var(--hair);flex-wrap:wrap;margin-top:10px}
/* «правишь: X» — своя строка над инпутами формы правки, не сжимается в ряд */
.edit-variant-note{flex:0 0 100%;font-size:11px;color:var(--muted-2);font-family:'Space Mono',monospace}
/* §полка п.4: отказ сохранить пустой/нечисловой/минусовой вес — своя строка,
   янтарный стиль подсказок (как .pinerror/.warn), скрыта пока нет ошибки */
.edit-w-err{flex:0 0 100%;font-size:11.5px;color:#ffd0a8;background:rgba(255,162,76,.1);border:1px solid rgba(255,162,76,.35);border-radius:10px;padding:8px 10px;display:none}
.edit-w-err.is-shown{display:block}
.hist-edit-form input{
  font-family:'Space Mono',monospace;font-size:14px;text-align:center;padding:8px 3px;
  border:1px solid var(--hair-2);border-radius:9px;width:52px;background:var(--surface-2);color:var(--text);
}
.hist-edit-form input:focus{outline:none;border-color:var(--lime)}
.hist-edit-form button{
  font-family:'Space Grotesk','Inter',sans-serif;font-size:12px;font-weight:600;padding:9px 12px;
  border:none;border-radius:9px;background:var(--lime);color:#0c1206;cursor:pointer;
}
.hist-edit-form button.cancel{background:transparent;color:var(--muted);border:1px solid var(--hair-2)}

/* пикер вариантов */
.variant-radiogroup{display:flex;flex-direction:column}
.variant-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:15px 4px;min-height:44px;border-top:1px solid var(--hair);cursor:pointer;font-size:15px;font-weight:500}
.variant-row:first-child{border-top:none}
.variant-row-main{display:flex;align-items:center;gap:12px;min-width:0;flex:1}
.variant-row-check{
  width:22px;height:22px;flex:0 0 auto;border-radius:50%;border:2px solid var(--hair-2);
  display:grid;place-items:center;font-size:12px;color:#0c1206;font-weight:700;
}
.variant-row.selected .variant-row-check{border-color:var(--lime);background:var(--lime)}
/* полное название варианта и в пикере — переносим, не обрезаем */
.variant-row-name{color:var(--text);white-space:normal;line-height:1.3;min-width:0}
.variant-row.selected .variant-row-name{color:var(--lime);font-weight:600}
.variant-row-hint{flex:0 0 auto;font-size:11px;color:var(--muted-2);font-family:'Space Mono',monospace;white-space:nowrap}

/* ===== PIN gate ===== */
.pingate{
  position:absolute;inset:0;z-index:100;overflow-y:auto;
  background:
    radial-gradient(120% 60% at 50% -8%, #14201b 0%, transparent 55%),
    linear-gradient(180deg, var(--ink) 0%, var(--ink2) 100%);
  display:flex;align-items:center;justify-content:center;padding:24px;
}
.pin-inner{width:100%;max-width:320px;text-align:center}
.pin-mark{
  width:44px;height:44px;border-radius:14px;margin:0 auto 16px;
  display:grid;place-items:center;
  background:radial-gradient(circle at 50% 30%, rgba(200,248,74,.25), transparent 70%), #10160f;
  border:1px solid rgba(200,248,74,.35);
}
.pingate h1{font-size:26px;font-weight:700;letter-spacing:-.5px;margin-bottom:6px}
.pin-sub{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:20px}
#pininput{
  width:100%;font-family:'Space Mono',monospace;font-size:28px;letter-spacing:.3em;text-align:center;
  padding:14px;border:1px solid var(--hair-2);border-radius:16px;
  background:var(--surface-2);color:var(--text);
}
#pininput:focus{outline:none;border-color:rgba(200,248,74,.6)}
button.pinsubmit{
  width:100%;margin-top:12px;font-family:'Space Grotesk','Inter',sans-serif;font-weight:700;font-size:15px;
  color:#0c1206;background:linear-gradient(180deg,#d3ff54,#a9dd35);border:none;border-radius:16px;
  padding:14px;cursor:pointer;box-shadow:0 12px 28px -10px rgba(200,248,74,.5);
}
.pinerror{margin-top:12px;font-size:12.5px;color:#ffd0a8;background:rgba(255,162,76,.1);border:1px solid rgba(255,162,76,.35);border-radius:10px;padding:8px 10px;display:none}
.pinerror.show{display:block}

/* ===== v2-19 календарь занятий ===== */
/* Первая сетка в проекте — до неё вся раскладка была на flex. Колонки строго
   1fr, без фиксированных ширин: .phone{overflow:clip} обрезал бы переполнение
   МОЛЧА, без скролла и без единой ошибки, поэтому ширину клетки задаёт
   контейнер, а не содержимое. На 360px это ~42px на клетку, на 390px ~46px. */
.cal-nav{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:12px 0 8px}
.cal-month{flex:1;text-align:center;font-size:15px;font-weight:600;color:var(--text);text-transform:capitalize}
.cal-arrow{
  flex:0 0 auto;width:36px;height:36px;border-radius:12px;
  background:var(--surface);border:1px solid var(--hair);
  color:var(--muted);font-family:inherit;font-size:17px;line-height:1;cursor:pointer;
  display:grid;place-items:center;-webkit-appearance:none;appearance:none;
}
.cal-arrow:hover,.cal-arrow:focus-visible{border-color:rgba(200,248,74,.45);color:var(--lime)}
.cal-week,.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.cal-wd{
  text-align:center;font-family:'Space Mono',monospace;font-size:9.5px;
  letter-spacing:.04em;color:var(--muted-2);padding-bottom:2px;
}
.cal-cell{
  aspect-ratio:1;display:grid;place-items:center;
  border-radius:10px;border:1px solid transparent;
  font-family:'Space Mono',monospace;font-size:13px;color:var(--muted);
}
/* Занятый день одет как активный чип дня (.chip.on выше) — тот же градиент,
   бордер и тень. В этом приложении такая заливка уже означает «здесь есть я»,
   и заводить под календарь второй визуальный язык было бы враньём. */
.cal-cell.has-session{
  background:linear-gradient(180deg, rgba(200,248,74,.16), rgba(200,248,74,.06));
  border-color:rgba(200,248,74,.45);color:var(--lime);font-weight:700;
  box-shadow:0 6px 18px -8px rgba(200,248,74,.5);
}
/* v2-32 (R4): даты с занятием стали <button> (было <div> у всех клеток без
   исключения) — appearance/cursor снимают нативный вид кнопки, тем же
   приёмом, что .cal-arrow чуть выше. Фон/рамка/цвет уже объявлены полным
   shorthand правилом над этим — UA-стиль кнопки их не перебивает (author CSS
   всегда выше по приоритету происхождения), трогать незачем. */
.cal-cell.has-session{-webkit-appearance:none;appearance:none;cursor:pointer}
/* «Сегодня» — тонкая обводка ПОВЕРХ подсветки: серая на пустом дне, лаймовая
   на занятом. Два класса весят больше одного, поэтому порядок правил здесь
   ничего не решает — специфичность делает это сама. */
.cal-cell.is-today{border-color:var(--muted)}
.cal-cell.has-session.is-today{border-color:var(--lime)}
.cal-foot{
  margin-top:14px;text-align:center;font-family:'Space Mono',monospace;
  font-size:11px;color:var(--muted-2);
}

/* шторка «День» (v2-32, R4) — список упражнений даты, в фактическом порядке.
   Строки одолжены у .hist-row/.pname/.ex-sub (см. app.js daySheetRowHtml) —
   своя только колонка времени. У самой шторки-контейнера — СВОЙ вид (фон/
   рамка/тень ниже, .day-eyebrow) — это утверждённый владельцем «второй
   визуальный слой» мокапа (вариант Б, r4-mockup.html:78–90), а не второй
   язык карточек. Стек «кто открыт поверх кого» держит порядок в DOM (см.
   index.html), не размер.
   ---
   ПИК (край шторки календаря виден над «Днём») — координатор поднял на
   ревью, что прежняя версия этого комментария («пик = разница капов
   88%−77%») была домыслом, не замером, и оказалась неверна. Обе шторки —
   .sheet{position:absolute;bottom:0}, поэтому top = phoneBottom − height и
   пик = top(День) − top(календарь) = height(календарь) − height(День)
   РОВНО. Высота календаря почти всегда держится КОНТЕНТОМ (сетка месяца —
   423–485px по факту на двух проверенных viewport, число строк недели
   зависит только от месяца), а не капом 88% — до него она не дотягивает
   никогда на разумных высотах экрана. Замер headless Chromium на живой
   истории (15 занятых дат × 2 viewport = 30 точек, 02.08.2026) БЕЗ пары
   правил ниже даёт пик отрицательным на всех 30: от −41.7 до −215.7px.
   Процентный кап у одного «Дня» это не чинит в принципе — он не делает
   шторку ниже соседа, если сосед сам ниже своего капа.
   Чинится ПАРОЙ id-переопределений, обе — проценты от .phone (тот же приём
   и та же причина «откуда отзывчивость», что у .sheet{max-height:88%} чуть
   выше и .phone{height:100dvh} на мобильном, строка 64): #calendarSheet
   поднят min-height'ом выше обычного контента, #daySheet ограничен
   max-height ниже этого пола. Раз пол календаря СТРОГО выше потолка «Дня»
   на 6 процентных пунктов (68−62), пик ≥ phoneH×0.06 ГАРАНТИРОВАН при любой
   высоте экрана и любом числе упражнений — это свойство box-модели
   (min-height/max-height раздвигают контентную высоту в нужную сторону), а
   не подгонка под две проверенные точки.
   Числа — РОВНО из утверждённого мокапа (кадры Б2/Б3, телефон 740):
   календарь 520px = 70%, «День» 438px = 59%, пик 82px = 11% высоты экрана.
   Промежуточная версия 68/62 (пик 6%) давала на строку списка больше и была
   отвергнута на ревью: при пике 6% заголовок «Календарь» (26.6px) виден
   полосой в 16.6px — слово разрезано по глифам, тогда как мокап показывает
   грабер, ✕ и полный заголовок. Пик существует ради ответа «где я»; пик,
   режущий слово пополам, этой работы не делает. Размен «одна строка списка
   против читаемого края» решён в пользу мокапа, который владелец утвердил.
   Раздвинуть #calendarSheetBody флексом и прижать .cal-foot к низу
   (margin-top:auto) — тоже пробовалось и ОТКЛОНЕНО: на границе, где
   min-height чуть ниже контента 6-строчного месяца (375×667, август),
   связка flex-shrink+min-height:0 сжимала тело шторки на несколько px НИЖЕ
   контента (замечено замером, не гипотеза) — по цифрам не страшно, но
   непредсказуемо и не проверено на WebKit/iOS, реальной платформе
   владельца. Пустое место остаётся там, где его сажает обычный block-flow —
   после последнего ребёнка (.cal-foot), перед padding-bottom; на скриншоте
   это не выглядит сломанным (см. отчёт), просто просторная карточка.
   Приглушение (`opacity`) базы под пиком РАССМАТРИВАЛОСЬ и было снято по
   ревью координатора: в утверждённом мокапе .mock-sheet под «Днём» (кадры
   Б2/Б3) рисуется в полную непрозрачность, opacity там не встречается вовсе
   — разделение слоёв там и здесь держит .sheet-backdrop (уже есть, не
   трогали), не альфа-канал самой шторки-базы. Не заводить снова «для
   наглядности» без нового утверждения владельца. */
#calendarSheet{min-height:70%}
#daySheet{
  max-height:59%;
  background:linear-gradient(180deg,#171f1a,#0e1310);
  border-top:1px solid rgba(200,248,74,.18);
  border-radius:30px 30px 0 0;
  box-shadow:0 -26px 60px -12px rgba(0,0,0,.85);
}
.day-eyebrow{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--lime-dim);margin:4px 0}
/* v2-38 (R9): пометка «цель/застой» слева у строки — утверждённый мокап
   docs/r9-mockup.html, вариант В. position:relative + padding-left:10px
   (было 2px, те же +8px, что в мокапе) стоят на БАЗОВОМ .day-row, а не на
   отдельном модификаторе: в проде, в отличие от мокапа (который рисует
   несколько демо-вариантов на одной странице), у пометки один живой путь
   рендера, и КАЖДАЯ строка обязана резервировать место под полосу — иначе
   непомеченные соседи «прыгали» бы на 8px левее помеченных.
   .day-row-nums{margin:2px 0 0 46px} ниже НЕ трогается — 46px остаётся
   константой, растёт только padding-left самого .day-row. Офсет текста от
   левого края строки ПОЭТОМУ ИЗМЕНИЛСЯ (измерено рендером, 390px:
   .day-row-name/.day-row-nums 48px→56px, ширина .day-row-name 300px→292px)
   — верно другое: они остаются выровнены ДРУГ С ДРУГОМ, как и раньше (было
   48=48, стало 56=56), потому что оба зависят от одного и того же
   padding-left. */
.day-row{position:relative;padding:9px 2px 9px 10px;border-top:1px solid var(--hair)}
.day-row:first-child{border-top:none}
/* Полоса — span, не border-left (проще мерить getBoundingClientRect напрямую,
   без getComputedStyle(el,'::before')). Инсет 3px сверху/снизу — измерено
   рендером в мокапе (getBoundingClientRect, таблица подбора зазора): даёт
   видимый зазор 7px между соседними полосами и длину полосы 87.7% высоты
   строки; меньший зазор не разделяет два подряд идущих одноцветных блока
   (проверено рендером на паре записей одного цвета). Прозрачный фон по
   умолчанию — цвет красят только .row-goal/.row-stall ниже, у непомеченной
   строки полоса невидима, но место под неё зарезервировано паддингом
   .day-row выше. */
.day-row-bar{position:absolute;left:0;top:3px;bottom:3px;width:2px;border-radius:1px;background:transparent}
.day-row.row-goal .day-row-bar{background:var(--lime)}
.day-row.row-stall .day-row-bar{background:var(--ember)}
/* v2-48 (R18, владелец, docs/r18-mockup.html): третье состояние строки —
   спад относительно прошлого занятия. --rose уже в палитре с v2-44 (окно
   «Спад»), новый токен не заводим. */
.day-row.row-drop .day-row-bar{background:var(--rose)}
.day-row-top{display:flex;align-items:baseline;gap:8px}
.day-row-time{flex:0 0 auto;width:38px;font-family:'Space Mono',monospace;font-size:11px;color:var(--muted-2)}
.day-row-name{flex:1;min-width:0;font-size:14px;font-weight:600;color:var(--text);line-height:1.3}
.day-row-nums{margin:2px 0 0 46px;font-family:'Space Mono',monospace;font-size:12.5px;color:var(--muted)}
.day-row-nums b{color:var(--lime-dim);font-weight:700}
/* v2-48 (R18): хвост «· было …» у строк со спадом — серее основного текста,
   var(--muted-2), тот же токен, что у .day-row-time. class="was" — из
   утверждённого мокапа docs/r18-mockup.html, не заведён заново. */
.day-row-nums .was{color:var(--muted-2)}
.day-empty{font-size:12.5px;color:var(--muted)}

/* utility */
.hidden{display:none !important}
body.sheet-open{}
@media (prefers-reduced-motion: reduce){ *{transition:none!important;animation:none!important} }

/* PIN-гейт vs приложение (pre-paint скрипт в index.html) */
html.no-token #app{display:none}
html.has-token #pingate{display:none}
