:root {
  --bg: #0c0c0e;
  --surface: #18181c;
  --elevated: #1f1f24;
  --hover: #26262b;
  --text: #f0f0f2;
  --muted: #8b8b95;
  --dim: #6e6e78;
  --accent: #63bda4;
  --accent-active: #52ad94;
  --accent-soft: rgba(99, 189, 164, 0.16);
  --green: #34c07a;
  --red: #f0554b;
  --red-soft: rgba(240, 85, 75, 0.15);
  --border: #2c2c32;
  --line-strong: #3a3a42;
  --bar-bg: rgba(12, 12, 14, 0.92);
  /* матовое стекло плавающей панели: полупрозрачный surface, под ним размытие */
  --glass: rgba(24, 24, 28, 0.72);
  --glass-edge: rgba(255, 255, 255, 0.08);
  --backdrop: rgba(0, 0, 0, 0.55);
  --shadow: rgba(0, 0, 0, 0.45);
  --on-accent: #fff;
  --radius: 12px;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* Тема идёт за системной настройкой телефона */
@media (prefers-color-scheme: light) {
  :root {
    --bg: #f6f6f7;
    --surface: #ffffff;
    --elevated: #f0f0f2;
    --hover: #e8e8ec;
    --text: #17171a;
    --muted: #5b5b65;
    --dim: #8a8a94;
    --accent: #3a9a7f;
    --accent-active: #2f8a70;
    --accent-soft: rgba(58, 154, 127, 0.12);
    --green: #1f9d5f;
    --red: #d93a30;
    --red-soft: rgba(217, 58, 48, 0.10);
    --border: #e3e3e7;
    --line-strong: #cfcfd6;
    --bar-bg: rgba(246, 246, 247, 0.92);
    --glass: rgba(255, 255, 255, 0.72);
    --glass-edge: rgba(0, 0, 0, 0.06);
    --backdrop: rgba(20, 20, 30, 0.35);
    --shadow: rgba(20, 20, 30, 0.18);
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }

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

/* В standalone-PWA зону под «домашней полосой» (safe-area) рисует именно html.
   Без фона там айфон подсвечивает серым — в обычном браузере этого не видно. */
html { background: var(--bg); }
/* экран при потягивании оттягиваем сами (см. pull в app.js) — родная резинка только мешает */
html { overscroll-behavior-y: none; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;
  font-size: 15px;
  min-height: 100vh;
  overscroll-behavior-y: none;
}

/* Шапка */
.topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: calc(52px + var(--safe-top));
  padding: var(--safe-top) 16px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--bar-bg);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 150ms ease-out;
  z-index: 20;
}

.topbar.scrolled { border-bottom-color: var(--border); }

.topbar-title { font-size: 17px; font-weight: 650; letter-spacing: -0.2px; opacity: 0; transition: opacity 150ms ease-out; }
.topbar.scrolled .topbar-title { opacity: 1; }

.screen-title { margin: 2px 3px 12px; font-size: 30px; font-weight: 700; letter-spacing: -0.7px; }
.screen-sub { margin: -8px 4px 14px; font-size: 13px; color: var(--dim); }

.topbar-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border: none;
  border-radius: 9px;
  background: var(--elevated);
  color: var(--muted);
}

.topbar-btn:active { background: var(--hover); }
.topbar-btn [data-icon] { font-size: 18px; }
.topbar { gap: 8px; }
.topbar-title { flex: 1; }
.topbar-btn.spinning svg { animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Экраны */
.screens {
  position: relative;
  padding: calc(60px + var(--safe-top)) 0 calc(78px + var(--safe-bottom));
}

.screen { display: none; padding: 0 14px; }
.screen[data-screen="notes"] { padding-bottom: 60px; position: relative; }

/* Невидимые полосы-тумблеры под списком при нулевой прокрутке: перетаскивание тумблера пальцем
   даёт системный тик без проверки жеста — так потягивание получает отклик (см. lockOverlay) */
.lock-overlay { position: absolute; left: 0; top: calc(60px + var(--safe-top)); width: 100%; pointer-events: none; z-index: 2; }
.lock-overlay.on { pointer-events: auto; }
.lock-overlay input {
  position: absolute; left: 0; width: 40px; height: 328px; margin: 0; opacity: 0.0001;
  writing-mode: vertical-lr; transform-origin: 0 0;
}
.screen.active { display: block; }

.search-row { margin-bottom: 10px; }
/* поиск проектов — та же таблетка, что поиск заметок */
.search-row input[type="search"] { height: 44px; padding: 0 18px; border-radius: 22px; }

input[type="search"], input[type="text"], select {
  width: 100%;
  padding: 11px 13px;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 10px;
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  outline: none;
  -webkit-appearance: none;
}

input:focus, select:focus { border-color: var(--accent); }

/* Чипсы */
.chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 12px;
  scrollbar-width: none;
}

.chips::-webkit-scrollbar { display: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  padding: 7px 13px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  font-family: inherit;
  font-size: 13px;
}

.chip span { font-size: 11px; opacity: 0.7; }
.chip.active { background: var(--accent); color: var(--on-accent); }
.chip.active span { opacity: 0.75; }

/* Списки */
.list { display: flex; flex-direction: column; gap: 8px; }

/* Проекты — как иконки приложений на домашнем экране */
.apps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px 8px;
  padding: 6px 4px 10px;
}

.app-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 0;
  border: none;
  background: none;
  font-family: inherit;
  color: var(--text);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.app-shell { position: relative; }

/* буква вместо иконки — текст, и iOS при долгом нажатии тянется его выделить */
.app-icon, .app-name, .peek-tile, .peek-tile * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.app-icon img { pointer-events: none; }

.app-icon {
  width: 60px; height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 15px;
  overflow: hidden;
  font-size: 25px;
  font-weight: 700;
  color: var(--on-accent);
  box-shadow: 0 2px 8px var(--shadow);
}

.app-icon img { width: 100%; height: 100%; object-fit: cover; }

/* счётчик открытых задач — как значок непрочитанного на иконке */
.app-badge {
  position: absolute;
  top: -5px; right: -5px;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
}

.app-name {
  max-width: 78px;
  font-size: 11px;
  line-height: 1.25;
  text-align: center;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  word-break: break-word;
}

.app-tile:active .app-icon { transform: scale(0.94); }
.app-icon { transition: transform 150ms ease-out; }

/* Меню по долгому нажатию. Нативное меню айфона из веба недоступно — повторяем вид:
   размытый фон, поднятая плитка и панель действий. */
.peek { position: fixed; inset: 0; z-index: 50; }

.peek-bg {
  position: absolute;
  inset: 0;
  background: var(--backdrop);
  backdrop-filter: blur(22px);
  opacity: 0;
  transition: opacity 180ms ease-out;
}

.peek.open .peek-bg { opacity: 1; }

.peek-tile {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  color: var(--text);
  transform: scale(0.94);
  opacity: 0;
  transition: transform 180ms ease-out, opacity 180ms ease-out;
}

.peek.open .peek-tile { transform: scale(1.06); opacity: 1; }

.peek-menu {
  position: absolute;
  width: 232px;
  padding: 5px;
  border-radius: 15px;
  background: var(--elevated);
  box-shadow: 0 18px 40px var(--shadow);
  transform: scale(0.92);
  opacity: 0;
  transform-origin: top center;
  transition: transform 180ms ease-out, opacity 180ms ease-out;
}

.peek.open .peek-menu { transform: scale(1); opacity: 1; }

.peek-menu button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 12px 13px;
  border: none;
  border-radius: 11px;
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  text-align: left;
}

.peek-menu button + button { box-shadow: inset 0 1px 0 var(--border); }
.peek-menu button:active { background: var(--hover); }
.peek-menu button svg { width: 19px; height: 19px; flex-shrink: 0; color: var(--muted); }

.card {
  padding: 13px 14px;
  background: var(--surface);
  border-radius: var(--radius);
}

/* Группа: подряд идущие строки — один скруглённый блок без рамок,
   разделитель начинается от текста, а не от края (как в списках айфона). */
.group {
  background: var(--surface);
  border-radius: 14px;
  overflow: hidden;
}

.group > * {
  background: transparent;
  border-radius: 0;
}

.group > * + * { position: relative; }

.group > * + *::before {
  content: '';
  position: absolute;
  top: 0; left: 14px; right: 14px;
  height: 1px;
  background: var(--border);
}

.card-head { display: flex; align-items: center; gap: 10px; }

.avatar {
  width: 30px; height: 30px;
  border-radius: 8px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--on-accent);
}

.card-titles { flex: 1; min-width: 0; }

.card-name {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-sub {
  margin-top: 2px;
  font-size: 12px;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

/* Claude одинаковой ширины на всех карточках, сколько бы соседей ни было */
.card-extra {
  display: flex;
  gap: 8px;
  margin-left: auto;
}

.btn {
  padding: 9px 12px;
  border: none;
  border-radius: 9px;
  background: var(--elevated);
  color: var(--text);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
}

.btn:active { background: var(--hover); }

.btn-run {
  flex: 0 0 45%;
  min-width: 118px;
  background: var(--accent);
  color: var(--on-accent);
}

.btn-run:active { background: var(--accent-active); }

.btn-narrow {
  flex: 0 0 auto;
  min-width: 62px;
  padding: 9px 14px;
  color: var(--muted);
  text-align: center;
  text-decoration: none;
}

.badge {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  background: var(--elevated);
  color: var(--muted);
}

.badge-active { background: var(--accent-soft); color: var(--accent); }
.badge-alert { background: var(--red-soft); color: var(--red); }

/* Задачи */
.group-title {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin: 22px 4px 8px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.3px;
  color: var(--text);
}

.group-title span { font-size: 13px; font-weight: 400; color: var(--dim); }

/* просрочку помечаем счётчиком, а не целым заголовком: красный не должен быть самым громким на экране */
.group-title.alert span { color: var(--red); }
.group-title:first-child { margin-top: 2px; }

.task {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 13px 14px;
  background: var(--surface);
  border-radius: var(--radius);
}

.check {
  width: 21px; height: 21px;
  flex-shrink: 0;
  margin-top: 1px;
  border: 1.6px solid var(--line-strong);
  border-radius: 50%;
  background: transparent;
}

.task.done .check { position: relative; background: var(--green); border-color: var(--green); }
.task.done .check::after {
  content: '';
  position: absolute;
  left: 6px; top: 2.5px;
  width: 5px; height: 10px;
  border: solid var(--on-accent);
  border-width: 0 1.8px 1.8px 0;
  transform: rotate(45deg);
}
.task-body { flex: 1; min-width: 0; }
.task-title { font-size: 14.5px; line-height: 1.35; }
.task.done .task-title { color: var(--dim); text-decoration: line-through; }

/* выполненные свёрнуты до строки и приглушены */
/* Прозрачность вешаем на содержимое, а не на саму строку: строка перекрывает
   кнопки свайпа, и полупрозрачная просвечивала бы их насквозь. */
.task.done { padding: 10px 14px; }
.task.done > * { opacity: 0.55; }
.task.done .task-title { font-size: 14px; }
.task.done .task-meta { margin-top: 2px; }
.group-title span { margin-left: 6px; letter-spacing: 0; opacity: 0.7; }
.more-row { display: flex; gap: 20px; padding: 0 4px 6px; }
.more-btn { border: none; background: transparent; padding: 6px 0; font-size: 13.5px; color: var(--accent); }
.more-btn.more-collapse { color: var(--dim); }
.empty.empty-short { padding: 32px 20px 10px; }

.task-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--dim);
}

.task.overdue .task-due { color: var(--red); }
.task-flag { color: var(--red); }

.empty {
  padding: 60px 20px;
  text-align: center;
  color: var(--dim);
  font-size: 14px;
}

/* Нижняя навигация */
.tabbar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  display: flex;
  padding-bottom: var(--safe-bottom);
  background: var(--bar-bg);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--border);
  z-index: 20;
}

.tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 9px 0 10px;
  border: none;
  background: transparent;
  color: var(--dim);
  font-family: inherit;
  font-size: 10.5px;
}

.tab.active { color: var(--accent); }
.tab span { position: relative; }

.tab-badge {
  position: absolute;
  top: -3px; right: -17px;
  min-width: 15px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--red);
  color: var(--on-accent);
  font-size: 9.5px;
  font-style: normal;
  line-height: 15px;
  text-align: center;
}

/* Кнопка добавления */
.fab {
  position: fixed;
  right: 18px;
  bottom: calc(84px + var(--safe-bottom));
  width: 52px; height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: 0 8px 22px var(--shadow);
  z-index: 15;
}

.fab [data-icon] { font-size: 26px; }
.fab:active { transform: scale(0.94); }

/* Форма */
.sheet-backdrop {
  position: fixed;
  inset: 0;
  background: var(--backdrop);
  z-index: 30;
}

.sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 31;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-radius: 18px 18px 0 0;
  border-top: 1px solid var(--border);
  animation: rise 220ms ease-out;
  /* сам блок тянется до физического низа (фон закрывает системную зону),
     а отступ под «домашнюю полосу» живёт внутри прокрутки — см. .sheet-body */
  padding-bottom: 0;
}

/* В standalone-PWA fixed-элемент упирается в линию safe-area, а не в физический низ экрана,
   и под шторкой проглядывает затемнитель — снизу видна серая полоса. Заполняем эту зону
   фоном шторки: псевдоэлемент уходит ниже её края (если шторка и так внизу — он за экраном). */
.sheet::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  height: 80px;
  background: var(--bg);
  pointer-events: none;
}

@keyframes rise { from { transform: translateY(100%); } to { transform: translateY(0); } }

.sheet-handle {
  width: 38px; height: 4px;
  margin: 0 auto 8px;
  border-radius: 2px;
  background: var(--line-strong);
}

.sheet-tabs { display: flex; gap: 6px; }

.sheet-tab {
  flex: 1;
  padding: 8px;
  border: none;
  border-radius: 9px;
  background: var(--elevated);
  color: var(--muted);
  font-family: inherit;
  font-size: 13.5px;
}

.sheet-tab.active { background: var(--accent-soft); color: var(--accent); }

.quick-dates { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; }
.quick-dates::-webkit-scrollbar { display: none; }

.quick-dates button {
  flex-shrink: 0;
  padding: 7px 12px;
  border: none;
  border-radius: 999px;
  background: var(--elevated);
  color: var(--muted);
  font-family: inherit;
  font-size: 12.5px;
}

.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 2px;
  font-size: 14px;
  color: var(--muted);
}

.switch-row input { width: 51px; height: 31px; accent-color: var(--accent); }

.primary {
  padding: 13px;
  border: none;
  border-radius: 11px;
  background: var(--accent);
  color: var(--on-accent);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
}

.primary:active { background: var(--accent-active); }

/* Уведомление */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(96px + var(--safe-bottom));
  transform: translateX(-50%);
  max-width: 90vw;
  padding: 11px 18px;
  border-radius: 11px;
  background: var(--elevated);
  color: var(--text);
  font-size: 13.5px;
  text-align: center;
  z-index: 40;
  animation: pop 180ms ease-out;
}

@keyframes pop { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* Экран входа */
.login {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--bg);
}

.login-box {
  width: 100%;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: center;
}

.login-logo { color: var(--accent); display: flex; justify-content: center; }

.login-box h1 {
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -0.3px;
}

.login-hint {
  margin-bottom: 6px;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--muted);
}

#login-code {
  text-align: center;
  font-size: 21px;
  letter-spacing: 5px;
  padding: 14px;
  font-variant-numeric: tabular-nums;
}

#login-code::placeholder { letter-spacing: 5px; color: var(--line-strong); }

.login-scan {
  padding: 11px;
  border: none;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.14);
  color: var(--muted);
  font-family: inherit;
  font-size: 13.5px;
}

.login-scan:active { background: var(--elevated); }

.login-note {
  font-size: 12px;
  line-height: 1.45;
  color: var(--dim);
}

.login-note.error { color: var(--red); }

/* невидимое поле для клавиатуры: в видимой области, иначе iOS прокрутит к нему */
.kb-warm {
  position: fixed; left: 0; bottom: 0; width: 1px; height: 1px;
  opacity: 0; border: 0; padding: 0; pointer-events: none; font-size: 16px;
}

/* защищённая заметка: вместо текста замок и поле PIN */
.note-locked {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 24px; color: var(--dim); font-size: 14px;
}
.note-locked [data-icon] { font-size: 30px; }
.note-card-title [data-icon] { font-size: 12px; margin-right: 5px; color: var(--muted); vertical-align: -1px; }
#n-lock.is-on { color: var(--accent); }

/* экран PIN-кода: преграда на весь экран, выезжает снизу, своя цифровая клавиатура */
html { background: var(--bg); }
.pin-screen {
  position: fixed; inset: 0; z-index: 80;
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--text);
  padding: calc(8px + env(safe-area-inset-top)) 16px calc(24px + env(safe-area-inset-bottom));
  transform: translateY(100%);
  transition: transform 320ms cubic-bezier(0.32, 0.72, 0, 1);
}
.pin-screen.open { transform: translateY(0); }
.pin-top { display: flex; justify-content: flex-end; }
.pin-body { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; }
.pin-lock { font-size: 34px; color: var(--muted); }
.pin-title { font-size: 20px; font-weight: 600; }
.pin-hint { font-size: 13.5px; color: var(--dim); text-align: center; min-height: 1.3em; max-width: 280px; line-height: 1.4; }
.pin-dots { display: flex; gap: 14px; margin-top: 10px; }
.pin-dot { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--line-strong); transition: background 120ms, border-color 120ms; }
.pin-dot.on { background: var(--accent); border-color: var(--accent); }
.pin-dots.shake { animation: pinShake 0.4s ease; }
@keyframes pinShake { 20%, 60% { transform: translateX(-8px); } 40%, 80% { transform: translateX(8px); } }
.pin-pad {
  display: grid; grid-template-columns: repeat(3, 76px); gap: 14px 22px;
  justify-content: center; padding-top: 18px;
}
.pin-pad button {
  width: 76px; height: 76px; border-radius: 50%;
  font: inherit; font-size: 28px; font-weight: 500;
  background: var(--elevated); color: var(--text); border: none;
  display: flex; align-items: center; justify-content: center;
}
.pin-pad button:active { background: var(--line-strong); }
.pin-pad .pin-ok, .pin-pad .pin-del { background: transparent; }
.pin-pad .pin-ok { color: var(--accent); visibility: hidden; }
.pin-pad .pin-ok.is-visible { visibility: visible; }
.pin-pad .pin-del [data-icon] { font-size: 26px; }
.pin-pad .pin-ok [data-icon] { font-size: 28px; }
.note-locked-open {
  font: inherit; font-size: 15px; padding: 10px 22px; border-radius: 12px; border: none;
  background: var(--accent); color: #fff;
}

/* экран загрузки: тот же BMO, что на входе, но маленький и по центру */
.boot {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background: #63bda4;
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.boot.hidden { opacity: 0; transform: scale(1.04); pointer-events: none; }
.boot-face { width: 118px; height: auto; display: block; filter: drop-shadow(0 10px 22px rgba(8, 39, 41, 0.16)); }
.boot-face .bmo-eye { transform-box: fill-box; transform-origin: center; animation: bootBlink 4.2s ease-in-out infinite; }
.boot-fill { transition: width 0.4s ease; }
.boot-author {
  position: absolute; left: 0; right: 0;
  bottom: calc(28px + env(safe-area-inset-bottom));
  text-align: center; font-size: 12px; letter-spacing: 0.4px;
  color: rgba(8, 39, 41, 0.6);
}
@keyframes bootBlink { 0%, 92%, 100% { transform: scaleY(1); } 95% { transform: scaleY(0.1); } }

.install-steps {
  margin: 0; padding-left: 22px;
  text-align: left; font-size: 15px; line-height: 1.5;
  display: flex; flex-direction: column; gap: 8px;
}

.scanner {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 6px;
}

.scanner video {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 14px;
  background: #000;
}

/* Календарь */
.cal-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 2px 0 10px;
}

.cal-month-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 18px;
  font-weight: 650;
  letter-spacing: -0.2px;
}

.cal-month-btn svg { color: var(--dim); transition: transform 150ms ease-out; }
.cal-month-btn.collapsed svg { transform: rotate(-90deg); }

.cal-top-actions { display: flex; gap: 4px; align-items: center; }

.cal-icon-btn {
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  border: none;
  border-radius: 8px;
  background: var(--elevated);
  color: var(--muted);
  font-family: inherit;
  font-size: 18px;
  line-height: 1;
}

.cal-today-btn { font-size: 12.5px; padding: 0 11px; }
.cal-icon-btn:active { background: var(--hover); }

.cal-month {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  padding-bottom: 10px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

.cal-month.collapsed { display: none; }

.cal-wd {
  text-align: center;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--dim);
  padding-bottom: 4px;
}

.cal-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 3px 0 4px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  font-family: inherit;
}

.cal-day span {
  width: 30px;
  height: 30px;
  line-height: 30px;
  border-radius: 50%;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.cal-day.other { color: var(--dim); opacity: 0.55; }
.cal-day.today span { color: var(--accent); font-weight: 700; }
.cal-day.selected span { background: var(--accent); color: var(--on-accent); font-weight: 600; }

.cal-day em {
  display: flex;
  gap: 2px;
  height: 5px;
}

.cal-day em i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--dim);
}

.cat-work { --cat: var(--accent); }
.cat-call { --cat: #e0a33e; }
.cat-personal { --cat: var(--green); }
.cat-other { --cat: var(--dim); }
.cat-task { --cat: var(--muted); }
.cal-day em i { background: var(--cat, var(--dim)); }

/* Лента дней */
.cal-agenda { display: flex; flex-direction: column; gap: 4px; }

.agenda-day {
  display: flex;
  gap: 10px;
  padding: 8px 0;
  scroll-margin-top: calc(60px + var(--safe-top));
}

.agenda-date {
  width: 44px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding-top: 4px;
}

.agenda-date b {
  width: 30px;
  height: 30px;
  line-height: 30px;
  text-align: center;
  border-radius: 50%;
  font-size: 16px;
  font-weight: 600;
}

.agenda-date span { font-size: 10.5px; text-transform: uppercase; color: var(--dim); }
.agenda-date.today b { background: var(--accent); color: var(--on-accent); }
/* выбранный день отмечаем цветом, а не второй окружностью — она наезжала на день недели */
.agenda-day.selected .agenda-date:not(.today) b { color: var(--accent); }
.agenda-day.selected .agenda-date span { color: var(--accent); font-weight: 600; }

.agenda-items {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.agenda-item {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "time title" "time sub";
  column-gap: 12px;
  align-items: center;
  width: 100%;
  padding: 10px 12px 10px 10px;
  border: none;
  border-left: 4px solid var(--cat, var(--dim));
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  text-align: left;
}

.agenda-item:active { background: var(--elevated); }
.agenda-item.done { opacity: 0.5; }
.agenda-item.done .agenda-title { text-decoration: line-through; }
.agenda-item.overdue { border-left-color: var(--red); }

.agenda-time {
  grid-area: time;
  font-size: 11.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 46px;
}

.agenda-title {
  grid-area: title;
  font-size: 14.5px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.agenda-sub {
  grid-area: sub;
  font-size: 11.5px;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.agenda-sub:empty { display: none; }

.agenda-empty {
  width: 100%;
  padding: 10px 12px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: transparent;
  color: var(--dim);
  font-family: inherit;
  font-size: 13px;
  text-align: left;
}

/* Панель подробностей */

.sheet-kind {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--dim);
}

.f-row { display: flex; gap: 8px; }

.f-field {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11.5px;
  color: var(--dim);
}

.f-field input, .f-field select { padding: 9px 10px; font-size: 14px; }

input[type="date"], input[type="time"] {
  width: 100%;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 10px;
  color: var(--text);
  font-family: inherit;
  outline: none;
  -webkit-appearance: none;
  min-height: 42px;
}

textarea {
  width: 100%;
  padding: 11px 13px;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 10px;
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  outline: none;
  resize: none;
}

textarea:focus { border-color: var(--accent); }

/* Заметки растут под свой текст, после лимита прокручиваются внутри поля.
   flex-shrink: 0 — иначе flex-колонка .sheet-body сжимает textarea до min-height. */
#f-notes { max-height: 45vh; flex-shrink: 0; }

/* Заголовок растёт под текст до четырёх строк, дальше прокручивается внутри поля */
#f-title {
  padding: 12px 14px;
  background: var(--surface);
  border: none; border-radius: 14px;
  font-size: 18px; font-weight: 650; line-height: 1.3;
  min-height: 48px; max-height: calc(4 * 1.3em + 24px);
  overflow-y: auto; resize: none; flex-shrink: 0;
}

.task-notes {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--muted);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.sheet-actions { display: flex; gap: 8px; margin-top: 4px; }
.sheet-actions .primary { flex: 1; }

.ghost {
  padding: 13px 14px;
  border: none;
  border-radius: 11px;
  background: var(--elevated);
  color: var(--muted);
  font-family: inherit;
  font-size: 14px;
}

.ghost:active { background: var(--elevated); }
#f-delete:active { color: var(--red); }

.btn-wide { flex: 1 1 auto; }

/* Иконки из библиотеки: размер задаётся здесь, цвет — currentColor */
[data-icon] { display: inline-flex; align-items: center; justify-content: center; line-height: 0; }
[data-icon] svg { width: 1em; height: 1em; }
.tab [data-icon] { font-size: 22px; }
.btn [data-icon] { font-size: 16px; }
.btn-run [data-icon] { font-size: 14px; }
.cal-icon-btn [data-icon] { font-size: 18px; }
.cal-month-btn [data-icon] { font-size: 16px; color: var(--dim); transition: transform 150ms ease-out; }
.cal-month-btn.collapsed [data-icon] { transform: rotate(-90deg); }

.btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; white-space: nowrap; }
.btn-icon-only { min-width: 44px; padding: 9px 0; }

/* Обновление потягиванием вниз */
/* Индикатор потягивания: замок заметок и стрелка обновления — без кружка, цветом текста,
   у самого верха поверх шапки; в покое спрятан за Dynamic Island (остров кончается на ~11px
   выше safe-area, поле рисунка 40px — safe-top − 54). Без выреза это просто выше кромки экрана */
.ptr {
  position: fixed;
  top: 0; left: 50%; z-index: 50;
  width: 57px; height: 40px; margin-left: -28px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text);
  transform: translateY(calc(var(--safe-top) - 54px));
  opacity: 0;
  transition: transform 260ms ease-in, opacity 200ms ease-out;
  pointer-events: none;
}
.ptr.pulling { transition: none; }
.ptr.ready { color: var(--accent); }
/* Круг стрелки не в центре её рамки: слева торчит наконечник, и рисунок «шире» круга —
   в viewBox круг стоит на 12.5 при рамке 12, отражение переносит его на 11.5. Крутить надо
   вокруг круга (11.5 / 24 ширины), иначе он ходит по окружности 1.25px — стрелка пьяная. */
.ptr [data-icon] { font-size: 30px; transform-origin: 47.917% 50%; }
.ptr [data-icon] svg { transform: scaleX(-1); }   /* стрелка по часовой — как и её вращение */
.ptr .ptr-lock { display: none; }
.ptr.reveal [data-icon] { display: none; }
.ptr.reveal .ptr-lock { display: block; width: 57px; height: 40px; overflow: visible; }
/* обновление: стрелка резко встаёт под остров и крутится, пока идёт загрузка, потом уезжает обратно */
.ptr.loading { transform: translateY(calc(var(--safe-top) + 6px)) !important; opacity: 1 !important; transition: transform 150ms ease-out; }
.ptr.loading [data-icon] { animation: ptr-spin 0.7s linear infinite; }
/* Крутим с угла, на который стрелку довернул палец: у общего spin нет `from`, и он брал
   inline-поворот — каждый круг шёл только до 360° и дёргался обратно */
@keyframes ptr-spin {
  from { transform: rotate(var(--angle, 0deg)); }
  to { transform: rotate(calc(var(--angle, 0deg) + 360deg)); }
}
.ptr.done { transform: translateY(calc(var(--safe-top) + 6px)) scale(1.1) !important; opacity: 1 !important; transition: transform 160ms ease-out; }

/* защищённые заметки въезжают и сворачиваются анимацией настоящей высоты (см. toggleLockedNotes) */
.locked-group { display: flex; flex-direction: column; gap: 8px; overflow: hidden; }

/* Этапы проекта */
.cat-milestone { --cat: var(--accent); }
.agenda-item.cat-milestone { background: transparent; box-shadow: inset 3px 0 0 var(--accent); }
.task-stage::before { content: '\25C6 '; font-size: 8px; color: var(--accent); }

/* Офлайн: только просмотр */
.offline-pill {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--elevated);
  color: var(--muted);
  font-size: 11px;
}

.offline-bar {
  position: fixed;
  top: calc(52px + var(--safe-top));
  left: 0; right: 0;
  z-index: 18;
  padding: 7px 14px;
  background: var(--elevated);
  color: var(--muted);
  font-size: 12px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

body.offline .screens { padding-top: calc(92px + var(--safe-top)); }
body.offline .btn-run, body.offline .btn-narrow, body.offline .fab, body.offline .check,
body.offline .agenda-empty { opacity: 0.4; pointer-events: none; }
body.offline .task .check { border-style: dashed; }
.sheet.readonly input, .sheet.readonly select, .sheet.readonly textarea { pointer-events: none; opacity: 0.7; }
.sheet.readonly .sheet-actions, .sheet.readonly #f-check-add, .sheet.readonly .quick-dates { display: none; }

/* Чек-лист */
.f-checklist { display: flex; flex-direction: column; gap: 6px; }
.f-check-head { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--dim); }
.f-check-list { list-style: none; display: flex; flex-direction: column; }

.f-check-item {
  display: grid;
  grid-template-columns: 22px 1fr 28px;
  align-items: center;
  gap: 10px;
  padding: 2px 14px;
  border-top: 1px solid var(--border);
}
.f-check-list .f-check-item:first-child { border-top: none; }

.f-check-item input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--green); margin: 0; }
.f-check-item input[type="text"] { padding: 8px 10px; font-size: 14px; }
.f-check-item.done input[type="text"] { color: var(--dim); text-decoration: line-through; }

.f-check-remove {
  border: none;
  background: transparent;
  color: var(--dim);
  font-size: 20px;
  line-height: 1;
}

#f-check-add { font-size: 14px; border-top: 1px solid var(--border); border-radius: 0; }

.task-steps { display: inline-flex; align-items: center; gap: 6px; font-variant-numeric: tabular-nums; }
.task-steps i { width: 32px; height: 4px; border-radius: 2px; background: var(--elevated); position: relative; overflow: hidden; }
.task-steps i::after { content: ''; position: absolute; inset: 0; width: var(--p, 0%); background: var(--accent); }
.task-steps.complete { color: var(--green); }
.task-steps.complete i::after { background: var(--green); }

/* Шторка: шапка с действиями, тело прокручивается само */
/* Фон под шторкой запираем не на body: position:fixed на нём схлопывает вьюпорт iOS
   на высоту статус-бара (852 -> 793) и обрезает всё, что ниже, — снизу оставалась
   полоса голого фона. Запираем сам .app-root, body остаётся обычным. */
body.sheet-open .app-root {
  position: fixed;
  left: 0; right: 0;
  overflow: hidden;
}

/* Пока открыта шторка, нижняя навигация и «плюс» не нужны. Прячем их: у таб-бара
   backdrop-filter, из-за которого на WebKit его полупрозрачная плашка всплывала поверх
   нижней части шторки и перекрывала поле комментария и кнопки. */
body.sheet-open .tabbar,
body.sheet-open .notes-bar,
body.sheet-open .fab { display: none; }

.sheet-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 10px 8px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  border-radius: 18px 18px 0 0;
  flex-shrink: 0;
}

.sheet-head .sheet-tabs { flex: 1; }
.sheet-head .sheet-kind { flex: 1; text-align: center; }
.sheet-head-actions { display: flex; align-items: center; gap: 2px; margin-left: auto; }

.sheet-icon {
  width: 38px; height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
}

.sheet-icon [data-icon] { font-size: 20px; }
.sheet-icon:active { background: var(--elevated); }
.sheet-icon.is-done { color: var(--green); }
.sheet-icon-danger:active { color: var(--red); }

.sheet-save {
  margin-left: 2px;
  border: none;
  background: transparent;
  color: var(--accent);
}

.sheet-save:active { background: var(--accent-soft); }

.sheet-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* «Домашняя полоса» перекрывает низ, а env(safe-area-inset-bottom) в этом PWA
     отдаёт 0 — поэтому минимум задаём числом, как у обычных экранов с таббаром */
  /* снизу запас: последнее поле не должно упираться в край шторки и «домашнюю полосу» */
  padding: 12px 12px calc(56px + var(--safe-bottom));
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* поля собраны в группы поверх фона страницы — иначе всё сливается в белое полотно */
  background: var(--bg);
}

/* Группа полей: одна карточка, строки внутри разделены волосяной линией.
   flex-shrink: 0 — иначе колонка .sheet-body сжимает карточки, когда форма длиннее экрана */
.f-group { background: var(--surface); border-radius: 14px; flex-shrink: 0; }
.f-line {
  display: flex; align-items: center; gap: 12px;
  min-height: 46px; padding: 6px 14px;
  border-top: 1px solid var(--border);
  font-size: 11.5px; color: var(--dim);
}
.f-group > .f-line:first-child { border-top: none; }
.f-key { flex: 0 0 auto; font-size: 14.5px; color: var(--muted); }
/* значение прижато вправо, поле без своей рамки — рамка тут одна, у группы */
.f-line input, .f-line select {
  margin-left: auto; width: auto; max-width: 62%;
  min-height: 34px; padding: 0; border: none; background: transparent;
  color: var(--text); font-family: inherit; font-size: 15px; text-align: right;
}
.f-line select { direction: rtl; }          /* стрелка селекта слева от значения */
.f-line select option { direction: ltr; }
.f-line input[type="date"], .f-line input[type="time"] { border-radius: 0; }
.f-line.switch-row { padding: 4px 14px; }
.f-line.switch-row { min-height: 52px; }
.f-line.switch-row input { max-width: none; width: 51px; height: 31px; margin-left: auto; flex-shrink: 0; }
.f-line-chips { padding: 8px 8px 10px; }
.f-line-chips .quick-dates { width: 100%; }

/* Подпись группы — внутри неё, а не над: так видно, к чему относится */
.f-cap {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 44px; padding: 12px 14px 8px;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.4px; text-transform: uppercase;
  color: var(--dim);
}
.f-notes-group textarea, .f-checklist #f-check-add, .f-files .file-strip {
  background: transparent; border: none;
}
.f-notes-group textarea { padding: 2px 14px 12px; min-height: 76px; }
.f-checklist #f-check-add { padding: 8px 14px 12px; min-height: 0; }
.f-files .file-strip { padding: 4px 14px 12px; }

.sheet.readonly .sheet-head-actions { display: none; }

/* Свайп шторки: ручка сверху как подсказка, что её можно утянуть вниз */
.sheet-head::before {
  content: '';
  position: absolute;
  top: 6px; left: 50%;
  width: 36px; height: 4px;
  margin-left: -18px;
  border-radius: 2px;
  background: var(--line-strong);
}
.sheet-head { position: relative; padding-top: 16px; touch-action: pan-y; }
.sheet { will-change: transform; }

/* заметки */
.note-card {
  display: block; width: 100%; text-align: left; font-family: inherit; color: var(--text);
  background: transparent; border: none; border-radius: 0;
  padding: 12px 15px;
}

/* Действия по свайпу: строка едет влево, из-под неё показываются кнопки */
.swipe { position: relative; overflow: hidden; }

.swipe-actions {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 176px;            /* покой: по 88px на кнопку — хватает самой длинной подписи */
  display: flex;
  overflow: hidden;
  transition: width 200ms ease-out;
}

.swipe.dragging .swipe-actions { transition: none; }

/* делят открывшуюся полосу поровну: 86px — их размер в покое */
.swipe-act {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border: none;
  background: var(--elevated);
  color: var(--text);
}

.swipe-act svg { width: 21px; height: 21px; flex-shrink: 0; }
.note-swipe .swipe-actions { width: 232px; }   /* четыре кнопки по 58px */
.note-swipe.locked .swipe-actions { width: 174px; }   /* у защищённой нет «Закрепить» */
.swipe-act.is-on { color: var(--accent); }

.swipe-act.danger { background: var(--red); color: #fff; }

.swipe .swipe-body {
  position: relative;
  background: var(--surface);
  border-radius: 0;          /* скруглённые углы не закрывали бы полосу с кнопками */
  transition: transform 200ms ease-out;
}

.swipe.dragging .swipe-body { transition: none; }

/* Строка свайпа непрозрачна и перекрывает разделитель родителя, поэтому линию
   несёт она сама — заодно линия уезжает вместе со строкой, как в iOS. */
.group > * + .swipe::before { display: none; }

.group > * + .swipe .swipe-body::before {
  content: '';
  position: absolute;
  top: 0; left: 14px; right: 14px;
  height: 1px;
  background: var(--border);
}
.note-card:active { background: var(--hover); }
.note-card-title { font-size: 16px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note-card-sub { margin-top: 3px; font-size: 13px; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note-card-when { color: var(--muted); }

/* заметка — отдельный экран, iOS push (предыдущий уезжает влево с затемнением).
   Двигаем каждый элемент экрана по отдельности, а НЕ общий контейнер: если наложить
   transform на контейнер, его fixed-дети (топбар, нижняя панель) начинают считать низ
   от контейнера, а не от экрана, и панель прыгает вверх при открытии. */
.app-root > * { transition: transform 500ms cubic-bezier(0.32, 0.72, 0, 1); }
/* экран звонка лежит поверх всего и под сдвиг страниц не попадает: принятый из журнала
   уведомлений звонок иначе рисуется сдвинутым на пятую часть экрана */
.app-root.pushed > *:not(.call) { transform: translateX(-22%); }
.app-root.dragging > * { transition: none; }
.app-root > .fab { transition: transform 500ms cubic-bezier(0.32, 0.72, 0, 1), opacity 180ms ease; }
.app-root.pushed > .fab { opacity: 0; }
.app-root::after {
  content: ''; position: fixed; inset: 0; z-index: 34;
  background: #000; opacity: 0; pointer-events: none;
  transition: opacity 500ms cubic-bezier(0.32, 0.72, 0, 1);
}
.app-root.pushed::after { opacity: 0.18; }

.note-page {
  position: fixed; inset: 0; z-index: 40;
  display: flex; flex-direction: column;
  background: var(--bg);
  transform: translateX(calc(100% + 44px));
  transition: transform 500ms cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3);
}
.note-page.open { transform: translateX(0); }
.note-page.dragging { transition: none; }

/* три колонки: «Назад» слева, заголовок строго по центру, действия справа — где чего нет,
   колонка просто пустая, и центр не съезжает */
.note-nav {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  padding: calc(var(--safe-top) + 8px) 8px 8px;
}
.note-nav > :first-child { grid-column: 1; justify-self: start; }
.note-nav-title { grid-column: 2; min-width: 0; max-width: 60vw; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note-nav-actions, .note-nav > :last-child:not(:first-child):not(.note-nav-title) { grid-column: 3; justify-self: end; }
.note-back {
  display: inline-flex; align-items: center; gap: 1px;
  background: none; border: none; color: var(--accent);
  font-family: inherit; font-size: 16px; padding: 4px 4px 4px 2px;
}
.note-back [data-icon] { font-size: 24px; }
.note-nav-actions { display: flex; gap: 2px; }
.note-nav-btn {
  width: 40px; height: 40px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--text);
}
.note-nav-btn [data-icon] { font-size: 20px; }
.note-nav-btn:active { background: var(--elevated); }
.note-nav-btn.danger:active { color: var(--red); }
.note-nav-btn.is-pinned { color: var(--accent); }
.pin-svg { width: 20px; height: 20px; }

.note-page-body {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* у края текста жест не уходит в резинку документа */
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px 18px 0;
}
/* снизу всегда запас в экран, как в заметках iPhone: последнюю строку можно поднять хоть к
   самому верху. Отдельным блоком, а не отступом: отступ у прокручиваемой flex-колонки Safari
   считает от конца блока текста, а не от его содержимого, и последние абзацы накрывались */
.note-page-body::after { content: ''; flex: 0 0 100vh; }
/* дата и заголовок не сжимаются: когда тело и запас перестали ужиматься, всё сжатие
   колонки досталось им, и заголовок схлопнулся в ноль */
.note-page-body > .note-date, .note-page-body > #n-title { flex-shrink: 0; }
.note-date { text-align: center; font-size: 13px; color: var(--dim); }
#n-title {
  border: none; background: none; padding: 0; font-family: inherit;
  font-size: 23px; font-weight: 600; line-height: 1.25; color: var(--text);
  outline: none; resize: none; overflow: hidden;
}
#n-title::placeholder { color: var(--dim); }
#n-body {
  position: relative;
  /* высота по тексту: с flex: 1 блок не рос при переполнении, и текст вытекал за него */
  flex: 0 0 auto; min-height: 50vh; padding: 0;
  font-family: inherit; font-size: 16.5px; line-height: 1.55; color: var(--text);
  outline: none;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Текст храним построчно: строка, начатая с «# », показывается как заголовок раздела */
.note-line { min-height: 1.55em; }

.note-line.note-h {
  font-size: 20px;
  font-weight: 650;
  line-height: 1.3;
  margin: 16px 0 4px;
}

.note-line.note-h:first-child { margin-top: 0; }

/* второй уровень: подзаголовок */
.note-line.note-h2 {
  font-size: 17px;
  font-weight: 650;
  line-height: 1.35;
  margin: 12px 0 2px;
  color: var(--muted);
}

/* Маркеры разметки живут в тексте, но не показываются: заголовок просто крупный,
   пункт списка — кружок. Span не редактируется, поэтому курсор в него не заходит. */
.note-line.note-check { padding-left: 29px; position: relative; }

.note-line.note-check::before {
  content: '';
  position: absolute;
  left: 0; top: 3px;
  width: 19px; height: 19px;
  border: 1.6px solid var(--line-strong);
  border-radius: 50%;
}

.note-line.note-check.done::before { background: var(--accent); border-color: var(--accent); }

/* галочка — тот же вектор, что иконка check из библиотеки, по центру того же кружка */
.note-line.note-check.done::after {
  content: '';
  position: absolute;
  left: 0; top: 3px;
  width: 19px; height: 19px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22.3 7.7 12 18.7 6.3 12.6'/%3E%3C/svg%3E") center / 13px 13px no-repeat;
}

.note-line.note-check.done { color: var(--dim); }

/* Панель форматирования — над клавиатурой */
/* Панель лежит вне слоя заметки: при открытой клавиатуре тот перестаёт быть
   фиксированным и уезжает вместе с документом, утаскивая панель за собой. */
.fmt-bar {
  position: absolute;
  left: 10px; right: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  touch-action: pan-x;     /* вертикальный свайп панель игнорирует, кнопки листаются вбок */
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px;
  border-radius: 22px;
  background: var(--elevated);
  box-shadow: 0 8px 24px var(--shadow);
  z-index: 44;
}

.fmt-bar::-webkit-scrollbar { display: none; }

.fmt-btn {
  flex: 0 0 44px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 17px;
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
}

.fmt-btn [data-icon] { font-size: 19px; }
.fmt-btn:active { background: var(--hover); }
.fmt-btn.on { background: var(--accent-soft); color: var(--accent); }
.fmt-done { color: var(--accent); }
.fmt-btn.fx { font-size: 17px; }
.fmt-head { font-size: 17px; font-weight: 700; }
.fx-italic { font-style: italic; font-family: Georgia, serif; }
.fx-under { text-decoration: underline; }
.fx-strike { text-decoration: line-through; }

/* сами начертания в тексте */
.fx-b { font-weight: 700; }
.fx-i { font-style: italic; }
.fx-u { text-decoration: underline; }
.fx-s { text-decoration: line-through; }
.note-link { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; word-break: break-all; }
.fx-c {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 0.9em;
  background: var(--elevated); padding: 1px 5px; border-radius: 5px;
}
.fx-h { border-radius: 3px; padding: 0 1px; }
.fx-h1 { background: rgba(255, 214, 92, 0.42); }
.fx-h2 { background: rgba(120, 220, 160, 0.38); }
.fx-h3 { background: rgba(130, 190, 255, 0.38); }
.fx-h4 { background: rgba(255, 150, 190, 0.36); }

/* палитра выделения */
.hl-palette {
  position: absolute;
  display: flex;
  gap: 8px;
  padding: 8px;
  border-radius: 16px;
  background: var(--elevated);
  box-shadow: 0 10px 26px var(--shadow);
  z-index: 45;
}

.hl-palette button {
  width: 30px; height: 30px;
  border: none;
  border-radius: 50%;
}

.hl-palette [data-tint="1"] { background: rgba(255, 214, 92, 0.9); }
.hl-palette [data-tint="2"] { background: rgba(120, 220, 160, 0.9); }
.hl-palette [data-tint="3"] { background: rgba(130, 190, 255, 0.9); }
.hl-palette [data-tint="4"] { background: rgba(255, 150, 190, 0.9); }

/* Ссылка — нижняя шторка. Позицию задаёт JS: при открытой клавиатуре
   position: fixed на iOS не держится, см. запись 4 в справочнике заметок. */
.link-sheet {
  position: absolute;
  left: 0; right: 0;
  z-index: 46;
  padding: 8px 16px 18px;
  border-radius: 18px 18px 0 0;
  background: var(--surface);
  box-shadow: 0 -12px 34px var(--shadow);
  flex-direction: column;
  gap: 14px;
  /* Закрытая шторка должна исчезать совсем. Раньше её прятал translateY(110%), но
     проценты тут считаются от высоты самого элемента, а не от экрана: невысокая шторка
     уезжала лишь на свою высоту от места в потоке и торчала на коротких страницах. */
  display: none;
}

.link-sheet.open { display: flex; animation: rise 220ms ease-out; }

/* Затемнитель тоже absolute, а не fixed: при открытой клавиатуре iOS fixed не держится,
   поэтому его границы каждый раз считает JS по visualViewport. */
.link-backdrop {
  position: absolute;
  left: 0; right: 0;
  z-index: 45;
  background: var(--backdrop);
}

.link-grip {
  width: 36px; height: 4px;
  margin: 0 auto 2px;
  border-radius: 2px;
  background: var(--line-strong);
}

.link-head { display: flex; align-items: center; gap: 8px; }
.link-head .note-nav-title { flex: 1; text-align: center; }
.link-field { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; color: var(--dim); }
.link-field input { font-size: 16px; }

/* подсказка лежит поверх первой строки, а не перед ней — иначе каретка вставала строкой ниже */
#n-body:has(> .note-line:only-child:empty)::before {
  content: attr(data-placeholder);
  color: var(--dim);
  position: absolute; top: 0; left: 0;
  pointer-events: none;
}

.note-local { margin-left: 6px; font-size: 11px; color: var(--accent); }

/* предложение включить уведомления — один раз, над списком задач */
.push-banner {
  margin: 2px 0 14px; padding: 12px 14px;
  border: 1px solid var(--line-strong); border-radius: 12px;
  display: flex; flex-direction: column; gap: 10px;
}
.push-text { display: flex; flex-direction: column; gap: 3px; font-size: 13px; color: var(--muted); }
.push-text b { font-size: 14.5px; color: var(--text); font-weight: 600; }
.push-actions { display: flex; justify-content: flex-end; gap: 8px; }
.push-actions button {
  font: inherit; font-size: 13.5px; padding: 7px 14px;
  border-radius: 9px; border: 1px solid var(--line-strong);
  background: none; color: var(--text);
}
.push-actions .push-on { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Схема проекта — только просмотр: снимок редактора, который можно тянуть и приближать */
.canvas-page {
  position: fixed; inset: 0; z-index: 40;
  display: flex; flex-direction: column;
  background: var(--bg);
  transform: translateX(calc(100% + 44px));
  transition: transform 500ms cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3);
}

.canvas-page.open { transform: translateX(0); }

.canvas-view {
  flex: 1;
  position: relative;
  overflow: hidden;
  background: #fff;
  touch-action: none;             /* жесты забираем себе: пинч, перетаскивание, двойной тап */
}

/* ширину stage задаёт зум; во время жеста поверх — transform, при отпускании он снимается */
.canvas-stage { width: 100%; transform-origin: 0 0; }
.canvas-stage svg { display: block; width: 100%; height: auto; }

.canvas-page .note-nav { position: relative; }
.canvas-nav-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  max-width: 60%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.canvas-view .empty { color: var(--dim); }

/* Просмотр файла конфигурации — тот же выезжающий экран, что и заметка */
.doc-page {
  position: fixed; inset: 0; z-index: 40;
  display: flex; flex-direction: column;
  background: var(--bg);
  transform: translateX(calc(100% + 44px));
  transition: transform 500ms cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3);
}

.doc-page.open { transform: translateX(0); }

.doc-body {
  flex: 1;
  overflow: auto;
  margin: 0;
  padding: 4px 16px 24px;
  font: 12.5px/1.5 ui-monospace, Menlo, monospace;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}

/* Уведомления: журнал пушей */
.alerts-badge {
  position: absolute; top: -4px; right: -4px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px;
  background: var(--accent); color: var(--on-accent);
  font-size: 10px; font-weight: 600; line-height: 16px; text-align: center;
}
/* Переписка: новое внизу, пузыри слева, между днями — плашка с датой */
.alerts-list {
  flex: 1; overflow: auto; -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column; gap: 8px;
  padding: 8px 14px calc(20px + var(--safe-bottom));
}
.alerts-day {
  align-self: center; margin: 10px 0 2px; padding: 3px 11px;
  border-radius: 11px; background: var(--elevated);
  font-size: 11.5px; font-weight: 600; color: var(--dim);
}
.alerts-unread {
  display: flex; align-items: center; gap: 10px; margin: 6px 0 2px;
  font-size: 11.5px; font-weight: 600; color: var(--accent);
}
.alerts-unread::before, .alerts-unread::after { content: ''; flex: 1; height: 1px; background: var(--accent-soft); }
.alert { display: flex; align-items: flex-end; gap: 8px; }
/* аватарка отправителя: круг с иконкой типа или иконка проекта */
.alert-avatar {
  flex: 0 0 30px; width: 30px; height: 30px; border-radius: 50%; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--elevated); color: var(--muted);
}
.alert-avatar img { width: 100%; height: 100%; object-fit: cover; }
/* иконка проекта — со скруглением, как плитка в списке проектов */
.alert-avatar.project { border-radius: 8px; background: transparent; }
.alert-avatar [data-icon] { font-size: 16px; }
.alert-bubble {
  max-width: 82%; min-width: 0;
  padding: 7px 11px 6px; border-radius: 16px 16px 16px 5px;
  background: var(--surface);
}
.alert-from { font-size: 12.5px; font-weight: 650; color: var(--accent); }
.alert-title { font-size: 15px; font-weight: 600; line-height: 1.3; }
.alert-body { margin-top: 2px; font-size: 14.5px; line-height: 1.38; color: var(--muted); white-space: pre-line; word-break: break-word; }
.alert-body b { color: var(--text); font-weight: 650; }
.alert-body code, .alert-title code {
  padding: 1px 5px; border-radius: 5px; background: var(--hover);
  font-family: ui-monospace, Menlo, monospace; font-size: 0.9em;
}
.alert-tag { color: var(--accent); }
.alert-link { color: var(--accent); text-decoration: underline; }
/* время в углу пузыря, как в мессенджере: последняя строка обтекает его */
.alert-time { float: right; margin: 3px 0 0 10px; font-size: 11px; color: var(--dim); }
.alert-items { display: flex; flex-direction: column; margin-top: 5px; }
.alert-item {
  display: flex; align-items: center; gap: 6px; padding: 6px 0 6px 2px;
  background: none; border: none; border-top: 1px solid var(--border);
  color: var(--text); font: inherit; font-size: 14.5px; line-height: 1.3; text-align: left;
}
.alert-item::after { content: '\203A'; margin-left: auto; padding-left: 8px; color: var(--dim); font-size: 18px; line-height: 1; }
.alert-item:active { color: var(--accent); }
.alerts-empty { padding: 64px 24px; text-align: center; color: var(--muted); font-size: 15px; line-height: 1.45; }
.alerts-empty b { display: block; margin-bottom: 6px; font-size: 17px; font-weight: 600; color: var(--text); }
.alerts-empty button {
  margin-top: 18px; padding: 10px 22px;
  border: none; border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 15px; font-weight: 600;
}

/* Оглавление заметки */
.note-outline {
  position: absolute;
  top: calc(var(--safe-top) + 52px);
  right: 10px;
  min-width: 190px;
  max-width: 76vw;
  max-height: 60vh;
  overflow-y: auto;
  padding: 6px;
  border-radius: 14px;
  background: var(--elevated);
  box-shadow: 0 12px 30px var(--shadow);
  z-index: 41;
}

.note-outline button {
  display: block;
  width: 100%;
  padding: 10px 12px;
  border: none;
  border-radius: 9px;
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  text-align: left;
}

.note-outline button:active { background: var(--hover); }
.note-outline .empty { padding: 10px 12px; font-size: 13px; color: var(--dim); }


/* задачи из чужих трекеров и комментарии */
.task-source {
  display: inline-flex;
  align-items: center;
  height: 17px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--elevated);
  color: var(--muted);
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}

.task-comments { display: inline-flex; align-items: center; gap: 4px; }
.task-comments [data-icon] { font-size: 12px; }

.f-external {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--dim);
}

.f-external a { color: var(--accent); text-decoration: none; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
.f-external a [data-icon] { font-size: 12px; }

.sheet.external .sheet-body input:disabled, .sheet.external .sheet-body select:disabled, .sheet.external .sheet-body textarea:disabled {
  opacity: 1;
  color: var(--text);
  -webkit-text-fill-color: var(--text);
}

.sheet.external #f-check-add, .sheet.external .quick-dates, .sheet.external .f-check-list button { display: none; }

.f-comments { display: flex; flex-direction: column; }
.comment-list { list-style: none; display: flex; flex-direction: column; }
.comment-list .comment { padding: 10px 14px; border-top: 1px solid var(--border); }
.comment-form { padding: 10px 14px 12px; border-top: 1px solid var(--border); }
.comment-head { display: flex; align-items: baseline; gap: 8px; font-size: 12px; color: var(--dim); }
.comment-author { font-weight: 600; color: var(--muted); }
.comment.is-mine .comment-author { color: var(--accent); }
.comment-pending { font-style: italic; }
.comment-text { margin-top: 3px; font-size: 14px; line-height: 1.45; color: var(--text); white-space: pre-wrap; word-break: break-word; }
.comment-form { display: flex; gap: 8px; align-items: flex-end; }
.comment-form textarea { background: var(--elevated); border-radius: 10px; }
.comment-form textarea { flex: 1; min-height: 40px; }
.comment-send {
  flex-shrink: 0;
  height: 40px;
  padding: 0 14px;
  border: none;
  border-radius: 10px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 500;
}

.comment-author.is-claude { display: inline-flex; align-items: center; gap: 5px; }
.comment-author.is-claude svg { width: 11px; height: 11px; color: var(--accent); }

/* счётчик задач — в правом верхнем углу иконки вкладки, а не после подписи */
.tab { position: relative; }
.tab-badge { top: 4px; right: auto; left: calc(50% + 7px); }

/* иконки проектов вместо буквы, когда они найдены */
.avatar-img { background: var(--elevated); overflow: hidden; }
.avatar-img img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* стадии задач */
.task-stage-pill { display: inline-flex; align-items: center; height: 17px; padding: 0 7px; border-radius: 999px; background: var(--elevated); color: var(--muted); font-size: 11px; font-weight: 500; white-space: nowrap; }
.task-stage-pill.is-progress { background: var(--accent-soft); color: var(--accent); }
.task-stage-pill.is-review { background: rgba(224, 163, 62, 0.16); color: #d9a13c; }
.task-stage-pill.is-backlog { color: var(--dim); }
.sheet.external #f-stage:not(:disabled) { opacity: 1; }


/* Экран входа: фон и мордочка BMO, как на экране загрузки десктопа */
.login { background: #63bda4; color: #082729; }
.login-box { gap: 14px; }

.login-face {
  width: min(70vw, 250px);
  height: auto;
  display: block;
  margin: 0 auto 4px;
  filter: drop-shadow(0 12px 28px rgba(8, 39, 41, 0.16));
}

.bmo-eye { transform-box: fill-box; transform-origin: center; animation: bmoBlink 4.2s ease-in-out infinite; }
.bmo-mouth { transform-box: fill-box; transform-origin: center top; transition: transform 0.25s ease; }
.login.is-typing .bmo-mouth { transform: scaleY(0.55); }
.login.is-happy .bmo-mouth { transform: scaleY(1.35); }
.login.is-sad .bmo-mouth { transform: scaleY(0.2); }
.login.is-sad .bmo-eye { animation: none; transform: scaleY(0.35); }
.login.is-sad .login-face { animation: bmoShake 0.45s ease; }
@keyframes bmoBlink { 0%, 91%, 100% { transform: scaleY(1); } 94% { transform: scaleY(0.08); } }
@keyframes bmoShake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-10px); } 40% { transform: translateX(9px); } 60% { transform: translateX(-6px); } 80% { transform: translateX(4px); } }

.login-box h1 { color: #082729; letter-spacing: 4px; margin-left: 4px; }
.login .login-hint { color: rgba(8, 39, 41, 0.72); }
.login #login-code { background: #d6ffdd; border: 2px solid #082729; border-radius: 14px; color: #082729; }
.login #login-code::placeholder { color: rgba(8, 39, 41, 0.35); }
.login #login-code:focus { border-color: #082729; box-shadow: 0 0 0 4px rgba(8, 39, 41, 0.12); }
.login .primary { background: #082729; color: #d6ffdd; }
.login .primary:active { background: #0f3a3c; }
.login .login-scan { border-color: rgba(8, 39, 41, 0.35); color: #082729; }
.login .login-scan:active { background: rgba(8, 39, 41, 0.08); }
.login .login-note { color: rgba(8, 39, 41, 0.7); }
.login .login-note.error { color: #8c0e35; font-weight: 500; }

/* На iOS фиксированные слои (шторка и затемнитель) не достают до физического низа
   экрана — в зоне «домашней полосы» проглядывает фон страницы. Пока шторка открыта,
   красим его в её цвет, иначе снизу видна серая полоса. */
body.sheet-open { background: var(--surface); }

/* Корзина заметок */
/* Список и стартовый экран поиска лежат друг на друге и меняются плавным
   проявлением: пока список не виден, скачок вьюпорта под клавиатуру глазу не заметен. */
/* Заголовок экрана уходит вверх и гаснет вместе со списком: во время поиска
   единственный заголовок — «Разделы», иначе кажется, что экран дёргается. */
.screen[data-screen="notes"] .screen-title,
.screen[data-screen="notes"] .screen-sub {
  overflow: hidden;
  transition: opacity 620ms ease-out, transform 620ms ease-out;
}

/* Место под заголовком схлопываем, иначе результаты поиска начинались бы низко.
   Высоту убираем с задержкой в 620 мс — ровно когда заголовок уже погас, чтобы
   схлопывание не было видно. */
body.searching .screen[data-screen="notes"] .screen-title,
body.searching .screen[data-screen="notes"] .screen-sub {
  opacity: 0;
  transform: translateY(-14px);
  pointer-events: none;
  height: 0;
  margin: 0;
  transition: opacity 620ms ease-out, transform 620ms ease-out,
              height 0ms linear 620ms, margin 0ms linear 620ms;
}

/* список гаснет раньше, чем клавиатура успеет сжать вьюпорт */
#notes-list { transition: opacity 620ms ease-out; }
#notes-list.faded { opacity: 0; pointer-events: none; }

/* разделы проявляются уже после скачка, поэтому его не видно */
.screen[data-screen="notes"] { position: relative; }

/* начинается там же, где заголовок экрана: он к этому моменту уже погас */
#search-start {
  position: absolute;
  top: 2px; left: 14px; right: 14px;   /* абсолютный отсчёт идёт от края экрана, боковые отступы задаём сами */
  opacity: 0;
  pointer-events: none;
  transition: opacity 620ms ease-out;
}

#search-start.on { opacity: 1; pointer-events: auto; }

.notes-trash-toggle {
  width: 100%;
  margin-top: 6px;
  padding: 11px;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--dim);
  font-family: inherit;
  font-size: 13px;
}
/* Удалённая заметка отличается приглушённым заголовком, а не прозрачностью:
   строка едет поверх кнопок свайпа и должна быть плотной. */
.note-card.trashed .note-card-title { font-weight: 500; color: var(--muted); }

/* Поиск и создание заметки — плавающей полосой над таббаром */
.notes-bar {
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(74px + var(--safe-bottom));
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 14;
}

.notes-search {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 14px;
  border-radius: 22px;
  color: var(--dim);
}

/* поле, «плюс» и крестик — один материал: панель плавает над списком, стекло, а не плашка */
.notes-search, .notes-compose, .notes-cancel {
  background: var(--glass);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  box-shadow: inset 0 0 0 0.5px var(--glass-edge), 0 2px 8px rgba(0, 0, 0, 0.08);
}

.notes-search [data-icon] { font-size: 17px; }

.notes-search input {
  flex: 1;
  height: 100%;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  font-size: 15px;
}

.notes-compose {
  flex-shrink: 0;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  border: none;
  border-radius: 50%;
  color: var(--accent);
}

.notes-compose [data-icon] { font-size: 20px; }
.notes-compose:active { background: var(--hover); }

.notes-cancel {
  display: none;
  flex-shrink: 0;
  width: 44px; height: 44px;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;

  color: var(--muted);
}

.notes-cancel [data-icon] { font-size: 20px; }
.notes-cancel:active { background: var(--hover); }

body.searching .notes-compose { display: none; }
body.searching .notes-cancel { display: flex; }
body.searching .tabbar { opacity: 0; pointer-events: none; }

/* пока набирают в поиске, страница не прокручивается: иначе Safari уводит её к полю */
/* body тянется на 100vh, а 100vh — это всегда полный экран, даже когда клавиатура
   ужала видимую область. Отсюда берётся запас прокрутки, который Safari выбирает,
   чтобы показать поле. На время набора убираем эту растяжку. */
body.typing { min-height: 0; }

body.searching .notes-bar { bottom: calc(8px + var(--safe-bottom)); }

/* пока открыта заметка, панель уезжает вместе с экраном */
.app-root.pushed ~ .notes-bar { opacity: 0; }

/* top меняется один раз — когда выехала клавиатура; пусть полоса поднимется плавно */
.notes-bar { transition: opacity 180ms ease-out, top 220ms ease-out; }

/* Вложения задачи: ряд квадратиков — на телефоне так их видно все сразу */
.f-files { margin-top: 18px; }

.file-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.file-tile {
  position: relative;
  width: 68px; height: 68px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--elevated);
  overflow: hidden;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}

.file-tile img { width: 100%; height: 100%; object-fit: cover; }

.file-ext {
  font-size: 11px;
  font-weight: 600;
  color: var(--dim);
}

.file-drop {
  position: absolute;
  top: 3px; right: 3px;
  width: 20px; height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 14px;
  line-height: 1;
}

.file-add {
  font-size: 24px;
  font-weight: 300;
  color: var(--dim);
  border-style: dashed;
  background: transparent;
}

/* Открытые сейчас сессии */
#live-list .live-cap:first-child { margin-top: 2px; }
.live-cap { margin: 16px 4px 8px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .5px; color: var(--dim); }
.live-card .card-head { align-items: center; }
.live-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--dim); }
/* работающую сессию видно сразу — она единственная мигает */
.live-dot.is-busy { background: var(--accent); animation: live-pulse 1.6s ease-in-out infinite; }
@keyframes live-pulse { 50% { opacity: .35; } }

/* Недавняя сессия — строка целиком: нажатие продолжает её, значок справа подсказывает,
   что откроется терминал. Кнопка во всю ширину под каждой карточкой была тяжеловесной. */
.session-card { padding: 11px 14px; }
.session-card:active { background: var(--hover); }
.session-go {
  flex: 0 0 30px; width: 30px; height: 30px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--elevated); color: var(--muted);
}
.session-go [data-icon] { font-size: 15px; }
.session-card:active .session-go { color: var(--accent); }

/* Действия прямо в уведомлении: закрыть или отложить задачу, не уходя в списки */
.alert-task { border-top: 1px solid var(--border); }
.alert-task:first-child { border-top: none; }
.alert-task .alert-item { border-top: none; padding-bottom: 2px; }
.alert-acts { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 0 8px; }
.alert-act {
  padding: 5px 11px; border: none; border-radius: 999px;
  background: var(--elevated); color: var(--text);
  font: inherit; font-size: 13px;
}
.alert-act:active { background: var(--accent-soft); color: var(--accent); }
.alert-act:disabled { opacity: .5; }
.alert-act-done { padding: 4px 0; font-size: 13px; color: var(--green); }
.alert-task.is-done .alert-item { color: var(--dim); text-decoration: line-through; }

/* Корзина: те же свайп-действия, что у живых заметок, только их два */
.trash-swipe .swipe-actions { width: 116px; }

/* Выбор иконки: плитки стоят прямо поверх фокуса, без подложки — с ней выбор
   читался как ещё одно окно поверх размытия */
.peek-icons {
  position: absolute;
  left: 12px; right: 12px;
  overflow-y: auto;
  transform: scale(0.92);
  opacity: 0;
  transform-origin: top center;
  transition: transform 180ms ease-out, opacity 180ms ease-out;
}

.peek.open .peek-icons { transform: scale(1); opacity: 1; }

.peek-icons-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 12px;
  padding: 2px;
}

.peek-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  min-width: 0;          /* иначе длинный путь распирает колонку сетки и лезет на соседей */
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-size: 12px;
}

.peek-icon.is-current { color: var(--text); }
.peek-icon.is-current .peek-icon-art { box-shadow: 0 0 0 2px var(--accent); }
.peek-icon:active .peek-icon-art { transform: scale(0.94); }

/* ровная подложка: у иконок часто прозрачные поля, и клетка вокруг знака читалась рамкой */
.peek-icon-art {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 58px; height: 58px;
  border-radius: 15px;
  background: var(--elevated);
  box-shadow: 0 8px 20px var(--shadow);
  transition: transform 120ms ease-out;
}

.peek-icon-art img { max-width: 44px; max-height: 44px; }

/* разрешение — прямо на превью: отдельной строкой оно раздувало плитку */
.peek-icon-px {
  position: absolute;
  right: -7px;
  bottom: -6px;
  padding: 1px 5px;
  border-radius: 8px;
  background: var(--surface);
  color: var(--muted);
  font-size: 10px;
  font-weight: 600;
  line-height: 15px;
}

.peek-icon.is-current .peek-icon-px { color: var(--accent); }

/* откуда файл: у мобильного приложения и сайта иконки часто разные.
   Цвет как у названия проекта под плиткой — серым по размытию не читается. */
.peek-icon-where {
  max-width: 100%;
  font-size: 11px;
  color: var(--text);
  text-shadow: 0 1px 5px var(--backdrop);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  direction: rtl;
}

.peek-icons-note { padding: 16px 4px; text-align: center; color: var(--muted); font-size: 14px; }

/* Переход на заметку из уведомления: карандаш перед заголовком, действий нет */
.alert-item-note { display: flex; align-items: center; gap: 8px; padding-bottom: 10px; }
/* кнопки ответа под вопросом; после ответа — строка с выбранным */
.alert-ask { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.alert-opt {
  padding: 8px 16px; border: none; border-radius: 18px;
  background: var(--accent); color: var(--on-accent);
  font-family: inherit; font-size: 14px; font-weight: 600;
}
.alert-opt:active { background: var(--accent-active); }
.alert-asked { margin-top: 6px; font-size: 13px; color: var(--accent); font-weight: 600; }
.alert-item-note svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--muted); }

/* Экран компьютера: картинка во всю ширину, ниже переключатель мониторов */
.screen-peek {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; margin-top: 12px; padding: 13px;
  border: none; border-radius: 14px;
  background: var(--surface); color: var(--text);
  font-family: inherit; font-size: 15px;
}
.screen-peek [data-icon] { font-size: 17px; color: var(--muted); }
.screen-peek:active { background: var(--hover); }

/* Экран звонка: всегда тёмный, как экран разговора; панели лежат поверх кадра и прячутся
   по тапу, чтобы в альбомной ориентации монитор занимал весь телефон */
.call {
  position: fixed; inset: 0; z-index: 90;
  background: #000; color: #fff;
  --edge-l: env(safe-area-inset-left, 0px);
  --edge-r: env(safe-area-inset-right, 0px);
  transition: opacity 380ms ease, transform 380ms ease;
}
.call[hidden] { display: none; }
/* появление и уход экрана — плавно, как у звонка, а не щелчком */
.call.is-gone { opacity: 0; transform: scale(0.96); }
/* трубка положена: картинка гаснет, панели уходят, в шапке остаётся «Звонок завершён» */
.call.is-ending .call-img { filter: brightness(0.3); transition: filter 500ms ease; }
.call.is-ending .call-foot, .call.is-ending .call-face { opacity: 0; transition: opacity 400ms ease; pointer-events: none; }
.call.is-ending .call-stage { pointer-events: none; }
body.calling { overflow: hidden; }
.call-stage { position: absolute; inset: 0; overflow: hidden; touch-action: none; }
.call-img {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  object-fit: contain; opacity: 0; transition: opacity 200ms;
}
.call-img.is-live { opacity: 1; }
.call-note {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255, 255, 255, 0.5); font-size: 14px; pointer-events: none;
}
.call-head, .call-foot {
  position: absolute; left: 0; right: 0;
  transition: opacity 220ms ease-out, transform 220ms ease-out;
}
.call-head {
  top: 0;
  display: flex; align-items: center; gap: 12px;
  padding: calc(var(--safe-top) + 10px) calc(var(--edge-r) + 16px) 32px calc(var(--edge-l) + 16px);
  background: linear-gradient(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
}
.call-foot {
  bottom: 0;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  padding: 36px calc(var(--edge-r) + 16px) calc(var(--safe-bottom) + 14px) calc(var(--edge-l) + 16px);
  background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));
}
/* тап по кадру прячет шапку, чипы и кнопки; лицо и субтитры остаются — это и есть звонок */
.call.is-bare .call-head { opacity: 0; transform: translateY(-12px); pointer-events: none; }
.call.is-bare .call-displays, .call.is-bare .call-actions { display: none; }
.call.is-bare .call-foot { padding-top: 24px; }
.call-avatar {
  flex: none; width: 44px; height: 44px; border-radius: 12px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; font-size: 18px; font-weight: 700;
}
.call-avatar img { width: 100%; height: 100%; object-fit: cover; }
.call-who { min-width: 0; }
.call-name { font-size: 17px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.call-sub { font-size: 13px; color: rgba(255, 255, 255, 0.6); font-variant-numeric: tabular-nums; }
.call-msg { margin-top: 3px; font-size: 13px; color: rgba(255, 255, 255, 0.8); line-height: 1.3; }
.call-displays { display: flex; gap: 8px; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.call-displays::-webkit-scrollbar { display: none; }
.call-chip {
  flex: none; min-width: 42px; height: 34px; padding: 0 13px;
  border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 17px;
  background: rgba(255, 255, 255, 0.1); color: rgba(255, 255, 255, 0.75);
  font-family: inherit; font-size: 13px; backdrop-filter: blur(10px);
}
.call-chip.is-on { background: #fff; color: #000; border-color: #fff; }
.call-actions { display: flex; align-items: center; gap: 18px; }
.call-btn {
  width: 58px; height: 58px; border: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.16); color: #fff; font-size: 23px;
  backdrop-filter: blur(10px);
}
.call-btn [data-icon] { display: flex; }
.call-btn svg { width: 1em; height: 1em; }
.call-btn.is-on { background: #fff; color: #000; }
.call-btn:active { filter: brightness(0.8); }
.call-end { background: var(--red); }

/* субтитры над кнопками: реплика сессии — дослушанное ярче, недослушанное гаснет;
   ответ пользователя — акцентом */
.call-subs {
  width: 100%; max-width: 560px; margin-bottom: 4px;
  display: flex; flex-direction: column; gap: 6px; text-align: center;
}
/* две строки на двоих: один говорит — его текст занимает обе строки, говорят оба — по строке.
   Никаких троеточий: слова переносятся, а сколько текста показать, считает JS по ширине */
.call-subs { max-height: 50px; overflow: hidden; }
.call-sub-line { font-size: 16px; line-height: 1.35; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8); overflow-wrap: anywhere; }
.call-sub-line.session { color: #fff; }
.call-sub-line.session .unheard { color: rgba(255, 255, 255, 0.4); }
.call-sub-line.me { color: var(--accent); font-size: 15px; }
.call-sub-line.me::before { content: '— '; }

/* журнал звонков */
.peek-row { display: flex; gap: 10px; }
.peek-row .screen-peek { flex: 1; }
.calls-body { flex: 1; overflow: auto; -webkit-overflow-scrolling: touch; padding: 4px 14px calc(20px + var(--safe-bottom)); }
.note-nav-title { font-size: 17px; font-weight: 600; }
.call-row {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 11px 2px;
  background: none; border: none; border-top: 1px solid var(--border);
  color: var(--text); font: inherit; text-align: left;
}
.call-row:first-child { border-top: none; }
.call-row .avatar { flex: none; }
.call-row-main { flex: 1; min-width: 0; }
.call-row-title { font-size: 15.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.call-row-sub { font-size: 13px; color: var(--muted); margin-top: 1px; }
.call-row-sub.missed { color: var(--red); }
.call-row-when { flex: none; font-size: 13px; color: var(--dim); font-variant-numeric: tabular-nums; }
.call-row::after { content: '\203A'; padding-left: 4px; color: var(--dim); font-size: 18px; line-height: 1; }
.calls-empty { padding: 64px 24px; text-align: center; color: var(--muted); font-size: 15px; line-height: 1.45; }
.transcript-head { padding: 6px 2px 14px; border-bottom: 1px solid var(--border); margin-bottom: 8px; }
.transcript-head .call-row-sub { margin-top: 3px; }
.transcript-msg { font-size: 14px; color: var(--muted); margin-top: 8px; line-height: 1.4; }
.transcript-line { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; }
.transcript-line .who { font-size: 12px; color: var(--dim); }
.transcript-line .text { font-size: 15px; line-height: 1.4; }
.transcript-line.me .text { color: var(--accent); }
.transcript-line .unheard { color: var(--dim); text-decoration: line-through; }
.transcript-line .unheard::before { content: ' '; }

/* «видеоокно» BMO в углу над панелью: моргает всегда, рот ходит, пока сессия говорит */
/* книжный формат 3:4, как окошко собеседника в FaceTime; положение задаёт JS: тянется куда
   угодно, отпущенное прилипает к ближайшему углу, вытолкнутое за край прячется до язычка */
.call-face {
  position: absolute; left: 0; top: 0; z-index: 2;
  width: 82px; height: 110px; border-radius: 16px;
  display: flex; align-items: center; justify-content: center;
  background: #63bda4; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.18);
  touch-action: none; will-change: transform;
}
.call-face svg { display: block; width: 66px; height: auto; pointer-events: none; }
.call-face-tab {
  position: absolute; right: 0; z-index: 2; width: 28px; height: 46px; padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.18); border-right: none; border-radius: 12px 0 0 12px;
  background: #63bda4; color: #082729; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}
.call-face-tab.left { right: auto; left: 0; border-right: 1px solid rgba(255, 255, 255, 0.18); border-left: none; border-radius: 0 12px 12px 0; }
.call-face-tab [data-icon] { display: flex; font-size: 18px; }
.call-face-tab svg { width: 1em; height: 1em; }
.call-face .bmo-eye { transform-box: fill-box; transform-origin: center; animation: bmo-blink 4.6s infinite; }
/* глаза и рот двигаются вместе — так BMO «поворачивает голову»: куда смотрит, туда и лицо */
.call-face .face-features { transition: transform 420ms cubic-bezier(0.2, 0.7, 0.2, 1); }
/* покадровый рот: кадры лежат все сразу, виден один — какой, решает JS */
.call-face .mouths .m { display: none; }
.call-face .mouths[data-m="0"] .m0, .call-face .mouths[data-m="1"] .m1, .call-face .mouths[data-m="2"] .m2,
.call-face .mouths[data-m="3"] .m3, .call-face .mouths[data-m="4"] .m4, .call-face .mouths[data-m="5"] .m5 { display: block; }
.call-face[data-mood="thinking"] .bmo-eye { animation-duration: 3.1s; }
.call-face[data-mood="listening"] .bmo-eye { r: 7; }
@keyframes bmo-blink { 0%, 92%, 100% { transform: scaleY(1); } 95% { transform: scaleY(0.1); } }

/* подсветка места на экране: рамка акцентом с подписью, пульсирует, живёт секунд десять */
.call-view { position: absolute; inset: 0; transform-origin: 0 0; will-change: transform; }
.call-hl {
  position: absolute; border: 3px solid var(--accent); border-radius: 8px; pointer-events: none;
  box-shadow: 0 0 0 4px rgba(99, 189, 164, 0.35), 0 0 26px rgba(99, 189, 164, 0.7);
  animation: hl-pulse 1.3s ease-in-out infinite;
}
.call-hl-label {
  position: absolute; left: -3px; bottom: 100%; margin-bottom: 7px; padding: 3px 9px;
  border-radius: 7px; background: var(--accent); color: #082729;
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
@keyframes hl-pulse { 0%, 100% { box-shadow: 0 0 0 4px rgba(99, 189, 164, 0.35), 0 0 26px rgba(99, 189, 164, 0.7); }
  50% { box-shadow: 0 0 0 8px rgba(99, 189, 164, 0.18), 0 0 34px rgba(99, 189, 164, 0.9); } }
/* альбомная, как у FaceTime: мониторы столбиком у левого края, кнопки столбиком у правого,
   субтитры внизу по центру; лицо — в правом верхнем углу под шапкой */
@media (orientation: landscape) {
  .call-foot { top: 0; bottom: 0; padding: 0; display: block; background: none; pointer-events: none; }
  .call-foot > * { pointer-events: auto; }
  .call-subs {
    position: absolute; left: 50%; bottom: calc(var(--safe-bottom) + 12px); transform: translateX(-50%);
    width: 62%; max-width: none; margin: 0; padding: 7px 12px; border-radius: 12px;
    box-sizing: border-box; max-height: 64px;   /* две строки плюс поля, иначе низ обрезается */
    background: rgba(0, 0, 0, 0.45); backdrop-filter: blur(8px);
  }
  .call-displays {
    position: absolute; left: calc(var(--edge-l) + 12px); top: 50%; transform: translateY(-50%);
    flex-direction: column; overflow: visible;
  }
  .call-actions {
    position: absolute; right: calc(var(--edge-r) + 12px); top: 50%; transform: translateY(-50%);
    flex-direction: column; gap: 14px;
  }
  .call-btn { width: 50px; height: 50px; font-size: 20px; }
  .call.is-bare .call-foot { padding: 0; }
  .call-face { width: 62px; height: 84px; }
  .call-face svg { width: 50px; }
}

/* «Не дома» в шапке: включён — таблетка с подписью акцентом */
.away-btn { width: auto; gap: 6px; padding: 0 10px; border-radius: 18px; }
.away-btn .away-label { display: none; font-size: 13px; font-weight: 600; }
.away-btn.is-on { background: var(--accent-soft); color: var(--accent); }
.away-btn.is-on .away-label { display: inline; }

/* фото из разговора в транскрипте звонка и кнопка отправки, пока фото уходит */
.transcript-photo { display: block; max-width: 100%; max-height: 320px; border-radius: 10px; margin-top: 6px; }
.call-btn.is-busy { opacity: 0.5; pointer-events: none; }

/* Свёрнутый звонок: свайп вниз по кадру превращает экран в плитку с лицом и таймером над
   нижней панелью — приложение остаётся рабочим, разговор продолжается; тап раскрывает обратно */
.call.is-mini {
  inset: auto; left: 12px; bottom: calc(var(--safe-bottom) + 76px);
  width: 92px; height: 132px; border-radius: 18px; overflow: hidden;
  background: #63bda4; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
}
.call.is-mini .call-stage, .call.is-mini .call-head, .call.is-mini .call-foot, .call.is-mini .call-face-tab { display: none; }
.call.is-mini .call-face {
  position: static; transform: none !important; width: auto; height: auto;
  box-shadow: none; border: none; background: none; pointer-events: none;
}
.call-mini-time { display: none; color: #082729; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.call.is-mini .call-mini-time { display: block; }
