/* Лавандовый стиль: фиолетовая шапка со скруглённым низом, дела — мягкие цветные плашки.
   Цвета плашек несут смысл: лавандовая — можно сделать, зелёная — сделано, жёлтая — цель. */
:root {
  --bg: #ffffff;
  --ink: #1d1b3a;
  --dim: #8a88a6;
  --line: #ebe8f7;
  --accent: #6d4af5;
  --accent-ink: #ffffff;
  --hero-sub: #d9d0ff;
  --plate: #f3f0ff;
  --plate-done: #eaf8f0;
  --good: #2aa76a;
  --goal: #fff6cf;
  --goal-track: #f1e3a0;
  --goal-fill: #f2b705;
  --goal-ink: #6b5a12;
  --bad: #d64545;
  --star: #f2b705;
  --radius: 16px;
  /* Вырез под камеру и полоса «домой». На айфонах с чёлкой/островом страница идёт во весь экран
     (viewport-fit=cover + apple-mobile-web-app-status-bar-style=black-translucent),
     поэтому заливка доходит до верха, а содержимое отодвигают вниз эти отступы.
     На айфонах без выреза и в обычном браузере значения нулевые — разметка та же. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14122b; --ink: #efedff; --dim: #9d9ac0; --line: #2c2856; --accent: #7c5cff; --hero-sub: #cfc5ff;
    --plate: #211e46; --plate-done: #173a2c; --good: #4cc38a;
    --goal: #3a3314; --goal-track: #5a4f1e; --goal-fill: #f2b705; --goal-ink: #f4e6a6; --bad: #ff7b72;
  }
}

/* touch-action: manipulation — браузер не ждёт второго тапа, чтобы решить, не зум ли это.
   Без этого быстрый набор PIN на телефоне превращался в масштабирование страницы. */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font: 16px/1.35 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased;
}
button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; padding: 0; text-align: inherit; }
h1, h2, h3 { margin: 0; line-height: 1.2; }
h2 { font-size: 1rem; font-weight: 700; }
h3 { font-size: 1.2rem; font-weight: 700; margin-bottom: 10px; }
dialog h2 { margin: 18px 0 6px; }
.dim, .sub { color: var(--dim); }
.sub { font-size: .82rem; }
.grow { flex: 1 1 0; min-width: 0; }

#app { max-width: 560px; margin: 0 auto; padding-bottom: calc(84px + var(--safe-bottom)); }

/* Подложка статус-бара. Под шапкой её не видно — цвет тот же, — но она держит
   надписи iOS (часы, батарея) читаемыми на экране входа и когда шапка уехала при прокрутке.
   Диалог лежит в верхнем слое и перекрывает её вместе со всей страницей. */
body::before {
  content: ''; position: fixed; top: 0; left: 0; right: 0; height: var(--safe-top);
  background: var(--accent); z-index: 10;
}
.wrap { padding: 18px 16px 0; }
.wrap.lifted { position: relative; z-index: 1; margin-top: -42px; padding-top: 0; }

/* ---------- шапка ---------- */
.hero { position: relative; background: var(--accent); color: #fff; padding: calc(34px + var(--safe-top)) 20px 62px; border-radius: 0 0 32px 32px; }
/* у ребёнка без цели на шапку ничего не наезжает — нижний запас под карточку не нужен */
.hero.flat { padding-bottom: 30px; }
.hero.slim { padding-top: calc(20px + var(--safe-top)); padding-bottom: 22px; border-radius: 0 0 24px 24px; }
.hero-row { display: flex; align-items: center; gap: 12px; }
.hero .name { font-size: 1.2rem; font-weight: 700; }
.hero-sub { font-size: .82rem; color: var(--hero-sub); }
.hero .bar { background: rgba(255, 255, 255, .25); max-width: 170px; margin-top: 6px; height: 5px; }
.hero .bar > i { background: #fff; }
.hero .balance { text-align: right; }
.hero .balance b { display: block; font-size: 1.7rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.hero .balance .hero-sub { text-decoration: underline; text-underline-offset: 3px; }
.hero-link { color: var(--hero-sub); font-size: .85rem; font-weight: 600; padding: 6px 0 6px 12px; }
.hero .avatar { background: #fff; }
.avatar {
  --c: var(--accent);
  flex: none; display: inline-grid; place-items: center; width: 50px; height: 50px; border-radius: 50%;
  font-size: 27px; background: color-mix(in srgb, var(--c) 18%, var(--bg));
}
.avatar.sm { width: 40px; height: 40px; font-size: 22px; }
.avatar.xs { width: 22px; height: 22px; font-size: 13px; margin-right: 4px; vertical-align: -6px; }
.avatar-btn { flex: none; border-radius: 50%; transition: transform .08s; }
.avatar-btn:active { transform: scale(.94); }

/* цель-копилка */
.goal { display: block; width: 100%; background: var(--goal); color: var(--ink); border-radius: 20px; padding: 16px; margin-bottom: 18px; }
.goal .goal-sub { font-size: .82rem; color: var(--goal-ink); }
.goal .bar { background: var(--goal-track); height: 7px; margin-top: 10px; }
.goal .bar > i { background: var(--goal-fill); }
.goal.reached { background: var(--plate-done); }
.goal.reached .goal-sub { color: var(--good); text-decoration: underline; text-underline-offset: 3px; }
.bar { height: 6px; border-radius: 99px; background: var(--line); overflow: hidden; }
.bar > i { display: block; height: 100%; border-radius: 99px; background: var(--accent); transition: width .5s; }

/* ---------- плашки ---------- */
.head { margin: 4px 4px 10px; min-height: 28px; }
.head + .plate, .head + .list, .head + .card { margin-top: 0; }
.plate + .head, .list + .head { margin-top: 22px; }
.plate { display: flex; align-items: center; gap: 10px; background: var(--plate); border-radius: var(--radius); padding: 12px 14px; margin-bottom: 8px; }
.plate .emoji { font-size: 1.5rem; width: 28px; text-align: center; flex: none; }
.plate .title { font-weight: 600; }
.plate.done { background: var(--plate-done); }
.plate.done .pts { color: var(--good); }
.plate.taken { opacity: .55; }
.plate.taken .pts { color: var(--dim); }

/* Вторая строка плашки. Награда (.pts) — самое заметное, остальное приглушено,
   иначе «+30 баллов · кто первый · 0 из 2» читается как сплошная каша. */
.meta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin-top: 3px; line-height: 1.25; min-width: 0; }
.meta:empty { display: none; }
/* nowrap, но с многоточием: в узкой плашке длинная подпись иначе вылезает поверх соседей */
.pts { font-size: .82rem; font-weight: 700; color: var(--accent); white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.tag { font-size: .78rem; color: var(--dim); }
.who { font-size: .78rem; color: var(--dim); display: inline-flex; align-items: center; }
.pips { display: inline-flex; gap: 4px; }
.pips i { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--accent); opacity: .5; }
.pips i.on { background: var(--accent); opacity: 1; }
/* чужая отметка общего дела — значок профиля того, кто сделал, на месте точки */
.pips { align-items: center; }
.pip-who { font-size: .85rem; line-height: 1; }
.plate.done .pips i { border-color: var(--good); }
.plate.done .pips i.on { background: var(--good); }

/* Кнопка «Сделано» и галочка занимают один и тот же слот: отметка не меняет размер карточки */
.act { flex: none; width: 88px; display: flex; justify-content: flex-end; align-items: center; }
.act .btn { width: 100%; padding-left: 8px; padding-right: 8px; }
.tick { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%; background: var(--good); color: #fff; font-weight: 700; font-size: 1.05rem; }
/* анимация — только у дела, которое отметили прямо сейчас: иначе при каждой перерисовке дёргаются все галочки */
.tick.pop { animation: pop .3s; }
.tick:active { transform: scale(.92); }
.rank { width: 14px; text-align: center; color: var(--dim); font-weight: 700; flex: none; }
/* Звезда после числа: размер и посадка от окружающего текста, цвет — один на весь портал */
.star { width: .95em; height: .95em; margin-left: .14em; vertical-align: -.1em; fill: var(--star); stroke: var(--star); stroke-width: 2; stroke-linejoin: round; }
.hero .balance .star { width: .7em; height: .7em; vertical-align: .02em; margin-left: .18em; }
.money { font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.money.neg { color: var(--bad); }
.money.dim { font-weight: 500; }
.money.big { font-size: 1.1rem; }
.empty { text-align: center; padding: 28px 12px; color: var(--dim); }

/* длинные списки (лента, оценки, профили) — лёгкие строки с разделителями */
.card, .list { border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 12px; }
.card { padding: 14px; }
.list { overflow: hidden; }
/* padding-right — чтобы полоса прокрутки не наезжала на суммы справа */
.list.plain { border: 0; margin: 0; max-height: 46vh; overflow-y: auto; padding-right: 6px; }
.list.plain .item { padding-left: 0; padding-right: 0; }
.item { display: flex; align-items: center; gap: 12px; padding: 11px 14px; border-bottom: 1px solid var(--line); }
.item:last-child { border-bottom: 0; }
.item .title { font-weight: 600; }
.item.void .what { text-decoration: line-through; color: var(--dim); }
.item.taken { opacity: .5; }

.plate.wait { background: var(--goal); }
.plate.wait .pts { color: var(--goal-ink); }
.foot-links { display: flex; justify-content: center; gap: 18px; flex-wrap: wrap; margin: 18px 0 6px; }
.foot-links .link { margin: 0; font-size: .85rem; }
.list.plain .plate { margin-bottom: 8px; padding: 12px 10px; }
table.summary { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
table.summary th { font-size: .75rem; font-weight: 600; color: var(--dim); text-align: right; padding: 10px 14px 4px; }
table.summary td { padding: 9px 14px; text-align: right; border-top: 1px solid var(--line); white-space: nowrap; }
table.summary td:first-child { text-align: left; font-weight: 600; }
table.summary tr:nth-child(2) td { border-top: 0; }

/* ---------- кнопки и формы ---------- */
.btn {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  padding: 9px 15px; border-radius: 12px; font-weight: 700; font-size: .9rem; white-space: nowrap;
  background: var(--accent); color: var(--accent-ink); transition: transform .08s;
}
.btn:active { transform: scale(.96); }
/* Долгое нажатие: кнопка за время удержания бледнеет и сжимается — видно, что «что-то зреет».
   Выделение текста и системная лупа на кнопках отключены, иначе iOS перехватывает удержание. */
.btn, .tick { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.btn.holding { transform: scale(.88); opacity: .45; transition: transform .65s linear, opacity .65s linear; }
.hint { text-align: center; margin: 12px 8px 0; }
.btn.ghost { background: var(--plate); color: var(--accent); }
.link { color: var(--dim); text-decoration: underline; text-underline-offset: 2px; font-size: .8rem; padding: 2px 0; margin-right: 8px; }
/* обводку показываем только при ходьбе по Tab: иначе первая строка списка в модалке
   выглядела выделенной просто потому, что диалог отдал ей фокус при открытии */
button:focus { outline: none; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

label { display: block; font-size: .82rem; color: var(--dim); margin: 14px 0 4px; }
input[type=text], input[type=number], input[type=date], input[type=password], select {
  width: 100%; padding: 10px 12px; border-radius: 12px; border: 1.5px solid var(--line);
  background: var(--bg); outline: none; min-height: 44px;
}
input[type=color] { width: 100%; height: 44px; padding: 2px; border: 1.5px solid var(--line); border-radius: 12px; background: var(--bg); }
input:focus, select:focus { border-color: var(--accent); }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.row.between { justify-content: space-between; }
.row.end { justify-content: flex-end; }
.row > .grow { flex-basis: 130px; }
.row.quad { flex-wrap: nowrap; align-items: flex-end; }
.row.quad > .grow { flex-basis: 0; }
.row.quad label { margin-top: 0; }
.actions { margin-top: 20px; }
.checks { display: flex; flex-wrap: wrap; gap: 6px; }
.checks label { margin: 0; }
.checks input { position: absolute; opacity: 0; }
.checks span { display: inline-block; padding: 7px 12px; border-radius: 10px; color: var(--ink); background: var(--plate); cursor: pointer; font-size: .92rem; font-weight: 600; }
.checks input:checked + span { background: var(--accent); color: var(--accent-ink); }
.checks input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
details { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 12px; }
summary { cursor: pointer; color: var(--dim); font-size: .9rem; }
.menu { display: grid; gap: 8px; margin-top: 12px; }
.menu .btn { justify-content: flex-start; padding: 13px 14px; }
.chips { display: flex; gap: 6px; margin-bottom: 14px; overflow-x: auto; }
.chips button { padding: 7px 14px; border-radius: 99px; background: var(--plate); color: var(--accent); font-weight: 600; white-space: nowrap; }
.chips button.on { background: var(--accent); color: var(--accent-ink); }
.chips.multi { flex-wrap: wrap; }

/* Песочница: плашка над нижней навигацией. Плавает поверх, чтобы вёрстка экрана оставалась как в настоящем портале. */
.sandbox-pill {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(70px + var(--safe-bottom)); z-index: 6;
  max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 7px 14px; border-radius: 99px; font-size: .8rem; font-weight: 700;
  background: var(--goal-fill); color: #3a2f00; box-shadow: 0 4px 14px rgba(29, 27, 58, .25);
}
/* запас снизу, чтобы плашка не закрывала последнюю строку списка */
#app:has(.sandbox-pill) { padding-bottom: calc(130px + var(--safe-bottom)); }

/* ---------- нижняя навигация ---------- */
nav.tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 5; display: flex; justify-content: center; gap: 8px;
  padding: 10px 16px calc(10px + var(--safe-bottom));
  background: color-mix(in srgb, var(--bg) 90%, transparent); backdrop-filter: blur(12px); border-top: 1px solid var(--line);
}
nav.tabs button { flex: 1; max-width: 150px; text-align: center; padding: 9px 6px; border-radius: 12px; font-weight: 700; font-size: .9rem; color: var(--dim); }
nav.tabs button.on { color: var(--accent); background: var(--plate); }

/* ---------- выбор дня ---------- */
/* Заголовок дня — кнопка: раскрывает полоску дат. Уголок рисуется рамкой, без значков-картинок. */
.day-switch { display: inline-flex; align-items: center; gap: 8px; padding: 4px 0; }
.day-switch i { width: 7px; height: 7px; margin-top: -3px; border: solid var(--dim); border-width: 0 2px 2px 0; transform: rotate(45deg); transition: transform .15s; }
.day-switch.open i { transform: rotate(-135deg); margin-top: 4px; }
.note { margin: -2px 4px 10px; }
.nav { flex: none; display: grid; place-items: center; width: 28px; height: 36px; border-radius: 10px; font-size: 1.4rem; line-height: 1; color: var(--accent); }
.nav:disabled { opacity: .25; cursor: default; }
.strip { display: flex; align-items: center; gap: 2px; margin: 0 -4px 12px; }
.sheet .strip { margin: 4px -4px 10px; flex: none; }
/* Три состояния не спорят друг с другом: выбранный день — залитый кружок, сегодня — цветная цифра,
   «в этот день что-то сделано» — зелёная точка под числом. */
.day { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 2px 0; font-size: .72rem; font-weight: 600; color: var(--dim); }
.day i { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; font-style: normal; font-weight: 700; font-size: .92rem; color: var(--ink); font-variant-numeric: tabular-nums; }
.day.today i { color: var(--accent); background: var(--plate); }
.day.on i { background: var(--accent); color: var(--accent-ink); }
.day.on span { color: var(--accent); }
.day:disabled { opacity: .35; cursor: default; }
.day u { width: 5px; height: 5px; border-radius: 50%; text-decoration: none; }
.day u.dot { background: var(--good); }

/* ---------- выбор аватарки ---------- */
.emoji-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 6px; margin: 6px 0 4px; max-height: 42vh; overflow-y: auto; }
.emoji-pick { height: 44px; border-radius: 12px; background: var(--plate); font-size: 22px; text-align: center; }
.emoji-pick.on { background: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.emoji-pick:active { transform: scale(.94); }

/* ---------- оценки ---------- */
.mark { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 11px; font-weight: 700; }
.mark.v5 { color: #1a7f4e; background: #e1f3e9; } .mark.v4 { color: #2563a8; background: #e2edf8; }
.mark.v3 { color: #9a6700; background: #f8eed5; } .mark.v2 { color: #c93c37; background: #fbe4e3; }
.marks { display: flex; gap: 8px; }
.marks label { margin: 0; cursor: pointer; }
.marks input { position: absolute; opacity: 0; }
.marks .mark { width: 46px; height: 46px; font-size: 1.2rem; opacity: .45; }
.marks input:checked + .mark { opacity: 1; box-shadow: 0 0 0 2px currentColor; }
.marks input:focus-visible + .mark { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---------- вход ---------- */
.login { min-height: 92vh; display: flex; flex-direction: column; justify-content: center; text-align: center; padding: calc(24px + var(--safe-top)) 20px calc(24px + var(--safe-bottom)); }
.login h1 { font-size: 1.5rem; margin: 8px 0 4px; }
.gate { width: 100%; max-width: 320px; margin: 22px auto 14px; }
.gate input { text-align: center; }
.offline-title { font-size: 1.1rem; font-weight: 700; margin: 28px 0 6px; }
.profiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; margin-top: 24px; }
.profile { background: var(--plate); border-radius: 20px; padding: 18px 8px 14px; font-weight: 700; text-align: center; }
.profile:active { transform: scale(.98); }
.profile .avatar { margin-bottom: 8px; background: var(--bg); }
.pin-dots { display: flex; justify-content: center; gap: 14px; margin: 22px 0; }
.pin-dots i { width: 14px; height: 14px; border-radius: 50%; background: var(--plate); }
.pin-dots i.on { background: var(--accent); }
.pin-dots.shake { animation: shake .35s; }
.pad { display: grid; grid-template-columns: repeat(3, 72px); gap: 12px; justify-content: center; }
.pad button { height: 72px; border-radius: 50%; background: var(--plate); font-size: 1.5rem; font-weight: 600; text-align: center; }
.pad button:active { background: var(--line); }
.pad .blank { visibility: hidden; }
.error { color: var(--bad); min-height: 1.6em; margin-top: 12px; }

/* ---------- модалка и тосты ---------- */
/* Пока окно открыто, страница под ним стоит на месте; прокрутка не «протекает» наружу. */
html:has(dialog[open]) { overflow: hidden; }
dialog { overscroll-behavior: contain; }
/* Окно со списком (.sheet): фиксированная высота, листается только список. Поэтому окно не прыгает,
   когда в списке становится больше или меньше строк, и не ездит целиком под пальцем. */
dialog:has(> .sheet) { overflow: hidden; }
.sheet { display: flex; flex-direction: column; height: min(78dvh, 640px); }
.sheet > * { flex: none; }
.sheet > .list.plain { flex: 1 1 0; min-height: 0; max-height: none; overflow-y: auto; overscroll-behavior: contain; margin-top: 8px; }
.sheet > .actions { margin-top: 14px; }
dialog { border: 0; border-radius: 24px; padding: 20px 16px; width: min(460px, calc(100vw - 24px)); max-height: 90vh; max-height: 90dvh; background: var(--bg); color: var(--ink); box-shadow: 0 20px 60px rgba(29, 27, 58, .3); }
dialog::backdrop { background: rgba(29, 27, 58, .5); }
#toasts { position: fixed; top: calc(14px + var(--safe-top)); left: 0; right: 0; z-index: 99; display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; }
.toast { background: var(--ink); color: var(--bg); padding: 11px 20px; border-radius: 99px; font-weight: 700; animation: toast 2.6s forwards; }
.toast.bad { background: var(--bad); color: #fff; }
dialog > .toast { position: fixed; top: 14px; left: 0; right: 0; margin: 0 auto; width: fit-content; max-width: 90vw; }

.confetti { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 98; }
.confetti i { position: absolute; top: -14px; width: 9px; height: 14px; border-radius: 2px; opacity: .95; animation: fall linear forwards; }
@keyframes fall { to { transform: translate(var(--drift), 105vh) rotate(var(--spin)); opacity: .9; } }
@keyframes pop { 0% { transform: scale(.3); } 70% { transform: scale(1.25); } 100% { transform: scale(1); } }
@keyframes shake { 25% { transform: translateX(-8px); } 50% { transform: translateX(8px); } 75% { transform: translateX(-5px); } }
@keyframes toast { 0% { opacity: 0; transform: translateY(-16px); } 10%, 85% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(-10px); } }
@media (prefers-reduced-motion: reduce) { * { animation-duration: .01s !important; transition: none !important; } }
input:disabled { opacity: .45; }

/* Отладочный портал (./run.sh dev): метка, чтобы не отмечать настоящие дела не там */
html.dev body::after { content: 'Отладка'; position: fixed; left: 10px; bottom: calc(70px + var(--safe-bottom)); z-index: 100; padding: 4px 10px; border-radius: 99px; background: var(--bad); color: #fff; font-size: 12px; font-weight: 700; pointer-events: none; }
